]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Merge 2.3.X from development to master
authorMke Brady <mikebrady@eircom.net>
Thu, 27 Aug 2015 22:03:31 +0000 (23:03 +0100)
committerMke Brady <mikebrady@eircom.net>
Thu, 27 Aug 2015 22:03:31 +0000 (23:03 +0100)
1  2 
README.md
RELEASENOTES.md
mdns_dns_sd.c
shairport.c

diff --cc README.md
index 228ebde826b0a6bcd7e14692f4726213aba0fe8b,9b33c0aaa2f300a95b2ab2dd906d1106e6e724b1..add485d1cf774d9c657b9e4f83057a9be3eee159
+++ b/README.md
@@@ -107,91 -143,170 +143,169 @@@ Enter
  
  `$ make` 
  
- Run `$sudo make install` to install `shairport-sync` along with an init script which will automatically launch it at startup. The settings in the init script are the most basic defaults, so you will want to edit it -- the file is `/etc/init.d/shairport-sync` -- to give the service a name, use a different card, use the hardware mixer and volume control, etc. -- there are some examples in the script file.
+ to build the application. Next, run:
  
- Man Page
- --------
- You can see a web version of the man page here: http://htmlpreview.github.io/?https://github.com/mikebrady/shairport-sync/blob/master/man/shairport-sync.html
+ ```
+ $sudo make install
+ $sudo update-rc.d shairport-sync defaults 90 10
+ ```
  
+ to install `shairport-sync` along with a `man` page, a default configuration file and a System V startup script to launch it automatically at system startup.
+ The settings are the most basic defaults, so you will want to edit the configuration — the file is `/etc/shairport-sync.conf` — to give the service a name,
+ use a specific sound card and mixer control, etc. — there are some examples in the sample configuration file.
  
