Using Gajim with MPD

This is a simple example of what's possible with D-Bus and gajim-remote. This script reads the currently playing song out of MPD and updates the Gajim status message with gajim-remote when the song has changed.

Requirements:

Notes:

  • As of 2005-11-09 this only works for me with the svn version of Gajim. Gajim 0.8.2 give a "Service not available" error when running gajim-remote
  • gajim-remote currently (also 2005-11-09) doesn't offer an option to set just the status message without setting online/offline status. Hence the status is set to online whenever the song title changes.
  • The script adds a music note (♫) in front of the current track. It might be that this Unicode character is not supported in all (Windows?) clients.
#!/bin/bash

function reset_status_message() {
    gajim-remote change_status online ""
}

trap reset_status_message EXIT

while sleep 1
do
    if [ "`mpc | wc -l`" == "1" ] ; then
        CURRENT_TITLE=""
    else
        CURRENT_TITLE="`mpc --format \"[%name%: &[%artist% - ]%title%]|%name%|[%artist% - [%album% - ]]%title%|%shortfile%|\" | head -n 1`"
    fi

    if [ "$CURRENT_TITLE" != "$LAST_TITLE" ]
    then
        LAST_TITLE="$CURRENT_TITLE"
        if [ -n "$CURRENT_TITLE" ]
        then
            echo `date +"%Y-%m-%d %H:%M:%S"` - \"$CURRENT_TITLE\"
            gajim-remote change_status online "♫ $CURRENT_TITLE"
        else
            gajim-remote change_status online ""
        fi
    fi
done

This is the same script, but modified to only update when you are online.

#!/bin/bash

function reset_status_message() {
    gajim-remote change_status online ""
}

trap reset_status_message EXIT

while sleep 1
do
    if [ "`mpc | wc -l`" == "1" ] ; then
        CURRENT_TITLE=""
    else
        CURRENT_TITLE="`mpc --format \"[%title%[ - %artist%][ #[%album%#]]]|[%file%]\" | head -n 1`"
    fi

    STATUS=`gajim-remote get_status`

    if [[ "$CURRENT_TITLE" != "$LAST_TITLE" && $STATUS == "online" ]]
    then
        LAST_TITLE="$CURRENT_TITLE"
        if [ -n "$CURRENT_TITLE" ]
        then
            echo `date +"%Y-%m-%d %H:%M:%S"` - \"$CURRENT_TITLE\"
            gajim-remote change_status online "Listening to: $CURRENT_TITLE"
        else
            gajim-remote change_status online ""
        fi
    fi
done

And a third variant which uses less resources (running gajim-remote commands every second uses 22% of my Athlon64 3400Mhz cpu)

#!/bin/bash
#
# show the current playing song in gajim

function reset_status_message() {
    gajim-remote change_status online ""
}

trap reset_status_message EXIT

while sleep 1
do
    if [ "`mpc | wc -l`" == "1" ] ; then
        CURRENT_TITLE=""
    else
        CURRENT_TITLE="`mpc --format \"[[%artist% - ]%title%]|[%file%]\" | sed '3,$d' | sed '2s,].*$,],' | awk 'BEGIN { FS = "\n"; RS = "" } { print $1, $NF }'`"
    fi

    if [ "$CURRENT_TITLE" != "$LAST_TITLE" ] ; then
        STATUS=`gajim-remote get_status`
        if [ $STATUS == "online" ] ; then
            LAST_TITLE="$CURRENT_TITLE"
            if [ -n "$CURRENT_TITLE" ] ; then
                gajim-remote change_status online "♫ $CURRENT_TITLE"
            else
                gajim-remote change_status online ""
            fi
        fi
    fi
done

Variant of script in Python (uses ~0% cpu on P4 :-)

#!/usr/bin/python
# -*- coding: utf-8 -*-
HOST = ""                 # localhost
PORT = 6600              # Port
global oldm,oldmus
oldm=oldmus=""

import  socket,string,time,os

