summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Boot <bootc@boo.tc>2021-11-13 17:13:39 +0000
committerChris Boot <bootc@boo.tc>2021-11-13 17:13:39 +0000
commitb38b523c0060fb8bc7b599773a3bec073fd86cfc (patch)
treef6911c721a0e5ce3e4bd273158c604191326dd75
parentc987f51e20fb1f0833bb691de4cea9c763647ac3 (diff)
parentc19f697be2b6761616876787064d6b067cf87089 (diff)
New upstream version 3.3.8
-rw-r--r--.gitignore1
-rw-r--r--INSTALL.md6
-rw-r--r--MQTT.md192
-rw-r--r--README.md16
-rw-r--r--RELEASENOTES.md13
-rw-r--r--UPDATING.md4
-rw-r--r--audio_alsa.c79
-rw-r--r--common.c8
-rw-r--r--configure.ac368
-rw-r--r--dacp.c10
-rw-r--r--rtsp.c96
-rw-r--r--scripts/shairport-sync.conf1
-rw-r--r--shairport-sync.spec50
-rw-r--r--shairport.c4
-rw-r--r--tests/configure_test.sh207
15 files changed, 762 insertions, 293 deletions
diff --git a/.gitignore b/.gitignore
index 6f76aec..9d13084 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
/shairport-sync-mpris-test-client
*.o
+*.log
/*~
*.xml~
/config.mk
diff --git a/INSTALL.md b/INSTALL.md
index 964be27..85a2445 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -17,7 +17,7 @@ If you are using WiFi, you should turn off WiFi Power Management:
```
# iwconfig wlan0 power off
```
-WiFi Power Management will put the WiFi system in low-power mode when the WiFi system considered inactive, and in this mode it may not respond to events initiated from the network, such as AirPlay requests. Hence, WiFi Power Management should be turned off. (See [TROUBLESHOOTING.md](https://github.com/mikebrady/shairport-sync/blob/master/TROUBLESHOOTING.md#wifi-adapter-running-in-power-saving--low-power-mode) for more details.)
+WiFi Power Management will put the WiFi system in low-power mode when the WiFi system is considered inactive, and in this mode it may not respond to events initiated from the network, such as AirPlay requests. Hence, WiFi Power Management should be turned off. (See [TROUBLESHOOTING.md](https://github.com/mikebrady/shairport-sync/blob/master/TROUBLESHOOTING.md#wifi-adapter-running-in-power-saving--low-power-mode) for more details.)
Reboot the Pi.
@@ -33,8 +33,8 @@ Remove it as follows:
```
Do this until no more copies of `shairport-sync` are found.
-### Remove Old Startup Scripts
-You should also remove the startup script files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service` and `/etc/init.d/shairport-sync` if they exist – new ones will be installed if necessary.
+### Remove Old Startup and Service Scripts
+You should also remove the startup script and service definition files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service`, `/etc/init.d/shairport-sync`, `/etc/dbus-1/system.d/shairport-sync-dbus.conf` and `/etc/dbus-1/system.d/shairport-sync-mpris.conf` if they exist – new ones will be installed if necessary.
### Reboot after Cleaning Up
If you removed any installations of Shairport Sync or any of its startup script files in the last two steps, you should reboot.
diff --git a/MQTT.md b/MQTT.md
new file mode 100644
index 0000000..da21a3f
--- /dev/null
+++ b/MQTT.md
@@ -0,0 +1,192 @@
+Setting Up MQTT Publishing
+====
+
+This is a rough guide on the setup of MQTT publishing in ShairPort-Sync. The MQTT service listens for and publishes metadata generated by the airplay source and shairport-sync.
+
+Below is a simple example of configuring shairport-sync to send parsed metadata to a MQTT server under the topic "shairport"
+
+Example Configuration
+----
+
+Shairport-sync is configured below to published parsed metadata information and album-art to a MQTT server.
+
+```xml
+
+metadata =
+{
+ enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe
+ include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes".
+ cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems
+ pipe_name = "/tmp/shairport-sync-metadata";
+ pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up
+};
+
+
+mqtt =
+{
+ enabled = "yes"; // set this to yes to enable the mqtt-metadata-service
+ hostname = "192.168.1.111"; // Hostname of the MQTT Broker
+ port = 1883; // Port on the MQTT Broker to connect to
+ username = "username"; //set this to a string to your username in order to enable username authentication
+ password = "password"; //set this to a string you your password in order to enable username & password authentication
+ topic = "shairport"; //MQTT topic where this instance of shairport-sync should publish. If not set, the general.name value is used.
+// publish_raw = "no"; //whether to publish all available metadata under the codes given in the 'metadata' docs.
+ publish_parsed = "yes"; //whether to publish a small (but useful) subset of metadata under human-understandable topics
+ publish_cover = "yes"; //whether to publish the cover over mqtt in binary form. This may lead to a bit of load on the broker
+// enable_remote = "no"; //whether to remote control via MQTT. RC is available under `topic`/remote.
+};
+```
+
+Import Notes
+----
+
+Publish Options
+
+One needs to set either `publish_raw`, `publish_parsed` or `publish_cover` in the MQTT setup or no messages will be published.
+
+
+Overall Active State of Stream
+
+`active_start` and `active_end` represent a stable on/off flag for the current airplay session.
+
+`active_start` is plublished when any new airplay session begins
+
+`active_end` will fire after a configured timeout period unless the airplay stream is resumed.
+
+```xml
+sessioncontrol =
+{
+// "active" state starts when play begins and ends when the active_state_timeout has elapsed after play ends, unless another play session starts before the timeout has fully elapsed.
+ active_state_timeout = 30.0;
+};
+```
+
+MetaData Parsing
+----
+
+
+Additional details regarding the metadata can be found at [https://github.com/mikebrady/shairport-sync-metadata-reader]
+
+Meta data is generated by both the stream source (iOS, itunes, etc) and by shairport-sync itself. This data is coded as two 4-character codes to identify each piece of data, the `type` and the `code`.
+
+The first 4-character code, called the `type`, is either:
+ * `core` for all the regular metadadata coming from iTunes, etc., or
+ * `ssnc` (for 'shairport-sync') for all metadata coming from Shairport Sync itself, such as start/end delimiters, etc.
+
+* For `core` metadata, the second 4-character code is the 4-character metadata code that comes from iTunes etc. See, for example, https://code.google.com/p/ytrack/wiki/DMAP for information about the significance of the codes. The original data supplied by the source, if any, follows, and is encoded in base64 format. The length of the data is also provided.
+* For `ssnc` metadata, the second 4-character code is used to distinguish the messages. Cover art, coming from the source, is not tagged in the same way as other metadata, it seems, so is sent as an `ssnc` type metadata message with the code `PICT`. Progress information, similarly, is not tagged like other source-originated metadata, so it is sent as an `ssnc` type with the code `prgr`.
+
+Here are some of the `core` codes commonly passed from the source:
+ * `asar` -- "artist"
+ * `asal` -- "album"
+ * `minm` -- "title"
+ * `asgn` -- "genre"
+ * `asfm` -- "format"
+ * `asal` -- "songalbum'
+ * `pvol` -- "volume"
+ * `clip` -- "client_ip"
+
+Here are the 'ssnc' codes defined so far:
+ * `PICT` -- the payload is a picture, either a JPEG or a PNG. Check the first few bytes to see which.
+ * `clip` -- the payload is the IP number of the client, i.e. the sender of audio. Can be an IPv4 or an IPv6 number.
+ * `pbeg` -- play stream begin. No arguments
+ * `pend` -- play stream end. No arguments
+ * `pfls` -- play stream flush. No arguments
+ * `prsm` -- play stream resume. No arguments
+ * `pvol` -- play volume. The volume is sent as a string -- "airplay_volume,volume,lowest_volume,highest_volume", where "volume", "lowest_volume" and "highest_volume" are given in dB. The "airplay_volume" is what's sent by the source (e.g. iTunes) to the player, and is from 0.00 down to -30.00, with -144.00 meaning "mute". This is linear on the volume control slider of iTunes or iOS AirPlay. If the volume setting is being ignored by Shairport Sync itself, the volume, lowest_volume and highest_volume values are zero.
+ * `prgr` -- progress -- this is metadata from AirPlay consisting of RTP timestamps for the start of the current play sequence, the current play point and the end of the play sequence.
+ * `mdst` -- a sequence of metadata is about to start. The RTP timestamp associated with the metadata sequence is included as data, if available.
+ * `mden` -- a sequence of metadata has ended. The RTP timestamp associated with the metadata sequence is included as data, if available.
+ * `pcst` -- a picture is about to be sent. The RTP timestamp associated with it is included as data, if available.
+ * `pcen` -- a picture has been sent. The RTP timestamp associated with it is included as data, if available.
+ * `snam` -- a device e.g. "Joe's iPhone" has started a play session. Specifically, it's the "X-Apple-Client-Name" string.
+ * `snua` -- a "user agent" e.g. "iTunes/12..." has started a play session. Specifically, it's the "User-Agent" string.
+ * `stal` -- this is an error message meaning that reception of a large piece of metadata, usually a large picture, has stalled; bad things may happen.
+
+
+Parsed Messages
+----
+
+The MQTT service can parse the above raw messages into a subset of human-readable topics that include,
+
+* `artist` -- text of artist name
+* `album` -- text of album name
+* `title` -- text of song title
+* `genre` -- text of genre
+* `format` -- ??
+* `songalbum` --
+* `volume` -- The volume is sent as a string -- "airplay_volume,volume,lowest_volume,highest_volume", where "volume", "lowest_volume" and "highest_volume" are given in dB. (see above)
+* `client_ip` -- IP address of the connected client
+
+and empty messages at the following topics are published.
+
+* `play_start` -- fired at the begining of every song
+* `play_end` -- fired at the end of every song
+* `play_flush` -- fired when song is skipped or on positional change
+* `play_resume` -- fired when song play resumes from pause
+* `active_start` -- fired when a new active airplay session begins
+* `active_end` -- fired after a configured timeout period after the stream ends (unless a new stream begins)
+
+
+
+## Consuming MQTT Data
+
+Users will find examples on how to consume the MQTT data in various home automation projects. If a user has an interesting use please raise a new issue to suggest adding it to the guide, or simply fork the development branch and create a pull-request.
+
+### Home Assistant Variable Templates
+
+Examples of consuming "parsed" MQTT data in [Home Assistant](https://www.home-assistant.io/)
+The `active_start` and `active_end` have good potential use as triggers to turn on and off various connect receivers/zones. The messages published are empty and therefor no "payload_on" is set, "payload_off" however is set to prevent accidental triggering.
+
+```yml
+binary_sensor:
+
+ - platform: mqtt
+ name: "shairport active start"
+ state_topic: "shairport/active_start"
+ payload_on: ""
+ payload_off: "OFF"
+ off_delay: 300
+
+ - platform: mqtt
+ name: "shairport active end"
+ state_topic: "shairport/active_end"
+ payload_on: ""
+ payload_off: "OFF"
+ off_delay: 300
+```
+
+Below parsed data is saved into the Home Assistant database as sensor data. Please not the conversion of the volume from dB to percentage.
+
+```yml
+sensor:
+ - platform: mqtt
+ name: "shairport album"
+ state_topic: "shairport/album"
+ expire_after: 600
+
+ - platform: mqtt
+ name: "shairport artist"
+ state_topic: "shairport/artist"
+ expire_after: 600
+
+ - platform: mqtt
+ name: "shairport title"
+ state_topic: "shairport/title"
+ expire_after: 600
+
+ - platform: mqtt
+ name: "shairport genre"
+ state_topic: "shairport/genre"
+ expire_after: 600
+
+ - platform: mqtt
+ name: "shairport volume (dB)"
+ state_topic: "shairport/volume"
+
+ - platform: mqtt
+ name: "shairport volume (PCT)"
+ state_topic: "shairport/volume"
+ value_template: "{{ value | regex_findall_index(find='^(.+?),', index=0, ignorecase=False) | float / 30 + 1 }}"
+ unit_of_measurement: 'percent'
+```
diff --git a/README.md b/README.md
index fde314f..38c7075 100644
--- a/README.md
+++ b/README.md
@@ -42,6 +42,7 @@ What else?
* An [MPRIS](https://specifications.freedesktop.org/mpris-spec/2.2/) interface, partially complete and very functional, including access to metadata and artwork, and some limited remote control.
* An interface to [MQTT](https://en.wikipedia.org/wiki/MQTT), an often-used protocol in home automation projects.
* A native D-Bus interface, including access to metadata and artwork, some limited remote control and some system settings.
+* Digital Signal Processing facilities -- please see the [DSP Wiki Page Guide](https://github.com/mikebrady/shairport-sync/wiki/Digital-Signal-Processing-with-Shairport-Sync). (Thanks to [Yann Pomarède](https://github.com/yannpom) for the code and to [Paul Wieland](https://github.com/PaulWieland) for the guide.)
Heritage
-------
@@ -71,6 +72,8 @@ Shairport Sync may already be available as a package in your Linux distribution
**Debian:** shairport-sync is in the Debian archive.
+**Ansible Playbooks for CentOS 8 Stream on Raspberry Pi:** A suite of Ansible playbooks and scripts to make deploying Shairport Sync easy on CentOS 8 Stream specifically on Raspberry Pi is available at https://github.com/p3ck/ansible-shairport.
+
**OpenWrt:** There is a Shairport Sync package in OpenWrt trunk. Also, there's an OpenWrt package at https://github.com/mikebrady/shairport-sync-for-openwrt, including one that builds back to Barrier Breaker.
**Arch Linux:** Shairport Sync is available for x86_64 and i686 platforms in the Arch Linux Community Repository -- search for `shairport-sync`. See also https://www.archlinux.org/packages/.
@@ -85,6 +88,8 @@ Note that the installation uses the libao library and so synchronisation is not
**Fedora:** Please see the guide at [FEDORA.md](https://github.com/mikebrady/shairport-sync/blob/master/FEDORA.md).
+**Gentoo:** Shairport Sync is available in griffon_overlay, please see the guide at [https://github.com/windfail/griffon_overlay/wiki/shairport-sync](https://github.com/windfail/griffon_overlay/wiki/shairport-sync).
+
**Cygwin:** Please see the guide at [CYGWIN.md](https://github.com/mikebrady/shairport-sync/blob/master/CYGWIN.md).
Sincere thanks to all package contributors!
@@ -95,7 +100,7 @@ If you wish to build and install the latest version of Shairport Sync on Debian,
You should check to see if `shairport-sync` is already installed – you can use the command `$ which shairport-sync` to find where it is located, if installed. If it is installed you should delete it – you may need superuser privileges. After deleting, check again in case further copies are installed elsewhere.
-You should also remove the startup script files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service` and `/etc/init.d/shairport-sync` if they exist – new ones will be installed in necessary.
+You should also remove the startup script and service definition files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service`, `/etc/init.d/shairport-sync`, `/etc/dbus-1/system.d/shairport-sync-dbus.conf` and `/etc/dbus-1/system.d/shairport-sync-mpris.conf` if they exist – new ones will be installed if necessary.
If you removed any installations of Shairport Sync or any of its startup script files, you should reboot.
@@ -629,3 +634,12 @@ If you are using WiFi, you should ensure that WiFi power management is off. See
Troubleshooting
---------------
Please refer to [TROUBLESHOOTING](https://github.com/mikebrady/shairport-sync/blob/master/TROUBLESHOOTING.md) for a few hints, contributed by users.
+
+MQTT
+---------------
+Please refer to the [MQTT INFO](https://github.com/mikebrady/shairport-sync/blob/master/MQTT.md) page for additional info on building, configuring and using MQTT to interface shairport-sync with common home automation systems (contributed by users).
+
+Packaging status
+----------------
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/shairport-sync.svg)](https://repology.org/project/shairport-sync/versions)
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 273b666..e86b136 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -1,5 +1,18 @@
Please see the [Release Notes for 3.3](https://github.com/mikebrady/shairport-sync/releases/tag/3.3).
+Version 3.3.8
+====
+**Enhancements**
+* Documentation for the MQTT interface. Many thanks to [minix1234](https://github.com/minix1234)!
+
+**Bug Fixes**
+* Fix a bug in the `alsa` back end. In the interval between checking that the alsa device handle was non-`NULL` and actually using it, the handle could be set to `NULL`. The interval between check and usage is now protected.
+* Fix a bug in the `alsa` precision timing code. Thanks to [durwin99](https://github.com/durwin99), [Nicolas Da Mutten](https://github.com/cleverer), [mistakenideas](https://github.com/mistakenideas), [Ben Willmore](https://github.com/ben-willmore) and [giggywithit](https://github.com/giggywithit) for the [report](https://github.com/mikebrady/shairport-sync/issues/1158).
+* Fix a bug that caused Shairport Sync to hang, but not actually crash, if an `on-...` script failed.
+* Fix a crash that occurred if metadata support is enabled during compilation but turned off in the configuration file. Thanks to [Tim Curtis](https://github.com/moodeaudio) for the report.
+* Fix a crash that occurred playing from AirPower on Android. Thanks to [Ircama](https://github.com/Ircama) for the report.
+* Fix the configure.ac file so that `--without-<feature>` configuration options are not interpreted as `--with-<feature>` options instead! Thanks to [David Racine](https://github.com/bassdr) for the report.
+
Version 3.3.7
====
**Docker Integration**
diff --git a/UPDATING.md b/UPDATING.md
index 5803e27..6988528 100644
--- a/UPDATING.md
+++ b/UPDATING.md
@@ -29,8 +29,8 @@ Remove it as follows:
```
Do this until no more copies of `shairport-sync` are found. This is especially important if you are building Shairport Sync over an old version that was installed from packages, as the built application will be installed in a different directory to the packaged installation.
-### Remove Old Startup Scripts
-You should also remove the startup script files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service` and `/etc/init.d/shairport-sync` if they exist – new ones will be installed if necessary. As with the previous section, this is especially important if you are building Shairport Sync over an old version that was installed from packages, as the scripts for the built application may be different to those of the packaged version. If they are left in place, bad things can happen.
+### Remove Old Startup and Service Scripts
+You should also remove the startup script and service definition files `/etc/systemd/system/shairport-sync.service`, `/lib/systemd/system/shairport-sync.service`, `/etc/init.d/shairport-sync`, `/etc/dbus-1/system.d/shairport-sync-dbus.conf` and `/etc/dbus-1/system.d/shairport-sync-mpris.conf` if they exist – new ones will be installed if necessary. As with the previous section, this is especially important if you are building Shairport Sync over an old version that was installed from packages, as the scripts for the built application may be different to those of the packaged version. If they are left in place, bad things can happen.
### Reboot after Cleaning Up
If you removed any installations of Shairport Sync or any of its startup script files in the last two steps, you should reboot.
diff --git a/audio_alsa.c b/audio_alsa.c
index 69722d1..b464279 100644
--- a/audio_alsa.c
+++ b/audio_alsa.c
@@ -1455,19 +1455,31 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
int ret = snd_pcm_status(alsa_handle, alsa_snd_pcm_status);
if (ret == 0) {
-// must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
-#if SND_LIB_MINOR == 0
snd_pcm_status_get_htstamp(alsa_snd_pcm_status, &update_timestamp);
-#else
- snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &update_timestamp);
+
+/*
+// must be 1.1 or later to use snd_pcm_status_get_driver_htstamp
+#if SND_LIB_MINOR != 0
+ snd_htimestamp_t driver_htstamp;
+ snd_pcm_status_get_driver_htstamp(alsa_snd_pcm_status, &driver_htstamp);
+ uint64_t driver_htstamp_ns = driver_htstamp.tv_sec;
+ driver_htstamp_ns = driver_htstamp_ns * 1000000000;
+ driver_htstamp_ns = driver_htstamp_ns + driver_htstamp.tv_nsec;
+ debug(1,"driver_htstamp: %f.", driver_htstamp_ns * 0.000000001);
#endif
+*/
*state = snd_pcm_status_get_state(alsa_snd_pcm_status);
if ((*state == SND_PCM_STATE_RUNNING) || (*state == SND_PCM_STATE_DRAINING)) {
- uint64_t update_timestamp_ns =
- update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
+ // uint64_t update_timestamp_ns =
+ // update_timestamp.tv_sec * (uint64_t)1000000000 + update_timestamp.tv_nsec;
+
+ uint64_t update_timestamp_ns = update_timestamp.tv_sec;
+ update_timestamp_ns = update_timestamp_ns * 1000000000;
+ update_timestamp_ns = update_timestamp_ns + update_timestamp.tv_nsec;
+
// if the update_timestamp is zero, we take this to mean that the device doesn't report
// interrupt timings. (It could be that it's not a real hardware device.)
@@ -1497,7 +1509,7 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
if (update_timestamp_ns == 0) {
ret = snd_pcm_delay(alsa_handle, delay);
} else {
- *delay = snd_pcm_status_get_delay(alsa_snd_pcm_status);
+ snd_pcm_sframes_t delay_temp = snd_pcm_status_get_delay(alsa_snd_pcm_status);
/*
// It seems that the alsa library uses CLOCK_REALTIME before 1.0.28, even though
@@ -1514,11 +1526,15 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
else
clock_gettime(CLOCK_REALTIME, &tn);
- uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
+ // uint64_t time_now_ns = tn.tv_sec * (uint64_t)1000000000 + tn.tv_nsec;
+ uint64_t time_now_ns = tn.tv_sec;
+ time_now_ns = time_now_ns * 1000000000;
+ time_now_ns = time_now_ns + tn.tv_nsec;
+
// see if it's stalled
- if ((stall_monitor_start_time != 0) && (stall_monitor_frame_count == *delay)) {
+ if ((stall_monitor_start_time != 0) && (stall_monitor_frame_count == delay_temp)) {
// hasn't outputted anything since the last call to delay()
if (((update_timestamp_ns - stall_monitor_start_time) > stall_monitor_error_threshold) ||
@@ -1539,19 +1555,27 @@ int precision_delay_and_status(snd_pcm_state_t *state, snd_pcm_sframes_t *delay,
}
} else {
stall_monitor_start_time = update_timestamp_ns;
- stall_monitor_frame_count = *delay;
+ stall_monitor_frame_count = delay_temp;
}
if (ret == 0) {
uint64_t delta = time_now_ns - update_timestamp_ns;
- uint64_t frames_played_since_last_interrupt =
- ((uint64_t)config.output_rate * delta) / 1000000000;
+// uint64_t frames_played_since_last_interrupt =
+// ((uint64_t)config.output_rate * delta) / 1000000000;
+
+ uint64_t frames_played_since_last_interrupt = config.output_rate;
+ frames_played_since_last_interrupt = frames_played_since_last_interrupt * delta;
+ frames_played_since_last_interrupt = frames_played_since_last_interrupt / 1000000000;
+
+
snd_pcm_sframes_t frames_played_since_last_interrupt_sized =
frames_played_since_last_interrupt;
-
- *delay = *delay - frames_played_since_last_interrupt_sized;
+ if ((frames_played_since_last_interrupt_sized < 0) || ((uint64_t)frames_played_since_last_interrupt_sized != frames_played_since_last_interrupt))
+ debug(1,"overflow resizing frames_played_since_last_interrupt % " PRIx64 " to frames_played_since_last_interrupt %lx.", frames_played_since_last_interrupt, frames_played_since_last_interrupt_sized);
+ delay_temp = delay_temp - frames_played_since_last_interrupt_sized;
}
+ *delay = delay_temp;
}
} else { // not running, thus no delay information, thus can't check for
// stall
@@ -1582,25 +1606,26 @@ int delay(long *the_delay) {
// sps_extra_code_output_state_cannot_make_ready codes
int ret = 0;
*the_delay = 0;
- if (alsa_handle == NULL)
- ret = ENODEV;
- else {
- int oldState;
- snd_pcm_state_t state;
- snd_pcm_sframes_t my_delay = 0; // this initialisation is to silence a clang warning
+ int oldState;
- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable
- pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 0);
+ snd_pcm_state_t state;
+ snd_pcm_sframes_t my_delay = 0; // this initialisation is to silence a clang warning
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable
+ pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 0);
+
+ if (alsa_handle == NULL)
+ ret = ENODEV;
+ else
ret = delay_and_status(&state, &my_delay, NULL);
- debug_mutex_unlock(&alsa_mutex, 0);
- pthread_cleanup_pop(0);
- pthread_setcancelstate(oldState, NULL);
+ debug_mutex_unlock(&alsa_mutex, 0);
+ pthread_cleanup_pop(0);
+ pthread_setcancelstate(oldState, NULL);
+
+ *the_delay = my_delay; // note: snd_pcm_sframes_t is a long
- *the_delay = my_delay; // note: snd_pcm_sframes_t is a long
- }
return ret;
}
diff --git a/common.c b/common.c
index b48adad..6e0f12a 100644
--- a/common.c
+++ b/common.c
@@ -831,10 +831,10 @@ void command_set_volume(double volume) {
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(EXIT_FAILURE); /* only if execv fails */
+ _exit(EXIT_FAILURE); /* only if execv fails */
}
}
-
+ _exit(EXIT_SUCCESS);
} else {
if (config.cmd_blocking) { /* pid!=0 means parent process and if blocking is true, wait for
process to finish */
@@ -886,7 +886,7 @@ void command_start(void) {
execv(argV[0], argV);
warn("Execution of on-start command failed to start");
debug(1, "Error executing on-start command %s", config.cmd_start);
- exit(EXIT_FAILURE); /* only if execv fails */
+ _exit(EXIT_FAILURE); /* only if execv fails */
}
} else {
if (config.cmd_blocking || config.cmd_start_returns_output) { /* pid!=0 means parent process
@@ -942,7 +942,7 @@ void command_execute(const char *command, const char *extra_argument, const int
execv(argV[0], argV);
warn("Execution of command \"%s\" failed to start", full_command);
debug(1, "Error executing command \"%s\".", full_command);
- exit(EXIT_FAILURE); /* only if execv fails */
+ _exit(EXIT_FAILURE); /* only if execv fails */
}
} else {
if (block) { /* pid!=0 means parent process and if blocking is true, wait for
diff --git a/configure.ac b/configure.ac
index ed0dcda..f77087c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.50])
-AC_INIT([shairport-sync], [3.3.7], [4265913+mikebrady@users.noreply.github.com])
+AC_INIT([shairport-sync], [3.3.8], [4265913+mikebrady@users.noreply.github.com])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([shairport.c])
AC_CONFIG_HEADERS([config.h])
@@ -17,6 +17,10 @@ if test "z$with_os" = "z"; then
fi
with_os=`echo ${with_os} | tr '[[:upper:]]' '[[:lower:]]' `
+if test "x${with_os}" != xlinux && "x${with_os}" != xfreebsd && "x${with_os}" != xdarwin ; then
+ AC_MSG_ERROR(--with-os=<arg> argument must linux, freebsd, openbsd or darwin)
+fi
+
# Checks for programs.
AC_PROG_CC
AC_PROG_CXX
@@ -40,9 +44,9 @@ AM_CONDITIONAL([BUILD_FOR_OPENBSD], [test "x${with_os}" = xopenbsd ])
##### Some build systems are not fully using pkg-config, so we can use the flag ${with_pkg_config} on a case-by-case basis
##### to control how to deal with them
+##### Note -- this flag is sometimes ignored, especially for newer packages
-AC_ARG_WITH([pkg_config],
-[ --with-pkg-config = use pkg-config to find libraries], ,[with_pkg_config=yes])
+AC_ARG_WITH([pkg_config],[AS_HELP_STRING([--with-pkg-config],[use pkg-config to find libraries])],[],[with_pkg_config=yes])
##### The following check for the pthreads library doesn't put the compiler into the correct pthread mode
##### so we add the -pthread compilation flag in AMFLAGS in the Makefile.am as well.
@@ -50,145 +54,149 @@ AC_ARG_WITH([pkg_config],
AC_CHECK_LIB([pthread],[pthread_create], , AC_MSG_ERROR(pthread library needed))
AC_CHECK_LIB([m],[exp], , AC_MSG_ERROR(maths library needed))
-AC_MSG_RESULT(>>Including libpopt)
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
- [POPT], [popt],
- [CFLAGS="${POPT_CFLAGS} ${CFLAGS}"
- LIBS="${POPT_LIBS} ${LIBS}"])
+ [popt], [popt],
+ [CFLAGS="${popt_CFLAGS} ${CFLAGS}"
+ LIBS="${popt_LIBS} ${LIBS}"], AC_MSG_ERROR(libpopt needed))
else
AC_CHECK_LIB([popt],[poptGetContext], , AC_MSG_ERROR(libpopt needed))
fi
-AC_ARG_WITH([dummy],[ --with-dummy = include the dummy audio back end ],[AC_MSG_RESULT(>>Including the dummy audio back end) AC_DEFINE([CONFIG_DUMMY], 1, [Needed by the compiler.]) ], )
+AC_ARG_WITH([dummy],[AS_HELP_STRING([--with-dummy],[include the dummy audio back end])])
+if test "x$with_dummy" = "xyes" ; then
+ AC_MSG_RESULT(include the dummy audio back end)
+ AC_DEFINE([CONFIG_DUMMY], 1, [Include a fake audio backend.])
+fi
AM_CONDITIONAL([USE_DUMMY], [test "x$with_dummy" = "xyes" ])
-AC_ARG_WITH([stdout],[ --with-stdout = include the stdout audio back end ],[ AC_MSG_RESULT(>>Including the stdout audio back end) AC_DEFINE([CONFIG_STDOUT], 1, [Needed by the compiler.]) ], )
-AM_CONDITIONAL([USE_STDOUT], [test "x$with_stdout" = "xyes" ])
+AC_ARG_WITH([stdout],[AS_HELP_STRING([--with-stdout],[include the stdout audio back end])])
+if test "x$with_stdout" = "xyes" ; then
+ AC_MSG_RESULT(include the stdout audio back end)
+ AC_DEFINE([CONFIG_STDOUT], 1, [Include an audio backend to output to standard output (stdout).])
+fi
+AM_CONDITIONAL([USE_STDOUT], [test "x$with_stdout" = "xyes"])
-AC_ARG_WITH([pipe],[ --with-pipe = include the pipe audio back end ],[ AC_MSG_RESULT(>>Including the pipe audio back end) AC_DEFINE([CONFIG_PIPE], 1, [Needed by the compiler.]) ], )
+AC_ARG_WITH([pipe],[AS_HELP_STRING([--with-pipe],[include the pipe audio back end])])
+if test "x$with_pipe" = "xyes" ; then
+ AC_MSG_RESULT(include the pipe audio back end)
+ AC_DEFINE([CONFIG_PIPE], 1, [Include an audio backend to output to a unix pipe.])
+fi
AM_CONDITIONAL([USE_PIPE], [test "x$with_pipe" = "xyes" ])
# Check to see if we should include the System V initscript
-AC_ARG_WITH([systemv],
-[ --with-systemv = install a System V startup script during a make install], , )
+AC_ARG_WITH([systemv],[AS_HELP_STRING([--with-systemv],[install a System V startup script during a make install])])
AM_CONDITIONAL([INSTALL_SYSTEMV], [test "x$with_systemv" = "xyes"])
# Check to see if we should include the systemd stuff to define it as a service
-AC_ARG_WITH([systemd],
-[ --with-systemd = install a systemd startup script during a make install], , )
+AC_ARG_WITH([systemd],[AS_HELP_STRING([--with-systemd],[install a systemd startup script during a make install])])
AM_CONDITIONAL([INSTALL_SYSTEMD], [test "x$with_systemd" = "xyes"])
-AC_ARG_WITH([freebsd-service],
-[ --with-freebsd-service = install a FreeBSD startup script during a make install], , )
+AC_ARG_WITH([freebsd-service],[AS_HELP_STRING([--with-freebsd-service],[install a FreeBSD startup script during a make install])])
AM_CONDITIONAL([INSTALL_FREEBSD_SERVICE], [test "x$with_freebsd_service" = "xyes"])
-AC_ARG_WITH([cygwin-service],
-[ --with-cygwin-service = install a CYGWIN config script during a make install], , )
+AC_ARG_WITH([cygwin-service],[AS_HELP_STRING([--with-cygwin-service],[install a CYGWIN config script during a make install])])
AM_CONDITIONAL([INSTALL_CYGWIN_SERVICE], [test "x$with_cygwin_service" = "xyes"])
-AC_ARG_WITH([external-mdns],[ --with-external-mdns = support the use of 'avahi-publish-service' or 'mDNSPublish' to advertise the service on Bonjour/ZeroConf ],[ AC_MSG_RESULT(>>Including external mdns support) AC_DEFINE([CONFIG_EXTERNAL_MDNS], 1, [Needed by the compiler.]) ], )
+AC_ARG_WITH([external-mdns],[AS_HELP_STRING([--with-external-mdns],[support the use of 'avahi-publish-service' or 'mDNSPublish' to advertise the service on Bonjour/ZeroConf])])
+if test "x$with_external_mdns" = xyes ; then
+ AC_MSG_RESULT(include external mdns support)
+ AC_DEFINE([CONFIG_EXTERNAL_MDNS], 1, [Use 'avahi-publish-service' or 'mDNSPublish' to advertise.])
+fi
AM_CONDITIONAL([USE_EXTERNAL_MDNS], [test "x$with_external_mdns" = "xyes" ])
# Add the libconfig package
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
- [LIBCONFIG], [libconfig],
- [LIBS="${LIBCONFIG_LIBS} ${LIBS}"])
+ [libconfig], [libconfig],
+ [LIBS="${libconfig_LIBS} ${LIBS}"], AC_MSG_ERROR([libconfig library needed]))
else
AC_CHECK_LIB([config],[config_init], , AC_MSG_ERROR([libconfig library needed]))
fi
-AC_ARG_WITH([configfiles],
-[ --with-configfiles = install configuration files during a make install ], ,[with_configfiles=yes])
+AC_ARG_WITH([configfiles],[AS_HELP_STRING([--with-configfiles],[install configuration files during a make install])], ,[with_configfiles=yes])
AM_CONDITIONAL([INSTALL_CONFIG_FILES], [test "x$with_configfiles" = "xyes"])
# Look for Apple ALAC flag
-AC_ARG_WITH(apple-alac, [ --with-apple-alac = include support for the Apple ALAC decoder],
- [AC_MSG_RESULT(>>Including the Apple ALAC Decoder)
+AC_ARG_WITH(apple-alac,[AS_HELP_STRING([--with-apple-alac],[include support for the Apple ALAC decoder])])
+if test "x${with_apple_alac}" = "xyes" ; then
AC_DEFINE([CONFIG_APPLE_ALAC], 1, [Include support for using the Apple ALAC Decoder])
- REQUESTED_APPLE_ALAC=1
if test "x${with_pkg_config}" = xyes ; then
- PKG_CHECK_MODULES(
- [ALAC], [alac],
- [LIBS="${ALAC_LIBS} ${LIBS}"])
+ PKG_CHECK_MODULES([alac], [alac], [LIBS="${alac_LIBS} ${LIBS}"], AC_MSG_ERROR(Apple ALAC Decoder support requires the ALAC library. See https://github.com/mikebrady/alac.))
else
- AC_CHECK_LIB([alac], [BitBufferInit], , AC_MSG_ERROR(Apple ALAC Decoder support requires the alac library!))
- fi ])
-AM_CONDITIONAL([USE_APPLE_ALAC], [test "x$REQUESTED_APPLE_ALAC" = "x1"])
+ AC_CHECK_LIB([alac], [BitBufferInit], , AC_MSG_ERROR(Apple ALAC Decoder support requires the ALAC library. See https://github.com/mikebrady/alac.))
+ fi
+fi
+AM_CONDITIONAL([USE_APPLE_ALAC], [test "x${with_apple_alac}" = "xyes"])
# Look for piddir flag
-AC_ARG_WITH(piddir, [ --with-piddir=<pathname> Specify a pathname to a directory in which to write the PID file.], [
+AC_ARG_WITH(piddir, [AS_HELP_STRING([--with-piddir=<pathname>],[Specify a pathname to a directory in which to write the PID file.])])
+if test "x${with_piddir}" != "x" ; then
AC_MSG_CHECKING(--with-piddir argument)
if test "x${with_piddir}" = x -o "x${with_piddir}" = xyes ; then
AC_MSG_RESULT(not found)
AC_MSG_ERROR(when you use the --with-piddir directive you must specify the pathname of the directory into which the PID file will be written)
fi
AC_MSG_RESULT(${with_piddir})
- REQUESTED_CUSTOMPIDDIR=1
- AC_SUBST(CUSTOM_PID_DIR,["${with_piddir}"])
- AC_DEFINE([DEFINED_CUSTOM_PID_DIR],1,[Hook up special proc to libdaemon to point to this directory])], )
-AM_CONDITIONAL([USE_CUSTOMPIDDIR], [test "x$REQUESTED_CUSTOMPIDDIR" = "x1"])
-
+ AC_SUBST(CUSTOM_PID_DIR,["${with_piddir}"])
+ AC_DEFINE([DEFINED_CUSTOM_PID_DIR],1,[Hook up special proc to libdaemon to point to this directory])
+fi
+AM_CONDITIONAL([USE_CUSTOMPIDDIR], [ test "x${with_piddir}" != "x" ])
# Look for libdaemon
-AC_ARG_WITH(libdaemon, [--with-libdaemon = include support for daemonising in non-systemd systems], REQUESTED_LIBDAEMON=1, )
-if test "x$REQUESTED_LIBDAEMON" = "x1"; then
- AC_MSG_RESULT(>>Including libdaemon support for older systems)
- AC_DEFINE([CONFIG_LIBDAEMON], 1, [Include libdaemon])
+AC_ARG_WITH(libdaemon,[AS_HELP_STRING([--with-libdaemon],[include support for daemonising in non-systemd systems])])
+if test "x$with_libdaemon" = "xyes"; then
+ AC_DEFINE([CONFIG_LIBDAEMON], 1, [Include libdaemon for daemonising in non-systemd systems])
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
[DAEMON], [libdaemon],
- [LIBS="${DAEMON_LIBS} ${LIBS}"])
+ [LIBS="${DAEMON_LIBS} ${LIBS}"],
+ [AC_MSG_ERROR(the libdaemon library has been selected but is missing -- libdaemon-dev suggested!)])
else
- AC_CHECK_LIB([daemon],[daemon_fork], , AC_MSG_ERROR(libdaemon needed))
+ AC_CHECK_LIB([daemon],[daemon_fork], , AC_MSG_ERROR(the libdaemon library has been selected but is missing -- libdaemon-dev suggested!))
fi
fi
-AM_CONDITIONAL([USE_LIBDAEMON], [test "x$REQUESTED_LIBDAEMON" = "x1"])
+AM_CONDITIONAL([USE_LIBDAEMON], [test "x$with_libdaemon" = "xyes"])
# Check --with-ssl=argument
-AC_ARG_WITH(ssl, [ choose --with-ssl=openssl, --with-ssl=mbedtls or --with-ssl=polarssl (deprecated) for encryption services ], [
- AC_MSG_CHECKING(encryption libraries chosen)
- if test "x${with_ssl}" = x -o "x${with_ssl}" = xyes ; then
- AC_MSG_RESULT(not found)
- AC_MSG_ERROR(choose "openssl", "mbedtls" or "polarssl" encryption)
- fi
- if test "x${with_ssl}" = xopenssl ; then
- AC_DEFINE([CONFIG_OPENSSL], 1, [Use the OpenSSL libraries for encryption and encoding and decoding])
- if test "x${with_pkg_config}" = xyes ; then
- PKG_CHECK_MODULES(
- [SSL], [libssl,libcrypto],
- [LIBS="${SSL_LIBS} ${LIBS}"])
- else
- AC_CHECK_LIB([crypto], [main], , AC_MSG_ERROR(libcrypto selected but the library cannot be found!))
- AC_CHECK_LIB([ssl], [main], , AC_MSG_ERROR(libssl selected but the library cannot be found!))
- fi
- elif test "x${with_ssl}" = xmbedtls ; then
- AC_DEFINE([CONFIG_MBEDTLS], 1, [Use the mbed TLS libraries for encryption and encoding and decoding])
- AC_CHECK_LIB([mbedtls],[mbedtls_ssl_init],,
+AC_ARG_WITH(ssl, [AS_HELP_STRING([--with-ssl=<argument>],[choose --with-ssl=openssl, --with-ssl=mbedtls or --with-ssl=polarssl (deprecated) for encryption services ])])
+
+if test "x${with_ssl}" = xopenssl ; then
+ AC_DEFINE([CONFIG_OPENSSL], 1, [Use the OpenSSL libraries for encryption and encoding and decoding])
+ if test "x${with_pkg_config}" = xyes ; then
+ PKG_CHECK_MODULES(
+ [SSL], [libssl,libcrypto],
+ [LIBS="${SSL_LIBS} ${LIBS}"])
+ else
+ AC_CHECK_LIB([crypto], [main], , AC_MSG_ERROR(libcrypto selected but the library cannot be found!))
+ AC_CHECK_LIB([ssl], [main], , AC_MSG_ERROR(libssl selected but the library cannot be found!))
+ fi
+elif test "x${with_ssl}" = xmbedtls ; then
+ AC_DEFINE([CONFIG_MBEDTLS], 1, [Use the mbed TLS libraries for encryption and encoding and decoding])
+ AC_CHECK_LIB([mbedtls],[mbedtls_ssl_init],,
[AC_MSG_ERROR([mbed tls support requires the mbedtls library -- libmbedtls-dev suggested],1)])
- AC_CHECK_LIB([mbedcrypto], [mbedtls_entropy_func],,
- [AC_MSG_ERROR([mbed tls support requires the mbedcrypto library -- libmbedcrypto0 suggested],1)])
- AC_CHECK_LIB([mbedx509], [mbedtls_pk_init],,
- [AC_MSG_ERROR([mbed tls support requires the mbedx509 library -- libmbedx509-0 suggested],1)])
- elif test "x${with_ssl}" = xpolarssl ; then
- AC_DEFINE([CONFIG_POLARSSL], 1, [Use the PolarSSL libraries for encryption and encoding and decoding])
- AC_CHECK_LIB([polarssl],[ssl_init], , AC_MSG_ERROR(PolarSSL is selected but the library cannot be found and is deprecated. Consider selecting mbed TLS instead using --with-ssl=mbedtls.))
- else
- AC_MSG_ERROR(unknown option "${with_ssl}"." Please choose with "openssl", "mbedtls" or "polarssl")
- fi
-], )
+ AC_CHECK_LIB([mbedcrypto], [mbedtls_entropy_func],,
+ [AC_MSG_ERROR([mbed tls support requires the mbedcrypto library -- libmbedcrypto0 suggested],1)])
+ AC_CHECK_LIB([mbedx509], [mbedtls_pk_init],,
+ [AC_MSG_ERROR([mbed tls support requires the mbedx509 library -- libmbedx509-0 suggested],1)])
+elif test "x${with_ssl}" = xpolarssl ; then
+ AC_DEFINE([CONFIG_POLARSSL], 1, [Use the PolarSSL libraries for encryption and encoding and decoding])
+ AC_CHECK_LIB([polarssl],[ssl_init], , AC_MSG_ERROR(PolarSSL is selected but the library libpolarssl-dev does not seem to be installed and is deprecated. Consider selecting mbedtls instead using --with-ssl=mbedtls.))
+else
+ AC_MSG_ERROR(specify one of --with-ssl=openssl or --with-ssl=mbedtls or --with-ssl=polarssl)
+fi
# Look for soxr flag
-AC_ARG_WITH(soxr, [ --with-soxr = choose libsoxr for high-quality interpolation], [
- AC_MSG_RESULT(>>Including support for soxr-based interpolation)
+
+AC_ARG_WITH(soxr, [AS_HELP_STRING([--with-soxr],[choose libsoxr for high-quality interpolation])])
+if test "x$with_soxr" = "xyes" ; then
AC_DEFINE([CONFIG_SOXR], 1, [Include support for using the SoX Resampler library for interpolation])
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
- [SOXR], [soxr],
- [LIBS="${SOXR_LIBS} ${LIBS}"],
+ [soxr], [soxr],
+ [LIBS="${soxr_LIBS} ${LIBS}"],
[AC_MSG_ERROR(soxr support requires the libsoxr library -- libsoxr-dev suggested!)])
else
AC_CHECK_LIB([avutil],[av_get_cpu_flags])
@@ -199,89 +207,87 @@ AC_ARG_WITH(soxr, [ --with-soxr = choose libsoxr for high-quality interpolation
AC_CHECK_LIB([soxr],[soxr_create], , AC_MSG_ERROR(soxr support requires the libsoxr library -- libsoxr-dev suggested!))
fi
fi
-], )
+fi
# Look for metadata flag and resolve it further down the script
-AC_ARG_WITH(metadata, [ --with-metadata = include support for a metadata feed], [
- REQUESTED_METADATA=1], )
+AC_ARG_WITH(metadata,[AS_HELP_STRING([--with-metadata],[include support for a metadata feed])])
# What follows is a bit messy, because if the relevant library is requested, a compiler flag is defined, a file is included in the compilation
# and the relevant link files are added.
# Look for avahi flag
-AC_ARG_WITH(avahi, [ --with-avahi = choose Avahi-based mDNS support], [
- AC_MSG_RESULT(>>Including Avahi mDNS support)
- REQUESTED_AVAHI=1
- AC_DEFINE([CONFIG_AVAHI], 1, [Needed by the compiler.])
+AC_ARG_WITH(avahi, [AS_HELP_STRING([--with-avahi],[choose Avahi-based mDNS support])])
+if test "x$with_avahi" = "xyes" ; then
+ AC_DEFINE([CONFIG_AVAHI], 1, [Include Avahi-based mDNS support.])
AC_CHECK_LIB([avahi-client], [avahi_client_new], , AC_MSG_ERROR(Avahi support requires the avahi-client library!))
- AC_CHECK_LIB([avahi-common],[avahi_strerror], , AC_MSG_ERROR(Avahi support requires the avahi-common library!))], )
-AM_CONDITIONAL([USE_AVAHI], [test "x$REQUESTED_AVAHI" = "x1"])
+ AC_CHECK_LIB([avahi-common],[avahi_strerror], , AC_MSG_ERROR(Avahi support requires the avahi-common library!))
+fi
+AM_CONDITIONAL([USE_AVAHI], [test "x$with_avahi" = "xyes"])
# Look for tinysvcmdns flag
-AC_ARG_WITH(tinysvcmdns, [ --with-tinysvcmdns = choose tinysvcmdns-based mDNS support], [
- AC_MSG_RESULT(>>Including tinysvcmdns mDNS support)
- REQUESTED_TINYSVCMDNS=1
- AC_DEFINE([CONFIG_TINYSVCMDNS], 1, [Needed by the compiler.])], )
-AM_CONDITIONAL([USE_TINYSVCMDNS], [test "x$REQUESTED_TINYSVCMDNS" = "x1"])
+AC_ARG_WITH(tinysvcmdns, [AS_HELP_STRING([--with-tinysvcmdns],[choose tinysvcmdns-based mDNS support])])
+if test "x$with_tinysvcmdns" = "xyes" ; then
+ AC_DEFINE([CONFIG_TINYSVCMDNS], 1, [Include TinySVCmDNS-based mDNS support])
+fi
+AM_CONDITIONAL([USE_TINYSVCMDNS], [test "x$with_tinysvcmdns" = "xyes"])
# Look for ALSA flag
-AC_ARG_WITH(alsa, [ --with-alsa = choose ALSA API support (GNU/Linux only)],
- [AC_MSG_RESULT(>>Including an ALSA back end)
- REQUESTED_ALSA=1
+AC_ARG_WITH(alsa, [AS_HELP_STRING([--with-alsa],[choose ALSA API support (GNU/Linux only)])])
+if test "x$with_alsa" = "xyes" ; then
AC_DEFINE([CONFIG_ALSA], 1, [Needed by the compiler.])
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
- [ALSA], [alsa],
- [LIBS="${ALSA_LIBS} ${LIBS}"])
+ [alsa], [alsa],
+ [LIBS="${alsa_LIBS} ${LIBS}"])
else
AC_CHECK_LIB([asound], [snd_pcm_open], , AC_MSG_ERROR(ALSA support requires the asound library!))
- fi ])
-AM_CONDITIONAL([USE_ALSA], [test "x$REQUESTED_ALSA" = "x1"])
+ fi
+fi
+AM_CONDITIONAL([USE_ALSA], [test "x$with_alsa" = "xyes"])
# Look for jack flag
-AC_ARG_WITH(jack, [ --with-jack = include a Jack Audio Connection Kit (jack) backend], [
- AC_MSG_RESULT(>>Including a Jack Audio Connection Kit (jack) back end)
- REQUESTED_JACK=1
- AC_DEFINE([CONFIG_JACK], 1, [Needed by the compiler.])
+AC_ARG_WITH(jack, [AS_HELP_STRING([--with-jack],[include a Jack Audio Connection Kit (jack) backend])])
+if test "x$with_jack" = "xyes" ; then
+ AC_DEFINE([CONFIG_JACK], 1, [Include a Jack Audio Connection Kit (jack) audio backend])
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
- [JACK], [jack],
- [LIBS="${JACK_LIBS} ${LIBS}"],
+ [jack], [jack],
+ [LIBS="${jack_LIBS} ${LIBS}"],
[AC_MSG_ERROR(Jack Audio Connection Kit support requires the jack library -- libjack-dev suggested!)])
else
AC_CHECK_LIB([jack], [jack_client_open], , AC_MSG_ERROR(Jack Audio Connection Kit support requires the jack library -- libjack-dev suggested!))
- fi ])
-AM_CONDITIONAL([USE_JACK], [test "x$REQUESTED_JACK" = "x1"])
+ fi
+fi
+AM_CONDITIONAL([USE_JACK], [test "x$with_jack" = "xyes"])
# Look for SNDIO flag
-AC_ARG_WITH(sndio, [ --with-sndio = choose SNDIO API support], [
- AC_MSG_RESULT(>>Including a SNDIO back end)
- REQUESTED_SNDIO=1
- AC_DEFINE([CONFIG_SNDIO], 1, [Needed by the compiler.])
- AC_CHECK_LIB([sndio], [sio_open], , AC_MSG_ERROR(SNDIO support requires the sndio library -- libsndio-dev suggested))], )
-AM_CONDITIONAL([USE_SNDIO], [test "x$REQUESTED_SNDIO" = "x1"])
+AC_ARG_WITH(sndio, [AS_HELP_STRING([--with-sndio],[choose SNDIO API support])])
+if test "x$with_sndio" = "xyes" ; then
+ AC_DEFINE([CONFIG_SNDIO], 1, [Include a sndio-compatible audio backend.])
+ AC_CHECK_LIB([sndio], [sio_open], , AC_MSG_ERROR(SNDIO support requires the sndio library -- libsndio-dev suggested))
+fi
+AM_CONDITIONAL([USE_SNDIO], [test "x$with_sndio" = "xyes"])
# Look for AO flag
-AC_ARG_WITH(ao, [ --with-ao = choose AO (Audio Output?) API support. N.B. no synchronisation -- so underflow or overflow is inevitable!], [
- AC_MSG_RESULT(>>Including an AO back end. N.B. no synchronisation -- so underflow or overflow is inevitable!)
- REQUESTED_AO=1
- AC_DEFINE([CONFIG_AO], 1, [Needed by the compiler.])
- AC_CHECK_LIB([ao], [ao_initialize], , AC_MSG_ERROR(AO support requires the ao library -- libao-dev suggested))], )
-AM_CONDITIONAL([USE_AO], [test "x$REQUESTED_AO" = "x1"])
+AC_ARG_WITH(ao, [AS_HELP_STRING([--with-ao],[choose AO (Audio Output?) API support. N.B. no synchronisation -- so underflow or overflow is inevitable!])])
+if test "x$with_ao" = "xyes" ; then
+ AC_DEFINE([CONFIG_AO], 1, [Include an AO-compatible audio backend.])
+ AC_CHECK_LIB([ao], [ao_initialize], , AC_MSG_ERROR(AO support requires the ao library -- libao-dev suggested))
+fi
+AM_CONDITIONAL([USE_AO], [test "x$with_ao" = "xyes"])
# Look for Soundio flag
-AC_ARG_WITH(soundio, [ --with-soundio = choose soundio API support.], [
- AC_MSG_RESULT(>>Including an soundio back end)
- REQUESTED_SOUNDIO=1
- AC_DEFINE([CONFIG_SOUNDIO], 1, [Needed by the compiler.])
- AC_CHECK_LIB([soundio], [soundio_create], , AC_MSG_ERROR(soundio support requires the soundio library -- libsoundio-dev suggested))], )
-AM_CONDITIONAL([USE_SOUNDIO], [test "x$REQUESTED_SOUNDIO" = "x1"])
+AC_ARG_WITH(soundio, [AS_HELP_STRING([--with-soundio],[choose soundio API support.])])
+if test "x$with_soundio" = "xyes" ; then
+ AC_DEFINE([CONFIG_SOUNDIO], 1, [Include SoundIO Support.])
+ AC_CHECK_LIB([soundio], [soundio_create], , AC_MSG_ERROR(soundio support requires the soundio library -- libsoundio-dev suggested))
+fi
+AM_CONDITIONAL([USE_SOUNDIO], [test "x$with_soundio" = "xyes"])
# Look for pulseaudio flag
-AC_ARG_WITH(pa, [ --with-pa = choose PulseAudio support.], [
- AC_MSG_RESULT(>>Including a PulseAudio back end.)
- REQUESTED_PA=1
- AC_DEFINE([CONFIG_PA], 1, [Needed by the compiler.])
+AC_ARG_WITH(pa, [AS_HELP_STRING([--with-pa],[choose PulseAudio support.])])
+if test "x$with_pa" = "xyes" ; then
+ AC_DEFINE([CONFIG_PA], 1, [Include PulseAudio support.])
if test "x${with_pkg_config}" = xyes ; then
PKG_CHECK_MODULES(
[PULSEAUDIO], [libpulse >= 0.9.2],
@@ -289,75 +295,70 @@ AC_ARG_WITH(pa, [ --with-pa = choose PulseAudio support.], [
else
AC_CHECK_LIB([pulse-simple], [pa_simple_new], , AC_MSG_ERROR(PulseAudio support requires the libpulse library!))
AC_CHECK_LIB([pulse], [pa_stream_peek], , AC_MSG_ERROR(PulseAudio support requires the libpulse-dev library.))
- fi ])
-AM_CONDITIONAL([USE_PA], [test "x$REQUESTED_PA" = "x1"])
+ fi
+fi
+AM_CONDITIONAL([USE_PA], [test "x$with_pa" = "xyes"])
# Look for Convolution flag
-AC_ARG_WITH(convolution, [ --with-convolution = choose audio DSP convolution support], [
- AC_MSG_RESULT(>>Including convolution support)
- REQUESTED_CONVOLUTION=1
+AC_ARG_WITH(convolution, [AS_HELP_STRING([--with-convolution],[choose audio DSP convolution support])])
+if test "x$with_convolution" = "xyes" ; then
AM_INIT_AUTOMAKE([subdir-objects])
- AC_DEFINE([CONFIG_CONVOLUTION], 1, [Needed by the compiler.])
- AC_CHECK_LIB([sndfile], [sf_open], , AC_MSG_ERROR(Convolution support requires the sndfile library -- libsndfile1-dev suggested!))], )
-AM_CONDITIONAL([USE_CONVOLUTION], [test "x$REQUESTED_CONVOLUTION" = "x1"])
+ AC_DEFINE([CONFIG_CONVOLUTION], 1, [Include audio DSP convolution support.])
+ AC_CHECK_LIB([sndfile], [sf_open], , AC_MSG_ERROR(Convolution support requires the sndfile library -- libsndfile1-dev suggested!))
+fi
+AM_CONDITIONAL([USE_CONVOLUTION], [test "x$with_convolution" = "xyes"])
# Look for dns_sd flag
-AC_ARG_WITH(dns_sd, [ --with-dns_sd = choose dns_sd mDNS support], [
- AC_MSG_RESULT(>>Including dns_sd for mDNS support)
- REQUESTED_DNS_SD=1
- AC_DEFINE([CONFIG_DNS_SD], 1, [Needed by the compiler.])
- AC_SEARCH_LIBS([DNSServiceRefDeallocate], [dns_sd], , AC_MSG_ERROR(dns_sd support requires the dns_sd library!))], )
-AM_CONDITIONAL([USE_DNS_SD], [test "x$REQUESTED_DNS_SD" = "x1"])
+AC_ARG_WITH(dns_sd, [AS_HELP_STRING([--with-dns_sd],[choose dns_sd mDNS support])])
+if test "x$with_dns_sd" = "xyes" ; then
+ AC_DEFINE([CONFIG_DNS_SD], 1, [Include dns_sd mDNS support.])
+ AC_SEARCH_LIBS([DNSServiceRefDeallocate], [dns_sd], , [AC_MSG_ERROR(dns_sd support requires the dns_sd library. Originally in Apple's mDNSResponder but also in libavahi-compat-libdnssd-dev.)])
+fi
+AM_CONDITIONAL([USE_DNS_SD], [test "x$with_dns_sd" = "xyes"])
# Look for dbus flag
-AC_ARG_WITH(dbus-interface, [ --with-dbus-interface = include support for the native Shairport Sync D-Bus interface], [
- AC_MSG_RESULT(>>Including dbus support)
- AC_DEFINE([CONFIG_DBUS_INTERFACE], 1, [Include support for the native Shairport Sync D-Bus interface])
- REQUESTED_DBUS=1
- PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0 >= 2.30.0],[CFLAGS="${GIO_UNIX_CFLAGS} ${CFLAGS}" LIBS="${GIO_UNIX_LIBS} ${LIBS}"],[AC_MSG_ERROR(dbus messaging support requires the glib 2.0 library -- libglib2.0-dev suggested!)])
- ], )
-AM_CONDITIONAL([USE_DBUS], [test "x$REQUESTED_DBUS" = "x1"])
+AC_ARG_WITH(dbus-interface, [AS_HELP_STRING([--with-dbus-interface],[include support for the native Shairport Sync D-Bus interface])])
+if test "x$with_dbus_interface" = "xyes" ; then
+ AC_DEFINE([CONFIG_DBUS_INTERFACE], 1, [Support the native Shairport Sync D-Bus interface])
+ # remember to include glib, below
+fi
+AM_CONDITIONAL([USE_DBUS], [test "x$with_dbus_interface" = "xyes"])
# Look for dbus test client flag
-AC_ARG_WITH(dbus-test-client, [ --with-dbus-test-client = compile dbus test client], [
- AC_MSG_RESULT(>>Including dbus test client)
- REQUESTED_DBUS_CLIENT=1
- PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0 >= 2.30.0],[CFLAGS="${GIO_UNIX_CFLAGS} ${CFLAGS}" LIBS="${GIO_UNIX_LIBS} ${LIBS}"],[AC_MSG_ERROR(dbus client support requires the glib 2.0 library -- libglib2.0-dev suggested!)])
- ], )
-AM_CONDITIONAL([USE_DBUS_CLIENT], [test "x$REQUESTED_DBUS_CLIENT" = "x1"])
+AC_ARG_WITH(dbus-test-client, [AS_HELP_STRING([--with-dbus-test-client],[compile a D-Bus test client application])])
+# remember to include glib, below
+AM_CONDITIONAL([USE_DBUS_CLIENT], [test "x$with_dbus_test_client" = "xyes"])
# Look for mpris flag
-AC_ARG_WITH(mpris-interface, [ --with-mpris-interface = include support for a D-Bus interface conforming to the MPRIS standard], [
- AC_MSG_RESULT(>>Including the MPRIS D-Bus Interface)
- AC_DEFINE([CONFIG_MPRIS_INTERFACE], 1, [Include support for a D-Bus interface conforming to the MPRIS standard])
- REQUESTED_MPRIS=1
- PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0 >= 2.30.0],[CFLAGS="${GIO_UNIX_CFLAGS} ${CFLAGS}" LIBS="${GIO_UNIX_LIBS} ${LIBS}"],[AC_MSG_ERROR(dbus messaging support for mpris requires the glib 2.0 library -- libglib2.0-dev suggested!)])
- ], )
-AM_CONDITIONAL([USE_MPRIS], [test "x$REQUESTED_MPRIS" = "x1"])
+AC_ARG_WITH(mpris-interface, [AS_HELP_STRING([--with-mpris-interface],[include support for a D-Bus interface conforming to the MPRIS standard])])
+if test "x$with_mpris_interface" = "xyes" ; then
+ AC_DEFINE([CONFIG_MPRIS_INTERFACE], 1, [Support the MPRIS standard])
+ # remember to include glib, below
+fi
+AM_CONDITIONAL([USE_MPRIS], [test "x$with_mpris_interface" = "xyes"])
# Look for mpris test client flag
-AC_ARG_WITH(mpris-test-client, [ --with-mpris-test-client = compile mpris test client], [
- AC_MSG_RESULT(>>Including mpris test client)
- REQUESTED_MPRIS_CLIENT=1
- PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0 >= 2.30.0],[CFLAGS="${GIO_UNIX_CFLAGS} ${CFLAGS}" LIBS="${GIO_UNIX_LIBS} ${LIBS}"],[AC_MSG_ERROR(mpris client support requires the glib 2.0 library -- libglib2.0-dev suggested!)])
- ], )
-AM_CONDITIONAL([USE_MPRIS_CLIENT], [test "x$REQUESTED_MPRIS_CLIENT" = "x1"])
+AC_ARG_WITH(mpris-test-client, [AS_HELP_STRING([--with-mpris-test-client],[compile an MPRIS test client application])])
+# remember to include glib, below
+AM_CONDITIONAL([USE_MPRIS_CLIENT], [test "x$with_mpris_test_client" = "xyes"])
+
+if test "x$with_mpris_test_client" = "xyes" || test "x$with_dbus_test_client" = "xyes" || test "x$with_mpris_interface" = "xyes" || test "x$with_dbus_interface" = "xyes" ; then
+ PKG_CHECK_MODULES([glib], [gio-unix-2.0 >= 2.30.0],[CFLAGS="${glib_CFLAGS} ${CFLAGS}" LIBS="${glib_LIBS} ${LIBS}"],[AC_MSG_ERROR(MPRIS client support requires the glib 2.0 library -- libglib2.0-dev suggested!)])
+fi
# Look for mqtt flag
-AC_ARG_WITH(mqtt-client, [ --with-mqtt-client = include a client for MQTT -- the Message Queuing Telemetry Transport protocol], [
+AC_ARG_WITH(mqtt-client, [AS_HELP_STRING([--with-mqtt-client],[include a client for MQTT -- the Message Queuing Telemetry Transport protocol])])
+if test "x$with_mqtt_client" = "xyes" ; then
AC_DEFINE([CONFIG_MQTT], 1, [Include a client for MQTT, the Message Queuing Telemetry Transport protocol])
- AC_MSG_RESULT(>>Including MQTT support)
- REQUESTED_MQTT=1
AC_CHECK_LIB([mosquitto], [mosquitto_lib_init], , AC_MSG_ERROR(MQTT support requires the mosquitto library -- libmosquitto-dev suggested!))
- ],)
-AM_CONDITIONAL([USE_MQTT], [test "x$REQUESTED_MQTT" = "x1"])
+fi
+AM_CONDITIONAL([USE_MQTT], [test "x$with_mqtt_client" = "xyes"])
-if test "x$REQUESTED_MQTT" = "x1" && test "x$REQUESTED_AVAHI" != "x1"; then
- AC_MSG_WARN([>>MQTT needs Avahi to allow remote control functionality. Only Metadata publishing will be supported])
+if test "x$with_mqtt_client" = "xyes" && test "x$with_avahi" != "xyes" ; then
+ AC_MSG_WARN([MQTT needs Avahi for remote control functionality. With the current configuration settings, only metadata publishing will be supported.])
fi
-if test "x$REQUESTED_MPRIS" = "x1" || test "x$REQUESTED_DBUS" = "x1" || test "x$REQUESTED_MQTT" = "x1"; then
- AC_MSG_RESULT(>>Including extended metadata and DACP client support)
+if test "x$with_mpris_interface" = "xyes" || test "x$with_dbus_interface" = "xyes" || test "x$with_mqtt_client" = "xyes" ; then
REQUESTED_EXTENDED_METADATA_SUPPORT=1
AC_DEFINE([CONFIG_METADATA_HUB], 1, [Needed by the compiler.])
AC_DEFINE([CONFIG_DACP_CLIENT], 1, [Needed by the compiler.])
@@ -365,11 +366,10 @@ fi
AM_CONDITIONAL([USE_METADATA_HUB], [test "x$REQUESTED_EXTENDED_METADATA_SUPPORT" = "x1"])
AM_CONDITIONAL([USE_DACP_CLIENT], [test "x$REQUESTED_EXTENDED_METADATA_SUPPORT" = "x1"])
-if test "x$REQUESTED_EXTENDED_METADATA_SUPPORT" = "x1" || test "x$REQUESTED_METADATA" = "x1"; then
- AC_MSG_RESULT(>>Including metadata support)
+if test "x$REQUESTED_EXTENDED_METADATA_SUPPORT" = "x1" || test "x$with_metadata" = "xyes" ; then
AC_DEFINE([CONFIG_METADATA], 1, [Needed by the compiler.])
fi
-AM_CONDITIONAL([USE_METADATA], [test "x$REQUESTED_METADATA" = "x1"])
+AM_CONDITIONAL([USE_METADATA], [test "x$with_metadata" = "xyes"])
if test "x${with_systemd}" = xyes ; then
# Find systemd unit dir
@@ -391,7 +391,7 @@ fi
# Look for xmltoman
AC_CHECK_PROGS([XMLTOMAN], [xmltoman])
if test -z "$XMLTOMAN"; then
- AC_MSG_WARN([>>xmltoman not found - not rebuilding man pages])
+ AC_MSG_WARN([xmltoman not found - not rebuilding man pages])
fi
AM_CONDITIONAL([HAVE_XMLTOMAN], [test -n "$XMLTOMAN"])
diff --git a/dacp.c b/dacp.c
index acb963b..0230ac1 100644
--- a/dacp.c
+++ b/dacp.c
@@ -445,9 +445,13 @@ void set_dacp_server_information(rtsp_conn_info *conn) {
}
if (dacp_server.active_remote_id)
free(dacp_server.active_remote_id);
- dacp_server.active_remote_id =
- strdup(conn->dacp_active_remote); // even if the dacp_id remains the same,
- // the active remote will change.
+ if (conn->dacp_active_remote)
+ dacp_server.active_remote_id =
+ strdup(conn->dacp_active_remote); // even if the dacp_id remains the same,
+ // the active remote will change.
+ else
+ dacp_server.active_remote_id = NULL;
+
debug(3, "set_dacp_server_information set active-remote id to %s.", dacp_server.active_remote_id);
pthread_cond_signal(&dacp_server_information_cv);
debug_mutex_unlock(&dacp_server_information_lock, 3);
diff --git a/rtsp.c b/rtsp.c
index abfabc4..2661cce 100644
--- a/rtsp.c
+++ b/rtsp.c
@@ -1652,41 +1652,42 @@ void *metadata_mqtt_thread_function(__attribute__((unused)) void *ignore) {
#endif
void metadata_init(void) {
+ int ret;
+ if (config.metadata_enabled) {
+ // create the metadata pipe, if necessary
+ size_t pl = strlen(config.metadata_pipename) + 1;
+ char *path = malloc(pl + 1);
+ snprintf(path, pl + 1, "%s", config.metadata_pipename);
+ mode_t oldumask = umask(000);
+ if (mkfifo(path, 0666) && errno != EEXIST)
+ die("Could not create metadata pipe \"%s\".", path);
+ umask(oldumask);
+ debug(1, "metadata pipe name is \"%s\".", path);
+
+ // try to open it
+ fd = try_to_open_pipe_for_writing(path);
+ // we check that it's not a "real" error. From the "man 2 open" page:
+ // "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
+ // open for reading." Which is okay.
+ if ((fd == -1) && (errno != ENXIO)) {
+ char errorstring[1024];
+ strerror_r(errno, (char *)errorstring, sizeof(errorstring));
+ debug(1, "metadata_hub_thread_function -- error %d (\"%s\") opening pipe: \"%s\".", errno,
+ (char *)errorstring, path);
+ warn("can not open metadata pipe -- error %d (\"%s\") opening pipe: \"%s\".", errno,
+ (char *)errorstring, path);
+ }
+ free(path);
+ int ret;
+ ret = pthread_create(&metadata_thread, NULL, metadata_thread_function, NULL);
+ if (ret)
+ debug(1, "Failed to create metadata thread!");
- // create the metadata pipe, if necessary
- size_t pl = strlen(config.metadata_pipename) + 1;
- char *path = malloc(pl + 1);
- snprintf(path, pl + 1, "%s", config.metadata_pipename);
-
- mode_t oldumask = umask(000);
- if (mkfifo(path, 0666) && errno != EEXIST)
- die("Could not create metadata pipe \"%s\".", path);
- umask(oldumask);
- debug(1, "metadata pipe name is \"%s\".", path);
-
- // try to open it
- fd = try_to_open_pipe_for_writing(path);
- // we check that it's not a "real" error. From the "man 2 open" page:
- // "ENXIO O_NONBLOCK | O_WRONLY is set, the named file is a FIFO, and no process has the FIFO
- // open for reading." Which is okay.
- if ((fd == -1) && (errno != ENXIO)) {
- char errorstring[1024];
- strerror_r(errno, (char *)errorstring, sizeof(errorstring));
- debug(1, "metadata_hub_thread_function -- error %d (\"%s\") opening pipe: \"%s\".", errno,
- (char *)errorstring, path);
- warn("can not open metadata pipe -- error %d (\"%s\") opening pipe: \"%s\".", errno,
- (char *)errorstring, path);
+ ret =
+ pthread_create(&metadata_multicast_thread, NULL, metadata_multicast_thread_function, NULL);
+ if (ret)
+ debug(1, "Failed to create metadata multicast thread!");
}
- free(path);
-
- int ret = pthread_create(&metadata_thread, NULL, metadata_thread_function, NULL);
- if (ret)
- debug(1, "Failed to create metadata thread!");
-
- ret = pthread_create(&metadata_multicast_thread, NULL, metadata_multicast_thread_function, NULL);
- if (ret)
- debug(1, "Failed to create metadata multicast thread!");
-
#ifdef CONFIG_METADATA_HUB
ret = pthread_create(&metadata_hub_thread, NULL, metadata_hub_thread_function, NULL);
if (ret)
@@ -1715,15 +1716,20 @@ void metadata_stop(void) {
pthread_join(metadata_hub_thread, NULL);
// debug(2, "metadata stop hub done.");
#endif
- // debug(2, "metadata stop multicast thread.");
- pthread_cancel(metadata_multicast_thread);
- pthread_join(metadata_multicast_thread, NULL);
- // debug(2, "metadata stop multicast done.");
-
- // debug(2, "metadata stop metadata_thread thread.");
- pthread_cancel(metadata_thread);
- pthread_join(metadata_thread, NULL);
- // debug(2, "metadata_stop finished successfully.");
+ if (config.metadata_enabled) {
+ // debug(2, "metadata stop multicast thread.");
+ if (metadata_multicast_thread) {
+ pthread_cancel(metadata_multicast_thread);
+ pthread_join(metadata_multicast_thread, NULL);
+ // debug(2, "metadata stop multicast done.");
+ }
+ if (metadata_thread) {
+ // debug(2, "metadata stop metadata_thread thread.");
+ pthread_cancel(metadata_thread);
+ pthread_join(metadata_thread, NULL);
+ // debug(2, "metadata_stop finished successfully.");
+ }
+ }
}
}
@@ -1793,7 +1799,11 @@ int send_metadata_to_queue(pc_queue *queue, uint32_t type, uint32_t code, char *
int send_metadata(uint32_t type, uint32_t code, char *data, uint32_t length, rtsp_message *carrier,
int block) {
int rc;
- rc = send_metadata_to_queue(&metadata_queue, type, code, data, length, carrier, block);
+ if (config.metadata_enabled) {
+ rc = send_metadata_to_queue(&metadata_queue, type, code, data, length, carrier, block);
+ rc =
+ send_metadata_to_queue(&metadata_multicast_queue, type, code, data, length, carrier, block);
+ }
#ifdef CONFIG_METADATA_HUB
rc = send_metadata_to_queue(&metadata_hub_queue, type, code, data, length, carrier, block);
diff --git a/scripts/shairport-sync.conf b/scripts/shairport-sync.conf
index 6444b8a..e7f9e74 100644
--- a/scripts/shairport-sync.conf
+++ b/scripts/shairport-sync.conf
@@ -134,6 +134,7 @@ sndio =
pa =
{
// server = "host"; // Set this to override the default pulseaudio server that should be used.
+// sink = "Sink Name"; // Set this to override the default pulseaudio sink that should be used. (Untested)
// application_name = "Shairport Sync"; //Set this to the name that should appear in the Sounds "Applications" tab when Shairport Sync is active.
};
diff --git a/shairport-sync.spec b/shairport-sync.spec
index 215b303..ed0c3d4 100644
--- a/shairport-sync.spec
+++ b/shairport-sync.spec
@@ -1,5 +1,5 @@
Name: shairport-sync
-Version: 3.3.7
+Version: 3.3.8
Release: 1%{?dist}
Summary: AirTunes emulator. Multi-Room with Audio Synchronisation
# MIT licensed except for tinysvcmdns under BSD,
@@ -66,29 +66,31 @@ getent passwd %{name} &> /dev/null || useradd --system -c "%{name} User" \
%license LICENSES
%changelog
-* Tue Nov 1 2020 Mike Brady <mikebradydublin@icloud.com) 3.3.7
+* Mon Apr 26 2021 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.8
+- Bug fixes and enhancements.
+* Tue Nov 1 2020 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.7
- Jack resampling, bug fixes and additions to the pipe and stdout backends, to metadata and to the D-Bus and MPRIS interfaces.
-* Thu Feb 20 2020 Mike Brady <mikebradydublin@icloud.com) 3.3.6
+* Thu Feb 20 2020 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.6
- Jack resampling, bug fixes and additions to the D-Bus and MPRIS interfaces.
-* Wed Nov 13 2019 Mike Brady <mikebrady@eircom.net) 3.3.5
+* Wed Nov 13 2019 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.5
- Bug fixes and additions to the D-Bus interface.
-* Mon Oct 28 2019 Mike Brady <mikebrady@eircom.net) 3.3.4
+* Mon Oct 28 2019 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.4
- Bug fixes and minor enhancements.
-* Fri Jul 26 2019 Mike Brady <mikebrady@eircom.net) 3.3.2
+* Fri Jul 26 2019 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.2
- Minor bug fixes.
-* Wed Jun 05 2019 Mike Brady <mikebrady@eircom.net) 3.3.1
+* Wed Jun 05 2019 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3.1
- Bug fixes.
-* Fri May 24 2019 Mike Brady <mikebrady@eircom.net) 3.3
+* Fri May 24 2019 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.3
- Audio enhancements, stability improvements, MQTT and Jack Audio interfaces.
-* Sun Oct 14 2018 Mike Brady <mikebrady@eircom.net) 3.2.2
+* Sun Oct 14 2018 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.2.2
- Compatibility with iOS 12 and mac OS Mojave AirPlay latencies. Minor bug fix.
-* Fri Jul 13 2018 Mike Brady <mikebrady@eircom.net) 3.2.1
+* Fri Jul 13 2018 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.2.1
- Stability improvements when soxr interpolation is chosen.
-* Mon Jul 09 2018 Mike Brady <mikebrady@eircom.net) 3.2
+* Mon Jul 09 2018 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.2
- New D-Bus and MPRIS Interfaces, Bug Fixes and Enhancements.
-* Thu Dec 21 2017 Mike Brady <mikebrady@eircom.net> 3.1.7
+* Thu Dec 21 2017 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.1.7
- Bug fix for unexpectedly resuming play at full volume from iOS 11.2 and macOS 10.3.2.
-* Mon Dec 11 2017 Mike Brady <mikebrady@eircom.net> 3.1.5
+* Mon Dec 11 2017 Mike Brady <4265913+mikebrady@users.noreply.github.com> 3.1.5
- Bug fixes and better compatibility with iOS 11.2 and mac OS 10.13.2.
- Better AirPlay synchronisation.
* Wed Sep 13 2017 Bill Peck <bpeck@redhat.com> 3.1.2-1
@@ -115,27 +117,27 @@ getent passwd %{name} &> /dev/null || useradd --system -c "%{name} User" \
- new optional loudness and convolution filters
- improvements in non-synchronised backends
- enhancements, stability improvements and bug fixes
-* Fri Feb 24 2017 Mike Brady <mikebrady@eircom.net> 2.8.6
+* Fri Feb 24 2017 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.6
- Many changes including 8- 16- 24- and 32-bit output
-* Fri Oct 21 2016 Mike Brady <mikebrady@eircom.net> 2.8.6
+* Fri Oct 21 2016 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.6
- Advertise self as ShairportSync rather than AirPort device 2.8.6
-* Sun Sep 25 2016 Mike Brady <mikebrady@eircom.net> 2.8.5
+* Sun Sep 25 2016 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.5
- Bug fixes and small enhancements 2.8.5
-* Sat May 28 2016 Mike Brady <mikebrady@eircom.net> 2.8.4
+* Sat May 28 2016 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.4
- Bug fixes and a few small enhancements 2.8.4
-* Fri Apr 15 2016 Mike Brady <mikebrady@eircom.net> 2.8.2
+* Fri Apr 15 2016 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.2
- Stability improvements, bug fixes and a few special-purpose settings 2.8.2
-* Wed Mar 02 2016 Mike Brady <mikebrady@eircom.net> 2.8.1
+* Wed Mar 02 2016 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.1
- Stability improvements and important bug fixes 2.8.1
-* Sat Jan 30 2016 Mike Brady <mikebrady@eircom.net> 2.8.0
+* Sat Jan 30 2016 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.8.0
- Enhancements and bug fixes 2.8.0
-* Sun Oct 18 2015 Mike Brady <mikebrady@eircom.net> 2.6
+* Sun Oct 18 2015 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.6
- Important enhancements and bug fixes 2.6
-* Thu Aug 27 2015 Mike Brady <mikebrady@eircom.net> 2.4.1
+* Thu Aug 27 2015 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.4.1
- Minor bug fixes 2.4.1
-* Thu Aug 27 2015 Mike Brady <mikebrady@eircom.net> 2.4
+* Thu Aug 27 2015 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.4
- Prepare for stable release 2.4
-* Wed Aug 26 2015 Mike Brady <mikebrady@eircom.net> 2.3.13.1-1
+* Wed Aug 26 2015 Mike Brady <4265913+mikebrady@users.noreply.github.com> 2.3.13.1-1
- Harmonise release numbers
* Fri Jul 24 2015 Bill Peck <bill@pecknet.com> 2.3.7-1
- Initial spec file
diff --git a/shairport.c b/shairport.c
index ba99523..a32216d 100644
--- a/shairport.c
+++ b/shairport.c
@@ -1322,7 +1322,7 @@ void exit_function() {
#ifdef CONFIG_LIBDAEMON
if ((this_is_the_daemon_process) ||
(config.daemonise == 0)) { // if this is the daemon process that is exiting or it's not
- // actually deamonised at all
+ // actually daemonised at all
#endif
debug(2, "exit function called...");
/*
@@ -1617,7 +1617,7 @@ int main(int argc, char **argv) {
debug(2, "killed the %s daemon.", config.appName);
else
daemon_log(LOG_WARNING,
- "killed the %s deamon, but cannot remove old PID file: \"%s\", errno %u.",
+ "killed the %s daemon, but cannot remove old PID file: \"%s\", errno %u.",
config.appName, strerror(errno), errno);
}
return ret < 0 ? 1 : 0;
diff --git a/tests/configure_test.sh b/tests/configure_test.sh
new file mode 100644
index 0000000..a374779
--- /dev/null
+++ b/tests/configure_test.sh
@@ -0,0 +1,207 @@
+#!/bin/sh
+
+# These tests check that the requested configuration can be made and can be built
+# In many cases it will check that the Shairport Sync configuration string
+# contains or omits the relevant string
+# If doesn't check for the presence or absence of products except
+# when it checks for the configuration string
+
+# To get it to work first time, and assuming you have already build Shairport Sync according to the standard
+# you need the following extra libraries in Linux:
+# libmbedtls-dev libpolarssl-dev libjack-dev libsndio-dev libao-dev libpulse-dev libsndfile1-dev libavahi-compat-libdnssd-dev libglib2.0-dev libmosquitto-dev
+# Also, you'll need to build the ALAC library -- see https://github.com/mikebrady/alac.
+
+# At present, it is Linux-only.
+check_configuration_string_includes()
+{
+ echo -n " checking configuration string includes \"$1\"..."
+ ./shairport-sync -V | grep -q $1
+ if [ "$?" -eq "1" ] ; then
+ echo "\nError: \"$1\" not included in configuration string. See \"../configure_test.log\"."
+ exit 1
+ fi
+ echo -n "ok"
+}
+
+check_configuration_string_excludes()
+{
+ echo -n " checking configuration string excludes \"$1\"..."
+ ./shairport-sync -V | grep -q $1
+ if [ "$?" -eq "0" ] ; then
+ echo "\nError: \"$1\" is unexpectedly included in the configuration string. See \"../configure_test.log\"."
+ exit 1
+ fi
+ echo -n "ok"
+}
+check_for_success()
+{
+ if [ "$2" = "x" ] ; then
+ A2=""
+ else
+ A2="$2"
+ fi
+ if [ "$3" = "x" ] ; then
+ A3=""
+ else
+ A3="$3"
+ fi
+ if [ "$4" = "x" ] ; then
+ A4=""
+ else
+ A4="$4"
+ fi
+ if [ "$5" = "x" ] ; then
+ A5=""
+ else
+ A5=$5
+ fi
+ if [ "$1" = "x" -o "$1" = "x$A2" ] ; then
+ TESTCOUNT="$(expr "$TESTCOUNT" '+' '1')"
+ echo -n "Checking \"$A2\": "
+ echo -n "configuring..."
+ echo "./configure $A3 $A2" > $LOGFILE
+ ./configure $A3 $A2 >> $LOGFILE 2>&1
+ if [ "$?" -eq "0" ] ; then
+ echo -n "ok making..."
+ echo "make clean" >> $LOGFILE
+ make clean >> $LOGFILE 2>&1
+ echo "make -j $((`nproc`*2))" >> $LOGFILE
+ make -j $((`nproc`*2)) >> $LOGFILE 2>&1
+ if [ "$?" -ne "0" ] ; then
+ echo "\nError at build step with arg \"$A2\". See \"../configure_test.log\"."
+ exit 1
+ fi
+ echo -n "ok"
+ else
+ echo "\nError at configure step with arg \"$A2\". See \"../configure_test.log\"."
+ exit 1
+ fi
+ if [ "$A4" != "" ] ; then
+ check_configuration_string_includes $A4
+ fi
+ if [ "$A5" != "" ] ; then
+ check_configuration_string_excludes $A5
+ fi
+ echo "."
+ fi
+}
+
+check_for_configuration_fail()
+{
+ if [ "$1" = "x" -o "$1" = "x$2" ] ; then
+ echo -n "Checking \"$2\" fails during configuration... "
+ TESTCOUNT="$(expr "$TESTCOUNT" '+' '1')"
+ ./configure $3 $2 > $LOGFILE 2>&1
+ if [ "$?" -eq "0" ] ; then
+ echo "\nError: configuration did not fail with arg \"$2\". See \"../configure_test.log\"."
+ exit 1
+ fi
+ echo " done."
+ fi
+ return 0
+}
+
+echo -n "Preparing..."
+LOGFILE=configure_test.log
+CWD=`pwd`
+cd ..
+autoreconf -fi > $LOGFILE 2>&1
+if [ "$?" -ne "0" ] ; then
+ echo " error running \"autoreconf -fi\" -- see \"../configure_test.log\"."
+ exit 1
+fi
+echo "ok."
+TESTCOUNT=0
+check_for_success x$1 --with-pkg-config --with-ssl=mbedtls
+check_for_success x$1 --with-ssl=openssl x OpenSSL
+check_for_success x$1 --with-ssl=mbedtls x mbedTLS
+check_for_success x$1 --with-ssl=polarssl x PolarSSL
+check_for_configuration_fail x$1 --with-ssl
+check_for_configuration_fail x$1 --without-ssl=openssl
+check_for_configuration_fail x$1 --without-ssl=mbedtls
+check_for_configuration_fail x$1 --without-ssl=polarssl
+check_for_configuration_fail x$1
+check_for_success x$1 --with-alsa --with-ssl=mbedtls ALSA
+check_for_success x$1 --without-alsa --with-ssl=mbedtls x ALSA
+
+check_for_success x$1 --with-dummy --with-ssl=mbedtls dummy
+check_for_success x$1 --without-dummy --with-ssl=mbedtls x dummy
+
+check_for_success x$1 --with-stdout --with-ssl=mbedtls stdout
+check_for_success x$1 --without-stdout --with-ssl=mbedtls x stdout
+
+check_for_success x$1 --with-pipe --with-ssl=mbedtls pipe
+check_for_success x$1 --without-pipe --with-ssl=mbedtls x pipe
+
+check_for_success x$1 --with-external-mdns --with-ssl=mbedtls external_mdns
+check_for_success x$1 --without-external-mdns --with-ssl=mbedtls x external_mdns
+
+check_for_success x$1 --with-apple-alac --with-ssl=mbedtls alac
+check_for_success x$1 --without-apple-alac --with-ssl=mbedtls x alac
+
+check_for_success x$1 --with-piddir=/var --with-ssl=mbedtls
+check_for_success x$1 --without-piddir --with-ssl=mbedtls
+
+check_for_success x$1 --with-libdaemon --with-ssl=mbedtls
+check_for_success x$1 --without-libdaemon --with-ssl=mbedtls
+
+check_for_success x$1 --with-soxr --with-ssl=mbedtls soxr
+check_for_success x$1 --without-soxr --with-ssl=mbedtls x soxr
+
+check_for_success x$1 --with-metadata --with-ssl=mbedtls metadata
+check_for_success x$1 --without-metadata --with-ssl=mbedtls x metadata
+
+check_for_success x$1 --with-avahi --with-ssl=mbedtls Avahi
+check_for_success x$1 --without-avahi --with-ssl=mbedtls x Avahi
+
+check_for_success x$1 --with-tinysvcmdns --with-ssl=mbedtls tinysvcmdns
+check_for_success x$1 --without-tinysvcmdns --with-ssl=mbedtls x tinysvcmdns
+
+check_for_success x$1 --with-jack --with-ssl=mbedtls jack
+check_for_success x$1 --without-jack --with-ssl=mbedtls x jack
+
+check_for_success x$1 --with-sndio --with-ssl=mbedtls sndio
+check_for_success x$1 --without-sndio --with-ssl=mbedtls x sndio
+
+check_for_success x$1 --with-ao --with-ssl=mbedtls ao
+check_for_success x$1 --without-ao --with-ssl=mbedtls x ao
+
+# the following is disabled because there is no soundio library for Raspberry OS
+#check_for_success x$1 --with-soundio --with-ssl=mbedtls soundio
+check_for_success x$1 --without-soundio --with-ssl=mbedtls x soundio
+
+check_for_success x$1 --with-pa --with-ssl=mbedtls pa
+check_for_success x$1 --without-pa --with-ssl=mbedtls x pa
+
+check_for_success x$1 --with-convolution --with-ssl=mbedtls convolution
+check_for_success x$1 --without-convolution --with-ssl=mbedtls x convolution
+
+check_for_success x$1 --with-dns_sd --with-ssl=mbedtls dns_sd
+check_for_success x$1 --without-dns_sd --with-ssl=mbedtls x dns_sd
+
+check_for_success x$1 --with-dbus-interface --with-ssl=mbedtls metadata-dbus
+check_for_success x$1 --without-dbus-interface --with-ssl=mbedtls x dbus
+
+check_for_success x$1 --with-dbus-test-client --with-ssl=mbedtls
+check_for_success x$1 --without-dbus-test-client --with-ssl=mbedtls
+
+check_for_success x$1 --with-mpris-interface --with-ssl=mbedtls metadata-mpris
+check_for_success x$1 --without-mpris-interface --with-ssl=mbedtls x mpris
+
+check_for_success x$1 --with-mpris-test-client --with-ssl=mbedtls
+check_for_success x$1 --without-mpris-test-client --with-ssl=mbedtls
+
+check_for_success x$1 --with-mqtt-client --with-ssl=mbedtls metadata-mqtt
+check_for_success x$1 --without-mqtt-client --with-ssl=mbedtls x mqtt
+
+check_for_success x$1 --with-configfiles '--sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd' OpenSSL-Avahi-ALSA-soxr-sysconfdir:/etc
+check_for_success x$1 --without-configfiles '--sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl --with-systemd' OpenSSL-Avahi-ALSA-soxr-sysconfdir:/etc
+
+check_for_success x$1 --with-systemd '--sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl' OpenSSL-Avahi-ALSA-soxr-sysconfdir:/etc
+check_for_success x$1 --without-systemd '--sysconfdir=/etc --with-alsa --with-soxr --with-avahi --with-ssl=openssl' OpenSSL-Avahi-ALSA-soxr-sysconfdir:/etc
+check_for_success x$1 --with-systemv '--sysconfdir=/etc --with-libdaemon --with-alsa --with-soxr --with-avahi --with-ssl=openssl' OpenSSL-Avahi-ALSA-soxr-sysconfdir:/etc
+check_for_success x$1 --without-systemv '--sysconfdir=/etc --with-libdaemon --with-alsa --with-soxr --with-avahi --with-ssl=openssl' OpenSSL-Avahi-ALSA-soxr-sysconfdir:/etc
+
+cd $CWD
+echo "$TESTCOUNT tests completed."
+