Moves speaker selection, volume handling and startup to outputs.c, plus adds
the ability to "resurrect" a speaker that disconnects.
The purpose of moving the code is to concentrate device handling in one place.
Also changes how we deal with speaker selection. The player will now generally
not alter a user selection, even if the device fails. The purpose of this is to
maintain selection both if the device briefly fails, and if the user switches
off the device (we stop playback) and later turns it on + starts new playback.
Instead of using OPTIONS we use SET_PARAMETER with progress metadata to avoid
disconnects from Apple TVs, Homepods and possibly also Airport Expresses.
The player will write 24 bit samples using 3 bytes, not 4, so the appropriate
sample format is SND_PCM_FORMAT_S24_3LE, not SND_PCM_FORMAT_S24_LE.
For extra protection we also use snd_pcm_bytes_to_frames() instead of BTOS(),
because that way we can be more certain that the buffer is not too short for
snd_pcm_writei().
Since it is unknown how to do real sync on Chromecast, this commit instead adds
a primitive delay to the stream, so that it is at least somewhat closer to
Airplay/local audio.
Also some cleanup of unused stuff.
Fixes bugs which were due to incorrect handling of unsigned integer wrap-around:
1. Calling packet_resend() with seqnum + len greater than UINT16_MAX => infinite loop
2. Calling rtp_packet_get() with session->seqnum - seqnum greater than pktbuf_next => wrong packet
* Fix "clicks" during playback, especially on low buffer size devices
Bug had two causes: Trying to write to the prebuf ringbuffer when it was full
and writing new audio to the device without first having drained the prebuf,
thus writing out of order.
* Use snd_pcm_drain() so alsa doesn't report underrun on playback session end
Removes SNDRV_PCM_IOCTL_SYNC_PTR errors
* Fix missing error check of the return value from snd_pcm_avail (now use snd_pcm_avail_delay)
This change is preparation to use ffmpeg's resampling capabilities to keep local
audio in sync (by up/downsampling slightly). This requires that sample rates are
not fixed for a transcode profile.
Added benefit of this is that we don't need quite as many xcode profiles.
In the output implementations playback_stop() was somewhat redundant,
since device_stop() does the same.
The timer should make sure that we always close outputs (previously
they were in some cases kept open).
The commit also includes some renaming.
Player now stops 10 secs after stop command and 10 mins after pause. At
that time the outputs have probably cut the connection themselves, but
that might be ok (needs testing).
outputs_playback_start() had the problem that was not consistently invoked: If
for instance local audio playback was running and a Airplay device was then
activated, the raop's playback_start would never be invoked (and vice versa,
of course).
Instead, the player now writes the presentation timestamp every time to the
output, so it doesn't need to keep track of it from the start.
* Untie Airtunes stuff further from player and non-Airplay outputs
* Change raop.c to use rtp_common.c (step 1)
* Change heartbeat of player to 100 ticks/sec, since we have untied from
Airtunes 352 samples per packet (which equals 126 ticks/sec at 44100)
Still a lot to be done in the player, since the rtptime's in it don't
are probably broken.
Some remotes don't respond as expected to the test. Retune will give connection
refused, because the test is made too quickly, before the service is running.
Even if we delay the test it won't work because Retune crashes.
Since the false mdns advertisements are only seen on Airplay, we only do the
test there.
The unconfigurable resync period of 10 seconds was not frequent
enough to keep my own ALSA device in sync with the AirPlay stream.
Now the period is configurable. The default is still at 10
seconds, to prevent any change in behavior unless opted in by
the user.
Currently the adjustment causes a tiny "click" distortion in the
ALSA output, so it is better to make the check as infrequent as
possible, while still being frequent enough to stay in sync
over lengthy sessions of playback.
Added source_sample_rate, target_sample_rate to alsa_session.
This is a first step toward rendering ALSA at a different
sampling rate than the AirPlay stream, so that (a) we will
be able to dynamically adjust the ALSA sampling rate for an
improved sync algorithm, and (b) later, a more generalized
resampling algorithm can accommodate very different hardware
sampling rates like 22050 Hz or 48000 Hz.
Reworked alsa_session_free() so that it can be used to
tear down a partially initialized alsa_session if an
error occurs in the middle of alsa_session_make().
This simplifies the error handling logic in alsa_session_make().
This refactoring will be helpful later when resampling is added,
because more data structures will be dynamically allocated
during initialization.
Signed-off-by: Don Cross <cosinekitty@gmail.com>
AirPlay 2 devices like Sonos One and AirPort Express with firmware 7.8
require auth-setup before ANNOUNCE, otherwise they will return 403.
Also fixed a problem where metadata did not get sent when toggling
a speaker on/off if we were playing an endless stream.
Implements Active-Remote, which is sent to the speaker, so it can use this
to tell us who it is when it makes dacp request with a device-volume update.
These commands are not used by Remote, but some Airplay speakers are
able to make them (e.g. my Sony STR-DN1040).
Also prepare being able to set the device volume property.
Old Airport Express hangs up if we use GET_PARAMETER (despite announcing support
for it...), and since iTunes seems to use OPTIONS we also do that. We weren't
really using the return value of GET_PARAMETER anyway.
See also comment added to commit d9a67b6dce
Thanks to Denis Denisov and cppcheck for notifying about the below. The leaks
are edge cases, but the warning of dereference of avail in alsa.c points at
a bug that could probably cause actual crashes.
[src/evrtsp/rtsp.c:1352]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
[src/httpd_daap.c:228]: (error) Memory leak: s
[src/library.c:280]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'.
[src/library.c:284]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'.
[src/library/filescanner_playlist.c:251]: (error) Resource leak: fp
[src/library/filescanner_playlist.c:273]: (error) Resource leak: fp
[src/outputs/alsa.c:143]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
[src/outputs/alsa.c:657]: (warning) Possible null pointer dereference: avail
[src/outputs/dummy.c:75]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
[src/outputs/fifo.c:245]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
[src/outputs/raop.c:1806]: (warning) Assignment of function parameter has no effect outside the function. Did you forget dereferencing it?
[src/outputs/raop.c:1371]: (warning) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'signed int'.
[src/outputs/raop.c:1471]: (warning) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'signed int'.
[src/outputs/raop_verification.c:705] -> [src/outputs/raop_verification.c:667]: (warning) Either the condition 'if(len_M)' is redundant or there is possible null pointer dereference: len_M.
- also change how speakers are saved/retrieved from the db
- add generic authorization methods in outputs.c and player.c
- let filescanner read *.verification files (containing PIN)
- configure options to enable and disable, since libsodium is required
Added configure checks needed to detect missing functions on OSX
Added compat clock functions using clock_get_time on OSX
Added compat timer functions using clock_gettime and setitimer on OSX
Added byteswap functions on OSX
- Added custom checks for libraries and pkgconfig modules that test library
presence with additional checks for use of headers and functions with
given options. Also support correct additional feature library checks
using provided flags.
- Added custom enable/disable feature macros to simplify their use.
- Use custom CFLAGS and LIBS variables for Makefiles to simplify maintenance.
- Update many feature checks from platform to function.
- Streamline many function checks.
- Correctly check gnutls, gcrypt and gpg-error libraries.
- Fix chromecast and spotify config and compile on FreeBSD
- Added inotify, signalfd and kqueue, and byte swap checks.
- Many clarifications of error messages.
- Correct json-c checks to properly use supplied CFLAGS.
- Correct many quoting inconsistencies
- Use __DATE__ in place of BUILDDATE
- Use full path for gperf and antlr3
- Remove unnecessary CFLAGS
- Added tests for pthread_setname_np parameters
- Added tests for clock_gettime and timer_settime
- Added tests for time.h
- Test if pthread, dl and rt libs are required/available.
- Updated checks for libunistring
Support a separate mixer_device configuration file option for
advanced ALSA configurations. Previously, ALSA local output
happened to work becasue "default" is valid as both a PCM and a
mixer. Now you can separately specify the device name for PCM
output and mixer operations.
In my setup, I am using the following setup:
card = "default:CARD=NVidia"
mixer = "Front"
mixer_device = "hw:CARD=NVidia"
Requiring the user to set up Pulseaudio in system mode is not optimal. This
would, however, be required especially on headless systems. This is the
sledgehammer alternative to starting Pulseaudio.