summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Brady <mikebrady@eircom.net>2019-06-05 15:02:26 +0100
committerMike Brady <mikebrady@eircom.net>2019-06-05 15:02:26 +0100
commit1704916a4745c69ba08a0646601c10a7de3f9a17 (patch)
treec74a30217942df1a8b1026fde34f2533d5de0d70
parent3c4a878ad9e0b3097c8c93433d6bf2f62af19c81 (diff)
Squashed commit of the following:
commit 85fae473bb30373e5675f6fcf6d97148739fb94e Merge: bf91d35 854942d Author: Mike Brady <mikebrady@eircom.net> Date: Tue Jun 4 22:15:37 2019 +0100 Merge pull request #860 from joerg-krause/patch-2 Debug requested period size value commit 854942df9232fce0bc375dc94eae8a4ed5f19b20 Author: Jörg Krause <joerg.krause@embedded.rocks> Date: Tue Jun 4 20:47:43 2019 +0200 Debug requested period size value commit bf91d35bfb6b4ea65abefe5ac915c5f8dc29b2e6 Author: Mike Brady <mikebrady@eircom.net> Date: Tue Jun 4 15:33:30 2019 +0100 Update RELEASENOTES-DEVELOPMENT.md commit 3ca3408255c042d47d1a3acfa4361fb1ee72b1d8 Author: Mike Brady <mikebrady@eircom.net> Date: Tue Jun 4 15:32:10 2019 +0100 Fix error message for invalid standby mode choice commit 4bafe1c982e33392e72e16068c1005b3c6c5fe07 Author: Mike Brady <mikebrady@eircom.net> Date: Mon Jun 3 10:03:54 2019 +0100 quieten a compilation warning commit 9d96906402529045934ed24d0a5909378b886d36 Author: Mike Brady <mikebrady@eircom.net> Date: Sun Jun 2 18:05:40 2019 +0100 Update configure.ac commit 0c5c4bfe3f9618f63695b3127404272b1ec81a06 Author: Mike Brady <mikebrady@eircom.net> Date: Sun Jun 2 18:04:51 2019 +0100 Update RELEASENOTES-DEVELOPMENT.md commit 85cc1bdd97991547424e646483b3e0fcd78f1137 Author: Mike Brady <mikebrady@eircom.net> Date: Sun Jun 2 17:56:47 2019 +0100 Fix the dither calculation -- it was 12 dB too high, really noticable on the U8 setting. commit 25f0fbc24da7f115bb6a509259b8c5993460f3bc Author: Mike Brady <mikebrady@eircom.net> Date: Sun Jun 2 13:42:19 2019 +0100 Update INSTALL.md commit d91e41d976e3ea15f441eb96b2d6446b84586882 Author: Mike Brady <mikebrady@eircom.net> Date: Wed May 29 17:26:44 2019 +0100 Add missing support for S32_LE, S32_BE, S24_LE and S24_LE formats. commit 7f2e6b1aac6740168c7fac5b1054ed234e420159 Author: Mike Brady <mikebrady@eircom.net> Date: Wed May 29 16:18:51 2019 +0100 Add support for S32_LE, S32_BE, S24_LE and S24_BE wqhen generating frames of dithered silence commit 76ad4e6a73709f6c42bd9a8ccd6a85844096719e Author: Mike Brady <mikebrady@eircom.net> Date: Wed May 29 16:00:47 2019 +0100 enable specification of specific formats and/or speeds to turn off automatic format/speed selection, fixing a bug. Clarify some of the warnings. Fix a few typos in the configuration file sample. commit a8222e3f8531f28580130cc4009a33f497da6a59 Merge: c677006 19fbede Author: Mike Brady <mikebrady@eircom.net> Date: Mon May 27 09:30:57 2019 +0100 Merge pull request #855 from idcrook/conf_mqtt_port mqtt port config changes – fix error in the configuration file and check port number for sanity. Many thanks, David. It'll find it's easy into the next release. commit 19fbededcfc77c83ca2c076026412157ee5fc956 Author: David Crook <idcrook@users.noreply.github.com> Date: Sat May 25 13:01:22 2019 -0600 mqtt port config changes 1. update example shairport-sync.conf file 2. update config file mqtt port parsing Signed-off-by: David Crook <idcrook@users.noreply.github.com> commit c677006541e93c5a40406accc670d9a65e68cbb9 Merge: 744c595 3c4a878 Author: Mike Brady <mikebrady@eircom.net> Date: Fri May 24 17:37:26 2019 +0100 Bring into line with master 3.3
-rw-r--r--INSTALL.md1
-rw-r--r--audio_alsa.c67
-rw-r--r--common.c60
-rw-r--r--player.c17
-rw-r--r--scripts/shairport-sync.conf12
-rw-r--r--shairport.c13
6 files changed, 120 insertions, 50 deletions
diff --git a/INSTALL.md b/INSTALL.md
index 33058c8..8d8dc7d 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -9,7 +9,6 @@ Do the usual update and upgrade:
```
# apt-get update
# apt-get upgrade
-# rpi-update
```
(Separately, if you haven't done so already, consider using the `raspi-config` tool to expand the file system to use the entire card.)
diff --git a/audio_alsa.c b/audio_alsa.c
index cd692f1..956deba 100644
--- a/audio_alsa.c
+++ b/audio_alsa.c
@@ -192,7 +192,9 @@ static void help(void) {
" -c mixer-control set the mixer control name, default is to use no mixer.\n"
" -m mixer-device set the mixer device, default is the output device.\n"
" -i mixer-index set the mixer index, default is 0.\n");
- system("if [ -d /proc/asound ] ; then echo \" hardware output devices:\" ; ls -al /proc/asound/ 2>/dev/null | grep '\\->' | tr -s ' ' | cut -d ' ' -f 9 | while read line; do echo \" \\\"hw:$line\\\"\" ; done ; fi");
+ int r = system("if [ -d /proc/asound ] ; then echo \" hardware output devices:\" ; ls -al /proc/asound/ 2>/dev/null | grep '\\->' | tr -s ' ' | cut -d ' ' -f 9 | while read line; do echo \" \\\"hw:$line\\\"\" ; done ; fi");
+ if (r != 0)
+ debug(2, "error %d executing a script to list alsa hardware device names", r);
}
void set_alsa_out_dev(char *dev) { alsa_out_dev = dev; }
@@ -510,7 +512,7 @@ int actual_open_alsa_device(int do_auto_setup) {
}
if (set_period_size_request != 0) {
- debug(1, "Attempting to set the period size");
+ debug(1, "Attempting to set the period size to %lu", period_size_requested);
ret = snd_pcm_hw_params_set_period_size_near(alsa_handle, alsa_params, &period_size_requested,
&dir);
if (ret < 0) {
@@ -1037,6 +1039,8 @@ static int init(int argc, char **argv) {
/* Get the output format, using the same names as aplay does*/
if (config_lookup_string(config.cfg, "alsa.output_format", &str)) {
+ int temp_output_format_auto_requested = config.output_format_auto_requested;
+ config.output_format_auto_requested = 0; // assume a valid format will be given.
if (strcasecmp(str, "S16") == 0)
config.output_format = SPS_FORMAT_S16;
else if (strcasecmp(str, "S16_LE") == 0)
@@ -1066,11 +1070,12 @@ static int init(int argc, char **argv) {
else if (strcasecmp(str, "auto") == 0)
config.output_format_auto_requested = 1;
else {
- warn("Invalid output format \"%s\". It should be \"U8\", \"S8\", "
+ config.output_format_auto_requested = temp_output_format_auto_requested; //format was invalid; recall the original setting
+ warn("Invalid output format \"%s\". It should be \"auto\", \"U8\", \"S8\", "
"\"S16\", \"S24\", \"S24_LE\", \"S24_BE\", "
"\"S24_3LE\", \"S24_3BE\" or "
- "\"S32\", \"S32_LE\", \"S32_BE\". It is set to \"%s\".",
- sps_format_description_string(config.output_format));
+ "\"S32\", \"S32_LE\", \"S32_BE\". It remains set to \"%s\".", str,
+ config.output_format_auto_requested == 1 ? "auto" : sps_format_description_string(config.output_format));
}
}
@@ -1078,25 +1083,35 @@ static int init(int argc, char **argv) {
if (strcasecmp(str, "auto") == 0) {
config.output_rate_auto_requested = 1;
} else {
- /* Get the output rate, which must be a multiple of 44,100*/
- if (config_lookup_int(config.cfg, "alsa.output_rate", &value)) {
- debug(1, "alsa output rate is %d frames per second", value);
- switch (value) {
- case 44100:
- case 88200:
- case 176400:
- case 352800:
- config.output_rate = value;
- break;
- default:
- warn("Invalid output rate \"%d\". It should be \"auto\" or a multiple of 44,100 up "
- "to 352,800. It is "
- "set to %d.",
- value,config.output_rate);
- }
- }
+ if (config.output_rate_auto_requested == 1)
+ warn("Invalid output rate \"%s\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
+ "It remains set to \"auto\". Note: numbers should not be placed in quotes.", str);
+ else
+ warn("Invalid output rate \"%s\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
+ "It remains set to %d. Note: numbers should not be placed in quotes.", str, config.output_rate);
}
- }
+ }
+
+ /* Get the output rate, which must be a multiple of 44,100*/
+ if (config_lookup_int(config.cfg, "alsa.output_rate", &value)) {
+ debug(1, "alsa output rate is %d frames per second", value);
+ switch (value) {
+ case 44100:
+ case 88200:
+ case 176400:
+ case 352800:
+ config.output_rate = value;
+ config.output_rate_auto_requested = 0;
+ break;
+ default:
+ if (config.output_rate_auto_requested == 1)
+ warn("Invalid output rate \"%d\". It should be \"auto\", 44100, 88200, 176400 or 352800. "
+ "It remains set to \"auto\".",value);
+ else
+ warn("Invalid output rate \"%d\".It should be \"auto\", 44100, 88200, 176400 or 352800. "
+ "It remains set to %d.", value, config.output_rate);
+ }
+ }
/* Get the use_mmap_if_available setting. */
if (config_lookup_string(config.cfg, "alsa.use_mmap_if_available", &str)) {
@@ -1107,7 +1122,7 @@ static int init(int argc, char **argv) {
else {
warn("Invalid use_mmap_if_available option choice \"%s\". It should be "
"\"yes\" or \"no\". "
- "It is set to \"yes\".");
+ "It remains set to \"yes\".");
config.no_mmap = 0;
}
}
@@ -1163,7 +1178,7 @@ static int init(int argc, char **argv) {
else {
warn("Invalid disable_standby_mode option choice \"%s\". It should be "
"\"always\", \"auto\" or \"never\". "
- "It is set to \"never\".");
+ "It remains set to \"never\".", str);
}
}
@@ -1179,7 +1194,7 @@ static int init(int argc, char **argv) {
else {
warn("Invalid use_precision_timing option choice \"%s\". It should be "
"\"yes\", \"auto\" or \"no\". "
- "It is set to \"auto\".");
+ "It remains set to \"%s\".", config.use_precision_timing == YNA_NO ? "no" : config.use_precision_timing == YNA_AUTO ? "auto" : "yes");
}
}
diff --git a/common.c b/common.c
index b097dda..9775b07 100644
--- a/common.c
+++ b/common.c
@@ -1376,12 +1376,14 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
int64_t hyper_sample = 0;
// add a TPDF dither -- see
- // http://www.users.qwest.net/%7Evolt42/cadenzarecording/DitherExplained.pdf
+ // http://educypedia.karadimov.info/library/DitherExplained.pdf
// and the discussion around https://www.hydrogenaud.io/forums/index.php?showtopic=16963&st=25
// I think, for a 32 --> 16 bits, the range of
// random numbers needs to be from -2^16 to 2^16, i.e. from -65536 to 65536 inclusive, not from
// -32768 to +32767
+
+ // Actually, what would be generated here is from -65535 to 65535, i.e. one less on the limits.
// See the original paper at
// http://www.ece.rochester.edu/courses/ECE472/resources/Papers/Lipshitz_1992.pdf
@@ -1392,23 +1394,23 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
case SPS_FORMAT_S32:
case SPS_FORMAT_S32_LE:
case SPS_FORMAT_S32_BE:
- dither_mask = (int64_t)1 << (64 + 1 - 32);
+ dither_mask = (int64_t)1 << (64 - 32);
break;
case SPS_FORMAT_S24:
case SPS_FORMAT_S24_LE:
case SPS_FORMAT_S24_BE:
case SPS_FORMAT_S24_3LE:
case SPS_FORMAT_S24_3BE:
- dither_mask = (int64_t)1 << (64 + 1 - 24);
+ dither_mask = (int64_t)1 << (64 - 24);
break;
case SPS_FORMAT_S16:
case SPS_FORMAT_S16_LE:
case SPS_FORMAT_S16_BE:
- dither_mask = (int64_t)1 << (64 + 1 - 16);
+ dither_mask = (int64_t)1 << (64 - 16);
break;
case SPS_FORMAT_S8:
case SPS_FORMAT_U8:
- dither_mask = (int64_t)1 << (64 + 1 - 8);
+ dither_mask = (int64_t)1 << (64 - 8);
break;
case SPS_FORMAT_UNKNOWN:
die("Unexpected SPS_FORMAT_UNKNOWN while calculating dither mask.");
@@ -1442,6 +1444,30 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
*(int32_t *)op = hyper_sample;
result = 4;
break;
+ case SPS_FORMAT_S32_LE:
+ hyper_sample >>= (64 - 32);
+ byt = (uint8_t)hyper_sample;
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 8);
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 16);
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 24);
+ *op++ = byt;
+ result = 4;
+ break;
+ case SPS_FORMAT_S32_BE:
+ hyper_sample >>= (64 - 32);
+ byt = (uint8_t)(hyper_sample >> 24);
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 16);
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 8);
+ *op++ = byt;
+ byt = (uint8_t)hyper_sample;
+ *op++ = byt;
+ result = 4;
+ break;
case SPS_FORMAT_S24_3LE:
hyper_sample >>= (64 - 24);
byt = (uint8_t)hyper_sample;
@@ -1467,6 +1493,28 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
*(int32_t *)op = hyper_sample;
result = 4;
break;
+ case SPS_FORMAT_S24_LE:
+ hyper_sample >>= (64 - 24);
+ byt = (uint8_t)hyper_sample;
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 8);
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 16);
+ *op++ = byt;
+ *op++ = 0;
+ result = 4;
+ break;
+ case SPS_FORMAT_S24_BE:
+ hyper_sample >>= (64 - 24);
+ *op++ = 0;
+ byt = (uint8_t)(hyper_sample >> 16);
+ *op++ = byt;
+ byt = (uint8_t)(hyper_sample >> 8);
+ *op++ = byt;
+ byt = (uint8_t)hyper_sample;
+ *op++ = byt;
+ result = 4;
+ break;
case SPS_FORMAT_S16_LE:
hyper_sample >>= (64 - 16);
byt = (uint8_t)hyper_sample;
@@ -1501,7 +1549,7 @@ int64_t generate_zero_frames(char *outp, size_t number_of_frames, enum sps_forma
break;
default:
result = 0; // stop a compiler warning
- die("Unexpected SPS_FORMAT_UNKNOWN while outputting samples");
+ die("Unexpected SPS_FORMAT_* with index %d while outputting silence",format);
}
p += result;
previous_random_number = r;
diff --git a/player.c b/player.c
index 08c9203..92bda3a 100644
--- a/player.c
+++ b/player.c
@@ -650,12 +650,14 @@ static inline void process_sample(int32_t sample, char **outp, enum sps_format_t
if (dither) {
// add a TPDF dither -- see
- // http://www.users.qwest.net/%7Evolt42/cadenzarecording/DitherExplained.pdf
+ // http://educypedia.karadimov.info/library/DitherExplained.pdf
// and the discussion around https://www.hydrogenaud.io/forums/index.php?showtopic=16963&st=25
// I think, for a 32 --> 16 bits, the range of
// random numbers needs to be from -2^16 to 2^16, i.e. from -65536 to 65536 inclusive, not from
// -32768 to +32767
+
+ // Actually, what would be generated here is from -65535 to 65535, i.e. one less on the limits.
// See the original paper at
// http://www.ece.rochester.edu/courses/ECE472/resources/Papers/Lipshitz_1992.pdf
@@ -666,23 +668,23 @@ static inline void process_sample(int32_t sample, char **outp, enum sps_format_t
case SPS_FORMAT_S32:
case SPS_FORMAT_S32_LE:
case SPS_FORMAT_S32_BE:
- dither_mask = (int64_t)1 << (64 + 1 - 32);
+ dither_mask = (int64_t)1 << (64 - 32);
break;
case SPS_FORMAT_S24:
case SPS_FORMAT_S24_LE:
case SPS_FORMAT_S24_BE:
case SPS_FORMAT_S24_3LE:
case SPS_FORMAT_S24_3BE:
- dither_mask = (int64_t)1 << (64 + 1 - 24);
+ dither_mask = (int64_t)1 << (64 - 24);
break;
case SPS_FORMAT_S16:
case SPS_FORMAT_S16_LE:
case SPS_FORMAT_S16_BE:
- dither_mask = (int64_t)1 << (64 + 1 - 16);
+ dither_mask = (int64_t)1 << (64 - 16);
break;
case SPS_FORMAT_S8:
case SPS_FORMAT_U8:
- dither_mask = (int64_t)1 << (64 + 1 - 8);
+ dither_mask = (int64_t)1 << (64 - 8);
break;
case SPS_FORMAT_UNKNOWN:
die("Unexpected SPS_FORMAT_UNKNOWN while calculating dither mask.");
@@ -1673,10 +1675,15 @@ void *player_thread_func(void *arg) {
case SPS_FORMAT_S24_3BE:
conn->output_bytes_per_frame = 6;
break;
+
case SPS_FORMAT_S24:
+ case SPS_FORMAT_S24_LE:
+ case SPS_FORMAT_S24_BE:
conn->output_bytes_per_frame = 8;
break;
case SPS_FORMAT_S32:
+ case SPS_FORMAT_S32_LE:
+ case SPS_FORMAT_S32_BE:
conn->output_bytes_per_frame = 8;
break;
default:
diff --git a/scripts/shairport-sync.conf b/scripts/shairport-sync.conf
index 7b030d6..a17d633 100644
--- a/scripts/shairport-sync.conf
+++ b/scripts/shairport-sync.conf
@@ -31,7 +31,7 @@ general =
// volume_control_profile = "standard" ; // use this advanced setting to specify how the airplay volume is transferred to the mixer volume.
// "standard" makes the volume change more quickly at lower volumes and slower at higher volumes.
// "flat" makes the volume change at the same rate at all volumes.
-// volume_range_combined_hardware_priority = "no"; // when extending the volume range by combining the built-in software attenuator with the hardware mixer attenuator, set this to "yes" to reduce volume by using the hardware mixer first, then the built-in software attenuator.
+// volume_range_combined_hardware_priority = "no"; // when extending the volume range by combining the built-in software attenuator with the hardware mixer attenuator, set this to "yes" to reduce volume by using the hardware mixer first, then the built-in software attenuator.
// run_this_when_volume_is_set = "/full/path/to/application/and/args"; // Run the specified application whenever the volume control is set or changed.
// The desired AirPlay volume is appended to the end of the command line – leave a space if you want it treated as an extra argument.
// AirPlay volume goes from 0 to -30 and -144 means "mute".
@@ -84,7 +84,7 @@ alsa =
// mixer_control_name = "PCM"; // the name of the mixer to use to adjust output volume. If not specified, volume in adjusted in software.
// mixer_device = "default"; // the mixer_device default is whatever the output_device is. Normally you wouldn't have to use this.
// output_rate = "auto"; // can be "auto", 44100, 88200, 176400 or 352800, but the device must have the capability.
-// output_format = "auto"; // can be "auto", ""U8", "S8", "S16", "S16_LE", "S16_BE", "S24", "S24_LE", "S24_BE", "S24_3LE", "S24_3BE", "S32", "S32_LE" or "S32_BE" but the device must have the capability. Except where stated using (*LE or *BE), endianness matches that of the processor.
+// output_format = "auto"; // can be "auto", "U8", "S8", "S16", "S16_LE", "S16_BE", "S24", "S24_LE", "S24_BE", "S24_3LE", "S24_3BE", "S32", "S32_LE" or "S32_BE" but the device must have the capability. Except where stated using (*LE or *BE), endianness matches that of the processor.
// disable_synchronization = "no"; // Set to "yes" to disable synchronization. Default is "no".
// period_size = <number>; // Use this optional advanced setting to set the alsa period size near to this value
// buffer_size = <number>; // Use this optional advanced setting to set the alsa buffer size near to this value
@@ -199,9 +199,9 @@ mqtt =
{
// enabled = "no"; // set this to yes to enable the mqtt-metadata-service
// hostname = "iot.eclipse.org"; // Hostname of the MQTT Broker
-// port = "1883";
-// username = NULL; //set this to a string with your username, to enable username authentication
-// password = NULL; //set this to a string with your password, to enable username & password authentication
+// port = 1883; // Port on the MQTT Broker to connect to
+// username = NULL; //set this to a string to your username in order to enable username authentication
+// password = NULL; //set this to a string you your password in order to enable username & password authentication
// capath = NULL; //set this to the folder with the CA-Certificates to be accepted for the server certificate. If not set, TLS is not used
// cafile = NULL; //this may be used as an (exclusive) alternative to capath with a single file for all ca-certificates
// certfile = NULL; //set this to a string to a user certificate to enable MQTT Client certificates. keyfile must also be set!
@@ -216,7 +216,7 @@ mqtt =
// Available commands are "command", "beginff", "beginrew", "mutetoggle", "nextitem", "previtem", "pause", "playpause", "play", "stop", "playresume", "shuffle_songs", "volumedown", "volumeup"
}
-// Diagnostic settings. These are for diagnostic and debugging only. Normally you sould leave them commented out
+// Diagnostic settings. These are for diagnostic and debugging only. Normally you should leave them commented out
diagnostics =
{
// disable_resend_requests = "no"; // set this to yes to stop Shairport Sync from requesting the retransmission of missing packets. Default is "no".
diff --git a/shairport.c b/shairport.c
index 9e9400b..667a565 100644
--- a/shairport.c
+++ b/shairport.c
@@ -992,7 +992,6 @@ int parse_options(int argc, char **argv) {
#endif
#ifdef CONFIG_MQTT
- int tmpval = 0;
config_set_lookup_bool(config.cfg, "mqtt.enabled", &config.mqtt_enabled);
if (config.mqtt_enabled && !config.metadata_enabled) {
die("You need to have metadata enabled in order to use mqtt");
@@ -1001,11 +1000,13 @@ int parse_options(int argc, char **argv) {
config.mqtt_hostname = (char *)str;
// TODO: Document that, if this is false, whole mqtt func is disabled
}
- if (config_lookup_int(config.cfg, "mqtt.port", &tmpval)) {
- config.mqtt_port = tmpval;
- } else {
- // TODO: Is this the correct way to set a default value?
- config.mqtt_port = 1883;
+ config.mqtt_port = 1883;
+ if (config_lookup_int(config.cfg, "mqtt.port", &value)) {
+ if ((value < 0) || (value > 65535))
+ die("Invalid mqtt port number \"%sd\". It should be between 0 and 65535, default is 1883",
+ value);
+ else
+ config.mqtt_port = value;
}
if (config_lookup_string(config.cfg, "mqtt.username", &str)) {