Add an "active" mode that can time out after a period -- 10 seconds by default -- after play ends.

This commit is contained in:
Mike Brady
2019-01-21 21:43:55 +00:00
parent 604ca8dee4
commit 2e4428538d
18 changed files with 300 additions and 261 deletions
+99 -90
View File
@@ -1,11 +1,11 @@
/*
* Activity Monitor
*
*
* Contains code to run an activity flag and associated timer
* A pthread implements a simple state machine with three states,
* A pthread implements a simple state machine with three states,
* "idle", "active" and "timing out".
*
*
*
*
* This file is part of Shairport Sync.
* Copyright (c) Mike Brady 2019
* All rights reserved.
@@ -31,41 +31,43 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/types.h>
#include "config.h"
#include "activity_monitor.h"
#include "common.h"
#include "rtsp.h"
#include "activity_monitor.h"
enum am_state {am_inactive, am_active, am_timing_out} state;
enum ps_state {ps_inactive, ps_active} player_state;
enum am_state { am_inactive, am_active, am_timing_out } state;
enum ps_state { ps_inactive, ps_active } player_state;
pthread_t activity_monitor_thread;
pthread_mutex_t activity_monitor_mutex;
pthread_cond_t activity_monitor_cv;
void going_active(int block) {
// debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" : "out");
// debug(1, "activity_monitor: state transitioning to \"active\" with%s blocking", block ? "" :
// "out");
if (config.cmd_active_start)
command_execute(config.cmd_active_start, "", block);
#ifdef CONFIG_METADATA
debug(2, "abeg"); // active mode begin
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
debug(2, "abeg"); // active mode begin
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
#endif
}
void going_inactive(int block) {
// debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" : "out");
// debug(1, "activity_monitor: state transitioning to \"inactive\" with%s blocking", block ? "" :
// "out");
if (config.cmd_active_stop)
command_execute(config.cmd_active_stop, "", block);
#ifdef CONFIG_METADATA
debug(2, "aend"); // active mode end
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
debug(2, "aend"); // active mode end
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
#endif
}
@@ -83,17 +85,20 @@ void activity_monitor_signify_activity(int active) {
// The reason for all this is that we might want to perform the attached scripts
// and wait for them to complete before continuing. If they were perfomed in the
// activity monitor thread, then we coldn't wait for them to complete.
// Thus, the only time the thread will execute a going_... function is when a non-zero
// timeout actually matures.
if ((state == am_inactive) && (player_state == ps_active)) {
going_active(config.cmd_blocking); // note -- will be executed with the mutex locked, but that's okay
} else if ((state == am_active) && (player_state == ps_inactive) && (config.active_mode_timeout == 0.0)) {
going_inactive(config.cmd_blocking); // note -- will be executed with the mutex locked, but that's okay
going_active(
config.cmd_blocking); // note -- will be executed with the mutex locked, but that's okay
} else if ((state == am_active) && (player_state == ps_inactive) &&
(config.active_mode_timeout == 0.0)) {
going_inactive(
config.cmd_blocking); // note -- will be executed with the mutex locked, but that's okay
}
pthread_cond_signal(&activity_monitor_cv);
pthread_cond_signal(&activity_monitor_cv);
pthread_mutex_unlock(&activity_monitor_mutex);
}
@@ -115,7 +120,7 @@ void *activity_monitor_thread_code(void *arg) {
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); // can't do this in OS X, and don't need it.
rc = pthread_cond_init(&activity_monitor_cv, &attr);
pthread_condattr_destroy(&attr);
#endif
#ifdef COMPILE_FOR_OSX
rc = pthread_cond_init(&activity_monitor_cv, NULL);
@@ -123,84 +128,89 @@ void *activity_monitor_thread_code(void *arg) {
if (rc)
die("activity_monitor: error %d initialising activity_monitor_cv.");
pthread_cleanup_push(activity_thread_cleanup_handler, arg);
uint64_t sec;
uint64_t nsec;
int rc;
struct timespec time_for_wait;
state = am_inactive;
player_state = ps_inactive;
pthread_mutex_lock(&activity_monitor_mutex);
do {
switch (state) {
case am_inactive:
// debug(1,"am_state: am_inactive");
while (player_state != ps_active)
pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);
state = am_active;
// going_active(); // this is done in activity_monitor_signify_activity
case am_inactive:
// debug(1,"am_state: am_inactive");
while (player_state != ps_active)
pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);
state = am_active;
// going_active(); // this is done in activity_monitor_signify_activity
break;
case am_active:
// debug(1,"am_state: am_active");
while (player_state != ps_inactive)
pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);
if (config.active_mode_timeout == 0.0) {
state = am_inactive;
// going_inactive(); // this is done in activity_monitor_signify_activity
} else {
state = am_timing_out;
uint64_t time_to_wait_for_wakeup_fp = (uint64_t)(config.active_mode_timeout *1000000); // resolution of microseconds
time_to_wait_for_wakeup_fp = time_to_wait_for_wakeup_fp << 32;
time_to_wait_for_wakeup_fp = time_to_wait_for_wakeup_fp / 1000000;
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
uint64_t time_of_wakeup_fp = get_absolute_time_in_fp() + time_to_wait_for_wakeup_fp;
sec = time_of_wakeup_fp >> 32;
nsec = ((time_of_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
time_for_wait.tv_sec = sec;
time_for_wait.tv_nsec = nsec;
#endif
#ifdef COMPILE_FOR_OSX
sec = time_to_wait_for_wakeup_fp >> 32;
nsec = ((time_to_wait_for_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
time_for_wait.tv_sec = sec;
time_for_wait.tv_nsec = nsec;
#endif
}
break;
case am_timing_out:
// debug(1,"am_state: am_timing_out");
rc = 0;
while ((player_state != ps_active) && (rc != ETIMEDOUT)) {
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
rc = pthread_cond_timedwait(&activity_monitor_cv, &activity_monitor_mutex, &time_for_wait); // this is a pthread cancellation point
#endif
#ifdef COMPILE_FOR_OSX
rc = pthread_cond_timedwait_relative_np(&activity_monitor_cv, &activity_monitor_mutex, &time_for_wait);
#endif
}
if (player_state == ps_active)
state = am_active; // player has gone active -- do nothing, because it's still active
else if (rc == ETIMEDOUT) {
state = am_inactive;
pthread_mutex_unlock(&activity_monitor_mutex);
going_inactive(0); // don't wait for completion -- it makes no sense
pthread_mutex_lock(&activity_monitor_mutex);
} else {
// activity monitor was woken up in the state am_timing_out, but not by a timeout and player is not in ps_active state
debug(1, "activity monitor was woken up in the state am_timing_out, but didn't change state");
}
break;
default:
debug(1,"activity monitor in an illegal state!");
case am_active:
// debug(1,"am_state: am_active");
while (player_state != ps_inactive)
pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);
if (config.active_mode_timeout == 0.0) {
state = am_inactive;
// going_inactive(); // this is done in activity_monitor_signify_activity
} else {
state = am_timing_out;
uint64_t time_to_wait_for_wakeup_fp =
(uint64_t)(config.active_mode_timeout * 1000000); // resolution of microseconds
time_to_wait_for_wakeup_fp = time_to_wait_for_wakeup_fp << 32;
time_to_wait_for_wakeup_fp = time_to_wait_for_wakeup_fp / 1000000;
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
uint64_t time_of_wakeup_fp = get_absolute_time_in_fp() + time_to_wait_for_wakeup_fp;
sec = time_of_wakeup_fp >> 32;
nsec = ((time_of_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
time_for_wait.tv_sec = sec;
time_for_wait.tv_nsec = nsec;
#endif
#ifdef COMPILE_FOR_OSX
sec = time_to_wait_for_wakeup_fp >> 32;
nsec = ((time_to_wait_for_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
time_for_wait.tv_sec = sec;
time_for_wait.tv_nsec = nsec;
#endif
}
break;
case am_timing_out:
// debug(1,"am_state: am_timing_out");
rc = 0;
while ((player_state != ps_active) && (rc != ETIMEDOUT)) {
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN_AND_OPENBSD
rc = pthread_cond_timedwait(&activity_monitor_cv, &activity_monitor_mutex,
&time_for_wait); // this is a pthread cancellation point
#endif
#ifdef COMPILE_FOR_OSX
rc = pthread_cond_timedwait_relative_np(&activity_monitor_cv, &activity_monitor_mutex,
&time_for_wait);
#endif
}
if (player_state == ps_active)
state = am_active; // player has gone active -- do nothing, because it's still active
else if (rc == ETIMEDOUT) {
state = am_inactive;
pthread_mutex_unlock(&activity_monitor_mutex);
going_inactive(0); // don't wait for completion -- it makes no sense
pthread_mutex_lock(&activity_monitor_mutex);
} else {
// activity monitor was woken up in the state am_timing_out, but not by a timeout and player
// is not in ps_active state
debug(1,
"activity monitor was woken up in the state am_timing_out, but didn't change state");
}
break;
default:
debug(1, "activity monitor in an illegal state!");
state = am_inactive;
break;
}
} while (1);
pthread_mutex_unlock(&activity_monitor_mutex);
pthread_mutex_unlock(&activity_monitor_mutex);
pthread_cleanup_pop(0); // should never happen
pthread_exit(NULL);
}
@@ -211,9 +221,8 @@ void activity_monitor_start() {
}
void activity_monitor_stop() {
debug(1,"activity_monitor_stop start...");
debug(1, "activity_monitor_stop start...");
pthread_cancel(activity_monitor_thread);
pthread_join(activity_monitor_thread,NULL);
debug(1,"activity_monitor_stop complete");
pthread_join(activity_monitor_thread, NULL);
debug(1, "activity_monitor_stop complete");
}
+2 -1
View File
@@ -22,7 +22,8 @@ typedef struct {
void (*start)(int sample_rate, int sample_format);
// block of samples
int (*preflight)(void *buf, int samples); // say you are about to send these samples (before interpolation)
int (*preflight)(void *buf,
int samples); // say you are about to send these samples (before interpolation)
int (*play)(void *buf, int samples);
void (*stop)(void);
+17 -13
View File
@@ -469,8 +469,9 @@ int actual_open_alsa_device(void) {
buffer_size);
}
*/
debug(1, "The alsa buffer is smaller (%lu bytes) than the desired backend buffer "
"length (%ld) you have chosen.",
debug(1,
"The alsa buffer is smaller (%lu bytes) than the desired backend buffer "
"length (%ld) you have chosen.",
actual_buffer_length, config.audio_backend_buffer_desired_length);
}
@@ -633,13 +634,15 @@ static int init(int argc, char **argv) {
config.audio_backend_buffer_interpolation_threshold_in_seconds =
0.120; // below this, basic interpolation will be used to save time.
config.alsa_maximum_stall_time = 0.200; // 200 milliseconds -- if it takes longer, it's a problem
config.audio_backend_silence_threshold = 0.040; //start sending silent frames if the delay goes below this time
config.audio_backend_silence_scan_interval = 0.004; //check silence threshold this often
config.audio_backend_silence_threshold =
0.040; // start sending silent frames if the delay goes below this time
config.audio_backend_silence_scan_interval = 0.004; // check silence threshold this often
stall_monitor_error_threshold =
(uint64_t)1000000 * config.alsa_maximum_stall_time; // stall time max to microseconds;
stall_monitor_error_threshold = (stall_monitor_error_threshold << 32) / 1000000; // now in fp form
debug(1, "stall_monitor_error_threshold is 0x%" PRIx64 ", with alsa_maximum_stall_time of %f sec.",
debug(1,
"stall_monitor_error_threshold is 0x%" PRIx64 ", with alsa_maximum_stall_time of %f sec.",
stall_monitor_error_threshold, config.alsa_maximum_stall_time);
stall_monitor_start_time = 0;
@@ -1047,9 +1050,10 @@ int delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay) {
if (((update_timestamp_ns - stall_monitor_start_time) > stall_monitor_error_threshold) ||
((time_now_ns - stall_monitor_start_time) > stall_monitor_error_threshold)) {
debug(2, "DAC seems to have stalled with time_now_ns: %" PRIX64
", update_timestamp_ns: %" PRIX64 ", stall_monitor_start_time %" PRIX64
", stall_monitor_error_threshold %" PRIX64 ".",
debug(2,
"DAC seems to have stalled with time_now_ns: %" PRIX64
", update_timestamp_ns: %" PRIX64 ", stall_monitor_start_time %" PRIX64
", stall_monitor_error_threshold %" PRIX64 ".",
time_now_ns, update_timestamp_ns, stall_monitor_start_time,
stall_monitor_error_threshold);
ret = sps_extra_code_output_stalled;
@@ -1264,8 +1268,8 @@ static void flush(void) {
int preflight(__attribute__((unused)) void *buf, __attribute__((unused)) int samples) {
uint64_t time_now =
get_absolute_time_in_fp(); // this is to regulate access by the silence filler thread
uint64_t standoff_time = 60; // milliseconds
standoff_time = (standoff_time << 32)/1000;
uint64_t standoff_time = 60; // milliseconds
standoff_time = (standoff_time << 32) / 1000;
most_recent_write_time = time_now + standoff_time;
return 0;
}
@@ -1467,7 +1471,7 @@ void *alsa_buffer_monitor_thread_code(void *arg) {
int sleep_time_ms = (int)(config.audio_backend_silence_scan_interval * 1000);
long buffer_size_threshold = (long)(config.audio_backend_silence_threshold * desired_sample_rate);
uint64_t sleep_time_in_fp = sleep_time_ms;
sleep_time_in_fp = sleep_time_in_fp << 32;
sleep_time_in_fp = sleep_time_in_fp / 1000;
@@ -1489,8 +1493,8 @@ void *alsa_buffer_monitor_thread_code(void *arg) {
if ((most_recent_write_time == 0) || (present_time > most_recent_write_time)) {
// ((present_time > most_recent_write_time) &&
// ((present_time - most_recent_write_time) > (sleep_time_in_fp)))) {
// ((present_time > most_recent_write_time) &&
// ((present_time - most_recent_write_time) > (sleep_time_in_fp)))) {
reply = delay(&buffer_size);
if (reply != 0) {
buffer_size = 0;
+3 -3
View File
@@ -27,7 +27,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <jack/jack.h>
@@ -336,8 +335,9 @@ int jack_init(__attribute__((unused)) int argc, __attribute__((unused)) char **a
* we should try. */
if (config_lookup_int(config.cfg, "jack.auto_client_open_interval", &value)) {
if ((value < 0) || (value > 300))
debug(1, "Invalid jack auto_client_open_interval \"%sd\". It should be between 0 and 300, "
"default is %d.",
debug(1,
"Invalid jack auto_client_open_interval \"%sd\". It should be between 0 and 300, "
"default is %d.",
value, config.jack_auto_client_open_interval);
else
config.jack_auto_client_open_interval = value;
+3 -2
View File
@@ -27,8 +27,9 @@ static void write_callback(struct SoundIoOutStream *outstream, int frame_count_m
int fill_bytes = soundio_ring_buffer_fill_count(ring_buffer);
int fill_count = fill_bytes / outstream->bytes_per_frame;
debug(3, "[--->>] frame_count_min: %d , frame_count_max: %d , fill_bytes: %d , fill_count: %d , "
"outstream->bytes_per_frame: %d",
debug(3,
"[--->>] frame_count_min: %d , frame_count_max: %d , fill_bytes: %d , fill_count: %d , "
"outstream->bytes_per_frame: %d",
frame_count_min, frame_count_max, fill_bytes, fill_count, outstream->bytes_per_frame);
if (frame_count_min > fill_count) {
+20 -18
View File
@@ -114,7 +114,8 @@ uint16_t nextFreeUDPPort() {
if (UDPPortIndex == 0)
UDPPortIndex = config.udp_port_base;
else if (UDPPortIndex == (config.udp_port_base + config.udp_port_range - 1))
UDPPortIndex = config.udp_port_base + 3; // avoid wrapping back to the first three, as they can be assigned by resetFreeUDPPort without checking
UDPPortIndex = config.udp_port_base + 3; // avoid wrapping back to the first three, as they can
// be assigned by resetFreeUDPPort without checking
else
UDPPortIndex++;
return UDPPortIndex;
@@ -394,7 +395,7 @@ uint8_t *base64_dec(char *input, int *outlen) {
#ifdef CONFIG_OPENSSL
char *base64_enc(uint8_t *input, int length) {
int oldState;
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
BIO *bmem, *b64;
BUF_MEM *bptr;
@@ -421,7 +422,7 @@ char *base64_enc(uint8_t *input, int length) {
}
uint8_t *base64_dec(char *input, int *outlen) {
int oldState;
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
BIO *bmem, *b64;
int inlen = strlen(input);
@@ -479,7 +480,7 @@ static char super_secret_key[] =
#ifdef CONFIG_OPENSSL
uint8_t *rsa_apply(uint8_t *input, int inlen, int *outlen, int mode) {
int oldState;
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState);
RSA *rsa = NULL;
if (!rsa) {
@@ -794,7 +795,7 @@ void command_execute(const char *command, const char *extra_argument, const int
void command_stop(void) {
// this has a cancellation point if waiting is enabled
if (config.cmd_stop)
command_execute(config.cmd_stop,"",config.cmd_blocking);
command_execute(config.cmd_stop, "", config.cmd_blocking);
}
// this is for reading an unsigned 32 bit number, such as an RTP timestamp
@@ -829,17 +830,17 @@ double flat_vol2attn(double vol, long max_db, long min_db) {
double vol2attn(double vol, long max_db, long min_db) {
// We use a little coordinate geometry to build a transfer function from the volume passed in to
// the device's dynamic range. (See the diagram in the documents folder.) The x axis is the
// "volume in" which will be from -30 to 0. The y axis will be the "volume out" which will be from
// the bottom of the range to the top. We build the transfer function from one or more lines. We
// characterise each line with two numbers: the first is where on x the line starts when y=0 (x
// can be from 0 to -30); the second is where on y the line stops when when x is -30. thus, if the
// line was characterised as {0,-30}, it would be an identity transfer. Assuming, for example, a
// dynamic range of lv=-60 to hv=0 Typically we'll use three lines -- a three order transfer
// function First: {0,30} giving a gentle slope -- the 30 comes from half the dynamic range
// Second: {-5,-30-(lv+30)/2} giving a faster slope from y=0 at x=-12 to y=-42.5 at x=-30
// Third: {-17,lv} giving a fast slope from y=0 at x=-19 to y=-60 at x=-30
// We use a little coordinate geometry to build a transfer function from the volume passed in to
// the device's dynamic range. (See the diagram in the documents folder.) The x axis is the
// "volume in" which will be from -30 to 0. The y axis will be the "volume out" which will be from
// the bottom of the range to the top. We build the transfer function from one or more lines. We
// characterise each line with two numbers: the first is where on x the line starts when y=0 (x
// can be from 0 to -30); the second is where on y the line stops when when x is -30. thus, if the
// line was characterised as {0,-30}, it would be an identity transfer. Assuming, for example, a
// dynamic range of lv=-60 to hv=0 Typically we'll use three lines -- a three order transfer
// function First: {0,30} giving a gentle slope -- the 30 comes from half the dynamic range
// Second: {-5,-30-(lv+30)/2} giving a faster slope from y=0 at x=-12 to y=-42.5 at x=-30
// Third: {-17,lv} giving a fast slope from y=0 at x=-19 to y=-60 at x=-30
#define order 3
@@ -1151,8 +1152,9 @@ int sps_pthread_mutex_timedlock(pthread_mutex_t *mutex, useconds_t dally_time,
et = (et * 1000000) >> 32; // microseconds
char errstr[1000];
if (r == ETIMEDOUT)
debug(debuglevel, "timed out waiting for a mutex, having waiting %f seconds, with a maximum "
"waiting time of %d microseconds. \"%s\".",
debug(debuglevel,
"timed out waiting for a mutex, having waiting %f seconds, with a maximum "
"waiting time of %d microseconds. \"%s\".",
(1.0 * et) / 1000000, dally_time, debugmessage);
else
debug(debuglevel, "error %d: \"%s\" waiting for a mutex: \"%s\".", r,
+6 -5
View File
@@ -172,15 +172,16 @@ typedef struct {
double audio_backend_buffer_interpolation_threshold_in_seconds; // below this, soxr interpolation
// will not occur -- it'll be
// basic interpolation instead.
double audio_backend_silence_threshold; // below this, silence will be added to the output buffer
double audio_backend_silence_threshold; // below this, silence will be added to the output buffer
double audio_backend_silence_scan_interval; // check the threshold this often
double audio_backend_latency_offset; // this will be the offset in seconds to compensate for any
// fixed latency there might be in the audio path
double audio_backend_silent_lead_in_time; // the length of the silence that should precede a play.
double active_mode_timeout; // the amount of time from when play ends to when the system leaves into the "active" mode.
uint32_t volume_range_db; // the range, in dB, from max dB to min dB. Zero means use the mixer's
// native range.
double active_mode_timeout; // the amount of time from when play ends to when the system leaves
// into the "active" mode.
uint32_t volume_range_db; // the range, in dB, from max dB to min dB. Zero means use the mixer's
// native range.
enum sps_format_t output_format;
enum volume_control_profile_type volume_control_profile;
int output_rate;
+14 -8
View File
@@ -111,7 +111,10 @@ static void response_code(void *opaque, int code) {
}
static const struct http_funcs responseFuncs = {
response_realloc, response_body, response_header, response_code,
response_realloc,
response_body,
response_header,
response_code,
};
// static pthread_mutex_t dacp_conversation_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -324,9 +327,10 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
// debug(1,"Sent command\"%s\" with a response body of size %d.",command,response.size);
// debug(1,"dacp_conversation_lock released.");
} else {
debug(3, "dacp_send_command: could not acquire a lock on the dacp transmit/receive section "
"when attempting to "
"send the command \"%s\". Possible timeout?",
debug(3,
"dacp_send_command: could not acquire a lock on the dacp transmit/receive section "
"when attempting to "
"send the command \"%s\". Possible timeout?",
command);
response.code = 494; // This client is already busy
}
@@ -423,8 +427,9 @@ void set_dacp_server_information(rtsp_conn_info *conn) {
void dacp_monitor_port_update_callback(char *dacp_id, uint16_t port) {
debug_mutex_lock(&dacp_server_information_lock, 500000, 2);
debug(3, "dacp_monitor_port_update_callback with Remote ID \"%s\", target ID \"%s\" and port "
"number %d.",
debug(3,
"dacp_monitor_port_update_callback with Remote ID \"%s\", target ID \"%s\" and port "
"number %d.",
dacp_id, dacp_server.dacp_id, port);
if (strcmp(dacp_id, dacp_server.dacp_id) == 0) {
dacp_server.port = port;
@@ -472,8 +477,9 @@ void *dacp_monitor_thread_code(__attribute__((unused)) void *na) {
(metadata_store.advanced_dacp_server_active != 0);
metadata_store.dacp_server_active = 0;
metadata_store.advanced_dacp_server_active = 0;
debug(2, "setting dacp_server_active and advanced_dacp_server_active to 0 with an update "
"flag value of %d",
debug(2,
"setting dacp_server_active and advanced_dacp_server_active to 0 with an update "
"flag value of %d",
ch);
metadata_hub_modify_epilog(ch);
while (dacp_server.scan_enable == 0) {
+3 -3
View File
@@ -379,7 +379,7 @@ gboolean notify_verbosity_callback(ShairportSyncDiagnostics *skeleton,
}
gboolean notify_disable_standby_callback(ShairportSync *skeleton,
__attribute__((unused)) gpointer user_data) {
__attribute__((unused)) gpointer user_data) {
// debug(1, "\"notify_disable_standby_callback\" called.");
if (shairport_sync_get_disable_standby(skeleton)) {
debug(1, ">> activating disable standby");
@@ -624,9 +624,9 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name
G_CALLBACK(notify_alacdecoder_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::volume-control-profile",
G_CALLBACK(notify_volume_control_profile_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::disable-standby",
g_signal_connect(shairportSyncSkeleton, "notify::disable-standby",
G_CALLBACK(notify_disable_standby_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::loudness-filter-active",
g_signal_connect(shairportSyncSkeleton, "notify::loudness-filter-active",
G_CALLBACK(notify_loudness_filter_active_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::loudness-threshold",
G_CALLBACK(notify_loudness_threshold_callback), NULL);
+1 -1
View File
@@ -24,8 +24,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "mdns.h"
#include "common.h"
#include "mdns.h"
#include <arpa/inet.h>
#include <dns_sd.h>
#include <stdlib.h>
+1 -1
View File
@@ -24,8 +24,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "mdns.h"
#include "common.h"
#include "mdns.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
+1 -1
View File
@@ -205,7 +205,7 @@ char *metadata_write_image_file(const char *buf, int len) {
char *path = NULL; // this will be what is returned
uint8_t img_md5[16];
// uint8_t ap_md5[16];
// uint8_t ap_md5[16];
#ifdef CONFIG_SSL
MD5_CTX ctx;
+1 -2
View File
@@ -82,8 +82,7 @@ typedef struct metadata_bundle {
enum play_status_type
player_state; // this is the state of the actual player itself, which can be a bit noisy.
enum active_mode_type
active_state;
enum active_mode_type active_state;
int speaker_volume; // this is the actual speaker volume, allowing for the main volume and the
// speaker volume control
+74 -73
View File
@@ -285,16 +285,18 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
}
if (outsize > toutsize) {
debug(2, "Output from alac_decode larger (%d bytes, not frames) than expected (%d bytes) -- "
"truncated, but buffer overflow possible! Encrypted = %d.",
debug(2,
"Output from alac_decode larger (%d bytes, not frames) than expected (%d bytes) -- "
"truncated, but buffer overflow possible! Encrypted = %d.",
outsize, toutsize, conn->stream.encrypted);
reply = -1; // output packet is the wrong size
}
*destlen = outsize / conn->input_bytes_per_frame;
if ((outsize % conn->input_bytes_per_frame) != 0)
debug(1, "Number of audio frames (%d) does not correspond exactly to the number of bytes (%d) "
"and the audio frame size (%d).",
debug(1,
"Number of audio frames (%d) does not correspond exactly to the number of bytes (%d) "
"and the audio frame size (%d).",
*destlen, outsize, conn->input_bytes_per_frame);
return reply;
}
@@ -454,9 +456,10 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, uint8_t *data, in
if ((conn->flush_rtp_timestamp != 0) && (actual_timestamp != conn->flush_rtp_timestamp) &&
(modulo_32_offset(actual_timestamp, conn->flush_rtp_timestamp) <
conn->input_rate * 10)) { // if it's less than 10 seconds
debug(3, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRIu32
", flushing to "
"timestamp: %" PRIu32 ".",
debug(3,
"Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRIu32
", flushing to "
"timestamp: %" PRIu32 ".",
seqno, actual_timestamp, conn->flush_rtp_timestamp);
conn->initial_reference_time = 0;
conn->initial_reference_timestamp = 0;
@@ -849,9 +852,10 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
(curframe->given_timestamp != conn->flush_rtp_timestamp) &&
(modulo_32_offset(curframe->given_timestamp, conn->flush_rtp_timestamp) <
conn->input_rate * 10)) { // if it's less than ten seconds
debug(3, "Dropping flushed packet in buffer_get_frame, seqno %u, timestamp %" PRIu32
", flushing to "
"timestamp: %" PRIu32 ".",
debug(3,
"Dropping flushed packet in buffer_get_frame, seqno %u, timestamp %" PRIu32
", flushing to "
"timestamp: %" PRIu32 ".",
curframe->sequence_number, curframe->given_timestamp, conn->flush_rtp_timestamp);
curframe->ready = 0;
curframe->resend_level = 0;
@@ -934,8 +938,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
frame_to_local_time(conn->first_packet_timestamp + conn->latency +
(uint32_t)(config.audio_backend_latency_offset *
conn->input_rate), // this will go modulo 2^32
&should_be_time,
conn);
&should_be_time, conn);
conn->first_packet_time_to_play = should_be_time;
@@ -956,8 +959,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
frame_to_local_time(conn->first_packet_timestamp + conn->latency +
(uint32_t)(config.audio_backend_latency_offset *
conn->input_rate), // this should go modulo 2^32
&should_be_time,
conn);
&should_be_time, conn);
conn->first_packet_time_to_play = should_be_time;
@@ -1028,8 +1030,9 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
// this might happen if a big clock adjustment was made at just the wrong
// time.
debug(1, "Run a bit past the exact start time by %" PRId64
" frames with a DAC delay of %ld frames.",
debug(1,
"Run a bit past the exact start time by %" PRId64
" frames with a DAC delay of %ld frames.",
-exact_frame_gap, dac_delay);
if (config.output->flush)
config.output->flush();
@@ -1187,8 +1190,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
(uint32_t)(config.audio_backend_latency_offset * conn->input_rate) -
(uint32_t)(config.audio_backend_buffer_desired_length *
conn->input_rate), // this will go modulo 2^32
&time_to_play,
conn);
&time_to_play, conn);
if (local_time_now >= time_to_play) {
do_wait = 0;
@@ -1491,7 +1493,7 @@ void player_thread_cleanup_handler(void *arg) {
}
void *player_thread_func(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
// pthread_cleanup_push(player_thread_initial_cleanup_handler, arg);
conn->packet_count = 0;
conn->packet_count_since_flush = 0;
@@ -1667,17 +1669,17 @@ void *player_thread_func(void *arg) {
// if ((input_rate!=config.output_rate) || (input_bit_depth!=output_bit_depth)) {
// debug(1,"Define tbuf of length
// %d.",output_bytes_per_frame*(max_frames_per_packet*output_sample_ratio+max_frame_size_change));
conn->tbuf =
malloc(sizeof(int32_t) * 2 * (conn->max_frames_per_packet * conn->output_sample_ratio +
conn->max_frame_size_change));
conn->tbuf = malloc(
sizeof(int32_t) * 2 *
(conn->max_frames_per_packet * conn->output_sample_ratio + conn->max_frame_size_change));
if (conn->tbuf == NULL)
die("Failed to allocate memory for the transition buffer.");
// initialise this, because soxr stuffing might be chosen later
conn->sbuf =
malloc(sizeof(int32_t) * 2 * (conn->max_frames_per_packet * conn->output_sample_ratio +
conn->max_frame_size_change));
conn->sbuf = malloc(
sizeof(int32_t) * 2 *
(conn->max_frames_per_packet * conn->output_sample_ratio + conn->max_frame_size_change));
if (conn->sbuf == NULL)
die("Failed to allocate memory for the sbuf buffer.");
@@ -1965,8 +1967,9 @@ void *player_thread_func(void *arg) {
SUCCESSOR(conn->last_seqno_read); // int32_t from seq_t, i.e. uint16_t, so okay.
if (inframe->sequence_number !=
conn->last_seqno_read) { // seq_t, ei.e. uint16_t and int32_t, so okay
debug(2, "Player: packets out of sequence: expected: %u, got: %u, with ab_read: %u "
"and ab_write: %u.",
debug(2,
"Player: packets out of sequence: expected: %u, got: %u, with ab_read: %u "
"and ab_write: %u.",
conn->last_seqno_read, inframe->sequence_number, conn->ab_read, conn->ab_write);
conn->last_seqno_read = inframe->sequence_number; // reset warning...
}
@@ -2191,7 +2194,7 @@ void *player_thread_func(void *arg) {
#ifdef CONFIG_CONVOLUTION
|| config.convolution
#endif
) {
) {
int32_t *tbuf32 = (int32_t *)conn->tbuf;
float fbuf_l[inbuflength];
float fbuf_r[inbuflength];
@@ -2429,42 +2432,41 @@ 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 */
"%*" 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),
10, moving_average_insertions_plus_deletions * 1000000 /
(352 * conn->output_sample_ratio),
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->remote_frame_rate, 11,
conn->input_frame_rate, 11, conn->frame_rate, 10,
(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);
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), 10,
moving_average_insertions_plus_deletions * 1000000 /
(352 * conn->output_sample_ratio),
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->remote_frame_rate, 11, conn->input_frame_rate, 11, conn->frame_rate, 10,
(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 */
@@ -2479,10 +2481,9 @@ void *player_thread_func(void *arg) {
"%*.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,
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->remote_frame_rate, 11, conn->input_frame_rate, 10,
(conn->local_to_remote_time_gradient - 1.0) * 1000000, 6,
@@ -2501,10 +2502,9 @@ void *player_thread_func(void *arg) {
"%*.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,
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->remote_frame_rate, 11,
conn->input_frame_rate, 10,
(conn->local_to_remote_time_gradient - 1.0) * 1000000, 6,
@@ -2800,7 +2800,8 @@ int player_play(rtsp_conn_info *conn) {
if (config.buffer_start_fill > BUFFER_FRAMES)
die("specified buffer starting fill %d > buffer size %d", config.buffer_start_fill,
BUFFER_FRAMES);
activity_monitor_signify_activity(1); // active, and should be before play's command hook, command_start()
activity_monitor_signify_activity(
1); // active, and should be before play's command hook, command_start()
command_start();
pthread_t *pt = malloc(sizeof(pthread_t));
if (pt == NULL)
+10 -7
View File
@@ -137,8 +137,9 @@ void *rtp_audio_receiver(void *arg) {
stat_mean += stat_delta / stat_n;
stat_M2 += stat_delta * (time_interval_us - stat_mean);
if (stat_n % 2500 == 0) {
debug(2, "Packet reception interval stats: mean, standard deviation and max for the last "
"2,500 packets in microseconds: %10.1f, %10.1f, %10.1f.",
debug(2,
"Packet reception interval stats: mean, standard deviation and max for the last "
"2,500 packets in microseconds: %10.1f, %10.1f, %10.1f.",
stat_mean, sqrtf(stat_M2 / (stat_n - 1)), longest_packet_time_interval_us);
stat_n = 0;
stat_mean = 0.0;
@@ -368,9 +369,10 @@ void *rtp_control_receiver(void *arg) {
if (la != conn->latency) {
conn->latency = la;
debug(3, "New latency detected: %" PRIu32 ", sync latency: %" PRIu32
", minimum latency: %" PRIu32 ", maximum "
"latency: %" PRIu32 ", fixed offset: %" PRIu32 ".",
debug(3,
"New latency detected: %" PRIu32 ", sync latency: %" PRIu32
", minimum latency: %" PRIu32 ", maximum "
"latency: %" PRIu32 ", fixed offset: %" PRIu32 ".",
la, sync_rtp_timestamp - rtp_timestamp_less_latency, conn->minimum_latency,
conn->maximum_latency, config.fixedLatencyOffset);
}
@@ -1226,8 +1228,9 @@ void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn) {
(struct sockaddr *)&conn->rtp_client_control_socket, msgsize) == -1) {
char em[1024];
strerror_r(errno, em, sizeof(em));
debug(1, "Error %d using sendto to an audio socket: \"%s\". Backing off for 1/16th of a "
"second.",
debug(1,
"Error %d using sendto to an audio socket: \"%s\". Backing off for 1/16th of a "
"second.",
errno, em);
conn->rtp_time_of_last_resend_request_error_fp = time_of_sending_fp;
} else {
+29 -21
View File
@@ -288,15 +288,16 @@ void *player_watchdog_thread_code(void *arg) {
if (time_since_last_bark >= ct) {
conn->watchdog_barks++;
if (conn->watchdog_barks == 1) {
debug(1, "Connection %d: As Yeats almost said, \"Too long a silence / can make a stone "
"of the heart\".",
debug(1,
"Connection %d: As Yeats almost said, \"Too long a silence / can make a stone "
"of the heart\".",
conn->connection_number);
conn->stop = 1;
pthread_cancel(conn->thread);
} else if (conn->watchdog_barks == 3) {
if ((config.cmd_unfixable) && (conn->unfixable_error_reported == 0)) {
conn->unfixable_error_reported = 1;
command_execute(config.cmd_unfixable, "unable_to_cancel_play_session",1);
command_execute(config.cmd_unfixable, "unable_to_cancel_play_session", 1);
} else {
warn("an unrecoverable error, \"unable_to_cancel_play_session\", has been detected.",
conn->connection_number);
@@ -404,17 +405,17 @@ static char *nextline(char *in, int inbuf) {
}
void msg_retain(rtsp_message *msg) {
int rc = pthread_mutex_lock(&reference_counter_lock);
if (rc)
debug(1, "Error %d locking reference counter lock");
if (msg > (rtsp_message *) 0x00010000) {
int rc = pthread_mutex_lock(&reference_counter_lock);
if (rc)
debug(1, "Error %d locking reference counter lock");
if (msg > (rtsp_message *)0x00010000) {
msg->referenceCount++;
// debug(1,"msg_retain -- item %d reference count %d.", msg->index_number, msg->referenceCount);
rc = pthread_mutex_unlock(&reference_counter_lock);
if (rc)
debug(1, "Error %d unlocking reference counter lock");
} else {
debug(1, "invalid rtsp_message pointer 0x%x passed to retain", (uintptr_t) msg);
debug(1, "invalid rtsp_message pointer 0x%x passed to retain", (uintptr_t)msg);
}
}
@@ -499,13 +500,18 @@ void msg_free(rtsp_message **msgh) {
uintptr_t index = (msg->index_number) & 0xFFFF;
if (index == 0)
index = 0x10000; // ensure it doesn't fold to zero.
*msgh = (rtsp_message *)(index); // put a version of the index number of the freed message in here
*msgh =
(rtsp_message *)(index); // put a version of the index number of the freed message in here
free(msg);
} else {
// debug(1,"msg_free item %d -- decrement reference to %d.",msg->index_number,msg->referenceCount);
// debug(1,"msg_free item %d -- decrement reference to
// %d.",msg->index_number,msg->referenceCount);
}
} else if (*msgh != NULL) {
debug(1, "msg_free: error attempting to free an allocated but already-freed rtsp_message, number %d.",(uintptr_t)*msgh);
debug(1,
"msg_free: error attempting to free an allocated but already-freed rtsp_message, number "
"%d.",
(uintptr_t)*msgh);
}
debug_mutex_unlock(&reference_counter_lock, 0);
}
@@ -831,9 +837,10 @@ void handle_options(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *
rtsp_message *resp) {
debug(3, "Connection %d: OPTIONS", conn->connection_number);
resp->respcode = 200;
msg_add_header(resp, "Public", "ANNOUNCE, SETUP, RECORD, "
"PAUSE, FLUSH, TEARDOWN, "
"OPTIONS, GET_PARAMETER, SET_PARAMETER");
msg_add_header(resp, "Public",
"ANNOUNCE, SETUP, RECORD, "
"PAUSE, FLUSH, TEARDOWN, "
"OPTIONS, GET_PARAMETER, SET_PARAMETER");
}
void handle_teardown(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *req,
@@ -1564,7 +1571,7 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m
char *ct = msg_get_header(req, "Content-Type");
if (ct) {
// debug(2, "SET_PARAMETER Content-Type:\"%s\".", ct);
// debug(2, "SET_PARAMETER Content-Type:\"%s\".", ct);
#ifdef CONFIG_METADATA
// It seems that the rtptime of the message is used as a kind of an ID that
@@ -2009,7 +2016,6 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
uint8_t digest_urp[16], digest_mu[16], digest_total[16];
#ifdef CONFIG_OPENSSL
MD5_CTX ctx;
@@ -2244,8 +2250,9 @@ static void *rtsp_conversation_thread_func(void *pconn) {
if (strcmp(req->method, "OPTIONS") !=
0) // the options message is very common, so don't log it until level 3
debug_level = 2;
debug(debug_level, "Connection %d: Received an RTSP Packet of type \"%s\":",
conn->connection_number, req->method),
debug(debug_level,
"Connection %d: Received an RTSP Packet of type \"%s\":", conn->connection_number,
req->method),
debug_print_msg_headers(debug_level, req);
apple_challenge(conn->fd, req, resp);
@@ -2304,8 +2311,9 @@ static void *rtsp_conversation_thread_func(void *pconn) {
if (conn->stop == 0) {
int err = msg_write_response(conn->fd, resp);
if (err) {
debug(1, "Connection %d: Unable to write an RTSP message response. Terminating the "
"connection.",
debug(1,
"Connection %d: Unable to write an RTSP message response. Terminating the "
"connection.",
conn->connection_number);
struct linger so_linger;
so_linger.l_onoff = 1; // "true"
@@ -2602,7 +2610,7 @@ void rtsp_listen_loop(void) {
char errorstring[1024];
strerror_r(ret, (char *)errorstring, sizeof(errorstring));
die("Connection %d: cannot create an RTSP conversation thread. Error %d: \"%s\".",
conn->connection_number, ret, (char *)errorstring);
conn->connection_number, ret, (char *)errorstring);
}
debug(3, "Successfully created RTSP receiver thread %d.", conn->connection_number);
conn->running = 1; // this must happen before the thread is tracked
+14 -11
View File
@@ -59,11 +59,11 @@
#include <glib.h>
#endif
#include "activity_monitor.h"
#include "common.h"
#include "mdns.h"
#include "rtp.h"
#include "rtsp.h"
#include "activity_monitor.h"
#if defined(CONFIG_DACP_CLIENT)
#include "dacp.h"
@@ -723,24 +723,26 @@ int parse_options(int argc, char **argv) {
config.cmd_stop = (char *)str;
}
if (config_lookup_string(config.cfg, "sessioncontrol.run_this_before_entering_active_mode", &str)) {
if (config_lookup_string(config.cfg, "sessioncontrol.run_this_before_entering_active_mode",
&str)) {
config.cmd_active_start = (char *)str;
}
if (config_lookup_string(config.cfg, "sessioncontrol.run_this_after_exiting_active_mode", &str)) {
if (config_lookup_string(config.cfg, "sessioncontrol.run_this_after_exiting_active_mode",
&str)) {
config.cmd_active_stop = (char *)str;
}
if (config_lookup_float(config.cfg, "sessioncontrol.active_mode_timeout", &dvalue)) {
if (dvalue < 0.0)
warn("Invalid value \"%f\" for sessioncontrol.active_mode_timeout. It must be positive. The default of %f will be used instead.",
dvalue, config.active_mode_timeout);
warn("Invalid value \"%f\" for sessioncontrol.active_mode_timeout. It must be positive. "
"The default of %f will be used instead.",
dvalue, config.active_mode_timeout);
else
config.active_mode_timeout = dvalue;
}
if (config_lookup_string(config.cfg,
if (config_lookup_string(config.cfg,
"sessioncontrol.run_this_if_an_unfixable_error_is_detected", &str)) {
config.cmd_unfixable = (char *)str;
}
@@ -1181,7 +1183,7 @@ void main_cleanup_handler(__attribute__((unused)) void *arg) {
#endif
activity_monitor_stop(0);
if (config.output->deinit) {
debug(1, "Deinitialise the audio backend.");
config.output->deinit();
@@ -1519,8 +1521,9 @@ int main(int argc, char **argv) {
/* Print out options */
debug(1, "log verbosity is %d.", debuglev);
debug(1, "disable resend requests is %s.", config.disable_resend_requests ? "on" : "off");
debug(1, "diagnostic_drop_packet_fraction is %f. A value of 0.0 means no packets will be dropped "
"deliberately.",
debug(1,
"diagnostic_drop_packet_fraction is %f. A value of 0.0 means no packets will be dropped "
"deliberately.",
config.diagnostic_drop_packet_fraction);
debug(1, "statistics_requester status is %d.", config.statistics_requested);
debug(1, "daemon status is %d.", config.daemonise);
@@ -1599,7 +1602,7 @@ int main(int argc, char **argv) {
uint8_t ap_md5[16];
#ifdef CONFIG_OPENSSL
// can't imagine this is necessary, but here it is anyway
// can't imagine this is necessary, but here it is anyway
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable
MD5_CTX ctx;
+2 -1
View File
@@ -1713,7 +1713,8 @@ void mdnsd_stop(struct mdnsd *s) {
assert(s != NULL);
struct timeval tv = {
.tv_sec = 0, .tv_usec = 500 * 1000,
.tv_sec = 0,
.tv_usec = 500 * 1000,
};
s->stop_flag = 1;