Closed JulianWAS closed 5 years ago
Thanks for the post. Yes, Shairport Sync has an optional D-Bus interface (and an MQTT interface too).
If the streaming source permits a basic level of remote control (and the iPad does) you can send a D-Bus command to Shairport Sync which will be relayed to the source. You can, for example, pause/resume, raise/lower volume.
The first step is to include D-Bus support with --with-dbus-interface
at the configuration step. Then you can explore the D-Bus interface with, e.g. dfeet
.
[Update] You need to fully install Shairport Sync for the D-Bus interface to be enabled on the D-Bus system bus.
You may wish to take a look at the sample commands here. One of them – "# Play using regular Remote Control"
is close to what you are suggesting; just use the commands Pause
to stop and Play
to start again. Alternatively, the command PlayPause
can be use to toggle play on and off. BTW, not all commands are available on all remote devices; for instance, Resume
may not be available.
I have two apps that send remote commands if you wanted additional examples. They use MQTT, and require the MQTT remote interface to be enabled in shairport-sync.conf.
One is a webapp that has buttons on webpage that, e.g., can play/pause iTunes, Airfoil, etc. The other uses physical buttons to activate the remote controls on a Character LCD on a Raspberry Pi hat.
They can be found in https://github.com/idcrook/shairport-sync-mqtt-display
@idcrook – they look impressive!
@mikebrady - The DBus pause is exactly what I need, thanks! I recompiled with the appropriate flag and on starting up I get the following error:
Error org.freedesktop.DBus.Error.ServiceUnknown: The name org.gnome.ShairportSync was not provided by any .service files
The application is cross-compiled for an iMX ARM processor so everything's a little hand-tweaked so this might be a install issue. What do you suggest I need to fix this; add something to one of my dbus confs?
Thanks.
Added shairport-sync-dbus-policy.conf to /etc/dbus-1/system.d/ - which fixed the above issue but resulted in: Could not acquire a Shairport Sync native D-Bus interface "org.gnome.ShairportSync.i606" on the system bus.
Bear in mind this is a headless ARM system where most things are root if it's a permissions issue. What's with the i606 on the end of org.gnome.ShairportSync.i606?
Thanks
That's good news! For an application to provide a service on the D-Bus system
bus, there some security involved. On the standard # make install
, a user and group called shairport-sync
are created, if necessary, and the application shairport-sync
is set up to launch under user shairport-sync
. Then, a D-Bus policy file called shairport-sync-dbus-policy.conf
is also installed, usually into /etc/dbus-1/system.d
, to give the appropriate permission to the user shairport-sync
to provide the service org.gnome.ShairportSync
. It might be worth looking at the last part (line 162 onwards) of the Makefile.am for more info.
The policy doc requires the provider to be the user shairport-sync
, so maybe change that to root
.
The i606 is made up from the process number in case there is the possibility of a name clash. It's in the guidelines somewhere.
Hi, Changing the conf to root cleared up all the starting DBus problems. The next issue is purely one of no response to the DBus pause command.
Attached is a file containing the response of the pause command and a dump from DBUS Introspect. Pause, play etc all come up as methods but issuing any command has no effect on the iPad whatsoever.
ShairportSync-DBus-Pause-Dump.txt
Shairport-sync-3.2.2 Kernel 4.9.88 DBus 1.10.20
Thanks again
Thanks. Just looking at this now on my own system and it seems as if something has changed at the client end. I'll take a look at it now.
I just updated the iPad to 13.1.3 and it's all working! It was quite a few updates behind as I'm always a bit reluctant to update if everything works on it.... play, pause, volume now are good. Stop doesn't, work but I'm not going to need it at the moment.
Interesting that you've found an inconsistency though..
Thanks again,
Yeah, I'm worried about something there. Glad it's working for you though.
I'll keep an eye on this ticket if any updates are available. Cheers.
Thanks. I'm afraid I have to leave it now until tomorrow...
It turns out that the new Music app on the Mac – the one replacing iTunes – doesn't offer any the iTunes remote control facilities. I guess this is hardly a surprise.
However, if you direct the System Output to a Shairport Sync device, you still have limited commands, including Pause
.
Functionality from iOS is unchanged.
Quick question before closing this ticket, can I "catch" incoming Shairport-Sync DBus signals like a volume change "from" the iPad? The iPad can of course adjust the volume on my headless Shairport-Sync platform so are these volume changes passed onto to DBus internally?
Below is a section of how I monitor Bluez volume changes in Python, if Shairport-sync volume changes are passed onto to DBus I imagine it's just a few path changes - in principle..? Bluez is fairly layered and complex, if I can pick up Shairport-Sync volume signals do you have the DBus paths/properties handy?
def device_property_changed_cb(property_name, value, path, interface, device_path): global bus if property_name != BLUEZ_DEV: return
device = dbus.Interface(bus.get_object("org.bluez", device_path), "org.freedesktop.DBus.Properties")
properties = device.GetAll(BLUEZ_DEV)
print("Getting dbus interface for device: %s interface: %s property_name: %s" % (device_path, interface, property_name))
vol = properties["Volume"]
volume_percentage = format(vol / 1.27, '.2f')
Cheers.
Thanks for the suggestion. I can't believe that I didn't think of providing this volume control information! I'll try to incorporate it over the next few days.
Actually, AirPlay volume control information is provided (whew!) in the RemoteControl interface. This is from the shairport-sync-dbus-test
program:
...
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -16.0
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -14.0
...
Great! Interestingly though I can send to the iPad via DBus as you've instructed but monitoring DBus I see nothing from Shairport-Sync on DBus locally ( incoming ). If I use dbus-monitor --system there's nothing from Shairport whatsoever i.e. pause iPad -> Shairport-Sync pauses -> local DBus = nothing. Is this expected?
Hmm, not sure if that isn't a problem with dbus-monitor
, which I never really figured out.
The shairport-sync-dbus-test
program monitors the bus (the system bus by default) to get information about Shairport Sync.
OK I'll give it a burst. I think that wraps this question up really. Appreciate your advice. Thanks.
Instead of org.gnome.ShairportSync.RemoteControl.VolumeDown, can I use the AdvancedRemoteControl interface ( below ) to pass a volume value directly to my iPad? If so what would the end of the DBus string look like ( ie. org.gnome.ShairportSync.AdvancedRemoteControl ...........?
org.gnome.ShairportSync.AdvancedRemoteControl.SetVolume int32:50 According to https://github.com/mikebrady/shairport- sync/blob/master/documents/sample%20dbus%20commands doesn't appear to do anything
interface name="org.gnome.ShairportSync.AdvancedRemoteControl" method name="SetVolume" arg type="i" name="volume" direction="in" method property type="b" name="Available" access="read" property type="s" name="PlaybackStatus" access="read" property type="b" name="Shuffle" access="readwrite" property type="s" name="LoopStatus" access="readwrite" property type="i" name="Volume" access="read" interface
Thanks.
Unfortunately, the answers is “no”. iOS devices don’t offer the features that the advanced remote control interface depends on, so it never goes active. The only client that it works with is iTunes, and that is now gone/deprecated, replaced by the Music app, which offers no remote control whatever.
Understood, thank you.
Hi, regarding all the conversation above, I OK with VolumeUp/Down to the iPad :)
My attention now is what's outputted to local DBus from ShairportSync i.e. to "capture" play/pause/volume changes. I not sure if this information is truly available. Perhaps I'm missing a flag or something ( have included ----with-dbus-interface whist building ) ?
I tried "shairport-sync-dbus-test" and a number of other bus monitoring applications ( python etc ) and I get absolutely no local DBus information form ShairportSync with exception of the initial connect. I understand your comment above about a possible bug in dbus-monitor hence trying lots of other apps/code. Looking at the DBus introspection for ShairportSync is seems a little lean on "signals" but I'm certainly no DBus expert. My DBus is 1.10.20, have you any python examples that simply output Shairport signals like volume/play/pause?
I'd like to use this information to drive a local LCD display etc.
Apologies about dragging this mater on.... appreciate your patience!
No apologies needed – this is very interesting and may help to clarify the issue for others.
So, I have just run an experiment on a Raspberry Pi Zero and an iPhone Xs Max running iOS 13.1.3 and using its Music app. Here is some output from shairport-sync-dbus-test-client
running on the Pi Zero. The metadata
section of the /etc/shairport-sync.conf
file is all defaults.
pi@zeropi:~/shairport-sync $ shairport-sync -V
3.3.3d9-OpenSSL-Avahi-ALSA-soxr-metadata-dbus-sysconfdir:/etc
pi@zeropi:~/shairport-sync $ ./shairport-sync-dbus-test-client
Listening on the D-Bus system bus.
Starting test...
*** Properties Changed:
ShairportSync.RemoteControl.Metadata -> @a{sv} {}
ShairportSync.RemoteControl.Server -> 'fde6:4029:319e:e180:1d46:7fc9:bf39:a33e'
*** Properties Changed:
ShairportSync.Active -> true
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Playing'
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -18.0
*** Properties Changed:
ShairportSync.RemoteControl.Metadata -> {'mpris:artUrl': <'file:///tmp/shairport-sync/.cache/coverart/cover-e672a9bf4d3c83cb506d5d415cb3e0d8.jpg'>}
*** Properties Changed:
ShairportSync.RemoteControl.ProgressString -> '1081171389/1084836999/1101803965'
*** Properties Changed:
ShairportSync.RemoteControl.Metadata -> {'mpris:artUrl': <'file:///tmp/shairport-sync/.cache/coverart/cover-e672a9bf4d3c83cb506d5d415cb3e0d8.jpg'>, 'mpris:trackid': <objectpath '/org/gnome/ShairportSync/mper_685169194'>, 'xesam:title': <'Mozart: Apollo et Hyacinthus, K38 - No 05. Aria: Saepe terrent Numina (Hyacinthus) '>, 'xesam:album': <'Mozart: Apollo et Hyacinthus'>, 'xesam:artist': <['Sophie Bevan; Ian Page: Classical Opera']>, 'xesam:genre': <['Classical']>, 'mpris:length': <int64 467858000>}
*** Properties Changed:
ShairportSync.RemoteControl.Available -> true
*** Properties Changed:
ShairportSync.RemoteControl.ProgressString -> '1081171368/1084846151/1101803944'
*** Properties Changed:
ShairportSync.RemoteControl.ProgressString -> '1082909460/1084885223/1103542036'
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -16.0
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -18.0
Volume up for five seconds...
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -16.0
Volume down
Finished test. Listening for property changes...
*** Properties Changed:
ShairportSync.RemoteControl.AirplayVolume -> -18.0
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Paused'
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Playing'
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Stopped'
*** Properties Changed:
ShairportSync.Active -> false
*** Properties Changed:
ShairportSync.Active -> true
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Playing'
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Paused'
*** Properties Changed:
ShairportSync.RemoteControl.ProgressString -> '1812296259/1812299779/1812296259'
*** Properties Changed:
ShairportSync.RemoteControl.Metadata -> {'mpris:artUrl': <'file:///tmp/shairport-sync/.cache/coverart/cover-e672a9bf4d3c83cb506d5d415cb3e0d8.jpg'>, 'mpris:trackid': <objectpath '/org/gnome/ShairportSync/mper_1313128366'>, 'xesam:title': <'Radio Svizzera Classica'>, 'xesam:album': <'Radio Svizzera Classica'>, 'xesam:artist': <['La radio classica per rilassarsi']>}
*** Properties Changed:
ShairportSync.RemoteControl.ProgressString -> '1812296807/1812301891/1812296807'
*** Properties Changed:
ShairportSync.RemoteControl.PlayerState -> 'Playing'
*** Properties Changed:
ShairportSync.RemoteControl.Metadata -> {'mpris:artUrl': <'file:///tmp/shairport-sync/.cache/coverart/cover-8f0cb63fb3a32e029bdba6b888b2ae91.jpg'>, 'mpris:trackid': <objectpath '/org/gnome/ShairportSync/mper_1313128366'>, 'xesam:title': <'Radio Svizzera Classica'>, 'xesam:album': <'Radio Svizzera Classica'>, 'xesam:artist': <['La radio classica per rilassarsi']>}
*** Properties Changed:
ShairportSync.RemoteControl.ProgressString -> '1812296337/1812313155/1812296337'
...
Hmm.... clearly something different. I enabled --with-metadata, --with-dbus-interface, --with-mpris-interface and build it, ran it and it resulted in below, which I think I got anyway.
I'm running as root in shairport-sync-dbus-policy.conf => policy user="root" and system not session. I can send play, pause and volume over DBus but nothing when monitored so I assume the confs OK. Could this be a system vs session issue? I thought system would give everything..
As there's obvious differences between our Linux builds, DBus versions, compilers etc perhaps something like a bit of Python shared between us could help? I've tried hacking some simple Python of the net to dump out some signals but didn't show anything, but if you were to do it and it worked then I tried it, any exception(s) thrown on my build ( Yocto / iMx7 ) could then provide some useful information.
== with flags enabled ===== This came out on connection only. Play, stop, volume after this yielded nothing.
signal time=1571750128.949492 sender=:1.178 -> destination=(null destination) serial=8 path=/org/gnome/ShairportSync; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged string "org.gnome.ShairportSync.RemoteControl" array [ dict entry( string "Server" variant string "fdaa:bbcc:ddee:0:10a3:c1be:397e:a1e2" ) ] array [ ]
signal time=1571750129.282383 sender=:1.178 -> destination=(null destination) serial=9 path=/org/gnome/ShairportSync; interface=org.freedesktop.DBus.Properties; member=PropertiesChanged string "org.gnome.ShairportSync.RemoteControl" array [ dict entry( string "Metadata" variant array [ ] ) ] array [ ]
Thanks.
I'm not a Python guy, so if you could post some of your Python examples, I might get the hang of it sufficiently to check this out...
Ha, you and me both! I'll look around for the best and easiest example.
Here are two files I use to monitor Bluetooth transport status and volume. If you run them and connect some music via Bluetooth on your RPi you'll see DBus info. Python has it's good points at least one can change a file and save it without recompilation on board. Depending on how much you've used it, don't forget it's all about the indentation ( tabs or spaces ) separating functions and conditional statements etc. I much prefer C but Python has it's good points especially for hacking stuff like this..
Hi,
After discovering
run_this_when_volume_is_set = "/full/path/to/application/and/args"; // Run the specified application whenever the volume control is set or changed. // The desired AirPlay volume is appended to the end of the command line – leave a space if you want it treated as an extra argument. // AirPlay volume goes from 0 to -30 and -144 means "mute".
and run_this_before_play_begins = run_this_after_play_ends =
I think this will suffice for the DBus stuff. Thanks again.
Okay. Good stuff.
Hi,
I'd like to know if it is possible to pause the streaming device? Are there any hooks or commands within shairport-sync that I can use to fire back to the streaming device ( iPad ) to pause it? I have an ARM platform that also uses Bluetooth audio so as one starts to play ( user presses play ) I'd like to pause the other ( from the ARM ). Bluetooth start -> pause Shairport, resume play on Shairport ( user presses play on iPad ) -> pause Bluetooth. The Bluetooth side is all done over DBus, now I just need to send a command to the iPad over whatever protocol/interface Shairport uses to pause the it.
If this can be done, what would be the best method?
Thanks.