diff --git a/icon_spotify.png b/icon_spotify.png
new file mode 100644
index 0000000..a640f7d
Binary files /dev/null and b/icon_spotify.png differ
diff --git a/one-tmux b/one-tmux
index 9c8f57c..7b063c3 100755
--- a/one-tmux
+++ b/one-tmux
@@ -1,5 +1,5 @@
#!/bin/bash
-TERMINAL_EMULATOR='xfce4-terminal'
+TERMINAL_EMULATOR='urxvt'
tab=1
pgrep -l -u "$USER" -f "$TERMINAL_EMULATOR" | egrep -v "/bin/zsh|/bin/bash|/bin/sh" | grep -vq "$$"
if [ $? != "0" ]
diff --git a/spotify-remote.py b/spotify-remote.py
new file mode 100755
index 0000000..e0a7dbf
--- /dev/null
+++ b/spotify-remote.py
@@ -0,0 +1,419 @@
+#!/usr/bin/python
+
+# Spoify-remote
+# Modified version of Spotify-notify that runs once when invoked instead of looping.
+#
+# v0.6d (28th aug 11)
+# by JonW (jon.neverwinter@gmail.com)
+# patched 20110907 by Jansen Price (sumpygump@gmail.com)
+# patched 20120729 by Jansen Price (sumpygump@gmail.com) and brandl.matthaeus
+# modified 20130405 by Fernando Sánchez (balkian@gmail.com)
+#
+# Original by SveinT (sveint@gmail.com)
+# up to v0.5.2 (27th jan 11)
+
+
+import dbus
+
+import gobject, gtk, os, tempfile, sys, time, re, indicate, urllib2
+from optparse import OptionParser
+from subprocess import *
+
+# The url to use when fetching spotify track information.
+SPOTIFY_OPEN_URL = "http://open.spotify.com/track/"
+
+# The path to this application's directory.
+APPLICATION_DIR = sys.path[0] + "/"
+
+# The file path to spotify. If empty, it will try to auto detect.
+SPOTIFY_PROCESS_NAME = 'spotify'
+
+# How often to check if spotify has been closed (in milliseconds).
+SPOTIFY_CLOSED_CHECK = 20000
+
+class SpotifyNotify():
+
+ spotifyPath = ''
+
+ tryToReconnect = False
+
+ tmpfile = False
+
+ def __init__(self, debugger):
+ self.debug = debugger
+ self.spotifyservice = False
+
+ self.prev = 0
+ self.new = False
+ self.prevMeta = {}
+ self.notifyid = 0
+
+ self.connect()
+
+ def __del__(self):
+ if SpotifyNotify and SpotifyNotify.tmpfile:
+ SpotifyNotify.tmpfile.close()
+
+ def connect(self):
+ self.debug.out("Connecting to spotify.")
+ self.bus = dbus.Bus(dbus.Bus.TYPE_SESSION)
+
+ try:
+ self.spotifyservice = self.bus.get_object(
+ 'com.spotify.qt',
+ '/org/mpris/MediaPlayer2'
+ )
+ SpotifyNotify.tryToReconnect = False
+ except Exception, e:
+ self.spotifyservice = False
+ self.debug.out("Failed to connect.")
+ self.debug.out(e)
+
+ def executeCommand(self, key):
+ if not key:
+ return
+
+ self.connect()
+ self.debug.out("Running command: {0}".format(key))
+ self.cmd = self.spotifyservice.get_dbus_method(key, 'org.mpris.MediaPlayer2.Player')
+ self.cmd()
+
+ def pollChange(self):
+ try:
+ self.spotifyservice = self.bus.get_object('com.spotify.qt', '/')
+ self.cmd = self.spotifyservice.get_dbus_method(
+ 'GetMetadata',
+ 'org.freedesktop.MediaPlayer2'
+ )
+ self.new = self.cmd()
+ except Exception, e:
+ self.debug.out('Spotify service not connected.')
+ SpotifyNotify.tryToReconnect = True
+
+ if (self.prev != self.new):
+ self.trackChange(self.new)
+ self.prev = self.new
+
+ return 1
+
+ def trackChange(self, *trackChange):
+ if not trackChange[0]:
+ return
+
+ self.prev = trackChange[0]
+
+ trackInfo = {}
+ trackMap = {
+ 'artist' : 'xesam:artist',
+ 'album' : 'xesam:album',
+ 'title' : 'xesam:title',
+ 'year' : 'xesam:contentCreated',
+ 'trackhash' : 'mpris:trackid',
+ 'arturl' : 'mpris:artUrl'
+ }
+
+ # Fetch the track information for the notification window.
+ for key in trackMap:
+ if not trackMap[key] in trackChange[0]:
+ continue
+ piece = trackChange[0][trackMap[key]]
+ if key == 'year':
+ piece = str(piece[:4])
+ elif isinstance(piece, list):
+ piece = ", ".join(piece)
+
+ if not isinstance(piece, str):
+ piece = str(piece)
+
+ trackInfo[key] = piece.encode('utf-8')
+
+ if not self.prevMeta\
+ or not SpotifyNotify.tmpfile\
+ or 'iconfilename' not in self.prevMeta\
+ or self.prevMeta['artist'] != trackInfo['artist']\
+ or self.prevMeta['album'] != trackInfo['album']:
+ trackInfo['iconfilename'] = self.retrieveCoverImage(trackInfo)
+
+ cover_image = ''
+
+ if 'iconfilename' in trackInfo:
+ cover_image = trackInfo['iconfilename']
+ elif 'iconfilename' in self.prevMeta:
+ cover_image = self.prevMeta['iconfilename']
+ trackInfo['iconfilename'] = cover_image
+
+ if cover_image == '':
+ cover_image = APPLICATION_DIR + 'icon_spotify.png'
+
+ self.prevMeta = trackInfo
+
+ # Connect to notification interface on DBUS.
+ self.notifyservice = self.bus.get_object(
+ 'org.freedesktop.Notifications',
+ '/org/freedesktop/Notifications'
+ )
+ self.notifyservice = dbus.Interface(
+ self.notifyservice,
+ "org.freedesktop.Notifications"
+ )
+ notifyText = "{0}\n{1}".format(
+ trackInfo['title'],
+ trackInfo['album']
+ )
+ if len(trackInfo['year']) > 0:
+ notifyText += " ({0})".format(trackInfo['year'])
+
+ # Send track change information to stdout
+ print "Changing track : {0} | {1} | {2} ({3})".format(
+ trackInfo['artist'],
+ trackInfo['title'],
+ trackInfo['album'],
+ trackInfo['year']
+ )
+
+ # The second param is the replace id, so get the notify id back,
+ # store it, and send it as the replacement on the next call.
+ self.notifyid = self.notifyservice.Notify(
+ "Spotify-notify",
+ self.notifyid,
+ cover_image,
+ trackInfo['artist'],
+ notifyText,
+ [],
+ {},
+ 2000
+ )
+
+ def retrieveCoverImage(self, trackInfo):
+ if 'arturl' in trackInfo:
+ self.debug.out("Simply retrieving image from {0}".format(trackInfo['arturl']))
+ iconfilename = self.fetchCoverImage(trackInfo['arturl'])
+ else:
+ #if (trackInfo['trackhash'][0:14] == 'spotify:local:'):
+ # self.debug.out("Track is a local file. No art available.")
+ # return ''
+
+ self.debug.out("Attempting to fetch image from spotify")
+ iconfilename = self.fetchCoverImageSpotify(
+ trackInfo['artist'],
+ trackInfo['album'],
+ trackInfo['trackhash']
+ )
+ return iconfilename
+
+ def fetchCoverImageSpotify(self, artist, album, trackhash):
+ try:
+ trackid = trackhash.split(":")[2]
+ url = SPOTIFY_OPEN_URL + trackid
+ tracksite = urllib2.urlopen(url).read()
+
+ # Attempt to get the image url from the open graph image meta tag.
+ imageurl = False
+ metaMatch = re.search(
+ ']*property\s*=\s*["\']og:image["\'][^\>]*/?>',
+ tracksite
+ )
+ if metaMatch:
+ contentMatch = re.search(
+ 'content\s*=\s*["\']([^\"\']*)["\']',
+ metaMatch.group(0)
+ )
+ if contentMatch:
+ imageurl = contentMatch.group(1)
+
+ if not imageurl:
+ self.debug.out("No cover available.")
+ raise()
+
+ return self.fetchCoverImage(imageurl)
+ except Exception, e:
+ self.debug.out("Couldn't fetch cover image.")
+ self.debug.out(e)
+
+ return ''
+
+ def fetchCoverImage(self, url):
+ # Close the temporary image file, we are going to make a new one.
+ if SpotifyNotify.tmpfile:
+ SpotifyNotify.tmpfile.close()
+ SpotifyNotify.tmpfile = False
+
+ try:
+ SpotifyNotify.tmpfile = tempfile.NamedTemporaryFile()
+ tmpfilename = SpotifyNotify.tmpfile.name
+ self.debug.out("Album art tmp filepath: {0}".format(tmpfilename))
+
+ coverfile = urllib2.urlopen(url)
+ SpotifyNotify.tmpfile.write(coverfile.read())
+ SpotifyNotify.tmpfile.flush()
+ return tmpfilename
+ except Exception, e:
+ self.debug.out("Couldn't fetch cover image.")
+ self.debug.out(e)
+
+ return ''
+
+ @staticmethod
+ def startSpotify(Debug):
+ if not SpotifyNotify.spotifyPath:
+ Debug.out("No spotify process identifier found.")
+ return
+
+ ident = SpotifyNotify.spotifyPath
+ Debug.out("Looking for spotify as: {0}".format(ident))
+
+ procs = SpotifyNotify.checkForProcess(
+ 'ps x | grep "{0}" | grep -v grep'.format(ident),
+ Debug
+ )
+ if len(procs):
+ Debug.out("Spotify process found as: {0}".format(" ".join(procs[0])))
+ return
+
+ Debug.out("Starting new Spotify now.")
+
+ FNULL = open('/dev/null', 'w')
+ spid = Popen([ident], stdout=FNULL, stderr=FNULL).pid
+ if spid:
+ Debug.out("Spotify started, pid: {0}.".format(spid))
+ else:
+ Debug.out("Spotify could not be started.")
+
+ @staticmethod
+ def checkForClosedSpotify(SN, Debug):
+ if not SpotifyNotify.spotifyPath:
+ Debug.out("No spotify process identifier found.")
+ return False
+
+ ident = SpotifyNotify.spotifyPath
+ Debug.out("Looking for spotify as: {0}".format(ident))
+
+ procs = SpotifyNotify.checkForProcess(
+ 'ps x | grep "{0}" | grep -v grep'.format(ident),
+ Debug
+ )
+ if len(procs):
+ Debug.out("Spotify process found as: {0}".format(" ".join(procs[0])))
+
+ if (SpotifyNotify.tryToReconnect):
+ SN.connect()
+
+ return True
+
+ if SpotifyNotify.tmpfile:
+ SpotifyNotify.tmpfile.close()
+
+ Debug.out("Spotify has been closed, therefore I die.")
+ exit(0)
+
+ @staticmethod
+ def preventDuplicate(Debug):
+ mypid = os.getpid()
+ Debug.out("My pid: {0}".format(mypid))
+
+ proc = SpotifyNotify.checkForProcess('ps -p {0}'.format(mypid), Debug)
+ if not proc[0][3]:
+ return
+
+ process = proc[0][3]
+ search = 'ps -C {0}'.format(process)
+
+ Debug.out("Looking for other processes named: {0}".format(process).strip())
+
+ if process == 'python':
+ if not sys.argv[0]:
+ Debug.out("Process started using python, cannot determine script name.")
+ return
+
+ search = 'ps ax | grep "python {0}" | grep -v grep'.format(sys.argv[0])
+
+ for line in SpotifyNotify.checkForProcess(search, Debug):
+ if int(line[0]) != mypid:
+ print("This program was already running.")
+ Debug.out("I am a duplicate. I shall end myself. ({0})".format(" ".join(line)))
+ exit(0)
+
+ @staticmethod
+ def checkForProcess(proc, Debug):
+ output = []
+
+ for line in Popen(proc, shell=True, stdout=PIPE).stdout:
+ fields = line.split()
+ if not fields[0].isdigit():
+ continue
+
+ output.append(fields)
+
+ return output
+
+class DebugMe():
+ def __init__(self, toggle):
+ if toggle:
+ self.output = True
+ else:
+ self.output = False
+
+ def out(self, msg):
+ if not self.output:
+ return
+
+ print(">> {0}".format(msg))
+
+if __name__ == "__main__":
+ parser = OptionParser()
+ parser.add_option(
+ '-a',
+ '--action',
+ dest = 'action',
+ default = None,
+ type = 'choice',
+ choices = ['playPause', 'play', 'pause', 'next', 'previous'],
+ help = 'Music player actions (playPause/play/pause/next/previous).'
+ )
+ parser.add_option(
+ '-n',
+ '--skip_notify',
+ dest = 'skipNotify',
+ action = 'store_true',
+ default = False,
+ help = 'Song change notifications will be turned off.'
+ )
+ parser.add_option(
+ '-d',
+ '--debug',
+ dest = 'debug',
+ action = 'store_true',
+ default = False,
+ help = 'Debug messages will be displayed.'
+ )
+
+ (options, args) = parser.parse_args()
+
+ Debug = DebugMe(options.debug)
+ print("Spotify-notify v0.6")
+
+ if SPOTIFY_PROCESS_NAME:
+ SpotifyNotify.spotifyPath = SPOTIFY_PROCESS_NAME
+ else:
+ print "Spotify is not running"
+ sys.exit(0)
+
+ SN = SpotifyNotify(Debug)
+
+ if options.action:
+ action = options.action
+ action = action[0:1].upper() + action[1:]
+ SN.executeCommand(action)
+
+ SpotifyNotify.preventDuplicate(Debug)
+
+ try:
+ indicateserver = indicate.indicate_server_ref_default()
+ indicateserver.set_type("music.spotify")
+ indicateserver.set_desktop_file("/usr/share/applications/spotify.desktop")
+ indicateserver.show()
+ except:
+ pass
+ SN.pollChange()
+ print "Done"
+
diff --git a/spotify-remote.sh b/spotify-remote.sh
new file mode 100755
index 0000000..49d760e
--- /dev/null
+++ b/spotify-remote.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+# Extracted from: http://ubuntuforums.org/showthread.php?t=1797848
+# User: azzid
+# Modified by Balkian
+# Collect DBUS_SESSION_BUS_ADDRESS from running process
+function set_dbus_adress
+{
+ USER=$1
+ PROCESS=$2
+ PID=`pgrep -o -u $USER $PROCESS`
+ ENVIRON=/proc/$PID/environ
+
+ if [ -e $ENVIRON ]
+ then
+ export `grep -z DBUS_SESSION_BUS_ADDRESS $ENVIRON`
+ else
+ echo "Unable to set DBUS_SESSION_BUS_ADDRESS."
+ exit 1
+ fi
+}
+
+function spotify_cmd
+{
+ dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.$1 1> /dev/null
+}
+
+function spotify_query
+{
+ qdbus org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get org.mpris.MediaPlayer2.Player PlaybackStatus
+}
+
+function spotify_metadata
+{
+ qdbus com.spotify.qt / org.freedesktop.MediaPlayer2.GetMetadata
+}
+
+function spotify_notify
+{
+ metadata=`spotify_metadata`
+ echo "Metadata: $metadata"
+ title=`echo "$metadata" | grep title | cut -d' ' -f2-`
+ artist=`echo "$metadata" | grep artist | cut -d' ' -f2-`
+ image=`echo "$metadata" | grep artUrl | cut -d' ' -f3`
+ wget $image -O /tmp/image
+ echo "notifying $title"
+ notify-send "$artist" "$title" --icon=/tmp/image
+}
+
+function quit_message
+{
+ echo "Usage: `basename $0` {play|pause|playpause|next|previous|stop|playstatus|}"
+ exit 1
+}
+
+# Count arguments, must be 1
+if [ "$#" -ne "1" ]
+then
+ echo -e "You must supply exactly one argument!\n"
+ quit_message
+fi
+
+# Check if DBUS_SESSION is set
+if [ -z $DBUS_SESSION_BUS_ADDRESS ]
+ then
+ #echo "DBUS_SESSION_BUS_ADDRESS not set. Guessing."
+ set_dbus_adress `whoami` spotify
+fi
+
+case "$1" in
+ play)
+ spotify_cmd Play
+ spotify_notify
+ ;;
+ pause)
+ spotify_cmd Pause
+ spotify_notify
+ ;;
+ playpause)
+ spotify_cmd PlayPause
+ spotify_notify
+ ;;
+ next)
+ spotify_cmd Next
+ spotify_notify
+ ;;
+ previous)
+ spotify_cmd Previous
+ spotify_notify
+ ;;
+ stop)
+ spotify_cmd Stop
+ spotify_notify
+ ;;
+ spotify:user:*)
+ spotify_cmd "OpenUri string:$1"
+ spotify_cmd Play
+ spotify_notify
+ ;;
+ spotify:*:*)
+ spotify_cmd "OpenUri string:$1"
+ ;;
+ playstatus)
+ spotify_query
+ ;;
+ metadata)
+ spotify_metadata;
+ ;;
+ *)
+ echo -e "Bad argument.\n"
+ quit_message
+ ;;
+esac
+
+exit 0