debug(1, "Error %d in delay(): \"%s\". Delay reported is %d frames.", reply,
snd_strerror(reply), *the_delay);
derr = snd_pcm_recover(alsa_handle, reply, 1);
- if (derr < 0)
- warn("Error %d -- could not clear an error after attempting delay(): \"%s\".", derr,
- snd_strerror(derr));
+ if (derr < 0)
+ warn("Error %d -- could not clear an error after attempting delay(): \"%s\".", derr,
+ snd_strerror(derr));
frame_index = 0;
measurement_data_is_valid = 0;
if ((derr = snd_pcm_prepare(alsa_handle))) {
debug(1, "Error preparing after delay error: \"%s\".", snd_strerror(derr));
derr = snd_pcm_recover(alsa_handle, derr, 1);
- if (derr < 0)
- warn("Error %d -- could not clear an error after attempting to recover following a delay(): \"%s\".", derr,
- snd_strerror(derr));
+ if (derr < 0)
+ warn("Error %d -- could not clear an error after attempting to recover following a "
+ "delay(): \"%s\".",
+ derr, snd_strerror(derr));
}
}
}
if (snd_pcm_state(alsa_handle) == SND_PCM_STATE_XRUN) {
if ((err = snd_pcm_prepare(alsa_handle))) {
debug(1, "Error preparing after underrun: \"%s\".", snd_strerror(err));
- err = snd_pcm_recover(alsa_handle, err, 1);
- if (err < 0)
- warn("Error %d -- could not clear an error after detecting underrun in play(): \"%s\".", err,
- snd_strerror(err));
+ err = snd_pcm_recover(alsa_handle, err, 1);
+ if (err < 0)
+ warn("Error %d -- could not clear an error after detecting underrun in play(): \"%s\".",
+ err, snd_strerror(err));
}
frame_index = 0; // we'll be starting over
measurement_data_is_valid = 0;
debug(1, "Error %d writing %d samples in play(): \"%s\".", err, samples,
snd_strerror(err));
err = snd_pcm_recover(alsa_handle, err, 1);
- if (err < 0)
- warn("Error %d -- could not clear an error after attempting to write %d samples in play(): \"%s\".", err, samples,
- snd_strerror(err));
+ if (err < 0)
+ warn("Error %d -- could not clear an error after attempting to write %d samples in "
+ "play(): \"%s\".",
+ err, samples, snd_strerror(err));
}
if (frame_index == 0) {
frames_sent_for_playing = samples;
debug(1, "Error %d in delay in play(): \"%s\". Delay reported is %d frames.", err2,
snd_strerror(err2), fl);
err2 = snd_pcm_recover(alsa_handle, err2, 1);
- if (err2 < 0)
- warn("Error %d -- could not clear an error after checking delay in play(): \"%s\".", err2,
- snd_strerror(err2));
+ if (err2 < 0)
+ warn("Error %d -- could not clear an error after checking delay in play(): \"%s\".",
+ err2, snd_strerror(err2));
frame_index = 0;
measurement_data_is_valid = 0;
} else {
if ((err = snd_pcm_prepare(alsa_handle))) {
debug(1, "Error preparing after play error: \"%s\".", snd_strerror(err));
err2 = snd_pcm_recover(alsa_handle, err, 1);
- if (err2 < 0)
- warn("Error %d -- could not clear an error after reporting ALSA device in incorrect state for play: \"%s\".", err2,
- snd_strerror(err2));
+ if (err2 < 0)
+ warn("Error %d -- could not clear an error after reporting ALSA device in incorrect "
+ "state for play: \"%s\".",
+ err2, snd_strerror(err2));
}
frame_index = 0;
measurement_data_is_valid = 0;
daemon_log(LOG_EMERG, "% 20.9f|*fatal error: %s", tss, s);
else
daemon_log(LOG_EMERG, "fatal error: %s", s);
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
exit(1);
}
daemon_log(LOG_WARNING, "% 20.9f|*warning: %s", tss, s);
else
daemon_log(LOG_WARNING, "%s", s);
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
}
void debug(int level, const char *format, ...) {
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, ¤tState);
if (currentState == PTHREAD_CANCEL_ENABLE)
daemon_log(LOG_DEBUG, "Warning -- cancellation is enabled after logging");
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
}
void inform(const char *format, ...) {
daemon_log(LOG_INFO, "% 20.9f|%s", tss, s);
else
daemon_log(LOG_INFO, "%s", s);
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
}
// The following two functions are adapted slightly and with thanks from Jonathan Leffler's sample
}
void command_set_volume(double volume) {
-//this has a cancellation point if waiting is enabled
+ // this has a cancellation point if waiting is enabled
if (config.cmd_set_volume) {
/*Spawn a child to run the program.*/
pid_t pid = fork();
}
void command_start(void) {
- //this has a cancellation point if waiting is enabled or a response is awaited
+ // this has a cancellation point if waiting is enabled or a response is awaited
if (config.cmd_start) {
pid_t pid;
int pipes[2];
}
void command_stop(void) {
-//this has a cancellation point if waiting is enabled
+ // this has a cancellation point if waiting is enabled
if (config.cmd_stop) {
/*Spawn a child to run the program.*/
pid_t pid = fork();
debug(debuglevel, "error %d: \"%s\" waiting for a mutex: \"%s\".", r,
strerror_r(r, errstr, sizeof(errstr)), debugmessage);
}
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
return r;
}
#endif
strerror_r(r, errstr, sizeof(errstr)), debugmessage);
}
}
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
return r;
}
#endif
-int _debug_mutex_lock(pthread_mutex_t *mutex, useconds_t dally_time, const char *mutexname, const char *filename,
- const int line, int debuglevel) {
+int _debug_mutex_lock(pthread_mutex_t *mutex, useconds_t dally_time, const char *mutexname,
+ const char *filename, const int line, int debuglevel) {
if ((debuglevel > debuglev) || (debuglevel == 0))
return pthread_mutex_lock(mutex);
int oldState;
uint64_t divisor = (uint64_t)1 << 32;
double delay = 1.0 * time_delay / divisor;
debug(debuglevel,
- "mutex_lock \"%s\" at \"%s\" expected max wait: %0.9f, actual wait: %0.9f sec.", mutexname, dstring,
- (1.0 * dally_time) / 1000000, delay);
+ "mutex_lock \"%s\" at \"%s\" expected max wait: %0.9f, actual wait: %0.9f sec.",
+ mutexname, dstring, (1.0 * dally_time) / 1000000, delay);
}
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
return result;
}
-int _debug_mutex_unlock(pthread_mutex_t *mutex, const char *mutexname, const char *filename, const int line,
- int debuglevel) {
+int _debug_mutex_unlock(pthread_mutex_t *mutex, const char *mutexname, const char *filename,
+ const int line, int debuglevel) {
if ((debuglevel > debuglev) || (debuglevel == 0))
return pthread_mutex_unlock(mutex);
int oldState;
if ((debuglevel != 0) && (r != 0))
debug(1, "error %d: \"%s\" unlocking mutex \"%s\" at \"%s\".", r,
strerror_r(r, errstr, sizeof(errstr)), mutexname, dstring);
- pthread_setcancelstate(oldState,NULL);
+ pthread_setcancelstate(oldState, NULL);
return r;
}
const char *debugmessage, int debuglevel);
// wait for the specified time, checking every 20 milliseconds, and block if it can't acquire the
// lock
-int _debug_mutex_lock(pthread_mutex_t *mutex, useconds_t dally_time, const char *mutexName, const char *filename,
- const int line, int debuglevel);
+int _debug_mutex_lock(pthread_mutex_t *mutex, useconds_t dally_time, const char *mutexName,
+ const char *filename, const int line, int debuglevel);
-#define debug_mutex_lock(mu, t, d) _debug_mutex_lock(mu, t, #mu , __FILE__, __LINE__, d)
+#define debug_mutex_lock(mu, t, d) _debug_mutex_lock(mu, t, #mu, __FILE__, __LINE__, d)
-int _debug_mutex_unlock(pthread_mutex_t *mutex, const char *mutexName, const char *filename, const int line,
- int debuglevel);
+int _debug_mutex_unlock(pthread_mutex_t *mutex, const char *mutexName, const char *filename,
+ const int line, int debuglevel);
#define debug_mutex_unlock(mu, d) _debug_mutex_unlock(mu, #mu, __FILE__, __LINE__, d)
void pthread_cleanup_debug_mutex_unlock(void *arg);
#define pthread_cleanup_debug_mutex_lock(mu, t, d) \
- if (_debug_mutex_lock(mu, t, #mu, __FILE__, __LINE__, d) == 0) \
+ if (_debug_mutex_lock(mu, t, #mu, __FILE__, __LINE__, d) == 0) \
pthread_cleanup_push(pthread_cleanup_debug_mutex_unlock, (void *)mu)
char *get_version_string(); // mallocs a string space -- remember to free it afterwards
// now, if a flush_rtp_timestamp has been defined and the incoming timestamp is "before" it,
// drop it…
- if ((conn->flush_rtp_timestamp != 0) && (actual_timestamp != conn->flush_rtp_timestamp) &&
+ if ((conn->flush_rtp_timestamp != 0) && (actual_timestamp != conn->flush_rtp_timestamp) &&
(modulo_32_offset(actual_timestamp, conn->flush_rtp_timestamp) <
conn->input_rate * 10)) { // if it's less than 10 seconds
debug(2, "Dropping flushed packet in player_put_packet, seqno %u, timestamp %" PRIu32
conn->initial_reference_timestamp = 0;
} else {
if ((conn->flush_rtp_timestamp != 0) &&
- (modulo_32_offset(conn->flush_rtp_timestamp, actual_timestamp) > conn->input_rate/5) &&
+ (modulo_32_offset(conn->flush_rtp_timestamp, actual_timestamp) > conn->input_rate / 5) &&
(modulo_32_offset(conn->flush_rtp_timestamp, actual_timestamp) < conn->input_rate)) {
- // between 0.2 and 1 second
+ // between 0.2 and 1 second
debug(2, "Dropping flush request in player_put_packet");
conn->flush_rtp_timestamp = 0;
}
local_time_now = get_absolute_time_in_fp(); // type okay
debug(3, "buffer_get_frame is iterating");
-
// if config.timeout (default 120) seconds have elapsed since the last audio packet was
// received, then we should stop.
// config.timeout of zero means don't check..., but iTunes may be confused by a long gap
if (conn->ab_synced) {
curframe = conn->audio_buffer + BUFIDX(conn->ab_read);
-
-
-
-
+
if ((conn->ab_read != conn->ab_write) &&
(curframe->ready)) { // it could be synced and empty, under
// exceptional circumstances, with the
}
}
- if ((conn->flush_rtp_timestamp != 0) && (curframe->given_timestamp != conn->flush_rtp_timestamp) &&
+ if ((conn->flush_rtp_timestamp != 0) &&
+ (curframe->given_timestamp != conn->flush_rtp_timestamp) &&
(modulo_32_offset(curframe->given_timestamp, conn->flush_rtp_timestamp) <
conn->input_rate * 10)) { // if it's less than ten seconds
debug(2, "Dropping flushed packet in buffer_get_frame, seqno %u, timestamp %" PRIu32
conn->initial_reference_timestamp = 0;
}
if ((conn->flush_rtp_timestamp != 0) &&
- (modulo_32_offset(conn->flush_rtp_timestamp, curframe->given_timestamp) > conn->input_rate / 5) &&
- (modulo_32_offset(conn->flush_rtp_timestamp, curframe->given_timestamp) < conn->input_rate * 10 )) {
+ (modulo_32_offset(conn->flush_rtp_timestamp, curframe->given_timestamp) >
+ conn->input_rate / 5) &&
+ (modulo_32_offset(conn->flush_rtp_timestamp, curframe->given_timestamp) <
+ conn->input_rate * 10)) {
debug(2, "Dropping flush request in buffer_get_frame");
conn->flush_rtp_timestamp = 0;
}
}
-
+
if ((curframe) && (curframe->ready)) {
notified_buffer_empty = 0; // at least one buffer now -- diagnostic only.
if (conn->ab_buffering) { // if we are getting packets but not yet forwarding them to the
void player_thread_initial_cleanup_handler(__attribute__((unused)) void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
- debug(3, "Connection %d: player thread main loop exit via player_thread_initial_cleanup_handler.", conn->connection_number);
+ debug(3, "Connection %d: player thread main loop exit via player_thread_initial_cleanup_handler.",
+ conn->connection_number);
}
void player_thread_cleanup_handler(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
- debug(3, "Connection %d: player thread main loop exit via player_thread_cleanup_handler.", conn->connection_number);
+ debug(3, "Connection %d: player thread main loop exit via player_thread_cleanup_handler.",
+ conn->connection_number);
if (config.statistics_requested) {
int rawSeconds = (int)difftime(time(NULL), conn->playstart);
debug(2, "Play begin");
while (1) {
- pthread_testcancel(); // allow a pthread_cancel request to take effect.
- abuf_t *inframe = buffer_get_frame(conn); // this has cancellation point(s), but it's not guaranteed that they'll aways be executed
+ pthread_testcancel(); // allow a pthread_cancel request to take effect.
+ abuf_t *inframe = buffer_get_frame(conn); // this has cancellation point(s), but it's not
+ // guaranteed that they'll aways be executed
if (inframe) {
inbuf = inframe->data;
inbuflength = inframe->length;
int64_t rt, nt;
rt = reference_timestamp; // uint32_t to int64_t
nt = inframe->given_timestamp; // uint32_t to int64_t
- rt = rt*conn->output_sample_ratio;
- nt = nt*conn->output_sample_ratio;
+ rt = rt * conn->output_sample_ratio;
+ nt = nt * conn->output_sample_ratio;
uint64_t local_time_now = get_absolute_time_in_fp(); // types okay
// struct timespec tn;
// sync_error_out_of_bounds, sync_error);
sync_error_out_of_bounds = 0;
- int64_t filler_length = (int64_t)(config.resyncthreshold * config.output_rate); // number of samples
+ int64_t filler_length =
+ (int64_t)(config.resyncthreshold * config.output_rate); // number of samples
if ((sync_error > 0) && (sync_error > filler_length)) {
debug(2, "Large positive sync error: %" PRId64 ".", sync_error);
int64_t local_frames_to_drop = sync_error / conn->output_sample_ratio;
uint32_t frames_to_drop_sized = local_frames_to_drop;
- do_flush(inframe->given_timestamp+frames_to_drop_sized,conn);
+ do_flush(inframe->given_timestamp + frames_to_drop_sized, conn);
} else if ((sync_error < 0) && ((-sync_error) > filler_length)) {
- debug(2, "Large negative sync error: %" PRId64 " with should_be_frame_32 of %" PRIu32
- ", nt of %" PRId64 " and current_delay of %" PRId64 ".", sync_error, should_be_frame_32, nt, current_delay);
+ debug(2,
+ "Large negative sync error: %" PRId64 " with should_be_frame_32 of %" PRIu32
+ ", nt of %" PRId64 " and current_delay of %" PRId64 ".",
+ sync_error, should_be_frame_32, nt, current_delay);
int64_t silence_length = -sync_error;
if (silence_length > (filler_length * 5))
silence_length = filler_length * 5;
char *long_silence = malloc(conn->output_bytes_per_frame * silence_length_sized);
if (long_silence) {
memset(long_silence, 0, conn->output_bytes_per_frame * silence_length_sized);
- debug(2,"Play a silence of %d frames.",silence_length_sized);
+ debug(2, "Play a silence of %d frames.", silence_length_sized);
config.output->play(long_silence, silence_length_sized);
free(long_silence);
} else {
pthread_cleanup_pop(1); // pop the cleanup handler
debug(1, "This should never be called either.");
pthread_cleanup_pop(1); // pop the initial cleanup handler
- pthread_exit(NULL);
+ pthread_exit(NULL);
}
// takes the volume as specified by the airplay protocol
debug(2, "pend");
send_ssnc_metadata('pend', NULL, 0, 1); // contains cancellation points
#endif
- debuglev = dl;
+ debuglev = dl;
command_stop();
return 0;
} else {
debug(3, "Connection %d: player thread already deleted.", conn->connection_number);
- debuglev = dl;
+ debuglev = dl;
return -1;
}
}
distant_transmit_time = (uint64_t)nctohl(&packet[24]) << 32;
distant_transmit_time += nctohl(&packet[28]);
-
+
uint64_t remote_processing_time = 0;
-
+
if (distant_transmit_time >= distant_receive_time)
- remote_processing_time = distant_transmit_time - distant_receive_time;
+ remote_processing_time = distant_transmit_time - distant_receive_time;
else {
- debug(1, "Yikes: distant_transmit_time is before distant_receive_time; remote processing time set to zero.");
+ debug(1, "Yikes: distant_transmit_time is before distant_receive_time; remote "
+ "processing time set to zero.");
}
// debug(1,"Return trip time: %" PRIu64 " uS, remote processing time: %" PRIu64 "
// uS.",(return_time*1000000)>>32,(remote_processing_time*1000000)>>32);
pktfree -= n;
p += n;
if (pktfree <= 1024) {
- debug(1,"Attempted to write overlong RTSP packet 1");
+ debug(1, "Attempted to write overlong RTSP packet 1");
return -1;
}
}
pktfree -= n;
p += n;
if (pktfree <= 1024) {
- debug(1,"Attempted to write overlong RTSP packet 2");
+ debug(1, "Attempted to write overlong RTSP packet 2");
return -2;
}
debug(1, "Content is \"%s\"", resp->content);
p += n;
if (pktfree <= 1024) {
- debug(1,"Attempted to write overlong RTSP packet 3");
+ debug(1, "Attempted to write overlong RTSP packet 3");
return -3;
}
if (write(fd, pkt, p - pkt) != p - pkt) {
// debug(1, "Connection %d: rtsp_conversation_thread_func_cleanup_function called.",
// conn->connection_number);
if (conn->player_thread)
- player_stop(conn);
+ player_stop(conn);
if (conn->fd > 0) {
// debug(1, "Connection %d: closing fd %d.",
// conn->connection_number,conn->fd);
if (method_selected == 0) {
debug(1, "RTSP thread %d: Unrecognised and unhandled rtsp request \"%s\".",
conn->connection_number, req->method);
-
-
- int y = req->contentlength;
- if (y > 0) {
- char obf[4096];
- if (y > 4096)
- y = 4096;
- char *p = req->content;
- char *obfp = obf;
- int obfc;
- for (obfc = 0; obfc < y; obfc++) {
- snprintf(obfp, 3, "%02X", (unsigned int)*p);
- p++;
- obfp += 2;
- };
- *obfp = 0;
- debug(1, "Content: \"%s\".",obf);
- }
+
+ int y = req->contentlength;
+ if (y > 0) {
+ char obf[4096];
+ if (y > 4096)
+ y = 4096;
+ char *p = req->content;
+ char *obfp = obf;
+ int obfc;
+ for (obfc = 0; obfc < y; obfc++) {
+ snprintf(obfp, 3, "%02X", (unsigned int)*p);
+ p++;
+ obfp += 2;
+ };
+ *obfp = 0;
+ debug(1, "Content: \"%s\".", obf);
+ }
}
}
debug(debug_level, "RTSP thread %d: RTSP Response:", conn->connection_number);
if (conn->stop == 0) {
int err = msg_write_response(conn->fd, resp);
if (err) {
- debug(1,"A communication error was detected. Closing the play session.");
- player_stop(conn);
+ debug(1, "A communication error was detected. Closing the play session.");
+ player_stop(conn);
}
}
pthread_cleanup_pop(1);
// See: https://github.com/mikebrady/shairport-sync/issues/329
fcntl(fd, F_SETFD, FD_CLOEXEC);
ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
-
+
struct timeval tv;
tv.tv_sec = 3; // three seconds write timeout
tv.tv_usec = 0;
if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&tv, sizeof tv) == -1)
debug(1, "Error %d setting send timeout for rtsp writeback.", errno);
-
#ifdef IPV6_V6ONLY
// some systems don't support v4 access on v6 sockets, but some do.
// since we need to account for two sockets we might as well
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <sys/socket.h>
-#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <popt.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>