#Getting string with songname
def get(s):
	artist=album=title=""
	for i in s.split("\n"):
		if i.startswith("Artist:"):
			artist=i.replace("Artist: ","",1)
		elif i.startswith("Album:"):
			album=i.replace("Album: ","",1)
		elif i.startswith("Title: "):
			title=i.replace("Title: ","",1)
                elif i.startswith("file: "):
                        file=i.replace("file: ","",1)
        if artist==title=="":
                return file
        else:
	        return artist+": "+album+" - "+title
#Getting gajim status
def get_gajim():
	f=os.popen("gajim-remote get_status")
	return f.read().replace("\n","")
#Getting status-message
def getm_gajim():
	f=os.popen("gajim-remote get_status_message")
	return "\""+f.read().replace("\n","")+"\""
#Setting status
def set_gajim(s=""):
	global oldm,oldmus
	if s=="":
		if oldmus!="":
			o=getm_gajim()
			if o!=oldmus:
				oldm=o
			s=oldm
			oldmus=""
		else:
			return
	else:
		if s==oldmus:
			return
		else:
			o=getm_gajim()
			if o!=oldmus:
				oldm=o
			oldmus=s
	print s
	f=os.popen("gajim-remote change_status "+get_gajim()+" "+s)
	
#Playing status (play/pause/...)
def status(s):
	for i in s.split("\n"):
		if i.startswith("state:"):
			return i.replace("state: ","",1)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
sock.recv(1024)	#Zeroing...
try:
	while 1:
		sock.send("status\n")
		if status(sock.recv(1024)) == "play":
			sock.send("currentsong\n")
			s="\"NP: "+get(sock.recv(1024))+"\""
			set_gajim(s)
		else:
			set_gajim()
		time.sleep(1)
except KeyboardInterrupt:
	set_gajim()
	sock.send("close")
	sock.close()
	print "-----------------------\nExiting..."

This script reads the currently playing song out of MPD and updates the Gajim Tune message when the song has changed:

#!/usr/bin/python
# -*- coding: utf-8 -*-

HOST = 'localhost'
PORT = 6600

import socket, time, dbus.service
from dbus.mainloop.glib import DBusGMainLoop

class mpdtune(dbus.service.Object):
	def __init__(self):
		dbus.service.Object.__init__(self, dbus.SessionBus(), '/Player')
	@dbus.service.signal(dbus_interface = 'org.freedesktop.MediaPlayer')
	def TrackChange(self, trackinfo):
		print trackinfo

def get_status(data):
	for line in data.split('\n'):
		if line.startswith('state:'):
			return line.replace('state: ', '', 1)

def get_data(data):
	artist = album = title = ''
	for line in data.split('\n'):
		if line.startswith('Artist:'):
			artist = line.replace('Artist: ', '', 1)
		elif line.startswith('Album:'):
			album = line.replace('Album: ', '', 1)
		elif line.startswith('Title: '):
			title = line.replace('Title: ', '', 1)
		elif line.startswith('Name:'):
			title = line.replace('Name: ', '', 1)
		elif line.startswith('file: http'):
			album = line.replace('file: ', '', 1)
	return title, artist, album

def set_status(title = '', artist = '', album = ''):
	global lasttune
	if lasttune == title + ' - ' + artist + ' - ' + album:
		return
	lasttune = title + ' - ' + artist + ' - '+ album
	tune.TrackChange(dbus.Dictionary({'title' : title, 'artist' : artist, 'album' : album}))

dbus.SessionBus(mainloop = DBusGMainLoop())
lasttune = ''
tune = mpdtune()
handle = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
handle.connect((HOST, PORT))
handle.recv(1024)
try:
	while 1:
		handle.send('status\n')
		if get_status(handle.recv(1024)) == 'play':
			handle.send('currentsong\n')
			data = get_data(handle.recv(1024))
			set_status(data[0], data[1], data[2])
		else:
			set_status()
		time.sleep(3)
except KeyboardInterrupt:
	set_status()
	handle.send('close\n')
	handle.close()

Attachments