find . \( -name \*.cpp -or -name \*.h -or -name \*.c \) -exec clang-format -i -style='{BasedOnStyle: llvm, IndentWidth: 2, ColumnLimit: 100}' '{}' \;

This commit is contained in:
Mike Brady
2019-06-19 19:06:54 +01:00
parent 7fc977d8d3
commit c8b0be30b4
19 changed files with 575 additions and 570 deletions
+10 -13
View File
@@ -46,7 +46,6 @@
#include "dbus-service.h"
#endif
enum am_state state;
enum ps_state { ps_inactive, ps_active } player_state;
@@ -73,10 +72,10 @@ void going_active(int block) {
if (config.disable_standby_mode == disable_standby_auto) {
#ifdef CONFIG_DBUS_INTERFACE
if (dbus_service_is_running())
shairport_sync_set_disable_standby(SHAIRPORT_SYNC(shairportSyncSkeleton), TRUE);
else
config.keep_dac_busy = 1;
if (dbus_service_is_running())
shairport_sync_set_disable_standby(SHAIRPORT_SYNC(shairportSyncSkeleton), TRUE);
else
config.keep_dac_busy = 1;
#else
config.keep_dac_busy = 1;
#endif
@@ -100,12 +99,12 @@ void going_inactive(int block) {
if (config.disable_standby_mode == disable_standby_auto) {
#ifdef CONFIG_DBUS_INTERFACE
if (dbus_service_is_running())
shairport_sync_set_disable_standby(SHAIRPORT_SYNC(shairportSyncSkeleton), FALSE);
else
config.keep_dac_busy = 0;
if (dbus_service_is_running())
shairport_sync_set_disable_standby(SHAIRPORT_SYNC(shairportSyncSkeleton), FALSE);
else
config.keep_dac_busy = 0;
#else
config.keep_dac_busy = 0;
config.keep_dac_busy = 0;
#endif
}
}
@@ -255,9 +254,7 @@ void *activity_monitor_thread_code(void *arg) {
pthread_exit(NULL);
}
enum am_state activity_status() {
return (state);
}
enum am_state activity_status() { return (state); }
void activity_monitor_start() {
// debug(1,"activity_monitor_start");
+1 -1
View File
@@ -5,4 +5,4 @@ enum am_state { am_inactive, am_active, am_timing_out };
void activity_monitor_start();
void activity_monitor_stop();
void activity_monitor_signify_activity(int active); // 0 means inactive, non-zero means active
enum am_state activity_status(); // true if non inactive; false if inactive
enum am_state activity_status(); // true if non inactive; false if inactive
+1 -1
View File
@@ -116,7 +116,7 @@ void audio_ls_outputs(void) {
printf("Settings and options for the audio backend \"%s\":\n", (*out)->name);
(*out)->help();
} else {
printf("There are no settings or options for the audio backend \"%s\".\n", (*out)->name);
printf("There are no settings or options for the audio backend \"%s\".\n", (*out)->name);
}
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ typedef struct {
int (*init)(int argc, char **argv);
// at end of program
void (*deinit)(void);
int (*prepare)(void); // looks and sets stuff in the config data structure
void (*start)(int sample_rate, int sample_format);
+289 -271
View File
@@ -37,9 +37,9 @@
#include "config.h"
#include "common.h"
#include "activity_monitor.h"
#include "audio.h"
#include "common.h"
enum alsa_backend_mode {
abm_disconnected,
@@ -48,8 +48,8 @@ enum alsa_backend_mode {
} alsa_backend_state; // under the control of alsa_mutex
typedef struct {
snd_pcm_format_t alsa_code;
int frame_size;
snd_pcm_format_t alsa_code;
int frame_size;
} format_record;
static void help(void);
@@ -72,8 +72,9 @@ static void parameters(audio_parameters *info);
int mute(int do_mute); // returns true if it actually is allowed to use the mute
static double set_volume;
static int output_method_signalled = 0; // for reporting whether it's using mmap or not
int delay_type_notified = -1; // for controlling the reporting of whether the output device can do precison delays (e.g. alsa->pulsaudio virtual devices can't)
int use_monotonic_clock = 0; // this value will be set when the hardware is initialised
int delay_type_notified = -1; // for controlling the reporting of whether the output device can do
// precison delays (e.g. alsa->pulsaudio virtual devices can't)
int use_monotonic_clock = 0; // this value will be set when the hardware is initialised
audio_output audio_alsa = {
.name = "alsa",
@@ -122,8 +123,9 @@ int frame_size; // in bytes for interleaved stereo
int alsa_device_initialised; // boolean to ensure the initialisation is only
// done once
enum yndk_type precision_delay_available_status = YNDK_DONT_KNOW; // initially, we don't know if the device can do precision delay
enum yndk_type precision_delay_available_status =
YNDK_DONT_KNOW; // initially, we don't know if the device can do precision delay
snd_pcm_t *alsa_handle = NULL;
static snd_pcm_hw_params_t *alsa_params = NULL;
static snd_pcm_sw_params_t *alsa_swparams = NULL;
@@ -155,15 +157,17 @@ int volume_based_mute_is_active =
0; // set when muting is being done by a setting the volume to a magic value
// use this to allow the use of snd_pcm_writei or snd_pcm_mmap_writei
snd_pcm_sframes_t (*alsa_pcm_write)(snd_pcm_t *, const void *,
snd_pcm_uframes_t) = snd_pcm_writei;
snd_pcm_sframes_t (*alsa_pcm_write)(snd_pcm_t *, const void *, snd_pcm_uframes_t) = snd_pcm_writei;
int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
enum yndk_type *using_update_timestamps);
int standard_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
enum yndk_type *using_update_timestamps);
int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum yndk_type *using_update_timestamps);
int standard_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum yndk_type *using_update_timestamps);
// use this to allow the use of standard or precision delay calculations, with standard the, uh, standard.
int (*delay_and_status)(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum yndk_type *using_update_timestamps) = standard_delay_and_status;
// use this to allow the use of standard or precision delay calculations, with standard the, uh,
// standard.
int (*delay_and_status)(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
enum yndk_type *using_update_timestamps) = standard_delay_and_status;
// this will return true if the DAC can return precision delay information and false if not
// if it is not yet known, it will test the output device to find out
@@ -175,19 +179,21 @@ int (*delay_and_status)(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum y
int precision_delay_available() {
if (precision_delay_available_status == YNDK_DONT_KNOW) {
// this is very crude -- if the device is a hardware device, then it's assumed the delay is precise
// this is very crude -- if the device is a hardware device, then it's assumed the delay is
// precise
const char *output_device_name = snd_pcm_name(alsa_handle);
int is_a_real_hardware_device = (strstr(output_device_name,"hw:") == output_device_name);
int is_a_real_hardware_device = (strstr(output_device_name, "hw:") == output_device_name);
// The criteria as to whether precision delay is available
// is whether the device driver returns non-zero update timestamps
// If it does, and the device is a hardware device (i.e. its name begins with "hw:"),
// it is considered that precision delay is available. Otherwise, it's considered to be unavailable.
// it is considered that precision delay is available. Otherwise, it's considered to be
// unavailable.
// To test, we play a silence buffer (fairly large to avoid underflow)
// and then we check the delay return. It will tell us if it
// and then we check the delay return. It will tell us if it
// was able to use the (non-zero) update timestamps
int frames_of_silence = 4410;
size_t size_of_silence_buffer = frames_of_silence * frame_size;
void *silence = malloc(size_of_silence_buffer);
@@ -213,20 +219,23 @@ int precision_delay_available() {
// now we can get the delay, and we'll note if it uses update timestamps
enum yndk_type uses_update_timestamps;
snd_pcm_state_t state;
snd_pcm_sframes_t delay;
snd_pcm_sframes_t delay;
int ret = precision_delay_and_status(&state, &delay, &uses_update_timestamps);
// debug(3,"alsa: precision_delay_available asking for delay and status with a return status of %d, a delay of %ld and a uses_update_timestamps of %d.", ret, delay, uses_update_timestamps);
// debug(3,"alsa: precision_delay_available asking for delay and status with a return status
// of %d, a delay of %ld and a uses_update_timestamps of %d.", ret, delay,
// uses_update_timestamps);
if (ret == 0) {
if ((uses_update_timestamps == YNDK_YES) && (is_a_real_hardware_device)) {
precision_delay_available_status = YNDK_YES;
debug(2,"alsa: precision delay timing is available.");
debug(2, "alsa: precision delay timing is available.");
} else {
if ((uses_update_timestamps == YNDK_YES) && (!is_a_real_hardware_device)) {
debug(2,"alsa: precision delay timing is not available because it's not definitely a hardware device.");
debug(2, "alsa: precision delay timing is not available because it's not definitely a "
"hardware device.");
} else {
debug(2,"alsa: precision delay timing is not available.");
}
precision_delay_available_status = YNDK_NO;
debug(2, "alsa: precision delay timing is not available.");
}
precision_delay_available_status = YNDK_NO;
}
}
}
@@ -234,7 +243,6 @@ int precision_delay_available() {
return (precision_delay_available_status == YNDK_YES);
}
// static int play_number;
// static int64_t accumulated_delay, accumulated_da_delay;
int alsa_characteristics_already_listed = 0;
@@ -259,7 +267,9 @@ static void help(void) {
" -c mixer-control set the mixer control name, default is to use no mixer.\n"
" -m mixer-device set the mixer device, default is the output device.\n"
" -i mixer-index set the mixer index, default is 0.\n");
int r = system("if [ -d /proc/asound ] ; then echo \" hardware output devices:\" ; ls -al /proc/asound/ 2>/dev/null | grep '\\->' | tr -s ' ' | cut -d ' ' -f 9 | while read line; do echo \" \\\"hw:$line\\\"\" ; done ; fi");
int r = system("if [ -d /proc/asound ] ; then echo \" hardware output devices:\" ; ls -al "
"/proc/asound/ 2>/dev/null | grep '\\->' | tr -s ' ' | cut -d ' ' -f 9 | while "
"read line; do echo \" \\\"hw:$line\\\"\" ; done ; fi");
if (r != 0)
debug(2, "error %d executing a script to list alsa hardware device names", r);
}
@@ -343,66 +353,51 @@ void actual_close_alsa_device() {
}
}
// This array is a sequence of the output rates to be tried if automatic speed selection is requested.
// This array is a sequence of the output rates to be tried if automatic speed selection is
// requested.
// There is no benefit to upconverting the frame rate, other than for compatibility.
// The lowest rate that the DAC is capable of is chosen.
unsigned int auto_speed_output_rates[] = {
44100,
88200,
176400,
352800,
44100, 88200, 176400, 352800,
};
// This array is of all the formats known to Shairport Sync, in order of the SPS_FORMAT definitions, with their equivalent alsa codes and their frame sizes.
// If just one format is requested, then its entry is searched for in the array and checked on the device
// This array is of all the formats known to Shairport Sync, in order of the SPS_FORMAT definitions,
// with their equivalent alsa codes and their frame sizes.
// If just one format is requested, then its entry is searched for in the array and checked on the
// device
// If auto format is requested, then each entry in turn is tried until a working format is found.
// So, it should be in the search order.
format_record fr[] = {
{SND_PCM_FORMAT_UNKNOWN,0}, // unknown
{SND_PCM_FORMAT_S8,2},
{SND_PCM_FORMAT_U8,2},
{SND_PCM_FORMAT_S16,4},
{SND_PCM_FORMAT_S16_LE,4},
{SND_PCM_FORMAT_S16_BE,4},
{SND_PCM_FORMAT_S24,4},
{SND_PCM_FORMAT_S24_LE,8},
{SND_PCM_FORMAT_S24_BE,8},
{SND_PCM_FORMAT_S24_3LE,6},
{SND_PCM_FORMAT_S24_3BE,6},
{SND_PCM_FORMAT_S32,8},
{SND_PCM_FORMAT_S32_LE,8},
{SND_PCM_FORMAT_S32_BE,8},
{SND_PCM_FORMAT_UNKNOWN,0}, // auto
{SND_PCM_FORMAT_UNKNOWN,0}, // illegal
};
// This array is the sequence of formats to be tried if automatic selection of the format is requested.
// Ideally, audio should pass through Shairport Sync unaltered, apart from occasional interpolation.
// If the user chooses a hardware mixer, then audio could go straight through, unaltered, as signed 16 bit stereo.
// However, the user might, at any point, select an option that requires modification, such as stereo to mono mixing,
// additional volume attenuation, convolution, and so on. For this reason,
// we look for the greatest depth the DAC is capable of, since upconverting it is completely lossless.
// If audio processing is required, then the dither that must be added will
// be added at the lowest possible level.
// Hence, selecting the greatest bit depth is always either beneficial or neutral.
enum sps_format_t auto_format_check_sequence[] = {
SPS_FORMAT_S32,
SPS_FORMAT_S32_LE,
SPS_FORMAT_S32_BE,
SPS_FORMAT_S24,
SPS_FORMAT_S24_LE,
SPS_FORMAT_S24_BE,
SPS_FORMAT_S24_3LE,
SPS_FORMAT_S24_3BE,
SPS_FORMAT_S16,
SPS_FORMAT_S16_LE,
SPS_FORMAT_S16_BE,
SPS_FORMAT_S8,
SPS_FORMAT_U8,
};
format_record fr[] = {
{SND_PCM_FORMAT_UNKNOWN, 0}, // unknown
{SND_PCM_FORMAT_S8, 2}, {SND_PCM_FORMAT_U8, 2}, {SND_PCM_FORMAT_S16, 4},
{SND_PCM_FORMAT_S16_LE, 4}, {SND_PCM_FORMAT_S16_BE, 4}, {SND_PCM_FORMAT_S24, 4},
{SND_PCM_FORMAT_S24_LE, 8}, {SND_PCM_FORMAT_S24_BE, 8}, {SND_PCM_FORMAT_S24_3LE, 6},
{SND_PCM_FORMAT_S24_3BE, 6}, {SND_PCM_FORMAT_S32, 8}, {SND_PCM_FORMAT_S32_LE, 8},
{SND_PCM_FORMAT_S32_BE, 8}, {SND_PCM_FORMAT_UNKNOWN, 0}, // auto
{SND_PCM_FORMAT_UNKNOWN, 0}, // illegal
};
// This array is the sequence of formats to be tried if automatic selection of the format is
// requested.
// Ideally, audio should pass through Shairport Sync unaltered, apart from occasional interpolation.
// If the user chooses a hardware mixer, then audio could go straight through, unaltered, as signed
// 16 bit stereo.
// However, the user might, at any point, select an option that requires modification, such as
// stereo to mono mixing,
// additional volume attenuation, convolution, and so on. For this reason,
// we look for the greatest depth the DAC is capable of, since upconverting it is completely
// lossless.
// If audio processing is required, then the dither that must be added will
// be added at the lowest possible level.
// Hence, selecting the greatest bit depth is always either beneficial or neutral.
enum sps_format_t auto_format_check_sequence[] = {
SPS_FORMAT_S32, SPS_FORMAT_S32_LE, SPS_FORMAT_S32_BE, SPS_FORMAT_S24, SPS_FORMAT_S24_LE,
SPS_FORMAT_S24_BE, SPS_FORMAT_S24_3LE, SPS_FORMAT_S24_3BE, SPS_FORMAT_S16, SPS_FORMAT_S16_LE,
SPS_FORMAT_S16_BE, SPS_FORMAT_S8, SPS_FORMAT_U8,
};
// assuming pthread cancellation is disabled
// if do_auto_setting is true and auto format or auto speed has been requested,
@@ -420,7 +415,8 @@ int actual_open_alsa_device(int do_auto_setup) {
*/
int ret, dir = 0;
unsigned int actual_sample_rate; // this will be given the rate requested and will be given the actual rate
unsigned int
actual_sample_rate; // this will be given the rate requested and will be given the actual rate
// snd_pcm_uframes_t frames = 441 * 10;
snd_pcm_uframes_t actual_buffer_length;
snd_pcm_access_t access;
@@ -444,7 +440,8 @@ int actual_open_alsa_device(int do_auto_setup) {
} else {
char errorstring[1024];
strerror_r(-ret, (char *)errorstring, sizeof(errorstring));
warn("alsa: error %d (\"%s\") opening alsa device \"%s\".", ret, (char *)errorstring, alsa_out_dev);
warn("alsa: error %d (\"%s\") opening alsa device \"%s\".", ret, (char *)errorstring,
alsa_out_dev);
}
return ret;
}
@@ -455,8 +452,8 @@ int actual_open_alsa_device(int do_auto_setup) {
ret = snd_pcm_hw_params_any(alsa_handle, alsa_params);
if (ret < 0) {
die("audio_alsa: Broken configuration for device \"%s\": no configurations "
"available",
alsa_out_dev);
"available",
alsa_out_dev);
return ret;
}
@@ -484,7 +481,6 @@ int actual_open_alsa_device(int do_auto_setup) {
snd_strerror(ret));
return ret;
}
ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
if (ret < 0) {
@@ -494,90 +490,92 @@ int actual_open_alsa_device(int do_auto_setup) {
}
snd_pcm_format_t sf;
if ((do_auto_setup == 0) || (config.output_format_auto_requested == 0)) { // no auto format
if ((config.output_format > SPS_FORMAT_UNKNOWN) && (config.output_format < SPS_FORMAT_AUTO)) {
sf = fr[config.output_format].alsa_code;
frame_size = fr[config.output_format].frame_size;
} else {
warn("alsa: unexpected output format %d. Set to S16_LE.",config.output_format);
config.output_format = SPS_FORMAT_S16_LE;
sf = fr[config.output_format].alsa_code;
frame_size = fr[config.output_format].frame_size;
}
ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
if (ret < 0) {
warn("audio_alsa: Alsa sample format %d not available for device \"%s\": %s", sf,
alsa_out_dev, snd_strerror(ret));
return ret;
}
if ((config.output_format > SPS_FORMAT_UNKNOWN) && (config.output_format < SPS_FORMAT_AUTO)) {
sf = fr[config.output_format].alsa_code;
frame_size = fr[config.output_format].frame_size;
} else {
warn("alsa: unexpected output format %d. Set to S16_LE.", config.output_format);
config.output_format = SPS_FORMAT_S16_LE;
sf = fr[config.output_format].alsa_code;
frame_size = fr[config.output_format].frame_size;
}
ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
if (ret < 0) {
warn("audio_alsa: Alsa sample format %d not available for device \"%s\": %s", sf,
alsa_out_dev, snd_strerror(ret));
return ret;
}
} else { // auto format
int number_of_formats_to_try;
enum sps_format_t *formats;
formats = auto_format_check_sequence;
number_of_formats_to_try = sizeof(auto_format_check_sequence)/sizeof(sps_format_t);
int i = 0;
int format_found = 0;
enum sps_format_t trial_format = SPS_FORMAT_UNKNOWN;
while ((i < number_of_formats_to_try) && (format_found == 0)) {
trial_format = formats[i];
sf = fr[trial_format].alsa_code;
frame_size = fr[trial_format].frame_size;
ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
if (ret == 0)
format_found = 1;
else
i++;
}
if (ret == 0) {
config.output_format = trial_format;
debug(1,"alsa: output format chosen is \"%s\".",sps_format_description_string(config.output_format));
} else {
warn("audio_alsa: Could not automatically set the output format for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
return ret;
}
int number_of_formats_to_try;
enum sps_format_t *formats;
formats = auto_format_check_sequence;
number_of_formats_to_try = sizeof(auto_format_check_sequence) / sizeof(sps_format_t);
int i = 0;
int format_found = 0;
enum sps_format_t trial_format = SPS_FORMAT_UNKNOWN;
while ((i < number_of_formats_to_try) && (format_found == 0)) {
trial_format = formats[i];
sf = fr[trial_format].alsa_code;
frame_size = fr[trial_format].frame_size;
ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
if (ret == 0)
format_found = 1;
else
i++;
}
if (ret == 0) {
config.output_format = trial_format;
debug(1, "alsa: output format chosen is \"%s\".",
sps_format_description_string(config.output_format));
} else {
warn("audio_alsa: Could not automatically set the output format for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
return ret;
}
}
if ((do_auto_setup == 0) || (config.output_rate_auto_requested == 0)) { // no auto format
actual_sample_rate = config.output_rate; // this is the requested rate -- it'll be changed to the actual rate
ret = snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, &actual_sample_rate, &dir);
if (ret < 0) {
warn("audio_alsa: Rate %iHz not available for playback: %s", config.output_rate,
snd_strerror(ret));
return ret;
}
} else {
int number_of_speeds_to_try;
unsigned int *speeds;
speeds = auto_speed_output_rates;
number_of_speeds_to_try = sizeof(auto_speed_output_rates)/sizeof(int);
int i = 0;
int speed_found = 0;
while ((i < number_of_speeds_to_try) && (speed_found == 0)) {
actual_sample_rate = speeds[i];
ret = snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, &actual_sample_rate, &dir);
if (ret == 0) {
speed_found = 1;
if (actual_sample_rate != speeds[i])
warn("Speed requested: %d. Speed available: %d.",speeds[i],actual_sample_rate);
} else {
i++;
}
}
if (ret == 0) {
config.output_rate = actual_sample_rate;
debug(1,"alsa: output speed chosen is %d.",config.output_rate);
} else {
warn("audio_alsa: Could not automatically set the output rate for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
return ret;
}
}
actual_sample_rate =
config.output_rate; // this is the requested rate -- it'll be changed to the actual rate
ret = snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, &actual_sample_rate, &dir);
if (ret < 0) {
warn("audio_alsa: Rate %iHz not available for playback: %s", config.output_rate,
snd_strerror(ret));
return ret;
}
} else {
int number_of_speeds_to_try;
unsigned int *speeds;
speeds = auto_speed_output_rates;
number_of_speeds_to_try = sizeof(auto_speed_output_rates) / sizeof(int);
int i = 0;
int speed_found = 0;
while ((i < number_of_speeds_to_try) && (speed_found == 0)) {
actual_sample_rate = speeds[i];
ret = snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, &actual_sample_rate, &dir);
if (ret == 0) {
speed_found = 1;
if (actual_sample_rate != speeds[i])
warn("Speed requested: %d. Speed available: %d.", speeds[i], actual_sample_rate);
} else {
i++;
}
}
if (ret == 0) {
config.output_rate = actual_sample_rate;
debug(1, "alsa: output speed chosen is %d.", config.output_rate);
} else {
warn("audio_alsa: Could not automatically set the output rate for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
return ret;
}
}
if (set_period_size_request != 0) {
debug(1, "Attempting to set the period size to %lu", period_size_requested);
ret = snd_pcm_hw_params_set_period_size_near(alsa_handle, alsa_params, &period_size_requested,
@@ -648,8 +646,8 @@ int actual_open_alsa_device(int do_auto_setup) {
warn("Can't set the D/A converter to sample rate %d.", config.output_rate);
return -EINVAL;
}
use_monotonic_clock = snd_pcm_hw_params_is_monotonic(alsa_params);
use_monotonic_clock = snd_pcm_hw_params_is_monotonic(alsa_params);
ret = snd_pcm_hw_params_get_buffer_size(alsa_params, &actual_buffer_length);
if (ret < 0) {
@@ -680,11 +678,10 @@ int actual_open_alsa_device(int do_auto_setup) {
snd_strerror(ret));
return ret;
}
ret = snd_pcm_prepare(alsa_handle);
if (ret < 0) {
warn("audio_alsa: Unable to prepare the device: \"%s\": %s.", alsa_out_dev,
snd_strerror(ret));
warn("audio_alsa: Unable to prepare the device: \"%s\": %s.", alsa_out_dev, snd_strerror(ret));
return ret;
}
@@ -716,14 +713,13 @@ int actual_open_alsa_device(int do_auto_setup) {
"length (%ld) you have chosen.",
actual_buffer_length, config.audio_backend_buffer_desired_length);
}
if (config.use_precision_timing == YNA_YES)
if (config.use_precision_timing == YNA_YES)
delay_and_status = precision_delay_and_status;
else if (config.use_precision_timing == YNA_AUTO) {
if (precision_delay_available()) {
delay_and_status = precision_delay_and_status;
debug(2,"alsa: precision timing selected for \"auto\" mode");
debug(2, "alsa: precision timing selected for \"auto\" mode");
}
}
@@ -1020,7 +1016,7 @@ static int init(int argc, char **argv) {
stall_monitor_start_time = 0;
stall_monitor_frame_count = 0;
config.disable_standby_mode = disable_standby_off;
config.keep_dac_busy = 0;
config.use_precision_timing = YNA_AUTO;
@@ -1102,12 +1098,11 @@ static int init(int argc, char **argv) {
config.alsa_use_hardware_mute = 0;
}
}
/* Get the output format, using the same names as aplay does*/
if (config_lookup_string(config.cfg, "alsa.output_format", &str)) {
int temp_output_format_auto_requested = config.output_format_auto_requested;
config.output_format_auto_requested = 0; // assume a valid format will be given.
int temp_output_format_auto_requested = config.output_format_auto_requested;
config.output_format_auto_requested = 0; // assume a valid format will be given.
if (strcasecmp(str, "S16") == 0)
config.output_format = SPS_FORMAT_S16;
else if (strcasecmp(str, "S16_LE") == 0)
@@ -1137,48 +1132,54 @@ static int init(int argc, char **argv) {
else if (strcasecmp(str, "auto") == 0)
config.output_format_auto_requested = 1;
else {
config.output_format_auto_requested = temp_output_format_auto_requested; //format was invalid; recall the original setting
config.output_format_auto_requested =
temp_output_format_auto_requested; // format was invalid; recall the original setting
warn("Invalid output format \"%s\". It should be \"auto\", \"U8\", \"S8\", "
"\"S16\", \"S24\", \"S24_LE\", \"S24_BE\", "
"\"S24_3LE\", \"S24_3BE\" or "
"\"S32\", \"S32_LE\", \"S32_BE\". It remains set to \"%s\".", str,
config.output_format_auto_requested == 1 ? "auto" : sps_format_description_string(config.output_format));
"\"S32\", \"S32_LE\", \"S32_BE\". It remains set to \"%s\".",
str, config.output_format_auto_requested == 1 ? "auto" : sps_format_description_string(
config.output_format));
}
}
if (config_lookup_string(config.cfg, "alsa.output_rate", &str)) {
if (strcasecmp(str, "auto") == 0) {
config.output_rate_auto_requested = 1;
} else {
if (config.output_rate_auto_requested == 1)
warn("Invalid output rate \"%s\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to \"auto\". Note: numbers should not be placed in quotes.", str);
else
warn("Invalid output rate \"%s\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to %d. Note: numbers should not be placed in quotes.", str, config.output_rate);
}
}
/* Get the output rate, which must be a multiple of 44,100*/
if (config_lookup_int(config.cfg, "alsa.output_rate", &value)) {
debug(1, "alsa output rate is %d frames per second", value);
switch (value) {
case 44100:
case 88200:
case 176400:
case 352800:
config.output_rate = value;
config.output_rate_auto_requested = 0;
break;
default:
if (config.output_rate_auto_requested == 1)
warn("Invalid output rate \"%d\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to \"auto\".",value);
else
warn("Invalid output rate \"%d\".It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to %d.", value, config.output_rate);
}
}
if (strcasecmp(str, "auto") == 0) {
config.output_rate_auto_requested = 1;
} else {
if (config.output_rate_auto_requested == 1)
warn("Invalid output rate \"%s\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to \"auto\". Note: numbers should not be placed in quotes.",
str);
else
warn("Invalid output rate \"%s\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to %d. Note: numbers should not be placed in quotes.",
str, config.output_rate);
}
}
/* Get the output rate, which must be a multiple of 44,100*/
if (config_lookup_int(config.cfg, "alsa.output_rate", &value)) {
debug(1, "alsa output rate is %d frames per second", value);
switch (value) {
case 44100:
case 88200:
case 176400:
case 352800:
config.output_rate = value;
config.output_rate_auto_requested = 0;
break;
default:
if (config.output_rate_auto_requested == 1)
warn("Invalid output rate \"%d\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to \"auto\".",
value);
else
warn("Invalid output rate \"%d\".It should be \"auto\", 44100, 88200, 176400 or 352800. "
"It remains set to %d.",
value, config.output_rate);
}
}
/* Get the use_mmap_if_available setting. */
if (config_lookup_string(config.cfg, "alsa.use_mmap_if_available", &str)) {
@@ -1232,12 +1233,13 @@ static int init(int argc, char **argv) {
}
}
/* Get the optional disable_standby_mode setting. */
if (config_lookup_string(config.cfg, "alsa.disable_standby_mode", &str)) {
if ((strcasecmp(str, "no") == 0) || (strcasecmp(str, "off") == 0) || (strcasecmp(str, "never") == 0))
if ((strcasecmp(str, "no") == 0) || (strcasecmp(str, "off") == 0) ||
(strcasecmp(str, "never") == 0))
config.disable_standby_mode = disable_standby_off;
else if ((strcasecmp(str, "yes") == 0) || (strcasecmp(str, "on") == 0) || (strcasecmp(str, "always") == 0)) {
else if ((strcasecmp(str, "yes") == 0) || (strcasecmp(str, "on") == 0) ||
(strcasecmp(str, "always") == 0)) {
config.disable_standby_mode = disable_standby_always;
config.keep_dac_busy = 1;
} else if (strcasecmp(str, "auto") == 0)
@@ -1245,15 +1247,17 @@ static int init(int argc, char **argv) {
else {
warn("Invalid disable_standby_mode option choice \"%s\". It should be "
"\"always\", \"auto\" or \"never\". "
"It remains set to \"never\".", str);
"It remains set to \"never\".",
str);
}
}
if (config_lookup_string(config.cfg, "alsa.use_precision_timing", &str)) {
if ((strcasecmp(str, "no") == 0) || (strcasecmp(str, "off") == 0) || (strcasecmp(str, "never") == 0))
if ((strcasecmp(str, "no") == 0) || (strcasecmp(str, "off") == 0) ||
(strcasecmp(str, "never") == 0))
config.use_precision_timing = YNA_NO;
else if ((strcasecmp(str, "yes") == 0) || (strcasecmp(str, "on") == 0) || (strcasecmp(str, "always") == 0)) {
else if ((strcasecmp(str, "yes") == 0) || (strcasecmp(str, "on") == 0) ||
(strcasecmp(str, "always") == 0)) {
config.use_precision_timing = YNA_YES;
config.keep_dac_busy = 1;
} else if (strcasecmp(str, "auto") == 0)
@@ -1261,11 +1265,17 @@ static int init(int argc, char **argv) {
else {
warn("Invalid use_precision_timing option choice \"%s\". It should be "
"\"yes\", \"auto\" or \"no\". "
"It remains set to \"%s\".", config.use_precision_timing == YNA_NO ? "no" : config.use_precision_timing == YNA_AUTO ? "auto" : "yes");
"It remains set to \"%s\".",
config.use_precision_timing == YNA_NO ? "no" : config.use_precision_timing == YNA_AUTO
? "auto"
: "yes");
}
}
debug(1, "alsa: disable_standby_mode is \"%s\".", config.disable_standby_mode == disable_standby_off ? "never" : config.disable_standby_mode == disable_standby_always ? "always" : "auto");
debug(1, "alsa: disable_standby_mode is \"%s\".",
config.disable_standby_mode == disable_standby_off
? "never"
: config.disable_standby_mode == disable_standby_always ? "always" : "auto");
}
optind = 1; // optind=0 is equivalent to optind=1 plus special behaviour
@@ -1362,14 +1372,15 @@ int set_mute_state() {
close_mixer();
}
debug_mutex_unlock(&alsa_mixer_mutex, 3); // release the mutex
pthread_cleanup_pop(0); // release the mutex
pthread_cleanup_pop(0); // release the mutex
pthread_setcancelstate(oldState, NULL);
return response;
}
static void start(__attribute__((unused)) int i_sample_rate, __attribute__((unused)) int i_sample_format) {
static void start(__attribute__((unused)) int i_sample_rate,
__attribute__((unused)) int i_sample_format) {
debug(3, "audio_alsa start called.");
frame_index = 0;
measurement_data_is_valid = 0;
@@ -1381,31 +1392,33 @@ static void start(__attribute__((unused)) int i_sample_rate, __attribute__((unus
}
}
int standard_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum yndk_type *using_update_timestamps) {
int standard_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
enum yndk_type *using_update_timestamps) {
int ret = 0;
if (using_update_timestamps)
*using_update_timestamps = YNDK_NO;
*state = snd_pcm_state(alsa_handle);
if ((*state == SND_PCM_STATE_RUNNING) || (*state == SND_PCM_STATE_DRAINING)) {
ret = snd_pcm_delay(alsa_handle,delay);
ret = snd_pcm_delay(alsa_handle, delay);
} else {
// not running, thus no delay information, thus can't check for frame
// rates
// not running, thus no delay information, thus can't check for frame
// rates
frame_index = 0; // we'll be starting over...
measurement_data_is_valid = 0;
*delay = 0;
*delay = 0;
}
stall_monitor_start_time = 0; // zero if not initialised / not started / zeroed by flush
stall_monitor_frame_count = 0; // set to delay at start of time, incremented by any writes
return ret;
}
int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay, enum yndk_type *using_update_timestamps) {
int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
enum yndk_type *using_update_timestamps) {
snd_pcm_status_t *alsa_snd_pcm_status;
snd_pcm_status_alloca(&alsa_snd_pcm_status);
if (using_update_timestamps)
*using_update_timestamps = YNDK_DONT_KNOW;
@@ -1414,12 +1427,12 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
int ret = snd_pcm_status(alsa_handle, alsa_snd_pcm_status);
if (ret == 0) {
// must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
// must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
#if SND_LIB_MINOR == 0
snd_pcm_status_get_htstamp(alsa_snd_pcm_status, &update_timestamp);
snd_pcm_status_get_htstamp(alsa_snd_pcm_status, &update_timestamp);
#else
snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &update_timestamp);
snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &update_timestamp);
#endif
*state = snd_pcm_status_get_state(alsa_snd_pcm_status);
@@ -1439,41 +1452,41 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
else
*using_update_timestamps = YNDK_YES;
}
// user information
// user information
if (update_timestamp_ns == 0) {
if (delay_type_notified != 1) {
debug(2,"alsa: update timestamps unavailable");
debug(2, "alsa: update timestamps unavailable");
delay_type_notified = 1;
}
} else {
// diagnostic
// diagnostic
if (delay_type_notified != 0) {
debug(2,"alsa: update timestamps available");
debug(2, "alsa: update timestamps available");
delay_type_notified = 0;
}
}
if (update_timestamp_ns == 0) {
ret = snd_pcm_delay (alsa_handle,delay);
ret = snd_pcm_delay(alsa_handle, delay);
} else {
*delay = snd_pcm_status_get_delay(alsa_snd_pcm_status);
/*
// It seems that the alsa library uses CLOCK_REALTIME before 1.0.28, even though
// the check for monotonic returns true. Might have to watch out for this.
#if SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR < 28
clock_gettime(CLOCK_REALTIME, &tn);
#else
clock_gettime(CLOCK_MONOTONIC, &tn);
#endif
*/
/*
// It seems that the alsa library uses CLOCK_REALTIME before 1.0.28, even though
// the check for monotonic returns true. Might have to watch out for this.
#if SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR < 28
clock_gettime(CLOCK_REALTIME, &tn);
#else
clock_gettime(CLOCK_MONOTONIC, &tn);
#endif
*/
if (use_monotonic_clock)
clock_gettime(CLOCK_MONOTONIC, &tn);
else
clock_gettime(CLOCK_REALTIME, &tn);
uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
// see if it's stalled
@@ -1491,8 +1504,8 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
debug(2, "DAC seems to have stalled with time_now: %lx,%lx"
", update_timestamp: %lx,%lx, stall_monitor_start_time %" PRIX64
", stall_monitor_error_threshold %" PRIX64 ".",
tn.tv_sec, tn.tv_nsec, update_timestamp.tv_sec, update_timestamp.tv_nsec, stall_monitor_start_time,
stall_monitor_error_threshold);
tn.tv_sec, tn.tv_nsec, update_timestamp.tv_sec, update_timestamp.tv_nsec,
stall_monitor_start_time, stall_monitor_error_threshold);
ret = sps_extra_code_output_stalled;
}
} else {
@@ -1649,9 +1662,9 @@ int do_play(void *buf, int samples) {
} else {
char errorstring[1024];
strerror_r(-ret, (char *)errorstring, sizeof(errorstring));
debug(1, "alsa: error %d (\"%s\") writing %d samples to alsa device.", ret, (char *)errorstring, samples);
debug(1, "alsa: error %d (\"%s\") writing %d samples to alsa device.", ret,
(char *)errorstring, samples);
}
}
}
} else {
@@ -1684,7 +1697,7 @@ int do_open(int do_auto_setup) {
// set accordingly
// do_mute(0); // complete unmute
}
alsa_backend_state = abm_connected; // only do this if it really opened it.
}
} else {
@@ -1739,11 +1752,11 @@ int play(void *buf, int samples) {
if (alsa_backend_state != abm_playing) {
debug(2, "alsa: play() -- alsa_backend_state => abm_playing");
alsa_backend_state = abm_playing;
// mute_requested_internally = 0; // stop requesting a mute for backend's own
// reasons, which might have been a flush
//debug(2, "play() set_mute_state");
//set_mute_state(); // try to action the request and return a status
// reasons, which might have been a flush
// debug(2, "play() set_mute_state");
// set_mute_state(); // try to action the request and return a status
// do_mute(0); // unmute for backend's reason
}
ret = do_play(buf, samples);
@@ -1755,16 +1768,15 @@ int play(void *buf, int samples) {
}
int prepare(void) {
// this will leave the DAC open / connected.
// this will leave the DAC open / connected.
int ret = 0;
pthread_cleanup_debug_mutex_lock(&alsa_mutex, 50000, 0);
if (alsa_backend_state == abm_disconnected) {
ret = do_open(1); // do auto setup
ret = do_open(1); // do auto setup
if (ret == 0)
debug(2, "alsa: prepare() -- opened output device");
}
debug_mutex_unlock(&alsa_mutex, 0);
@@ -1888,9 +1900,10 @@ void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) {
int error_count = 0;
int error_threshold_exceeded = 0;
int okb = -1;
while (error_threshold_exceeded == 0) { // if too many play errors occur early on, we will turn off the disable stanby mode
while (error_threshold_exceeded ==
0) { // if too many play errors occur early on, we will turn off the disable stanby mode
if (okb != config.keep_dac_busy) {
debug(2,"keep_dac_busy is now \"%s\"",config.keep_dac_busy == 0 ? "no" : "yes");
debug(2, "keep_dac_busy is now \"%s\"", config.keep_dac_busy == 0 ? "no" : "yes");
okb = config.keep_dac_busy;
}
if ((config.keep_dac_busy != 0) && (alsa_device_initialised == 0)) {
@@ -1921,7 +1934,8 @@ void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) {
// to be in the
// abm_connected state in the first place...) then do the silence-filling
// thing, if needed /* only if the output device is capable of precision delay */.
if ((alsa_backend_state != abm_disconnected) && (config.keep_dac_busy != 0) /* && precision_delay_available() */ ) {
if ((alsa_backend_state != abm_disconnected) &&
(config.keep_dac_busy != 0) /* && precision_delay_available() */) {
int reply;
long buffer_size = 0;
snd_pcm_state_t state;
@@ -1976,9 +1990,13 @@ void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) {
error_count++;
char errorstring[1024];
strerror_r(-ret, (char *)errorstring, sizeof(errorstring));
debug(2, "alsa: alsa_buffer_monitor_thread_code error %d (\"%s\") writing %d samples to alsa device -- %d errors in %d trials.", ret, (char *)errorstring, frames_of_silence, error_count, frame_count);
debug(2, "alsa: alsa_buffer_monitor_thread_code error %d (\"%s\") writing %d samples "
"to alsa device -- %d errors in %d trials.",
ret, (char *)errorstring, frames_of_silence, error_count, frame_count);
if ((error_count > 40) && (frame_count < 100)) {
warn("disable_standby_mode has been turned off because too many underruns occurred. Is Shairport Sync outputting to a virtual device or running in a virtual machine?");
warn("disable_standby_mode has been turned off because too many underruns "
"occurred. Is Shairport Sync outputting to a virtual device or running in a "
"virtual machine?");
error_threshold_exceeded = 1;
}
}
-1
View File
@@ -54,7 +54,6 @@ static int play(__attribute__((unused)) void *buf, __attribute__((unused)) int s
static void stop(void) { debug(1, "dummy audio stopped\n"); }
audio_output audio_dummy = {.name = "dummy",
.help = NULL,
.init = &init,
+37 -40
View File
@@ -20,10 +20,10 @@
#include "audio.h"
#include "common.h"
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <jack/jack.h>
@@ -64,7 +64,7 @@ audio_output audio_jack = {.name = "jack",
// So make it exactly the number of incoming audio channels!
#define NPORTS 2
static jack_port_t *port[NPORTS];
static const char* port_name[NPORTS] = { "out_L", "out_R" };
static const char *port_name[NPORTS] = {"out_L", "out_R"};
static jack_client_t *client;
static jack_nframes_t sample_rate;
@@ -76,7 +76,6 @@ static int flush_please = 0;
static jack_latency_range_t latest_latency_range[NPORTS];
static int64_t time_of_latest_transfer;
static inline jack_default_audio_sample_t sample_conv(short sample) {
// It sounds correct, but I don't understand it.
// Zero int needs to be zero float. Check.
@@ -88,9 +87,8 @@ static inline jack_default_audio_sample_t sample_conv(short sample) {
}
static void deinterleave_and_convert(const char *interleaved_input_buffer,
jack_default_audio_sample_t* jack_output_buffer[],
jack_nframes_t offset,
jack_nframes_t nframes) {
jack_default_audio_sample_t *jack_output_buffer[],
jack_nframes_t offset, jack_nframes_t nframes) {
jack_nframes_t f;
// We're dealing with 16bit audio here:
short *ifp = (short *)interleaved_input_buffer;
@@ -111,7 +109,7 @@ static void deinterleave_and_convert(const char *interleaved_input_buffer,
static int process(jack_nframes_t nframes, __attribute__((unused)) void *arg) {
jack_default_audio_sample_t *buffer[NPORTS];
// Expect an array of two elements because of possible ringbuffer wrap-around:
jack_ringbuffer_data_t v[2] = { 0 };
jack_ringbuffer_data_t v[2] = {0};
jack_nframes_t i, thisbuf;
int frames_written = 0;
int frames_required = 0;
@@ -130,7 +128,7 @@ static int process(jack_nframes_t nframes, __attribute__((unused)) void *arg) {
thisbuf = v[i].len / bytes_per_frame;
if (thisbuf > nframes) {
frames_required = nframes;
} else {
} else {
frames_required = thisbuf;
}
deinterleave_and_convert(v[i].buf, buffer, frames_written, frames_required);
@@ -154,13 +152,13 @@ static int process(jack_nframes_t nframes, __attribute__((unused)) void *arg) {
// This is the JACK graph reorder callback. Now we know some JACK connections
// have changed, so we recompute the latency.
static int graph(__attribute__((unused)) void * arg) {
static int graph(__attribute__((unused)) void *arg) {
int latency = 0;
debug(2, "JACK graph reorder callback called.");
for (int i=0; i<NPORTS; i++) {
for (int i = 0; i < NPORTS; i++) {
jack_port_get_latency_range(port[i], JackPlaybackLatency, &latest_latency_range[i]);
debug(2, "JACK latency for port %s\tmin: %d\t max: %d",
port_name[i], latest_latency_range[i].min, latest_latency_range[i].max);
debug(2, "JACK latency for port %s\tmin: %d\t max: %d", port_name[i],
latest_latency_range[i].min, latest_latency_range[i].max);
latency += latest_latency_range[i].max;
}
latency /= NPORTS;
@@ -170,14 +168,10 @@ static int graph(__attribute__((unused)) void * arg) {
}
// This the function JACK will call in case of an error in the library.
static void error(const char *desc) {
warn("JACK error: \"%s\"", desc);
}
static void error(const char *desc) { warn("JACK error: \"%s\"", desc); }
// This is the function JACK will call in case of a non-critical event in the library.
static void info(const char *desc) {
inform("JACK information: \"%s\"", desc);
}
static void info(const char *desc) { inform("JACK information: \"%s\"", desc); }
int jack_init(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) {
int i;
@@ -221,15 +215,16 @@ int jack_init(__attribute__((unused)) int argc, __attribute__((unused)) char **a
sample_rate = jack_get_sample_rate(client);
if (sample_rate != 44100) {
die("The JACK server is running at the wrong sample rate (%d) for Shairport Sync."
" Must be 44100 Hz.", sample_rate);
" Must be 44100 Hz.",
sample_rate);
}
jack_set_process_callback(client, &process, NULL);
jack_set_graph_order_callback(client, &graph, NULL);
jack_set_error_function(&error);
jack_set_info_function(&info);
for (i=0; i < NPORTS; i++) {
port[i] = jack_port_register(client, port_name[i], JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
for (i = 0; i < NPORTS; i++) {
port[i] =
jack_port_register(client, port_name[i], JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
if (jack_activate(client)) {
die("Could not activate %s JACK client.", config.jack_client_name);
@@ -237,15 +232,16 @@ int jack_init(__attribute__((unused)) int argc, __attribute__((unused)) char **a
debug(2, "JACK client %s activated sucessfully.", config.jack_client_name);
}
if (config.jack_autoconnect_pattern != NULL) {
inform("config.jack_autoconnect_pattern is %s. If you see the program die after this,"
"you made a syntax error.", config.jack_autoconnect_pattern);
inform("config.jack_autoconnect_pattern is %s. If you see the program die after this,"
"you made a syntax error.",
config.jack_autoconnect_pattern);
// Sadly, this will throw a segfault if the user provides a syntactically incorrect regex.
// I've reported it to the jack-devel mailing list, they're in a better place to fix it.
const char** port_list = jack_get_ports(client, config.jack_autoconnect_pattern,
const char **port_list = jack_get_ports(client, config.jack_autoconnect_pattern,
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput);
if (port_list != NULL) {
for (i = 0; i < NPORTS ; i++) {
char* full_port_name[NPORTS];
for (i = 0; i < NPORTS; i++) {
char *full_port_name[NPORTS];
full_port_name[i] = malloc(sizeof(char) * jack_port_name_size());
sprintf(full_port_name[i], "%s:%s", config.jack_client_name, port_name[i]);
if (port_list[i] != NULL) {
@@ -254,15 +250,15 @@ int jack_init(__attribute__((unused)) int argc, __attribute__((unused)) char **a
err = jack_connect(client, full_port_name[i], port_list[i]);
switch (err) {
case EEXIST:
inform("The requested connection from %s to %s already exists.",
full_port_name[i], port_list[i]);
inform("The requested connection from %s to %s already exists.", full_port_name[i],
port_list[i]);
break;
case 0:
// success
break;
default:
warn("JACK error no. %d occured while trying to connect %s to %s.",
err, full_port_name[i], port_list[i]);
warn("JACK error no. %d occured while trying to connect %s to %s.", err,
full_port_name[i], port_list[i]);
break;
}
} else {
@@ -272,7 +268,8 @@ int jack_init(__attribute__((unused)) int argc, __attribute__((unused)) char **a
free(full_port_name[i]);
}
while (port_list[i++] != NULL) {
inform("Additional matching port %s found. Check that the connections are what you intended.");
inform(
"Additional matching port %s found. Check that the connections are what you intended.");
}
jack_free(port_list);
}
@@ -316,10 +313,10 @@ int jack_delay(long *the_delay) {
// occupancy after another transfer had occurred, so we could "lose" a full transfer
// (e.g. 1024 frames @ 44,100 fps ~ 23.2 milliseconds)
pthread_mutex_lock(&buffer_mutex);
int64_t time_now = get_absolute_time_in_fp();
int64_t delta = time_now - time_of_latest_transfer;
size_t audio_occupancy_now = jack_ringbuffer_read_space(jackbuf) / bytes_per_frame;
debug(2, "audio_occupancy_now is %d.", audio_occupancy_now);
int64_t time_now = get_absolute_time_in_fp();
int64_t delta = time_now - time_of_latest_transfer;
size_t audio_occupancy_now = jack_ringbuffer_read_space(jackbuf) / bytes_per_frame;
debug(2, "audio_occupancy_now is %d.", audio_occupancy_now);
pthread_mutex_unlock(&buffer_mutex);
int64_t frames_processed_since_latest_latency_check = (delta * 44100) >> 32;
@@ -339,12 +336,12 @@ int play(void *buf, int samples) {
bytes_to_transfer = samples * bytes_per_frame;
// It's ok to lock here since we're not in the realtime callback:
pthread_mutex_lock(&buffer_mutex);
bytes_transferred = jack_ringbuffer_write(jackbuf, buf, bytes_to_transfer);
time_of_latest_transfer = get_absolute_time_in_fp();
bytes_transferred = jack_ringbuffer_write(jackbuf, buf, bytes_to_transfer);
time_of_latest_transfer = get_absolute_time_in_fp();
pthread_mutex_unlock(&buffer_mutex);
if (bytes_transferred < bytes_to_transfer) {
warn("JACK ringbuffer overrun. Only wrote %d of %d bytes.",
bytes_transferred, bytes_to_transfer);
warn("JACK ringbuffer overrun. Only wrote %d of %d bytes.", bytes_transferred,
bytes_to_transfer);
}
return 0;
}
+5 -4
View File
@@ -46,16 +46,17 @@ int warned = 0;
static void start(__attribute__((unused)) int sample_rate,
__attribute__((unused)) int sample_format) {
// this will leave fd as -1 if a reader hasn't been attached to the pipe
// we check that it's not a "real" error though. From the "man 2 open" page:
// "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO open for reading."
// "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
// open for reading."
fd = open(pipename, O_WRONLY | O_NONBLOCK);
if ((fd == -1) && (errno != ENXIO) && (warned == 0)) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
debug(1, "pipe: start -- error %d (\"%s\") opening the pipe named \"%s\".", errno, (char*)errorstring, pipename);
debug(1, "pipe: start -- error %d (\"%s\") opening the pipe named \"%s\".", errno,
(char *)errorstring, pipename);
warn("Error %d opening the pipe named \"%s\".", errno, pipename);
warned = 1;
}
+3 -4
View File
@@ -76,7 +76,8 @@ struct sndio_formats {
static struct sndio_formats formats[] = {{"S8", SPS_FORMAT_S8, 44100, 8, 1, 1, SIO_LE_NATIVE},
{"U8", SPS_FORMAT_U8, 44100, 8, 1, 0, SIO_LE_NATIVE},
{"S16", SPS_FORMAT_S16, 44100, 16, 2, 1, SIO_LE_NATIVE},
{"AUTOMATIC", SPS_FORMAT_S16, 44100, 16, 2, 1, SIO_LE_NATIVE}, // TODO: make this really automatic?
{"AUTOMATIC", SPS_FORMAT_S16, 44100, 16, 2, 1,
SIO_LE_NATIVE}, // TODO: make this really automatic?
{"S24", SPS_FORMAT_S24, 44100, 24, 4, 1, SIO_LE_NATIVE},
{"S24_3LE", SPS_FORMAT_S24_3LE, 44100, 24, 3, 1, 1},
{"S24_3BE", SPS_FORMAT_S24_3BE, 44100, 24, 3, 1, 0},
@@ -176,7 +177,6 @@ static int init(int argc, char **argv) {
written = played = 0;
time_of_last_onmove_cb = 0;
at_least_one_onmove_cb_seen = 0;
for (i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) {
if (formats[i].fmt == config.output_format) {
@@ -187,7 +187,7 @@ static int init(int argc, char **argv) {
break;
}
}
if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par))
die("sndio: failed to set audio parameters");
for (i = 0, found = 0; i < sizeof(formats) / sizeof(formats[0]); i++) {
@@ -200,7 +200,6 @@ static int init(int argc, char **argv) {
}
if (!found)
die("sndio: could not set output device to the required format and rate.");
framesize = par.bps * par.pchan;
config.output_rate = par.rate;
+2 -3
View File
@@ -27,9 +27,8 @@ 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) {
+27 -28
View File
@@ -87,9 +87,11 @@
void set_alsa_out_dev(char *);
#endif
const char * sps_format_description_string_array[] = {"unknown", "S8", "U8" ,"S16", "S16_LE", "S16_BE", "S24", "S24_LE", "S24_BE", "S24_3LE", "S24_3BE", "S32", "S32_LE", "S32_BE", "auto", "invalid" };
const char *sps_format_description_string_array[] = {
"unknown", "S8", "U8", "S16", "S16_LE", "S16_BE", "S24", "S24_LE",
"S24_BE", "S24_3LE", "S24_3BE", "S32", "S32_LE", "S32_BE", "auto", "invalid"};
const char * sps_format_description_string(enum sps_format_t format) {
const char *sps_format_description_string(enum sps_format_t format) {
if ((format >= SPS_FORMAT_UNKNOWN) && (format <= SPS_FORMAT_AUTO))
return sps_format_description_string_array[format];
else
@@ -115,12 +117,10 @@ void do_sps_log(__attribute__((unused)) int prio, const char *t, ...) {
va_start(args, t);
vsnprintf(s, sizeof(s), t, args);
va_end(args);
fprintf(stderr,"%s\n",s);
fprintf(stderr, "%s\n", s);
}
void log_to_stderr() {
sps_log = do_sps_log;
}
void log_to_stderr() { sps_log = do_sps_log; }
shairport_cfg config;
@@ -183,7 +183,7 @@ void die(const char *format, ...) {
else if ((debuglev) && (config.debugger_show_elapsed_time))
sps_log(LOG_ERR, "% 20.9f|*fatal error: %s", tss, s);
else
sps_log(LOG_ERR, "fatal error: %s", s);
sps_log(LOG_ERR, "fatal error: %s", s);
pthread_setcancelstate(oldState, NULL);
abort(); // exit() doesn't always work, by heaven.
}
@@ -436,7 +436,7 @@ char *base64_enc(uint8_t *input, int length) {
b64 = BIO_push(b64, bmem);
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
BIO_write(b64, input, length);
(void) BIO_flush(b64);
(void)BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
char *buf = (char *)malloc(bptr->length);
@@ -468,7 +468,7 @@ uint8_t *base64_dec(char *input, int *outlen) {
BIO_write(bmem, input, inlen);
while (inlen++ & 3)
BIO_write(bmem, "=", 1);
(void) BIO_flush(bmem);
(void)BIO_flush(bmem);
int bufsize = strlen(input) * 3 / 4 + 1;
uint8_t *buf = malloc(bufsize);
@@ -862,17 +862,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
@@ -1000,7 +1000,7 @@ ssize_t non_blocking_write_with_timeout(int fd, const void *buf, size_t count, i
}
ssize_t non_blocking_write(int fd, const void *buf, size_t count) {
return non_blocking_write_with_timeout(fd,buf,count,5000); // default is 5 seconds.
return non_blocking_write_with_timeout(fd, buf, count, 5000); // default is 5 seconds.
}
/* from
@@ -1189,9 +1189,8 @@ 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,
@@ -1293,10 +1292,10 @@ char *get_version_string() {
strcpy(version_string, PACKAGE_VERSION);
#ifdef CONFIG_LIBDAEMON
strcat(version_string, "-libdaemon");
strcat(version_string, "-libdaemon");
#endif
#ifdef CONFIG_MBEDTLS
strcat(version_string, "-mbedTLS");
strcat(version_string, "-mbedTLS");
#endif
#ifdef CONFIG_POLARSSL
strcat(version_string, "-PolarSSL");
@@ -1382,7 +1381,7 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
// I think, for a 32 --> 16 bits, the range of
// random numbers needs to be from -2^16 to 2^16, i.e. from -65536 to 65536 inclusive, not from
// -32768 to +32767
// Actually, what would be generated here is from -65535 to 65535, i.e. one less on the limits.
// See the original paper at
@@ -1549,7 +1548,7 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
break;
default:
result = 0; // stop a compiler warning
die("Unexpected SPS_FORMAT_* with index %d while outputting silence",format);
die("Unexpected SPS_FORMAT_* with index %d while outputting silence", format);
}
p += result;
previous_random_number = r;
+18 -22
View File
@@ -34,18 +34,10 @@ enum dbus_session_type {
#define sps_extra_code_output_state_cannot_make_ready 32769
// yeah/no/auto
enum yna_type {
YNA_AUTO = -1,
YNA_NO = 0,
YNA_YES = 1
} yna_type;
enum yna_type { YNA_AUTO = -1, YNA_NO = 0, YNA_YES = 1 } yna_type;
// yeah/no/dont-care
enum yndk_type {
YNDK_DONT_KNOW = -1,
YNDK_NO = 0,
YNDK_YES = 1
} yndk_type;
enum yndk_type { YNDK_DONT_KNOW = -1, YNDK_NO = 0, YNDK_YES = 1 } yndk_type;
enum endian_type {
SS_LITTLE_ENDIAN = 0,
@@ -56,7 +48,7 @@ enum endian_type {
enum stuffing_type {
ST_basic = 0, // straight deletion or insertion of a frame in a 352-frame packet
ST_soxr, // use libsoxr to make a 352 frame packet one frame longer or shorter
ST_auto, // use soxr if compiled for it and if the soxr_index is low enough
ST_auto, // use soxr if compiled for it and if the soxr_index is low enough
} s_type;
enum playback_mode_type {
@@ -95,7 +87,7 @@ enum sps_format_t {
SPS_FORMAT_S16_BE,
SPS_FORMAT_S24,
SPS_FORMAT_S24_LE,
SPS_FORMAT_S24_BE,
SPS_FORMAT_S24_BE,
SPS_FORMAT_S24_3LE,
SPS_FORMAT_S24_3BE,
SPS_FORMAT_S32,
@@ -105,7 +97,7 @@ enum sps_format_t {
SPS_FORMAT_INVALID,
} sps_format_t;
const char * sps_format_description_string(enum sps_format_t format);
const char *sps_format_description_string(enum sps_format_t format);
typedef struct {
config_t *cfg;
@@ -172,7 +164,7 @@ typedef struct {
uint32_t userSuppliedLatency; // overrides all other latencies -- use with caution
uint32_t fixedLatencyOffset; // add this to all automatic latencies supplied to get the actual
// total latency
// the total latency will be limited to the min and max-latency values, if supplied
// the total latency will be limited to the min and max-latency values, if supplied
#ifdef CONFIG_LIBDAEMON
int daemonise;
int daemonise_store_pid; // don't try to save a PID file
@@ -192,7 +184,8 @@ typedef struct {
double tolerance; // allow this much drift before attempting to correct it
enum stuffing_type packet_stuffing;
int soxr_delay_index;
int soxr_delay_threshold; // the soxr delay must be less or equal to this for soxr interpolation to be enabled under the auto setting
int soxr_delay_threshold; // the soxr delay must be less or equal to this for soxr interpolation
// to be enabled under the auto setting
int decoders_supported;
int use_apple_decoder; // set to 1 if you want to use the apple decoder instead of the original by
// David Hammerton
@@ -215,16 +208,18 @@ typedef struct {
// 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_state_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.
int volume_range_hw_priority; // when extending the volume range by combining sw and hw attenuators, lowering the volume, use all the hw attenuation before using
// 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.
int volume_range_hw_priority; // when extending the volume range by combining sw and hw
// attenuators, lowering the volume, use all the hw attenuation
// before using
// sw attenuation
enum volume_control_profile_type volume_control_profile;
int output_format_auto_requested; // true if the configuration requests auto configuration
int output_format_auto_requested; // true if the configuration requests auto configuration
enum sps_format_t output_format;
int output_rate_auto_requested; // true if the configuration requests auto configuration
int output_rate_auto_requested; // true if the configuration requests auto configuration
unsigned int output_rate;
#ifdef CONFIG_CONVOLUTION
@@ -283,7 +278,8 @@ int get_requested_connection_state_to_output();
void set_requested_connection_state_to_output(int v);
ssize_t non_blocking_write_with_timeout(int fd, const void *buf, size_t count, int timeout); // timeout in milliseconds
ssize_t non_blocking_write_with_timeout(int fd, const void *buf, size_t count,
int timeout); // timeout in milliseconds
ssize_t non_blocking_write(int fd, const void *buf, size_t count); // used in a few places
+10 -16
View File
@@ -39,8 +39,8 @@
#include <netinet/in.h>
#include <pthread.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include "metadata_hub.h"
@@ -112,10 +112,7 @@ 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;
@@ -323,10 +320,9 @@ 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
}
@@ -378,7 +374,7 @@ void set_dacp_server_information(rtsp_conn_info *conn) {
if ((conn->dacp_id == NULL) || (strcmp(conn->dacp_id, dacp_server.dacp_id) != 0)) {
if (conn->dacp_id)
strncpy(dacp_server.dacp_id, conn->dacp_id, sizeof(dacp_server.dacp_id)-1);
strncpy(dacp_server.dacp_id, conn->dacp_id, sizeof(dacp_server.dacp_id) - 1);
else
dacp_server.dacp_id[0] = '\0';
dacp_server.port = 0;
@@ -423,9 +419,8 @@ 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;
@@ -473,9 +468,8 @@ 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) {
+34 -34
View File
@@ -433,12 +433,14 @@ gboolean notify_drift_tolerance_callback(ShairportSync *skeleton,
}
gboolean notify_disable_standby_mode_callback(ShairportSync *skeleton,
__attribute__((unused)) gpointer user_data) {
__attribute__((unused)) gpointer user_data) {
char *th = (char *)shairport_sync_get_disable_standby_mode(skeleton);
if ((strcasecmp(th, "no") == 0) || (strcasecmp(th, "off") == 0) || (strcasecmp(th, "never") == 0)) {
if ((strcasecmp(th, "no") == 0) || (strcasecmp(th, "off") == 0) ||
(strcasecmp(th, "never") == 0)) {
config.disable_standby_mode = disable_standby_off;
config.keep_dac_busy = 0;
} else if ((strcasecmp(th, "yes") == 0) || (strcasecmp(th, "on") == 0) || (strcasecmp(th, "always") == 0)) {
} else if ((strcasecmp(th, "yes") == 0) || (strcasecmp(th, "on") == 0) ||
(strcasecmp(th, "always") == 0)) {
config.disable_standby_mode = disable_standby_always;
config.keep_dac_busy = 1;
} else if (strcasecmp(th, "auto") == 0)
@@ -446,17 +448,17 @@ gboolean notify_disable_standby_mode_callback(ShairportSync *skeleton,
else {
warn("An unrecognised disable_standby_mode: \"%s\" was requested via D-Bus interface.", th);
switch (config.disable_standby_mode) {
case disable_standby_off:
shairport_sync_set_disable_standby_mode(skeleton, "off");
break;
case disable_standby_always:
shairport_sync_set_disable_standby_mode(skeleton, "always");
break;
case disable_standby_auto:
shairport_sync_set_disable_standby_mode(skeleton, "auto");
break;
default:
break;
case disable_standby_off:
shairport_sync_set_disable_standby_mode(skeleton, "off");
break;
case disable_standby_always:
shairport_sync_set_disable_standby_mode(skeleton, "always");
break;
case disable_standby_auto:
shairport_sync_set_disable_standby_mode(skeleton, "auto");
break;
default:
break;
}
}
return TRUE;
@@ -661,7 +663,7 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name
G_CALLBACK(notify_alacdecoder_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::disable-standby-mode",
G_CALLBACK(notify_disable_standby_mode_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::volume-control-profile",
g_signal_connect(shairportSyncSkeleton, "notify::volume-control-profile",
G_CALLBACK(notify_volume_control_profile_callback), NULL);
g_signal_connect(shairportSyncSkeleton, "notify::disable-standby",
G_CALLBACK(notify_disable_standby_callback), NULL);
@@ -749,21 +751,21 @@ static void on_dbus_name_acquired(GDBusConnection *connection, const gchar *name
debug(1, ">> Active set to \"false\"");
switch (config.disable_standby_mode) {
case disable_standby_off:
shairport_sync_set_disable_standby_mode(SHAIRPORT_SYNC(shairportSyncSkeleton), "off");
debug(1, ">> disable standby mode set to \"off\"");
break;
case disable_standby_always:
shairport_sync_set_disable_standby_mode(SHAIRPORT_SYNC(shairportSyncSkeleton), "always");
debug(1, ">> disable standby mode set to \"always\"");
break;
case disable_standby_auto:
shairport_sync_set_disable_standby_mode(SHAIRPORT_SYNC(shairportSyncSkeleton), "auto");
debug(1, ">> disable standby mode set to \"auto\"");
break;
default:
debug(1,"invalid disable_standby mode!");
break;
case disable_standby_off:
shairport_sync_set_disable_standby_mode(SHAIRPORT_SYNC(shairportSyncSkeleton), "off");
debug(1, ">> disable standby mode set to \"off\"");
break;
case disable_standby_always:
shairport_sync_set_disable_standby_mode(SHAIRPORT_SYNC(shairportSyncSkeleton), "always");
debug(1, ">> disable standby mode set to \"always\"");
break;
case disable_standby_auto:
shairport_sync_set_disable_standby_mode(SHAIRPORT_SYNC(shairportSyncSkeleton), "auto");
debug(1, ">> disable standby mode set to \"auto\"");
break;
default:
debug(1, "invalid disable_standby mode!");
break;
}
#ifdef CONFIG_SOXR
@@ -902,9 +904,7 @@ void stop_dbus_service() {
g_bus_unown_name(ownerID);
else
debug(1, "Zero OwnerID for \"org.gnome.ShairportSync\".");
service_is_running = 0;
service_is_running = 0;
}
int dbus_service_is_running() {
return service_is_running;
}
int dbus_service_is_running() { return service_is_running; }
+1 -1
View File
@@ -24,8 +24,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "common.h"
#include "mdns.h"
#include "common.h"
#include <arpa/inet.h>
#include <dns_sd.h>
#include <stdlib.h>
+13 -13
View File
@@ -46,8 +46,8 @@
#include "metadata_hub.h"
#ifdef CONFIG_MBEDTLS
#include <mbedtls/version.h>
#include <mbedtls/md5.h>
#include <mbedtls/version.h>
#endif
#ifdef CONFIG_POLARSSL
@@ -223,7 +223,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_OPENSSL
MD5_CTX ctx;
@@ -233,17 +233,17 @@ char *metadata_write_image_file(const char *buf, int len) {
#endif
#ifdef CONFIG_MBEDTLS
#if MBEDTLS_VERSION_MINOR >= 7
mbedtls_md5_context tctx;
mbedtls_md5_starts_ret(&tctx);
mbedtls_md5_update_ret(&tctx, (const unsigned char *)buf, len);
mbedtls_md5_finish_ret(&tctx, img_md5);
#else
mbedtls_md5_context tctx;
mbedtls_md5_starts(&tctx);
mbedtls_md5_update(&tctx, (const unsigned char *)buf, len);
mbedtls_md5_finish(&tctx, img_md5);
#endif
#if MBEDTLS_VERSION_MINOR >= 7
mbedtls_md5_context tctx;
mbedtls_md5_starts_ret(&tctx);
mbedtls_md5_update_ret(&tctx, (const unsigned char *)buf, len);
mbedtls_md5_finish_ret(&tctx, img_md5);
#else
mbedtls_md5_context tctx;
mbedtls_md5_starts(&tctx);
mbedtls_md5_update(&tctx, (const unsigned char *)buf, len);
mbedtls_md5_finish(&tctx, img_md5);
#endif
#endif
#ifdef CONFIG_POLARSSL
+11 -9
View File
@@ -656,7 +656,7 @@ static inline void process_sample(int32_t sample, char **outp, enum sps_format_t
// I think, for a 32 --> 16 bits, the range of
// random numbers needs to be from -2^16 to 2^16, i.e. from -65536 to 65536 inclusive, not from
// -32768 to +32767
// Actually, what would be generated here is from -65535 to 65535, i.e. one less on the limits.
// See the original paper at
@@ -1522,7 +1522,8 @@ int stuff_buffer_soxr_32(int32_t *inptr, int32_t *scratchBuffer, int length,
debug(3, "soxr_oneshot execution time in microseconds: mean, standard deviation and max "
"for %" PRId32 " interpolations in the last "
"1250 packets. %10.1f, %10.1f, %10.1f.",
stat_n, stat_mean, stat_n <= 1 ? 0.0 : sqrtf(stat_M2 / (stat_n - 1)), longest_soxr_execution_time_us);
stat_n, stat_mean, stat_n <= 1 ? 0.0 : sqrtf(stat_M2 / (stat_n - 1)),
longest_soxr_execution_time_us);
stat_n = 0;
stat_mean = 0.0;
stat_M2 = 0.0;
@@ -1675,7 +1676,7 @@ void *player_thread_func(void *arg) {
case SPS_FORMAT_S24_3BE:
conn->output_bytes_per_frame = 6;
break;
case SPS_FORMAT_S24:
case SPS_FORMAT_S24_LE:
case SPS_FORMAT_S24_BE:
@@ -1801,7 +1802,6 @@ void *player_thread_func(void *arg) {
if ((config.output->parameters == NULL) || (conn->input_bit_depth > output_bit_depth) ||
(config.playback_mode == ST_mono))
conn->enable_dither = 1;
// remember, the output device may never have been initialised prior to this call
config.output->start(config.output_rate, config.output_format); // will need a corresponding stop
@@ -2386,15 +2386,17 @@ void *player_thread_func(void *arg) {
if ((current_delay < conn->dac_buffer_queue_minimum_length) ||
(config.packet_stuffing == ST_basic) ||
(config.soxr_delay_index == 0) || // not computed yet
((config.packet_stuffing == ST_auto) && (config.soxr_delay_index > config.soxr_delay_threshold)) // if the CPU is deemed too slow
((config.packet_stuffing == ST_auto) &&
(config.soxr_delay_index >
config.soxr_delay_threshold)) // if the CPU is deemed too slow
) {
#endif
play_samples =
stuff_buffer_basic_32((int32_t *)conn->tbuf, inbuflength, config.output_format,
conn->outbuf, amount_to_stuff, conn->enable_dither, conn);
#ifdef CONFIG_SOXR
}
else { // soxr requested or auto requested with the index less or equal to the threshold
} else { // soxr requested or auto requested with the index less or equal to the
// threshold
play_samples = stuff_buffer_soxr_32((int32_t *)conn->tbuf, (int32_t *)conn->sbuf,
inbuflength, config.output_format, conn->outbuf,
amount_to_stuff, conn->enable_dither, conn);
@@ -2943,8 +2945,8 @@ int player_play(rtsp_conn_info *conn) {
command_start();
// call on the output device to prepare itself
if ((config.output) && (config.output->prepare))
config.output->prepare();
config.output->prepare();
pthread_t *pt = malloc(sizeof(pthread_t));
if (pt == NULL)
die("Couldn't allocate space for pthread_t");
+15 -18
View File
@@ -137,9 +137,8 @@ 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;
@@ -369,10 +368,9 @@ 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);
}
@@ -396,11 +394,11 @@ void *rtp_control_receiver(void *arg) {
remote_frame_time_interval; // an IEEE double calculation with a 32-bit
// numerator and 64-bit denominator
// integers
conn->remote_frame_rate = conn->remote_frame_rate *
(uint64_t)0x100000000; // this should just change the
// [binary] exponent in the IEEE
// FP representation; the
// mantissa should be unaffected.
conn->remote_frame_rate =
conn->remote_frame_rate * (uint64_t)0x100000000; // this should just change the
// [binary] exponent in the IEEE
// FP representation; the
// mantissa should be unaffected.
} else {
conn->remote_frame_rate = 0.0; // use as a flag.
}
@@ -824,7 +822,7 @@ void *rtp_timing_receiver(void *arg) {
conn->local_to_remote_time_gradient = (1.0 * mtl) / mbl;
else {
conn->local_to_remote_time_gradient = 1.0;
debug(1,"rtp_timing_receiver: mbl is 0");
debug(1, "rtp_timing_receiver: mbl is 0");
}
} else {
conn->local_to_remote_time_gradient = 1.0;
@@ -1105,7 +1103,7 @@ int sanitised_source_rate_information(uint32_t *frames, uint64_t *time, rtsp_con
if (local_time)
calculated_frame_rate = ((1.0 * local_frames) / local_time) * one_fp;
else
debug(1,"sanitised_source_rate_information: local_time is zero");
debug(1, "sanitised_source_rate_information: local_time is zero");
if ((local_time == 0) || ((calculated_frame_rate / conn->input_rate) > 1.002) ||
((calculated_frame_rate / conn->input_rate) < 0.998)) {
debug(3, "input frame rate out of bounds at %.2f fps.", calculated_frame_rate);
@@ -1188,7 +1186,7 @@ int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn) {
if (time_difference)
frame_interval = (time_interval * frame_difference) / time_difference;
else
debug(1,"local_time_to_frame: time_difference is zero");
debug(1, "local_time_to_frame: time_difference is zero");
if (reference_time_was_earlier) {
// debug(1,"Frame interval is %" PRId64 " frames.",frame_interval);
*frame = (conn->reference_timestamp + frame_interval);
@@ -1240,9 +1238,8 @@ 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 {
+97 -90
View File
@@ -31,6 +31,7 @@
#include <libconfig.h>
#include <libgen.h>
#include <memory.h>
#include <net/if.h>
#include <popt.h>
#include <stdio.h>
#include <stdlib.h>
@@ -38,10 +39,8 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <net/if.h>
#include <unistd.h>
#include "config.h"
#ifdef CONFIG_MBEDTLS
@@ -97,15 +96,14 @@
#endif
#ifdef CONFIG_SOXR
#include <soxr.h>
#include <math.h>
#include <soxr.h>
#endif
#ifdef CONFIG_CONVOLUTION
#include <FFTConvolver/convolver.h>
#endif
#ifdef CONFIG_LIBDAEMON
pid_t pid;
#endif
@@ -165,33 +163,34 @@ void print_version(void) {
}
#ifdef CONFIG_SOXR
pthread_t soxr_time_check_thread;
void* soxr_time_check(__attribute__((unused)) void *arg) {
pthread_t soxr_time_check_thread;
void *soxr_time_check(__attribute__((unused)) void *arg) {
const int buffer_length = 352;
int32_t inbuffer[buffer_length*2];
int32_t outbuffer[(buffer_length+1)*2];
//int32_t *outbuffer = (int32_t*)malloc((buffer_length+1)*2*sizeof(int32_t));
//int32_t *inbuffer = (int32_t*)malloc((buffer_length)*2*sizeof(int32_t));
int32_t inbuffer[buffer_length * 2];
int32_t outbuffer[(buffer_length + 1) * 2];
// int32_t *outbuffer = (int32_t*)malloc((buffer_length+1)*2*sizeof(int32_t));
// int32_t *inbuffer = (int32_t*)malloc((buffer_length)*2*sizeof(int32_t));
// generate a sample signal
const double frequency = 440; //
const double frequency = 440; //
int i;
int number_of_iterations = 0;
uint64_t soxr_start_time = get_absolute_time_in_fp();
uint64_t loop_until_time = (uint64_t)0x180000000 + soxr_start_time; // loop for a second and a half, max
uint64_t loop_until_time =
(uint64_t)0x180000000 + soxr_start_time; // loop for a second and a half, max
while (get_absolute_time_in_fp() < loop_until_time) {
number_of_iterations++;
for (i = 0; i < buffer_length ; i++) {
double w = sin(i * (frequency + number_of_iterations * 2) * 2 * M_PI/44100);
for (i = 0; i < buffer_length; i++) {
double w = sin(i * (frequency + number_of_iterations * 2) * 2 * M_PI / 44100);
int32_t wint = (int32_t)(w * INT32_MAX);
inbuffer[i * 2] = wint;
inbuffer[i * 2 + 1] = wint;
}
soxr_io_spec_t io_spec;
io_spec.itype = SOXR_INT32_I;
io_spec.otype = SOXR_INT32_I;
@@ -201,37 +200,39 @@ void* soxr_time_check(__attribute__((unused)) void *arg) {
size_t odone;
soxr_oneshot(buffer_length, buffer_length + 1, 2, // Rates and # of chans.
inbuffer, buffer_length, NULL, // Input.
outbuffer, buffer_length + 1, &odone, // Output.
&io_spec, // Input, output and transfer spec.
NULL, NULL); // Default configuration.
soxr_oneshot(buffer_length, buffer_length + 1, 2, // Rates and # of chans.
inbuffer, buffer_length, NULL, // Input.
outbuffer, buffer_length + 1, &odone, // Output.
&io_spec, // Input, output and transfer spec.
NULL, NULL); // Default configuration.
io_spec.itype = SOXR_INT32_I;
io_spec.otype = SOXR_INT32_I;
io_spec.scale = 1.0; // this seems to crash if not = 1.0
io_spec.e = NULL;
io_spec.flags = 0;
soxr_oneshot(buffer_length, buffer_length - 1, 2, // Rates and # of chans.
inbuffer, buffer_length, NULL, // Input.
outbuffer, buffer_length - 1, &odone, // Output.
&io_spec, // Input, output and transfer spec.
NULL, NULL); // Default configuration.
soxr_oneshot(buffer_length, buffer_length - 1, 2, // Rates and # of chans.
inbuffer, buffer_length, NULL, // Input.
outbuffer, buffer_length - 1, &odone, // Output.
&io_spec, // Input, output and transfer spec.
NULL, NULL); // Default configuration.
}
double soxr_execution_time_us =
(((get_absolute_time_in_fp() - soxr_start_time) * 1000000) >> 32) * 1.0;
(((get_absolute_time_in_fp() - soxr_start_time) * 1000000) >> 32) * 1.0;
// free(outbuffer);
// free(inbuffer);
config.soxr_delay_index = (int)(0.9 + soxr_execution_time_us/(number_of_iterations *1000));
debug(2,"soxr_delay_index: %d.", config.soxr_delay_index);
if ((config.packet_stuffing == ST_soxr) && (config.soxr_delay_index > config.soxr_delay_threshold))
inform("Note: this device may be too slow for \"soxr\" interpolation. Consider choosing the \"basic\" or \"auto\" interpolation setting.");
config.soxr_delay_index = (int)(0.9 + soxr_execution_time_us / (number_of_iterations * 1000));
debug(2, "soxr_delay_index: %d.", config.soxr_delay_index);
if ((config.packet_stuffing == ST_soxr) &&
(config.soxr_delay_index > config.soxr_delay_threshold))
inform("Note: this device may be too slow for \"soxr\" interpolation. Consider choosing the "
"\"basic\" or \"auto\" interpolation setting.");
if (config.packet_stuffing == ST_auto)
debug(1,"\"%s\" interpolation has been chosen.", config.soxr_delay_index <= config.soxr_delay_threshold ? "soxr" : "basic");
pthread_exit(NULL);
debug(1, "\"%s\" interpolation has been chosen.",
config.soxr_delay_index <= config.soxr_delay_threshold ? "soxr" : "basic");
pthread_exit(NULL);
}
#endif
@@ -428,10 +429,14 @@ int parse_options(int argc, char **argv) {
config.fixedLatencyOffset = 11025; // this sounds like it works properly.
config.diagnostic_drop_packet_fraction = 0.0;
config.active_state_timeout = 10.0;
config.soxr_delay_threshold = 30; // the soxr measurement time (milliseconds) of two oneshots must not exceed this if soxr interpolation is to be chosen automatically.
config.volume_range_hw_priority = 0; // if combining software and hardware volume control, give the software priority
config.soxr_delay_threshold = 30; // the soxr measurement time (milliseconds) of two oneshots must
// not exceed this if soxr interpolation is to be chosen
// automatically.
config.volume_range_hw_priority =
0; // if combining software and hardware volume control, give the software priority
// i.e. when reducing volume, reduce the sw first before reducing the software.
// this is because some hw mixers mute at the bottom of their range, and they don't always advertise this fact
// this is because some hw mixers mute at the bottom of their range, and they don't always advertise
// this fact
#ifdef CONFIG_METADATA_HUB
config.cover_art_cache_dir = "/tmp/shairport-sync/.cache/coverart";
@@ -536,13 +541,13 @@ int parse_options(int argc, char **argv) {
config.packet_stuffing = ST_soxr;
#else
warn("The soxr option not available because this version of shairport-sync was built "
"without libsoxr "
"support. Change the \"general/interpolation\" setting in the configuration file.");
"without libsoxr "
"support. Change the \"general/interpolation\" setting in the configuration file.");
#endif
else
die("Invalid interpolation option choice. It should be \"auto\", \"basic\" or \"soxr\"");
}
#ifdef CONFIG_SOXR
/* Get the soxr_delay_threshold setting. */
if (config_lookup_int(config.cfg, "general.soxr_delay_threshold", &value)) {
@@ -550,9 +555,9 @@ int parse_options(int argc, char **argv) {
config.soxr_delay_threshold = value;
else
warn("Invalid general soxr_delay_threshold setting option choice \"%d\". It should be "
"between 0 and 100, "
"inclusive. Default is %d (milliseconds).",
value, config.soxr_delay_threshold);
"between 0 and 100, "
"inclusive. Default is %d (milliseconds).",
value, config.soxr_delay_threshold);
}
#endif
@@ -1003,10 +1008,10 @@ int parse_options(int argc, char **argv) {
config.mqtt_port = 1883;
if (config_lookup_int(config.cfg, "mqtt.port", &value)) {
if ((value < 0) || (value > 65535))
die("Invalid mqtt port number \"%sd\". It should be between 0 and 65535, default is 1883",
value);
die("Invalid mqtt port number \"%sd\". It should be between 0 and 65535, default is 1883",
value);
else
config.mqtt_port = value;
config.mqtt_port = value;
}
if (config_lookup_string(config.cfg, "mqtt.username", &str)) {
@@ -1051,11 +1056,11 @@ int parse_options(int argc, char **argv) {
}
config_set_lookup_bool(config.cfg, "mqtt.enable_remote", &config.mqtt_enable_remote);
#ifndef CONFIG_AVAHI
if (config.mqtt_enable_remote) {
die("You have enabled MQTT remote control which requires shairport-sync to be built with "
"Avahi, but your installation is not using avahi. Please reinstall/recompile with "
"avahi enabled, or disable remote control.");
}
if (config.mqtt_enable_remote) {
die("You have enabled MQTT remote control which requires shairport-sync to be built with "
"Avahi, but your installation is not using avahi. Please reinstall/recompile with "
"avahi enabled, or disable remote control.");
}
#endif
#endif
}
@@ -1125,7 +1130,6 @@ int parse_options(int argc, char **argv) {
// here, we are finally finished reading the options
#ifdef CONFIG_LIBDAEMON
if ((daemonisewith) && (daemonisewithout))
die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected "
@@ -1138,7 +1142,9 @@ int parse_options(int argc, char **argv) {
#else
/* Check if we are called with -d or --daemon or -j or justDaemoniseNoPIDFile options*/
if ((daemonisewith != 0) || (daemonisewithout != 0)) {
fprintf(stderr,"%s was built without libdaemon, so does not support daemonisation using the -d, --deamon, -j or --justDaemoniseNoPIDFile options\n",config.appName);
fprintf(stderr, "%s was built without libdaemon, so does not support daemonisation using the "
"-d, --deamon, -j or --justDaemoniseNoPIDFile options\n",
config.appName);
exit(EXIT_FAILURE);
}
@@ -1313,16 +1319,16 @@ void main_cleanup_handler(__attribute__((unused)) void *arg) {
debug(2, "Deinitialise the audio backend.");
config.output->deinit();
}
#ifdef CONFIG_LIBDAEMON
// only do this if you are the daemon
// only do this if you are the daemon
if (pid == 0) {
daemon_retval_send(0);
daemon_pid_file_remove();
daemon_signal_done();
}
}
#endif
debug(2, "Exit...");
exit(EXIT_SUCCESS);
}
@@ -1366,12 +1372,12 @@ int main(int argc, char **argv) {
die("can not allocate memory for the app name!");
free(basec);
// debug(1,"startup");
// debug(1,"startup");
#ifdef CONFIG_LIBDAEMON
daemon_set_verbosity(LOG_DEBUG);
#else
setlogmask (LOG_UPTO (LOG_DEBUG));
openlog(NULL,0,LOG_DAEMON);
setlogmask(LOG_UPTO(LOG_DEBUG));
openlog(NULL, 0, LOG_DAEMON);
#endif
atexit(exit_function);
@@ -1410,8 +1416,9 @@ int main(int argc, char **argv) {
// config.statistics_requested = 0; // don't print stats in the log
// config.userSuppliedLatency = 0; // zero means none supplied
config.debugger_show_relative_time = 1; // by default, log the time back to the previous debug message
config.debugger_show_relative_time =
1; // by default, log the time back to the previous debug message
config.resyncthreshold = 0.05; // 50 ms
config.timeout = 120; // this number of seconds to wait for [more] audio before switching to idle.
config.tolerance =
@@ -1419,14 +1426,13 @@ int main(int argc, char **argv) {
config.buffer_start_fill = 220;
config.port = 5000;
#ifdef CONFIG_SOXR
config.packet_stuffing = ST_auto; // use soxr interpolation by default if support has been included and if the CPU is fast enough
config.packet_stuffing = ST_auto; // use soxr interpolation by default if support has been
// included and if the CPU is fast enough
#else
config.packet_stuffing = ST_basic; // simple interpolation or deletion
#endif
// char hostname[100];
// gethostname(hostname, 100);
// config.service_name = malloc(20 + 100);
@@ -1488,7 +1494,6 @@ int main(int argc, char **argv) {
#endif
// parse arguments into config -- needed to locate pid_dir
int audio_arg = parse_options(argc, argv);
@@ -1499,7 +1504,7 @@ int main(int argc, char **argv) {
}
/* Check if we are called with -k or --kill option */
if (killOption != 0) {
if (killOption != 0) {
#ifdef CONFIG_LIBDAEMON
int ret;
@@ -1512,7 +1517,8 @@ int main(int argc, char **argv) {
}
return ret < 0 ? 1 : 0;
#else
fprintf(stderr,"%s was built without libdaemon, so does not support the -k or --kill option\n",config.appName);
fprintf(stderr, "%s was built without libdaemon, so does not support the -k or --kill option\n",
config.appName);
return 1;
#endif
}
@@ -1591,7 +1597,7 @@ int main(int argc, char **argv) {
daemon_signal_done();
return 0;
}
if (daemon_pid_file_create() < 0) {
daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno));
@@ -1608,7 +1614,7 @@ int main(int argc, char **argv) {
}
#endif
debug(1,"Started!");
debug(1, "Started!");
main_thread_id = pthread_self();
if (!main_thread_id)
debug(1, "Main thread is set up to be NULL!");
@@ -1618,7 +1624,6 @@ int main(int argc, char **argv) {
// make sure the program can create files that group and world can read
umask(S_IWGRP | S_IWOTH);
/* print out version */
char *version_dbs = get_version_string();
@@ -1628,7 +1633,7 @@ int main(int argc, char **argv) {
} else {
debug(1, "can't print the version information!");
}
debug(1, "log verbosity is %d.", debuglev);
config.output = audio_get_output(config.output_name);
@@ -1701,7 +1706,9 @@ int main(int argc, char **argv) {
debug(1, "active_state_timeout is %f seconds.", config.active_state_timeout);
debug(1, "mdns backend \"%s\".", config.mdns_name);
debug(2, "userSuppliedLatency is %d.", config.userSuppliedLatency);
debug(1, "interpolation setting is \"%s\".", config.packet_stuffing == ST_basic ? "basic" : config.packet_stuffing == ST_soxr ? "soxr" : "auto");
debug(1, "interpolation setting is \"%s\".",
config.packet_stuffing == ST_basic ? "basic" : config.packet_stuffing == ST_soxr ? "soxr"
: "auto");
debug(1, "interpolation soxr_delay_threshold is %d.", config.soxr_delay_threshold);
debug(1, "resync time is %f seconds.", config.resyncthreshold);
debug(1, "allow a session to be interrupted: %d.", config.allow_session_interruption);
@@ -1715,25 +1722,25 @@ int main(int argc, char **argv) {
debug(1, "volume_max_db is not set");
debug(1, "volume range in dB (zero means use the range specified by the mixer): %u.",
config.volume_range_db);
debug(
1,
"volume_range_combined_hardware_priority (1 means hardware mixer attenuation is used first) is %d.",
config.volume_range_hw_priority);
debug(1, "volume_range_combined_hardware_priority (1 means hardware mixer attenuation is used "
"first) is %d.",
config.volume_range_hw_priority);
debug(1, "playback_mode is %d (0-stereo, 1-mono, 1-reverse_stereo, 2-both_left, 3-both_right).",
config.playback_mode);
debug(1, "disable_synchronization is %d.", config.no_sync);
debug(1, "use_mmap_if_available is %d.", config.no_mmap ? 0 : 1);
debug(1, "output_format automatic selection is %sabled.", config.output_format_auto_requested ? "en" : "dis");
debug(1, "output_format automatic selection is %sabled.",
config.output_format_auto_requested ? "en" : "dis");
if (config.output_format_auto_requested == 0)
debug(1,
"output_format is \"%s\".",
sps_format_description_string(config.output_format));
debug(1, "output_rate automatic selection is %sabled.", config.output_rate_auto_requested ? "en" : "dis");
debug(1, "output_format is \"%s\".", sps_format_description_string(config.output_format));
debug(1, "output_rate automatic selection is %sabled.",
config.output_rate_auto_requested ? "en" : "dis");
if (config.output_rate_auto_requested == 0)
debug(1, "output_rate is %d.", config.output_rate);
debug(1, "output_rate is %d.", config.output_rate);
debug(1, "audio backend desired buffer length is %f seconds.",
config.audio_backend_buffer_desired_length);
debug(1, "audio_backend_buffer_interpolation_threshold_in_seconds is %f seconds.", config.audio_backend_buffer_interpolation_threshold_in_seconds);
debug(1, "audio_backend_buffer_interpolation_threshold_in_seconds is %f seconds.",
config.audio_backend_buffer_interpolation_threshold_in_seconds);
debug(1, "audio backend latency offset is %f seconds.", config.audio_backend_latency_offset);
debug(1, "audio backend silence lead-in time is %f seconds. A value -1.0 means use the default.",
config.audio_backend_silent_lead_in_time);
@@ -1783,7 +1790,7 @@ int main(int argc, char **argv) {
uint8_t ap_md5[16];
#ifdef CONFIG_SOXR
pthread_create(&soxr_time_check_thread, NULL, &soxr_time_check, NULL);
pthread_create(&soxr_time_check_thread, NULL, &soxr_time_check, NULL);
#endif
#ifdef CONFIG_OPENSSL