Commit 12f9e10c authored by Rafaël Carré's avatar Rafaël Carré

mpris.py: update to mpris 2.1

loop/repeat controls are gone, we now need a tri-state button
track change signal doesn't exist anymore in mpris 2.1 and i can't find how
we can be notified of track changes
parent a0de10de
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf8 -*- # -*- coding: utf8 -*-
# #
# Copyright © 2006-2007 Rafaël Carré <funman at videolanorg> # Copyright © 2006-2011 Rafaël Carré <funman at videolanorg>
# #
# $Id$
#
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or # the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version. # (at your option) any later version.
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
...@@ -24,9 +22,9 @@ ...@@ -24,9 +22,9 @@
# NOTE: This controller is a SAMPLE, and thus doesn't use all the # NOTE: This controller is a SAMPLE, and thus doesn't use all the
# Media Player Remote Interface Specification (MPRIS for short) capabilities # Media Player Remote Interface Specification (MPRIS for short) capabilities
# #
# MPRIS: http://wiki.xmms2.xmms.se/index.php/Media_Player_Interfaces # MPRIS: http://www.mpris.org/2.1/spec/
# #
# You'll need pygtk >= 2.10 to use gtk.StatusIcon # You'll need pygtk >= 2.12
# #
# TODO # TODO
# Ability to choose the Media Player if several are connected to the bus # Ability to choose the Media Player if several are connected to the bus
...@@ -39,7 +37,7 @@ import dbus.glib ...@@ -39,7 +37,7 @@ import dbus.glib
import gtk import gtk
# timer # timer
import gobject from gobject import timeout_add
# file loading # file loading
import os import os
...@@ -49,47 +47,47 @@ global win_position # store the window position on the screen ...@@ -49,47 +47,47 @@ global win_position # store the window position on the screen
global playing global playing
playing = False playing = False
global shuffle # playlist will play randomly global shuffle
global repeat # repeat the playlist
global loop # loop the current element
# mpris doesn't support getting the status of these (at the moment) global root
shuffle = False global player
repeat = False global tracklist
loop = False global props
# these are defined on the mpris detected unique name
global root # / org.freedesktop.MediaPlayer
global player # /Player org.freedesktop.MediaPlayer
global tracklist # /Tracklist org.freedesktop.MediaPlayer
global bus # Connection to the session bus global bus # Connection to the session bus
global identity # MediaPlayer Identity
mpris='org.mpris.MediaPlayer2'
# If a Media Player connects to the bus, we'll use it # If a Media Player connects to the bus, we'll use it
# Note that we forget the previous Media Player we were connected to # Note that we forget the previous Media Player we were connected to
def NameOwnerChanged(name, new, old): def NameOwnerChanged(name, new, old):
if old != "" and "org.mpris." in name: if old != '' and mpris in name:
Connect(name) Connect(name)
# Callback for when "TrackChange" signal is emitted def PropGet(prop):
global props
return props.Get(mpris + '.Player', prop)
def PropSet(prop, val):
global props
props.Set(mpris + '.Player', prop, val)
# Callback for when 'TrackChange' signal is emitted
def TrackChange(Track): def TrackChange(Track):
# the only mandatory metadata is "location"
try: try:
a = Track["artist"] a = Track['xesam:artist']
except: except:
a = "" a = ''
try: try:
t = Track["title"] t = Track['xesam:title']
except: except:
t = Track["location"] t = Track['xesam:url']
try: try:
length = Track["length"] length = Track['mpris:length']
except: except:
length = 0 length = 0
if length > 0: if length > 0:
time_s.set_range(0,Track["length"]) time_s.set_range(0, length)
time_s.set_sensitive(True) time_s.set_sensitive(True)
else: else:
# disable the position scale if length isn't available # disable the position scale if length isn't available
...@@ -100,41 +98,36 @@ def TrackChange(Track): ...@@ -100,41 +98,36 @@ def TrackChange(Track):
# Connects to the Media Player we detected # Connects to the Media Player we detected
def Connect(name): def Connect(name):
global root, player, tracklist global root, player, tracklist, props
global playing, identity global playing, shuffle
# first we connect to the objects
root_o = bus.get_object(name, "/")
player_o = bus.get_object(name, "/Player")
tracklist_o = bus.get_object(name, "/TrackList")
# there is only 1 interface per object root_o = bus.get_object(name, '/org/mpris/MediaPlayer2')
root = dbus.Interface(root_o, "org.freedesktop.MediaPlayer") root = dbus.Interface(root_o, mpris)
tracklist = dbus.Interface(tracklist_o, "org.freedesktop.MediaPlayer") tracklist = dbus.Interface(root_o, mpris + '.TrackList')
player = dbus.Interface(player_o, "org.freedesktop.MediaPlayer") player = dbus.Interface(root_o, mpris + '.Player')
props = dbus.Interface(root_o, dbus.PROPERTIES_IFACE)
# FIXME : doesn't exist anymore in mpris 2.1
# connect to the TrackChange signal # connect to the TrackChange signal
player_o.connect_to_signal("TrackChange", TrackChange, dbus_interface="org.freedesktop.MediaPlayer") # root_o.connect_to_signal('TrackChange', TrackChange, dbus_interface=mpris)
# determine if the Media Player is playing something # determine if the Media Player is playing something
if player.GetStatus() == 0: if PropGet('PlaybackStatus') == 'Playing':
playing = True playing = True
TrackChange(player.GetMetadata()) TrackChange(PropGet('Metadata'))
# gets its identity (name and version) window.set_title(props.Get(mpris, 'Identity'))
identity = root.Identity()
window.set_title(identity)
#plays an element #plays an element
def AddTrack(widget): def AddTrack(widget):
mrl = e_mrl.get_text() mrl = e_mrl.get_text()
if mrl != None and mrl != "": if mrl != None and mrl != '':
tracklist.AddTrack(mrl, True) tracklist.AddTrack(mrl, '/', True)
e_mrl.set_text('') e_mrl.set_text('')
else: else:
mrl = bt_file.get_filename() mrl = bt_file.get_filename()
if mrl != None and mrl != "": if mrl != None and mrl != '':
tracklist.AddTrack("directory://" + mrl, True) tracklist.AddTrack('directory://' + mrl, '/', True)
update(0) update(0)
# basic control # basic control
...@@ -152,78 +145,50 @@ def Stop(widget): ...@@ -152,78 +145,50 @@ def Stop(widget):
update(0) update(0)
def Quit(widget): def Quit(widget):
root.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) global props
l_title.set_text("") if props.Get(mpris, 'CanQuit'):
root.Quit(reply_handler=(lambda *args: None), error_handler=(lambda *args: None))
l_title.set_text('')
window.set_title('')
def Pause(widget): def Pause(widget):
player.Pause() player.PlayPause()
status = player.GetStatus() if PropGet('PlaybackStatus') == 'Playing':
if status == 0: icon = gtk.STOCK_MEDIA_PAUSE
img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PAUSE, gtk.ICON_SIZE_SMALL_TOOLBAR)
else: else:
img_bt_toggle.set_from_stock(gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_SMALL_TOOLBAR) icon = gtk.STOCK_MEDIA_PLAY
img_bt_toggle.set_from_stock(icon, gtk.ICON_SIZE_SMALL_TOOLBAR)
update(0) update(0)
def Repeat(widget):
global repeat
repeat = not repeat
player.Repeat(repeat)
def Shuffle(widget): def Shuffle(widget):
global shuffle global shuffle
shuffle = not shuffle shuffle = not shuffle
tracklist.SetRandom(shuffle) PropSet('Shuffle', shuffle)
def Loop(widget):
global loop
loop = not loop
tracklist.SetLoop(loop)
# update status display # update status display
def update(widget): def update(widget):
Track = player.GetMetadata() Track = PropGet('Metadata')
vol.set_value(player.VolumeGet()) vol.set_value(PropGet('Volume') * 100.0)
try: TrackChange(Track)
a = Track["artist"]
except:
a = ""
try:
t = Track["title"]
except:
t = ""
if t == "":
try:
t = Track["location"]
except:
t = ""
l_artist.set_text(a)
l_title.set_text(t)
try:
length = Track["length"]
except:
length = 0
if length > 0:
time_s.set_range(0,Track["length"])
time_s.set_sensitive(True)
else:
# disable the position scale if length isn't available
time_s.set_sensitive(False)
GetPlayStatus(0) GetPlayStatus(0)
# callback for volume change # callback for volume change
def volchange(widget): def volchange(widget):
player.VolumeSet(vol.get_value_as_int(), reply_handler=(lambda *args: None), error_handler=(lambda *args: None)) PropSet('Volume', vol.get_value_as_int() / 100.0)
# 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.SetPosition(PropGet('Metadata')['mpris:trackid'],
time_s.get_value(),
reply_handler=(lambda *args: None),
error_handler=(lambda *args: None))
# refresh position change # refresh position change
def timeset(): def timeset():
global playing global playing
if playing == True: if playing == True:
try: try:
time_s.set_value(player.PositionGet()) time_s.set_value(PropGet('Position'))
except: except:
playing = False playing = False
return True return True
...@@ -231,9 +196,9 @@ def timeset(): ...@@ -231,9 +196,9 @@ def timeset():
# toggle 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 : hide in the systray # close event : hide in the systray
def delete_event(self, widget): def delete_event(self, widget):
...@@ -271,21 +236,15 @@ def icon_clicked(widget, event): ...@@ -271,21 +236,15 @@ def icon_clicked(widget, event):
def GetPlayStatus(widget): def GetPlayStatus(widget):
global playing global playing
global shuffle global shuffle
global loop
global repeat
status = player.GetStatus()
playing = status[0] == 0 playing = PropGet('PlaybackStatus') == 'Playing'
if playing: if playing:
img_bt_toggle.set_from_stock("gtk-media-pause", gtk.ICON_SIZE_SMALL_TOOLBAR) img_bt_toggle.set_from_stock('gtk-media-pause', gtk.ICON_SIZE_SMALL_TOOLBAR)
else: else:
img_bt_toggle.set_from_stock("gtk-media-play", gtk.ICON_SIZE_SMALL_TOOLBAR) img_bt_toggle.set_from_stock('gtk-media-play', gtk.ICON_SIZE_SMALL_TOOLBAR)
shuffle = status[1] == 1 shuffle = PropGet('Shuffle')
bt_shuffle.set_active( shuffle ) bt_shuffle.set_active( shuffle )
loop = status[2] == 1
bt_loop.set_active( loop )
repeat = status[3] == 1
bt_repeat.set_active( repeat )
# loads UI file from the directory where the script is, # loads UI file from the directory where the script is,
# so we can use /path/to/mpris.py to execute it. # so we can use /path/to/mpris.py to execute it.
import sys import sys
...@@ -302,8 +261,6 @@ bt_stop = xml.get_object('stop') ...@@ -302,8 +261,6 @@ bt_stop = xml.get_object('stop')
bt_toggle = xml.get_object('toggle') bt_toggle = xml.get_object('toggle')
bt_mrl = xml.get_object('AddMRL') bt_mrl = xml.get_object('AddMRL')
bt_shuffle = xml.get_object('shuffle') bt_shuffle = xml.get_object('shuffle')
bt_repeat = xml.get_object('repeat')
bt_loop = xml.get_object('loop')
l_artist = xml.get_object('l_artist') l_artist = xml.get_object('l_artist')
l_title = xml.get_object('l_title') l_title = xml.get_object('l_title')
e_mrl = xml.get_object('mrl') e_mrl = xml.get_object('mrl')
...@@ -322,7 +279,7 @@ window.connect('delete_event', delete_event) ...@@ -322,7 +279,7 @@ 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)
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)
bt_close.connect('clicked', destroy) bt_close.connect('clicked', destroy)
...@@ -332,56 +289,46 @@ bt_toggle.connect('clicked', Pause) ...@@ -332,56 +289,46 @@ bt_toggle.connect('clicked', Pause)
bt_next.connect('clicked', Next) bt_next.connect('clicked', Next)
bt_prev.connect('clicked', Prev) bt_prev.connect('clicked', Prev)
bt_stop.connect('clicked', Stop) bt_stop.connect('clicked', Stop)
bt_loop.connect('clicked', Loop)
bt_repeat.connect('clicked', Repeat)
bt_shuffle.connect('clicked', Shuffle) bt_shuffle.connect('clicked', Shuffle)
exp.connect('activate', expander) exp.connect('activate', expander)
vol.connect('changed', volchange) vol.connect('changed', volchange)
time_s.connect('adjust-bounds', timechange) time_s.connect('adjust-bounds', timechange)
audioicon.set_events(gtk.gdk.BUTTON_PRESS_MASK) # hack for the bottom right icon 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 # 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", NameOwnerChanged, dbus_interface="org.freedesktop.DBus") # to detect new Media Players 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()
# connect to the first Media Player found # connect to the first Media Player found
for n in name_list: for n in dbus_intf.ListNames():
if "org.mpris." in n: if mpris in n:
Connect(n) Connect(n)
window.set_title(identity) vol.set_value(PropGet('Volume') * 100.0)
vol.set_value(player.VolumeGet())
update(0) update(0)
break break
# run a timer to update position # run a timer to update position
gobject.timeout_add( 1000, timeset) timeout_add( 1000, timeset)
window.set_icon_name('audio-x-generic') window.set_icon_name('audio-x-generic')
window.show() window.show()
icon_theme = gtk.icon_theme_get_default() window.set_icon(gtk.icon_theme_get_default().load_icon('audio-x-generic',24,0))
try:
pix = icon_theme.load_icon("audio-x-generic",24,0)
window.set_icon(pix)
except:
True
win_position = window.get_position() win_position = window.get_position()
gtk.main() # execute the main loop gtk.main() # execute the main loop
<?xml version="1.0"?> <?xml version="1.0" encoding="UTF-8"?>
<!--Generated with glade3 3.3.4 on Fri Sep 14 02:55:34 2007 -->
<interface> <interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkAdjustment" id="adjustment1"> <object class="GtkAdjustment" id="adjustment1">
<property name="upper">1000</property> <property name="upper">1000</property>
<property name="lower">0</property>
<property name="page_increment">100</property>
<property name="step_increment">10</property> <property name="step_increment">10</property>
<property name="page_size">0</property> <property name="page_increment">100</property>
<property name="value">0</property>
</object> </object>
<object class="GtkAdjustment" id="adjustment2"> <object class="GtkAdjustment" id="adjustment2">
<property name="upper">100</property> <property name="upper">100</property>
<property name="lower">0</property>
<property name="page_increment">10</property>
<property name="step_increment">1</property>
<property name="page_size">0</property>
<property name="value">100</property> <property name="value">100</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object> </object>
<object class="GtkWindow" id="window1"> <object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="resizable">False</property> <property name="resizable">False</property>
<property name="window_position">GTK_WIN_POS_CENTER</property> <property name="window_position">center</property>
<child> <child>
<object class="GtkVBox" id="vbox1"> <object class="GtkVBox" id="vbox1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkHBox" id="hbox1"> <object class="GtkHBox" id="hbox1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property> <property name="homogeneous">True</property>
<child> <child>
<object class="GtkButton" id="prev"> <object class="GtkButton" id="prev">
<property name="width_request">37</property> <property name="width_request">37</property>
<property name="height_request">37</property> <property name="height_request">37</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Previous</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Previous</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image8"> <object class="GtkImage" id="image8">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-previous</property> <property name="stock">gtk-media-previous</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
...@@ -50,16 +55,21 @@ ...@@ -50,16 +55,21 @@
<property name="width_request">37</property> <property name="width_request">37</property>
<property name="height_request">37</property> <property name="height_request">37</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Play/Pause</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Play/Pause</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image6"> <object class="GtkImage" id="image6">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-play</property> <property name="stock">gtk-media-play</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
...@@ -69,16 +79,21 @@ ...@@ -69,16 +79,21 @@
<property name="width_request">37</property> <property name="width_request">37</property>
<property name="height_request">37</property> <property name="height_request">37</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Next</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Next</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image1"> <object class="GtkImage" id="image1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-next</property> <property name="stock">gtk-media-next</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">2</property> <property name="position">2</property>
</packing> </packing>
...@@ -88,11 +103,15 @@ ...@@ -88,11 +103,15 @@
<property name="width_request">37</property> <property name="width_request">37</property>
<property name="height_request">37</property> <property name="height_request">37</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Stop</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Stop</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image9"> <object class="GtkImage" id="image9">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-media-stop</property> <property name="stock">gtk-media-stop</property>
</object> </object>
</child> </child>
...@@ -108,18 +127,23 @@ ...@@ -108,18 +127,23 @@
<property name="width_request">37</property> <property name="width_request">37</property>
<property name="height_request">37</property> <property name="height_request">37</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Quit Player</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Quit Player</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image5"> <object class="GtkImage" id="image5">
<property name="width_request">26</property> <property name="width_request">26</property>
<property name="height_request">26</property> <property name="height_request">26</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-quit</property> <property name="stock">gtk-quit</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
...@@ -129,142 +153,119 @@ ...@@ -129,142 +153,119 @@
<property name="width_request">37</property> <property name="width_request">37</property>
<property name="height_request">37</property> <property name="height_request">37</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Close controller</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Close controller</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image2"> <object class="GtkImage" id="image2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-close</property> <property name="stock">gtk-close</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">5</property> <property name="position">5</property>
</packing> </packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkExpander" id="expander2"> <object class="GtkExpander" id="expander2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Show more options</property> <property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Show more options</property>
<child> <child>
<object class="GtkVBox" id="vbox2"> <object class="GtkVBox" id="vbox2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkHBox" id="hbox5"> <object class="GtkHBox" id="hbox5">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child> <child>
<object class="GtkToggleButton" id="loop"> <object class="GtkToggleButton" id="shuffle">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="tooltip-text" translatable="yes">Loop playlist</property> <property name="tooltip_text" translatable="yes">Randomize playlist order</property>
<property name="use_action_appearance">False</property>
<child> <child>
<object class="GtkImage" id="image3"> <object class="GtkImage" id="image7">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-missing-image</property> <property name="stock">gtk-missing-image</property>
<property name="icon_name">media-playlist-repeat</property> <property name="icon_name">media-playlist-shuffle</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkToggleButton" id="repeat">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="tooltip-text" translatable="yes">Repeat current</property>
<child>
<object class="GtkHBox" id="hbox6">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">1.</property>
</object>
</child>
<child>
<object class="GtkImage" id="image10">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="stock">gtk-missing-image</property>
<property name="icon_name">media-playlist-repeat</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="position">1</property> <property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkToggleButton" id="shuffle"> <object class="GtkSpinButton" id="vol">
<property name="width_request">52</property>
<property name="height_request">20</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">True</property> <property name="editable">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="invisible_char"></property>
<property name="tooltip-text" translatable="yes">Randomize playlist order</property> <property name="primary_icon_activatable">False</property>
<child> <property name="secondary_icon_activatable">False</property>
<object class="GtkImage" id="image7"> <property name="primary_icon_sensitive">True</property>
<property name="visible">True</property> <property name="secondary_icon_sensitive">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="adjustment">adjustment2</property>
<property name="stock">gtk-missing-image</property> <property name="snap_to_ticks">True</property>
<property name="icon_name">media-playlist-shuffle</property> <property name="numeric">True</property>
</object> <property name="update_policy">if-valid</property>
</child>
</object> </object>
<packing> <packing>
<property name="position">2</property> <property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing> </packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkHBox" id="hbox2"> <object class="GtkHBox" id="hbox2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkHScale" id="time_s"> <object class="GtkHScale" id="time_s">
<property name="width_request">180</property> <property name="width_request">180</property>
<property name="height_request">20</property> <property name="height_request">20</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="adjustment">adjustment1</property> <property name="adjustment">adjustment1</property>
<property name="digits">-1</property> <property name="digits">-1</property>
<property name="draw_value">False</property> <property name="draw_value">False</property>
<property name="value_pos">GTK_POS_RIGHT</property> <property name="value_pos">right</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="vol">
<property name="width_request">42</property>
<property name="height_request">20</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="tooltip-text" translatable="yes">Volume in %</property>
<property name="editable">False</property>
<property name="adjustment">adjustment2</property>
<property name="snap_to_ticks">True</property>
<property name="numeric">True</property>
<property name="update_policy">GTK_UPDATE_IF_VALID</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">False</property>
<property name="position">1</property> <property name="position">0</property>
</packing> </packing>
</child> </child>
</object> </object>
...@@ -277,25 +278,38 @@ ...@@ -277,25 +278,38 @@
<child> <child>
<object class="GtkHBox" id="hbox4"> <object class="GtkHBox" id="hbox4">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkVBox" id="expandvbox"> <object class="GtkVBox" id="expandvbox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkFileChooserButton" id="ChooseFile"> <object class="GtkFileChooserButton" id="ChooseFile">
<property name="width_request">185</property> <property name="width_request">185</property>
<property name="height_request">35</property> <property name="height_request">35</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Choose a directory</property> <property name="can_focus">False</property>
<property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property> <property name="tooltip_text" translatable="yes">Choose a directory</property>
<property name="action">select-folder</property>
<property name="title" translatable="yes">Select Da Directory !</property> <property name="title" translatable="yes">Select Da Directory !</property>
</object> </object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="mrl"> <object class="GtkEntry" id="mrl">
<property name="width_request">185</property> <property name="width_request">185</property>
<property name="height_request">20</property> <property name="height_request">20</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Enter a full MRL</property> <property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Enter a full MRL</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
...@@ -304,23 +318,33 @@ ...@@ -304,23 +318,33 @@
</packing> </packing>
</child> </child>
</object> </object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkFixed" id="fixed1"> <object class="GtkFixed" id="fixed1">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkButton" id="AddMRL"> <object class="GtkButton" id="AddMRL">
<property name="width_request">35</property> <property name="width_request">35</property>
<property name="height_request">35</property> <property name="height_request">35</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Add MRL, or directory if empty</property> <property name="can_focus">False</property>
<property name="relief">GTK_RELIEF_NONE</property> <property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Add MRL, or directory if empty</property>
<property name="use_action_appearance">False</property>
<property name="relief">none</property>
<child> <child>
<object class="GtkImage" id="image4"> <object class="GtkImage" id="image4">
<property name="width_request">100</property> <property name="width_request">100</property>
<property name="height_request">80</property> <property name="height_request">80</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="tooltip-text" translatable="yes">Add to playlist</property> <property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Add to playlist</property>
<property name="stock">gtk-add</property> <property name="stock">gtk-add</property>
</object> </object>
</child> </child>
...@@ -331,11 +355,15 @@ ...@@ -331,11 +355,15 @@
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property> <property name="position">2</property>
</packing> </packing>
</child> </child>
...@@ -344,48 +372,64 @@ ...@@ -344,48 +372,64 @@
<property name="width_request">180</property> <property name="width_request">180</property>
<property name="height_request">20</property> <property name="height_request">20</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="justify">GTK_JUSTIFY_CENTER</property> <property name="can_focus">False</property>
<property name="justify">center</property>
<property name="wrap">True</property> <property name="wrap">True</property>
<property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property> <property name="ellipsize">middle</property>
<property name="single_line_mode">True</property> <property name="single_line_mode">True</property>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkHBox" id="hbox3"> <object class="GtkHBox" id="hbox3">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkLabel" id="l_title"> <object class="GtkLabel" id="l_title">
<property name="width_request">180</property> <property name="width_request">180</property>
<property name="height_request">20</property> <property name="height_request">20</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="justify">GTK_JUSTIFY_CENTER</property> <property name="can_focus">False</property>
<property name="justify">center</property>
<property name="wrap">True</property> <property name="wrap">True</property>
<property name="ellipsize">PANGO_ELLIPSIZE_MIDDLE</property> <property name="ellipsize">middle</property>
<property name="single_line_mode">True</property> <property name="single_line_mode">True</property>
</object> </object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child> </child>
<child> <child>
<object class="GtkEventBox" id="eventicon"> <object class="GtkEventBox" id="eventicon">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<child> <child>
<object class="GtkImage" id="audioicon"> <object class="GtkImage" id="audioicon">
<property name="visible">True</property> <property name="visible">True</property>
<property name="events"/> <property name="can_focus">False</property>
<property name="tooltip-text" translatable="yes">Update meta info</property> <property name="events"></property>
<property name="tooltip_text" translatable="yes">Update meta info</property>
<property name="xpad">8</property> <property name="xpad">8</property>
<property name="icon_name">audio-x-generic</property> <property name="icon_name">audio-x-generic</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
...@@ -394,11 +438,14 @@ ...@@ -394,11 +438,14 @@
<child type="label"> <child type="label">
<object class="GtkLabel" id="label2"> <object class="GtkLabel" id="label2">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">More</property> <property name="label" translatable="yes">More</property>
</object> </object>
</child> </child>
</object> </object>
<packing> <packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
......
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