Merge lp:~dobey/ubuntu/natty/rhythmbox-ubuntuone-music-store/use-defer into lp:ubuntu/natty/rhythmbox-ubuntuone-music-store
- Natty (11.04)
- use-defer
- Merge into natty
Proposed by
dobey
Status: | Merged |
---|---|
Merged at revision: | 56 |
Proposed branch: | lp:~dobey/ubuntu/natty/rhythmbox-ubuntuone-music-store/use-defer |
Merge into: | lp:ubuntu/natty/rhythmbox-ubuntuone-music-store |
Diff against target: |
1180 lines (+377/-305) 15 files modified
MANIFEST (+0/-36) MANIFEST.in (+5/-10) PKG-INFO (+6/-4) debian/changelog (+7/-0) gst/__init__.py (+14/-0) gst/pbutils.py (+6/-0) po/rhythmbox-ubuntuone-music-store.pot (+0/-60) rb.py (+36/-0) rhythmdb.py (+12/-0) run-tests (+24/-0) setup.py (+12/-8) umusicstore/MusicStoreWidget.py (+137/-100) umusicstore/U1MSLinks.py (+107/-68) umusicstore/__init__.py (+11/-9) umusicstore/umusicstore.rb-plugin (+0/-10) |
To merge this branch: | bzr merge lp:~dobey/ubuntu/natty/rhythmbox-ubuntuone-music-store/use-defer |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu branches | Pending | ||
Review via email: mp+44358@code.launchpad.net |
Commit message
Description of the change
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 | === removed file 'MANIFEST' |
2 | --- MANIFEST 2010-08-26 01:47:45 +0000 |
3 | +++ MANIFEST 1970-01-01 00:00:00 +0000 |
4 | @@ -1,36 +0,0 @@ |
5 | -COPYING |
6 | -MANIFEST |
7 | -MANIFEST.in |
8 | -README |
9 | -setup.cfg |
10 | -setup.py |
11 | -po/POTFILES.in |
12 | -po/ca.po |
13 | -po/cs.po |
14 | -po/da.po |
15 | -po/de.po |
16 | -po/el.po |
17 | -po/en_GB.po |
18 | -po/es.po |
19 | -po/eu.po |
20 | -po/fi.po |
21 | -po/fr.po |
22 | -po/fy.po |
23 | -po/gl.po |
24 | -po/he.po |
25 | -po/hr.po |
26 | -po/ka.po |
27 | -po/nl.po |
28 | -po/pl.po |
29 | -po/rhythmbox-ubuntuone-music-store.pot |
30 | -po/ro.po |
31 | -po/ru.po |
32 | -po/sv.po |
33 | -po/uk.po |
34 | -umusicstore/MusicStoreWidget.py |
35 | -umusicstore/U1MSLinks.py |
36 | -umusicstore/__init__.py |
37 | -umusicstore/empty.mp3 |
38 | -umusicstore/u1msurl.glade |
39 | -umusicstore/umusicstore.rb-plugin |
40 | -umusicstore/umusicstore.rb-plugin.in |
41 | |
42 | === modified file 'MANIFEST.in' |
43 | --- MANIFEST.in 2010-07-21 16:03:11 +0000 |
44 | +++ MANIFEST.in 2010-12-21 15:44:57 +0000 |
45 | @@ -1,10 +1,5 @@ |
46 | -include COPYING README |
47 | -include MANIFEST.in MANIFEST |
48 | -include po/* |
49 | -include umusicstore/umusicstore.rb-plugin* |
50 | -include umusicstore/empty.mp3 |
51 | -include umusicstore/musicstore_icon.png |
52 | -include umusicstore/__init__.py |
53 | -include umusicstore/MusicStoreWidget.py |
54 | -include umusicstore/U1MSLinks.py |
55 | -include umusicstore/u1msurl.glade |
56 | +include COPYING MANIFEST.in README |
57 | +include run-tests rb.py rhythmdb.py |
58 | +recursive-include gst *.py |
59 | +recursive-include po *.po POTFILES.in |
60 | +recursive-include umusicstore *.py *.glade *.mp3 *.rb-plugin.in |
61 | |
62 | === modified file 'PKG-INFO' |
63 | --- PKG-INFO 2010-10-07 13:09:46 +0000 |
64 | +++ PKG-INFO 2010-12-21 15:44:57 +0000 |
65 | @@ -1,11 +1,13 @@ |
66 | Metadata-Version: 1.1 |
67 | Name: rhythmbox-ubuntuone-music-store |
68 | -Version: 0.1.9 |
69 | -Summary: Ubuntu One Music Store Rhythmbox plugin |
70 | +Version: 0.1.10 |
71 | +Summary: Ubuntu One Music Store Rhythmbox plug-in |
72 | Home-page: https://launchpad.net/rhythmbox-ubuntuone-music-store |
73 | Author: Stuart Langridge |
74 | Author-email: stuart.langridge@canonical.com |
75 | License: LGPL v3 |
76 | -Description: A Rhythmbox plugin that makes the Ubuntu Music Store available in Rhythmbox. |
77 | +Description: A plug-in to access the Ubuntu One Music Store in Rhythmbox. |
78 | Platform: UNKNOWN |
79 | -Requires: DistUtilsExtra.auto |
80 | +Provides: gst |
81 | +Provides: rb |
82 | +Provides: rhythmdb |
83 | |
84 | === modified file 'debian/changelog' |
85 | --- debian/changelog 2010-12-21 10:32:15 +0000 |
86 | +++ debian/changelog 2010-12-21 15:44:57 +0000 |
87 | @@ -1,3 +1,10 @@ |
88 | +rhythmbox-ubuntuone-music-store (0.1.10-0ubuntu1) natty; urgency=low |
89 | + |
90 | + * New upstream release. |
91 | + - Handle the defer API being split out from aptdaemon. (LP: #691647) |
92 | + |
93 | + -- Rodney Dawes <rodney.dawes@ubuntu.com> Tue, 21 Dec 2010 10:37:55 -0500 |
94 | + |
95 | rhythmbox-ubuntuone-music-store (0.1.9-0ubuntu2) natty; urgency=low |
96 | |
97 | * debian/control: add Depends on python-defer (LP: #691647) |
98 | |
99 | === added directory 'gst' |
100 | === added file 'gst/__init__.py' |
101 | --- gst/__init__.py 1970-01-01 00:00:00 +0000 |
102 | +++ gst/__init__.py 2010-12-21 15:44:57 +0000 |
103 | @@ -0,0 +1,14 @@ |
104 | +"""Fake gst.py module for testing.""" |
105 | + |
106 | +STATE_NULL = 0 |
107 | +STATE_PLAYING = 1 |
108 | + |
109 | + |
110 | +def parse_launch(*args, **kwargs): |
111 | + """Fake parse_launch.""" |
112 | + return |
113 | + |
114 | + |
115 | +def update_registry(*args, **kwargs): |
116 | + """Fake update_registry.""" |
117 | + return |
118 | |
119 | === added file 'gst/pbutils.py' |
120 | --- gst/pbutils.py 1970-01-01 00:00:00 +0000 |
121 | +++ gst/pbutils.py 2010-12-21 15:44:57 +0000 |
122 | @@ -0,0 +1,6 @@ |
123 | +"""Fake pbutils module for testing.""" |
124 | + |
125 | + |
126 | +def is_missing_plugin_message(*args, **kwargs): |
127 | + """Fake is_missing_plugin_message.""" |
128 | + return |
129 | |
130 | === removed file 'po/rhythmbox-ubuntuone-music-store.pot' |
131 | --- po/rhythmbox-ubuntuone-music-store.pot 2010-04-01 17:30:54 +0000 |
132 | +++ po/rhythmbox-ubuntuone-music-store.pot 1970-01-01 00:00:00 +0000 |
133 | @@ -1,60 +0,0 @@ |
134 | -# SOME DESCRIPTIVE TITLE. |
135 | -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER |
136 | -# This file is distributed under the same license as the PACKAGE package. |
137 | -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
138 | -# |
139 | -#, fuzzy |
140 | -msgid "" |
141 | -msgstr "" |
142 | -"Project-Id-Version: PACKAGE VERSION\n" |
143 | -"Report-Msgid-Bugs-To: \n" |
144 | -"POT-Creation-Date: 2010-03-25 10:30+0100\n" |
145 | -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
146 | -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
147 | -"Language-Team: LANGUAGE <LL@li.org>\n" |
148 | -"MIME-Version: 1.0\n" |
149 | -"Content-Type: text/plain; charset=CHARSET\n" |
150 | -"Content-Transfer-Encoding: 8bit\n" |
151 | - |
152 | -#. Translators: this is the name under Music for U1 music in Rhythmbox |
153 | -#: ../umusicstore/__init__.py:172 |
154 | -msgid "Purchased from Ubuntu One" |
155 | -msgstr "" |
156 | - |
157 | -#: ../umusicstore/__init__.py:243 |
158 | -msgid "Ubuntu One" |
159 | -msgstr "" |
160 | - |
161 | -#: ../umusicstore/__init__.py:288 |
162 | -msgid "MP3 plugins are not installed" |
163 | -msgstr "" |
164 | - |
165 | -#: ../umusicstore/__init__.py:293 |
166 | -msgid "" |
167 | -"To listen to your purchased songs, you need to install MP3 plugins. Click " |
168 | -"below to install them." |
169 | -msgstr "" |
170 | - |
171 | -#: ../umusicstore/__init__.py:298 |
172 | -msgid "Install MP3 plugins" |
173 | -msgstr "" |
174 | - |
175 | -#: ../umusicstore/__init__.py:320 |
176 | -msgid "Installing MP3 plugins" |
177 | -msgstr "" |
178 | - |
179 | -#: ../umusicstore/__init__.py:340 |
180 | -msgid "There was a problem installing, sorry" |
181 | -msgstr "" |
182 | - |
183 | -#: ../umusicstore/__init__.py:343 |
184 | -msgid "Check your internet connection and try again." |
185 | -msgstr "" |
186 | - |
187 | -#: ../umusicstore/umusicstore.rb-plugin.in.h:1 |
188 | -msgid "The Ubuntu One Music Store" |
189 | -msgstr "" |
190 | - |
191 | -#: ../umusicstore/umusicstore.rb-plugin.in.h:2 |
192 | -msgid "Ubuntu One Music Store" |
193 | -msgstr "" |
194 | |
195 | === added file 'rb.py' |
196 | --- rb.py 1970-01-01 00:00:00 +0000 |
197 | +++ rb.py 2010-12-21 15:44:57 +0000 |
198 | @@ -0,0 +1,36 @@ |
199 | +"""Fake rb.py for use in testing.""" |
200 | + |
201 | +SOURCE_GROUP_CATEGORY_FIXED = 0 |
202 | + |
203 | + |
204 | +class Plugin(object): |
205 | + """Fake Plugin class for testing.""" |
206 | + |
207 | + def __init__(self, *args, **kwargs): |
208 | + super(Plugin, self).__init__() |
209 | + |
210 | + def find_file(self, *args, **kwargs): |
211 | + """Fake find_file method.""" |
212 | + pass |
213 | + |
214 | + |
215 | +class Source(object): |
216 | + """Fake Source class for testing.""" |
217 | + |
218 | + add = __fake_it |
219 | + remove = __fake_it |
220 | + show_all = __fake_it |
221 | + do_impl_activate = __fake_it |
222 | + |
223 | + def __fake_it(self, *args, **kwargs): |
224 | + """Fake method.""" |
225 | + |
226 | + |
227 | +def rb_source_group_get_by_name(*args, **kwargs): |
228 | + """Fake method.""" |
229 | + return |
230 | + |
231 | + |
232 | +def rb_source_group_register(*args, **kwargs): |
233 | + """Fake method.""" |
234 | + return |
235 | |
236 | === added file 'rhythmdb.py' |
237 | --- rhythmdb.py 1970-01-01 00:00:00 +0000 |
238 | +++ rhythmdb.py 2010-12-21 15:44:57 +0000 |
239 | @@ -0,0 +1,12 @@ |
240 | +"""Fake rhythmdb.py for use in testing.""" |
241 | + |
242 | +PROP_ARTIST = 0 |
243 | +PROP_TITLE = 1 |
244 | +PROP_ALBUM = 2 |
245 | + |
246 | + |
247 | +class EntryType(object): |
248 | + """Fake EntryType object.""" |
249 | + |
250 | + def __init__(self, *args, **kwargs): |
251 | + super(EntryType, self).__init__() |
252 | |
253 | === added file 'run-tests' |
254 | --- run-tests 1970-01-01 00:00:00 +0000 |
255 | +++ run-tests 2010-12-21 15:44:57 +0000 |
256 | @@ -0,0 +1,24 @@ |
257 | +#!/bin/bash |
258 | +# Author: Natalia Bidart <natalia.bidart@canonical.com> |
259 | +# |
260 | +# Copyright 2010 Canonical Ltd. |
261 | +# |
262 | +# This program is free software: you can redistribute it and/or modify it |
263 | +# under the terms of the GNU General Public License version 3, as published |
264 | +# by the Free Software Foundation. |
265 | +# |
266 | +# This program is distributed in the hope that it will be useful, but |
267 | +# WITHOUT ANY WARRANTY; without even the implied warranties of |
268 | +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
269 | +# PURPOSE. See the GNU General Public License for more details. |
270 | +# |
271 | +# You should have received a copy of the GNU General Public License along |
272 | +# with this program. If not, see <http://www.gnu.org/licenses/>. |
273 | +export PYTHONPATH=umusicstore |
274 | +u1lint . |
275 | +if [ -x `which pep8` ]; then |
276 | + pep8 --repeat . |
277 | +else |
278 | + echo "Please install the 'pep8' package." |
279 | +fi |
280 | +rm -rf _trial_temp |
281 | |
282 | === modified file 'setup.py' (properties changed: -x to +x) |
283 | --- setup.py 2010-10-07 13:09:46 +0000 |
284 | +++ setup.py 2010-12-21 15:44:57 +0000 |
285 | @@ -1,18 +1,22 @@ |
286 | +#!/usr/bin/python |
287 | +"""Setup script for Ubuntu One Music Store plug-in for Rhythmbox.""" |
288 | |
289 | import DistUtilsExtra.auto |
290 | |
291 | DistUtilsExtra.auto.setup( |
292 | name='rhythmbox-ubuntuone-music-store', |
293 | - version='0.1.9', |
294 | + version='0.1.10', |
295 | license='LGPL v3', |
296 | author='Stuart Langridge', |
297 | author_email='stuart.langridge@canonical.com', |
298 | - description='Ubuntu One Music Store Rhythmbox plugin', |
299 | - long_description='A Rhythmbox plugin that makes the Ubuntu Music Store available in Rhythmbox.', |
300 | + description='Ubuntu One Music Store Rhythmbox plug-in', |
301 | + long_description=('A plug-in to access the Ubuntu One Music Store ' |
302 | + 'in Rhythmbox.'), |
303 | url='https://launchpad.net/rhythmbox-ubuntuone-music-store', |
304 | - data_files = [('/usr/lib/rhythmbox/plugins/umusicstore', ['umusicstore/__init__.py', |
305 | - 'umusicstore/empty.mp3', |
306 | - 'umusicstore/MusicStoreWidget.py', |
307 | - 'umusicstore/U1MSLinks.py', |
308 | - 'umusicstore/u1msurl.glade'])], |
309 | + data_files=[('/usr/lib/rhythmbox/plugins/umusicstore', |
310 | + ['umusicstore/__init__.py', |
311 | + 'umusicstore/empty.mp3', |
312 | + 'umusicstore/MusicStoreWidget.py', |
313 | + 'umusicstore/U1MSLinks.py', |
314 | + 'umusicstore/u1msurl.glade'])], |
315 | ) |
316 | |
317 | === modified file 'umusicstore/MusicStoreWidget.py' |
318 | --- umusicstore/MusicStoreWidget.py 2010-10-07 13:09:46 +0000 |
319 | +++ umusicstore/MusicStoreWidget.py 2010-12-21 15:44:57 +0000 |
320 | @@ -16,39 +16,59 @@ |
321 | # |
322 | # Authored by Stuart Langridge <stuart.langridge@canonical.com> |
323 | |
324 | - |
325 | -import gtk, gobject, os, urllib, gconf, stat, urlparse, gio |
326 | -import gst, gst.pbutils |
327 | +# pylint: disable=W0201 |
328 | + |
329 | +# Import these here as gtk/gio import ordering seems to matter |
330 | +import gobject |
331 | +import gtk |
332 | +import gio |
333 | + |
334 | import aptdaemon.client |
335 | -from aptdaemon import policykit1 |
336 | -from aptdaemon.defer import inline_callbacks |
337 | -from aptdaemon.enums import * |
338 | -from aptdaemon.gtkwidgets import AptErrorDialog, \ |
339 | - AptProgressBar |
340 | -from commands import getstatusoutput |
341 | -import rb, rhythmdb |
342 | -from ubuntuone.gtkwidgets import MusicStore as U1MusicStore |
343 | -import xdg.BaseDirectory |
344 | import dbus |
345 | import dbus.exceptions |
346 | - |
347 | +import gconf |
348 | import gettext |
349 | +import gst |
350 | +import gst.pbutils |
351 | +import os |
352 | +# pylint: disable=F0401 |
353 | +import rb |
354 | +import rhythmdb |
355 | +# pylint: enable=F0401 |
356 | +import stat |
357 | +import urllib |
358 | +import urlparse |
359 | +import xdg.BaseDirectory |
360 | + |
361 | +from aptdaemon import policykit1 |
362 | +try: |
363 | + from aptdaemon.defer import inline_callbacks |
364 | +except ImportError: |
365 | + from defer import inline_callbacks |
366 | +from aptdaemon.enums import EXIT_SUCCESS |
367 | +from aptdaemon.gtkwidgets import AptProgressBar |
368 | from gettext import lgettext as _ |
369 | +from ubuntuone.gtkwidgets import MusicStore as U1MusicStore |
370 | + |
371 | gettext.bindtextdomain("rhythmbox-ubuntuone-music-store", "/usr/share/locale") |
372 | gettext.textdomain("rhythmbox-ubuntuone-music-store") |
373 | |
374 | -MUSIC_STORE_WIDGET = U1MusicStore() # keep this around for later |
375 | +MUSIC_STORE_WIDGET = U1MusicStore() # keep this around for later |
376 | U1LIBRARYPATH = MUSIC_STORE_WIDGET.get_library_location() |
377 | RB_LIBRARY_LOCATIONS = "/apps/rhythmbox/library_locations" |
378 | PARTNER_LIST = "canonical-partner-maverick.list" |
379 | SOURCES_DIR = "/etc/apt/sources.list.d/" |
380 | PLUGIN_PACKAGENAME = "gstreamer0.10-fluendo-plugins-mp3-partner" |
381 | |
382 | + |
383 | class U1EntryType(rhythmdb.EntryType): |
384 | + """Entry type for the Ubuntu One Music Store source.""" |
385 | + |
386 | def __init__(self): |
387 | rhythmdb.EntryType.__init__(self, name='ubuntuone') |
388 | |
389 | def can_sync_metadata(self, entry): |
390 | + """Not a real source, so we can't sync metadata.""" |
391 | return False |
392 | |
393 | |
394 | @@ -57,37 +77,37 @@ |
395 | def __init__(self, plugin, find_file): |
396 | self.plugin = plugin |
397 | self.find_file = find_file |
398 | - |
399 | + |
400 | def activate(self, shell): |
401 | """Plugin startup.""" |
402 | self.db = shell.get_property("db") |
403 | - group = rb.rb_source_group_get_by_name ("stores") |
404 | + group = rb.rb_source_group_get_by_name("stores") |
405 | if not group: |
406 | - group = rb.rb_source_group_register ("stores", |
407 | - "Stores", |
408 | - rb.SOURCE_GROUP_CATEGORY_FIXED) |
409 | - |
410 | + group = rb.rb_source_group_register("stores", |
411 | + "Stores", |
412 | + rb.SOURCE_GROUP_CATEGORY_FIXED) |
413 | + |
414 | icon = gtk.IconTheme().load_icon( |
415 | "ubuntuone", gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)[0], 0) |
416 | |
417 | self.entry_type = U1EntryType() |
418 | self.db.register_entry_type(self.entry_type) |
419 | |
420 | - self.source = gobject.new (U1Source, |
421 | - shell=shell, |
422 | - entry_type=self.entry_type, |
423 | - source_group=group, |
424 | - icon=icon, |
425 | - plugin=self.plugin) |
426 | + self.source = gobject.new(U1Source, |
427 | + shell=shell, |
428 | + entry_type=self.entry_type, |
429 | + source_group=group, |
430 | + icon=icon, |
431 | + plugin=self.plugin) |
432 | shell.register_entry_type_for_source(self.source, self.entry_type) |
433 | self.shell = shell |
434 | self.source.connect("preview-mp3", self.play_preview_mp3) |
435 | self.source.connect("play-library", self.play_library) |
436 | self.source.connect("download-finished", self.download_finished) |
437 | self.source.connect("url-loaded", self.url_loaded) |
438 | - |
439 | + |
440 | # Do these every time |
441 | - shell.append_source(self.source, None) # Add the source to the list |
442 | + shell.append_source(self.source, None) # Add the source to the list |
443 | self.add_u1_library() |
444 | |
445 | def deactivate(self, shell): |
446 | @@ -96,18 +116,20 @@ |
447 | self.source.delete_thyself() |
448 | # remove the library, if it's empty |
449 | try: |
450 | - filecount = len(os.listdir(self.U1_LIBRARY_SYMLINK)) |
451 | + filecount = len(os.listdir(self.u1_library_symlink)) |
452 | except OSError: |
453 | # symlink is dangling |
454 | # so they never downloaded anything |
455 | filecount = 0 |
456 | if filecount == 0: |
457 | client = gconf.client_get_default() |
458 | - libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING) |
459 | + libraries = client.get_list(RB_LIBRARY_LOCATIONS, |
460 | + gconf.VALUE_STRING) |
461 | if self.u1_library_path_url in libraries: |
462 | client.notify_remove(self.library_adder) |
463 | libraries.remove(self.u1_library_path_url) |
464 | - client.set_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING, libraries) |
465 | + client.set_list(RB_LIBRARY_LOCATIONS, |
466 | + gconf.VALUE_STRING, libraries) |
467 | # delete held references |
468 | del self.db |
469 | del self.source |
470 | @@ -116,24 +138,24 @@ |
471 | def url_loaded(self, source, url): |
472 | """A URL is loaded in the plugin""" |
473 | print "URL loaded:", url |
474 | - if urlparse.urlparse(url).scheme == "https": |
475 | + if urlparse.urlparse(url)[2] == "https": |
476 | pass |
477 | else: |
478 | pass |
479 | - |
480 | + |
481 | def _udf_path_to_library_uri(self, path): |
482 | - """Calculate the path in the library. |
483 | - Since the library is accessed via the created symlink, but the path |
484 | - passed to us is to a file in the actual music store UDF, we need to |
485 | + """Calculate the path in the library. |
486 | + Since the library is accessed via the created symlink, but the path |
487 | + passed to us is to a file in the actual music store UDF, we need to |
488 | work out the path inside the library, i.e., what the path to that file |
489 | is via the symlink.""" |
490 | - |
491 | if path.startswith(U1LIBRARYPATH): |
492 | subpath = path[len(U1LIBRARYPATH):] |
493 | else: |
494 | subpath = path |
495 | - if subpath.startswith("/"): subpath = subpath[1:] |
496 | - library_path = os.path.join(self.U1_LIBRARY_SYMLINK, subpath) |
497 | + if subpath.startswith("/"): |
498 | + subpath = subpath[1:] |
499 | + library_path = os.path.join(self.u1_library_symlink, subpath) |
500 | # convert path to URI. Don't use urllib for this; Python and |
501 | # glib escape URLs differently. gio does it the glib way. |
502 | library_uri = gio.File(library_path).get_uri() |
503 | @@ -150,11 +172,11 @@ |
504 | """Switch to and start playing a song from the library""" |
505 | uri = self._udf_path_to_library_uri(path) |
506 | entry = self.shell.props.db.entry_lookup_by_location(uri) |
507 | - if not entry: |
508 | + if not entry: |
509 | print "couldn't find entry", uri |
510 | return |
511 | libsrc = self.shell.props.library_source |
512 | - genre_view, artist_view, album_view = libsrc.get_property_views() |
513 | + artist_view, album_view = libsrc.get_property_views()[0:] |
514 | song_view = libsrc.get_entry_view() |
515 | artist = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ARTIST) |
516 | album = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ALBUM) |
517 | @@ -177,7 +199,7 @@ |
518 | player = self.shell.get_player() |
519 | player.stop() |
520 | player.play_entry(entry, self.source) |
521 | - # FIXME delete this entry when it finishes playing. Don't know how yet. |
522 | + # delete this entry when it finishes playing. Don't know how yet. |
523 | |
524 | def add_u1_library(self): |
525 | """Add the U1 library if not listed in RB and re-add if changed.""" |
526 | @@ -187,11 +209,12 @@ |
527 | os.chmod(u1_library_path_folder, |
528 | os.stat(u1_library_path_folder)[stat.ST_MODE] | stat.S_IWUSR) |
529 | # Translators: this is the name under Music for U1 music in Rhythmbox |
530 | - u1_library_path = os.path.join(u1_library_path_folder, _("Purchased from Ubuntu One")) |
531 | + u1_library_path = os.path.join(u1_library_path_folder, |
532 | + _("Purchased from Ubuntu One")) |
533 | if not os.path.islink(u1_library_path): |
534 | if not os.path.exists(u1_library_path): |
535 | - print "Attempting to symlink %s to %s" % (U1LIBRARYPATH, |
536 | - u1_library_path) |
537 | + print "Attempting to symlink %s to %s" % (U1LIBRARYPATH, |
538 | + u1_library_path) |
539 | os.symlink(U1LIBRARYPATH, u1_library_path) |
540 | else: |
541 | # something that isn't a symlink already exists. That's not |
542 | @@ -204,12 +227,13 @@ |
543 | "delete or rename %s.") % (u1_library_path, U1LIBRARYPATH, |
544 | u1_library_path) |
545 | self.u1_library_path_url = "file://%s" % urllib.quote(u1_library_path) |
546 | - self.U1_LIBRARY_SYMLINK = u1_library_path |
547 | + self.u1_library_symlink = u1_library_path |
548 | client = gconf.client_get_default() |
549 | self._add_u1_library_if_not_present(client) |
550 | self._remove_old_u1_library_if_present(client) |
551 | # Watch for changes to the gconf key and re-add the library |
552 | - self.library_adder = client.notify_add(RB_LIBRARY_LOCATIONS, |
553 | + self.library_adder = client.notify_add( |
554 | + RB_LIBRARY_LOCATIONS, |
555 | self._add_u1_library_if_not_present) |
556 | |
557 | def _add_u1_library_if_not_present(self, client, *args, **kwargs): |
558 | @@ -217,7 +241,8 @@ |
559 | libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING) |
560 | if self.u1_library_path_url not in libraries: |
561 | libraries.append(self.u1_library_path_url) |
562 | - client.set_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING, libraries) |
563 | + client.set_list(RB_LIBRARY_LOCATIONS, |
564 | + gconf.VALUE_STRING, libraries) |
565 | |
566 | def _remove_old_u1_library_if_present(self, client, *args, **kwargs): |
567 | """Check for the old U1 library and remove it from libraries list.""" |
568 | @@ -243,46 +268,57 @@ |
569 | # created under one name (say, English) and then had it created |
570 | # under another (say, after a translation to Dutch) |
571 | u1_library_path_folder = xdg.BaseDirectory.save_data_path("ubuntuone") |
572 | - u1_library_path_folder_url = "file://%s" % urllib.quote(u1_library_path_folder) |
573 | - symlink_url = "file://" + urllib.quote(self.U1_LIBRARY_SYMLINK) |
574 | - for l in libraries: |
575 | - if l.startswith(u1_library_path_folder_url) and l != symlink_url: |
576 | - libraries.remove(l) |
577 | + u1_library_path_folder_url = "file://%s" % urllib.quote( |
578 | + u1_library_path_folder) |
579 | + symlink_url = "file://" + urllib.quote(self.u1_library_symlink) |
580 | + for lib in libraries: |
581 | + if lib.startswith(u1_library_path_folder_url) and \ |
582 | + lib != symlink_url: |
583 | + libraries.remove(lib) |
584 | # and delete the symlink itself |
585 | - symlink_to_remove = urllib.unquote(l[7:]) |
586 | + symlink_to_remove = urllib.unquote(lib[7:]) |
587 | os.unlink(symlink_to_remove) |
588 | removed = True |
589 | if removed: |
590 | - client.set_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING, libraries) |
591 | - |
592 | -class U1Source(rb.Source): |
593 | + client.set_list(RB_LIBRARY_LOCATIONS, |
594 | + gconf.VALUE_STRING, libraries) |
595 | + |
596 | + |
597 | +class U1Source(rb.Source, gobject.GObject): |
598 | """A Rhythmbox source widget for the U1 Music Store.""" |
599 | # gproperties required so that rb.Source is instantiable |
600 | __gproperties__ = { |
601 | - 'plugin': (rb.Plugin, 'plugin', 'plugin', |
602 | - gobject.PARAM_WRITABLE|gobject.PARAM_CONSTRUCT_ONLY), |
603 | - } |
604 | - # we have the preview-mp3 signal; we receive it from the widget, and re-emit |
605 | - # it so that the plugin gets it, because the plugin actually plays the mp3 |
606 | + 'plugin': (rb.Plugin, 'plugin', 'plugin', |
607 | + gobject.PARAM_WRITABLE | gobject.PARAM_CONSTRUCT_ONLY), |
608 | + } |
609 | + # we have the preview-mp3 signal; we receive it from the widget, and |
610 | + # re-emit it so that the plugin gets it, because the plugin actually |
611 | + # plays the mp3 |
612 | __gsignals__ = { |
613 | - "preview-mp3": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str, str)), |
614 | - "play-library": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str,)), |
615 | - "download-finished": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str,)), |
616 | - "url-loaded": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str,)), |
617 | + "preview-mp3": (gobject.SIGNAL_RUN_FIRST, |
618 | + gobject.TYPE_NONE, (str, str)), |
619 | + "play-library": (gobject.SIGNAL_RUN_FIRST, |
620 | + gobject.TYPE_NONE, (str,)), |
621 | + "download-finished": (gobject.SIGNAL_RUN_FIRST, |
622 | + gobject.TYPE_NONE, (str,)), |
623 | + "url-loaded": (gobject.SIGNAL_RUN_FIRST, |
624 | + gobject.TYPE_NONE, (str,)), |
625 | } |
626 | - |
627 | + |
628 | def __init__(self): |
629 | rb.Source.__init__(self, name=_("Ubuntu One")) |
630 | + gobject.GObject.__init__(self) |
631 | self.browser = MUSIC_STORE_WIDGET |
632 | self.__activated = False |
633 | |
634 | def do_impl_activate(self): |
635 | """Source startup.""" |
636 | - if self.__activated: return |
637 | + if self.__activated: |
638 | + return |
639 | self.__activated = True |
640 | self.test_can_play_mp3() |
641 | - rb.Source.do_impl_activate (self) |
642 | - |
643 | + rb.Source.do_impl_activate(self) |
644 | + |
645 | def do_impl_want_uri(self, uri): |
646 | """I want to handle u1ms URLs""" |
647 | if uri.startswith("u1ms://"): |
648 | @@ -326,7 +362,7 @@ |
649 | """Handler for end of stream from the check-mp3 pipeline. |
650 | If we reach the end of the stream, mp3 playback is enabled.""" |
651 | self.install_pipeline.set_state(gst.STATE_NULL) |
652 | - if os.environ.has_key("U1INSTALLMP3ANYWAY"): |
653 | + if os.environ.get("U1INSTALLMP3ANYWAY", None) is not None: |
654 | # override the decision not to install the package |
655 | self.install_mp3_playback() |
656 | else: |
657 | @@ -349,7 +385,7 @@ |
658 | self.install_label_body.set_alignment(0.0, 0.5) |
659 | self.install_label_eula = gtk.Label() |
660 | # EULA text copied from |
661 | - # /var/lib/dpkg/info/gstreamer0.10-fluendo-plugins-mp3-partner.templates |
662 | + # gstreamer0.10-fluendo-plugins-mp3-partner.templates |
663 | # The partner package shows the EULA itself on installations, but |
664 | # aptdaemon installations work like DEBIAN_FRONTEND=noninteractive |
665 | # so we show the EULA here. (This also avoids a popup window.) |
666 | @@ -365,7 +401,7 @@ |
667 | "unless the seller has received a license by Fraunhofer IIS" |
668 | "and Thomson and pay the relevant royalties to them.</small>") |
669 | self.install_label_eula.set_alignment(0.0, 0.5) |
670 | - self.install_label_eula.set_size_request(400,200) |
671 | + self.install_label_eula.set_size_request(400, 200) |
672 | self.install_label_eula.set_line_wrap(True) |
673 | self.install_hbtn = gtk.HButtonBox() |
674 | self.install_hbtn.set_layout(gtk.BUTTONBOX_END) |
675 | @@ -403,11 +439,10 @@ |
676 | dist="maverick", |
677 | comps=["partner"], |
678 | comment="added by U1MusicStoreWidget", |
679 | - sourcesfile=PARTNER_LIST, defer=True) |
680 | + sourcesfile=PARTNER_LIST) |
681 | yield trans.run(defer=True) |
682 | trans = yield self.ac.update_cache(sources_list=SOURCES_DIR |
683 | - + PARTNER_LIST, |
684 | - defer=True) |
685 | + + PARTNER_LIST) |
686 | self.update_progress = AptProgressBar(trans) |
687 | self.update_progress.show() |
688 | self.install_label_head.set_text("") |
689 | @@ -417,7 +452,7 @@ |
690 | self.install_vbox.pack_start(self.update_progress, expand=False) |
691 | trans.connect("finished", self._package_update_finished) |
692 | yield trans.run(defer=True) |
693 | - except Exception, e: |
694 | + except Exception, e: # pylint: disable=W0703 |
695 | self._on_error(e) |
696 | |
697 | @inline_callbacks |
698 | @@ -428,8 +463,7 @@ |
699 | self._on_error(transaction) |
700 | return |
701 | try: |
702 | - trans = yield self.ac.install_packages([PLUGIN_PACKAGENAME], |
703 | - defer=True) |
704 | + trans = yield self.ac.install_packages([PLUGIN_PACKAGENAME]) |
705 | self.install_progress = AptProgressBar(transaction) |
706 | self.install_progress.show() |
707 | self.install_label_head.set_text("") |
708 | @@ -439,7 +473,7 @@ |
709 | self.install_vbox.pack_start(self.install_progress, expand=False) |
710 | trans.connect("finished", self._package_install_finished) |
711 | yield trans.run(defer=True) |
712 | - except Exception, e: |
713 | + except Exception, e: # pylint: disable=W0703 |
714 | self._on_error(e) |
715 | |
716 | def _package_install_finished(self, trans, exit_code): |
717 | @@ -449,7 +483,8 @@ |
718 | gst.update_registry() |
719 | self.add_music_store_widget() |
720 | else: |
721 | - self._on_error("Could not find the %r package" % PLUGIN_PACKAGENAME) |
722 | + self._on_error( |
723 | + "Could not find the %r package" % PLUGIN_PACKAGENAME) |
724 | |
725 | def _on_error(self, error): |
726 | """Error handler for aptdaemon.""" |
727 | @@ -457,10 +492,10 @@ |
728 | problem_installing = _("There was a problem installing, sorry") |
729 | self.install_label_head.set_markup('<span weight="bold" size="larger">' |
730 | '%s</span>' % problem_installing) |
731 | - self.install_label_body.set_text(_('Check your internet connection and ' |
732 | - 'try again.')) |
733 | - for widget in ("install_progress", "update_progress"): |
734 | - widget = getattr(self, widget, None) |
735 | + self.install_label_body.set_text(_('Check your internet connection ' |
736 | + 'and try again.')) |
737 | + for widget_name in ("install_progress", "update_progress"): |
738 | + widget = getattr(self, widget_name, None) |
739 | if widget is not None: |
740 | widget.hide() |
741 | self.install_hbtn.show() |
742 | @@ -471,37 +506,39 @@ |
743 | self.show_all() |
744 | self.browser.set_no_show_all(True) |
745 | self.browser.set_property("visible", True) |
746 | - self.browser.connect("preview-mp3", self.re_emit_preview) |
747 | - self.browser.connect("play-library", self.re_emit_playlibrary) |
748 | - self.browser.connect("download-finished", self.re_emit_downloadfinished) |
749 | - self.browser.connect("url-loaded", self.re_emit_urlloaded) |
750 | + self.browser.connect("preview-mp3", |
751 | + self.re_emit_preview) |
752 | + self.browser.connect("play-library", |
753 | + self.re_emit_playlibrary) |
754 | + self.browser.connect("download-finished", |
755 | + self.re_emit_downloadfinished) |
756 | + self.browser.connect("url-loaded", |
757 | + self.re_emit_urlloaded) |
758 | |
759 | - def do_impl_can_pause(self): |
760 | + def do_impl_can_pause(self): |
761 | """Implementation can pause. |
762 | If we don't handle this, Rhythmbox segfaults.""" |
763 | - return True # so we can pause, else we segfault |
764 | + return True # so we can pause, else we segfault |
765 | |
766 | def re_emit_preview(self, widget, url, title): |
767 | - """Handle the preview-mp3 signal and re-emit it to the rb.Plugin.""" |
768 | + """Handle the preview-mp3 signal and re-emit it to rb.Plugin.""" |
769 | self.emit("preview-mp3", url, title) |
770 | |
771 | def re_emit_playlibrary(self, widget, path): |
772 | - """Handle the play-library signal and re-emit it to the rb.Plugin.""" |
773 | + """Handle the play-library signal and re-emit it to rb.Plugin.""" |
774 | self.emit("play-library", path) |
775 | |
776 | def re_emit_downloadfinished(self, widget, path): |
777 | - """Handle the download-finished signal and re-emit it to the rb.Plugin.""" |
778 | + """Handle the download-finished signal and re-emit it to rb.Plugin.""" |
779 | self.emit("download-finished", path) |
780 | |
781 | def re_emit_urlloaded(self, widget, url): |
782 | - """Handle the url-loaded signal and re-emit it to the rb.Plugin.""" |
783 | + """Handle the url-loaded signal and re-emit it to rb.Plugin.""" |
784 | self.emit("url-loaded", url) |
785 | |
786 | - def do_set_property(self, property, value): |
787 | + def do_set_property(self, prop, value): |
788 | """Allow property settings to handle the plugin call.""" |
789 | - if property.name == 'plugin': |
790 | + if prop.name == 'plugin': |
791 | self.__plugin = value |
792 | else: |
793 | - raise AttributeError, 'unknown property %s' % property.name |
794 | - |
795 | - |
796 | + raise AttributeError('unknown property %s' % prop.name) |
797 | |
798 | === modified file 'umusicstore/U1MSLinks.py' |
799 | --- umusicstore/U1MSLinks.py 2010-09-20 18:02:02 +0000 |
800 | +++ umusicstore/U1MSLinks.py 2010-12-21 15:44:57 +0000 |
801 | @@ -16,22 +16,35 @@ |
802 | # |
803 | # Authored by Stuart Langridge <stuart.langridge@canonical.com> |
804 | |
805 | -import urllib, xml.parsers, cgi, os, locale, operator, re, unicodedata |
806 | -import gtk, gio, glib |
807 | -import rb, rhythmdb |
808 | +# Import gtk+/gio bits here because order matters for some unknown reason |
809 | +import glib |
810 | +import gtk |
811 | +import gio |
812 | + |
813 | +import cgi |
814 | +import gettext |
815 | +import locale |
816 | +import operator |
817 | +import os |
818 | +import re |
819 | +import rhythmdb |
820 | +import unicodedata |
821 | +import urllib |
822 | +import xml.parsers |
823 | + |
824 | +from gettext import lgettext as _ |
825 | from xml.dom import minidom |
826 | + |
827 | try: |
828 | import gwibber.lib.gtk.widgets |
829 | - gwibber_available = True |
830 | + GWIBBER_AVAILABLE = True |
831 | except ImportError: |
832 | - gwibber_available = False |
833 | + GWIBBER_AVAILABLE = False |
834 | |
835 | -import gettext |
836 | -from gettext import lgettext as _ |
837 | gettext.bindtextdomain("U1MSURL", "/usr/share/locale") |
838 | gettext.textdomain("U1MSURL") |
839 | |
840 | -ui_str = \ |
841 | +UI_STR = \ |
842 | """<ui> |
843 | <menubar name="MenuBar"> |
844 | <menu name="ViewMenu" action="View"> |
845 | @@ -53,12 +66,10 @@ |
846 | "the song in the Ubuntu One Music Store."), |
847 | "could-not-find": _("Unable to automatically find the song that is " |
848 | "currently playing in the Ubuntu One Music Store. " |
849 | - "Please try searching manually." |
850 | - ), |
851 | + "Please try searching manually."), |
852 | "could-not-connect": _("Unable to look up the song (couldn't connect " |
853 | "to Ubuntu One). Please check your internet " |
854 | - "connection, or try again shortly.") |
855 | -} |
856 | + "connection, or try again shortly.")} |
857 | |
858 | BASE_URL = os.environ.get("U1MSLINK_BASE_URL", "https://one.ubuntu.com") |
859 | # getpreferredencoding isn't threadsafe, but we should be OK |
860 | @@ -66,10 +77,11 @@ |
861 | SCRUBBING_RE = re.compile(r"[\W\s]+", re.UNICODE) |
862 | CLEANING_RE = re.compile(r"\s+", re.UNICODE) |
863 | |
864 | -def normalize(a): |
865 | + |
866 | +def normalize(string): |
867 | """Normalize the given string, to increase the chances of a match""" |
868 | # rule #0 of unicode mangling: first, normalize |
869 | - na = unicodedata.normalize('NFKD', a) |
870 | + na = unicodedata.normalize('NFKD', string) |
871 | # then, strip everything that's not alphanumeric |
872 | na = re.sub(SCRUBBING_RE, "", na) |
873 | # \w leaves _s |
874 | @@ -79,39 +91,52 @@ |
875 | # finally, lowercase |
876 | na = na.lower() |
877 | # if there's anything left, go with that, otherwise rollback |
878 | - return na if na else a |
879 | - |
880 | -def modified_levenshtein(a,b): |
881 | - """Calculates the Levenshtein distance between a and b, but counts added |
882 | - characters as worth 0 (thus meaning that 'Foo' will match |
883 | - 'Foo (Radio Edit)' with a high degree of accuracy.)""" |
884 | - a = normalize(a) |
885 | - b = normalize(b) |
886 | - n, m = len(a), len(b) |
887 | - if n > m: |
888 | - # Make sure n <= m, to use O(min(n,m)) space |
889 | - a,b = b,a |
890 | - n,m = m,n |
891 | - |
892 | - current = range(n+1) |
893 | - for i in range(1,m+1): |
894 | - previous, current = current, [i]+[0]*n |
895 | - for j in range(1,n+1): |
896 | - add, delete = previous[j]+1, current[j-1]+1 |
897 | - change = previous[j-1] |
898 | - if a[j-1] != b[i-1]: |
899 | + return na if na else string |
900 | + |
901 | + |
902 | +def modified_levenshtein(start, end): |
903 | + """Calculates the Levenshtein distance between start and end, |
904 | + but counts added characters as worth 0 (thus meaning that 'Foo' will match |
905 | + 'Foo (Radio Edit)' with a high degree of accuracy.)""" |
906 | + start = normalize(start) |
907 | + end = normalize(end) |
908 | + ls, le = len(start), len(end) |
909 | + if ls > le: |
910 | + # Make sure ls <= le, to use O(min(ls, le)) space |
911 | + start, end = end, start |
912 | + ls, le = le, ls |
913 | + |
914 | + current = range(ls + 1) |
915 | + for pose in range(1, le + 1): |
916 | + previous, current = current, [pose] + [0] * ls |
917 | + for poss in range(1, ls + 1): |
918 | + delete = current[poss - 1] + 1 |
919 | + change = previous[poss - 1] |
920 | + if start[poss - 1] != end[pose - 1]: |
921 | change = change + 1 |
922 | # replace add with 10000 to not count adds |
923 | - current[j] = min(10000, delete, change) |
924 | - |
925 | - return current[n] |
926 | + current[poss] = min(10000, delete, change) |
927 | + |
928 | + return current[ls] |
929 | + |
930 | |
931 | class U1MSLinkProvider(object): |
932 | - """Get a public link for any playing song to buy it in |
933 | + """Get a public link for any playing song to buy it in |
934 | the Ubuntu One Music Store.""" |
935 | |
936 | def __init__(self, find_file): |
937 | self.find_file = find_file |
938 | + self.track_fetch = None |
939 | + self.artist_fetch = None |
940 | + self.win = None |
941 | + self.button = None |
942 | + self.action_group = None |
943 | + self.builder = None |
944 | + self.pvb = None |
945 | + self.tweet_button = None |
946 | + self.message = None |
947 | + self.ui_id = None |
948 | + self.image = None |
949 | |
950 | def activate(self, shell): |
951 | """Plugin startup.""" |
952 | @@ -125,7 +150,7 @@ |
953 | self.action_group = gtk.ActionGroup('U1MSLinkPluginActions') |
954 | self.action_group.add_action(action) |
955 | manager.insert_action_group(self.action_group, 0) |
956 | - self.ui_id = manager.add_ui_from_string(ui_str) |
957 | + self.ui_id = manager.add_ui_from_string(UI_STR) |
958 | manager.ensure_update() |
959 | |
960 | def deactivate(self, shell): |
961 | @@ -136,6 +161,7 @@ |
962 | manager.ensure_update() |
963 | |
964 | def dialog_response_cb(self, dialog, response_id): |
965 | + """Destroy the window.""" |
966 | self.win.destroy() |
967 | self.win = None |
968 | |
969 | @@ -173,8 +199,9 @@ |
970 | _("Looking up <i>%s</i> by <i>%s</i> from <i>%s</i>") % ( |
971 | cgi.escape(title), cgi.escape(artist), cgi.escape(album))) |
972 | self.lookup_artist(title, artist, album) |
973 | - |
974 | + |
975 | def display_error(self, messagename): |
976 | + """Display error text and a warning icon.""" |
977 | self.builder.get_object("lblProgress").set_markup(ERRORS[messagename]) |
978 | self.image.set_from_icon_name("dialog-warning", |
979 | gtk.ICON_SIZE_DIALOG) |
980 | @@ -184,12 +211,13 @@ |
981 | base_url = "http://api.7digital.com/1.2/artist/search" |
982 | params = {"q": artist.encode("utf-8", "replace"), |
983 | "oauth_consumer_key": "canonical", |
984 | - "country":"GB"} |
985 | + "country": "GB"} |
986 | url = "%s?%s" % (base_url, urllib.urlencode(params)) |
987 | self.artist_fetch = gio.File(url) |
988 | - self.artist_fetch.read_async(self.artist_fetched, |
989 | + self.artist_fetch.read_async( |
990 | + self.artist_fetched, |
991 | user_data=(title, artist, album)) |
992 | - |
993 | + |
994 | def artist_fetched(self, gdaemonfile, result, user_data): |
995 | """Artist query is complete""" |
996 | title, artist, album = user_data |
997 | @@ -217,8 +245,7 @@ |
998 | possibles.append(( |
999 | anode.getAttribute("id"), |
1000 | modified_levenshtein(name, artist), |
1001 | - name |
1002 | - )) |
1003 | + name)) |
1004 | possibles.sort(key=operator.itemgetter(1)) |
1005 | if not possibles: |
1006 | self.display_error('could-not-find') |
1007 | @@ -227,7 +254,7 @@ |
1008 | artist_id = possibles[0][0] |
1009 | print "got artist %s" % possibles[0][2] |
1010 | self.lookup_track(title, artist, album, artist_id) |
1011 | - |
1012 | + |
1013 | def lookup_track(self, title, artist, album, artist_id): |
1014 | """Use the 7digital public API to look up the song.""" |
1015 | # There is no way of searching the 7digital API and saying |
1016 | @@ -238,7 +265,7 @@ |
1017 | params = {"q": "%s %s" % (artist.encode("utf-8", "replace"), |
1018 | title.encode("utf-8", "replace")), |
1019 | "oauth_consumer_key": "canonical", |
1020 | - "country":"GB", "pagesize": 50} |
1021 | + "country": "GB", "pagesize": 50} |
1022 | url = "%s?%s" % (base_url, urllib.urlencode(params)) |
1023 | self.track_fetch = gio.File(url) |
1024 | self.track_fetch.read_async(self.track_fetched, |
1025 | @@ -263,27 +290,35 @@ |
1026 | possibles = [] |
1027 | for tnode in tracknodes: |
1028 | anodes = tnode.getElementsByTagName("artist") |
1029 | - if not anodes: continue |
1030 | + if not anodes: |
1031 | + continue |
1032 | aid = anodes[0].getAttribute("id") |
1033 | if aid == artist_id: |
1034 | artist_score = 0 |
1035 | artist_name = artist |
1036 | else: |
1037 | atnodes = anodes[0].getElementsByTagName("name") |
1038 | - if not atnodes: continue |
1039 | - if not atnodes[0].hasChildNodes(): continue |
1040 | + if not atnodes: |
1041 | + continue |
1042 | + if not atnodes[0].hasChildNodes(): |
1043 | + continue |
1044 | # a +100 penalty for not being the right artist |
1045 | artist_score = 100 + modified_levenshtein( |
1046 | atnodes[0].firstChild.nodeValue, artist) |
1047 | artist_name = atnodes[0].firstChild.nodeValue |
1048 | nnodes = tnode.getElementsByTagName("title") |
1049 | - if not nnodes: continue |
1050 | - if not nnodes[0].hasChildNodes(): continue |
1051 | + if not nnodes: |
1052 | + continue |
1053 | + if not nnodes[0].hasChildNodes(): |
1054 | + continue |
1055 | rnodes = tnode.getElementsByTagName("release") |
1056 | - if not rnodes: continue |
1057 | + if not rnodes: |
1058 | + continue |
1059 | rtnodes = rnodes[0].getElementsByTagName("title") |
1060 | - if not rtnodes: continue |
1061 | - if not rtnodes[0].hasChildNodes(): continue |
1062 | + if not rtnodes: |
1063 | + continue |
1064 | + if not rtnodes[0].hasChildNodes(): |
1065 | + continue |
1066 | track_score = modified_levenshtein( |
1067 | nnodes[0].firstChild.nodeValue, title) |
1068 | album_score = modified_levenshtein( |
1069 | @@ -310,32 +345,36 @@ |
1070 | match = possibles[0] |
1071 | print "got a match", match |
1072 | dest_url = "%s/music/l/%s/%s" % ( |
1073 | - BASE_URL, match["trackid"], "0") # this 0 should be userid |
1074 | - self.builder.get_object("lblProgress").set_markup(_("Found <i>%s</i> by <i>%s</i> from <i>%s</i>") % ( |
1075 | - cgi.escape(match["track"]), cgi.escape(match["artist"]), |
1076 | - cgi.escape(match["album"]))) |
1077 | - self.builder.get_object("lblURL").set_markup("<big><b>%s</b></big>" % dest_url) |
1078 | + BASE_URL, match["trackid"], "0") # this 0 should be userid |
1079 | + self.builder.get_object("lblProgress").set_markup( |
1080 | + _("Found <i>%s</i> by <i>%s</i> from <i>%s</i>") % ( |
1081 | + cgi.escape(match["track"]), cgi.escape(match["artist"]), |
1082 | + cgi.escape(match["album"]))) |
1083 | + self.builder.get_object("lblURL").set_markup( |
1084 | + "<big><b>%s</b></big>" % dest_url) |
1085 | clipboard = gtk.Clipboard( |
1086 | gtk.gdk.display_manager_get().get_default_display(), "CLIPBOARD") |
1087 | clipboard.set_text(dest_url) |
1088 | |
1089 | - if gwibber_available: |
1090 | + if GWIBBER_AVAILABLE: |
1091 | self.tweet_button = gtk.Button("Tweet this link") |
1092 | - self.tweet_button.connect("clicked", self.gwibber, dest_url, |
1093 | + self.tweet_button.connect("clicked", self.gwibber, dest_url, |
1094 | artist, album, title) |
1095 | self.win.get_content_area().pack_end(self.tweet_button) |
1096 | self.tweet_button.show() |
1097 | - |
1098 | + |
1099 | def gwibber(self, button, url, artist, album, title): |
1100 | + """Show the Gwibber posting widget.""" |
1101 | self.pvb = gwibber.lib.gtk.widgets.GwibberPosterVBox() |
1102 | - self.message = "Currently listening to %s by %s %s" % (title, artist, url) |
1103 | - self.pvb.input.connect("expose-event", self.gwibber_input_text) |
1104 | - self.pvb.button_send.connect("clicked", |
1105 | + self.message = "Currently listening to %s by %s %s" % ( |
1106 | + title, artist, url) |
1107 | + self.pvb.input.connect("expose-event", self.gwibber_input_text) |
1108 | + self.pvb.button_send.connect("clicked", |
1109 | lambda x: self.builder.get_object("winMain").destroy()) |
1110 | self.pvb.show_all() |
1111 | self.builder.get_object("vbMain").pack_end(self.pvb) |
1112 | self.tweet_button.hide() |
1113 | |
1114 | def gwibber_input_text(self, *args): |
1115 | + """Set the Gwibber text input.""" |
1116 | self.pvb.input.set_text(self.message) |
1117 | - |
1118 | |
1119 | === modified file 'umusicstore/__init__.py' |
1120 | --- umusicstore/__init__.py 2010-09-23 16:36:08 +0000 |
1121 | +++ umusicstore/__init__.py 2010-12-21 15:44:57 +0000 |
1122 | @@ -17,23 +17,25 @@ |
1123 | # Authored by Stuart Langridge <stuart.langridge@canonical.com> |
1124 | |
1125 | import gconf |
1126 | -from MusicStoreWidget import U1MusicStoreWidget |
1127 | -from U1MSLinks import U1MSLinkProvider |
1128 | - |
1129 | -U1_FIRST_TIME_FLAG_ENTRY = "/apps/rhythmbox/plugins/umusicstore/first_time_flag" |
1130 | - |
1131 | import rb |
1132 | |
1133 | +from .MusicStoreWidget import U1MusicStoreWidget |
1134 | +from .U1MSLinks import U1MSLinkProvider |
1135 | + |
1136 | +U1_FIRST_TIME_FLAG_ENTRY = \ |
1137 | + "/apps/rhythmbox/plugins/umusicstore/first_time_flag" |
1138 | + |
1139 | + |
1140 | class U1MusicStorePlugin (rb.Plugin): |
1141 | """The Ubuntu One Music Store.""" |
1142 | |
1143 | def __init__(self): |
1144 | rb.Plugin.__init__(self) |
1145 | - |
1146 | + |
1147 | # The Music Store itself |
1148 | self.music_store_widget = U1MusicStoreWidget( |
1149 | plugin=self, find_file=self.find_file) |
1150 | - |
1151 | + |
1152 | # The Links button |
1153 | self.music_store_links_provider = U1MSLinkProvider( |
1154 | find_file=self.find_file) |
1155 | @@ -43,8 +45,8 @@ |
1156 | self.music_store_widget.activate(shell) |
1157 | self.music_store_links_provider.activate(shell) |
1158 | |
1159 | - # Select the source if it's the first time |
1160 | - conf_client = gconf.client_get_default () |
1161 | + # Select the source if it's the first time |
1162 | + conf_client = gconf.client_get_default() |
1163 | if not conf_client.get_bool(U1_FIRST_TIME_FLAG_ENTRY): |
1164 | shell.props.sourcelist.select(self.music_store_widget.source) |
1165 | conf_client.set_bool(U1_FIRST_TIME_FLAG_ENTRY, True) |
1166 | |
1167 | === removed file 'umusicstore/umusicstore.rb-plugin' |
1168 | --- umusicstore/umusicstore.rb-plugin 2010-07-21 16:03:11 +0000 |
1169 | +++ umusicstore/umusicstore.rb-plugin 1970-01-01 00:00:00 +0000 |
1170 | @@ -1,10 +0,0 @@ |
1171 | -[RB Plugin] |
1172 | -Loader=python |
1173 | -Module=umusicstore |
1174 | -IAge=1 |
1175 | -Name=Ubuntu One Music Store |
1176 | -Description=The Ubuntu One Music Store |
1177 | -Authors=Stuart Langridge <stuart.langridge@canonical.com>, Rodrigo Moya <rodrigo.moya@canonical.com> |
1178 | -Copyright=Copyright © 2009 Canonical |
1179 | -Website=http://one.ubuntu.com/ |
1180 | - |