- Configuring Shairport Sync
- --------
- Shairport Sync installs a default configuration at `/etc/init.d/shairport-sync` (it won't replace an existing one) which should work in almost any system with a sound card. If there is a problem, it will be noted in the logfile, normally `/etc/log/syslog`. However, to get the most out of your software and hardware, you need to adjust some of the settings.
+ *Man Page*
  
- To understand what follows, note that settings and parameters are passed to Shairport Sync through command line arguments. The purpose of the init script at `/etc/init.d/shairport-sync` is to launch or terminate Shairport Sync while passing the correct arguments to it. You are perfectly free to remove the init script and launch and terminate Shairport Sync yourself directly; indeed it is useful when you are troubleshooting the program. If you do launch it directly, make sure it isn't running already!
+ You can view the man page here: http://htmlpreview.github.io/?https://github.com/mikebrady/shairport-sync/blob/master/man/shairport-sync.html
  
- As well as the man page, don't forget you can launch Shairport Sync with the `-h` option to get some help on the options available.
 -
+ Configuring Shairport Sync
+ --------
+ There are two logically distinct parts to getting Shairport Sync to run properly on your machine — (1) starting and stopping it and (2) ensuring it has the right settings.
  
+ Starting and stopping automatically is taken care of differently in different versions of Linux. In the example above, when you run `$sudo make install`, a System V startup script is placed at `/etc/init.d/shairport-sync`. This will not be appropriate in Linuxes that use `systemd` such as Arch Linux, so please look at the separate installation scripts for those.
  
- These are the important options:
+ To get the best from Shairport Sync, you’ll need to (1) give Shairport Sync a service name by which it will be seen in iTunes etc., (2) specify the output device to use and (3) specify the name of the mixer volume control to use to control the output level. To get values for (2) and (3) you might need to explore the ALSA output devices with a program like `alsamixer` or similar.
  
The `-a` option allows you to specify the service name Shairport Sync will use on the network. If you don't specify a service name, the name `Shairport Sync on ...your computer's hostname...` will be used.
Shairport Sync reads settings from a configuration file at `/etc/shairport-sync.conf`. While it can also take configuration settings from command line options, it is recommended that you use the configuration file method. When you run `$sudo make install`,  a default configuration is installed at `/etc/shairport-sync.conf` (it won't replace an existing one) which should work in almost any system with a sound card.
  
The `-S` option allows you to specify the kind of "stuffing" or interpolation to be used -- `basic` (default) for simple insertion/deletion  or `soxr` for smoother resampling-based interpolation.
A sample configuration file is installed (or updated) at `/etc/shairport-sync.conf.sample`. This contains all the setting groups and all the settings available, but they all are commented out (comments begin with `//`) so that default values are used. The file contains explanations of the settings, useful hints and suggestions.
  
- The `--password` option allows you to password-protect access to the service provided by Shairport Sync.
+ Settings in the configuration file are grouped. For instance, there is a `general` group within which you can use the `name` tag to set the service name. Suppose you wanted to set the name of the service to `Front Room`, give the service the password `secret` and used `libsoxr` interpolation, then you should do the following:
  
- These may be also of interest:
+ ```
+ general =
+ {
+       name = "Front Room";
+       password = "secret";
+       interpolation = "soxr";
+       // ... other general settings
+ };
+ ```
+ The `alsa` group is used to specify properties of the output device. The most obvious setting is the name of the output device which you can set using the `output_device` tag.
  
- The `-B`, `-E` and `-w` options allow you to specify a program to execute before (`-B`) and after (`-E`) Shairport Sync plays. This is to facilitate situations where something has to be done before and  after playing, e.g. switching on an amplifier beforehand and switching it off afterwards. Use the `-w` option for Shairport Sync to wait until the respective commands have been completed before continuing. Please note that the full path to the programs must be specified, and script files will not be executed unless they are marked as executable and have the standard `#!/bin/...` first line. (This behaviour may be different from other Shairports.)
+ The following `alsa` group settings are very important for maximum performance. If your audio device has a mixer that can be use to control the volume, then Shairport Sync can use it to give instant response to volume and mute commands and it can offload some work from the processor.
+ * The `mixer_control_name` tag allows you to specify the name of the mixer volume control.
+ * The `mixer_device` tag allows you specify where the mixer is. By default, the mixer is on the `output_device`, so you only need to use the `mixer_device` tag if the mixer is elsewhere. This can happen if you specify a *device* rather than a *card* with the `output_device` tag, because normally a mixer is associated with a *card* rather than a device. Suppose you wish to use the output device `5` of card `hw:0` and the mixer volume-control named `PCM`:
  
- * The `-V` option gives you version information about  Shairport Sync and then quits.
- * The `-k` option causes Shairport Sync to kill an existing Shairport Sync daemon and then quit. You need to have sudo privileges for this.
- * The `-v` option causes Shairport Sync to print some information and debug messages.
- * The `-d` option causes Shairport Sync to properly daemonise itself, that is, to run in the background. You may need sudo privileges for this.
+ ```
+ alsa =
+ {
+   output_device = "hw:0,5";
+   mixer_device = "hw:0";
+   mixer_control_name = "PCM";
+   // ... other alsa settings
+ };
+ ```
  
- Apart from arguments of Shairport Sync, there are also arguments for controlling the ALSA audio system. ALSA arguments follow a `--` on the command line -- see the examples below for layout of command line.
- These are important because you use them to specify the actual audio device you wish to use and you give Shairport Sync important information about the capabilities of the device. The important ALSA arguments are:
+ Shairport Sync can run programs just before it starts to play an audio stream and just after it finishes. You specify them using the `sessioncontrol` group settings `run_this_before_play_begins` and `run_this_after_play_ends`. This is to facilitate situations where something has to be done before and after playing, e.g. switching on an amplifier beforehand and switching it off afterwards. Set the `wait_for_completion` value to `"yes"` for Shairport Sync to wait until the respective commands have been completed before continuing.
  
- * The `-d` option which allows you to specify the audio device to use. Typical values would be `default` (default), `hw:0`, `hw:1`, etc. Those examples are specifying which *soundcard* to use; the actual output device used is the card's default, typically output device 0. You could specify, for example, device 5 on card hw:0 with `-d hw:0,5`.
+ Please note that the full path to the programs must be specified, and script files will not be executed unless they are marked as executable and have the standard `#!/bin/...` first line. (This behaviour may be different from other Shairports.)
  
- The following settings are very important for maximum performance. If your audio device has a hardware mixer and volume control, then Shairport Sync can use it to give faster response to volume and mute commands and it can offload some work from the processor.
- * The `-m` option allows you specify where the mixer is. By default, the mixer is to be found where you specify with the `-d` option, so you only need to use the `-m` option if the mixer is elsewhere. This can happen if you specify a *device* rather than a *card* with the `-d` option, because normally a mixer is associated with a *card* rather than a device. For example, if you specified that the output device was device 5 of card hw:0 and if the mixer was associated with the card, you would write `-d hw:0,5 -m hw:0`. 
- * The `-t` option allows you to specify the type of audio mixer -- `software` (default) or `hardware`.
- * The `-c` option allows you to specify the name of the volume control on the hardware mixer.
+ *Command Line Arguments*
  
- The init script at `/etc/init.d/shairport-sync` has a bare minimum set of options (see line 60):
+ You can use command line arguments to provide settings to Shairport Sync as before. For full information, please read the Shairport Sync `man` page, also available at  http://htmlpreview.github.io/?https://github.com/mikebrady/shairport-sync/blob/update-documentation/man/shairport-sync.html.
  
- `-d`
+ Apart from the following options, all command line options can be replaced by settings in the configuration file. Here is a brief description of command line options that are not replicated by settings in the settings file.
  
- Basically all it does is put the program in daemon mode, selects the default output device and uses a software volume control.
+ * The `-c` option allows you to specify the location of the configuration file — default is `/etc/shairport-sync.conf`.
+ * The `-V` option gives you version information about  Shairport Sync and then quits.
+ * The `-d` option causes Shairport Sync to properly daemonise itself, that is, to run in the background. You may need sudo privileges for this.
+ * The `-k` option causes Shairport Sync to kill an existing Shairport Sync daemon. You may need to have sudo privileges for this.
  
- *Examples*
+ The System V init script at `/etc/init.d/shairport-sync` has a bare minimum :
+ `-d`. Basically all it does is put the program in daemon mode. The program will read its settings from the configuration file, normally `/etc/shairport-sync.conf`.
  
- Here are some examples of complete commands. If you are modifying the init script, you don't need the `shairport-sync` at the start, but you should include the `-d` option, as it puts the program into daemon mode. There are some commented-out examples in the init script -- see lines 61--63.
+ Examples
+ --------
  
- - `shairport-sync -d -a "Joe's Stereo" -- -d hw:0`
+ Here are some examples of complete configuration files. 
  
- This gives the service a particular name -- "Joe's Stereo" and specifies that audio device hw:0 be used.
+ ```
+ general = {
+   name = "Joe's Stereo";
+ };
  
+ alsa = {
+   output_device = "hw:0";
+ };
+ ```
  
For best results -- including getting true mute and instant response to volume control and pause commands -- you should access the hardware volume controls. Use `amixer` or `alsamixer` or similar to discover the name of the volume controller to be used after the `-c` option.
This gives the service a particular name — "Joe's Stereo" and specifies that audio device hw:0 be used.
  
- Here is an example for for a Raspberry Pi using its internal soundcard -- device hw:0 -- that drives the headphone jack:
+ For best results — including getting true mute and instant response to volume control and pause commands — you should access the hardware volume controls. Use `amixer` or `alsamixer` or similar to discover the name of the volume controller to be used after the `-c` option.
  
- - `shairport-sync -d -a "Mike's Boombox" -- -d hw:0 -t hardware -c PCM`
+ Here is an example for for a Raspberry Pi using its internal soundcard — device hw:0 — that drives the headphone jack:
+ ```
+ general = {
+   name = "Mike's Boombox";
+ };
+ alsa = {
+   output_device = "hw:0";
+   mixer_control_name = "PCM";
+ };
+ ```
  
  Here is an example of using soxr-based resampling and driving a Topping TP30 Digital Amplifier, which has an integrated USB DAC and which is connected as audio device `hw:1`:
- - `shairport-sync -d -a Kitchen -S soxr -- -d hw:1 -t hardware -c PCM`
+ ```
+ general = {
+   name = "Kitchen";
+   interpolation = "soxr";
+ };
+ alsa = {
+   output_device = "hw:1";
+   mixer_control_name = "PCM";
+ };
+ ```
  
  For a cheapo "3D Sound" USB card (Stereo output and input only) on a Raspberry Pi:
- - `shairport-sync -d -a "Front Room" -- -d hw:1 -t hardware -c Speaker`
+ ```
+ general = {
+   name = "Front Room";
+ };
+ alsa = {
+   output_device = "hw:1";
+   mixer_control_name = "Speaker";
+ };
+ ```
  
  For a first generation Griffin iMic on a Raspberry Pi:
+ ```
+ general = {
+   name = "Attic";
+ };
+ alsa = {
+   output_device = "hw:1";
+   mixer_control_name = "PCM";
+ };
+ ```
  
- - `shairport-sync -d -a "Attic" -- -d hw:1 -t hardware -c PCM`
- For an NSLU2, which has no internal soundcard, there appears to be a bug in ALSA -- you can not specify a device other than "default". Thus:
+ For an NSLU2, which has no internal soundcard, there appears to be a bug in ALSA — you can not specify a device other than "default". Thus:
  
  On an NSLU2, to drive a first generation Griffin iMic:
+ ```
+ general = {
+   name = "Den";
+ };
  
- - `shairport-sync -d -a "Den" -- -t hardware -c PCM`
+ alsa = {
+   mixer_control_name = "PCM";
+ };
+ ```
  
  On an NSLU2, to drive the "3D Sound" USB card:
+ ```
+ general = {
+   name = "TV Room";
+ };
  
- - `shairport-sync -d -a "TV Room" -- -t hardware -c Speaker`
+ alsa = {
+   mixer_control_name = "Speaker";
+ };
+ ```
  
  Latency
  -------
diff --cc RELEASENOTES.md
index 0bd26dafad174b372108e31fb1ee1c9ab3b42ab1,de425abad3adfcf10b65d410437d023d0f181176..0612da14b7e2a8bf76f9bd41944bd071356f8ffb
 - * A new, supported audio back end called `stdio` provides raw 16-bit 44.1kHz stereo PCM output. To activate, set  `output_backend = "stdout"` in the general section of the configuration file. Output is provided synchronously with the source feed. No stuffing or stripping is done. If you are feeding it to an output device that runs slower or faster, you'll eventually get buffer overflow or underflow in that device. To include support for this back end, use the configuration option `--with-stdout`.
+ Version 2.4
+ ----
+ **Stable release**
+ This stable release is the culmination of the 2.3.X sequence of development releases.
+ **Change Summary**
+ Changes from the previous stable version -- 2.2.5 -- are summarised here:
+  * Settings are now read from a configuration file. Command-line settings are supported but discouraged.
+  * Metadata is now supported -- it can be delivered to a unix pipe for processing by a helper application. See https://github.com/mikebrady/shairport-sync-metadata-reader for a sample metadata reader.
+  * Raw PCM audio can be delivered to standard output ("stdout") or to a unix pipe. The internal architecture has changed considerably to support this.
+  * Support for compilation on OpenWrt back to Attitude Adjustment.
+  * Version 2.4 uses the libconfig library.
+  * Runs on a wider range of platforms, including Arch Linux and Fedora.
+  * Bug fixes.
+ Please note that building instructions have changed slightly from the previous version.
+ Also, the `-t hardware/software` option has been deprecated in the alsa back end. 
+ Version 2.3.13
+ ----
+ **Note**
+ * We're getting ready to release the development branch as the new, stable, master branch at 2.4. If you're packaging Shairport Sync, you might prefer to wait a short while as we add a little polish before the release.
+ **Changes**
+ * Harmonise version numbers on the release and on the `shairport.spec` file used in Fedora.
+ Version 2.3.12
+ ----
+ **Note**
+ * We're getting ready to release the development branch as the new, stable, master branch at 2.4. If you're packaging Shairport Sync, you might prefer to wait a short while as we add a little polish before the release.
+ **Changes**
+ * `update-rc.d` has been removed from the installation script for System V because it causes problems for package makers. It's now noted in the user installation instructions.
+ * The `alsa` group `mixer_type` setting is deprecated and you should stop using it. Its functionality has been subsumed into `mixer_name` – when you specify a `mixer_name` it automatically chooses the `hardware` mixer type.
+ **Enhancements**
+ * Larger range of interpolation. Shairport Sync has previously constrained not to make interpolations ("corrections") of more than about 1 per 1000 real frames. This contraint has been relaxed, and it is now able to make corrections of up to 1 in 352 real frames. This might result in a faster and undesirably sudden correction early during a play session, so a number of further changes have been made. The full set of these changes is as follows:
+   * No corrections happen for the first five seconds.
+   * Corrections of up to about 1 in 1000 for the next 25 seconds.
+   * Corrections of up to 1 in 352 thereafter.
+ **Documentation Update**
+ * Nearly there with updates concerning the configuration file.
+ Version 2.3.11
+ ----
+ Documentation Update
+ * Beginning to update the `man` document to include information about the configuration file. It's pretty sparse, but it's a start.
+ Version 2.3.10
+ ----
+ Bug fix
+ * The "pipe" backend used output code that would block if the pipe didn't have a reader. This has been replaced by non-blocking code. Here are some implications:
+   * When the pipe is created, Shairport Sync will not block if a reader isn't present.
+   * If the pipe doesn't have a reader when Shairport Sync wants to output to it, the output will be discarded.
+   * If a reader disappears while writing is occuring, the write will time out after five seconds.
+   * Shairport Sync will only close the pipe on termination.
+ Version 2.3.9
+ ----
+ * Bug fix
+  * Specifying the configuration file using a *relative* file path now works properly.
+  * The debug verbosity requested with `-v`, `-vv`, etc. is now honoured before the configuration file is read. It is read and honoured from when the command line arguments are scanned the first time to get a possible configuration file path.
+ Version 2.3.8
+ ----
+ * Annoying changes you must make
+  * You probably need to change your `./configure` arguments. The flag `with-initscript` has changed to `with-systemv`. It was previously enabled by default; now you must enable it explicitly.
+ * Changes
+  * Added limited support for installing into `systemd` and Fedora systems. For `systemd` support, use the configuration flag `--with-systemd` in place of `--with-systemv`. The installation does not do everything needed, such as defining special users and groups.
+  * Renamed `with-initscript` configuration flag to `with-systemv` to describe its role more accurately.
+  * A System V startup script is no longer installed by default; if you want it, ask for it with the `--with-systemv` configuration flag.
+  * Added limited support for FreeBSD. You must specify `LDFLAGS='-I/usr/local/lib'` and `CPPFLAGS='-L/usr/local/include'` before running `./configure --with-foo etc.`
+  * Removed the `-configfile` annotation from the version string because it's no longer optional; it's always there.
+  * Removed the `dummy`, `pipe` and `stdout` backends from the standard build – they are now optional and are no longer automatically included in the build.
+ * Bug fixes
+  * Allow more stack space to prevent a segfault in certain configurations (thanks to https://github.com/joerg-krause).
+  * Add missing header files(thanks to https://github.com/joerg-krause).
+  * Removed some (hopefully) mostly silent bugs from the configure.ac file.
+  
+ Version 2.3.7
+ ----
+ * Changes
+   * Removed the two different buffer lengths for the alsa back end that made a brief appearance in 2.3.5.
+ * Enhancements
+  * Command line arguments are now given precedence over config file settings. This conforms to standard unix practice.
+  * A `–without-pkg-config` configuration argument now allows for build systems, e.g. for older OpenWrt builds, that haven't fully implemented it. There is still some unhappiness in arch linux builds.
+ * More
+  *  Quite a bit of extra diagnostic code was written to investigate clock drift, DAC timings and so on. It was useful but has been commented out. If might be useful in the future.
+ Version 2.3.5
+ ----
+ * Changes
+  * The metadata item 'sndr' is no longer sent in metadata. It's been replaced by 'snam' and 'snua' -- see below.
+ * Enhancements
+  * When a play session is initiated by a source, it attempts to reserve the player by sending an "ANNOUNCE" packet. Typically, a source device name and/or a source "user agent" is sent as part of the packet. The "user agent" is usually the name of the sending application along with some more information. If metadata is enabled, the source name, if provided, is emitted as a metadata item with the type `ssnc` and code `snam` and similarly the user agent, if provided, is sent with the type `ssnc` and code `snua`.
+  * Two default buffer lengths for ALSA -- default 6615 frames if a software volume control is used, to minimise the response time to pause and volume control changes; default 22050 frames if a hardware volume control is used, to give more resilience to timing problems, sudden processor loading, etc. This is especially useful if you are processing metadata and artwork on the same machine.
+  * Extra metadata: when a play session starts, the "Active-Remote" and "DACP-ID" fields -- information that can be used to identify the source -- are provided as metadata, with the type `ssnc` and the codes `acre` and `daid` respectively. The IDs are provided as strings.
+  * Unencrypted audio data. The iOS player "Whaale" attempts to send unencrypted audio, presumably to save processing effort; if unsuccessful, it will send encrypted audio as normal. Shairport Sync now recognises and handles unencrypted audio data. (Apparently it always advertised that it could process unencrypted audio!)
+  * Handle retransmitted audio in the control channel. When a packet of audio is missed, Shairport Sync will ask for it to be retransmitted. Normally the retransmitted audio comes back the audio channel, but "Whaale" sends it back in the control channel. (I think this is a bug in "Whaale".) Shairport Sync will now correctly handle retransmitted audio packets coming back in the control channel.
+ * Bugfixes
+  * Generate properly-formed `<item>..</item>` items of information.
+ Version 2.3.4
+ ----
+ * Enhancement
+  * When a play session starts, Shairport Sync opens three UDP ports to communicate with the source. Until now, those ports could be any high numbered port. Now, they are located within a range of 100 port locations starting at port 6001. The starting port and the port range are settable by two new general settings in `/etc/shairport-sync.conf` -- `udp_port_base` (default 6001) and `udp_port_range` (default 100). To retain the previous behaviour, set the `udp_port_base` to `0`.
+ * Bugfixes
+  * Fix an out-of-stack-space error that can occur in certain cases (thanks to https://github.com/joerg-krause).
+  * Fix a couple of compiler warnings (thanks to https://github.com/joerg-krause).
+  * Tidy up a couple of debug messages that were emitting misleading information.
+  
+ Version 2.3.3.2
+ ----
+ * Bugfix -- fixed an error in the sample configuration file.
+ Version 2.3.3.1
+ ----
+ * Enhancement
+  * Metadata format has changed slightly -- the format of each item is now `<item><type>..</type><code>..</code><length>..</length><data..>..</data></item>`, where the `<data..>..</data>` part is present if the length is non-zero. The change is that everything is now enclosed in an `<item>..</item>` pair.
+  
+ Version 2.3.2 and 2.3.3
+ ----
+ These releases were faulty and have been deleted.
+ Version 2.3.1
+ -----
+ Some big changes "under the hood" have been made, leading to limited support for unsynchronised output to `stdout` or to a named pipe and continuation of defacto support for unsynchronised PulseAudio. Also, support for a configuration file in preference to command line options, an option to ignore volume control and other improvements are provided.
+ In this release, Shairport Sync gains the ability to read settings from `/etc/shairport-sync.conf`.
+ This gives more flexibility in adding features gives better compatability across different versions of Linux.
+ Existing command-line options continue to work, but some will be deprecated and may disappear in a future version of Shairport Sync. New settings will only be available via the configuration file.
+ Note that, for the present, settings in the configuration will have priority over command line options for Shairport Sync itself, in contravention of the normal unix convention. Audio back end command line options, i.e. those after the `--`, have priority over configuration file settings for the audio backends.
+ In moving to the the use of a configuration file, some "housekeeping" is being done -- some logical corrections and other small changes are being made to option names and modes of operations, so the settings in the configuration file do not exactly match command line options.
+ When `make install` is executed, a sample configuration is installed or updated at `/etc/shairport-sync.conf.sample`. The same file is also installed as `/etc/shairport-sync.conf` if that file doesn't already exist. To prevent the configuration files being installed, use the configuration option `--without-configfiles`.
+ * Pesky Change You Must Do Something About
+ If you are using metadata, please note that the option has changed somewhat. The option `-M` has a new long name equivalent: `--metadata-pipename` and the argument you provide must now be the full name of the metadata pipe, e.g. `-M /tmp/shairport-sync-metadata`.
+ * Enhancements
+  * Shairport Sync now reads settings from the configuration file `/etc/shairport-sync.conf`. This has settings for most command-line options and it's where any new settings will go. A default configuration file will be installed if one doesn't exist, and a sample file configuration file is always installed or updated. Details of settings are provided in the sample file. Shairport Sync relies on the `libconfig` library to read configuration files. For the present, you can disable the new feature (and save the space taken up by `libconfig`) by using the configure option `--without-configfile-support`.
+  * New command-line option `-c <file>` or `--configfile=<file>` allows you to specify a configuration file other than `/etc/shairport-sync.conf`.
+  * Session Timeout and Allow Session Interruption can now be set independently. This is really some "housekeeping" as referred to above -- it's a kind of a bug fix, where the bug in question is an inappropriate connection of the setting of two parameters. To explain: (1) By default, when a source such as iTunes starts playing to the Shairport Sync device, any other source attempting to start a play session receives a "busy" signal. If a source disappears without warning, Shairport Sync will wait for 120 seconds before dropping the session and allowing another source to start a play session. (2) The command-line option `-t` or `--timeout` allows you to set the wait time before dropping the session. If you set this parameter to `0`, Shairport Sync will not send a "busy" signal, thus allowing another source to interrupt an existing one. (3) The problem is that if you set the parameter to `0`, a session will never be dropped if the source disappears without warning.
+  The (obvious) fix for this is to separate the setting of the two parameters, and this is now done in the configuration file `/etc/shairport-sync.conf` -- please see the settings `allow_session_interruption` and `session_timeout`. The behaviour of the `-t` and `--timeout` command-line options is unchanged but deprecated.
+  * New Option -- "Ignore Volume Control" ('ignore_volume_control'). If you set this to "yes", the output from Shairport Sync is always set at 100%. This is useful when you want to set the volume locally. Available via the settings file only.
+  * Statistics option correctly reports when no frames are received in a sampling interval and when output is not being synchronised.
-  * Modify the init script to start after all services are ready. Add in a commented-out sleep command if users find it necessary (thanks to https://github.com/BNoiZe).
-  * Two memory leaks fixed (thanks to https://github.com/pdgendt).
-  * An error handling time specifications for flushes was causing an audible glitch when pausing and resuming some tracks. This has been fixed (thanks to https://github.com/Hamster128).
++ * A new, supported audio back end called `stdout` provides raw 16-bit 44.1kHz stereo PCM output. To activate, set  `output_backend = "stdout"` in the general section of the configuration file. Output is provided synchronously with the source feed. No stuffing or stripping is done. If you are feeding it to an output device that runs slower or faster, you'll eventually get buffer overflow or underflow in that device. To include support for this back end, use the configuration option `--with-stdout`.
+  * Support for the `pipe` back end has been enhanced to provide raw 16-bit 44.1kHz stereo PCM output to a named pipe. To activate, set `output_backend = "pipe"` in the general section of the configuration and give the fully-specified pathname to the pipe in the pipe section of the configuration file -- see `etc/shairport-sync.conf.sample` for an example. No stuffing or stripping is done. If you are feeding it to an output device that runs slower or faster, you'll eventually get buffer overflow or underflow in that device.  To include support for this back end, use the configuration option `--with-pipe`.
+  * Support for the `dummy` audio backend device continues. To activate, set  `output_backend = "dummy"` in  in the general section of the configuration. To include support for this back end, use the configuration option `--with-dummy`.
+  * Limited support for the PulseAudio audio backend continues. To activate, set  `output_backend = "pulse"` in  in the general section of the configuration. You must still enter its settings via the command line, after the `--` as before. Note that no stuffing or stripping is done: if the PulseAudio sink runs slower or faster, you'll eventually get buffer overflow or underflow.
+  * New backend-specific settings are provided for setting the size of the backend's buffer and for adding or removing a fixed offset to the overall latency. The `audio_backend_buffer_desired_length` default is 6615 frames, or 0.15 seconds. On some slower machines, particularly with metadata processing going on, the DAC buffer can underflow on this setting, so it might be worth making the buffer larger. A problem on software mixers only is that changes to volume control settings have to propagate through the buffer to be heard, so the larger the buffer, the longer the response time. If you're using an alsa back end and are using a hardware mixers, this isn't a problem. The `audio_backend_latency_offset` allows you emit frames to the audio back end some time before or after the synchronised time. This would be useful, for example, if you are outputting to a device that takes 20 ms to process audio; yoou would specify a `audio_backend_latency_offset = -882`, where 882 is the number of frames in 20 ms, to compensate for the device delay.
+ Version 2.3
+ -----
+ * Enhancements
+  * Adding the System V startup script (the "initscript") is now a configuration option. The default is to include it, so if you want to omit the installation of the initscript, add the configuration option `--without-initscript`.
+  * Metadata support is now a compile-time option: `--with-metadata`.
+  * A metadata feed has been added. Use the option `-M <pipe-directory>`, e.g. `-M /tmp`. Shairport Sync will provide metadata in a pipe called `<pipe-directory>/shairport-sync-metadata`. (This is changed in 2.3.1.) There's a sample metadata reader at https://github.com/mikebrady/shairport-sync-metadata-reader. The format of the metadata is a mixture of XML-style tags, 4-character codes and base64 data. Please look at `rtsp.c` and `player.c` for examples. Please note that the format of the metadata may change.
+ Beware: there appears to be a serious bug in iTunes before 12.1.2, such that it may stall for a long period when sending large (more than a few hundred kilobytes) coverart images.
+ * Bugfix
+  * Fix a bug when compiling for Arch Linux on Raspberry Pi 2 (thanks to https://github.com/joaodriessen).
+  * Fix a bug  whereby if the ANNOUNCE and/or SETUP method fails, the play_lock mutex is never unlocked, thus blocking other clients from connecting. This can affect all types of users, but particularly Pulseaudio users. (Thanks to https://github.com/jclehner.)
+  * Modify the init script to start after all services are ready. Add in a commented-out sleep command if users find it necessary (thanks to https://github.com/BNoiZe).
+  * Two memory leaks fixed (thanks to https://github.com/pdgendt).
+  * An error handling time specifications for flushes was causing an audible glitch when pausing and resuming some tracks. This has been fixed (thanks to https://github.com/Hamster128).
 +Version 2.2.5
 +-----
 +* Bugfixes
 + * Fix a segfault error that can occur in certain cases (thanks again to https://github.com/joerg-krause).
 + * Include header files in common.c (thanks again to https://github.com/joerg-krause).
 +
 +Version 2.2.4
 +-----
 +* Bugfixes
 + * Fix an out-of-stack-space error that can occur in certain cases (thanks to https://github.com/joerg-krause).
 + * Fix a couple of compiler warnings (thanks to https://github.com/joerg-krause).
 +
 +Version 2.2.3
 +-----
 +* NOTE: all the metadata stuff has been moved to the "development" branch. This will become the stable branch henceforward, with just bug fixes or minor enhancements. Apologies for the inconvenience.
 +* Bugfixes
 + * Fix a bug when compiling for Arch Linux on Raspberry Pi 2 (thanks to https://github.com/joaodriessen).
 + * Fix a compiler warning (thanks to https://github.com/sdigit).
 +
  Version 2.2.2
  -----
  * Enhancement
diff --cc mdns_dns_sd.c
Simple merge
diff --cc shairport.c
index e16b670c16bedc0cc31665edd6fdd7a8ff93a4f1,8acd523b83a749dc2136ad989df97f598667f695..e6a9ea0a3314a4f245c6855d81342d3aaf94b4fd
@@@ -187,45 -220,281 +220,279 @@@ void usage(char *progname) 
  }
  
  int parse_options(int argc, char **argv) {
-   signed char    c;            /* used for argument parsing */
-   int     i = 0;        /* used for tracking options */
-   char    *stuffing = NULL;  /* used for picking up the stuffing option */
-   poptContext optCon;   /* context for parsing command-line options */
+   char *stuffing = NULL; /* used for picking up the stuffing option */
 -  
 -  
+   signed char c;      /* used for argument parsing */
+   int i = 0;          /* used for tracking options */
+   poptContext optCon; /* context for parsing command-line options */
    struct poptOption optionsTable[] = {
-     { "statistics", 0, POPT_ARG_NONE, &config.statistics_requested, 0, NULL},
-     { "version", 'V', POPT_ARG_NONE, NULL, 0, NULL},
-     { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', NULL },
-     { "daemon", 'd', POPT_ARG_NONE, &config.daemonise, 0, NULL },
-     { "disconnectFromOutput", 'D', POPT_ARG_NONE, NULL, 0, NULL },
-     { "reconnectToOutput", 'R', POPT_ARG_NONE, NULL, 0, NULL },
-     { "kill", 'k', POPT_ARG_NONE, NULL, 0, NULL },
-     { "port", 'p', POPT_ARG_INT, &config.port, 0, NULL } ,
-     { "name", 'a', POPT_ARG_STRING, &config.apname, 0, NULL } ,
-     { "output", 'o', POPT_ARG_STRING, &config.output_name, 0, NULL } ,
-     { "on-start", 'B', POPT_ARG_STRING, &config.cmd_start, 0, NULL } ,
-     { "on-stop", 'E', POPT_ARG_STRING, &config.cmd_stop, 0, NULL } ,
-     { "wait-cmd", 'w', POPT_ARG_NONE, &config.cmd_blocking, 0, NULL } ,
-     { "mdns", 'm', POPT_ARG_STRING, &config.mdns_name, 0, NULL } ,
-     { "latency", 'L', POPT_ARG_INT, &config.userSuppliedLatency, 0, NULL } ,
-     { "AirPlayLatency", 'A', POPT_ARG_INT, &config.AirPlayLatency, 0, NULL } ,
-     { "iTunesLatency", 'i', POPT_ARG_INT, &config.iTunesLatency, 0, NULL } ,
-     { "forkedDaapdLatency", 0, POPT_ARG_INT, &config.ForkedDaapdLatency, 0, NULL } ,
-     { "stuffing", 'S', POPT_ARG_STRING, &stuffing, 'S', NULL } ,
-     { "resync", 'r', POPT_ARG_INT, &config.resyncthreshold, 0, NULL } ,
-     { "timeout", 't', POPT_ARG_INT, &config.timeout, 0, NULL } ,
-     { "password", 0, POPT_ARG_STRING, &config.password, 0, NULL } ,
-     { "tolerance", 0, POPT_ARG_INT, &config.tolerance, 0, NULL } ,
-     POPT_AUTOHELP
-     { NULL, 0, 0, NULL, 0 }
-   };
-   
-   int optind=argc;
+       {"verbose", 'v', POPT_ARG_NONE, NULL, 'v', NULL},
+       {"disconnectFromOutput", 'D', POPT_ARG_NONE, NULL, 0, NULL},
+       {"reconnectToOutput", 'R', POPT_ARG_NONE, NULL, 0, NULL},
+       {"kill", 'k', POPT_ARG_NONE, NULL, 0, NULL},
+       {"daemon", 'd', POPT_ARG_NONE, &config.daemonise, 0, NULL},
+       {"configfile", 'c', POPT_ARG_STRING, &config.configfile, 0, NULL},
+       {"statistics", 0, POPT_ARG_NONE, &config.statistics_requested, 0, NULL},
+       {"version", 'V', POPT_ARG_NONE, NULL, 0, NULL},
+       {"port", 'p', POPT_ARG_INT, &config.port, 0, NULL},
+       {"name", 'a', POPT_ARG_STRING, &config.apname, 0, NULL},
+       {"output", 'o', POPT_ARG_STRING, &config.output_name, 0, NULL},
+       {"on-start", 'B', POPT_ARG_STRING, &config.cmd_start, 0, NULL},
+       {"on-stop", 'E', POPT_ARG_STRING, &config.cmd_stop, 0, NULL},
+       {"wait-cmd", 'w', POPT_ARG_NONE, &config.cmd_blocking, 0, NULL},
+       {"mdns", 'm', POPT_ARG_STRING, &config.mdns_name, 0, NULL},
+       {"latency", 'L', POPT_ARG_INT, &config.userSuppliedLatency, 0, NULL},
+       {"AirPlayLatency", 'A', POPT_ARG_INT, &config.AirPlayLatency, 0, NULL},
+       {"iTunesLatency", 'i', POPT_ARG_INT, &config.iTunesLatency, 0, NULL},
+       {"forkedDaapdLatency", 0, POPT_ARG_INT, &config.ForkedDaapdLatency, 0, NULL},
+       {"stuffing", 'S', POPT_ARG_STRING, &stuffing, 'S', NULL},
+       {"resync", 'r', POPT_ARG_INT, &config.resyncthreshold, 0, NULL},
+       {"timeout", 't', POPT_ARG_INT, &config.timeout, 't', NULL},
+       {"password", 0, POPT_ARG_STRING, &config.password, 0, NULL},
+       {"tolerance", 0, POPT_ARG_INT, &config.tolerance, 0, NULL},
+ #ifdef CONFIG_METADATA
+       {"metadata-pipename", 'M', POPT_ARG_STRING, &config.metadata_pipename, 'M', NULL},
+       {"get-coverart", 'g', POPT_ARG_NONE, &config.get_coverart, 'g', NULL},
+ #endif
+       POPT_AUTOHELP
+       {NULL, 0, 0, NULL, 0}};
+ // we have to parse the command line arguments to look for a config file
+   int optind;
+   optind = argc;
    int j;
-   for (j=0;j<argc;j++)
-     if (strcmp(argv[j],"--")==0)
-       optind=j;
+   for (j = 0; j < argc; j++)
+     if (strcmp(argv[j], "--") == 0)
+       optind = j;
+   optCon = poptGetContext(NULL, optind, (const char **)argv, optionsTable, 0);
+   poptSetOtherOptionHelp(optCon, "[OPTIONS]* ");
    
-   optCon = poptGetContext(NULL, optind,(const char **)argv, optionsTable, 0);
+    /* Now do options processing just to get a debug level */
+   debuglev = 0;
+   while ((c = poptGetNextOpt(optCon)) >= 0) {
+     switch (c) {
+     case 'v':
+       debuglev++;
+       break;
+     }
+   }
+   if (c < -1) {
+     die("%s: %s", poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(c));
+   }
+   config_setting_t *setting;
+   const char *str;
+   int value;
+   debug(1,"Looking for the configuration file \"%s\".",config.configfile);
+   
+   config_init(&config_file_stuff);
+   
+   char *config_file_real_path = realpath(config.configfile, NULL);
+   if (config_file_real_path==NULL) {
+     debug(2,"Can't resolve the configuration file \"%s\".",config.configfile);
+   } else {
+     debug(2, "Looking for configuration file at full path \"%s\"", config_file_real_path);
+     /* Read the file. If there is an error, report it and exit. */
+     if (config_read_file(&config_file_stuff, config_file_real_path)) {
+       // make config.cfg point to it
+       config.cfg = &config_file_stuff;
+       /* Get the Service Name. */
+       if (config_lookup_string(config.cfg, "general.name", &str))
+         config.apname = (char *)str;
+       /* Get the Daemonize setting. */
+       if (config_lookup_string(config.cfg, "general.daemonize", &str)) {
+         if (strcasecmp(str, "no") == 0)
+           config.daemonise = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.daemonise = 1;
+         else
+           die("Invalid daemonize option choice \"%s\". It should be \"yes\" or \"no\"");
+       }
+       /* Get the mdns_backend setting. */
+       if (config_lookup_string(config.cfg, "general.mdns_backend", &str))
+         config.mdns_name = (char *)str;
+       /* Get the output_backend setting. */
+       if (config_lookup_string(config.cfg, "general.output_backend", &str))
+         config.output_name = (char *)str;
+       /* Get the port setting. */
+       if (config_lookup_int(config.cfg, "general.port", &value)) {
+         if ((value < 0) || (value > 65535))
+           die("Invalid port number  \"%sd\". It should be between 0 and 65535, default is 5000",
+               value);
+         else
+           config.port = value;
+       }
+       /* Get the udp port base setting. */
+       if (config_lookup_int(config.cfg, "general.udp_port_base", &value)) {
+         if ((value < 0) || (value > 65535))
+           die("Invalid port number  \"%sd\". It should be between 0 and 65535, default is 6001",
+               value);
+         else
+           config.udp_port_base = value;
+       }
+       /* Get the udp port range setting. This is number of ports that will be tried for free ports , starting at the port base. Only three ports are needed. */
+       if (config_lookup_int(config.cfg, "general.udp_port_range", &value)) {
+         if ((value < 0) || (value > 65535))
+           die("Invalid port range  \"%sd\". It should be between 0 and 65535, default is 100",
+               value);
+         else
+           config.udp_port_range = value;
+       }
+       /* Get the password setting. */
+       if (config_lookup_string(config.cfg, "general.password", &str))
+         config.password = (char *)str;
+       if (config_lookup_string(config.cfg, "general.interpolation", &str)) {
+         if (strcasecmp(str, "basic") == 0)
+           config.packet_stuffing = ST_basic;
+         else if (strcasecmp(str, "soxr") == 0)
+           config.packet_stuffing = ST_soxr;
+         else
+           die("Invalid interpolation option choice \"%s\". It should be \"basic\" or \"soxr\"");
+       }
+       /* Get the statistics setting. */
+       if (config_lookup_string(config.cfg, "general.statistics", &str)) {
+         if (strcasecmp(str, "no") == 0)
+           config.statistics_requested = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.statistics_requested = 1;
+         else
+           die("Invalid statistics option choice \"%s\". It should be \"yes\" or \"no\"");
+       }
+       /* Get the drift tolerance setting. */
+       if (config_lookup_int(config.cfg, "general.drift", &value))
+         config.tolerance = value;
+       /* Get the resync setting. */
+       if (config_lookup_int(config.cfg, "general.resync_threshold", &value))
+         config.resyncthreshold = value;
+       /* Get the verbosity setting. */
+       if (config_lookup_int(config.cfg, "general.log_verbosity", &value))
+         if ((value >= 0) && (value <= 3))
+           debuglev = value;
+         else
+           die("Invalid log verbosity setting option choice \"%d\". It should be between 0 and 3, "
+               "inclusive.",
+               value);
+       /* Get the ignore_volume_control setting. */
+       if (config_lookup_string(config.cfg, "general.ignore_volume_control", &str)) {
+         if (strcasecmp(str, "no") == 0)
+           config.ignore_volume_control = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.ignore_volume_control = 1;
+         else
+           die("Invalid ignore_volume_control option choice \"%s\". It should be \"yes\" or \"no\"");
+       }
+       /* Get the default latency. */
+       if (config_lookup_int(config.cfg, "latencies.default", &value))
+         config.latency = value;
+       /* Get the itunes latency. */
+       if (config_lookup_int(config.cfg, "latencies.itunes", &value))
+         config.iTunesLatency = value;
+       /* Get the AirPlay latency. */
+       if (config_lookup_int(config.cfg, "latencies.airplay", &value))
+         config.AirPlayLatency = value;
+       /* Get the forkedDaapd latency. */
+       if (config_lookup_int(config.cfg, "latencies.forkedDaapd", &value))
+         config.ForkedDaapdLatency = value;
+   #ifdef CONFIG_METADATA
+       /* Get the metadata setting. */
+       if (config_lookup_string(config.cfg, "metadata.enabled", &str)) {
+         if (strcasecmp(str, "no") == 0)
+           config.metadata_enabled = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.metadata_enabled = 1;
+         else
+           die("Invalid metadata enabled option choice \"%s\". It should be \"yes\" or \"no\"");
+       }
+       if (config_lookup_string(config.cfg, "metadata.include_cover_art", &str)) {
+         if (strcasecmp(str, "no") == 0)
+           config.get_coverart = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.get_coverart = 1;
+         else
+           die("Invalid metadata include_cover_art option choice \"%s\". It should be \"yes\" or "
+               "\"no\"");
+       }
+       if (config_lookup_string(config.cfg, "metadata.pipe_name", &str)) {
+         config.metadata_pipename = (char *)str;
+       }
+   #endif
+       if (config_lookup_string(config.cfg, "sessioncontrol.run_this_before_play_begins", &str)) {
+         config.cmd_start = (char *)str;
+       }
+       if (config_lookup_string(config.cfg, "sessioncontrol.run_this_after_play_ends", &str)) {
+         config.cmd_stop = (char *)str;
+       }
+       if (config_lookup_string(config.cfg, "sessioncontrol.wait_for_completion", &str)) {
+         if (strcasecmp(str, "no") == 0)
+           config.cmd_blocking = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.cmd_blocking = 1;
+         else
+           die("Invalid session control wait_for_completion option choice \"%s\". It should be "
+               "\"yes\" or \"no\"");
+       }
+       if (config_lookup_string(config.cfg, "sessioncontrol.allow_session_interruption", &str)) {
+         config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0
+         if (strcasecmp(str, "no") == 0)
+           config.allow_session_interruption = 0;
+         else if (strcasecmp(str, "yes") == 0)
+           config.allow_session_interruption = 1;
+         else
+           die("Invalid session control allow_interruption option choice \"%s\". It should be \"yes\" "
+               "or \"no\"");
+       }
+       if (config_lookup_int(config.cfg, "sessioncontrol.session_timeout", &value)) {
+         config.timeout = value;
+         config.dont_check_timeout = 0; // this is for legacy -- only set by -t 0
+       }
+     } else {
+       if (config_error_type(&config_file_stuff) == CONFIG_ERR_FILE_IO)
+         debug(1, "Error reading configuration file \"%s\": \"%s\".",
+               config_error_file(&config_file_stuff), config_error_text(&config_file_stuff));
+       else {
+         die("Line %d of the configuration file \"%s\":\n%s", config_error_line(&config_file_stuff),
+             config_error_file(&config_file_stuff), config_error_text(&config_file_stuff));
+       }
+     }
+     free(config_file_real_path);
+   }
+ // now, do the command line options again, but this time do them fully -- it's a unix convention that command line
+ // arguments have precedence over configuration file settings.
+   optind = argc;
+   for (j = 0; j < argc; j++)
+     if (strcmp(argv[j], "--") == 0)
+       optind = j;
+   optCon = poptGetContext(NULL, optind, (const char **)argv, optionsTable, 0);
    poptSetOtherOptionHelp(optCon, "[OPTIONS]* ");
  
    /* Now do options processing, get portname */
@@@ -522,21 -867,23 +865,22 @@@ int main(int argc, char **argv) 
  #endif
  
  #ifdef HAVE_LIBPOLARSSL
-      md5_context tctx;
-      md5_starts(&tctx);
-      md5_update(&tctx, (unsigned char *)config.apname, strlen(config.apname));
-      md5_finish(&tctx, ap_md5);
+   md5_context tctx;
+   md5_starts(&tctx);
+   md5_update(&tctx, (unsigned char *)config.apname, strlen(config.apname));
+   md5_finish(&tctx, ap_md5);
  #endif
-     memcpy(config.hw_addr, ap_md5, sizeof(config.hw_addr));
-     rtsp_listen_loop();
+   memcpy(config.hw_addr, ap_md5, sizeof(config.hw_addr));
+ #ifdef CONFIG_METADATA
+   metadata_init(); // create the metadata pipe if necessary
+ #endif
 -
+   rtsp_listen_loop();
  
-     // should not reach this...
-     shairport_shutdown();
+   // should not reach this...
+   shairport_shutdown();
  finish:
-     daemon_log(LOG_NOTICE, "Unexpected exit...");
-     daemon_retval_send(255);
-     daemon_pid_file_remove();
-     return 1;
+   daemon_log(LOG_NOTICE, "Unexpected exit...");
+   daemon_retval_send(255);
+   daemon_pid_file_remove();
+   return 1;
  }