diff --git a/.gitignore b/.gitignore
index a559c3e4..a7708cab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
/shairport-sync
/*.o
/*~
+*.xml~
/config.mk
/config.h
Makefile
diff --git a/Makefile.am b/Makefile.am
index 97cebcbc..fcf68059 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
SUBDIRS = man
bin_PROGRAMS = shairport-sync
-shairport_sync_SOURCES = shairport.c rtsp.c mdns.c mdns_external.c common.c rtp.c player.c alac.c audio.c audio_dummy.c audio_pipe.c audio_stdout.c
+shairport_sync_SOURCES = shairport.c rtsp.c mdns.c mdns_external.c common.c rtp.c player.c alac.c audio.c
AM_CFLAGS = -Wno-multichar
@@ -56,10 +56,9 @@ if INSTALL_CONFIG_FILES
cp scripts/shairport-sync.conf $(DESTDIR)/etc/shairport-sync.conf.sample
[ -f $(DESTDIR)/etc/shairport-sync.conf ] || cp scripts/shairport-sync.conf $(DESTDIR)/etc/shairport-sync.conf
endif
-if INSTALL_INITSCRIPT
+if INSTALL_SYSTEMV
[ -e $(DESTDIR)/etc/init.d ] || mkdir -p $(DESTDIR)/etc/init.d
- [ -f /etc/init.d/shairport-sync ] || cp scripts/shairport-sync $(DESTDIR)/etc/init.d/
- update-rc.d shairport-sync defaults 90 10
+ [ -f $(DESTDIR)/etc/init.d/shairport-sync ] || cp scripts/shairport-sync $(DESTDIR)/etc/init.d/
endif
if INSTALL_SYSTEMD
[ -e $(DESTDIR)/usr/lib/systemd/system ] || mkdir -p $(DESTDIR)/usr/lib/systemd/system
diff --git a/README.md b/README.md
index 937c0328..5e3cacd4 100644
--- a/README.md
+++ b/README.md
@@ -1,50 +1,52 @@
Shairport Sync (Development Branch)
=============
Shairport Sync emulates an AirPort Express for the purpose of streaming audio from iTunes, iPods, iPhones, iPads and AppleTVs.
-Audio played by a Shairport Sync-powered device stays synchronised with the source and hence with similar devices playing the same source. Thus, for example, synchronised multi-room audio is possible without difficulty. (Hence the name Shairport Sync, BTW.)
+Audio played by a Shairport Sync-powered device stays synchronised with the source and hence with similar devices playing the same source. In this way, synchronised multi-room audio is possible without difficulty. (Hence the name Shairport Sync, BTW.)
Shairport Sync does not support AirPlay video or photo streaming.
-This branch -- "development" -- is the development branch of Shairport Sync and is unstable. To access the stable branch, please switch to the "master" branch.
+This branch — "development" — is unstable. To access the stable branch, please switch to the "master" branch.
More Information
----------
-Shairport Sync works by using timing information present in the audio data stream to keep in synchrony with the source. It does this by monitoring and controlling the "latency" -- the time between when a sound is time-stamped at the source and when it is played by the audio output device. To measure latency precisely, it keeps its own clock synchronised with the clock used by the source, usually to within a fraction of a millisecond, using a variant of NTP synchronisation protocols.
+Shairport Sync works by using timing information and timestamps present in data coming from the audio source (e.g. an iPhone) to "play" audio at exactly the right time. It does this by monitoring and controlling the *latency* — the time between a sound frame is supposed to be played, as specified by its `timestamp`, and the time when it is actually played by the audio output device, usually a Digital to Audio Converter (DAC). Timestamps are measured relative to the source computer's clocks, the `source clock`, but timing must be done relative to the clock of the computer running Shairport Sync, the `local clock`. The source and local clocks are synchronised, usually to within a fraction of a millisecond, using a variant of NTP synchronisation protocols.
-To maintain the exact latency required, if an output device is running slow relative to the source, Shairport Sync will delete frames of audio to allow the device to keep up; if the device is running fast, Shairport Sync will insert frames to keep time. The number of frames inserted or deleted is so small as to be almost inaudible. Frames are inserted or deleted as necessary at pseudorandom intervals. Alternatively, with `libsoxr` support, Shairport Sync can resample the audio feed to ensure the output device can keep up. This is even less obtrusive than insertion and deletion but requires a good deal of processing power -- most embedded devices probably can't support it.
+To maintain the exact latency required, if an output device is running slow relative to the source, Shairport Sync will delete frames of audio to allow the device to keep up. If the output device is running fast, Shairport Sync will insert frames to keep time. The number of frames inserted or deleted is so small as to be almost inaudible on normal audio material. Frames are inserted or deleted as necessary at pseudorandom intervals. Alternatively, with `libsoxr` support, Shairport Sync can resample the audio feed to ensure the output device can keep up. This is less obtrusive than insertion and deletion but requires a good deal of processing power — most embedded devices probably can't support it. The process of insertion/deletion or resampling is rather inelegantly called “stuffing”.
-There are four default latency settings, chosen automatically. One latency matches the latency used by recent versions of iTunes when playing audio and the other matches the latency used by older version of iTunes, by iOS devices and by iTunes and Quicktime Player when playing video. A third default latency is used when the audio source is `forked-daapd`. The fourth latency is the default if no other latency is chosen.
+There are four default latency settings, chosen automatically. One latency matches the latency used by recent versions of iTunes when playing audio and another matches the latency used by so-called "AirPlay" devices — iOS devices and iTunes and Quicktime Player when they are playing video. A third latency is used when the audio source is `forked-daapd`. The fourth latency is the default if no other latency is chosen and is used for older versions of iTunes.
-Shairport Sync is a pretty substantial rewrite of Shairport 1.0 by James Laird and others -- please see https://github.com/abrasive/shairport/blob/master/README.md#contributors-to-version-1x for a list of the contributors to Shairport 1.x and Shairport 0.x. From a "heritage" point of view, Shairport Sync is a fork of Shairport 1.0.
+Shairport Sync is a pretty substantial rewrite of the fantastic work done in Shairport 1.0 by James Laird and others — please see https://github.com/abrasive/shairport/blob/master/README.md#contributors-to-version-1x for a list of the contributors to Shairport 1.x and Shairport 0.x. From a "heritage" point of view, Shairport Sync is a fork of Shairport 1.0.
-Shairport Sync works only with Linux and ALSA. The sound card you use must be capable of working with 44,100 samples per second interleaved PCM stereo (you'll get a message in the logfile if there's a problem).
+Shairport Sync is designed for Linux and ALSA. It must have direct access to the output device, which must be a sound card capable of working with 44,100 samples per second interleaved PCM stereo (you'll get a message in the logfile if there's a problem).
For more about the motivation behind Shairport Sync, please see the wiki at https://github.com/mikebrady/shairport-sync/wiki.
What else?
--------------
-* Better Volume Control -- Shairport Sync offers finer control at very top and very bottom of the volume range. See http://tangentsoft.net/audio/atten.html for a good discussion of audio "attenuators", upon which volume control in Shairport Sync is modelled. See also the diagram of the volume transfer function in the documents folder.
-* Hardware Mute -- Shairport Sync will mute properly if the hardware supports it.
-* If Shairport Sync has to use software volume and mute controls, the response time is shorter than before -- now it responds in 0.15 seconds.
-* Non-Interruptible -- Shairport Sync sends back a "busy" signal if it's already playing audio from another source, so other sources can't disrupt an existing Shairport Sync session. (If a source disappears without warning, the session automatically terminates after two minutes and the device becomes available again.)
-* Metadata -- Shairport Sync can be configured to receive metadata, such as Album Name, Artist Name, Cover Art, etc. and deliver it through a pipe to a recipient application program -- see https://github.com/mikebrady/shairport-sync-metadata-reader for a sample recipient.
+* Better Volume Control — Shairport Sync offers finer control at very top and very bottom of the volume range. See http://tangentsoft.net/audio/atten.html for a good discussion of audio "attenuators", upon which volume control in Shairport Sync is modelled. See also the diagram of the volume transfer function in the documents folder.
+* Hardware Mute — Shairport Sync will mute properly if the hardware supports it.
+* Fast Response — With hardware volume control, response is instantaneous; otherwise the response time is 0.15 seconds.
+* Non-Interruptible — Shairport Sync sends back a "busy" signal if it's already playing audio from another source, so other sources can't disrupt an existing Shairport Sync session. (If a source disappears without warning, the session automatically terminates after two minutes and the device becomes available again.)
+* Metadata — Shairport Sync can be configured to deliver metadata, such as Album Name, Artist Name, Cover Art, etc. through a pipe to a recipient application program — see https://github.com/mikebrady/shairport-sync-metadata-reader for a sample recipient.
+* Raw Audio — Shairport Sync can deliver raw PCM audio to standard output or to a pipe. This output is delivered synchronously with the source after the appropriate latency and is not interpolated or "stuffed" on its way through Shairport Sync.
+* Autotools and Libtool Support — One important difference between Shairport Sync and other versions of Shairport is that the Shairport Sync build process uses GNU autotools and libtool to examine and configure the build environment — very important for cross compilation. Previous versions of Shairport looked at the current system to determine which packages were available, instead of looking at the target system for what packages were available.
Status
------
-Shairport Sync works on standard Ubuntu laptops, on the Raspberry Pi with Raspian and with OpenWrt, and it runs on a Linksys NSLU2 using OpenWrt. It works with built-in audio and with a variety of USB-connected audio amplifiers and DACs, including a cheapo USB "3D Sound" dongle, a first generation iMic and a Topping TP30 amplifier with a USB DAC input.
+Shairport Sync works on a wide variety of Linux devices. It works on standard Ubuntu laptops, on the Raspberry Pi with Raspian, Arch Linux and OpenWrt, and it runs on a Linksys NSLU2 and a TP-Link 710N using OpenWrt. It works with built-in audio and with a variety of USB-connected audio amplifiers and DACs, including a cheapo USB "3D Sound" dongle, a first generation iMic and a Topping TP30 amplifier with a USB DAC input.
-Shairport Sync runs well on the Raspberry Pi. It can drive the built-in sound card, and though you wouldn't mistake the output for HiFi, it's really not too shabby. USB-connected sound cards work well on the latest version of Raspian; however older versions of Raspian appear to suffer from a problem -- see http://www.raspberrypi.org/forums/viewtopic.php?t=23544, so it is wise to update. Shairport Sync works very well with the IQAudIO Pi-DAC -- see http://www.iqaudio.com.
+Shairport Sync runs well on the Raspberry Pi. It can drive the built-in sound card, though the audio out of the card is of poor quality. USB-connected sound cards work well on recent versions of Raspian; however older versions of Raspian appear to suffer from a problem — see http://www.raspberrypi.org/forums/viewtopic.php?t=23544, so it is wise to update. Shairport Sync works well with the IQAudIO Pi-DAC — see http://www.iqaudio.com.
At the time of writing, OpenWrt trunk does not support USB audio well on the Raspberry Pi.
-Shairport Sync runs on Ubuntu and Debian inside VMWare Fusion 7 on a Mac, but synchronisation does not work -- possibly because the soundcard is being emulated.
+Shairport Sync runs on Ubuntu and Debian inside VMWare Fusion 7 on a Mac, but synchronisation does not work — possibly because the soundcard is being emulated.
-Shairport Sync works only with the ALSA back end. You can try compiling the other back ends in as you wish, but it definitely will not work properly with them. Maybe someday...
-
-One other difference from other versions of Shairport is that the Shairport Sync build process uses GNU autotools and libtool to examine and configure the build environment -- very important for cross compilation. All previous versions looked in the current system to determine which packages were available, instead of looking at what packages were available in the target system.
+Shairport Sync will output to alsa cards, to standard output and to pipes using appropriate backends. You can try compiling additional backends in as you wish, but it definitely will not work properly with them. Maybe someday...
For information about changes and updates, please refer to the RELEASENOTES.md file in the distribution.
+Note: Historically, Shairport Sync has taken its settings from command line arguments. While this is still the case, it does not always work well across distributions. Accordingly, from version 2.4 onwards, Shairport Sync reads settings from the file `/etc/shairport-sync.conf`. Access to new settings will be provided only in the settings file.
+
Building And Installing
---------------------
If you're interested in Shairport Sync for OpenWrt, there's an OpenWrt package at https://github.com/mikebrady/shairport-sync-for-openwrt. OpenWrt doesn't support the IQaudIO Pi-DAC.
@@ -66,7 +68,7 @@ The following libraries are required:
Optional:
* libsoxr
-Many linux distributions have Avahi and OpenSSL already in place, so normally it probably makes sense to choose those options rather than tinysvcmdns or PolarSSL. Libsoxr is available in recent linux distributions, but it requires lots of processor power -- chances are an embedded processor won't be able to keep up.
+Many Linux distributions have Avahi and OpenSSL already in place, so normally it probably makes sense to choose those options rather than tinysvcmdns or PolarSSL. Libsoxr is available in recent Linux distributions, but it requires lots of processor power — chances are an embedded processor won't be able to keep up.
Assuming the usual build essentials and git, Debian, Ubuntu and Raspian users can get the basics with:
@@ -90,144 +92,224 @@ $ autoreconf -i -f
Choose the appropriate `--with-*` options:
- `--with-alsa` for the ALSA audio back end. This is required.
-- `--with-avahi` or `--with-tinysvcmdns` for mdns support. Avahi is a widely-used system-wide zero-configuration networking (zeroconf) service -- it may already be in your system. (There seem to be problems with the `--with-tinysvcmdns` option right now, so read the following with caution.) If you don't have Avahi, or similar, then consider including tinysvcmdns, which is a tiny zeroconf service embedded inside the shairport-sync application itself. To enable multicast for `tinysvcmdns`, you may have to add a default route with the following command: `route add -net 224.0.0.0 netmask 224.0.0.0 eth0` (substitute the correct network port for `eth0`). You should not have more than one zeroconf service on the same system -- bad things may happen, according to RFC 6762, §15.
+- `--with-avahi` or `--with-tinysvcmdns` for mdns support. Avahi is a widely-used system-wide zero-configuration networking (zeroconf) service — it may already be in your system. If you don't have Avahi, or similar, then consider including tinysvcmdns, which is a tiny zeroconf service embedded inside the shairport-sync application itself. To enable multicast for `tinysvcmdns`, you may have to add a default route with the following command: `route add -net 224.0.0.0 netmask 224.0.0.0 eth0` (substitute the correct network port for `eth0`). You should not have more than one zeroconf service on the same system — bad things may happen, according to RFC 6762, §15.
- `--with-ssl=openssl` or `--with-ssl=polarssl` for encryption and related utilities using either OpenSSL or PolarSSL.
- `--with-soxr` for libsoxr-based resampling.
- `--with-piddir` for specifying where the PID file should be stored. This directory is normally chosen automatically. The directory must be writable. If you use this option, you may have to edit the init script to search for the PID file in your new location.
- `--with-metadata` to add support for Shairport Sync to pipe metadata to a compatible application of your choice. See https://github.com/mikebrady/shairport-sync-metadata-reader for a sample metadata reader.
+- `--with-systemv` to install a System V init script at the `make install` stage. Default is not to to install.
+- `--with-configfiles` to install a configuration file and sample at the `make install` stage. Default is to install. An existing `/etc/shairport-sync.conf` will not be overwritten.
+- `--with-pkg-config` to use pkg-config to find libraries. Default is to use pkg-config — this option is for special purpose use.
-Here is an example, suitable for most installations:
+Here is an example, suitable for installations such as Ubuntu and Raspbian:
-`$ ./configure --with-alsa --with-avahi --with-ssl=openssl --with-metadata --with-soxr`
+`$ ./configure --with-alsa --with-avahi --with-ssl=openssl --with-metadata --with-soxr --with-systemv`
-Omit the `--with-soxr` if the libsoxr library is not available.
+Omit the `--with-soxr` if the libsoxr library is not available. For installation into a `systemd` system, replace the `--with-systemv` with `--with-systemd`.
+
+Enter:
`$ make`
-Run `$sudo make install` to install `shairport-sync` along with a default configuration file and 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 different card, use the hardware mixer and volume control, etc. -- there are some examples in the sample configuration file.
+to build the application. Next, run:
+
+```
+$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.
+
+*Man Page*
-Man Page
---------
You can view the man page here: http://htmlpreview.github.io/?https://github.com/mikebrady/shairport-sync/blob/development/man/shairport-sync.html
Configuring Shairport Sync
--------
-There are two logically distinct parts to getting Shairport Sync to run properly on your machine -- the first part is getting it to start and stop automatically, and this is taken care of using a startup script at `/etc/init.d/shairport-sync`. The second part is giving Shairport Sync the correct settings, e.g. the correct output device to use, the service name that will appear in iTunes, etc. and this is done using the configuration file `/etc/shairport-sync.conf`.
+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.
-Shairport Sync reads its configuration 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. A sample configuration file is also installed or updated at `/etc/shairport-sync.conf.sample`. 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.
+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.
-To understand what follows, note that settings and parameters are given to Shairport Sync via the file `/etc/shairport-sync.conf`. The purpose of the init script at `/etc/init.d/shairport-sync` is merely to launch and terminate Shairport Sync. 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!
+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.
-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.
+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.
-These are the important options:
+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 `-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.
+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:
-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.
+```
+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 `--password` option allows you to password-protect access to the service provided by Shairport Sync.
+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`:
-These may be also of interest:
+```
+alsa =
+{
+ output_device = "hw:0,5";
+ mixer_device = "hw:0";
+ mixer_control_name = "PCM";
+ // ... other alsa settings
+};
+```
-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.)
+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.
+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.)
+
+*Command Line Arguments*
+
+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.
+
+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.
+
+* 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 `-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.
+* The `-k` option causes Shairport Sync to kill an existing Shairport Sync daemon. You may need to have sudo privileges for this.
-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:
+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`.
-* 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`.
+Examples
+--------
-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.
+Here are some examples of complete configuration files.
-The init script at `/etc/init.d/shairport-sync` has a bare minimum set of options (see line 60):
+```
+general = {
+ name = "Joe's Stereo";
+};
-`-d`
+alsa = {
+ output_device = "hw:0";
+};
+```
-Basically all it does is put the program in daemon mode, selects the default output device and uses a software volume control.
+This gives the service a particular name — "Joe's Stereo" and specifies that audio device hw:0 be used.
-*Examples*
+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.
-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.
+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";
+};
-- `shairport-sync -d -a "Joe's Stereo" -- -d hw:0`
-
-This gives the service a particular name -- "Joe's Stereo" and specifies that audio device hw:0 be used.
-
-
-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.
-
-Here is an example for for a Raspberry Pi using its internal soundcard -- device hw:0 -- that drives the headphone jack:
-
-- `shairport-sync -d -a "Mike's Boombox" -- -d hw:0 -t hardware -c PCM`
+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`:
+```
+general = {
+ name = "Kitchen";
+ interpolation = "soxr";
+};
-- `shairport-sync -d -a Kitchen -S soxr -- -d hw:1 -t hardware -c PCM`
+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:
+```
+general = {
+ name = "Front Room";
+};
-- `shairport-sync -d -a "Front Room" -- -d hw:1 -t hardware -c Speaker`
+alsa = {
+ output_device = "hw:1";
+ mixer_control_name = "Speaker";
+};
+```
For a first generation Griffin iMic on a Raspberry Pi:
+```
+general = {
+ name = "Attic";
+};
-- `shairport-sync -d -a "Attic" -- -d hw:1 -t hardware -c PCM`
+alsa = {
+ output_device = "hw:1";
+ mixer_control_name = "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
-------
-Latency is the exact time from a sound signal's original timestamp until that signal actually "appears" on the output of the DAC, irrespective of any internal delays, processing times, etc. in the computer. From listening tests, it seems that there are two latencies in current use:
+Latency is the exact time from a sound signal's original timestamp until that signal actually "appears" on the output of the audio output device, usually a Digital to Audio Converter (DAC), irrespective of any internal delays, processing times, etc. in the computer. From listening tests, it seems that there are three latencies in current use:
* If the source is iTunes 10 or later, a latency of 99,400 frames seems to bring Shairport Sync into exact synchronisation both with the speakers on the iTunes computer itself and with AirPort Express receivers.
* If the source is an AirPlay device, the latency seems to be exactly 88,200 frames. AirPlay devices include AppleTV, iPod, iPad and iPhone and Quicktime Player on Mac.
* If the source is a `forked-daapd`-powered device, the latency seems to be exactly 99,400 frames.
* If the source cannot be identified as AirPlay or as iTunes 10 or later, then the default latency of 88,200 frames seems to work in general. Note that some third party programs masquerade as older versions of iTunes.
-Shairport Sync uses the latencies described above as defaults. You shouldn't need to change them, but occasionally problems arise when you are trying to synchronise with speaker systems -- typically surround-sound home theatre systems -- that have their own inherent delays. You can set the default latency with the `-L` or `--latency` option (e.g. `-L 99400` or `--latency=99400`). You can set your own iTunes 10 (or later) latency with the `-i` or `--iTunesLatency` option. Similarly you can set an AirPlay latency with the `-A` or `--AirPlayLatency` option and the forked-daapd latency with the `--forkedDaapdLatency` option.
+Shairport Sync uses the latencies described above as defaults. You shouldn't need to change them.
+
+Problems can arise when you are trying to synchronise with speaker systems — typically surround-sound home theatre systems — that have their own inherent delays. You can compensate for an inherent delay using the `alsa` group `audio_backend_latency_offset`. Set this offset (in frames) to compensate for a fixed delay in the audio back end, for example, if the output device delays by 100 ms, set this to -4410.
Resynchronisation
-------------
Shairport Sync actively maintains synchronisation with the source.
-If synchronisation is lost -- say due to a busy source or a congested network -- Shairport Sync will mute its output and resynchronise. The loss-of-sync threshold is a very conservative 50 ms -- i.e. the actual time and the expected time must differ by more than 50 ms to trigger a resynchronisation. Smaller disparities are corrected by insertions or deletions, as described above.
-* You can vary the resync threshold, or turn resync off completely, with the `-r` opton.
+If synchronisation is lost — say due to a busy source or a congested network — Shairport Sync will mute its output and resynchronise. The loss-of-sync threshold is a very conservative 50 ms — i.e. the actual time and the expected time must differ by more than 50 ms to trigger a resynchronisation. Smaller disparities are corrected by insertions or deletions, as described above.
+* You can vary the resync threshold, or turn resync off completely, with the `general` `resync_threshold` setting.
Tolerance
---------
-Playback synchronisation is allowed to wander a small amount before attempting to correct it. The default is 88 frames, i.e. 2 ms. The smaller the tolerance, the more likely it is that overcorrection will occur. Overcorrection is when more corrections (insertions and deletions) are made than are strictly necessary to keep the stream in sync. Use the --statistics option to monitor correction levels. Corrections should not greatly exceed net corrections.
-* You can vary the tolerance with the `--tolerance` option.
+Playback synchronisation is allowed to wander a small amount before attempting to correct it. The default is 88 frames, i.e. 2 ms. The smaller the tolerance, the more likely it is that overcorrection will occur. Overcorrection is when more corrections (insertions and deletions) are made than are strictly necessary to keep the stream in sync. Use the statistics setting to monitor correction levels. Corrections should not greatly exceed net corrections.
+* You can vary the tolerance with the `general` `drift` setting.
Some Statistics
---------------
-If you add the option `--statistics`, e.g. as follows for the Raspberry Pi with "3D Sound" card:
-
-`shairport-sync -a "Shairport Sync" --statistics -- -d hw:1 -t hardware -c Speaker`
-
-it will print statistics like this occasionally on the console (or in the logfile if running in daemon mode):
+If you turn on the `general` `statistics` setting, statistics like this will be printed at intervals on the console (or in the logfile if running in daemon mode):
`Sync error: -35.4 (frames); net correction: 24.2 (ppm); corrections: 24.2 (ppm); missing packets 0; late packets 5; too late packets 0; resend requests 6; min DAC queue size 4430.`
-"Sync error" is the average deviation from exact synchronisation. The example above indicates that the output is on average 35.4 frames ahead of exact synchronisation. Sync is allowed to wander by the tolerance -- 88 frames (± 2 milliseconds) by default -- before a correction will be made.
+"Sync error" is the average deviation from exact synchronisation. The example above indicates that the output is on average 35.4 frames ahead of exact synchronisation. Sync is allowed to wander by the tolerance — 88 frames (± 2 milliseconds) by default — before a correction will be made.
-"Net correction" is actually the net sum of corrections -- the number of frame insertions less the number of frame deletions -- given as a moving average in parts per million. After an initial settling period, it represents the divergence between the source clock and the sound device's clock. The example above indicates that the output DAC's clock is running 24.2 ppm faster than the source's clock.
+"Net correction" is actually the net sum of corrections — the number of frame insertions less the number of frame deletions — given as a moving average in parts per million. After an initial settling period, it represents the drift — the divergence between the rate at which frames are generated at the source and the rate at which the output device consumes them. The example above indicates that the output device is consuming frames 24.2 ppm faster than the source is generating them.
-"Corrections" is the number of frame insertions plus the number of frame deletions (i.e. the total number of corrections), given as a moving average in parts per million. The closer this is to the absolute value of the drift, the fewer "unnecessary" corrections that are being made. Third party programs tend to have much larger levels of corrections.
+"Corrections" is the number of frame insertions plus the number of frame deletions (i.e. the total number of corrections), given as a moving average in parts per million. The closer this is to the net corrections, the fewer "unnecessary" corrections that are being made. Third party programs tend to have much larger levels of corrections.
For reference, a drift of one second per day is approximately 11.57 ppm. Left uncorrected, even a drift this small between two audio outputs will be audible after a short time. The above sample is from a second-generation iPod driving the Raspberry Pi which is connected over Ethernet.
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 53a2595c..2065e991 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -1,3 +1,60 @@
+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
diff --git a/audio.c b/audio.c
index e8f56718..6c2c6fce 100644
--- a/audio.c
+++ b/audio.c
@@ -41,7 +41,15 @@ extern audio_output audio_pulse;
#ifdef CONFIG_ALSA
extern audio_output audio_alsa;
#endif
-extern audio_output audio_dummy, audio_pipe, audio_stdout;
+#ifdef CONFIG_DUMMY
+extern audio_output audio_dummy;
+#endif
+#ifdef CONFIG_PIPE
+extern audio_output audio_pipe;
+#endif
+#ifdef CONFIG_STDOUT
+extern audio_output audio_stdout;
+#endif
static audio_output *outputs[] = {
#ifdef CONFIG_SNDIO
@@ -56,7 +64,16 @@ static audio_output *outputs[] = {
#ifdef CONFIG_AO
&audio_ao,
#endif
- &audio_dummy, &audio_pipe, &audio_stdout, NULL};
+#ifdef CONFIG_DUMMY
+ &audio_dummy,
+#endif
+#ifdef CONFIG_PIPE
+ &audio_pipe,
+#endif
+#ifdef CONFIG_STDOUT
+ &audio_stdout,
+#endif
+ NULL};
audio_output *audio_get_output(char *name) {
audio_output **out;
diff --git a/audio_alsa.c b/audio_alsa.c
index b3335d7e..9b423f9e 100644
--- a/audio_alsa.c
+++ b/audio_alsa.c
@@ -85,7 +85,6 @@ static int64_t accumulated_delay, accumulated_da_delay;
static void help(void) {
printf(" -d output-device set the output device [default*|...]\n"
- " -t mixer-type set the mixer type [software*|hardware]\n"
" -m mixer-device set the mixer device ['output-device'*|...]\n"
" -c mixer-control set the mixer control [Master*|...]\n"
" -i mixer-index set the mixer index [0*|...]\n"
@@ -103,7 +102,7 @@ static int init(int argc, char **argv) {
- // get settings from settings file first, allow them to be over-ridden by command line options
+ // get settings from settings file first, allow them to be overridden by command line options
if (config.cfg != NULL) {
/* Get the desired buffer size setting. */
@@ -131,15 +130,13 @@ static int init(int argc, char **argv) {
alsa_out_dev = (char *)str;
}
+
/* Get the Mixer Type setting. */
+
if (config_lookup_string(config.cfg, "alsa.mixer_type", &str)) {
- if (strcasecmp(str, "software") == 0)
- hardware_mixer = 0;
- else if (strcasecmp(str, "hardware") == 0)
- hardware_mixer = 1;
- else
- die("Invalid alsa mixer option choice \"%s\". It should be \"software\" or \"hardware\"");
+ inform("The alsa mixer_type setting is deprecated and has been ignored. FYI, using the \"mixer_control_name\" setting automatically chooses a hardware mixer.");
}
+
/* Get the Mixer Device Name. */
if (config_lookup_string(config.cfg, "alsa.mixer_device", &str)) {
@@ -149,6 +146,7 @@ static int init(int argc, char **argv) {
/* Get the Mixer Control Name. */
if (config_lookup_string(config.cfg, "alsa.mixer_control_name", &str)) {
alsa_mix_ctrl = (char *)str;
+ hardware_mixer = 1;
}
}
@@ -162,15 +160,17 @@ static int init(int argc, char **argv) {
case 'd':
alsa_out_dev = optarg;
break;
+
case 't':
- if (strcmp(optarg, "hardware") == 0)
- hardware_mixer = 1;
+ inform("The alsa backend -t option is deprecated and has been ignored. FYI, using the -c option automatically chooses a hardware mixer.");
break;
+
case 'm':
alsa_mix_dev = optarg;
break;
case 'c':
alsa_mix_ctrl = optarg;
+ hardware_mixer = 1;
break;
case 'i':
alsa_mix_index = strtol(optarg, NULL, 10);
diff --git a/audio_pipe.c b/audio_pipe.c
index 210f99f9..d38cd8f8 100644
--- a/audio_pipe.c
+++ b/audio_pipe.c
@@ -40,24 +40,32 @@ static int fd = -1;
char *pipename = NULL;
static void start(int sample_rate) {
- debug(1, "Pipename to start is \"%s\"", pipename);
- if (strcasecmp(pipename, "STDOUT") == 0)
- fd = STDOUT_FILENO;
- else
- fd = open(pipename, O_WRONLY);
+ // this will leave fd as -1 if a reader hasn't been attached
+ fd = open(pipename, O_WRONLY | O_NONBLOCK);
}
-static void play(short buf[], int samples) { int ignore = write(fd, buf, samples * 4); }
+static void play(short buf[], int samples) {
+ // if the file is not open, try to open it.
+ if (fd == -1) {
+ fd = open(pipename, O_WRONLY | O_NONBLOCK);
+ }
+ // if it's got a reader, write to it.
+ if (fd != -1) {
+ int ignore = non_blocking_write(fd, buf, samples * 4);
+ }
+}
static void stop(void) {
- if (fd != STDOUT_FILENO)
- close(fd);
+// Don't close the pipe just because a play session has stopped.
+// if (fd > 0)
+// close(fd);
}
static int init(int argc, char **argv) {
+ debug(1, "pipe init");
const char *str;
int value;
-
+
config.audio_backend_buffer_desired_length = 44100; // one second.
config.audio_backend_latency_offset = 0;
@@ -67,6 +75,9 @@ static int init(int argc, char **argv) {
if (config_lookup_string(config.cfg, "pipe.name", &str)) {
pipename = (char *)str;
}
+
+ if ((pipename) && (strcasecmp(pipename, "STDOUT") == 0))
+ die("Can't use \"pipe\" backend for STDOUT. Use the \"stdout\" backend instead.");
/* Get the desired buffer size setting. */
if (config_lookup_int(config.cfg, "pipe.audio_backend_buffer_desired_length", &value)) {
@@ -86,29 +97,25 @@ static int init(int argc, char **argv) {
config.audio_backend_latency_offset = value;
}
}
-
+
if ((pipename == NULL) && (argc != 1))
die("bad or missing argument(s) to pipe");
if (argc == 1)
pipename = strdup(argv[0]);
-
+
+
// here, create the pipe
- if (strcasecmp(pipename, "STDOUT") != 0)
- if (mkfifo(pipename, 0644) && errno != EEXIST)
- die("Could not create output pipe \"%s\"", pipename);
+ if (mkfifo(pipename, 0644) && errno != EEXIST)
+ die("Could not create output pipe \"%s\"", pipename);
debug(1, "Pipename is \"%s\"", pipename);
- // test open pipe so we error on startup if it's going to fail
- start(44100);
- stop();
-
return 0;
}
static void deinit(void) {
- if ((fd > 0) && (fd != STDOUT_FILENO))
+ if (fd > 0)
close(fd);
}
diff --git a/common.c b/common.c
index 83837437..bb6dafa2 100644
--- a/common.c
+++ b/common.c
@@ -33,6 +33,8 @@
#include shairport-sync plays audio streamed from iTunes or from an AirPlay
- device to an audio device connected via an audio back end. At present,
- the only fully-implemented back end is for ALSA.
A feature of shairport-sync is that the audio is played synchronously. This means that if many devices are playing the same stream at the same @@ -74,11 +74,312 @@ This allows multiple devices play the same source without getting out of phase with one another, enabling, for example, simultaneous multi-room operation.
- + +shairport-sync can additionally be compiled and configured to stream raw audio to a pipe or to stdout.
+ +Settings can be made using the configuration file (recommended for all new installations) or by using command-line options.
+ + +You should use the configuration file for setting up shairport-sync.
+ This file is normally
Settings are organised into groups, for example, there is a "general" group of + standard settings, and there is an "alsa" group with settings that pertain to the ALSA + back end. Here is an example of a typical configuration file:
+ +Most settings have sensible default values, so -- as in the example above -- users generally only need to set (1) the service name, (2) a password (if desired) and + (3) the output device. If the output device has a mixer that can be used for volume control, then (4) the volume control's name should be specificed. It is highly desirable to use the output device's mixer for volume control, if available -- response time is reduced to zero and the processor load is reduced. In the example above, "soxr" interpolation was also enabled.
+ +A sample configuration file with all possible settings, but with all of them commented out, is installed at
To retain backwards compatability with previous versions of shairport-sync + you can use still use command line options, but any new features, etc. will + be available only via configuration file settings.
+ +The configuration file is processed using the
These are the settings available within the
There are four default latency settings, chosen automatically. One latency matches the latency used by recent versions of iTunes when playing audio and another matches the latency used by so-called "AirPlay" devices, including iOS devices and iTunes and Quicktime Player when they are playing video. A third latency is used when the audio source is forked-daapd. The fourth latency is the default if no other latency is chosen and is used for older versions of iTunes.
+If you want to change latencies to compensate for a delay in the audio output device (which will have the same effect on all sources), instead of changing these individual latencies, consider using the
shairport-sync can process metadata provided by the source, such as Track Number, Album Name, cover art, etc. and can provide additional metadata such as volume level,
+ pause/resume, etc. It provides the metadata to a pipe, by default
The
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.
+ + + + + + + + + +These settings are for the ALSA back end, used to communicate with audio output devices in the ALSA system.
+ (By the way, you can use tools such as
These settings are for the PIPE backend, used to route audio to a named unix pipe. The audio is in raw CD audio format: PCM 16 bit little endian, 44,100 samples per second, + stereo.
+Use the
There are two further settings affecting timing that might be useful if the pipe reader is, for example,
+ a program to play an audio stream such as
These are the settings available within the
These settings are for the STDOUT backend, used to route audio to standard output ("stdout"). + The audio is in raw CD audio format: PCM 16 bit little endian, 44,100 samples per second, stereo.
+There are two settings affecting timing that might be useful if the stdout reader is, for example,
+ a program to play an audio stream such as
These are the settings available within the
Note: if you are setting up shairport-sync for the first time or are updating an existing installation, + you are encouraged to use the configuration file settings described above. Most of the options described below + simply replicate the configuration settings and are retained to provide backward compatability with older installations of shairport-sync.
+Many of the options take sensible default values, so you can normally ignore most of them. See the EXAMPLES section for typical usages.
@@ -122,6 +423,13 @@ + +The program will run in daemon mode (
The example above is slightly contrived in order to show the use of the
shairport-sync plays audio streamed from iTunes or from an AirPlay - device to an audio device connected via an audio back end. At present, - the only fully-implemented back end is for ALSA.
+ device to an ALSA-compatible audio output device.A feature of shairport-sync is that the audio is played synchronously. This means that if many devices are playing the same stream at the same @@ -54,13 +54,316 @@ This allows multiple devices play the same source without getting out of phase with one another, enabling, for example, simultaneous multi-room operation.
+ +shairport-sync can additionally be compiled and configured to stream raw audio to a pipe or to stdout.
+ +Settings can be made using the configuration file (recommended for all new installations) or by using command-line options.
+ + +You should use the configuration file for setting up shairport-sync. + This file is normally /etc/shairport-sync.conf. + You may need to have root privileges to modify it.
+ +Settings are organised into groups, for example, there is a "general" group of + standard settings, and there is an "alsa" group with settings that pertain to the ALSA + back end. Here is an example of a typical configuration file:
+ +general = {
+name = "Mike's Boombox";
+interpolation = "soxr";
+password = "secret";
+};
++
alsa = {
+output_device = "hw:0";
+mixer_control_name = "PCM";
+};
+ +Most settings have sensible default values, so -- as in the example above -- users generally only need to set (1) the service name, (2) a password (if desired) and + (3) the output device. If the output device has a mixer that can be used for volume control, then (4) the volume control's name should be specificed. It is highly desirable to use the output device's mixer for volume control, if available -- response time is reduced to zero and the processor load is reduced. In the example above, "soxr" interpolation was also enabled.
+ +A sample configuration file with all possible settings, but with all of them commented out, is installed at /etc/shairport-sync.conf.sample.
+ +To retain backwards compatability with previous versions of shairport-sync + you can use still use command line options, but any new features, etc. will + be available only via configuration file settings.
+ +The configuration file is processed using the libconfig library + -- see http://www.hyperrealm.com/libconfig/libconfig_manual.html.
+ +"GENERAL" SETTINGS
+These are the settings available within the general group:
+ + +name="service_name";
+ + Use this service_name to identify this player in iTunes, etc. + The default name is "Shairport Sync on <hostname>". + + + + +password="password";
+ Require the password password to connect to the service. If you leave this setting commented out, no password is needed. + + +interpolation="mode";
+ Interpolate, or "stuff", the audio stream using the mode. Interpolation here refers to the + process of adding or removing frames of audio to or from the + stream sent to the output device to keep it exactly in synchrony + with the player. + The default mode, "basic", is normally almost completely inaudible. + The alternative mode, "soxr", is even less obtrusive but + requires much more processing power. For this mode, support for + libsoxr, the SoX Resampler Library, must be selected when + shairport-sync is compiled. + + + + +statistics="setting";
+ Use this setting to enable ("yes") or disable ("no") the output of some statistical information on the console or in the log. The default is to disable statistics. + + + +mdns_backend="backend";
+ shairport-sync has a number of modules of code ("backends") for interacting with the mDNS service to be used to advertise itself. Normally, the first mDNS backend that works is selected. This setting forces the selection of the specific mDNS backend. The default is "avahi". Perform the command shairport-sync -h to get a list of available mDNS modules. + + +output_backend="backend";
+ shairport-sync has a number of modules of code ("backends") through which audio is output. Normally, the first audio backend that works is selected. This setting forces the selection of the specific audio backend. The default is "alsa". Perform the command shairport-sync -h to get a list of available audio backends. Only the alsa backend supports synchronisation. + + +port=portnumber;
+ Use this to specify the portnumber shairport-sync uses to listen for service requests from iTunes, etc. The default is port 5000. + + +udp_port_base=portnumber;
+ When shairport-sync starts to play audio, it establises three UDP connections to the audio source. Use this setting to specify the starting portnumber for these three ports. It will pick the first three unused ports starting from portnumber. The default is port 6001. + + +udp_port_range=range;
+ Use this in conjunction with the prevous setting to specify the range of ports that can be checked for availability. Only three ports are needed. The default is 100, thus 100 ports will be checked from port 6001 upwards until three are found. + + +drift=frames;
+ Allow playback to drift up to frames out of exact synchronization before attempting to correct it. + The default is 88 frames, i.e. 2 ms. The smaller the tolerance, the more likely it is that overcorrection will occur. + Overcorrection is when more corrections (insertions and deletions) are made than are strictly necessary to keep the stream in sync. Use the statistics setting to + monitor correction levels. Corrections should not greatly exceed net corrections. + + + +resync_threshold=threshold;
+ Resynchronise if timings differ by more than threshold frames. + If the output timing differs from the source timing by more than + the threshold, output will be muted and a full resynchronisation + will occur. The default threshold is 2,205 frames, i.e. 50 + milliseconds. Specify 0 to disable resynchronisation. + + +log_verbosity=0;
+ Use this to specify how much debugging information should be output or logged. "0" means no debug information, "3" means most debug information. The default is "0". + + +ignore_volume_control="choice";
+ Set this choice to "yes" if you want the volume to be at 100% no matter what the source's volume control is set to. This might be useful if you want to set the volume on the output device, independently of the setting at the source. The default is "no". + + +"LATENCIES" SETTINGS
+There are four default latency settings, chosen automatically. One latency matches the latency used by recent versions of iTunes when playing audio and another matches the latency used by so-called "AirPlay" devices, including iOS devices and iTunes and Quicktime Player when they are playing video. A third latency is used when the audio source is forked-daapd. The fourth latency is the default if no other latency is chosen and is used for older versions of iTunes.
+If you want to change latencies to compensate for a delay in the audio output device (which will have the same effect on all sources), instead of changing these individual latencies, consider using the audio_backend_latency_offset setting in the alsa group (or the appropriate other group if you're not outputing through the alsa backend).
+ + + +itunes=latency;
+ This is the latency, in frames, used for iTunes 10 or later. Default is 99,400. + + +airplay=latency;
+ This is the latency, in frames, used for AirPlay devices, including iOS devices and iTunes and Quicktime Player when they are playing video. Default is 88,200. + + +forkedDaapd=latency;
+ This is the latency, in frames, used for forkedDaapd sources. Default is 99,400. + + +default=latency;
+ This is the latency, in frames, used when the source is unrecognised. Default is 88,200. + + +"METADATA" SETTINGS
+shairport-sync can process metadata provided by the source, such as Track Number, Album Name, cover art, etc. and can provide additional metadata such as volume level, + pause/resume, etc. It provides the metadata to a pipe, by default /tmp/shairport-sync-metadata. + To process metadata, shairport-sync must have been compiled with metadata support included. + You can check that this is so by running shairport-sync -V; the identification string will contain the word metadata.
+The metadata group of settings allow you to enable metadata handling and to control certain aspects of it:
+ + + +enabled="choice";
+ Set the choice to "yes" to enable shairport-sync to look for metadata from the audio source and to forward it, + along with metadata generated by shairport-sync itself, to the metadata pipe. The default is "no". + + +include_cover_art="choice";
+ Set the choice to "yes" to enable shairport-sync to look for cover art from the audio source and to include it in the feed to the metadata pipe. + You must also enable metadata (see above). + One reason for not including cover art is that the images can sometimes be very large and may delay transmission of subsequent metadata through the pipe. + The default is "no". + + +pipe_name="filepathname";
+ Specify the absolute path name of the pipe through which metadata should be sent The default is /tmp/shairport-sync-metadata". + + +"SESSIONCONTROL" SETTINGS
+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.
+ + + +run_this_before_play_begins="/path/to/application and args";
+ Here you can specify a program and its arguments that will be run just before a play session begins. Be careful to include the full path to the application. + The application must be marked as executable and, if it is a script, its first line must begin with the standard #!/bin/... as appropriate. + + +run_this_after_play_ends="/path/to/application and args";
+ Here you can specify a program and its arguments that will be run just after a play session ends. Be careful to include the full path to the application. + The application must be marked as executable and, if it is a script, its first line must begin with the standard #!/bin/... as appropriate. + + +wait_for_completion="choice";
+ Set choice to "yes" to make shairport-sync wait until the programs specified in the run_this_before_play_begins + and run_this_after_play_ends have completed execution before continuing. The default is "no". + + +allow_session_interruption="choice";
+ If choice is set to "yes", then another source will be able to interrupt an existing play session and start a new one. + When set to "no" (the default), other devices attempting to interrupt a session will fail, receiving a busy signal. + + +session_timeout=seconds;
+ If a play session has been established and the source disappears without warning (such as a device going out of range of a network) + then wait for seconds seconds before ending the session. Once the session has terminated, other devices can use it. + The default is 120 seconds. + + +"ALSA" SETTINGS
+These settings are for the ALSA back end, used to communicate with audio output devices in the ALSA system. + (By the way, you can use tools such as alsamixer or aplay to discover what devices are available.) + Use these settings to select the output device and the mixer control to be used to control the output volume. + You can additionally set the desired size of the output buffer and you can adjust overall latency. Here are the alsa group settings:
+ + +output_device="output_device";
+ Use the output device called output_device. The default is the device called "default". + + + +mixer_control_name="name";
+ Specify the name of the mixer control to be used by shairport-sync to control the volume. + The mixer control must be on the mixer device, which by default is the output device. + If you do not specify a mixer control name, shairport-sync will adjust the volume in software. + +mixer_type="mixer_type";
+ This setting is deprecated and will be removed soon. If you wish to use a mixer control to control the volume, then set mixer_type to "hardware". + The default is "software". + + +mixer_device="mixer_device";
+ By default, the mixer is assumed to be output_device. Use this setting to specify a device other than the output device. + + +audio_backend_latency_offset=offset;
+ Set this offset, in frames, to compensate for a fixed delay in the audio back end. + For example, if the output device delays by 100 ms, set this to -4410. + + +audio_backend_buffer_desired_length=length;
+ Use this to set the desired number frames to be in the output device's hardware output buffer. + The default is 6,615 frames, or 0.15 seconds. If set too small, buffer underflow may occur on low-powered machines. + If too large, the response times when using software volume control (i.e. when not using a mixer control to control volume) become annoying, + or it may exceed the hardware buffer size. + It may need to be larger on low-powered machines that are also performing other tasks, such as processing metadata. + + +"PIPE" SETTINGS
+These settings are for the PIPE backend, used to route audio to a named unix pipe. The audio is in raw CD audio format: PCM 16 bit little endian, 44,100 samples per second, + stereo.
+Use the name setting to set the name and location of the pipe.
+There are two further settings affecting timing that might be useful if the pipe reader is, for example, + a program to play an audio stream such as aplay. The audio_backend_latency_offset affects precisely when the first audio packet is sent + and the audio_backend_buffer_desired_length setting affects the nominal output buffer size.
+These are the settings available within the pipe group:
+ + +name="/path/to/pipe";
+ Use this to specify the name and location of the pipe. The pipe will be created and opened when shairport-sync starts up and will be closed upon shutdown. + Frames of audio will be sent to the pipe in packets of 352 frames and will be discarded if the pipe has not have a reader attached. + The sender will wait for up to five seconds for a packet to be written before discarding it. + + + +audio_backend_latency_offset=offset_in_frames;
+ + Packets of audio frames are written to the pipe synchronously -- that is, they are written to at exactly the time they should be played. + You can offset the time of initial audio output relative to its nominal time using this setting. + For example to send an audio stream to the pipe 100 milliseconds before it is due to be played, set this to -4410. Default setting is 0. + + + +audio_backend_buffer_desired_length=buffer_length_in_frames;
+ + Use this setting, in frames, to set the size of the output buffer. It works by determining how soon the second and subsequent packets of audio frames are sent to the pipe. + For example, if you send the first packet of audio exactly when it is due and, using a audio_backend_buffer_desired_length setting of 44100, + send subsequent packets of audio a second before they are due to be played, they will be buffered in the pipe reader's buffer, giving it a nominal buffer size of 44,100 frames. + Note that if the pipe reader consumes audio packets faster or slower than they are supplied, the buffer will eventually empty or overflow -- + shairport-sync performs no stuffing or interpolation when writing to a pipe. Default setting is 44,100 frames. + + + +"STDOUT" SETTINGS
+These settings are for the STDOUT backend, used to route audio to standard output ("stdout"). + The audio is in raw CD audio format: PCM 16 bit little endian, 44,100 samples per second, stereo.
+There are two settings affecting timing that might be useful if the stdout reader is, for example, + a program to play an audio stream such as aplay. The audio_backend_latency_offset affects precisely when the first audio packet is sent + and the audio_backend_buffer_desired_length setting affects the nominal output buffer size.
+These are the settings available within the stdout group:
+ + +audio_backend_latency_offset=offset_in_frames;
+ + Packets of audio frames are written to stdout synchronously -- that is, they are written at exactly the time they should be played. + You can offset the time of initial audio output relative to its nominal time using this setting. + For example to send an audio stream to stdout 100 milliseconds before it is due to be played, set this to -4410. Default setting is 0. + + + +audio_backend_buffer_desired_length=buffer_length_in_frames;
+ + Use this setting, in frames, to set the size of the output buffer. It works by determining how soon the second and subsequent packets of audio frames are sent to stdout. + For example, if you send the first packet of audio exactly when it is due and, using a audio_backend_buffer_desired_length setting of 44100, + send subsequent packets of audio a second before they are due to be played, they will be buffered in the stdout reader's buffer, giving it a nominal buffer size of 44,100 frames. + Note that if the stdout reader consumes audio packets faster or slower than they are supplied, the buffer will eventually empty or overflow -- + shairport-sync performs no stuffing or interpolation when writing to stdout. Default setting is 44,100 frames. + + + +Note: if you are setting up shairport-sync for the first time or are updating an existing installation, + you are encouraged to use the configuration file settings described above. Most of the options described below + simply replicate the configuration settings and are retained to provide backward compatability with older installations of shairport-sync.
+Many of the options take sensible default values, so you can normally ignore most of them. See the EXAMPLES section for typical usages.
@@ -107,6 +410,13 @@ +-c filename | --configfile=filename
++ Read configuration settings from filename. The default is to read them from /etc/shairport-sync.conf. For information about configuration settings, see the "Configuration File Settings" section above. +
+ + +-D | --disconnectFromOutput
Disconnect the shairport-sync daemon from the output device and @@ -198,7 +508,7 @@ Listen for metadata coming from the source and send it, along with metadata from shairport-sync itself, to a pipe called shairport-sync-metadata in the directory you specify. If you add the --get-cover-art then - cover art will be sent through the pipe too. See https://github.com/mikebrady/shairport-sync-metadata-reader + cover art will be sent through the pipe too. See https://github.com/mikebrady/shairport-sync-metadata-reader for a sample metadata reader.
@@ -384,11 +694,8 @@-t devicetype
- The type of the output device is devicetype which must be - hardware or software. The default is software. - If you specify hardware you must also specify the output device using the - -d option and the name of the volume control using the -c option. - You may also need to specify the mixer using the -m option. + This option is deprecated and is ignored. For your information, its functionality has been automatically incorporated in the -c option + -- if you specify a mixer name with the -c option, it is assumed that the mixer is implemented in hardware.
@@ -402,7 +709,6 @@ -- -d hw:1,0 -m hw:1 - -t hardware -c PCMThe example above is slightly contrived in order to show the use of the -m option.
@@ -424,7 +729,6 @@
-S soxr
--
-d hw:1
- -t hardware
-c PCM
diff --git a/player.c b/player.c
index 522b6fa4..425bc879 100644
--- a/player.c
+++ b/player.c
@@ -130,7 +130,7 @@ static pthread_mutex_t ab_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t flush_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t flowcontrol;
-static int64_t first_packet_time_to_play; // nanoseconds
+static int64_t first_packet_time_to_play, time_since_play_started; // nanoseconds
static audio_parameters audio_information;
@@ -441,6 +441,7 @@ static abuf_t *buffer_get_frame(void) {
ab_resync();
first_packet_timestamp = 0;
first_packet_time_to_play = 0;
+ time_since_play_started = 0;
flush_requested = 0;
}
pthread_mutex_unlock(&flush_mutex);
@@ -502,8 +503,7 @@ static abuf_t *buffer_get_frame(void) {
// Here, calculate when we should start playing. We need to know when to allow the
// packets to be sent to the player.
// We will send packets of silence from now until that time and then we will send the
- // first packet,
- // which will be followed by the subsequent packets.
+ // first packet, which will be followed by the subsequent packets.
// we will get a fix every second or so, which will be stored as a pair consisting of
// the time when the packet with a particular timestamp should be played, neglecting
@@ -513,9 +513,8 @@ static abuf_t *buffer_get_frame(void) {
// to do some calculations.
// To calculate when the first packet will be played, we figure out the exact time the
- // packet should
- // be played according to its timestamp and the reference time. We then need to add
- // the desired latency, typically 88200 frames.
+ // packet should be played according to its timestamp and the reference time.
+ // We then need to add the desired latency, typically 88200 frames.
// Then we need to offset this by the backend latency offset. For example, if we knew
// that the audio back end has a latency of 100 ms, we would
@@ -559,6 +558,7 @@ static abuf_t *buffer_get_frame(void) {
ab_resync();
first_packet_timestamp = 0;
first_packet_time_to_play = 0;
+ time_since_play_started = 0;
} else {
if (config.output->delay) {
dac_delay = config.output->delay();
@@ -663,7 +663,7 @@ static abuf_t *buffer_get_frame(void) {
time_to_wait_for_wakeup_fp *= 4 * 352; // four full 352-frame packets
time_to_wait_for_wakeup_fp /= 3; // four thirds of a packet time
-#ifdef COMPILE_FOR_LINUX
+#ifdef COMPILE_FOR_LINUX_AND_FREEBSD
uint64_t time_of_wakeup_fp = local_time_now + time_to_wait_for_wakeup_fp;
uint64_t sec = time_of_wakeup_fp >> 32;
uint64_t nsec = ((time_of_wakeup_fp & 0xffffffff) * 1000000000) >> 32;
@@ -902,8 +902,9 @@ static void *player_thread_func(void *arg) {
missing_packets = late_packets = too_late_packets = resend_requests = 0;
flush_rtp_timestamp = 0; // it seems this number has a special significance -- it seems to be used
// as a null operand, so we'll use it like that too
- int sync_error_out_of_bounds =
- 0; // number of times in a row that there's been a serious sync error
+ int sync_error_out_of_bounds = 0; // number of times in a row that there's been a serious sync error
+
+ uint64_t tens_of_seconds = 0;
while (!please_stop) {
abuf_t *inframe = buffer_get_frame();
if (inframe) {
@@ -1009,12 +1010,23 @@ static void *player_thread_func(void *arg) {
}
// try to keep the corrections definitely below 1 in 1000 audio frames
+
+ // calculate the time elapsed since the play session started.
+
if (amount_to_stuff) {
- uint32_t x = random() % 1000;
- if (x > 352)
- amount_to_stuff = 0;
- }
+ if ((local_time_now) && (first_packet_time_to_play) && (local_time_now >= first_packet_time_to_play)) {
+ int64_t tp = (local_time_now - first_packet_time_to_play)>>32; // seconds
+
+ if (tp<5)
+ amount_to_stuff = 0; // wait at least five seconds
+ else if (tp<30) {
+ if ((random() % 1000) > 352) // keep it to about 1:1000 for the first thirty seconds
+ amount_to_stuff = 0;
+ }
+ }
+ }
+
if ((amount_to_stuff == 0) && (fix_volume == 0x10000)) {
// if no stuffing needed and no volume adjustment, then
// don't send to stuff_buffer_* and don't copy to outbuf; just send directly to the
@@ -1268,7 +1280,7 @@ int player_play(stream_cfg *stream) {
#endif
// set the flowcontrol condition variable to wait on a monotonic clock
-#ifdef COMPILE_FOR_LINUX
+#ifdef COMPILE_FOR_LINUX_AND_FREEBSD
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); // can't do this in OS X, and don't need it.
@@ -1280,7 +1292,7 @@ int player_play(stream_cfg *stream) {
if (rc)
debug(1, "Error initialising condition variable.");
config.output->start(sampling_rate);
- size_t size = (PTHREAD_STACK_MIN + 128 * 1024);
+ size_t size = (PTHREAD_STACK_MIN + 256 * 1024);
pthread_attr_t tattr;
pthread_attr_init(&tattr);
rc = pthread_attr_setstacksize(&tattr, size);
diff --git a/rtsp.c b/rtsp.c
index 1a81b98f..9340dbfb 100644
--- a/rtsp.c
+++ b/rtsp.c
@@ -922,30 +922,6 @@ static void metadata_close(void) {
fd = -1;
}
-ssize_t non_blocking_write(int fd, const void *buf, size_t count) {
- // debug(1,"writing %u to pipe...",count);
- // we are assuming that the count is always smaller than the FIFO's buffer
- struct pollfd ufds[1];
- ssize_t reply;
- do {
- ufds[0].fd = fd;
- ufds[0].events = POLLOUT;
- int rv = poll(ufds, 1, 5000);
- if (rv == -1)
- debug(1, "error waiting for pipe to unblock...");
- if (rv == 0)
- debug(1, "timeout waiting for pipe to unblock");
- reply = write(fd, buf, count);
- if ((reply == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
- debug(1, "writing to pipe will block...");
- // else
- // debug(1,"writing %u to pipe done...",reply);
- } while ((reply == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)));
- return reply;
-
- // return write(fd,buf,count);
-}
-
void metadata_process(uint32_t type, uint32_t code, char *data, uint32_t length) {
debug(2, "Process metadata with type %x, code %x and length %u.", type, code, length);
int ret;
diff --git a/scripts/shairport-sync.conf b/scripts/shairport-sync.conf
index 3bfcde5b..b2ac51a5 100644
--- a/scripts/shairport-sync.conf
+++ b/scripts/shairport-sync.conf
@@ -5,74 +5,73 @@
general =
{
// name = "Shairport Sync Player"; // This is the name the service will advertise to iTunes. The default is "Shairport Sync on