Ninja Nichols

The discipline of programming

Controlling Banshee and RadioTray via DBus

I recently began using OpenBox as my window manager in Linux. One issue I ran into was that my media players were unable to automatically bind to the global media hotkeys. My solution was to write a little bash script to control the media players using DBus. Right now I have support for Banshee and RadioTray. VLC support should be fairly easy to add, but I haven’t had the motivation to search for documentation on their DBus interface.

#!/usr/bin/env bash
#
# Controls playback on any running media players.
#
# usage: media-controller <command>
#
# Command:
#   play
#   pause
#   stop
#   next
#   previous
#
# Supported commands by player:
#   banshee
#       play
#       pause
#       stop
#       next
#       previous
#
#   radiotray
#       play
#       pause
#       stop

if [ ! $# -eq 1 ]; then
    ech o "usage: media-controller <command>"
    exit
fi

COMMAND=$1

BANSHEE_PID=`pgrep -x "banshee"`
RADIO_TRAY_PID=`pgrep -x "radiotray"`

if [ $BANSHEE_PID ]; then
    case $COMMAND in
        play)
            dbus-send --session --type="method_call" 
               --dest='org.bansheeproject.Banshee' 
               '/org/bansheeproject/Banshee/PlayerEngine' 
               'org.bansheeproject.Banshee.PlayerEngine.TogglePlaying'
            ;;
        pause)
            dbus-send --session --type="method_call" 
               --dest='org.bansheeproject.Banshee' 
               '/org/bansheeproject/Banshee/PlayerEngine' 
               'org.bansheeproject.Banshee.PlayerEngine.Pause'
            ;;
        stop)
            dbus-send --session --type="method_call" 
               --dest='org.bansheeproject.Banshee' 
               '/org/bansheeproject/Banshee/PlayerEngine' 
               'org.bansheeproject.Banshee.PlayerEngine.Close'
            ;;
        next)
            dbus-send --session --type="method_call" 
                --dest='org.bansheeproject.Banshee' 
                '/org/bansheeproject/Banshee/PlaybackController' 
                'org.bansheeproject.Banshee.PlaybackController.Next' 
                'boolean:false'
            ;;
        previous)
            dbus-send --session --type="method_call" 
                --dest='org.bansheeproject.Banshee' 
                '/org/bansheeproject/Banshee/PlaybackController' 
                'org.bansheeproject.Banshee.PlaybackController.Previous' 
                'boolean:false'
            ;;
        *)
            ech o "Command not supported for this player"
            ;;
    esac
fi
if [ $RADIO_TRAY_PID ]; then
    case $COMMAND in
        play)
            STATUS=`dbus-send --print-reply --session --type="method_call" 
                --dest='net.sourceforge.radiotray' 
                '/net/sourceforge/radiotray' 
                'net.sourceforge.radiotray.getCurrentRadio'`

            CURRENT_SONG=`ech o '$STATUS' | sed 's/.*"(.*)"[^"]*$/1/'`

            dbus-send --session --type="method_call" 
                --dest='net.sourceforge.radiotray' 
                '/net/sourceforge/radiotray' 
                'net.sourceforge.radiotray.playRadio' 
                'string:'$CURRENT_SONG
            ;;
        pause)
            dbus-send --session --type="method_call" 
                --dest='net.sourceforge.radiotray' 
                '/net/sourceforge/radiotray' 
                'net.sourceforge.radiotray.turnOff'
            ;;
        stop)
            dbus-send --session --type="method_call" 
                --dest='net.sourceforge.radiotray' 
                '/net/sourceforge/radiotray' 
                'net.sourceforge.radiotray.turnOff'
            ;;
        *)
            ech o "Command not supported for this player"
            ;;
    esac
fi

Actually getting the desired effect from the media keys required adding the following XML to my ~/.config/openbox/rc.xml file:

    <keybind key="XF86AudioNext">
      <action name="Execute">
        <command>media-controller next</command>
      </action>
    </keybind>
    <keybind key="XF86AudioPlay">
      <action name="Execute">
        <command>media-controller play</command>
      </action>
    </keybind>
    <keybind key="XF86AudioPrev">
      <action name="Execute">
        <command>media-controller previous</command>
      </action>
    </keybind>
    <keybind key="XF86AudioStop">
      <action name="Execute">
        <command>media-controller stop</command>
      </action>
    </keybind>
    <keybind key="XF86AudioPause">
      <action name="Execute">
        <command>media-controller pause</command>
      </action>
    </keybind>