问题
I want to monitor the change of track in Rhythmbox using python. I want to continuously check for change of track and execute a set of functions if the track is changed. I have written a piece of code which gets hold of the Rhythmbox interfaces from the dbus and gets the current track details. But this program has to be run manually to check for any change.
I am new to this and I would like to know how we can create a background process which continuously runs and checks Rhythmbox.
I dont want to make a Rhythmbox plugin(which rather would make my work simple) as I will be extending the application to listen to multiple music players.
Please suggest me what exactly I would have to do to achieve the functionality.
回答1:
The Rhythmbox player object (/org/gnome/Rhythmbox/Player
) sends a playingUriChanged
signal whenever the current song changes. Connect a function to the signal to have it run whenever the signal is received. Here's an example that prints the title of the song whenever a new song starts, using the GLib main loop to process DBus messages:
#! /usr/bin/env python
import dbus
import dbus.mainloop.glib
import glib
# This gets called whenever Rhythmbox sends the playingUriChanged signal
def playing_song_changed (uri):
global shell
if uri != "":
song = shell.getSongProperties (uri)
print "Now playing: {0}".format (song["title"])
else:
print "Not playing anything"
dbus.mainloop.glib.DBusGMainLoop (set_as_default = True)
bus = dbus.SessionBus ()
proxy = bus.get_object ("org.gnome.Rhythmbox", "/org/gnome/Rhythmbox/Player")
player = dbus.Interface (proxy, "org.gnome.Rhythmbox.Player")
player.connect_to_signal ("playingUriChanged", playing_song_changed)
proxy = bus.get_object ("org.gnome.Rhythmbox", "/org/gnome/Rhythmbox/Shell")
shell = dbus.Interface (proxy, "org.gnome.Rhythmbox.Shell")
# Run the GLib event loop to process DBus signals as they arrive
mainloop = glib.MainLoop ()
mainloop.run ()
回答2:
Take a look at the Conky script here:
https://launchpad.net/~conkyhardcore/+archive/ppa/+files/conkyrhythmbox_2.12.tar.gz
That uses dbus to talk to rhythmbox, like so:
bus = dbus.SessionBus()
remote_object_shell = bus.get_object('org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Shell')
iface_shell = dbus.Interface(remote_object_shell, 'org.gnome.Rhythmbox.Shell')
remote_object_player = bus.get_object('org.gnome.Rhythmbox', '/org/gnome/Rhythmbox/Player')
iface_player = dbus.Interface(remote_object_player, 'org.gnome.Rhythmbox.Player')
You can call a number of functions on iface_player to get the required information. It looks like you'll have to poll from this example though. If you want to receive a message from dbus on track change you'll have to do that in a different way. This discusses from avenues to explore:
http://ubuntuforums.org/showthread.php?t=156706
回答3:
I am using Ubuntu 14.04.1 and the above script is deprecated for Rhythmbox 3. I am using this script to write the current song to ~/.now_playing for BUTT to read, but you can update it for your needs. Rhythmbox uses MPRIS now and you can get info here:
http://specifications.freedesktop.org/mpris-spec/latest/index.html
#!/usr/bin/python
import dbus
import dbus.mainloop.glib
import glib
# This gets called whenever Rhythmbox sends the playingUriChanged signal
def playing_song_changed (Player,two,three):
global iface
global track
global home
track2 = iface.Get(Player,"Metadata").get(dbus.String(u'xesam:artist'))[0] + " - "+ iface.Get(Player,"Metadata").get(dbus.String(u'xesam:title'))
if track != track2:
track = iface.Get(Player,"Metadata").get(dbus.String(u'xesam:artist'))[0] + " - "+ iface.Get(Player,"Metadata").get(dbus.String(u'xesam:title'))
f = open( home + '/.now_playing', 'w' )
f.write( track + '\n' )
f.close()
dbus.mainloop.glib.DBusGMainLoop (set_as_default = True)
bus = dbus.SessionBus ()
from os.path import expanduser
home = expanduser("~")
player = bus.get_object ("org.mpris.MediaPlayer2.rhythmbox", "/org/mpris/MediaPlayer2")
iface = dbus.Interface (player, "org.freedesktop.DBus.Properties")
track = iface.Get("org.mpris.MediaPlayer2.Player","Metadata").get(dbus.String(u'xesam:artist'))[0] + " - "+ iface.Get("org.mpris.MediaPlayer2.Player","Metadata").get(dbus.Strin$
f = open( home + "/.now_playing", 'w' )
f.write( track + '\n' )
f.close()
iface.connect_to_signal ("PropertiesChanged", playing_song_changed)
# Run the GLib event loop to process DBus signals as they arrive
mainloop = glib.MainLoop ()
mainloop.run ()
回答4:
Something like:
from time import sleep
execute = True
while execute:
your_function_call()
sleep(30) # in seconds; prevent busy polling
Should work just fine. If that was hooked up to something that listened to signals (import signal
) so that you could set execute to False when someone ctrl-c's the application, that'd be basically what you're after.
Otherwise, have a Google for daemonisation (which involves forking the process a couple of times); from memory, there's even a decent Python library now (which, from memory, requires 2.5/2.6 with
statements) which would help make that side of things easier :).
来源:https://stackoverflow.com/questions/3919735/how-to-continuously-monitor-rhythmbox-for-track-change-using-python