Changeset 4832c1e5dd8d1b8a435fd410ae6afeb2ec26ca32
- Timestamp:
- 09/15/07 13:01:48 (1 year ago)
- git-parent:
- Files:
-
- extras/mpris.py (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
extras/mpris.py
r41bb970 r4832c1e 2 2 # -*- coding: utf8 -*- 3 3 # 4 # Copyright (C) 2006Rafaël Carré <funman at videolanorg>4 # Copyright © 2006-2007 Rafaël Carré <funman at videolanorg> 5 5 # 6 6 # $Id$ … … 22 22 23 23 # 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 24 # NOTE: This controller is a SAMPLE, and thus doesn't use all the 25 # Media Player Remote Interface Specification (MPRIS for short) capabilities 26 # 27 # MPRIS: http://wiki.xmms2.xmms.se/index.php/Media_Player_Interfaces 27 28 # 28 29 # You'll need pygtk >= 2.10 to use gtk.StatusIcon 29 30 # 31 # TODO 32 # Ability to choose the Media Player if several are connected to the bus 33 34 # core dbus stuff 30 35 import dbus 31 36 import dbus.glib 37 38 # core interface stuff 32 39 import gtk 33 40 import gtk.glade 41 42 # timer 34 43 import gobject 44 45 # file loading 35 46 import os 36 47 37 global position38 global timer 48 global win_position # store the window position on the screen 49 39 50 global playing 40 51 playing = False 41 52 42 global shuffle 43 global repeat 44 global loop 45 #mpris doesn't support getting the status of these (at the moment) 53 global shuffle # playlist will play randomly 54 global repeat # repeat the playlist 55 global loop # loop the current element 56 57 # mpris doesn't support getting the status of these (at the moment) 46 58 shuffle = False 47 59 repeat = False 48 60 loop = False 49 61 50 global root 51 global player 52 global tracklist 53 54 global bus 55 56 def player_change(newname, a, b): 57 if b != "" and "org.mpris." in newname: 58 Connect(newname) 59 60 def itemchange_handler(item): 62 # these are defined on the mpris detected unique name 63 global root # / org.freedesktop.MediaPlayer 64 global player # /Player org.freedesktop.MediaPlayer 65 global tracklist # /Tracklist org.freedesktop.MediaPlayer 66 67 global bus # Connection to the session bus 68 global identity # MediaPlayer Identity 69 70 71 # If a Media Player connects to the bus, we'll use it 72 # Note that we forget the previous Media Player we were connected to 73 def NameOwnerChanged(name, new, old): 74 if old != "" and "org.mpris." in name: 75 Connect(name) 76 77 # Callback for when "TrackChange" signal is emitted 78 def TrackChange(Track): 79 # the only mandatory metadata is "URI" 61 80 try: 62 a = item["artist"]81 a = Track["artist"] 63 82 except: 64 83 a = "" 65 84 try: 66 t = item["title"]85 t = Track["title"] 67 86 except: 68 t = "" 69 if t == "": 70 t = item["URI"] 87 t = Track["URI"] 88 # update the labels 71 89 l_artist.set_text(a) 72 90 l_title.set_text(t) 73 91 74 # find the first media player available92 # Connects to the Media Player we detected 75 93 def Connect(name): 76 global root 77 global player 78 global tracklist 79 global bus 80 global playing 81 94 global root, player, tracklist 95 global playing, identity 96 97 # first we connect to the objects 82 98 root_o = bus.get_object(name, "/") 83 99 player_o = bus.get_object(name, "/Player") 84 100 tracklist_o = bus.get_object(name, "/TrackList") 85 101 102 # there is only 1 interface per object 86 103 root = dbus.Interface(root_o, "org.freedesktop.MediaPlayer") 87 104 tracklist = dbus.Interface(tracklist_o, "org.freedesktop.MediaPlayer") 88 105 player = dbus.Interface(player_o, "org.freedesktop.MediaPlayer") 89 player_o.connect_to_signal("TrackChange", itemchange_handler, dbus_interface="org.freedesktop.MediaPlayer") 106 107 # connect to the TrackChange signal 108 player_o.connect_to_signal("TrackChange", TrackChange, dbus_interface="org.freedesktop.MediaPlayer") 109 110 # determine if the Media Player is playing something 90 111 if player.GetStatus() == 0: 91 112 playing = True 92 window.set_title(root.Identity()) 113 114 # gets its identity (name and version) 115 identity = root.Identity() 116 window.set_title(identity) 93 117 94 118 #plays an element … … 104 128 update(0) 105 129 106 #basic control 130 # basic control 131 107 132 def Next(widget): 108 133 player.Next(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) … … 117 142 update(0) 118 143 119 #update status display 144 def Quit(widget): 145 player.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) 146 l_title.set_text("") 147 148 def Pause(widget): 149 player.Pause() 150 status = player.GetStatus() 151 if status == 0: 152 img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_SMALL_TOOLBAR) 153 else: 154 img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_SMALL_TOOLBAR) 155 update(0) 156 157 def Repeat(widget): 158 global repeat 159 repeat = not repeat 160 player.Repeat(repeat) 161 162 def Shuffle(widget): 163 global shuffle 164 shuffle = not shuffle 165 tracklist.Random(shuffle) 166 167 def Loop(widget): 168 global loop 169 loop = not loop 170 tracklist.Loop(loop) 171 172 # update status display 120 173 def update(widget): 121 174 item = tracklist.GetMetadata(tracklist.GetCurrentTrack()) … … 136 189 GetPlayStatus(0) 137 190 138 #get playing status from remote player 191 # callback for volume change 192 def volchange(widget, data): 193 player.VolumeSet(vol.get_value_as_int(), reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) 194 195 # callback for position change 196 def timechange(widget, x=None, y=None): 197 player.PositionSet(int(time_s.get_value()), reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) 198 199 # refresh position change 200 def timeset(): 201 global playing 202 if playing == True: 203 time_s.set_value(player.PositionGet()) 204 return True 205 206 # toggle simple/full display 207 def expander(widget): 208 if exp.get_expanded() == False: 209 exp.set_label("Less") 210 else: 211 exp.set_label("More") 212 213 # close event : hide in the systray 214 def delete_event(self, widget): 215 self.hide() 216 return True 217 218 # shouldn't happen 219 def destroy(widget): 220 gtk.main_quit() 221 222 # hide the controller when 'Esc' is pressed 223 def key_release(widget, event): 224 if event.keyval == gtk.keysyms.Escape: 225 global win_position 226 win_position = window.get_position() 227 widget.hide() 228 229 # callback for click on the tray icon 230 def tray_button(widget): 231 global win_position 232 if window.get_property('visible'): 233 # store position 234 win_position = window.get_position() 235 window.hide() 236 else: 237 # restore position 238 window.move(win_position[0], win_position[1]) 239 window.show() 240 241 # hack: update position, volume, and metadata 242 def icon_clicked(widget, event): 243 update(0) 244 245 # get playing status, modify the Play/Pause button accordingly 139 246 def GetPlayStatus(widget): 140 247 global playing … … 147 254 playing = False 148 255 149 def Quit(widget): 150 player.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) 151 l_title.set_text("") 152 153 def Pause(widget): 154 player.Pause() 155 status = player.GetStatus() 156 if status == 0: 157 img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_SMALL_TOOLBAR) 158 else: 159 img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_SMALL_TOOLBAR) 160 update(0) 161 162 def Repeat(widget): 163 global repeat 164 repeat = not repeat 165 player.Repeat(repeat) 166 167 def Shuffle(widget): 168 global shuffle 169 shuffle = not shuffle 170 tracklist.Random(shuffle) 171 172 def Loop(widget): 173 global loop 174 loop = not loop 175 tracklist.Loop(loop) 176 177 #callback for volume 178 def volchange(widget, data): 179 player.VolumeSet(vol.get_value_as_int(), reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) 180 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)) 184 185 #refresh position 186 def timeset(): 187 global playing 188 if playing == True: 189 time_s.set_value(player.PositionGet()) 190 return True 191 192 #simple/full display 193 def expander(widget): 194 if exp.get_expanded() == False: 195 exp.set_label("Less") 196 else: 197 exp.set_label("More") 198 199 #close event 200 def delete_event(self, widget): 201 self.hide() 202 return True 203 204 def destroy(widget): 205 gtk.main_quit() 206 207 def key_release(widget, event): 208 global position 209 if event.keyval == gtk.keysyms.Escape: 210 position = window.get_position() 211 widget.hide() 212 213 #click on the tray icon 214 def tray_button(widget): 215 global position 216 if window.get_property('visible'): 217 position = window.get_position() 218 window.hide() 219 else: 220 window.move(position[0], position[1]) 221 window.show() 222 223 #loads glade file from the directory where the script is, 224 #so we can use /path/to/mpris.py to execute it. 256 # loads glade file from the directory where the script is, 257 # so we can use /path/to/mpris.py to execute it. 225 258 import sys 226 259 xml = gtk.glade.XML(os.path.dirname(sys.argv[0]) + '/mpris.glade') 227 260 228 # ui setup261 # ui setup 229 262 bt_close = xml.get_widget('close') 230 263 bt_quit = xml.get_widget('quit') … … 250 283 time_l = xml.get_widget('time_l') 251 284 285 # connect to the different callbacks 286 252 287 window.connect('delete_event', delete_event) 253 288 window.connect('destroy', destroy) … … 256 291 tray = gtk.status_icon_new_from_icon_name("audio-x-generic") 257 292 tray.connect('activate', tray_button) 258 259 def icon_clicked(widget, event):260 update(0)261 293 262 294 bt_close.connect('clicked', destroy) … … 274 306 vol.connect('scroll-event', volchange) 275 307 time_s.connect('adjust-bounds', timechange) 276 audioicon.set_events(gtk.gdk.BUTTON_PRESS_MASK) 308 audioicon.set_events(gtk.gdk.BUTTON_PRESS_MASK) # hack for the bottom right icon 277 309 audioicon.connect('button_press_event', icon_clicked) 278 310 time_s.set_update_policy(gtk.UPDATE_DISCONTINUOUS) 279 311 280 library = "/media/mp3" #editme 281 312 library = "/media/mp3" # editme 313 314 # set the Directory chooser to a default location 282 315 try: 283 316 os.chdir(library) … … 286 319 bt_file.set_current_folder(os.path.expanduser("~")) 287 320 288 # connect to the bus321 # connect to the bus 289 322 bus = dbus.SessionBus() 290 323 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")324 dbus_names.connect_to_signal("NameOwnerChanged", NameOwnerChanged, dbus_interface="org.freedesktop.DBus") # to detect new Media Players 292 325 293 326 dbus_o = bus.get_object("org.freedesktop.DBus", "/") 294 327 dbus_intf = dbus.Interface(dbus_o, "org.freedesktop.DBus") 295 328 name_list = dbus_intf.ListNames() 296 name = "" 329 330 # connect to the first Media Player found 297 331 for n in name_list: 298 332 if "org.mpris." in n: 299 name = n 333 Connect(n) 334 window.set_title(identity) 335 vol.set_value(player.VolumeGet()) 336 update(0) 300 337 break 301 338 302 if name != "": 303 Connect(name) 304 window.set_title(root.Identity()) 305 vol.set_value(player.VolumeGet()) 306 307 #runs timer to update position 339 # run a timer to update position 308 340 gobject.timeout_add( 1000, timeset) 309 341 310 342 window.set_icon_name('audio-x-generic') 311 343 window.show() 312 313 try:314 update(0)315 except:316 True317 344 318 345 icon_theme = gtk.icon_theme_get_default() … … 322 349 except: 323 350 True 324 position = window.get_position() 325 326 gtk.main() 351 352 win_position = window.get_position() 353 354 gtk.main() # execute the main loop
