Merge lp:~thisfred/autoqueue/lp-777351 into lp:autoqueue

Proposed by Eric Casteleijn
Status: Merged
Approved by: Eric Casteleijn
Approved revision: 322
Merged at revision: 321
Proposed branch: lp:~thisfred/autoqueue/lp-777351
Merge into: lp:autoqueue
Diff against target: 305 lines (+62/-45)
3 files modified
autoqueue/__init__.py (+25/-34)
autoqueue/tests/test_autoqueue.py (+4/-0)
rhythmbox_autoqueue/__init__.py (+33/-11)
To merge this branch: bzr merge lp:~thisfred/autoqueue/lp-777351
Reviewer Review Type Date Requested Status
Eric Casteleijn Pending
Review via email: mp+60205@code.launchpad.net

Commit message

fixed rhythmbox support

Description of the change

fixed rhythmbox support

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'autoqueue/__init__.py'
2--- autoqueue/__init__.py 2011-05-06 00:03:33 +0000
3+++ autoqueue/__init__.py 2011-05-06 15:33:27 +0000
4@@ -24,6 +24,7 @@
5 import os
6 import random
7
8+from abc import ABCMeta, abstractmethod
9 from dbus.mainloop.glib import DBusGMainLoop
10 from collections import deque
11 from datetime import datetime, timedelta
12@@ -45,51 +46,49 @@
13 class SongBase(object):
14 """A wrapper object around player specific song objects."""
15
16+ __metaclass__ = ABCMeta
17+
18 def __init__(self, song):
19 self.song = song
20
21 def __str__(self):
22 return "<Song: %s - %s>" % (self.get_artist(), self.get_title())
23
24+ @abstractmethod
25 def get_artist(self):
26 """Return lowercase UNICODE name of artist."""
27- return NotImplemented
28
29+ @abstractmethod
30 def get_artists(self):
31 """Return lowercase UNICODE name of artists and performers."""
32- return NotImplemented
33
34+ @abstractmethod
35 def get_title(self):
36 """Return lowercase UNICODE title of song."""
37- return NotImplemented
38
39+ @abstractmethod
40 def get_tags(self):
41 """Return a list of tags for the song."""
42- return []
43
44+ @abstractmethod
45 def get_filename(self):
46 """Return filename for the song."""
47- return NotImplemented
48
49+ @abstractmethod
50 def get_length(self):
51 """Return length in seconds."""
52- return NotImplemented
53
54+ @abstractmethod
55 def get_last_started(self):
56 """Return the datetime the song was last played."""
57- return NotImplemented
58
59+ @abstractmethod
60 def get_rating(self):
61 """Return the rating of the song."""
62- return NotImplemented
63
64+ @abstractmethod
65 def get_playcount(self):
66 """Return the playcount of the song."""
67- return NotImplemented
68-
69- def get_added(self):
70- """Return the datetime the song was added to the library."""
71- return NotImplemented
72
73 def get_play_frequency(self):
74 """Return the play frequency of the song (plays / day)."""
75@@ -124,27 +123,19 @@
76 class AutoQueueBase(object):
77 """Generic base class for autoqueue plugins."""
78
79+ __metaclass__ = ABCMeta
80+
81 def __init__(self):
82 self.artist_block_time = 1
83 self._blocked_artists = deque([])
84 self._blocked_artists_times = deque([])
85 self._cache_dir = None
86- self.desired_queue_length = 0
87+ self.desired_queue_length = 15 * 60
88 self.cached_misses = deque([])
89- self.by_mirage = False
90- self.by_tracks = True
91- self.by_artists = True
92- self.by_tags = True
93 self.running = False
94 self.verbose = False
95- self.weed = False
96 self.song = None
97 self.restrictions = None
98- self.prune_artists = []
99- self.prune_titles = []
100- self.prune_filenames = []
101- self._rows = []
102- self._nrows = []
103 self.player_set_variables_from_config()
104 self.get_blocked_artists_pickle()
105 self.last_songs = []
106@@ -249,45 +240,45 @@
107 song.get_filename() for song in self.player_search(search)])
108 return filenames
109
110+ @abstractmethod
111 def player_construct_file_search(self, filename, restrictions=None):
112 """Construct a search that looks for songs with this artist and title.
113
114 """
115- return NotImplemented
116
117+ @abstractmethod
118 def player_construct_track_search(self, artist, title, restrictions=None):
119 """Construct a search that looks for songs with this artist
120 and title.
121 """
122- return NotImplemented
123
124+ @abstractmethod
125 def player_construct_artist_search(self, artist, restrictions=None):
126 """Construct a search that looks for songs with this artist."""
127- return NotImplemented
128
129+ @abstractmethod
130 def player_construct_tag_search(self, tags, restrictions=None):
131 """Construct a search that looks for songs with these tags."""
132- return NotImplemented
133
134+ @abstractmethod
135 def player_set_variables_from_config(self):
136 """Initialize user settings from the configuration storage."""
137- return NotImplemented
138
139+ @abstractmethod
140 def player_get_queue_length(self):
141 """Get the current length of the queue."""
142- return 0
143
144+ @abstractmethod
145 def player_enqueue(self, song):
146 """Put the song at the end of the queue."""
147- return NotImplemented
148
149+ @abstractmethod
150 def player_search(self, search):
151 """Perform a player search."""
152- return NotImplemented
153
154+ @abstractmethod
155 def player_get_songs_in_queue(self):
156 """Return (wrapped) song objects for the songs in the queue."""
157- return []
158
159 def player_execute_async(self, method, *args, **kwargs):
160 """Override this if the player has a way to execute methods
161@@ -418,7 +409,7 @@
162 return song
163 self.cached_misses.append((artist, title, filename, tags))
164 while len(self.cached_misses) > 1000:
165- print self.cached_misses.popleft()
166+ self.cached_misses.popleft()
167
168 def fill_queue(self):
169 """Search for appropriate songs and put them in the queue."""
170
171=== modified file 'autoqueue/tests/test_autoqueue.py'
172--- autoqueue/tests/test_autoqueue.py 2011-05-06 00:03:33 +0000
173+++ autoqueue/tests/test_autoqueue.py 2011-05-06 15:33:27 +0000
174@@ -213,6 +213,10 @@
175 artist_name,
176 len(self._blocked_artists)))
177
178+ def player_set_variables_from_config(self):
179+ """Set configuration variables."""
180+ pass
181+
182 def player_construct_file_search(self, filename, restrictions=None):
183 """Construct a search that looks for songs with this artist
184 and title.
185
186=== modified file 'rhythmbox_autoqueue/__init__.py'
187--- rhythmbox_autoqueue/__init__.py 2010-08-12 12:20:37 +0000
188+++ rhythmbox_autoqueue/__init__.py 2011-05-06 15:33:27 +0000
189@@ -1,3 +1,5 @@
190+"""Rhythmbox version of the autoqueue plugin."""
191+
192 # Copyright (C) 2007-2008 - Eric Casteleijn, Alexandre Rosenfeld
193 #
194 # This program is free software; you can redistribute it and/or modify
195@@ -16,24 +18,29 @@
196
197 import urllib
198 from time import time
199-import gconf, gobject
200+import gconf
201+import gobject
202 from gtk import gdk
203-import rb, rhythmdb
204+import rb
205+import rhythmdb
206 from collections import deque
207 from autoqueue import AutoQueueBase, SongBase
208
209 GCONFPATH = '/apps/rhythmbox/plugins/autoqueue/'
210
211+
212 class Song(SongBase):
213 """A wrapper object around rhythmbox song objects."""
214- def __init__(self, song, db):
215+
216+ def __init__(self, song, db): # pylint: disable=W0231
217 self.song = song
218 self.db = db
219
220 def get_artist(self):
221 """return lowercase UNICODE name of artist"""
222 return unicode(
223- self.db.entry_get(self.song, rhythmdb.PROP_ARTIST).lower(), 'utf-8')
224+ self.db.entry_get(self.song, rhythmdb.PROP_ARTIST).lower(),
225+ 'utf-8')
226
227 def get_artists(self):
228 return [self.get_artist()]
229@@ -59,8 +66,18 @@
230 def get_last_started(self):
231 return self.db.entry_get(self.song, rhythmdb.PROP_LAST_PLAYED)
232
233+ def get_rating(self):
234+ """Return the rating of the song."""
235+ return 5.0 / self.db.entry_get(self.song, rhythmdb.PROP_RATING)
236+
237+ def get_playcount(self):
238+ """Return the playcount of the song."""
239+ return self.db.entry_get(self.song, rhythmdb.PROP_PLAY_COUNT)
240+
241
242 class AutoQueuePlugin(rb.Plugin, AutoQueueBase):
243+ """Plugin implementation."""
244+
245 def __init__(self):
246 rb.Plugin.__init__(self)
247 AutoQueueBase.__init__(self)
248@@ -69,21 +86,27 @@
249 self.by_mirage = True
250 self.log("initialized")
251 self._generators = deque()
252+ self.pec_id = None
253+ self.rdb = None
254+ self.shell = None
255
256 def activate(self, shell):
257+ """Called on activation of the plugin."""
258 self.shell = shell
259 self.rdb = shell.get_property('db')
260- sp = shell.get_player ()
261+ sp = shell.get_player()
262 self.pec_id = sp.connect(
263 'playing-song-changed', self.playing_entry_changed)
264
265 def deactivate(self, shell):
266+ """Called on deactivation of the plugin."""
267 self.rdb = None
268 self.shell = None
269 sp = shell.get_player()
270 sp.disconnect(self.pec_id)
271
272 def _idle_callback(self):
273+ """Callback that performs task asynchronously."""
274 gdk.threads_enter()
275 while self._generators:
276 if self._generators[0] is None:
277@@ -97,24 +120,23 @@
278 return False
279
280 def player_execute_async(self, method, *args, **kwargs):
281- """Override this if the player has a way to execute methods
282- asynchronously, like the copooling in autoqueue.
283-
284- """
285+ """Execute method asynchronously."""
286 add_callback = False
287 if not self._generators:
288- add_callback = True
289+ add_callback = True
290 self._generators.append(method(*args, **kwargs))
291 if add_callback:
292 gobject.idle_add(self._idle_callback)
293
294 def log(self, msg):
295- """print debug messages"""
296+ """Print debug messages."""
297+ # TODO: replace with real logging
298 if not self.verbose:
299 return
300 print msg
301
302 def playing_entry_changed(self, sp, entry):
303+ """Handler for song change."""
304 if entry:
305 self.on_song_started(Song(entry, self.rdb))
306

Subscribers

People subscribed via source and target branches

to all changes: