4 # Copyright (C) 2006 Rafaël Carré <funman at videolanorg>
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 # NOTE: this controller is a SAMPLE, and thus doesn't implement all the
25 # Media Player Remote Interface Specification (MPRIS for short) available at
26 # http://wiki.xmms2.xmms.se/index.php/Media_Player_Interfaces
28 # You'll need pygtk >= 2.10 to use gtk.StatusIcon
45 #mpris doesn't support getting the status of these (at the moment)
56 def player_change(newname, a, b):
57 if b != "" and "org.mpris." in newname:
60 def itemchange_handler(item):
74 #find the first media player available
82 root_o = bus.get_object(name, "/")
83 player_o = bus.get_object(name, "/Player")
84 tracklist_o = bus.get_object(name, "/TrackList")
86 root = dbus.Interface(root_o, "org.freedesktop.MediaPlayer")
87 tracklist = dbus.Interface(tracklist_o, "org.freedesktop.MediaPlayer")
88 player = dbus.Interface(player_o, "org.freedesktop.MediaPlayer")
89 player_o.connect_to_signal("TrackChange", itemchange_handler, dbus_interface="org.freedesktop.MediaPlayer")
90 if player.GetStatus() == 0:
92 window.set_title(root.Identity())
96 mrl = e_mrl.get_text()
97 if mrl != None and mrl != "":
98 tracklist.AddTrack(mrl, True)
101 mrl = bt_file.get_filename()
102 if mrl != None and mrl != "":
103 tracklist.AddTrack("directory://" + mrl, True)
108 player.Next(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
112 player.Prev(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
116 player.Stop(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
119 #update status display
121 item = tracklist.GetMetadata(tracklist.GetCurrentTrack())
122 vol.set_value(player.VolumeGet())
138 #get playing status from remote player
139 def GetPlayStatus(widget):
141 status = player.GetStatus()
143 img_bt_toggle.set_from_stock("gtk-media-pause", gtk.ICON_SIZE_SMALL_TOOLBAR)
146 img_bt_toggle.set_from_stock("gtk-media-play", gtk.ICON_SIZE_SMALL_TOOLBAR)
150 player.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
155 status = player.GetStatus()
157 img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_SMALL_TOOLBAR)
159 img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_SMALL_TOOLBAR)
165 player.Repeat(repeat)
169 shuffle = not shuffle
170 tracklist.Random(shuffle)
178 def volchange(widget, data):
179 player.VolumeSet(vol.get_value_as_int(), reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
181 #callback for position change
182 def timechange(widget, x=None, y=None):
183 player.PositionSet(int(time_s.get_value()), reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
189 time_s.set_value(player.PositionGet())
193 def expander(widget):
194 if exp.get_expanded() == False:
195 exp.set_label("Less")
197 exp.set_label("More")
200 def delete_event(self, widget):
207 def key_release(widget, event):
209 if event.keyval == gtk.keysyms.Escape:
210 position = window.get_position()
213 #click on the tray icon
214 def tray_button(widget):
216 if window.get_property('visible'):
217 position = window.get_position()
220 window.move(position[0], position[1])
223 #loads glade file from the directory where the script is,
224 #so we can use /path/to/mpris.py to execute it.
226 xml = gtk.glade.XML(os.path.dirname(sys.argv[0]) + '/mpris.glade')
229 bt_close = xml.get_widget('close')
230 bt_quit = xml.get_widget('quit')
231 bt_file = xml.get_widget('ChooseFile')
232 bt_next = xml.get_widget('next')
233 bt_prev = xml.get_widget('prev')
234 bt_stop = xml.get_widget('stop')
235 bt_toggle = xml.get_widget('toggle')
236 bt_mrl = xml.get_widget('AddMRL')
237 bt_shuffle = xml.get_widget('shuffle')
238 bt_repeat = xml.get_widget('repeat')
239 bt_loop = xml.get_widget('loop')
240 l_artist = xml.get_widget('l_artist')
241 l_title = xml.get_widget('l_title')
242 e_mrl = xml.get_widget('mrl')
243 window = xml.get_widget('window1')
244 img_bt_toggle=xml.get_widget('image6')
245 exp = xml.get_widget('expander2')
246 expvbox = xml.get_widget('expandvbox')
247 audioicon = xml.get_widget('eventicon')
248 vol = xml.get_widget('vol')
249 time_s = xml.get_widget('time_s')
250 time_l = xml.get_widget('time_l')
252 window.connect('delete_event', delete_event)
253 window.connect('destroy', destroy)
254 window.connect('key_release_event', key_release)
256 tray = gtk.status_icon_new_from_icon_name("audio-x-generic")
257 tray.connect('activate', tray_button)
259 def icon_clicked(widget, event):
262 bt_close.connect('clicked', destroy)
263 bt_quit.connect('clicked', Quit)
264 bt_mrl.connect('clicked', AddTrack)
265 bt_toggle.connect('clicked', Pause)
266 bt_next.connect('clicked', Next)
267 bt_prev.connect('clicked', Prev)
268 bt_stop.connect('clicked', Stop)
269 bt_loop.connect('clicked', Loop)
270 bt_repeat.connect('clicked', Repeat)
271 bt_shuffle.connect('clicked', Shuffle)
272 exp.connect('activate', expander)
273 vol.connect('change-value', volchange)
274 vol.connect('scroll-event', volchange)
275 time_s.connect('adjust-bounds', timechange)
276 audioicon.set_events(gtk.gdk.BUTTON_PRESS_MASK)
277 audioicon.connect('button_press_event', icon_clicked)
278 time_s.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
280 library = "/media/mp3" #editme
284 bt_file.set_current_folder(library)
286 bt_file.set_current_folder(os.path.expanduser("~"))
289 bus = dbus.SessionBus()
290 dbus_names = bus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" )
291 dbus_names.connect_to_signal("NameOwnerChanged", player_change, dbus_interface="org.freedesktop.DBus")
293 dbus_o = bus.get_object("org.freedesktop.DBus", "/")
294 dbus_intf = dbus.Interface(dbus_o, "org.freedesktop.DBus")
295 name_list = dbus_intf.ListNames()
298 if "org.mpris." in n:
304 window.set_title(root.Identity())
305 vol.set_value(player.VolumeGet())
307 #runs timer to update position
308 gobject.timeout_add( 1000, timeset)
310 window.set_icon_name('audio-x-generic')
318 icon_theme = gtk.icon_theme_get_default()
320 pix = icon_theme.load_icon("audio-x-generic",24,0)
324 position = window.get_position()