Remap "next song" key in ubuntu to work with spotify and wine

Solution 1:

Or jbonney found a pretty neat solution using dbus-send here on his gist

Or if you in a hurry :

"dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause" XF86AudioPlay
"dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Stop" XF86AudioStop
"dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next" XF86AudioNext
"dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous" XF86AudioPrevious

Solution 2:

For Ubuntu, there is now a "Spotify for Linux". For mapping a key combination to "next song", dconf-editor may help (see here). Once a keymapping to "next song" is accomplished, there is a nice Spotify wrapper for media key integration written by John Reese.

EDIT: Spotify for linux now supports media keys.

Solution 3:

The way I do this is to use the following bash script, which I wrote using various commands borrowed from other sources. You're just asking for the "playpause" function, but I figured I might as well include the whole thing. The part you want is:

#!/bin/bash

# Spotify Launch Script by Ben Kraft

# Borrows some commands from Spotify Control by Tommy Matilla:
# http://sites.google.com/site/tommymattila/home/spotifycontrol
# which itself is based on Stuart Colville's
# http://muffinresearch.co.uk/archives/2009/10/22/ubuntu-lock-screen-and-pause-spotify/

# Requires wmctrl and xvkbd

WP="$HOME/.wine"
SPATH="$HOME/.wine/drive_c/Program Files/Spotify/spotify.exe"
TITLE=$(wmctrl -xl | grep -o -e "spotify\.exe\.Wine.*$" | grep -o -e "Spotify.*$")
ACTIVEWIN=$(wmctrl -va ":ACTIVE:" 2>&1 | grep -o -e "0x.*$")

sendkeys () {
    wmctrl -xa "spotify.exe.Wine" || return 1
    xvkbd -q -delay 100 -text "$1"
    wmctrl -ia $ACTIVEWIN
}

if [ -z $TITLE ] ; then
  echo "Spotify is not running!
  exit 1
else
  sendkeys '\ '
fi
exit 0

In short, it uses wmctrl to move to the workspace Spotify is on, uses xvkbd to send a space keystroke to Spotify, then uses wmctrl to move back.

To use it, save it in a file, mark the file executable (in the file permissions dialog), and then use CompizConfig Settings Manager to add it to commands. (Put bash /path/to/script in the first box in the "Commands" tab, then add a key binding in the second tab. This can be whatever key you want to use.) You will need wmctrl and xvkbd installed; search them in Ubuntu Software Center.

The whole script, which gives some other nice features like going to the previous or next track and displaying the title of the song, is below. You use it just like the snippet above, except that you have to put bash /path/to/script --option in the command box, where --option can be any of the things listed in the script.

#!/bin/bash

# Spotify Launch Script by Ben Kraft

# Borrows some commands from Spotify Control by Tommy Matilla:
# http://sites.google.com/site/tommymattila/home/spotifycontrol
# which itself is based on Stuart Colville's
# http://muffinresearch.co.uk/archives/2009/10/22/ubuntu-lock-screen-and-pause-spotify/

# Requires wmctrl and xvkbd
# Usage:
USAGE="
usage: spotify [OPTIONS]

OPTIONS:
--play: Starts Spotify playing if it isn't already
--pause: Pauses Spotify if it isn't already
--playpause: Toggles Spotify between playing and pausing
--prev: Plays the previous song
--next: Plays the next song
--display: Prints the currently playing song and artist to stdout
--notify-send: Use only *after* --display; also pops up a notification with currently playing song and artist
--uri URI: tells Spotify to display URI (e.g. a playlist or user).

With no options, this script will kill a currently running instance of spotify if there is one.  With --uri, it starts Spotify iff it isn't running.  With any other option, it will return 1 if Spotify is not running.
"

WP="$HOME/.wine"
SPATH="$HOME/.wine/drive_c/Program Files/Spotify/spotify.exe"
TITLE=$(wmctrl -xl | grep -o -e "spotify\.exe\.Wine.*$" | grep -o -e "Spotify.*$")
ACTIVEWIN=$(wmctrl -va ":ACTIVE:" 2>&1 | grep -o -e "0x.*$")

sendkeys () {
    wmctrl -xa "spotify.exe.Wine" || return 1
    xvkbd -q -delay 100 -text "$1"
    wmctrl -ia $ACTIVEWIN
}

if [ $# -eq 0 ] ; then
    if pgrep spotify.exe &>/dev/null ; then
        killall spotify.exe
    fi
    exec env WINEPREFIX="$WP" wine "$SPATH"
elif [ "$1" == "--uri" ] ; then
    shift
    exec env WINEPREFIX="$WP" wine "$SPATH" /uri "$@"
elif [ -z "$TITLE" ] ; then
    echo "Spotify is not running" >&2
    if [ "$@" = "--display --notify-send" ] ; then
        notify-send "Spotify is not running"
    fi
    exit 1
else
    case "$1" in
          --playpause) #toggles
        sendkeys '\ '
        ;;

          --next)
        sendkeys '\C\[Right]'
        ;;

          --prev)
        sendkeys '\C\[Left]'
        ;;

            --pause) #pauses if playing; does nothing if not
        if [ -n "${TITLE:9}" ] ; then
            sendkeys '\ '
        fi
        ;;

            --play) #plays if paused; does nothing if not
        if [ -z "${TITLE:9}" ] ; then
            sendkeys '\ '
        fi
        ;;

          --display)
        if [ -n "${TITLE:9}" ] ; then
            OUT1="Now Playing"
            OUT2="${TITLE:9}"
        else
            OUT1="Spotify paused."
            OUT2=""
        fi
        echo "$OUT"
        if [ "$#" -ge 2 ] && [ $2 == "--notify-send" ] ; then
            notify-send "$OUT1" "$OUT2"
        fi
        ;;
            *)
        echo "$USAGE"
        exit 2
        ;;
    esac
fi

exit 0

Solution 4:

Use xev (X event viewer) to determine what keycode is sent when you press that key. Then you can remap the key in the keymapping utility of whatever system you're using (Gnome, KDE, bare X, etc).

On my Debian system, xev is installed with the x11-utils package, so it's likely included in a typical Ubuntu desktop installation.

Example use:

$ xev
[example keypress: right option key on an apple USB keyboard]

KeyPress event, serial 33, synthetic NO, window 0x1200001,
    root 0x2e, subw 0x0, time 122600873, (-49,299), root:(679,325),
    state 0x0, keycode 255 (keysym 0xffec, Super_R), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

KeyRelease event, serial 34, synthetic NO, window 0x1200001,
    root 0x2e, subw 0x0, time 122600971, (-49,299), root:(679,325),
    state 0x0, keycode 255 (keysym 0xffec, Super_R), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False