Bring up to date with 3.3d2 from the raspberry pi
This commit is contained in:
+1
-3
@@ -8,7 +8,7 @@ shairport_sync_SOURCES = shairport.c rtsp.c mdns.c mdns_external.c common.c rtp.
|
||||
|
||||
AM_CFLAGS = -Wno-multichar -Wall -Wextra -Wno-clobbered -Wno-psabi -pthread -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
if BUILD_FOR_FREEBSD
|
||||
AM_CXXFLAGS = -I/usr/local/include -Wno-multichar -Wall -Wextra -Wno-clobbered -Wno-psabi -pthread -DSYSCONFDIR=\"$(sysconfdir)\" -O2
|
||||
AM_CXXFLAGS = -I/usr/local/include -Wno-multichar -Wall -Wextra -pthread -DSYSCONFDIR=\"$(sysconfdir)\" -O2
|
||||
else
|
||||
if BUILD_FOR_OPENBSD
|
||||
AM_CXXFLAGS = -I/usr/local/include -Wno-multichar -Wall -Wextra -Wno-clobbered -Wno-psabi -pthread -DSYSCONFDIR=\"$(sysconfdir)\"
|
||||
@@ -144,8 +144,6 @@ endif
|
||||
if INSTALL_SYSTEMV
|
||||
getent group shairport-sync &>/dev/null || groupadd -r shairport-sync >/dev/null
|
||||
getent passwd shairport-sync &> /dev/null || useradd -r -M -g shairport-sync -s /usr/bin/nologin -G audio shairport-sync >/dev/null
|
||||
[ -e /var/run/shairport-sync ] || mkdir -p /var/run/shairport-sync
|
||||
chown shairport-sync:shairport-sync /var/run/shairport-sync
|
||||
[ -e $(DESTDIR)$(sysconfdir)/init.d ] || mkdir -p $(DESTDIR)$(sysconfdir)/init.d
|
||||
[ -f $(DESTDIR)$(sysconfdir)/init.d/shairport-sync ] || cp scripts/shairport-sync $(DESTDIR)$(sysconfdir)/init.d/
|
||||
endif
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
Version 3.3d2
|
||||
====
|
||||
Modify the code that synchronises the Shairport Sync system's clock with the source clock to try to take account of the sources's true rate, which (oddly, e.g. iTunes on a Mac) might not be exactly 44,100 fps. Also try to interpolate for the measured drift between the standard three-second timing snapshots. These changes make a very slight difference from time to time, of the order of microseconds, and it's not clear yet how reliable the drift interpolation is.
|
||||
Modify the code that synchronises the Shairport Sync system's clock with the source clock to try to take account of the sources's nominal rate, which (oddly, e.g. iTunes on a Mac) might not be exactly 44,100 fps. Also try to interpolate for the measured drift between the standard three-second timing snapshots. These changes make a very slight difference from time to time, of the order of microseconds, and it's not clear yet how reliable the drift interpolation is.
|
||||
|
||||
Add some extra fields to the `statistics` output, including nominal source rate, actual input rate, actual output rate, source clock drift, calculated correction needed in ppm. All thesrt numbers agree to a high degree, but the generation of them is fragile and susceptible to errors when there are problems like underrun, and they are not actually running averages, which would be genuinely useful. But they show promise!
|
||||
|
||||
**Bug Fixes**
|
||||
* Fix a bug in the `dbus` native interface which would silently switch `soxr` interpolation to `basic`.
|
||||
|
||||
+15
-2
@@ -658,7 +658,7 @@ int open_alsa_device(void) {
|
||||
snd_strerror(ret));
|
||||
return -7;
|
||||
}
|
||||
|
||||
|
||||
// check parameters after attempting to set them…
|
||||
|
||||
if (set_period_size_request != 0) {
|
||||
@@ -884,6 +884,12 @@ int delay(long *the_delay) {
|
||||
snd_pcm_recover(alsa_handle, reply, 1);
|
||||
frame_index = 0;
|
||||
measurement_data_is_valid = 0;
|
||||
} else {
|
||||
if (*the_delay == 0) {
|
||||
// there's nothing in the pipeline, so we can't measure frame rate.
|
||||
frame_index = 0; // we'll be starting over...
|
||||
measurement_data_is_valid = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
frame_index = 0; // we'll be starting over...
|
||||
@@ -987,8 +993,15 @@ static int play(void *buf, int samples) {
|
||||
snd_pcm_recover(alsa_handle, err2, 1);
|
||||
frame_index = 0;
|
||||
measurement_data_is_valid = 0;
|
||||
} else {
|
||||
if (fl == 0) {
|
||||
// there's nothing in the pipeline, so we can't measure frame rate.
|
||||
frame_index = 0; // we'll be starting over...
|
||||
measurement_data_is_valid = 0;
|
||||
}
|
||||
}
|
||||
measurement_time = get_absolute_time_in_fp();
|
||||
|
||||
uint64_t tf = get_absolute_time_in_fp();
|
||||
frames_played_at_measurement_time = frames_sent_for_playing - fl;
|
||||
if (frame_index == start_measurement_from_this_frame) {
|
||||
frames_played_at_measurement_start_time = frames_played_at_measurement_time;
|
||||
|
||||
@@ -277,7 +277,7 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
|
||||
}
|
||||
|
||||
if (http_iserror(&rt)) {
|
||||
debug(1, "Error parsing data.");
|
||||
debug(3, "Error parsing data.");
|
||||
free(response.body);
|
||||
response.body = NULL;
|
||||
response.malloced_size = 0;
|
||||
|
||||
@@ -20,4 +20,9 @@ dbus-send --system --print-reply --type=method_call --dest=org.gnome.ShairportSy
|
||||
#Remote Control commands include: Play, Pause, PlayPause, Resume, Stop, Next, Previous, VolumeUp, VolumeDown, ToggleMute, FastForward, Rewind, ShuffleSongs
|
||||
|
||||
# Set Volume using Advanced Remote Control
|
||||
dbus-send --system --print-reply --type=method_call --dest=org.gnome.ShairportSync '/org/gnome/ShairportSync' org.gnome.ShairportSync.AdvancedRemoteControl.SetVolume int32:50
|
||||
dbus-send --system --print-reply --type=method_call --dest=org.gnome.ShairportSync '/org/gnome/ShairportSync' org.gnome.ShairportSync.AdvancedRemoteControl.SetVolume int32:50
|
||||
|
||||
# Get Drift Tolerance
|
||||
dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Get string:org.gnome.ShairportSync string:DriftTolerance
|
||||
# Set Drift Tolerance to 1 millisecond
|
||||
dbus-send --print-reply --system --dest=org.gnome.ShairportSync /org/gnome/ShairportSync org.freedesktop.DBus.Properties.Set string:org.gnome.ShairportSync string:DriftTolerance variant:double:0.001
|
||||
|
||||
@@ -1282,6 +1282,9 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
|
||||
if (notified_buffer_empty == 0) {
|
||||
debug(3, "Buffers exhausted.");
|
||||
notified_buffer_empty = 1;
|
||||
conn->initial_reference_time = 0;
|
||||
conn->initial_reference_timestamp = 0;
|
||||
conn->input_frame_rate_starting_point_is_valid = 0;
|
||||
}
|
||||
do_wait = 1;
|
||||
}
|
||||
@@ -1293,7 +1296,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
|
||||
time_to_wait_for_wakeup_fp *= 4 * 352; // four full 352-frame packets
|
||||
time_to_wait_for_wakeup_fp /= 3; // four thirds of a packet time
|
||||
|
||||
time_to_wait_for_wakeup_fp = (uint64_t)0x200000000/(uint64_t)1000; // two millisecond
|
||||
time_to_wait_for_wakeup_fp = (uint64_t)0x200000000 / (uint64_t)1000; // two millisecond
|
||||
|
||||
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
|
||||
uint64_t time_of_wakeup_fp = local_time_now + time_to_wait_for_wakeup_fp;
|
||||
@@ -1813,10 +1816,12 @@ void *player_thread_func(void *arg) {
|
||||
"min DAC queue size, "
|
||||
"min buffer occupancy, "
|
||||
"max buffer occupancy, "
|
||||
"source frames per second, "
|
||||
"average input frames per second, "
|
||||
"source nominal frames per second, "
|
||||
"source actual frames per second, "
|
||||
"output frames per second, "
|
||||
"client:local clock drift in ppm");
|
||||
"source clock drift in ppm, "
|
||||
"source clock drift sample count, "
|
||||
"rough calculated correction in ppm");
|
||||
} else {
|
||||
inform("sync error in milliseconds, "
|
||||
"total packets, "
|
||||
@@ -1827,7 +1832,10 @@ void *player_thread_func(void *arg) {
|
||||
"min DAC queue size, "
|
||||
"min buffer occupancy, "
|
||||
"max buffer occupancy, "
|
||||
"input frames per second.");
|
||||
"source nominal frames per second, "
|
||||
"source actual frames per second, "
|
||||
"source clock drift in ppm, "
|
||||
"source clock drift sample count");
|
||||
}
|
||||
} else {
|
||||
inform("sync error in milliseconds, "
|
||||
@@ -1838,7 +1846,10 @@ void *player_thread_func(void *arg) {
|
||||
"resend requests, "
|
||||
"min buffer occupancy, "
|
||||
"max buffer occupancy, "
|
||||
"input frames per second.");
|
||||
"source nominal frames per second, "
|
||||
"source actual frames per second, "
|
||||
"source clock drift in ppm, "
|
||||
"source clock drift sample count");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2096,10 +2107,20 @@ void *player_thread_func(void *arg) {
|
||||
int64_t should_be_frame;
|
||||
local_time_to_frame(local_time_now, &should_be_frame, conn);
|
||||
|
||||
<<<<<<< HEAD
|
||||
//if (abs(td_in_frames + rt - should_be_frame) > 10 * conn->output_sample_ratio)
|
||||
// debug(1, "Difference between old and new frame number is %" PRId64 " frames.",
|
||||
// td_in_frames + rt - should_be_frame);
|
||||
|
||||
=======
|
||||
int64_t absolute_difference_in_frames = td_in_frames + rt - should_be_frame;
|
||||
if (absolute_difference_in_frames < 0)
|
||||
absolute_difference_in_frames = -absolute_difference_in_frames;
|
||||
|
||||
if (absolute_difference_in_frames > 10 * conn->output_sample_ratio)
|
||||
debug(1, "Difference between old and new frame number is %" PRId64 " frames.",
|
||||
td_in_frames + rt - should_be_frame);
|
||||
>>>>>>> 347e63ba906e80bfc01596bacfbd18fbe0b6f940
|
||||
// this is the actual delay, including the latency we actually want, which will
|
||||
// fluctuate a good bit about a potentially rising or falling trend.
|
||||
|
||||
@@ -2119,8 +2140,8 @@ void *player_thread_func(void *arg) {
|
||||
delay - (conn->latency * conn->output_sample_ratio +
|
||||
(int64_t)(config.audio_backend_latency_offset *
|
||||
config.output_rate)); // int64_t from int64_t - int32_t, so okay
|
||||
|
||||
//debug(1,"%" PRId64 "",sync_error,inbuflength);
|
||||
|
||||
// debug(1,"%" PRId64 "",sync_error,inbuflength);
|
||||
|
||||
// not too sure if abs() is implemented for int64_t, so we'll do it manually
|
||||
int64_t abs_sync_error = sync_error;
|
||||
@@ -2181,24 +2202,25 @@ void *player_thread_func(void *arg) {
|
||||
amount_to_stuff = 1;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (amount_to_stuff==0) {
|
||||
|
||||
if (amount_to_stuff == 0) {
|
||||
// use a "V" shaped function to decide if stuffing should occur
|
||||
int64_t s = r64i();
|
||||
s = s>>31;
|
||||
s = s >> 31;
|
||||
s = s * config.tolerance * config.output_rate;
|
||||
s = (s>>32)+config.tolerance * config.output_rate; //should be a number from 0 to config.tolerance * config.output_rate;
|
||||
if ((sync_error>0) && (sync_error>s)) {
|
||||
//debug(1,"Extra stuff -1");
|
||||
s = (s >> 32) + config.tolerance * config.output_rate; // should be a number from 0
|
||||
// to config.tolerance *
|
||||
// config.output_rate;
|
||||
if ((sync_error > 0) && (sync_error > s)) {
|
||||
// debug(1,"Extra stuff -1");
|
||||
amount_to_stuff = -1;
|
||||
}
|
||||
if ((sync_error<0) && (sync_error<(-s))) {
|
||||
//debug(1,"Extra stuff +1");
|
||||
if ((sync_error < 0) && (sync_error < (-s))) {
|
||||
// debug(1,"Extra stuff +1");
|
||||
amount_to_stuff = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// try to keep the corrections definitely below 1 in 1000 audio frames
|
||||
|
||||
// calculate the time elapsed since the play session started.
|
||||
@@ -2276,14 +2298,15 @@ void *player_thread_func(void *arg) {
|
||||
tbuf32[2 * i + 1] = fbuf_r[i];
|
||||
}
|
||||
}
|
||||
|
||||
if ((current_delay < DAC_BUFFER_QUEUE_MINIMUM_LENGTH) || (config.packet_stuffing == ST_basic)) {
|
||||
|
||||
if ((current_delay < DAC_BUFFER_QUEUE_MINIMUM_LENGTH) ||
|
||||
(config.packet_stuffing == ST_basic)) {
|
||||
play_samples =
|
||||
stuff_buffer_basic_32((int32_t *)conn->tbuf, inbuflength, config.output_format,
|
||||
conn->outbuf, amount_to_stuff, enable_dither, conn);
|
||||
conn->outbuf, amount_to_stuff, enable_dither, conn);
|
||||
}
|
||||
#ifdef HAVE_LIBSOXR
|
||||
else if (config.packet_stuffing == ST_soxr) {
|
||||
else if (config.packet_stuffing == ST_soxr) {
|
||||
// if (amount_to_stuff) debug(1,"Soxr stuff...");
|
||||
play_samples = stuff_buffer_soxr_32((int32_t *)conn->tbuf, (int32_t *)conn->sbuf,
|
||||
inbuflength, config.output_format, conn->outbuf,
|
||||
@@ -2437,10 +2460,10 @@ void *player_thread_func(void *arg) {
|
||||
conn->frame_rate =
|
||||
(1.0 * frames_played) /
|
||||
elapsed_play_time; // an IEEE double calculation with two 64-bit integers
|
||||
conn->frame_rate = conn->frame_rate *
|
||||
(uint64_t)0x100000000; // this should just change the [binary]
|
||||
// exponent in the IEEE FP representation;
|
||||
// the mantissa should be unaffected.
|
||||
conn->frame_rate =
|
||||
conn->frame_rate * (uint64_t)0x100000000; // this should just change the [binary]
|
||||
// exponent in the IEEE FP representation;
|
||||
// the mantissa should be unaffected.
|
||||
} else {
|
||||
conn->frame_rate = 0.0;
|
||||
}
|
||||
@@ -2459,22 +2482,23 @@ void *player_thread_func(void *arg) {
|
||||
|
||||
if ((config.output->delay)) {
|
||||
if (config.no_sync == 0) {
|
||||
inform("%*.2f," /* Sync error in milliseconds */
|
||||
"%*.1f," /* net correction in ppm */
|
||||
"%*.1f," /* corrections in ppm */
|
||||
"%*d," /* total packets */
|
||||
"%*llu," /* missing packets */
|
||||
"%*llu," /* late packets */
|
||||
"%*llu," /* too late packets */
|
||||
"%*llu," /* resend requests */
|
||||
"%*lli," /* min DAC queue size */
|
||||
"%*d," /* min buffer occupancy */
|
||||
"%*d," /* max buffer occupancy */
|
||||
"%*.2f," /* remote frame rate */
|
||||
"%*.2f," /* actual (average) input frame rate */
|
||||
"%*.2f," /* output frame rate */
|
||||
"%*.2f," /* output frame rate */
|
||||
"%*d", /* sample count */
|
||||
inform("%*.2f," /* Sync error in milliseconds */
|
||||
"%*.1f," /* net correction in ppm */
|
||||
"%*.1f," /* corrections in ppm */
|
||||
"%*d," /* total packets */
|
||||
"%*" PRIu64 "," /* missing packets */
|
||||
"%*" PRIu64 "," /* late packets */
|
||||
"%*" PRIu64 "," /* too late packets */
|
||||
"%*" PRIu64 "," /* resend requests */
|
||||
"%*" PRId64 "," /* min DAC queue size */
|
||||
"%*" PRId32 "," /* min buffer occupancy */
|
||||
"%*" PRId32 "," /* max buffer occupancy */
|
||||
"%*.2f," /* source nominal frame rate */
|
||||
"%*.2f," /* source actual (average) frame rate */
|
||||
"%*.2f," /* output frame rate */
|
||||
"%*.2f," /* source clock drift */
|
||||
"%*d," /* source clock drift sample count */
|
||||
"%*.2f", /* rough calculated correction in ppm */
|
||||
10,
|
||||
1000 * moving_average_sync_error / config.output_rate, 10,
|
||||
moving_average_correction * 1000000 / (352 * conn->output_sample_ratio),
|
||||
@@ -2485,41 +2509,59 @@ void *player_thread_func(void *arg) {
|
||||
minimum_dac_queue_size, 5, minimum_buffer_occupancy, 5,
|
||||
maximum_buffer_occupancy, 11, conn->remote_frame_rate, 11,
|
||||
conn->input_frame_rate, 11, conn->frame_rate, 10,
|
||||
(1.0 - conn->local_to_remote_time_gradient) * 1000000, 6,
|
||||
conn->local_to_remote_time_gradient_sample_count);
|
||||
(conn->local_to_remote_time_gradient - 1.0) * 1000000, 6,
|
||||
conn->local_to_remote_time_gradient_sample_count, 10,
|
||||
(conn->frame_rate > 0.0)
|
||||
? ((conn->frame_rate -
|
||||
conn->remote_frame_rate * conn->output_sample_ratio *
|
||||
conn->local_to_remote_time_gradient) *
|
||||
1000000) /
|
||||
conn->frame_rate
|
||||
: 0.0);
|
||||
} else {
|
||||
inform("%*.2f," /* Sync error in milliseconds */
|
||||
"%*d," /* total packets */
|
||||
"%*llu," /* missing packets */
|
||||
"%*llu," /* late packets */
|
||||
"%*llu," /* too late packets */
|
||||
"%*llu," /* resend requests */
|
||||
"%*lli," /* min DAC queue size */
|
||||
"%*d," /* min buffer occupancy */
|
||||
"%*d," /* max buffer occupancy */
|
||||
"%*.2f", /* input frame rate */
|
||||
inform("%*.2f," /* Sync error in milliseconds */
|
||||
"%*d," /* total packets */
|
||||
"%*" PRIu64 "," /* missing packets */
|
||||
"%*" PRIu64 "," /* late packets */
|
||||
"%*" PRIu64 "," /* too late packets */
|
||||
"%*" PRIu64 "," /* resend requests */
|
||||
"%*" PRId64 "," /* min DAC queue size */
|
||||
"%*" PRId32 "," /* min buffer occupancy */
|
||||
"%*" PRId32 "," /* max buffer occupancy */
|
||||
"%*.2f," /* source nominal frame rate */
|
||||
"%*.2f," /* source actual (average) frame rate */
|
||||
"%*.2f," /* source clock drift */
|
||||
"%*d", /* source clock drift sample count */
|
||||
10,
|
||||
1000 * moving_average_sync_error / config.output_rate, 12, play_number, 7,
|
||||
conn->missing_packets, 7, conn->late_packets, 7, conn->too_late_packets, 7,
|
||||
conn->resend_requests, 7, minimum_dac_queue_size, 5,
|
||||
minimum_buffer_occupancy, 5, maximum_buffer_occupancy, 11,
|
||||
conn->input_frame_rate);
|
||||
conn->remote_frame_rate, 11, conn->input_frame_rate, 10,
|
||||
(conn->local_to_remote_time_gradient - 1.0) * 1000000, 6,
|
||||
conn->local_to_remote_time_gradient_sample_count);
|
||||
}
|
||||
} else {
|
||||
inform("%*.2f," /* Sync error in milliseconds */
|
||||
"%*d," /* total packets */
|
||||
"%*llu," /* missing packets */
|
||||
"%*llu," /* late packets */
|
||||
"%*llu," /* too late packets */
|
||||
"%*llu," /* resend requests */
|
||||
"%*d," /* min buffer occupancy */
|
||||
"%*d," /* max buffer occupancy */
|
||||
"%*.2f", /* input frame rate */
|
||||
inform("%*.2f," /* Sync error in milliseconds */
|
||||
"%*d," /* total packets */
|
||||
"%*" PRIu64 "," /* missing packets */
|
||||
"%*" PRIu64 "," /* late packets */
|
||||
"%*" PRIu64 "," /* too late packets */
|
||||
"%*" PRIu64 "," /* resend requests */
|
||||
"%*" PRId32 "," /* min buffer occupancy */
|
||||
"%*" PRId32 "," /* max buffer occupancy */
|
||||
"%*.2f," /* source nominal frame rate */
|
||||
"%*.2f," /* source actual (average) frame rate */
|
||||
"%*.2f," /* source clock drift */
|
||||
"%*d", /* source clock drift sample count */
|
||||
10,
|
||||
1000 * moving_average_sync_error / config.output_rate, 12, play_number, 7,
|
||||
conn->missing_packets, 7, conn->late_packets, 7, conn->too_late_packets, 7,
|
||||
conn->resend_requests, 5, minimum_buffer_occupancy, 5,
|
||||
maximum_buffer_occupancy, 11, conn->input_frame_rate);
|
||||
maximum_buffer_occupancy, 11, conn->remote_frame_rate, 11,
|
||||
conn->input_frame_rate, 10,
|
||||
(conn->local_to_remote_time_gradient - 1.0) * 1000000, 6,
|
||||
conn->local_to_remote_time_gradient_sample_count);
|
||||
}
|
||||
} else {
|
||||
inform("No frames received in the last sampling interval.");
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "alac.h"
|
||||
#include "audio.h"
|
||||
|
||||
#define time_ping_history 64 // at 1 per three seconds, approximately three minutes of records
|
||||
#define time_ping_history 128 // at 1 per three seconds, approximately six minutes of records
|
||||
|
||||
typedef struct time_ping_record {
|
||||
uint64_t local_to_remote_difference;
|
||||
|
||||
@@ -765,41 +765,40 @@ void *rtp_timing_receiver(void *arg) {
|
||||
x_bar += (conn->time_pings[cc].local_time >> 12);
|
||||
sample_count++;
|
||||
}
|
||||
|
||||
y_bar = y_bar / sample_count;
|
||||
x_bar = x_bar / sample_count;
|
||||
|
||||
int64_t xid, yid;
|
||||
int64_t mtl, mbl;
|
||||
mtl = 0;
|
||||
mbl = 0;
|
||||
for (cc = 0; cc < conn->time_ping_count; cc++)
|
||||
if ((conn->time_pings[cc].chosen) &&
|
||||
(conn->time_pings[cc].sequence_number > (settling_time / 3))) {
|
||||
|
||||
uint64_t slt = conn->time_pings[cc].local_time >> 12;
|
||||
if (slt > x_bar)
|
||||
xid = slt - x_bar;
|
||||
else
|
||||
xid = -(x_bar - slt);
|
||||
|
||||
uint64_t srt = conn->time_pings[cc].remote_time >> 12;
|
||||
if (srt > y_bar)
|
||||
yid = srt - y_bar;
|
||||
else
|
||||
yid = -(y_bar - srt);
|
||||
|
||||
mtl = mtl + xid * yid;
|
||||
mbl = mbl + xid * xid;
|
||||
}
|
||||
conn->local_to_remote_time_gradient_sample_count = sample_count;
|
||||
if (sample_count > sample_point_minimum) {
|
||||
y_bar = y_bar / sample_count;
|
||||
x_bar = x_bar / sample_count;
|
||||
|
||||
int64_t xid, yid;
|
||||
int64_t mtl, mbl;
|
||||
mtl = 0;
|
||||
mbl = 0;
|
||||
for (cc = 0; cc < conn->time_ping_count; cc++)
|
||||
if ((conn->time_pings[cc].chosen) &&
|
||||
(conn->time_pings[cc].sequence_number > (settling_time / 3))) {
|
||||
|
||||
uint64_t slt = conn->time_pings[cc].local_time >> 12;
|
||||
if (slt > x_bar)
|
||||
xid = slt - x_bar;
|
||||
else
|
||||
xid = -(x_bar - slt);
|
||||
|
||||
uint64_t srt = conn->time_pings[cc].remote_time >> 12;
|
||||
if (srt > y_bar)
|
||||
yid = srt - y_bar;
|
||||
else
|
||||
yid = -(y_bar - srt);
|
||||
|
||||
mtl = mtl + xid * yid;
|
||||
mbl = mbl + xid * xid;
|
||||
}
|
||||
conn->local_to_remote_time_gradient_sample_count = sample_count;
|
||||
conn->local_to_remote_time_gradient = (1.0 * mtl) / mbl;
|
||||
// debug(1,"Drift is %12.2f ppm, based on %d
|
||||
// samples.",(1.0-conn->local_to_remote_time_gradient)*1000000,sample_count);
|
||||
} else {
|
||||
conn->local_to_remote_time_gradient = 1.0;
|
||||
}
|
||||
// debug(1,"local to remote time gradient is %12.2f ppm, based on %d
|
||||
// samples.",conn->local_to_remote_time_gradient*1000000,sample_count);
|
||||
} else {
|
||||
debug(2, "Time ping turnaround time: %lld us -- it looks like a timing ping was lost.",
|
||||
(return_time * 1000000) >> 32);
|
||||
|
||||
@@ -14,7 +14,7 @@ stop_cmd="${name}_stop"
|
||||
|
||||
shairport_sync_start()
|
||||
{
|
||||
checkyesno shairport_sync_enable && echo "Starting shairport-sync." && \
|
||||
checkyesno shairport_sync_enable && echo "Starting shairport-sync." && \
|
||||
su -m shairport-sync -c "/usr/local/bin/shairport-sync -d"
|
||||
}
|
||||
|
||||
|
||||
+12
-25
@@ -23,8 +23,7 @@ DAEMON=@prefix@/bin/$NAME
|
||||
# impossible to pass as arguments.
|
||||
|
||||
# Instead, we add the arguments directly to the relevant line in the do_start() function below
|
||||
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
PIDFILE=/var/run/$NAME/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
|
||||
# Exit if the package is not installed
|
||||
@@ -48,31 +47,19 @@ do_start()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
# 1 if PID directory didn't exist and couldn't be created with approproate permission
|
||||
# 2 if daemon was already running
|
||||
# 3 if daemon could not be started
|
||||
[ -e /var/run/shairport-sync ] || ( mkdir -p /var/run/shairport-sync && chown shairport-sync:shairport-sync /var/run/shairport-sync ) || return 1
|
||||
start-stop-daemon -c shairport-sync:shairport-sync --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null || return 2
|
||||
|
||||
# This script is set to start running after all other services have started.
|
||||
# However, if you find that Shairport Sync is still being started before what it needs is ready,
|
||||
# uncomment the next line to get the script to wait for three seconds before attempting to start Shairport Sync.
|
||||
# sleep 3
|
||||
# This script is set to start running after all other services have started.
|
||||
# However, if you find that Shairport Sync is still being started before what it needs is ready,
|
||||
# uncomment the next line to get the script to wait for three seconds before attempting to start Shairport Sync.
|
||||
# sleep 3
|
||||
|
||||
# Uncomment just one of the following start-stop-daemon lines, or comment them all out and add your own.
|
||||
# Shairport Sync will read settings from the configuration file (/etc/shairport-sync.conf by default) and will then apply any command line options.
|
||||
# In the default script, the first line is uncommented, selecting daemon mode (-d). Settings will be taken from the configuration file.
|
||||
# BTW, if you're using software volume control, you may have to use alsamixer or similar to set the output device's volume to its maximum level first
|
||||
# BTW2, you can use alsamixer to find device identifiers (e.g. hw:1) and mixer names (e.g. "Speaker"). No need to change ALSA's defaults.
|
||||
# BTW3, the argument after -a is simply the name the shairport service will be visible as.
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- -d || return 2
|
||||
# start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- -d -a "Topping TP30 or Griffin iMic on Raspberry Pi" -- -d hw:1 -t hardware -c "PCM" || return 2
|
||||
# start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- -d -a "'3D Sound' USB Soundcard on Raspberry Pi" -- -d hw:1 -t hardware -c "Speaker" || return 2
|
||||
# BTW, that "3D Sound" USB soundcard sometimes has the mixer name "Headphone" rather than "Speaker" -- use alsamixer to check.
|
||||
# start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- -d -a "IQaudIO" -- -d hw:1 -t hardware -c "Playback Digital" || return 2
|
||||
# BTW, newer versions of IQaudIO have a different mixer name -- use alsamixer to check.
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
||||
# to handle requests from services started subsequently which depend
|
||||
# on this one. As a last resort, sleep for some time.
|
||||
# Settings from the configuration file (@sysconfdir@/shairport-sync.conf by default)
|
||||
start-stop-daemon -c shairport-sync:shairport-sync --start --quiet --pidfile $PIDFILE --exec $DAEMON -- -d || return 3
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user