Merge lp:~u-milan/dockmanager/audacious_helper into lp:dockmanager

Proposed by Milán Unicsovics
Status: Superseded
Proposed branch: lp:~u-milan/dockmanager/audacious_helper
Merge into: lp:dockmanager
Diff against target: 341 lines (+328/-0) (has conflicts)
2 files modified
metadata/audacious.py.info (+7/-0)
scripts/audacious.py (+321/-0)
Conflict adding file metadata.  Moved existing file to metadata.moved.
Conflict adding file scripts.  Moved existing file to scripts.moved.
To merge this branch: bzr merge lp:~u-milan/dockmanager/audacious_helper
Reviewer Review Type Date Requested Status
Dockers Pending
Review via email: mp+44956@code.launchpad.net

This proposal has been superseded by a proposal from 2011-01-01.

To post a comment you must log in.
3. By Milán Unicsovics

remove badge when playing stoppped

4. By Milán Unicsovics

merge trunk

Unmerged revisions

4. By Milán Unicsovics

merge trunk

3. By Milán Unicsovics

remove badge when playing stoppped

2. By Milán Unicsovics

merge trunk

1. By Milán Unicsovics

setup

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'metadata'
2=== renamed directory 'metadata' => 'metadata.moved'
3=== added file 'metadata/audacious.py.info'
4--- metadata/audacious.py.info 1970-01-01 00:00:00 +0000
5+++ metadata/audacious.py.info 2011-01-01 17:25:13 +0000
6@@ -0,0 +1,7 @@
7+[DockmanagerHelper]
8+Name=Audacious
9+Description=Control Audacious media playback
10+Icon=audacious
11+AppName=audacious2
12+DBusName=org.mpris.audacious
13+
14
15=== added directory 'scripts'
16=== renamed directory 'scripts' => 'scripts.moved'
17=== added file 'scripts/audacious.py'
18--- scripts/audacious.py 1970-01-01 00:00:00 +0000
19+++ scripts/audacious.py 2011-01-01 17:25:13 +0000
20@@ -0,0 +1,321 @@
21+#!/usr/bin/env python
22+#
23+# Copyright (C) 2010, Milan Unicsovics, <u.milan@gmail.com>
24+#
25+# This program is free software: you can redistribute it and/or modify
26+# it under the terms of the GNU General Public License as published by
27+# the Free Software Foundation, either version 3 of the License, or
28+# (at your option) any later version.
29+#
30+# This program is distributed in the hope that it will be useful,
31+# but WITHOUT ANY WARRANTY; without even the implied warranty of
32+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33+# GNU General Public License for more details.
34+#
35+# You should have received a copy of the GNU General Public License
36+# along with this program. If not, see <http://www.gnu.org/licenses/>.
37+#
38+
39+import atexit
40+import gobject
41+import glib
42+import dbus
43+from dbus import glib
44+from dbus import Bus, DBusException
45+import sys
46+import os
47+import gtk
48+from commands import getoutput
49+
50+try:
51+ from dockmanager.dockmanager import DockManagerItem, DockManagerSink, DOCKITEM_IFACE, RESOURCESDIR
52+ from signal import signal, SIGTERM
53+ from sys import exit
54+except ImportError, e:
55+ print e
56+ exit()
57+
58+
59+audaciousbus = 'org.mpris.audacious'
60+playerpath = '/Player'
61+playeriface = 'org.freedesktop.MediaPlayer'
62+
63+controlpath = '/org/atheme/audacious'
64+controliface = 'org.atheme.audacious'
65+
66+enable_badge_text = True;
67+enable_art_icon = True;
68+
69+AUDTOOL="/usr/bin/audtool"
70+
71+coverlist=['cover.jpg','cover.gif','cover.png','folder.jpg','folder.gif','folder.png']
72+
73+# 0 - none, 1- jewel, 2 - vinyl)
74+overlay = 2
75+
76+album_art_tmpfile = "/tmp/dockmanager_%s_audacious_helper.png" % os.getenv('USERNAME')
77+
78+class AudaciousItem(DockManagerItem):
79+ def __init__(self, sink, path):
80+ DockManagerItem.__init__(self, sink, path)
81+ self.timer = 0
82+ self.player = None
83+ self.control = None
84+
85+ self.duration_secs = 0
86+ self.songinfo = None
87+ self.clear_menu_buttons();
88+
89+ self.bus.add_signal_receiver(self.name_owner_changed_cb,
90+ dbus_interface='org.freedesktop.DBus',
91+ signal_name='NameOwnerChanged')
92+
93+ obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
94+ self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
95+
96+ self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
97+
98+ self.bus.add_signal_receiver(self.signal_TrackChange, "TrackChange", playeriface, audaciousbus, playerpath)
99+ self.bus.add_signal_receiver(self.signal_StatusChange, "StatusChange", playeriface, audaciousbus, playerpath)
100+
101+
102+ def list_names_handler(self, names):
103+ if audaciousbus in names:
104+ self.init_audacious_objects()
105+ self.set_menu_buttons()
106+ self.update_text()
107+ self.update_badge()
108+ self.update_icon()
109+
110+ def list_names_error_handler(self, error):
111+ print "error getting bus names - %s" % str(error)
112+
113+ def name_owner_changed_cb(self, name, old_owner, new_owner):
114+ if name == audaciousbus:
115+ if new_owner:
116+ self.init_audacious_objects()
117+ else:
118+ self.player = None
119+ self.control = None
120+ self.stop_timer()
121+ self.set_menu_buttons()
122+ self.update_text()
123+ self.update_badge()
124+ self.update_icon()
125+
126+ def start_timer(self):
127+ if not self.timer > 0:
128+ self.timer = gobject.timeout_add (1000, self.update_badge)
129+
130+ def stop_timer(self):
131+ if self.timer > 0:
132+ gobject.source_remove (self.timer)
133+ self.timer = 0
134+
135+ def init_audacious_objects(self):
136+ obj = self.bus.get_object(audaciousbus, playerpath)
137+ self.player = dbus.Interface(obj, playeriface)
138+ obj = self.bus.get_object(audaciousbus, controlpath)
139+ self.control = dbus.Interface(obj, controliface)
140+
141+ if self.player:
142+ self.update_songinfo()
143+
144+ if self.audacious_is_playing():
145+ self.start_timer()
146+
147+ def clear_menu_buttons(self):
148+ for k in self.id_map.keys():
149+ self.remove_menu_item(k)
150+
151+ def set_menu_buttons(self):
152+ self.clear_menu_buttons()
153+
154+ if not self.player:
155+ return
156+
157+ try:
158+ status=self.player.GetStatus()
159+ except:
160+ return
161+
162+ self.add_menu_item("Previous", "media-skip-backward")
163+ if status[0]==2:
164+ self.add_menu_item("Play", "media-playback-start")
165+ else:
166+ if self.audacious_is_playing():
167+ self.add_menu_item("Play/Pause", "media-playback-pause")
168+ else:
169+ self.add_menu_item("Play/Pause", "media-playback-start")
170+ self.add_menu_item("Next", "media-skip-forward")
171+
172+ def menu_pressed(self, menu_id):
173+ if not self.player:
174+ return False
175+
176+ if self.id_map[menu_id] == "Play/Pause":
177+ self.player.Pause()
178+ elif self.id_map[menu_id] == "Play":
179+ self.player.Play()
180+ elif self.id_map[menu_id] == "Next":
181+ self.player.Next()
182+ elif self.id_map[menu_id] == "Previous":
183+ self.player.Prev()
184+
185+ def signal_StatusChange(self, message):
186+ self.set_menu_buttons()
187+ self.update_text()
188+ self.update_badge()
189+ if message[0] == 0:
190+ self.start_timer()
191+ else:
192+ self.stop_timer()
193+
194+ def signal_TrackChange(self, message):
195+ self.update_songinfo();
196+ self.update_text()
197+ self.update_badge()
198+ self.update_icon()
199+
200+ def audacious_is_playing(self):
201+ if self.player:
202+ try:
203+ status=self.player.GetStatus()
204+ if status[0] == 0:
205+ return True
206+ else:
207+ return False
208+ except dbus.DBusException, e:
209+ return False
210+ return False
211+
212+ def get_aud(self):
213+ try:
214+ return self.bus.get_object('org.atheme.audacious', '/org/atheme/audacious')
215+ except dbus.exceptions.DBusException:
216+ print "\x02Either Audacious is not running or you have something wrong with your D-Bus setup."
217+ return None
218+
219+ def update_songinfo(self):
220+ if self.player:
221+ try:
222+ bus = Bus(Bus.TYPE_SESSION)
223+ aud = self.get_aud()
224+ audr = bus.get_object('org.mpris.audacious', '/')
225+ audi = bus.get_object('org.mpris.audacious', '/Player')
226+ audm = audi.GetMetadata()
227+ self.duration_secs = aud.SongLength(aud.Position())
228+ if self.duration_secs > 0:
229+ try:
230+ artist=(unicode(audm['artist']).encode('utf-8'))
231+ title=(unicode(audm['title']).encode('utf-8'))
232+ except:
233+ artist='Unknown'
234+ title='Unknown'
235+ self.songinfo = '%s - %s (%i:%02i)' %(artist, title, (self.duration_secs / 60), (self.duration_secs % 60))
236+ else:
237+ self.songinfo = '%s - %s' % artist, title
238+ except dbus.DBusException, e:
239+ self.duration_secs = 0
240+ self.songinfo = None
241+ return
242+ self.duration_secs = 0
243+ self.songinfo = None
244+
245+ def update_text(self):
246+ if not self.player:
247+ self.reset_tooltip()
248+
249+ if self.audacious_is_playing() and self.songinfo:
250+ self.set_tooltip(self.songinfo)
251+ else:
252+ self.reset_tooltip()
253+
254+ def update_badge(self):
255+ if not self.player:
256+ self.reset_badge()
257+ return False
258+
259+ if not enable_badge_text:
260+ return True
261+
262+ if self.audacious_is_playing():
263+ #if song length is 0 then counting up instead of down
264+ if self.duration_secs > 0:
265+ position = self.duration_secs - self.player.PositionGet() / 1000
266+ else:
267+ position = self.player.PositionGet() / 1000
268+ string = '%i:%02i' % (position / 60, position % 60)
269+ self.set_badge(string)
270+ else:
271+ self.reset_badge()
272+ return True
273+
274+ def update_icon(self):
275+ if not self.player:
276+ self.reset_icon()
277+ return False
278+
279+ if not enable_art_icon:
280+ return True
281+
282+ if self.audacious_is_playing():
283+ cover_found=True
284+ buffer = getoutput(AUDTOOL + ' current-song-filename')
285+ temp_filename = buffer.replace('file://', '')
286+ current = temp_filename.replace('%20', ' ')
287+ pathname = os.path.dirname(current)
288+ filename = os.path.abspath(pathname)
289+ for cover in coverlist:
290+ if os.path.exists(filename + '/' + cover):
291+ cover_2 = (filename + '/' + cover)
292+ self.set_icon(self.get_album_art_overlay_path(cover_2))
293+ return
294+ else:
295+ cover_found=False
296+ if cover_found==False:
297+ self.reset_icon()
298+ else:
299+ self.reset_icon()
300+ return True
301+
302+ def get_album_art_overlay_path(self, picfile):
303+ if overlay == 0:
304+ return picfile
305+ try:
306+ pb = gtk.gdk.pixbuf_new_from_file(picfile)
307+ except Exception, e:
308+ print e
309+ return picfile
310+ pb_result = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 250, 250)
311+ pb_result.fill(0x00000000)
312+ if overlay == 1:
313+ overlayfile = os.path.join(RESOURCESDIR, "albumoverlay_jewel.png")
314+ pb.composite(pb_result, 30, 21, 200, 200, 30, 21, 200.0/pb.get_width(), 200.0/pb.get_height(), gtk.gdk.INTERP_BILINEAR, 255)
315+ elif overlay == 2:
316+ overlayfile = os.path.join(RESOURCESDIR, "albumoverlay_vinyl.png")
317+ pb.composite(pb_result, 3, 26, 190, 190, 3, 26, 190.0/pb.get_width(), 190.0/pb.get_height(), gtk.gdk.INTERP_BILINEAR, 255)
318+ else:
319+ return picfile
320+ pb_overlay = gtk.gdk.pixbuf_new_from_file_at_size(overlayfile, 250, 250)
321+ pb_overlay.composite(pb_result, 0, 0, 250, 250, 0, 0, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
322+ pb_result.save(album_art_tmpfile, "png", {})
323+ return album_art_tmpfile
324+
325+
326+class AudaciousSink(DockManagerSink):
327+ def item_path_found(self, pathtoitem, item):
328+ if item.Get(DOCKITEM_IFACE, "DesktopFile", dbus_interface="org.freedesktop.DBus.Properties").endswith("audacious2.desktop"):
329+ self.items[pathtoitem] = AudaciousItem(self, pathtoitem)
330+
331+audacioussink = AudaciousSink()
332+
333+def cleanup():
334+ audacioussink.dispose()
335+
336+if __name__ == "__main__":
337+ mainloop = gobject.MainLoop(is_running=True)
338+ atexit.register(cleanup)
339+ signal(SIGTERM, lambda signum, stack_frame: exit(1))
340+ while mainloop.is_running():
341+ mainloop.run()

Subscribers

People subscribed via source and target branches

to status/vote changes: