diff options
author | Mike Brady <mikebrady@eircom.net> | 2019-06-05 15:02:26 +0100 |
---|---|---|
committer | Mike Brady <mikebrady@eircom.net> | 2019-06-05 15:02:26 +0100 |
commit | 1704916a4745c69ba08a0646601c10a7de3f9a17 (patch) | |
tree | c74a30217942df1a8b1026fde34f2533d5de0d70 | |
parent | 3c4a878ad9e0b3097c8c93433d6bf2f62af19c81 (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.md | 1 | ||||
-rw-r--r-- | audio_alsa.c | 67 | ||||
-rw-r--r-- | common.c | 60 | ||||
-rw-r--r-- | player.c | 17 | ||||
-rw-r--r-- | scripts/shairport-sync.conf | 12 | ||||
-rw-r--r-- | shairport.c | 13 |
6 files changed, 120 insertions, 50 deletions
@@ -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"); } } @@ -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; @@ -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)) { |