Tidy up source using clang-format

This commit is contained in:
Mike Brady
2017-07-31 11:57:57 +02:00
parent d1895a8b0e
commit e513e5330c
20 changed files with 472 additions and 449 deletions
+8 -7
View File
@@ -24,8 +24,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "common.h"
#include "audio.h"
#include "common.h"
#include "config.h"
#include <stdio.h>
#include <string.h>
@@ -117,7 +117,8 @@ void audio_ls_outputs(void) {
}
void parse_general_audio_options(void) {
/* this must be called after the output device has been initialised, so that the default values are set before any options are chosen */
/* this must be called after the output device has been initialised, so that the default values
* are set before any options are chosen */
int value;
double dvalue;
if (config.cfg != NULL) {
@@ -130,7 +131,7 @@ void parse_general_audio_options(void) {
die("Invalid audio_backend_buffer_desired_length value: \"%d\". It "
"should be between 0 and "
"66150, default is %d",
value,(int)(config.audio_backend_buffer_desired_length*44100));
value, (int)(config.audio_backend_buffer_desired_length * 44100));
} else {
inform("The setting general.audio_backend_buffer_desired_length is deprecated. "
"Use general.audio_backend_buffer_desired_length_in_seconds instead.");
@@ -145,7 +146,7 @@ void parse_general_audio_options(void) {
die("Invalid audio_backend_buffer_desired_length_in_seconds value: \"%f\". It "
"should be between 0 and "
"1.5, default is %.3f seconds",
dvalue,config.audio_backend_buffer_desired_length);
dvalue, config.audio_backend_buffer_desired_length);
} else {
config.audio_backend_buffer_desired_length = dvalue;
}
@@ -167,7 +168,8 @@ void parse_general_audio_options(void) {
}
/* Get the latency offset in seconds. */
if (config_lookup_float(config.cfg, "general.audio_backend_latency_offset_in_seconds", &dvalue)) {
if (config_lookup_float(config.cfg, "general.audio_backend_latency_offset_in_seconds",
&dvalue)) {
if ((dvalue < -1.0) || (dvalue > 1.5)) {
die("Invalid audio_backend_latency_offset_in_seconds \"%f\". It "
"should be between -1.0 and +1.5, default is 0 seconds",
@@ -178,8 +180,7 @@ void parse_general_audio_options(void) {
}
/* Get the desired length of the silent lead-in. */
if (config_lookup_float(config.cfg, "general.audio_backend_silent_lead_in_time",
&dvalue)) {
if (config_lookup_float(config.cfg, "general.audio_backend_silent_lead_in_time", &dvalue)) {
if ((dvalue < 0.0) || (dvalue > 4)) {
die("Invalid audio_backend_silent_lead_in_time \"%f\". It "
"must be between 0.0 and 4.0 seconds. Omit setting to use the default value",
+79 -75
View File
@@ -53,18 +53,19 @@ static void mute(int do_mute);
static double set_volume;
static int output_method_signalled = 0;
audio_output audio_alsa = {.name = "alsa",
.help = &help,
.init = &init,
.deinit = &deinit,
.start = &start,
.stop = &stop,
.flush = &flush,
.delay = &delay,
.play = &play,
.mute = NULL, // a function will be provided if it can, and is allowed to, do hardware mute
.volume = NULL, // a function will be provided if it can do hardware volume
.parameters = &parameters};
audio_output audio_alsa = {
.name = "alsa",
.help = &help,
.init = &init,
.deinit = &deinit,
.start = &start,
.stop = &stop,
.flush = &flush,
.delay = &delay,
.play = &play,
.mute = NULL, // a function will be provided if it can, and is allowed to, do hardware mute
.volume = NULL, // a function will be provided if it can do hardware volume
.parameters = &parameters};
static pthread_mutex_t alsa_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -87,8 +88,8 @@ static char *alsa_mix_ctrl = "Master";
static int alsa_mix_index = 0;
static int hardware_mixer = 0;
static int has_softvol = 0;
static int volume_set_request = 0; // set when an external request is made to set the volume.
int mute_request_pending = 0; // set when an external request is made to mute or unmute.
static int volume_set_request = 0; // set when an external request is made to set the volume.
int mute_request_pending = 0; // set when an external request is made to mute or unmute.
int overriding_mute_state_requested = 0; // 1 = mute; 0 = unmute requested
static snd_pcm_sframes_t (*alsa_pcm_write)(snd_pcm_t *, const void *,
@@ -109,9 +110,7 @@ static void help(void) {
" *) default option\n");
}
void set_alsa_out_dev(char *dev) {
alsa_out_dev = dev;
}
void set_alsa_out_dev(char *dev) { alsa_out_dev = dev; }
int open_mixer() {
if (hardware_mixer) {
@@ -138,18 +137,20 @@ int open_mixer() {
die("Failed to find mixer element");
return 1;
} else {
return 0;
return 0;
}
}
void close_mixer() {
if (alsa_mix_handle) {
snd_mixer_close(alsa_mix_handle);
alsa_mix_handle=NULL;
}
if (alsa_mix_handle) {
snd_mixer_close(alsa_mix_handle);
alsa_mix_handle = NULL;
}
}
#define RELEASE_ALSA_MUTEX_AND_DIE(X) pthread_mutex_unlock(&alsa_mutex);die(X);
#define RELEASE_ALSA_MUTEX_AND_DIE(X) \
pthread_mutex_unlock(&alsa_mutex); \
die(X);
static int init(int argc, char **argv) {
pthread_mutex_lock(&alsa_mutex);
@@ -164,11 +165,11 @@ static int init(int argc, char **argv) {
config.alsa_use_playback_switch_for_mute = 1;
config.audio_backend_latency_offset = 0;
config.audio_backend_buffer_desired_length = 0.15;
config.audio_backend_buffer_desired_length = 0.15;
// get settings from settings file first, allow them to be overridden by
// command line options
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
@@ -209,7 +210,7 @@ static int init(int argc, char **argv) {
die("Invalid disable_synchronization option choice \"%s\". It should be \"yes\" or \"no\"");
}
}
/* Get the mute_using_playback_switch setting. */
if (config_lookup_string(config.cfg, "alsa.mute_using_playback_switch", &str)) {
if (strcasecmp(str, "no") == 0)
@@ -218,10 +219,11 @@ static int init(int argc, char **argv) {
config.alsa_use_playback_switch_for_mute = 1;
else {
pthread_mutex_unlock(&alsa_mutex);
die("Invalid mute_use_playback_switch option choice \"%s\". It should be \"yes\" or \"no\"");
die("Invalid mute_use_playback_switch option choice \"%s\". It should be \"yes\" or "
"\"no\"");
}
}
/* Get the output format, using the same names as aplay does*/
if (config_lookup_string(config.cfg, "alsa.output_format", &str)) {
if (strcasecmp(str, "S16") == 0)
@@ -413,15 +415,16 @@ static int init(int argc, char **argv) {
*/
}
}
if ((config.alsa_use_playback_switch_for_mute==1) && (snd_mixer_selem_has_playback_switch(alsa_mix_elem))) {
if ((config.alsa_use_playback_switch_for_mute == 1) &&
(snd_mixer_selem_has_playback_switch(alsa_mix_elem))) {
audio_alsa.mute = &mute; // insert the mute function now we know it can do muting stuff
// debug(1, "Has mixer and mute ability we will use.");
} else {
// debug(1, "Has mixer but not using hardware mute.");
}
// debug(1, "Has mixer but not using hardware mute.");
}
close_mixer();
} else {
// debug(1, "Has no mixer and thus no hardware mute.");
// debug(1, "Has no mixer and thus no hardware mute.");
}
alsa_mix_handle = NULL;
@@ -435,7 +438,7 @@ static void deinit(void) {
}
int open_alsa_device(void) {
//the alsa mutex is already acquired when this is called
// the alsa mutex is already acquired when this is called
const snd_pcm_uframes_t minimal_buffer_headroom =
352 * 2; // we accept this much headroom in the hardware buffer, but we'll
@@ -467,7 +470,8 @@ int open_alsa_device(void) {
ret = snd_pcm_hw_params_any(alsa_handle, alsa_params);
if (ret < 0) {
pthread_mutex_unlock(&alsa_mutex);;
pthread_mutex_unlock(&alsa_mutex);
;
die("audio_alsa: Broken configuration for device \"%s\": no configurations "
"available",
alsa_out_dev);
@@ -527,8 +531,8 @@ int open_alsa_device(void) {
ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
if (ret < 0) {
pthread_mutex_unlock(&alsa_mutex);
die("audio_alsa: Sample format %d not available for device \"%s\": %s", sample_format, alsa_out_dev,
snd_strerror(ret));
die("audio_alsa: Sample format %d not available for device \"%s\": %s", sample_format,
alsa_out_dev, snd_strerror(ret));
}
ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
@@ -816,10 +820,10 @@ static void play(short buf[], int samples) {
pthread_mutex_lock(&alsa_mutex);
ret = open_alsa_device();
if (ret == 0) {
if (audio_alsa.volume)
do_volume(set_volume);
if (audio_alsa.mute)
do_mute(0);
if (audio_alsa.volume)
do_volume(set_volume);
if (audio_alsa.mute)
do_mute(0);
}
pthread_mutex_unlock(&alsa_mutex);
}
@@ -831,7 +835,7 @@ static void play(short buf[], int samples) {
if ((err = snd_pcm_prepare(alsa_handle))) {
ignore = snd_pcm_recover(alsa_handle, err, 1);
debug(1, "Error preparing after underrun: \"%s\".", snd_strerror(err));
}
}
}
if ((snd_pcm_state(alsa_handle) == SND_PCM_STATE_PREPARED) ||
(snd_pcm_state(alsa_handle) == SND_PCM_STATE_RUNNING)) {
@@ -874,7 +878,7 @@ static void flush(void) {
debug(1, "Error preparing after flush: \"%s\".", snd_strerror(derr));
// debug(1,"Frames successfully dropped.");
*/
/*
if (snd_pcm_state(alsa_handle)==SND_PCM_STATE_PREPARED)
debug(1,"Flush returns to SND_PCM_STATE_PREPARED state.");
@@ -886,21 +890,20 @@ static void flush(void) {
(snd_pcm_state(alsa_handle) == SND_PCM_STATE_RUNNING)))
debug(1, "Flush returning unexpected state -- %d.", snd_pcm_state(alsa_handle));
*/
// this is derived from http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2latency_8c-example.html#a45
if ((derr=snd_pcm_nonblock(alsa_handle, 0)))
// this is derived from
// http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2latency_8c-example.html#a45
if ((derr = snd_pcm_nonblock(alsa_handle, 0)))
debug(1, "Error %d (\"%s\") unblocking output device.", derr, snd_strerror(derr));
if ((derr=snd_pcm_drain(alsa_handle)))
if ((derr = snd_pcm_drain(alsa_handle)))
debug(1, "Error %d (\"%s\") draining output device.", derr, snd_strerror(derr));
if ((derr=snd_pcm_nonblock(alsa_handle, 1)))
if ((derr = snd_pcm_nonblock(alsa_handle, 1)))
debug(1, "Error %d (\"%s\") reblocking output device.", derr, snd_strerror(derr));
if ((derr=snd_pcm_hw_free(alsa_handle)))
if ((derr = snd_pcm_hw_free(alsa_handle)))
debug(1, "Error %d (\"%s\") freeing output device hardware.", derr, snd_strerror(derr));
// flush also closes the device
snd_pcm_close(alsa_handle);
alsa_handle = NULL;
@@ -949,7 +952,7 @@ void do_volume(double vol) { // caller is assumed to have the alsa_mutex when us
debug(1, "Can't set playback volume accurately to %f dB.", vol);
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol, -1) != 0)
if (snd_mixer_selem_set_playback_dB_all(alsa_mix_elem, vol, 1) != 0)
debug(1,"Could not set playback dB volume on the mixer.");
debug(1, "Could not set playback dB volume on the mixer.");
}
}
volume_set_request = 0; // any external request that has been made is now satisfied
@@ -994,31 +997,32 @@ static void mute(int mute_state_requested) {
void do_mute(int mute_state_requested) {
// if a mute is requested now, then
// if an external mute request is in place, leave everything muted
// otherwise, if an external mute request is pending, action it
// otherwise, action the do_mute request
int local_mute_state_requested = overriding_mute_state_requested; // go with whatever was asked by the external "mute" call
// if a mute is requested now, then
// if an external mute request is in place, leave everything muted
// otherwise, if an external mute request is pending, action it
// otherwise, action the do_mute request
int local_mute_state_requested =
overriding_mute_state_requested; // go with whatever was asked by the external "mute" call
// The mute state requested will be actioned unless mute_request_pending is set
// If it is set, then that the pending request will be actioned.
// If the hardware isn't there, or we are not allowed to use it, nothing will be done
// The caller must have the alsa mutex
if (config.alsa_use_playback_switch_for_mute==1) {
if (mute_request_pending==0)
local_mute_state_requested = mute_state_requested;
if (open_mixer()) {
if (local_mute_state_requested) {
// debug(1,"Playback Switch mute actually done");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
} else if (overriding_mute_state_requested==0) {
// debug(1,"Playback Switch unmute actually done");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
}
close_mixer();
}
}
mute_request_pending = 0;
if (config.alsa_use_playback_switch_for_mute == 1) {
if (mute_request_pending == 0)
local_mute_state_requested = mute_state_requested;
if (open_mixer()) {
if (local_mute_state_requested) {
// debug(1,"Playback Switch mute actually done");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 0);
} else if (overriding_mute_state_requested == 0) {
// debug(1,"Playback Switch unmute actually done");
snd_mixer_selem_set_playback_switch_all(alsa_mix_elem, 1);
}
close_mixer();
}
}
mute_request_pending = 0;
}
+3 -4
View File
@@ -47,7 +47,7 @@ static int init(int argc, char **argv) {
ao_initialize();
int driver = ao_default_driver_id();
ao_option *ao_opts = NULL;
// set up default values first
config.audio_backend_buffer_desired_length = 1.0;
@@ -55,7 +55,7 @@ static int init(int argc, char **argv) {
// get settings from settings file first, allow them to be overridden by
// command line options
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
@@ -118,8 +118,7 @@ static void deinit(void) {
ao_shutdown();
}
static void start(int sample_rate, int sample_format) {
}
static void start(int sample_rate, int sample_format) {}
static void play(short buf[], int samples) { ao_play(dev, (char *)buf, samples * 4); }
+38 -44
View File
@@ -39,15 +39,14 @@ void stream_state_cb(pa_stream *s, void *mainloop);
void stream_success_cb(pa_stream *stream, int success, void *userdata);
void stream_write_cb(pa_stream *stream, size_t requested_bytes, void *userdata);
static int init(int argc, char **argv) {
// set up default values first
config.audio_backend_buffer_desired_length = 0.35;
config.audio_backend_latency_offset = 0;
// get settings from settings file
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
@@ -60,10 +59,9 @@ static int init(int argc, char **argv) {
config.pa_application_name = (char *)str;
}
}
// finish collecting settings
// allocate space for the audio buffer
audio_lmb = malloc(audio_size);
if (audio_lmb == NULL)
@@ -71,7 +69,7 @@ static int init(int argc, char **argv) {
audio_toq = audio_eoq = audio_lmb;
audio_umb = audio_lmb + audio_size;
audio_occupancy = 0;
// Get a mainloop and its context
mainloop = pa_threaded_mainloop_new();
assert(mainloop);
@@ -79,7 +77,7 @@ static int init(int argc, char **argv) {
if (config.pa_application_name)
context = pa_context_new(mainloop_api, config.pa_application_name);
else
context = pa_context_new(mainloop_api, "Shairport Sync");
context = pa_context_new(mainloop_api, "Shairport Sync");
assert(context);
// Set a callback so we can wait for the context to be ready
@@ -135,9 +133,9 @@ static void start(int sample_rate, int sample_format) {
// recommended settings, i.e. server uses sensible values
pa_buffer_attr buffer_attr;
buffer_attr.maxlength = (uint32_t) -1;
buffer_attr.maxlength = (uint32_t)-1;
buffer_attr.tlength = buffer_size_in_bytes;
buffer_attr.prebuf = (uint32_t) 0;
buffer_attr.prebuf = (uint32_t)0;
buffer_attr.minreq = (uint32_t)-1;
// Settings copied as per the chromium browser source
@@ -145,7 +143,7 @@ static void start(int sample_rate, int sample_format) {
stream_flags = PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_NOT_MONOTONIC |
// PA_STREAM_AUTO_TIMING_UPDATE;
PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY;
// Connect stream to the default audio output sink
assert(pa_stream_connect_playback(stream, NULL, &buffer_attr, stream_flags, NULL, NULL) == 0);
@@ -187,7 +185,6 @@ static void play(short buf[], int samples) {
pa_threaded_mainloop_lock(mainloop);
pa_stream_cork(stream, 0, stream_success_cb, mainloop);
pa_threaded_mainloop_unlock(mainloop);
}
}
@@ -216,7 +213,7 @@ int pa_delay(long *the_delay) {
void flush(void) {
// Cork the stream so it will stop playing
pa_threaded_mainloop_lock(mainloop);
if (pa_stream_is_corked(stream)==0) {
if (pa_stream_is_corked(stream) == 0) {
// debug(1,"Flush and cork for flush.");
pa_stream_flush(stream, stream_success_cb, NULL);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
@@ -230,7 +227,7 @@ void flush(void) {
static void stop(void) {
// Cork the stream so it will stop playing
pa_threaded_mainloop_lock(mainloop);
if (pa_stream_is_corked(stream)==0) {
if (pa_stream_is_corked(stream) == 0) {
// debug(1,"Flush and cork for stop.");
pa_stream_flush(stream, stream_success_cb, NULL);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
@@ -244,9 +241,7 @@ static void stop(void) {
pa_stream_disconnect(stream);
}
static void help(void) {
printf(" no settings.\n");
}
static void help(void) { printf(" no settings.\n"); }
audio_output audio_pa = {.name = "pa",
.help = &help,
@@ -269,35 +264,35 @@ void stream_state_cb(pa_stream *s, void *mainloop) { pa_threaded_mainloop_signal
void stream_write_cb(pa_stream *stream, size_t requested_bytes, void *userdata) {
/*
// play with timing information
const struct pa_timing_info *ti = pa_stream_get_timing_info(stream);
if ((ti == NULL) || (ti->write_index_corrupt)) {
debug(2, "Timing info invalid");
} else {
struct timeval time_now;
/*
// play with timing information
const struct pa_timing_info *ti = pa_stream_get_timing_info(stream);
if ((ti == NULL) || (ti->write_index_corrupt)) {
debug(2, "Timing info invalid");
} else {
struct timeval time_now;
pa_gettimeofday(&time_now);
pa_gettimeofday(&time_now);
uint64_t time_now_fp = ((uint64_t)time_now.tv_sec << 32) +
((uint64_t)time_now.tv_usec << 32) / 1000000; // types okay
uint64_t time_of_ti_fp = ((uint64_t)(ti->timestamp.tv_sec) << 32) +
((uint64_t)(ti->timestamp.tv_usec) << 32) / 1000000; // types okay
uint64_t time_now_fp = ((uint64_t)time_now.tv_sec << 32) +
((uint64_t)time_now.tv_usec << 32) / 1000000; // types okay
uint64_t time_of_ti_fp = ((uint64_t)(ti->timestamp.tv_sec) << 32) +
((uint64_t)(ti->timestamp.tv_usec) << 32) / 1000000; // types okay
if (time_now_fp >= time_of_ti_fp) {
uint64_t estimate_age = ((time_now_fp - time_of_ti_fp) * 1000000) >> 32;
uint64_t bytes_in_buffer = ti->write_index - ti->read_index;
pa_usec_t microseconds_to_write_buffer = (bytes_in_buffer * 1000000) / (44100 * 2 * 2);
pa_usec_t ea = (pa_usec_t)estimate_age;
pa_usec_t pa_latency = ti->sink_usec + ti->transport_usec + microseconds_to_write_buffer;
pa_usec_t estimated_latency = pa_latency - estimate_age;
// debug(1,"Estimated latency is %d microseconds.",estimated_latency);
if (time_now_fp >= time_of_ti_fp) {
uint64_t estimate_age = ((time_now_fp - time_of_ti_fp) * 1000000) >> 32;
uint64_t bytes_in_buffer = ti->write_index - ti->read_index;
pa_usec_t microseconds_to_write_buffer = (bytes_in_buffer * 1000000) / (44100 * 2 * 2);
pa_usec_t ea = (pa_usec_t)estimate_age;
pa_usec_t pa_latency = ti->sink_usec + ti->transport_usec + microseconds_to_write_buffer;
pa_usec_t estimated_latency = pa_latency - estimate_age;
// debug(1,"Estimated latency is %d microseconds.",estimated_latency);
// } else {
// debug(1, "Time now is earlier than time of timing information");
// } else {
// debug(1, "Time now is earlier than time of timing information");
}
}
}
*/
*/
int bytes_to_transfer = requested_bytes;
int bytes_transferred = 0;
uint8_t *buffer = NULL;
@@ -307,13 +302,13 @@ void stream_write_cb(pa_stream *stream, size_t requested_bytes, void *userdata)
if (audio_occupancy < bytes_we_can_transfer) {
// debug(1, "Underflow? We have %d bytes but we are asked for %d bytes", audio_occupancy,
// bytes_we_can_transfer);
pa_stream_cork(stream,1, stream_success_cb, mainloop);
pa_stream_cork(stream, 1, stream_success_cb, mainloop);
// debug(1, "Corked");
bytes_we_can_transfer = audio_occupancy;
}
// bytes we can transfer will never be greater than the bytes available
pa_stream_begin_write(stream, (void **)&buffer, &bytes_we_can_transfer);
if (bytes_we_can_transfer <= (audio_umb - audio_toq)) {
// the bytes are all in a row in the audo buffer
@@ -375,4 +370,3 @@ void alt_stream_write_cb(pa_stream *stream, size_t requested_bytes, void *userda
}
void stream_success_cb(pa_stream *stream, int success, void *userdata) { return; }
+11 -12
View File
@@ -47,8 +47,8 @@ int warned = 0;
static void start(int sample_rate, int sample_format) {
// this will leave fd as -1 if a reader hasn't been attached
fd = open(pipename, O_WRONLY | O_NONBLOCK);
if ((fd<-1) && (warned==0)) {
warn("Error %d opening the pipe named \"%s\".",errno,pipename);
if ((fd < -1) && (warned == 0)) {
warn("Error %d opening the pipe named \"%s\".", errno, pipename);
warned = 1;
}
}
@@ -62,16 +62,16 @@ static void play(short buf[], int samples) {
// if it's got a reader, write to it.
if (fd > 0) {
int rc = non_blocking_write(fd, buf, samples * 4);
if ((rc<0) && (warned==0)) {
strerror_r(errno,(char*)errorstring,1024);
warn("Error %d writing to the pipe named \"%s\": \"%s\".",errno,pipename,errorstring);
if ((rc < 0) && (warned == 0)) {
strerror_r(errno, (char *)errorstring, 1024);
warn("Error %d writing to the pipe named \"%s\": \"%s\".", errno, pipename, errorstring);
warned = 1;
}
} else if ((fd == -1) && (warned==0)) {
strerror_r(errno,(char*)errorstring,1024);
warn("Error %d opening the pipe named \"%s\": \"%s\".",errno,pipename,errorstring);
} else if ((fd == -1) && (warned == 0)) {
strerror_r(errno, (char *)errorstring, 1024);
warn("Error %d opening the pipe named \"%s\": \"%s\".", errno, pipename, errorstring);
warned = 1;
}
}
}
static void stop(void) {
@@ -90,7 +90,7 @@ static int init(int argc, char **argv) {
config.audio_backend_buffer_desired_length = 1.0;
config.audio_backend_latency_offset = 0;
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
@@ -100,10 +100,9 @@ static int init(int argc, char **argv) {
if (config_lookup_string(config.cfg, "pipe.name", &str)) {
pipename = (char *)str;
}
if ((pipename) && (strcasecmp(pipename, "STDOUT") == 0))
die("Can't use \"pipe\" backend for STDOUT. Use the \"stdout\" backend instead.");
}
if ((pipename == NULL) && (argc != 1))
+1 -2
View File
@@ -110,8 +110,7 @@ static void deinit(void) {
pa_dev = NULL;
}
static void start(int sample_rate, int sample_format) {
}
static void start(int sample_rate, int sample_format) {}
static void play(short buf[], int samples) {
if (pa_simple_write(pa_dev, (char *)buf, (size_t)samples * 4, &pa_error) < 0) {
+19 -21
View File
@@ -71,23 +71,20 @@ struct sndio_formats {
unsigned int le;
};
static struct sndio_formats formats[] = {
{"S8", SPS_FORMAT_S8, 8, 1, 1, SIO_LE_NATIVE},
{"U8", SPS_FORMAT_U8, 8, 1, 0, SIO_LE_NATIVE},
{"S16", SPS_FORMAT_S16, 16, 2, 1, SIO_LE_NATIVE},
{"S24", SPS_FORMAT_S24, 24, 4, 1, SIO_LE_NATIVE},
{"S24_3LE", SPS_FORMAT_S24_3LE, 24, 3, 1, 1},
{"S24_3BE", SPS_FORMAT_S24_3BE, 24, 3, 1, 0},
{"S32", SPS_FORMAT_S32, 24, 4, 1, SIO_LE_NATIVE}};
static struct sndio_formats formats[] = {{"S8", SPS_FORMAT_S8, 8, 1, 1, SIO_LE_NATIVE},
{"U8", SPS_FORMAT_U8, 8, 1, 0, SIO_LE_NATIVE},
{"S16", SPS_FORMAT_S16, 16, 2, 1, SIO_LE_NATIVE},
{"S24", SPS_FORMAT_S24, 24, 4, 1, SIO_LE_NATIVE},
{"S24_3LE", SPS_FORMAT_S24_3LE, 24, 3, 1, 1},
{"S24_3BE", SPS_FORMAT_S24_3BE, 24, 3, 1, 0},
{"S32", SPS_FORMAT_S32, 24, 4, 1, SIO_LE_NATIVE}};
static void help() {
printf(" -d output-device set the output device [default*|...]\n");
}
static void help() { printf(" -d output-device set the output device [default*|...]\n"); }
static int init(int argc, char **argv) {
int i, found, opt, round, rate, bufsz;
const char *devname, *tmp;
// set up default values first
sio_initpar(&par);
@@ -98,17 +95,17 @@ static int init(int argc, char **argv) {
par.le = 1;
par.sig = 1;
devname = SIO_DEVANY;
config.audio_backend_buffer_desired_length = 1.0;
config.audio_backend_latency_offset = 0;
// get settings from settings file
// get settings from settings file
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
// get the specific settings
if (config.cfg != NULL) {
if (!config_lookup_string(config.cfg, "sndio.device", &devname))
devname = SIO_DEVANY;
@@ -186,8 +183,8 @@ static int init(int argc, char **argv) {
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++) {
if (formats[i].bits == par.bits && formats[i].bps == par.bps &&
formats[i].sig == par.sig && formats[i].le == par.le) {
if (formats[i].bits == par.bits && formats[i].bps == par.bps && formats[i].sig == par.sig &&
formats[i].le == par.le) {
config.output_format = formats[i].fmt;
found = 1;
break;
@@ -255,11 +252,12 @@ static int delay(long *_delay) {
// and use it to estimate the frames that would have been output
uint64_t time_difference = get_absolute_time_in_fp() - time_of_last_onmove_cb;
uint64_t frame_difference = time_difference * par.rate;
uint64_t frame_difference_big_integer = frame_difference>>32;
uint64_t frame_difference_big_integer = frame_difference >> 32;
estimated_extra_frames_output = frame_difference_big_integer;
// debug(1,"Frames played to last cb: %d, estimated to current time: %d.",played,estimated_extra_frames_output);
// debug(1,"Frames played to last cb: %d, estimated to current time:
// %d.",played,estimated_extra_frames_output);
}
*_delay = (written / framesize) - (played+estimated_extra_frames_output);
*_delay = (written / framesize) - (played + estimated_extra_frames_output);
pthread_mutex_unlock(&sndio_mutex);
return 0;
}
+4 -4
View File
@@ -84,17 +84,17 @@ static void underflow_callback(struct SoundIoOutStream *outstream) {
static int init(int argc, char **argv) {
int err;
config.audio_backend_buffer_desired_length = 2.0;
config.audio_backend_latency_offset = 0;
// get settings from settings file
// get settings from settings file
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
// get the specific settings
soundio = soundio_create();
if (!soundio) {
debug(0, "out of memory\n");
+6 -6
View File
@@ -43,10 +43,10 @@ static void start(int sample_rate, int sample_format) { fd = STDOUT_FILENO; }
static void play(short buf[], int samples) {
char errorstring[1024];
int warned = 0;
int rc = write(fd, buf, samples * 4);
if ((rc<0) && (warned==0)) {
strerror_r(errno,(char*)errorstring,1024);
warn("Error %d writing to stdout: \"%s\".",errno,errorstring);
int rc = write(fd, buf, samples * 4);
if ((rc < 0) && (warned == 0)) {
strerror_r(errno, (char *)errorstring, 1024);
warn("Error %d writing to stdout: \"%s\".", errno, errorstring);
warned = 1;
}
}
@@ -59,8 +59,8 @@ static int init(int argc, char **argv) {
// set up default values first
config.audio_backend_buffer_desired_length = 1.0;
config.audio_backend_latency_offset = 0;
// get settings from settings file
// get settings from settings file
// do the "general" audio options. Note, these options are in the "general" stanza!
parse_general_audio_options();
return 0;
+29 -29
View File
@@ -464,41 +464,40 @@ void command_set_volume(double volume) {
/*Spawn a child to run the program.*/
pid_t pid = fork();
if (pid == 0) { /* child process */
size_t command_buffer_size = strlen(config.cmd_set_volume)+32;
char* command_buffer = (char*)malloc(command_buffer_size);
if (command_buffer==NULL) {
inform("Couldn't allocate memory for set_volume argument string");
size_t command_buffer_size = strlen(config.cmd_set_volume) + 32;
char *command_buffer = (char *)malloc(command_buffer_size);
if (command_buffer == NULL) {
inform("Couldn't allocate memory for set_volume argument string");
} else {
memset(command_buffer,0,command_buffer_size);
sprintf(command_buffer, "%s%f", config.cmd_set_volume,volume);
// debug(1,"command_buffer is \"%s\".",command_buffer);
int argC;
char **argV;
// debug(1,"set_volume command found.");
if (poptParseArgvString(command_buffer, &argC, (const char ***)&argV) !=
0) {
// note that argV should be free()'d after use, but we expect this fork to exit
// eventually.
warn("Can't decipher on-set-volume command arguments \"%s\".",command_buffer);
free(argV);
free(command_buffer);
} else {
free(command_buffer);
// debug(1,"Executing on-set-volume command %s with %d arguments.",argV[0],argC);
execv(argV[0], argV);
warn("Execution of on-set-volume command \"%s\" failed to start", config.cmd_set_volume);
// debug(1, "Error executing on-set-volume command %s", config.cmd_set_volume);
exit(127); /* only if execv fails */
}
memset(command_buffer, 0, command_buffer_size);
sprintf(command_buffer, "%s%f", config.cmd_set_volume, volume);
// debug(1,"command_buffer is \"%s\".",command_buffer);
int argC;
char **argV;
// debug(1,"set_volume command found.");
if (poptParseArgvString(command_buffer, &argC, (const char ***)&argV) != 0) {
// note that argV should be free()'d after use, but we expect this fork to exit
// eventually.
warn("Can't decipher on-set-volume command arguments \"%s\".", command_buffer);
free(argV);
free(command_buffer);
} else {
free(command_buffer);
// debug(1,"Executing on-set-volume command %s with %d arguments.",argV[0],argC);
execv(argV[0], argV);
warn("Execution of on-set-volume command \"%s\" failed to start", config.cmd_set_volume);
// debug(1, "Error executing on-set-volume command %s", config.cmd_set_volume);
exit(127); /* only if execv fails */
}
}
} else {
if (config.cmd_blocking) { /* pid!=0 means parent process and if blocking is true, wait for
process to finish */
pid_t rc = waitpid(pid, 0, 0); /* wait for child to exit */
if (rc != pid) {
warn("Execution of on-set-volume command returned an error.");
debug(1, "on-set-volume command %s finished with error %d", config.cmd_set_volume,errno);
debug(1, "on-set-volume command %s finished with error %d", config.cmd_set_volume, errno);
}
}
// debug(1,"Continue after on-set-volume command");
@@ -545,9 +544,10 @@ void command_start(void) {
exit(127); /* only if execv fails */
}
} else {
if (config.cmd_blocking || config.cmd_start_returns_output) { /* pid!=0 means parent process and if blocking is true, wait for
if (config.cmd_blocking || config.cmd_start_returns_output) { /* pid!=0 means parent process
and if blocking is true, wait for
process to finish */
pid_t rc = waitpid(pid, 0, 0); /* wait for child to exit */
pid_t rc = waitpid(pid, 0, 0); /* wait for child to exit */
if (rc != pid) {
warn("Execution of on-start command returned an error.");
debug(1, "on-start command %s finished with error %d", config.cmd_start, errno);
+14 -12
View File
@@ -40,8 +40,8 @@ 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
} type;
ST_soxr, // use libsoxr to make a 352 frame packet one frame longer or shorter
} type;
enum playback_mode_type {
ST_stereo = 0,
@@ -56,7 +56,8 @@ enum decoders_supported_type {
decoder_apple_alac,
} decoders_supported_type;
// the following enum is for the formats recognised -- currently only S16LE is recognised for input, so these are output only for the present
// the following enum is for the formats recognised -- currently only S16LE is recognised for input,
// so these are output only for the present
enum sps_format_t {
SPS_FORMAT_UNKNOWN = 0,
@@ -75,8 +76,9 @@ typedef struct {
char *service_name; // the name for the shairport service, e.g. "Shairport Sync Version %v running
// on host %h"
#ifdef CONFIG_PA
char *pa_application_name; // the name under which Shairport Sync shows up as an "Application" in the Sound Preferences in most desktop Linuxes.
// Defaults to "Shairport Sync". Shairport Sync must be playing to see it.
char *pa_application_name; // the name under which Shairport Sync shows up as an "Application" in
// the Sound Preferences in most desktop Linuxes.
// Defaults to "Shairport Sync". Shairport Sync must be playing to see it.
#endif
#ifdef CONFIG_METADATA
int metadata_enabled;
@@ -114,9 +116,9 @@ typedef struct {
int64_t AirPlayLatency; // supplied with --AirPlayLatency option
int64_t ForkedDaapdLatency; // supplied with --ForkedDaapdLatency option
int daemonise;
int daemonise_store_pid; // don't try to save a PID file
char *piddir;
int logOutputLevel; // log output level
int daemonise_store_pid; // don't try to save a PID file
char *piddir;
int logOutputLevel; // log output level
int statistics_requested, use_negotiated_latencies;
enum playback_mode_type playback_mode;
char *cmd_start, *cmd_stop, *cmd_set_volume;
@@ -143,18 +145,18 @@ typedef struct {
// native range.
enum sps_format_t output_format;
int output_rate;
#ifdef CONFIG_CONVOLUTION
int convolution;
const char* convolution_ir_file;
const char *convolution_ir_file;
float convolution_gain;
int convolution_max_length;
#endif
int loudness;
float loudness_reference_volume_db;
int alsa_use_playback_switch_for_mute;
} shairport_cfg;
// true if Shairport Sync is supposed to be sending output to the output device, false otherwise
+19 -24
View File
@@ -1,54 +1,49 @@
#include "loudness.h"
#include <math.h>
#include "common.h"
#include <math.h>
loudness_processor loudness_r;
loudness_processor loudness_l;
void _loudness_set_volume(loudness_processor *p, float volume)
{
float gain = -(volume-config.loudness_reference_volume_db)*0.5;
void _loudness_set_volume(loudness_processor *p, float volume) {
float gain = -(volume - config.loudness_reference_volume_db) * 0.5;
if (gain < 0)
gain = 0;
float Fc = 10.0;
float Q = 0.5;
// Formula from http://www.earlevel.com/main/2011/01/02/biquad-formulas/
float Fs = 44100.0;
float K = tan(M_PI * Fc / Fs);
float V = pow(10.0, gain / 20.0);
float norm = 1 / (1 + 1/Q * K + K * K);
p->a0 = (1 + V/Q * K + K * K) * norm;
float norm = 1 / (1 + 1 / Q * K + K * K);
p->a0 = (1 + V / Q * K + K * K) * norm;
p->a1 = 2 * (K * K - 1) * norm;
p->a2 = (1 - V/Q * K + K * K) * norm;
p->a2 = (1 - V / Q * K + K * K) * norm;
p->b1 = p->a1;
p->b2 = (1 - 1/Q * K + K * K) * norm;
p->b2 = (1 - 1 / Q * K + K * K) * norm;
}
float loudness_process(loudness_processor *p, float i0)
{
float o0 = p->a0*i0 + p->a1*p->i1 + p->a2*p->i2 - p->b1*p->o1 - p->b2*p->o2;
float loudness_process(loudness_processor *p, float i0) {
float o0 = p->a0 * i0 + p->a1 * p->i1 + p->a2 * p->i2 - p->b1 * p->o1 - p->b2 * p->o2;
p->o2 = p->o1;
p->o1 = o0;
p->i2 = p->i1;
p->i1 = i0;
return o0;
}
void loudness_set_volume(float volume)
{
float gain = -(volume-config.loudness_reference_volume_db)*0.5;
void loudness_set_volume(float volume) {
float gain = -(volume - config.loudness_reference_volume_db) * 0.5;
if (gain < 0)
gain = 0;
inform("Volume: %.1f dB - Loudness gain @10Hz: %.1f dB", volume, gain);
_loudness_set_volume(&loudness_l, volume);
_loudness_set_volume(&loudness_r, volume);
-2
View File
@@ -7,10 +7,8 @@ typedef struct {
float i1, i2, o1, o2;
} loudness_processor;
extern loudness_processor loudness_r;
extern loudness_processor loudness_l;
void loudness_set_volume(float volume);
float loudness_process(loudness_processor *p, float sample);
+2 -2
View File
@@ -24,7 +24,7 @@ typedef struct {
// "sr=44100", "vn=3", "txtvers=1", config.password ? "pw=true" : "pw=false"
#define MDNS_RECORD_WITH_METADATA \
"sf=0x4", "fv=76400.10", "am=ShairportSync", "vs=105.1", "tp=TCP,UDP", "vn=65537", \
"sf=0x4", "fv=76400.10", "am=ShairportSync", "vs=105.1", "tp=TCP,UDP", "vn=65537", \
METADATA_EXPRESSION, "ss=16", "sr=44100", "da=true", "sv=false", "et=0,1", "ek=1", "cn=0,1", \
"ch=2", "txtvers=1", config.password ? "pw=true" : "pw=false"
@@ -35,7 +35,7 @@ typedef struct {
// "txtvers=1", config.password ? "pw=true" : "pw=false"
#define MDNS_RECORD_WITHOUT_METADATA \
"sf=0x4", "fv=76400.10", "am=ShairportSync", "vs=105.1", "tp=TCP,UDP", "vn=65537", "ss=16", \
"sf=0x4", "fv=76400.10", "am=ShairportSync", "vs=105.1", "tp=TCP,UDP", "vn=65537", "ss=16", \
"sr=44100", "da=true", "sv=false", "et=0,1", "ek=1", "cn=0,1", "ch=2", "txtvers=1", \
config.password ? "pw=true" : "pw=false"
+43 -32
View File
@@ -869,13 +869,16 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
(abs_delta << 32) / config.output_rate; // int64_t which is positive
conn->first_packet_time_to_play = reference_timestamp_time - delta_fp_sec;
}
// now, the size of the initial silence must be affected by the lead-in time.
// it must be somewhat less than the lead-in time so that dynamic adjustments can be made
// it must be somewhat less than the lead-in time so that dynamic adjustments can be
// made
// to compensate for delays due to paging, etc.
// The suggestion is that it should be at least 100 ms less than the lead-in time.
int64_t max_dac_delay = config.output_rate / 10; // so the lead-in time must be greater than this, say 0.2 sec, to allow for dynamic adjustment
int64_t max_dac_delay = config.output_rate / 10; // so the lead-in time must be greater
// than this, say 0.2 sec, to allow for
// dynamic adjustment
int64_t filler_size = max_dac_delay; // 0.1 second -- the maximum we'll add to the DAC
if (local_time_now >= conn->first_packet_time_to_play) {
@@ -889,27 +892,29 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
// flush.",(((tn-conn->first_packet_time_to_play)*config.output_rate)>>32)+dac_delay,tn,conn->first_packet_time_to_play,dac_delay,seq_diff(ab_read,
// ab_write));
/*
if (config.output->flush)
config.output->flush();
ab_resync(conn);
conn->first_packet_timestamp = 0;
conn->first_packet_time_to_play = 0;
conn->time_since_play_started = 0;
*/
/*
if (config.output->flush)
config.output->flush();
ab_resync(conn);
conn->first_packet_timestamp = 0;
conn->first_packet_time_to_play = 0;
conn->time_since_play_started = 0;
*/
} else {
// do some calculations
int64_t lead_time = conn->first_packet_time_to_play-local_time_now;
int64_t lead_in_time = (int64_t)(config.audio_backend_silent_lead_in_time*(int64_t)0x100000000);
// debug(1,"Lead time is %llx at fpttp %llx.",lead_time,conn->first_packet_time_to_play);
int64_t lead_time = conn->first_packet_time_to_play - local_time_now;
int64_t lead_in_time =
(int64_t)(config.audio_backend_silent_lead_in_time * (int64_t)0x100000000);
// debug(1,"Lead time is %llx at fpttp
// %llx.",lead_time,conn->first_packet_time_to_play);
// an audio_backend_silent_lead_in_time of less than zero means start filling ASAP
if ((lead_in_time<0) || (lead_time<=lead_in_time)) {
if ((lead_in_time < 0) || (lead_time <= lead_in_time)) {
// debug(1,"Checking");
if (config.output->delay) {
// conn->first_packet_time_to_play is definitely later than local_time_now
if (have_sent_prefiller_silence != 0) {
int resp = config.output->delay(&dac_delay);
if (resp != 0) {
debug(1, "Error %d getting dac_delay in buffer_get_frame.", resp);
dac_delay = 0;
@@ -918,7 +923,8 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
dac_delay = 0;
}
int64_t gross_frame_gap =
((conn->first_packet_time_to_play - local_time_now) * config.output_rate) >> 32;
((conn->first_packet_time_to_play - local_time_now) * config.output_rate) >>
32;
int64_t exact_frame_gap = gross_frame_gap - dac_delay;
if (exact_frame_gap < 0) {
// we've gone past the time...
@@ -937,14 +943,16 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
if (fs > (max_dac_delay - dac_delay))
fs = max_dac_delay - dac_delay;
if (fs < 0) {
debug(2, "frame size (fs) < 0 with max_dac_delay of %lld and dac_delay of %ld",
debug(2,
"frame size (fs) < 0 with max_dac_delay of %lld and dac_delay of %ld",
max_dac_delay, dac_delay);
fs = 0;
}
if ((exact_frame_gap <= fs) ||
(exact_frame_gap <= conn->max_frames_per_packet * 2)) {
fs = exact_frame_gap;
// debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is %d,
// debug(1,"Exact frame gap is %llu; play %d frames of silence. Dac_delay is
// %d,
// with %d packets, ab_read is %04x, ab_write is
// %04x.",exact_frame_gap,fs,dac_delay,seq_diff(ab_read,
// ab_write),ab_read,ab_write);
@@ -954,8 +962,10 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
// if (fs==0)
// debug(2,"Zero length silence buffer needed with gross_frame_gap of %lld and
// dac_delay of %lld.",gross_frame_gap,dac_delay);
// the fs (number of frames of silence to play) can be zero in the DAC doesn't start
// ouotputting frames for a while -- it could get loaded up but not start responding
// the fs (number of frames of silence to play) can be zero in the DAC doesn't
// start
// ouotputting frames for a while -- it could get loaded up but not start
// responding
// for many milliseconds.
if (fs > 0) {
silence = malloc(conn->output_bytes_per_frame * fs);
@@ -963,27 +973,30 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
debug(1, "Failed to allocate %d byte silence buffer.", fs);
else {
memset(silence, 0, conn->output_bytes_per_frame * fs);
// debug(1,"Frames to start: %llu, DAC delay %d, buffer: %d packets.",exact_frame_gap,dac_delay,seq_diff(conn->ab_read, conn->ab_write, conn->ab_read));
// debug(1,"Frames to start: %llu, DAC delay %d, buffer: %d
// packets.",exact_frame_gap,dac_delay,seq_diff(conn->ab_read,
// conn->ab_write, conn->ab_read));
config.output->play(silence, fs);
free(silence);
}
}
have_sent_prefiller_silence = 1; // even if we haven't sent silence because it's zero frames long...
have_sent_prefiller_silence =
1; // even if we haven't sent silence because it's zero frames long...
}
} else {
//no delay function on back end -- just send the prefiller silence
// no delay function on back end -- just send the prefiller silence
// debug(1,"Back end has no delay function.");
// send the appropriate prefiller here...
signed short *silence;
if (lead_time != 0) {
int64_t frame_gap = (lead_time * config.output_rate) >> 32;
// debug(1,"%d frames needed.",frame_gap);
while (frame_gap>0) {
size_t fs = config.output_rate/10;
if (fs>frame_gap)
while (frame_gap > 0) {
size_t fs = config.output_rate / 10;
if (fs > frame_gap)
fs = frame_gap;
silence = malloc(conn->output_bytes_per_frame * fs);
if (silence == NULL)
debug(1, "Failed to allocate %d frame silence buffer.", fs);
@@ -992,7 +1005,6 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
memset(silence, 0, conn->output_bytes_per_frame * fs);
config.output->play(silence, fs);
free(silence);
}
frame_gap -= fs;
}
@@ -1085,7 +1097,6 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
time_to_wait_for_wakeup_fp *= 4 * 352; // four full 352-frame packets
time_to_wait_for_wakeup_fp /= 3; // four thirds of a packet time
#ifdef COMPILE_FOR_LINUX_AND_FREEBSD_AND_CYGWIN
uint64_t time_of_wakeup_fp = local_time_now + time_to_wait_for_wakeup_fp;
uint64_t sec = time_of_wakeup_fp >> 32;
+40 -37
View File
@@ -19,8 +19,8 @@
#include <openssl/aes.h>
#endif
#include "audio.h"
#include "alac.h"
#include "audio.h"
#define time_ping_history 8
@@ -62,8 +62,8 @@ typedef struct {
pthread_t player_thread;
abuf_t audio_buffer[BUFFER_FRAMES];
int max_frames_per_packet,input_num_channels,input_bit_depth,input_rate;
int input_bytes_per_frame,output_bytes_per_frame,output_sample_ratio;
int max_frames_per_packet, input_num_channels, input_bit_depth, input_rate;
int input_bytes_per_frame, output_bytes_per_frame, output_sample_ratio;
int max_frame_size_change;
int64_t previous_random_number;
alac_file *decoder_info;
@@ -73,24 +73,25 @@ typedef struct {
int connection_state_to_output;
int player_thread_please_stop;
int64_t first_packet_time_to_play, time_since_play_started; // nanoseconds
// stats
uint64_t missing_packets, late_packets, too_late_packets, resend_requests;
int decoder_in_use;
// debug variables
int32_t last_seqno_read;
// mutexes and condition variables
pthread_cond_t flowcontrol;
pthread_mutex_t ab_mutex,flush_mutex;
pthread_mutex_t vol_mutex;
int fix_volume;
uint32_t timestamp_epoch, last_timestamp, maximum_timestamp_interval; // timestamp_epoch of zero means not initialised, could start at 2
// or 1.
int ab_buffering,ab_synced;
int64_t first_packet_timestamp;
int flush_requested;
int64_t flush_rtp_timestamp;
uint64_t time_of_last_audio_packet;
seq_t ab_read, ab_write;
// stats
uint64_t missing_packets, late_packets, too_late_packets, resend_requests;
int decoder_in_use;
// debug variables
int32_t last_seqno_read;
// mutexes and condition variables
pthread_cond_t flowcontrol;
pthread_mutex_t ab_mutex, flush_mutex;
pthread_mutex_t vol_mutex;
int fix_volume;
uint32_t timestamp_epoch, last_timestamp,
maximum_timestamp_interval; // timestamp_epoch of zero means not initialised, could start at 2
// or 1.
int ab_buffering, ab_synced;
int64_t first_packet_timestamp;
int flush_requested;
int64_t flush_rtp_timestamp;
uint64_t time_of_last_audio_packet;
seq_t ab_read, ab_write;
#ifdef HAVE_LIBMBEDTLS
mbedtls_aes_context dctx;
@@ -104,7 +105,7 @@ typedef struct {
AES_KEY aes;
#endif
int amountStuffed;
int amountStuffed;
int32_t framesProcessedInThisEpoch;
int32_t framesGeneratedInThisEpoch;
@@ -118,9 +119,9 @@ typedef struct {
char client_ip_string[INET6_ADDRSTRLEN]; // the ip string pointing to the client
char self_ip_string[INET6_ADDRSTRLEN]; // the ip string being used by this program -- it
// could be one of many, so we need to know it
uint32_t self_scope_id; // if it's an ipv6 connection, this will be its scope
short connection_ip_family; // AF_INET / AF_INET6
uint32_t client_active_remote; // used when you want to control the client...
uint32_t self_scope_id; // if it's an ipv6 connection, this will be its scope
short connection_ip_family; // AF_INET / AF_INET6
uint32_t client_active_remote; // used when you want to control the client...
SOCKADDR rtp_client_control_socket; // a socket pointing to the control port of the client
SOCKADDR rtp_client_timing_socket; // a socket pointing to the timing port of the client
@@ -147,27 +148,29 @@ typedef struct {
int timing_sender_stop; // for asking the timing-sending thread to stop
int last_stuff_request;
int64_t play_segment_reference_frame;
uint64_t play_segment_reference_frame_remote_time;
int32_t buffer_occupancy; // allow it to be negative because seq_diff may be negative
int64_t session_corrections;
int play_number_after_flush;
} rtsp_conn_info;
int player_play(pthread_t *thread, rtsp_conn_info* conn);
void player_stop(pthread_t *thread, rtsp_conn_info* conn);
int player_play(pthread_t *thread, rtsp_conn_info *conn);
void player_stop(pthread_t *thread, rtsp_conn_info *conn);
void player_volume(double f, rtsp_conn_info* conn);
void player_flush(int64_t timestamp, rtsp_conn_info* conn);
void player_put_packet(seq_t seqno, int64_t timestamp, uint8_t *data, int len, rtsp_conn_info* conn);
void player_volume(double f, rtsp_conn_info *conn);
void player_flush(int64_t timestamp, rtsp_conn_info *conn);
void player_put_packet(seq_t seqno, int64_t timestamp, uint8_t *data, int len,
rtsp_conn_info *conn);
int64_t monotonic_timestamp(uint32_t timestamp,rtsp_conn_info* conn); // add an epoch to the timestamp. The monotonic
// timestamp guaranteed to start between 2^32 2^33
// frames and continue up to 2^64 frames
int64_t monotonic_timestamp(uint32_t timestamp,
rtsp_conn_info *conn); // add an epoch to the timestamp. The monotonic
// timestamp guaranteed to start between 2^32 2^33
// frames and continue up to 2^64 frames
// which is about 2*10^8 * 1,000 seconds at 384,000 frames per second -- about 2 trillion seconds.
// assumes, without checking, that successive timestamps in a series always span an interval of less
// than one minute.
+54 -46
View File
@@ -42,30 +42,28 @@
#include "player.h"
#include "rtp.h"
void rtp_initialise(rtsp_conn_info* conn) {
void rtp_initialise(rtsp_conn_info *conn) {
conn->rtp_running = 0;
// initialise the timer mutex
// initialise the timer mutex
int rc = pthread_mutex_init(&conn->reference_time_mutex, NULL);
if (rc)
debug(1, "Error initialising reference_time_mutex.");
}
void rtp_terminate(rtsp_conn_info* conn) {
void rtp_terminate(rtsp_conn_info *conn) {
// destroy the timer mutex
// destroy the timer mutex
int rc = pthread_mutex_destroy(&conn->reference_time_mutex);
if (rc)
debug(1, "Error destroying reference_time_mutex variable.");
}
void *rtp_audio_receiver(void* arg) {
void *rtp_audio_receiver(void *arg) {
debug(2, "Audio receiver -- Server RTP thread starting.");
// we inherit the signal mask (SIGUSR1)
rtsp_conn_info *conn = (rtsp_conn_info*)arg;
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
int32_t last_seqno = -1;
uint8_t packet[2048], *pktp;
@@ -131,7 +129,7 @@ void *rtp_audio_receiver(void* arg) {
// debug(3, "RTP: Packets out of sequence: expected: %d, got %d.", last_seqno, seqno);
last_seqno = seqno; // reset warning...
}
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)),conn);
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)), conn);
// if (packet[1]&0x10)
// debug(1,"Audio packet Extension bit set.");
@@ -141,7 +139,7 @@ void *rtp_audio_receiver(void* arg) {
// check if packet contains enough content to be reasonable
if (plen >= 16) {
player_put_packet(seqno, timestamp, pktp, plen,conn);
player_put_packet(seqno, timestamp, pktp, plen, conn);
continue;
}
if (type == 0x56 && seqno == 0) {
@@ -160,12 +158,12 @@ void *rtp_audio_receiver(void* arg) {
return NULL;
}
void *rtp_control_receiver(void* arg) {
void *rtp_control_receiver(void *arg) {
// we inherit the signal mask (SIGUSR1)
debug(2, "Control receiver -- Server RTP thread starting.");
rtsp_conn_info *conn = (rtsp_conn_info*)arg;
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
conn->reference_timestamp = 0; // nothing valid received yet
uint8_t packet[2048], *pktp;
@@ -202,8 +200,8 @@ void *rtp_control_receiver(void* arg) {
// debug(1,"Remote Sync Time: %0llx.",remote_time_of_sync);
rtp_timestamp_less_latency = monotonic_timestamp(ntohl(*((uint32_t *)&packet[4])),conn);
sync_rtp_timestamp = monotonic_timestamp(ntohl(*((uint32_t *)&packet[16])),conn);
rtp_timestamp_less_latency = monotonic_timestamp(ntohl(*((uint32_t *)&packet[4])), conn);
sync_rtp_timestamp = monotonic_timestamp(ntohl(*((uint32_t *)&packet[16])), conn);
if (config.use_negotiated_latencies) {
int64_t la = sync_rtp_timestamp - rtp_timestamp_less_latency + 11025;
@@ -222,7 +220,8 @@ void *rtp_control_receiver(void* arg) {
}
pthread_mutex_lock(&conn->reference_time_mutex);
conn->remote_reference_timestamp_time = remote_time_of_sync;
conn->reference_timestamp_time = remote_time_of_sync - conn->local_to_remote_time_difference;
conn->reference_timestamp_time =
remote_time_of_sync - conn->local_to_remote_time_difference;
conn->reference_timestamp = sync_rtp_timestamp;
pthread_mutex_unlock(&conn->reference_time_mutex);
// debug(1,"New Reference timestamp and timestamp time...");
@@ -242,7 +241,7 @@ void *rtp_control_receiver(void* arg) {
plen -= 4;
seq_t seqno = ntohs(*(unsigned short *)(pktp + 2));
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)),conn);
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)), conn);
pktp += 12;
plen -= 12;
@@ -266,7 +265,7 @@ void *rtp_control_receiver(void* arg) {
void *rtp_timing_sender(void *arg) {
debug(2, "Timing sender thread starting.");
rtsp_conn_info *conn = (rtsp_conn_info*)arg;
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
struct timing_request {
char leader;
char type;
@@ -306,8 +305,8 @@ void *rtp_timing_sender(void *arg) {
msgsize = sizeof(struct sockaddr_in6);
}
#endif
if (sendto(conn->timing_socket, &req, sizeof(req), 0, (struct sockaddr *)&conn->rtp_client_timing_socket,
msgsize) == -1) {
if (sendto(conn->timing_socket, &req, sizeof(req), 0,
(struct sockaddr *)&conn->rtp_client_timing_socket, msgsize) == -1) {
perror("Error sendto-ing to timing socket");
}
request_number++;
@@ -323,7 +322,7 @@ void *rtp_timing_sender(void *arg) {
void *rtp_timing_receiver(void *arg) {
debug(2, "Timing receiver -- Server RTP thread starting.");
// we inherit the signal mask (SIGUSR1)
rtsp_conn_info *conn = (rtsp_conn_info*)arg;
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
uint8_t packet[2048], *pktp;
ssize_t nread;
@@ -391,11 +390,11 @@ void *rtp_timing_receiver(void *arg) {
uint64_t local_time_by_remote_clock = distant_transmit_time + return_time / 2;
unsigned int cc,chosen;
unsigned int cc, chosen;
for (cc = time_ping_history - 1; cc > 0; cc--) {
conn->time_pings[cc] = conn->time_pings[cc - 1];
conn->time_pings[cc].dispersion = (conn->time_pings[cc].dispersion * 110) /
100; // make the dispersions 'age' by this rational factor
100; // make the dispersions 'age' by this rational factor
}
// these are for diagnostics only -- not used
conn->time_pings[0].local_time = arrival_time;
@@ -463,9 +462,8 @@ void *rtp_timing_receiver(void *arg) {
clock_drift_in_usec = (clock_drift * 1000000) >> 32;
else
clock_drift_in_usec = -(((-clock_drift) * 1000000) >> 32);
clock_drift_ppm = (1.0*clock_drift_in_usec)/(local_time_change>>32);
}
clock_drift_ppm = (1.0 * clock_drift_in_usec) / (local_time_change >> 32);
}
int64_t source_drift_usec;
if (conn->play_segment_reference_frame != 0) {
@@ -475,15 +473,16 @@ void *rtp_timing_receiver(void *arg) {
&remote_reference_timestamp_time, conn);
uint64_t frame_difference = 0;
if (reference_timestamp >= conn->play_segment_reference_frame)
frame_difference = (uint64_t)reference_timestamp - (uint64_t)conn->play_segment_reference_frame;
else // rollover
frame_difference =
(uint64_t)reference_timestamp + 0x100000000 - (uint64_t)conn->play_segment_reference_frame;
(uint64_t)reference_timestamp - (uint64_t)conn->play_segment_reference_frame;
else // rollover
frame_difference = (uint64_t)reference_timestamp + 0x100000000 -
(uint64_t)conn->play_segment_reference_frame;
uint64_t frame_time_difference_calculated = (((uint64_t)frame_difference << 32) / 44100);
uint64_t frame_time_difference_actual =
remote_reference_timestamp_time -
conn->play_segment_reference_frame_remote_time; // this is all done by reference to the
// sources' system clock
// sources' system clock
// debug(1,"%llu frames since play started, %llu usec calculated, %llu usec
// actual",frame_difference, (frame_time_difference_calculated*1000000)>>32,
// (frame_time_difference_actual*1000000)>>32);
@@ -505,13 +504,14 @@ void *rtp_timing_receiver(void *arg) {
// config.output->delay(&current_delay);
//}
// Useful for troubleshooting:
//debug(1, "clock_drift_ppm %f\tchosen %5d\tsource_drift_usec %10.1lld\treturn_time_in_usec %10.1llu",
//clock_drift_ppm,
//chosen,
// debug(1, "clock_drift_ppm %f\tchosen %5d\tsource_drift_usec %10.1lld\treturn_time_in_usec
// %10.1llu",
// clock_drift_ppm,
// chosen,
//(session_corrections*1000000)/44100,
//current_delay,
//source_drift_usec,
//buffer_occupancy,
// current_delay,
// source_drift_usec,
// buffer_occupancy,
//(return_time*1000000)>>32);
} else {
@@ -568,7 +568,8 @@ static int bind_port(int ip_family, const char *self_ip_address, uint32_t scope_
if (ret < 0) {
close(local_socket);
die("error: could not bind a UDP port! Check the udp_port_range is large enough (>= 10) or check for restrictive firewall settings or a bad router!");
die("error: could not bind a UDP port! Check the udp_port_range is large enough (>= 10) or "
"check for restrictive firewall settings or a bad router!");
}
int sport;
@@ -610,7 +611,8 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int cport, int tport, uint32_t
char client_port_str[64];
char self_addr_str[64];
conn->connection_ip_family = remote->SAFAMILY; // keep information about the kind of ip of the client
conn->connection_ip_family =
remote->SAFAMILY; // keep information about the kind of ip of the client
#ifdef AF_INET6
if (conn->connection_ip_family == AF_INET6) {
@@ -632,10 +634,13 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int cport, int tport, uint32_t
self_port = ntohs(sa4->sin_port);
}
inet_ntop(conn->connection_ip_family, client_addr, conn->client_ip_string, sizeof(conn->client_ip_string));
inet_ntop(conn->connection_ip_family, self_addr, conn->self_ip_string, sizeof(conn->self_ip_string));
inet_ntop(conn->connection_ip_family, client_addr, conn->client_ip_string,
sizeof(conn->client_ip_string));
inet_ntop(conn->connection_ip_family, self_addr, conn->self_ip_string,
sizeof(conn->self_ip_string));
debug(1, "Set up play connection from %s to self at %s.", conn->client_ip_string, conn->self_ip_string);
debug(1, "Set up play connection from %s to self at %s.", conn->client_ip_string,
conn->self_ip_string);
// set up a the record of the remote's control socket
struct addrinfo hints;
@@ -683,9 +688,12 @@ void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int cport, int tport, uint32_t
// now, we open three sockets -- one for the audio stream, one for the timing and one for the
// control
*lsport = bind_port(conn->connection_ip_family, conn->self_ip_string, conn->self_scope_id, &conn->audio_socket);
*lcport = bind_port(conn->connection_ip_family, conn->self_ip_string, conn->self_scope_id, &conn->control_socket);
*ltport = bind_port(conn->connection_ip_family, conn->self_ip_string, conn->self_scope_id, &conn->timing_socket);
*lsport = bind_port(conn->connection_ip_family, conn->self_ip_string, conn->self_scope_id,
&conn->audio_socket);
*lcport = bind_port(conn->connection_ip_family, conn->self_ip_string, conn->self_scope_id,
&conn->control_socket);
*ltport = bind_port(conn->connection_ip_family, conn->self_ip_string, conn->self_scope_id,
&conn->timing_socket);
debug(2, "listening for audio, control and timing on ports %d, %d, %d.", *lsport, *lcport,
*ltport);
@@ -752,8 +760,8 @@ void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn) {
msgsize = sizeof(struct sockaddr_in6);
}
#endif
if (sendto(conn->audio_socket, req, sizeof(req), 0, (struct sockaddr *)&conn->rtp_client_control_socket,
msgsize) == -1) {
if (sendto(conn->audio_socket, req, sizeof(req), 0,
(struct sockaddr *)&conn->rtp_client_control_socket, msgsize) == -1) {
perror("Error sendto-ing to audio socket");
}
} else {
+8 -8
View File
@@ -5,8 +5,8 @@
#include "player.h"
void rtp_initialise(rtsp_conn_info* conn);
void rtp_terminate(rtsp_conn_info* conn);
void rtp_initialise(rtsp_conn_info *conn);
void rtp_terminate(rtsp_conn_info *conn);
void *rtp_audio_receiver(void *arg);
void *rtp_control_receiver(void *arg);
@@ -14,14 +14,14 @@ void *rtp_timing_receiver(void *arg);
void rtp_setup(SOCKADDR *local, SOCKADDR *remote, int controlport, int timingport,
uint32_t active_remote, int *local_server_port, int *local_control_port,
int *local_timing_port, rtsp_conn_info* conn);
void rtp_shutdown(rtsp_conn_info* conn);
void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info* conn);
void rtp_request_client_pause(rtsp_conn_info* conn); // ask the client to pause
int *local_timing_port, rtsp_conn_info *conn);
void rtp_shutdown(rtsp_conn_info *conn);
void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn);
void rtp_request_client_pause(rtsp_conn_info *conn); // ask the client to pause
void get_reference_timestamp_stuff(int64_t *timestamp, uint64_t *timestamp_time,
uint64_t *remote_timestamp_time, rtsp_conn_info* conn);
void clear_reference_timestamp(rtsp_conn_info* conn);
uint64_t *remote_timestamp_time, rtsp_conn_info *conn);
void clear_reference_timestamp(rtsp_conn_info *conn);
uint64_t static local_to_remote_time_jitters;
uint64_t static local_to_remote_time_jitters_count;
+37 -36
View File
@@ -646,7 +646,7 @@ static void handle_record(rtsp_conn_info *conn, rtsp_message *req, rtsp_message
rtptime = uatoi(p + 1); // unsigned integer -- up to 2^32-1
rtptime--;
// debug(1,"RTSP Flush Requested by handle_record: %u.",rtptime);
player_flush(rtptime,conn);
player_flush(rtptime, conn);
}
}
}
@@ -665,7 +665,7 @@ static void handle_teardown(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
"it's sending a response to teardown anyway");
resp->respcode = 200;
msg_add_header(resp, "Connection", "close");
debug(2,"TEARDOWN asking connection to stop");
debug(2, "TEARDOWN asking connection to stop");
conn->stop = 1;
}
@@ -687,14 +687,14 @@ static void handle_flush(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
rtptime = uatoi(p + 1); // unsigned integer -- up to 2^32-1
}
}
// debug(1,"RTSP Flush Requested: %u.",rtptime);
#ifdef CONFIG_METADATA
// debug(1,"RTSP Flush Requested: %u.",rtptime);
#ifdef CONFIG_METADATA
if (p)
send_metadata('ssnc', 'flsr', p, strlen(p), req, 1);
else
send_metadata('ssnc', 'flsr', NULL, 0, NULL,0);
#endif
player_flush(rtptime,conn);
send_metadata('ssnc', 'flsr', NULL, 0, NULL, 0);
#endif
player_flush(rtptime, conn);
resp->respcode = 200;
}
@@ -799,7 +799,8 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
tport = atoi(p);
// rtsp_take_player();
rtp_setup(&conn->local, &conn->remote, cport, tport, active_remote, &lsport, &lcport, &ltport, conn);
rtp_setup(&conn->local, &conn->remote, cport, tport, active_remote, &lsport, &lcport, &ltport,
conn);
if (!lsport)
goto error;
char *q;
@@ -818,7 +819,7 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
strcat(hdr, q); // should unsplice the timing port entry
}
player_play(&conn->player_thread,conn); // the thread better be 0
player_play(&conn->player_thread, conn); // the thread better be 0
char *resphdr = alloca(200);
*resphdr = 0;
@@ -857,7 +858,7 @@ static void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *r
if (!strncmp(cp, "volume: ", 8)) {
float volume = atof(cp + 8);
// debug(1, "AirPlay request to set volume to: %f\n", volume);
player_volume(volume,conn);
player_volume(volume, conn);
} else
#ifdef CONFIG_METADATA
if (!strncmp(cp, "progress: ", 10)) {
@@ -943,13 +944,10 @@ static void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *r
// `clip` -- the payload is the IP number of the client, i.e. the sender of audio.
// Can be an IPv4 or an IPv6 number.
// A special sub-protocol is used for sending large data items over UDP
// If the payload exceeded 4 MB, it is chunked using the following format:
// "ssnc", "chnk", packet_ix, packet_counts, packet_tag, packet_type, chunked_data.
// Notice that the number of items is different to the standard
// Notice that the number of items is different to the standard
// including a simple base64 encoder to minimise malloc/free activity
@@ -1093,15 +1091,15 @@ void metadata_process(uint32_t type, uint32_t code, char *data, uint32_t length)
} else if (metadata_sock >= 0) {
// send metadata in numbered chunks using the protocol:
// ("ssnc", "chnk", packet_ix, packet_counts, packet_tag, packet_type, chunked_data)
uint32_t chunk_ix = 0;
uint32_t chunk_total = length / (config.metadata_sockmsglength - 24);
if (chunk_total * (config.metadata_sockmsglength - 24) < length) {
chunk_total++;
chunk_total++;
}
uint32_t remaining = length;
uint32_t v;
char* data_crsr = data;
char *data_crsr = data;
do {
char *ptr = metadata_sockmsg;
memcpy(ptr, "ssncchnk", 8);
@@ -1120,15 +1118,16 @@ void metadata_process(uint32_t type, uint32_t code, char *data, uint32_t length)
ptr += 4;
uint32_t datalen = remaining;
if (datalen > config.metadata_sockmsglength - 24) {
datalen = config.metadata_sockmsglength - 24;
datalen = config.metadata_sockmsglength - 24;
}
memcpy(ptr, data_crsr, datalen);
data_crsr += datalen;
sendto(metadata_sock, metadata_sockmsg, datalen + 24, 0, (struct sockaddr *)&metadata_sockaddr,
sizeof(metadata_sockaddr));
sendto(metadata_sock, metadata_sockmsg, datalen + 24, 0,
(struct sockaddr *)&metadata_sockaddr, sizeof(metadata_sockaddr));
chunk_ix++;
remaining -= datalen;
if (remaining == 0) break;
if (remaining == 0)
break;
} while (1);
}
@@ -1400,14 +1399,15 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
if (config.allow_session_interruption == 1) {
// some other thread has the player ... ask it to relinquish the thread
if (playing_conn) {
debug(1,"Playing connection asked to stop");
if (playing_conn==conn) {
debug(1,"ANNOUNCE asking to stop itself.");
debug(1, "Playing connection asked to stop");
if (playing_conn == conn) {
debug(1, "ANNOUNCE asking to stop itself.");
} else {
playing_conn->stop = 1;
memory_barrier();
pthread_kill(playing_conn->thread, SIGUSR1);
usleep(1000000); // here, it is possible for other connections to come in and nab the player.
usleep(
1000000); // here, it is possible for other connections to come in and nab the player.
}
} else {
die("Non existent the_playing_conn with play_lock enabled.");
@@ -1417,7 +1417,7 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
if (pthread_mutex_trylock(&play_lock) == 0)
have_the_player = 1;
else
debug(1,"ANNOUNCE failed to get the player");
debug(1, "ANNOUNCE failed to get the player");
}
}
@@ -1496,7 +1496,7 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
conn->stream.fmtp[i] = atoi(strsep(&pfmtp, " \t"));
// here we should check the sanity ot the fmtp values
//for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
// for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
// debug(1," fmtp[%2d] is: %10d",i,conn->stream.fmtp[i]);
char *hdr = msg_get_header(req, "X-Apple-Client-Name");
@@ -1762,7 +1762,7 @@ static void *rtsp_conversation_thread_func(void *pconn) {
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
rtsp_conn_info *conn = pconn;
rtp_initialise(conn);
rtsp_message *req, *resp;
@@ -1812,7 +1812,7 @@ static void *rtsp_conversation_thread_func(void *pconn) {
debug(1, "Closing down RTSP conversation thread...");
if (rtsp_playing()) {
player_stop(&conn->player_thread,conn); // might be less noisy doing this first
player_stop(&conn->player_thread, conn); // might be less noisy doing this first
rtp_shutdown(conn);
// usleep(400000); // let an angel pass...
pthread_mutex_unlock(&play_lock);
@@ -1974,7 +1974,7 @@ void rtsp_listen_loop(void) {
continue;
rtsp_conn_info *conn = malloc(sizeof(rtsp_conn_info));
if (conn==0)
if (conn == 0)
die("Couldn't allocate memory for an rtsp_conn_info record.");
memset(conn, 0, sizeof(rtsp_conn_info));
socklen_t slen = sizeof(conn->remote);
@@ -2033,13 +2033,14 @@ void rtsp_listen_loop(void) {
} else {
debug(1, "Error figuring out Shairport Sync's own IP number.");
}
// usleep(500000);
// pthread_t rtsp_conversation_thread;
// conn->thread = rtsp_conversation_thread;
// conn->stop = 0; // record's memory has been zeroed
// conn->authorized = 0; // record's memory has been zeroed
// usleep(500000);
// pthread_t rtsp_conversation_thread;
// conn->thread = rtsp_conversation_thread;
// conn->stop = 0; // record's memory has been zeroed
// conn->authorized = 0; // record's memory has been zeroed
conn->running = 1;
ret = pthread_create(&conn->thread, NULL, rtsp_conversation_thread_func, conn); // also acts as a memory barrier
ret = pthread_create(&conn->thread, NULL, rtsp_conversation_thread_func,
conn); // also acts as a memory barrier
if (ret)
die("Failed to create RTSP receiver thread!");
track_thread(conn);
+57 -46
View File
@@ -254,8 +254,9 @@ void usage(char *progname) {
"88) before trying to correct it.\n");
printf(" --password=PASSWORD require PASSWORD to connect. Default is not to require a "
"password.\n");
printf(" --logOutputLevel log the output level setting -- useful for setting maximum volume.\n");
#ifdef CONFIG_METADATA
printf(" --logOutputLevel log the output level setting -- useful for setting maximum "
"volume.\n");
#ifdef CONFIG_METADATA
printf(" --metadata-pipename=PIPE send metadata to PIPE, e.g. "
"--metadata-pipename=/tmp/shairport-sync-metadata.\n");
printf(" The default is /tmp/shairport-sync-metadata.\n");
@@ -285,7 +286,7 @@ int parse_options(int argc, char **argv) {
{"reconnectToOutput", 'R', POPT_ARG_NONE, NULL, 0, NULL},
{"kill", 'k', POPT_ARG_NONE, NULL, 0, NULL},
{"daemon", 'd', POPT_ARG_NONE, &daemonisewith, 0, NULL},
{"justDaemoniseNoPIDFile", 'j', POPT_ARG_NONE,&daemonisewithout, 0, NULL},
{"justDaemoniseNoPIDFile", 'j', POPT_ARG_NONE, &daemonisewithout, 0, NULL},
{"configfile", 'c', POPT_ARG_STRING, &config.configfile, 0, NULL},
{"statistics", 0, POPT_ARG_NONE, &config.statistics_requested, 0, NULL},
{"logOutputLevel", 0, POPT_ARG_NONE, &config.logOutputLevel, 0, NULL},
@@ -363,17 +364,18 @@ int parse_options(int argc, char **argv) {
}
if ((daemonisewith) && (daemonisewithout))
die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected both!");
die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected "
"both!");
if ((daemonisewith) || (daemonisewithout)) {
config.daemonise = 1;
if (daemonisewith)
config.daemonise_store_pid = 1;
};
};
config.resyncthreshold = 1.0 * fResyncthreshold / 44100;
config.tolerance = 1.0 * fTolerance / 44100;
config.audio_backend_silent_lead_in_time = -1.0; // flag to indicate it has not been set
config_setting_t *setting;
const char *str = 0;
int value = 0;
@@ -405,7 +407,8 @@ int parse_options(int argc, char **argv) {
else if (strcasecmp(str, "yes") == 0)
daemonisewith = 1;
else
die("Invalid daemonize_with_pid_file option choice \"%s\". It should be \"yes\" or \"no\"");
die("Invalid daemonize_with_pid_file option choice \"%s\". It should be \"yes\" or "
"\"no\"");
}
/* Get the Just_Daemonize setting. */
@@ -415,15 +418,17 @@ int parse_options(int argc, char **argv) {
else if (strcasecmp(str, "yes") == 0)
daemonisewithout = 1;
else
die("Invalid daemonize_without_pid_file option choice \"%s\". It should be \"yes\" or \"no\"");
die("Invalid daemonize_without_pid_file option choice \"%s\". It should be \"yes\" or "
"\"no\"");
}
if ((daemonisewith) && (daemonisewithout))
die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have selected both!");
die("Select either daemonize_with_pid_file or daemonize_without_pid_file -- you have "
"selected both!");
if ((daemonisewith) || (daemonisewithout)) {
config.daemonise = 1;
if (daemonisewith)
config.daemonise_store_pid = 1;
}
}
/* Get the directory path for the pid file created when the program is daemonised. */
if (config_lookup_string(config.cfg, "sessioncontrol.daemon_pid_dir", &str))
config.piddir = (char *)str;
@@ -695,13 +700,15 @@ int parse_options(int argc, char **argv) {
"\"yes\" or \"no\"");
}
if (config_lookup_string(config.cfg, "sessioncontrol.before_play_begins_returns_output", &str)) {
if (config_lookup_string(config.cfg, "sessioncontrol.before_play_begins_returns_output",
&str)) {
if (strcasecmp(str, "no") == 0)
config.cmd_start_returns_output = 0;
else if (strcasecmp(str, "yes") == 0)
config.cmd_start_returns_output = 1;
else
die("Invalid session control before_play_begins_returns_output option choice \"%s\". It should be "
die("Invalid session control before_play_begins_returns_output option choice \"%s\". It "
"should be "
"\"yes\" or \"no\"");
}
@@ -721,9 +728,9 @@ int parse_options(int argc, char **argv) {
config.timeout = value;
config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0
}
#ifdef CONFIG_CONVOLUTION
if (config_lookup_string(config.cfg, "dsp.convolution", &str)) {
if (strcasecmp(str, "no") == 0)
config.convolution = 0;
@@ -731,33 +738,33 @@ int parse_options(int argc, char **argv) {
config.convolution = 1;
else
die("Invalid dsp.convolution. It should be \"yes\" or \"no\"");
}
if (config_lookup_float(config.cfg, "dsp.convolution_gain", &dvalue)) {
config.convolution_gain = dvalue;
if (dvalue > 10 || dvalue < -50)
die("Invalid value \"%f\" for dsp.convolution_gain. It should be between -50 and +10 dB", dvalue);
die("Invalid value \"%f\" for dsp.convolution_gain. It should be between -50 and +10 dB",
dvalue);
}
config.convolution_max_length = 8192;
if (config_lookup_int(config.cfg, "dsp.convolution_max_length", &value)) {
config.convolution_max_length = value;
if (value < 1 || value > 200000)
die("dsp.convolution_max_length must be within 1 and 200000");
}
if (config_lookup_string(config.cfg, "dsp.convolution_ir_file", &str)) {
config.convolution_ir_file = str;
convolver_init(config.convolution_ir_file, config.convolution_max_length);
}
if (config.convolution && config.convolution_ir_file == NULL) {
die("Convolution enabled but no convolution_ir_file provided");
}
#endif
if (config_lookup_string(config.cfg, "dsp.loudness", &str)) {
if (strcasecmp(str, "no") == 0)
config.loudness = 0;
@@ -766,17 +773,20 @@ int parse_options(int argc, char **argv) {
else
die("Invalid dsp.convolution. It should be \"yes\" or \"no\"");
}
config.loudness_reference_volume_db = -20;
if (config_lookup_float(config.cfg, "dsp.loudness_reference_volume_db", &dvalue)) {
config.loudness_reference_volume_db = dvalue;
if (dvalue > 0 || dvalue < -100)
die("Invalid value \"%f\" for dsp.loudness_reference_volume_db. It should be between -100 and 0", dvalue);
die("Invalid value \"%f\" for dsp.loudness_reference_volume_db. It should be between "
"-100 and 0",
dvalue);
}
if (config.loudness == 1 && config_lookup_string(config.cfg, "alsa.mixer_control_name", &str))
die("Loudness activated but hardware volume is active. You must remove \"alsa.mixer_control_name\" to use the loudness filter.");
die("Loudness activated but hardware volume is active. You must remove "
"\"alsa.mixer_control_name\" to use the loudness filter.");
} else {
if (config_error_type(&config_file_stuff) == CONFIG_ERR_FILE_IO)
debug(1, "Error reading configuration file \"%s\": \"%s\".",
@@ -924,21 +934,20 @@ void shairport_startup_complete(void) {
}
}
const char *pid_file_proc(void) {
#ifdef USE_CUSTOM_PID_DIR
char * use_this_pid_dir = PIDDIR;
#else
char * use_this_pid_dir = "/var/run/shairport-sync";
#endif
// debug(1,"config.piddir \"%s\".",config.piddir);
if (config.piddir)
use_this_pid_dir = config.piddir;
char fn[8192];
snprintf(fn, sizeof(fn), "%s/%s.pid", use_this_pid_dir,
daemon_pid_file_ident ? daemon_pid_file_ident : "unknown");
//debug(1,"fn \"%s\".",fn);
return strdup(fn);
#ifdef USE_CUSTOM_PID_DIR
char *use_this_pid_dir = PIDDIR;
#else
char *use_this_pid_dir = "/var/run/shairport-sync";
#endif
// debug(1,"config.piddir \"%s\".",config.piddir);
if (config.piddir)
use_this_pid_dir = config.piddir;
char fn[8192];
snprintf(fn, sizeof(fn), "%s/%s.pid", use_this_pid_dir,
daemon_pid_file_ident ? daemon_pid_file_ident : "unknown");
// debug(1,"fn \"%s\".",fn);
return strdup(fn);
}
void exit_function() {
@@ -982,7 +991,8 @@ int main(int argc, char **argv) {
die("Can not recognise the endianness of the processor.");
strcpy(configuration_file_path, SYSCONFDIR);
// strcat(configuration_file_path, "/shairport-sync"); // thinking about adding a special shairport-sync directory
// strcat(configuration_file_path, "/shairport-sync"); // thinking about adding a special
// shairport-sync directory
strcat(configuration_file_path, "/");
strcat(configuration_file_path, appName);
strcat(configuration_file_path, ".conf");
@@ -1102,7 +1112,7 @@ int main(int argc, char **argv) {
// parse arguments into config -- needed to locate pid_dir
int audio_arg = parse_options(argc, argv);
/* Check if we are called with -k or --kill parameter */
/* Check if we are called with -k or --kill parameter */
if (argc >= 2 && ((strcmp(argv[1], "-k") == 0) || (strcmp(argv[1], "--kill") == 0))) {
int ret;
@@ -1279,7 +1289,7 @@ int main(int argc, char **argv) {
/* Print out options */
debug(1, "statistics_requester status is %d.", config.statistics_requested);
debug(1, "daemon status is %d.", config.daemonise);
debug(1, "deamon pid file is \"%s\".",pid_file_proc());
debug(1, "deamon pid file is \"%s\".", pid_file_proc());
debug(1, "rtsp listening port is %d.", config.port);
debug(1, "udp base port is %d.", config.udp_port_base);
debug(1, "udp port range is %d.", config.udp_port_range);
@@ -1316,7 +1326,8 @@ int main(int argc, char **argv) {
debug(1, "audio backend desired buffer length is %f seconds.",
config.audio_backend_buffer_desired_length);
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);
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);
debug(1, "volume range in dB (zero means use the range specified by the mixer): %u.",
config.volume_range_db);
debug(1, "zeroconf regtype is \"%s\".", config.regtype);
@@ -1352,7 +1363,7 @@ int main(int argc, char **argv) {
#endif
debug(1, "loudness is %d.", config.loudness);
debug(1, "loudness reference level is %f", config.loudness_reference_volume_db);
uint8_t ap_md5[16];
#ifdef HAVE_LIBSSL