我想使用 python 来监控 Rhythmbox 中音轨的变化。我想不断检查轨道的变化并在轨道发生变化时执行一组函数。我编写了一段代码,它从 dbus 获取 Rhythmbox 接口并获取当前音轨详细信息。但是这个程序必须手动运行以检查是否有任何变化。
我是新手,我想知道我们如何创建一个持续运行和检查 Rhythmbox 的后台进程。
我不想制作一个 Rhythmbox 插件(这会让我的工作变得简单),因为我将扩展应用程序以收听多个音乐播放器。
请建议我要实现该功能究竟需要做什么。
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 ()
看看这里的 Conky 脚本:
https://launchpad.net/~conkyhardcore/+archive/ppa/+files/conkyrhythmbox_2.12.tar.gz
它使用 dbus 与节奏盒对话,如下所示:
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')
您可以调用 iface_player 上的许多函数来获取所需的信息。不过,看起来您必须从这个示例中进行轮询。如果您想从 dbus 接收有关轨道更改的消息,您必须以不同的方式进行。本文从探索途径探讨:
我正在使用 Ubuntu 14.04.1,并且 Rhythmbox 3 不推荐使用上述脚本。我正在使用此脚本将当前歌曲写入 ~/.now_playing 以供 BUTT 阅读,但您可以根据需要对其进行更新。Rhythmbox 现在使用 MPRIS,您可以在此处获取信息:
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 ()
就像是:
from time import sleep
execute = True
while execute:
your_function_call()
sleep(30) # in seconds; prevent busy polling
应该工作得很好。如果这与侦听信号(import signal
)的东西相关联,以便您可以在某人 ctrl-c 的应用程序时将 execute 设置为 False,那基本上就是您所追求的。
否则,请使用 Google 进行守护进程(这涉及多次分叉该进程);从内存中,现在甚至有一个不错的 Python 库(从内存中,它需要 2.5/2.6with
语句)这将有助于使这方面的事情变得更容易:)。