Commit 4832c1e5 authored by Rafaël Carré's avatar Rafaël Carré

Minor fixes, add comments

parent 191a84f4
#!/usr/bin/python #!/usr/bin/python
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
# #
# Copyright (C) 2006 Rafaël Carré <funman at videolanorg> # Copyright © 2006-2007 Rafaël Carré <funman at videolanorg>
# #
# $Id$ # $Id$
# #
...@@ -21,75 +21,99 @@ ...@@ -21,75 +21,99 @@
# #
# #
# NOTE: this controller is a SAMPLE, and thus doesn't implement all the # NOTE: This controller is a SAMPLE, and thus doesn't use all the
# Media Player Remote Interface Specification (MPRIS for short) available at # Media Player Remote Interface Specification (MPRIS for short) capabilities
# http://wiki.xmms2.xmms.se/index.php/Media_Player_Interfaces #
# MPRIS: http://wiki.xmms2.xmms.se/index.php/Media_Player_Interfaces
# #
# You'll need pygtk >= 2.10 to use gtk.StatusIcon # You'll need pygtk >= 2.10 to use gtk.StatusIcon
# #
# TODO
# Ability to choose the Media Player if several are connected to the bus
# core dbus stuff
import dbus import dbus
import dbus.glib import dbus.glib
# core interface stuff
import gtk import gtk
import gtk.glade import gtk.glade
# timer
import gobject import gobject
# file loading
import os import os
global position global win_position # store the window position on the screen
global timer
global playing global playing
playing = False playing = False
global shuffle global shuffle # playlist will play randomly
global repeat global repeat # repeat the playlist
global loop global loop # loop the current element
#mpris doesn't support getting the status of these (at the moment)
# mpris doesn't support getting the status of these (at the moment)
shuffle = False shuffle = False
repeat = False repeat = False
loop = False loop = False
global root # these are defined on the mpris detected unique name
global player global root # / org.freedesktop.MediaPlayer
global tracklist global player # /Player org.freedesktop.MediaPlayer
global tracklist # /Tracklist org.freedesktop.MediaPlayer
global bus # Connection to the session bus
global identity # MediaPlayer Identity
global bus
def player_change(newname, a, b): # If a Media Player connects to the bus, we'll use it
if b != "" and "org.mpris." in newname: # Note that we forget the previous Media Player we were connected to
Connect(newname) def NameOwnerChanged(name, new, old):
if old != "" and "org.mpris." in name:
Connect(name)
def itemchange_handler(item): # Callback for when "TrackChange" signal is emitted
def TrackChange(Track):
# the only mandatory metadata is "URI"
try: try:
a = item["artist"] a = Track["artist"]
except: except:
a = "" a = ""
try: try:
t = item["title"] t = Track["title"]
except: except:
t = "" t = Track["URI"]
if t == "": # update the labels
t = item["URI"]
l_artist.set_text(a) l_artist.set_text(a)
l_title.set_text(t) l_title.set_text(t)
#find the first media player available # Connects to the Media Player we detected
def Connect(name): def Connect(name):
global root global root, player, tracklist
global player global playing, identity
global tracklist
global bus
global playing
# first we connect to the objects
root_o = bus.get_object(name, "/") root_o = bus.get_object(name, "/")
player_o = bus.get_object(name, "/Player") player_o = bus.get_object(name, "/Player")
tracklist_o = bus.get_object(name, "/TrackList") tracklist_o = bus.get_object(name, "/TrackList")
# there is only 1 interface per object
root = dbus.Interface(root_o, "org.freedesktop.MediaPlayer") root = dbus.Interface(root_o, "org.freedesktop.MediaPlayer")
tracklist = dbus.Interface(tracklist_o, "org.freedesktop.MediaPlayer") tracklist = dbus.Interface(tracklist_o, "org.freedesktop.MediaPlayer")
player = dbus.Interface(player_o, "org.freedesktop.MediaPlayer") player = dbus.Interface(player_o, "org.freedesktop.MediaPlayer")
player_o.connect_to_signal("TrackChange", itemchange_handler, dbus_interface="org.freedesktop.MediaPlayer")
# connect to the TrackChange signal
player_o.connect_to_signal("TrackChange", TrackChange, dbus_interface="org.freedesktop.MediaPlayer")
# determine if the Media Player is playing something
if player.GetStatus() == 0: if player.GetStatus() == 0:
playing = True playing = True
window.set_title(root.Identity())
# gets its identity (name and version)
identity = root.Identity()
window.set_title(identity)
#plays an element #plays an element
def AddTrack(widget): def AddTrack(widget):
...@@ -103,7 +127,8 @@ def AddTrack(widget): ...@@ -103,7 +127,8 @@ def AddTrack(widget):
tracklist.AddTrack("directory://" + mrl, True) tracklist.AddTrack("directory://" + mrl, True)
update(0) update(0)
#basic control # basic control
def Next(widget): def Next(widget):
player.Next(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) player.Next(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
update(0) update(0)
...@@ -116,36 +141,6 @@ def Stop(widget): ...@@ -116,36 +141,6 @@ def Stop(widget):
player.Stop(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) player.Stop(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
update(0) update(0)
#update status display
def update(widget):
item = tracklist.GetMetadata(tracklist.GetCurrentTrack())
vol.set_value(player.VolumeGet())
try:
a = item["artist"]
except: a = ""
try:
t = item["title"]
except: t = ""
if t == "":
try:
t = item["URI"]
except:
t = ""
l_artist.set_text(a)
l_title.set_text(t)
GetPlayStatus(0)
#get playing status from remote player
def GetPlayStatus(widget):
global playing
status = player.GetStatus()
if status == 0:
img_bt_toggle.set_from_stock("gtk-media-pause", gtk.ICON_SIZE_SMALL_TOOLBAR)
playing = True
else:
img_bt_toggle.set_from_stock("gtk-media-play", gtk.ICON_SIZE_SMALL_TOOLBAR)
playing = False
def Quit(widget): def Quit(widget):
player.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) player.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
l_title.set_text("") l_title.set_text("")
...@@ -174,58 +169,96 @@ def Loop(widget): ...@@ -174,58 +169,96 @@ def Loop(widget):
loop = not loop loop = not loop
tracklist.Loop(loop) tracklist.Loop(loop)
#callback for volume # update status display
def update(widget):
item = tracklist.GetMetadata(tracklist.GetCurrentTrack())
vol.set_value(player.VolumeGet())
try:
a = item["artist"]
except: a = ""
try:
t = item["title"]
except: t = ""
if t == "":
try:
t = item["URI"]
except:
t = ""
l_artist.set_text(a)
l_title.set_text(t)
GetPlayStatus(0)
# callback for volume change
def volchange(widget, data): def volchange(widget, data):
player.VolumeSet(vol.get_value_as_int(), reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) player.VolumeSet(vol.get_value_as_int(), reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
#callback for position change # callback for position change
def timechange(widget, x=None, y=None): def timechange(widget, x=None, y=None):
player.PositionSet(int(time_s.get_value()), reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) player.PositionSet(int(time_s.get_value()), reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
#refresh position # refresh position change
def timeset(): def timeset():
global playing global playing
if playing == True: if playing == True:
time_s.set_value(player.PositionGet()) time_s.set_value(player.PositionGet())
return True return True
#simple/full display # toggle simple/full display
def expander(widget): def expander(widget):
if exp.get_expanded() == False: if exp.get_expanded() == False:
exp.set_label("Less") exp.set_label("Less")
else: else:
exp.set_label("More") exp.set_label("More")
#close event # close event : hide in the systray
def delete_event(self, widget): def delete_event(self, widget):
self.hide() self.hide()
return True return True
# shouldn't happen
def destroy(widget): def destroy(widget):
gtk.main_quit() gtk.main_quit()
# hide the controller when 'Esc' is pressed
def key_release(widget, event): def key_release(widget, event):
global position
if event.keyval == gtk.keysyms.Escape: if event.keyval == gtk.keysyms.Escape:
position = window.get_position() global win_position
win_position = window.get_position()
widget.hide() widget.hide()
#click on the tray icon # callback for click on the tray icon
def tray_button(widget): def tray_button(widget):
global position global win_position
if window.get_property('visible'): if window.get_property('visible'):
position = window.get_position() # store position
win_position = window.get_position()
window.hide() window.hide()
else: else:
window.move(position[0], position[1]) # restore position
window.move(win_position[0], win_position[1])
window.show() window.show()
#loads glade file from the directory where the script is, # hack: update position, volume, and metadata
#so we can use /path/to/mpris.py to execute it. def icon_clicked(widget, event):
update(0)
# get playing status, modify the Play/Pause button accordingly
def GetPlayStatus(widget):
global playing
status = player.GetStatus()
if status == 0:
img_bt_toggle.set_from_stock("gtk-media-pause", gtk.ICON_SIZE_SMALL_TOOLBAR)
playing = True
else:
img_bt_toggle.set_from_stock("gtk-media-play", gtk.ICON_SIZE_SMALL_TOOLBAR)
playing = False
# loads glade file from the directory where the script is,
# so we can use /path/to/mpris.py to execute it.
import sys import sys
xml = gtk.glade.XML(os.path.dirname(sys.argv[0]) + '/mpris.glade') xml = gtk.glade.XML(os.path.dirname(sys.argv[0]) + '/mpris.glade')
#ui setup # ui setup
bt_close = xml.get_widget('close') bt_close = xml.get_widget('close')
bt_quit = xml.get_widget('quit') bt_quit = xml.get_widget('quit')
bt_file = xml.get_widget('ChooseFile') bt_file = xml.get_widget('ChooseFile')
...@@ -249,6 +282,8 @@ vol = xml.get_widget('vol') ...@@ -249,6 +282,8 @@ vol = xml.get_widget('vol')
time_s = xml.get_widget('time_s') time_s = xml.get_widget('time_s')
time_l = xml.get_widget('time_l') time_l = xml.get_widget('time_l')
# connect to the different callbacks
window.connect('delete_event', delete_event) window.connect('delete_event', delete_event)
window.connect('destroy', destroy) window.connect('destroy', destroy)
window.connect('key_release_event', key_release) window.connect('key_release_event', key_release)
...@@ -256,9 +291,6 @@ window.connect('key_release_event', key_release) ...@@ -256,9 +291,6 @@ window.connect('key_release_event', key_release)
tray = gtk.status_icon_new_from_icon_name("audio-x-generic") tray = gtk.status_icon_new_from_icon_name("audio-x-generic")
tray.connect('activate', tray_button) tray.connect('activate', tray_button)
def icon_clicked(widget, event):
update(0)
bt_close.connect('clicked', destroy) bt_close.connect('clicked', destroy)
bt_quit.connect('clicked', Quit) bt_quit.connect('clicked', Quit)
bt_mrl.connect('clicked', AddTrack) bt_mrl.connect('clicked', AddTrack)
...@@ -273,54 +305,50 @@ exp.connect('activate', expander) ...@@ -273,54 +305,50 @@ exp.connect('activate', expander)
vol.connect('change-value', volchange) vol.connect('change-value', volchange)
vol.connect('scroll-event', volchange) vol.connect('scroll-event', volchange)
time_s.connect('adjust-bounds', timechange) time_s.connect('adjust-bounds', timechange)
audioicon.set_events(gtk.gdk.BUTTON_PRESS_MASK) audioicon.set_events(gtk.gdk.BUTTON_PRESS_MASK) # hack for the bottom right icon
audioicon.connect('button_press_event', icon_clicked) audioicon.connect('button_press_event', icon_clicked)
time_s.set_update_policy(gtk.UPDATE_DISCONTINUOUS) time_s.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
library = "/media/mp3" #editme library = "/media/mp3" # editme
# set the Directory chooser to a default location
try: try:
os.chdir(library) os.chdir(library)
bt_file.set_current_folder(library) bt_file.set_current_folder(library)
except: except:
bt_file.set_current_folder(os.path.expanduser("~")) bt_file.set_current_folder(os.path.expanduser("~"))
#connect to the bus # connect to the bus
bus = dbus.SessionBus() bus = dbus.SessionBus()
dbus_names = bus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" ) dbus_names = bus.get_object( "org.freedesktop.DBus", "/org/freedesktop/DBus" )
dbus_names.connect_to_signal("NameOwnerChanged", player_change, dbus_interface="org.freedesktop.DBus") dbus_names.connect_to_signal("NameOwnerChanged", NameOwnerChanged, dbus_interface="org.freedesktop.DBus") # to detect new Media Players
dbus_o = bus.get_object("org.freedesktop.DBus", "/") dbus_o = bus.get_object("org.freedesktop.DBus", "/")
dbus_intf = dbus.Interface(dbus_o, "org.freedesktop.DBus") dbus_intf = dbus.Interface(dbus_o, "org.freedesktop.DBus")
name_list = dbus_intf.ListNames() name_list = dbus_intf.ListNames()
name = ""
# connect to the first Media Player found
for n in name_list: for n in name_list:
if "org.mpris." in n: if "org.mpris." in n:
name = n Connect(n)
break window.set_title(identity)
if name != "":
Connect(name)
window.set_title(root.Identity())
vol.set_value(player.VolumeGet()) vol.set_value(player.VolumeGet())
update(0)
break
#runs timer to update position # run a timer to update position
gobject.timeout_add( 1000, timeset) gobject.timeout_add( 1000, timeset)
window.set_icon_name('audio-x-generic') window.set_icon_name('audio-x-generic')
window.show() window.show()
try:
update(0)
except:
True
icon_theme = gtk.icon_theme_get_default() icon_theme = gtk.icon_theme_get_default()
try: try:
pix = icon_theme.load_icon("audio-x-generic",24,0) pix = icon_theme.load_icon("audio-x-generic",24,0)
window.set_icon(pix) window.set_icon(pix)
except: except:
True True
position = window.get_position()
gtk.main() win_position = window.get_position()
gtk.main() # execute the main loop
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment