UDP port numbers are now chosen from port 7000 up. Two options are introduced to control this. joerg-krause's stack erro fix installed.
This commit is contained in:
@@ -48,6 +48,8 @@ typedef struct {
|
||||
#endif
|
||||
uint8_t hw_addr[6];
|
||||
int port;
|
||||
int udp_port_base;
|
||||
int udp_port_range;
|
||||
int ignore_volume_control;
|
||||
int resyncthreshold; // if it get's out of whack my more than this, resync. Zero means never
|
||||
// resync.
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.50])
|
||||
AC_INIT([shairport-sync], [2.3.2], [mikebrady@eircom.net])
|
||||
AC_INIT([shairport-sync], [2.3.3], [mikebrady@eircom.net])
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_SRCDIR([shairport.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
#include <pthread.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/signal.h>
|
||||
#include <signal.h>
|
||||
#include <sys/syslog.h>
|
||||
#include <assert.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -1271,8 +1272,14 @@ int player_play(stream_cfg *stream) {
|
||||
if (rc)
|
||||
debug(1, "Error initialising condition variable.");
|
||||
config.output->start(sampling_rate);
|
||||
pthread_create(&player_thread, NULL, player_thread_func, NULL);
|
||||
|
||||
size_t size = (PTHREAD_STACK_MIN + 128 * 1024);
|
||||
pthread_attr_t tattr;
|
||||
pthread_attr_init(&tattr);
|
||||
rc = pthread_attr_setstacksize(&tattr, size);
|
||||
if (rc)
|
||||
debug(1, "Error setting stack size for player_thread: %s", strerror(errno));
|
||||
pthread_create(&player_thread, &tattr, player_thread_func, NULL);
|
||||
pthread_attr_destroy(&tattr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -396,7 +396,7 @@ static void *rtp_timing_receiver(void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int bind_port(SOCKADDR *remote, int *sock, int desired_port) {
|
||||
static int bind_port(SOCKADDR *remote, int *sock) {
|
||||
struct addrinfo hints, *info;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
@@ -405,21 +405,32 @@ static int bind_port(SOCKADDR *remote, int *sock, int desired_port) {
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
char buffer[10];
|
||||
snprintf(buffer, 10, "%d", desired_port);
|
||||
|
||||
// look for a port in the range, if any was specified.
|
||||
int desired_port = config.udp_port_base;
|
||||
int ret;
|
||||
do {
|
||||
snprintf(buffer, 10, "%d", desired_port);
|
||||
|
||||
int ret = getaddrinfo(NULL, buffer, &hints, &info);
|
||||
ret = getaddrinfo(NULL, buffer, &hints, &info);
|
||||
|
||||
if (ret < 0)
|
||||
die("failed to get usable addrinfo?! %s.", gai_strerror(ret));
|
||||
if (ret < 0)
|
||||
die("failed to get usable addrinfo?! %s.", gai_strerror(ret));
|
||||
|
||||
*sock = socket(remote->SAFAMILY, SOCK_DGRAM, IPPROTO_UDP);
|
||||
ret = bind(*sock, info->ai_addr, info->ai_addrlen);
|
||||
*sock = socket(remote->SAFAMILY, SOCK_DGRAM, IPPROTO_UDP);
|
||||
ret = bind(*sock, info->ai_addr, info->ai_addrlen);
|
||||
|
||||
freeaddrinfo(info);
|
||||
|
||||
if (ret < 0)
|
||||
die("could not bind a UDP port!");
|
||||
freeaddrinfo(info);
|
||||
|
||||
} while ((ret<0) && (errno==EADDRINUSE) && (desired_port!=0) && (desired_port++ < config.udp_port_base+config.udp_port_range));
|
||||
|
||||
debug(1,"UDP port chosen: %d.",desired_port);
|
||||
|
||||
if (ret < 0) {
|
||||
die("error: could not bind a UDP port!");
|
||||
}
|
||||
|
||||
|
||||
int sport;
|
||||
SOCKADDR local;
|
||||
socklen_t local_len = sizeof(local);
|
||||
@@ -510,9 +521,9 @@ void rtp_setup(SOCKADDR *remote, int cport, int tport, uint32_t active_remote, i
|
||||
// now, we open three sockets -- one for the audio stream, one for the timing and one for the
|
||||
// control
|
||||
|
||||
*lsport = bind_port(remote, &audio_socket, 0);
|
||||
*lcport = bind_port(remote, &control_socket, 0);
|
||||
*ltport = bind_port(remote, &timing_socket, 0);
|
||||
*lsport = bind_port(remote, &audio_socket);
|
||||
*lcport = bind_port(remote, &control_socket);
|
||||
*ltport = bind_port(remote, &timing_socket);
|
||||
|
||||
debug(2, "listening for audio, control and timing on ports %d, %d, %d.", *lsport, *lcport,
|
||||
*ltport);
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/poll.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ general =
|
||||
// mdns_backend = "avahi"; // not used, not tested
|
||||
// output_backend = "alsa"; // alsa is default, other possibilities are "stdout", "pulse", "dummy". Only alsa supports synchronisation.
|
||||
// port = 5000;
|
||||
// udp_port_base = 7000; // start allocation UDP ports from this port number
|
||||
// udp_port_range = 100; // look for free ports in this number of places, starting at the UDP port base (only three are needed).
|
||||
// password = "secret"; // default is no password
|
||||
// interpolation = "basic"; // aka "stuffing". Default is "basic", alternative is "soxr"
|
||||
// statistics = "no"; // print statistics in the log
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// Sample Configuration File for Shairport Sync
|
||||
// Commented out settings are generally the defaults, except where noted.
|
||||
|
||||
// General Settings
|
||||
general =
|
||||
{
|
||||
// name = "Shairport Sync Player"; // This is the name the service will advertise to iTunes. The default is "Shairport Sync on <hostname>"
|
||||
// mdns_backend = "avahi"; // not used, not tested
|
||||
// output_backend = "alsa"; // alsa is default, other possibilities are "stdout", "pulse", "dummy". Only alsa supports synchronisation.
|
||||
// port = 5000;
|
||||
// password = "secret"; // default is no password
|
||||
// interpolation = "basic"; // aka "stuffing". Default is "basic", alternative is "soxr"
|
||||
// statistics = "no"; // print statistics in the log
|
||||
// drift = 88; // allow this number of frames of drift before correcting it
|
||||
// resync_threshold = 2205; // a synchronisation error greater than this will cause resynchronisation; 0 disables it
|
||||
// log_verbosity = 0; // "0" means no verbosity, "3" is most verbose.
|
||||
// ignore_volume_control = "no"; // set this to "yes" if you want the volume to be at 100% no matter what the source's volume control is set to.
|
||||
};
|
||||
|
||||
// Latencies for different sources.
|
||||
latencies =
|
||||
{
|
||||
// default = 88200;
|
||||
// itunes = 99400;
|
||||
// airplay = 88200;
|
||||
// forkedDaapd = 99400;
|
||||
};
|
||||
|
||||
|
||||
// How to deal with metadata, including artwork
|
||||
metadata =
|
||||
{
|
||||
// enabled = "no";
|
||||
// include_cover_art = "no";
|
||||
// pipe_name = "/tmp/shairport-sync-metadata";
|
||||
};
|
||||
|
||||
// Advanced parameters for controlling how a Shairport Sync runs
|
||||
sessioncontrol =
|
||||
{
|
||||
// run_this_before_play_begins = "/path/to/application and args";
|
||||
// run_this_after_play_ends = "/path/to/application and args";
|
||||
// wait_for_completion = "no";
|
||||
// allow_session_interruption = "no";
|
||||
// session_timeout = 120;
|
||||
};
|
||||
|
||||
//
|
||||
// Back End Settings
|
||||
//
|
||||
|
||||
// These are parameters for the alsa back end, the only back end that supports synchronisation
|
||||
{
|
||||
// output_device = "default";
|
||||
// mixer_type = "software"; // "software" or "hardware"
|
||||
// mixer_device = "default"; //actually, the mixer default is whatever the output_device is. Normally you wouldn't have to use this.
|
||||
// mixer_control_name = "PCM"; // the name of the mixer to use -- there is no default.
|
||||
// audio_backend_latency_offset = 0; // Set this offset to compensate for a fixed delay in the audio back end. E.g. if the output device delays by 100 ms, set this to -4410.
|
||||
// audio_backend_buffer_desired_length = 6615; // If set too small, buffer underflow occurs on low-powered machines. Too long and the response times with software mixer become annoying.
|
||||
};
|
||||
|
||||
// These are parameters for the pipe back end, an experimental back end that directs output to a pipe.
|
||||
pipe =
|
||||
{
|
||||
// audio_backend_latency_offset = 0; // Set this offset to compensate for a fixed delay in the audio back end. E.g. if the output device delays by 100 ms, set this to -4410.
|
||||
// audio_backend_buffer_desired_length = 44100;
|
||||
// name = "/path/to/pipe"; // there is no default pipe name for the output
|
||||
};
|
||||
|
||||
// These are parameters for the stdout back end, an experimental back end that directs output to stdout.
|
||||
stdout =
|
||||
{
|
||||
// audio_backend_latency_offset = 0; // Set this offset to compensate for a fixed delay in the audio back end. E.g. if the output device delays by 100 ms, set this to -4410.
|
||||
// audio_backend_buffer_desired_length = 44100;
|
||||
};
|
||||
+22
@@ -369,6 +369,24 @@ int parse_options(int argc, char **argv) {
|
||||
config.port = value;
|
||||
}
|
||||
|
||||
/* Get the udp port base setting. */
|
||||
if (config_lookup_int(config.cfg, "general.udp_port_base", &value)) {
|
||||
if ((value < 0) || (value > 65535))
|
||||
die("Invalid port number \"%sd\". It should be between 0 and 65535, default is 7000",
|
||||
value);
|
||||
else
|
||||
config.udp_port_base = value;
|
||||
}
|
||||
|
||||
/* Get the udp port range setting. This is number of ports that will be tried for free ports , starting at the port base. Only three ports are needed. */
|
||||
if (config_lookup_int(config.cfg, "general.udp_port_range", &value)) {
|
||||
if ((value < 0) || (value > 65535))
|
||||
die("Invalid port range \"%sd\". It should be between 0 and 65535, default is 100",
|
||||
value);
|
||||
else
|
||||
config.udp_port_range = value;
|
||||
}
|
||||
|
||||
/* Get the password setting. */
|
||||
if (config_lookup_string(config.cfg, "general.password", &str))
|
||||
config.password = (char *)str;
|
||||
@@ -606,6 +624,8 @@ int main(int argc, char **argv) {
|
||||
set_requested_connection_state_to_output(
|
||||
1); // we expect to be able to connect to the output device
|
||||
config.audio_backend_buffer_desired_length = 6615; // 0.15 seconds.
|
||||
config.udp_port_base = 7000;
|
||||
config.udp_port_range = 100;
|
||||
|
||||
// this is a bit weird, but apparently necessary
|
||||
char *basec = strdup(argv[0]);
|
||||
@@ -780,6 +800,8 @@ int main(int argc, char **argv) {
|
||||
debug(2, "statistics_requester status is %d.", config.statistics_requested);
|
||||
debug(2, "daemon status is %d.", config.daemonise);
|
||||
debug(2, "rtsp listening port is %d.", config.port);
|
||||
debug(2, "udp base port is %d.", config.udp_port_base);
|
||||
debug(2, "udp port range is %d.", config.udp_port_range);
|
||||
debug(2, "Shairport Sync player name is \"%s\".", config.apname);
|
||||
debug(2, "Audio Output name is \"%s\".", config.output_name);
|
||||
debug(2, "on-start action is \"%s\".", config.cmd_start);
|
||||
|
||||
Reference in New Issue
Block a user