Merge lp:~dobey/rhythmbox-ubuntuone/update-4-2 into lp:rhythmbox-ubuntuone/stable-4-2

Proposed by dobey
Status: Merged
Approved by: dobey
Approved revision: no longer in the source branch.
Merged at revision: 122
Proposed branch: lp:~dobey/rhythmbox-ubuntuone/update-4-2
Merge into: lp:rhythmbox-ubuntuone/stable-4-2
Diff against target: 423 lines (+48/-291)
7 files modified
po/POTFILES.in (+0/-2)
rhythmbox-ubuntuone.desktop.in (+0/-12)
run-tests (+3/-0)
setup.cfg (+1/-1)
setup.py (+0/-1)
ubuntuone/MusicStoreWidget.py (+0/-265)
ubuntuone/ubuntuone.py (+44/-10)
To merge this branch: bzr merge lp:~dobey/rhythmbox-ubuntuone/update-4-2
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Review via email: mp+142395@code.launchpad.net

Commit message

[Rodney Dawes]

    Update setup.py to remove MusicStoreWidget.py as well.
    Update POTFILES.in
    Remove the .desktop file as we don't need it any more
    Run setup.py build and clean in the run-tests script for basic checks
    Remove the UI and source for the music store
    Switch to using DownloadFinished directly from syncdaemon

To post a comment you must log in.
Revision history for this message
Roberto Alsina (ralsina) :
review: Approve
122. By dobey

[r=dobey] [Rodney Dawes]

    Update setup.py to remove MusicStoreWidget.py as well.
    Update POTFILES.in
    Remove the .desktop file as we don't need it any more
    Run setup.py build and clean in the run-tests script for basic checks
    Remove the UI and source for the music store
    Switch to using DownloadFinished directly from syncdaemon

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2012-02-23 00:50:54 +0000
+++ po/POTFILES.in 2013-01-08 20:17:25 +0000
@@ -1,5 +1,3 @@
1rhythmbox-ubuntuone.desktop.in
2ubuntuone/ubuntuone.py1ubuntuone/ubuntuone.py
3ubuntuone/MusicStoreWidget.py
4[type: gettext/ini]ubuntuone/ubuntuone.plugin.in2[type: gettext/ini]ubuntuone/ubuntuone.plugin.in
53
64
=== removed file 'rhythmbox-ubuntuone.desktop.in'
--- rhythmbox-ubuntuone.desktop.in 2012-03-07 16:01:45 +0000
+++ rhythmbox-ubuntuone.desktop.in 1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
1[Desktop Entry]
2Name=Ubuntu One Music Store
3_Comment=Purchase music on Ubuntu One in Rhythmbox
4Exec=rhythmbox %U
5Terminal=false
6Type=Application
7Icon=rhythmbox
8Categories=GNOME;GTK;AudioVideo;
9MimeType=x-scheme-handler/u1ms
10StartupNotify=true
11X-Ubuntu-Gettext-Domain=rhythmbox-ubuntuone
12NoDisplay=true
130
=== modified file 'run-tests'
--- run-tests 2012-08-24 19:36:25 +0000
+++ run-tests 2013-01-08 20:17:25 +0000
@@ -14,6 +14,7 @@
14#14#
15# You should have received a copy of the GNU General Public License along15# You should have received a copy of the GNU General Public License along
16# with this program. If not, see <http://www.gnu.org/licenses/>.16# with this program. If not, see <http://www.gnu.org/licenses/>.
17./setup.py build
17export PYTHONPATH=ubuntuone18export PYTHONPATH=ubuntuone
18USE_PYFLAKES=1 u1lint .19USE_PYFLAKES=1 u1lint .
19if [ -x `which pep8` ]; then20if [ -x `which pep8` ]; then
@@ -22,3 +23,5 @@
22 echo "Please install the 'pep8' package."23 echo "Please install the 'pep8' package."
23fi24fi
24rm -rf _trial_temp25rm -rf _trial_temp
26./setup.py clean
27
2528
=== modified file 'setup.cfg'
--- setup.cfg 2012-02-23 00:50:54 +0000
+++ setup.cfg 2013-01-08 20:17:25 +0000
@@ -1,2 +1,2 @@
1[build_i18n]1[build_i18n]
2desktop_files=[("lib/rhythmbox/plugins/ubuntuone", ("ubuntuone/ubuntuone.plugin.in",)), ("share/applications", ("rhythmbox-ubuntuone.desktop.in",))]2desktop_files=[("lib/rhythmbox/plugins/ubuntuone", ("ubuntuone/ubuntuone.plugin.in",))]
33
=== modified file 'setup.py'
--- setup.py 2012-12-07 18:50:52 +0000
+++ setup.py 2013-01-08 20:17:25 +0000
@@ -15,6 +15,5 @@
15 url='https://launchpad.net/rhythmbox-ubuntuone',15 url='https://launchpad.net/rhythmbox-ubuntuone',
16 data_files=[('lib/rhythmbox/plugins/ubuntuone',16 data_files=[('lib/rhythmbox/plugins/ubuntuone',
17 ['ubuntuone/ubuntuone.py',17 ['ubuntuone/ubuntuone.py',
18 'ubuntuone/MusicStoreWidget.py',
19 ])],18 ])],
20)19)
2120
=== removed file 'ubuntuone/MusicStoreWidget.py'
--- ubuntuone/MusicStoreWidget.py 2012-12-07 15:06:25 +0000
+++ ubuntuone/MusicStoreWidget.py 1970-01-01 00:00:00 +0000
@@ -1,265 +0,0 @@
1# Copyright (C) 2009-2012 Canonical, Ltd.
2#
3# This library is free software; you can redistribute it and/or modify
4# it under the terms of the GNU Lesser General Public License
5# version 3.0 as published by the Free Software Foundation.
6#
7# This library is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10# GNU Lesser General Public License version 3.0 for more details.
11#
12# You should have received a copy of the GNU Lesser General Public
13# License along with this library. If not, see
14# <http://www.gnu.org/licenses/>.
15"""The Ubuntu One Rhythmbox plugin."""
16
17from __future__ import print_function, unicode_literals
18
19import gettext
20import os
21
22# pylint: disable=E0611,F0401
23from gi.repository import Gio, GObject, Gtk, RB
24from gi.repository.UbuntuOneUI import MusicStore as U1MusicStore
25# pylint: enable=E0611,F0401
26
27from gettext import lgettext as _
28parseurl = None
29try:
30 import urllib.parse
31 parseurl = urllib.parse.urlparse
32except ImportError:
33 import urlparse
34 parseurl = urlparse.urlparse
35
36gettext.bindtextdomain("rhythmbox-ubuntuone", "/usr/share/locale")
37gettext.textdomain("rhythmbox-ubuntuone")
38
39MUSIC_STORE_WIDGET = U1MusicStore()
40U1LIBRARYPATH = MUSIC_STORE_WIDGET.get_library_location()
41
42
43class U1EntryType(RB.RhythmDBEntryType):
44 """Entry type for the Ubuntu One Music Store source."""
45
46 def __init__(self):
47 RB.RhythmDBEntryType.__init__(self, name='ubuntuone')
48
49 def do_can_sync_metadata(self, entry):
50 """Not a real source, so we can't sync metadata."""
51 return False
52
53 def do_sync_metadata(self, entry, changes):
54 """Do nothing."""
55 return
56
57
58class U1MusicStoreWidget(object):
59 """The Ubuntu One Music Store."""
60 def __init__(self, plugin):
61 self.plugin = plugin
62 self.db = None
63 self.shell = None
64 self.source = None
65 self.entry_type = U1EntryType()
66
67 def activate(self, shell):
68 """Plugin startup."""
69 self.db = shell.get_property("db")
70 group = RB.DisplayPageGroup.get_by_id("stores")
71
72 icon = Gtk.IconTheme.get_default().load_icon(
73 "ubuntuone", 24, 0)
74
75 self.db.register_entry_type(self.entry_type)
76
77 self.source = GObject.new(U1Source,
78 shell=shell,
79 entry_type=self.entry_type,
80 pixbuf=icon,
81 plugin=self.plugin)
82 shell.register_entry_type_for_source(self.source, self.entry_type)
83 shell.append_display_page(self.source, group)
84
85 self.shell = shell
86 self.source.connect("preview-mp3", self.play_preview_mp3)
87 self.source.connect("play-library", self.play_library)
88 self.source.connect("download-finished", self.download_finished)
89 self.source.connect("url-loaded", self.url_loaded)
90
91 self.source.props.query_model = RB.RhythmDBQueryModel.new_empty(
92 self.db)
93
94 def deactivate(self, shell):
95 """Plugin shutdown."""
96 # remove source
97 self.source.delete_thyself()
98 # delete held references
99 del self.db
100 del self.source
101 del self.shell
102
103 def url_loaded(self, source, url):
104 """A URL is loaded in the plugin"""
105 if parseurl(url)[2] == "https":
106 pass
107 else:
108 pass
109
110 def _udf_path_to_library_uri(self, path):
111 """Build a URI from the path for the song in the library."""
112 if path.startswith(U1LIBRARYPATH):
113 library_path = path
114 else:
115 subpath = path
116 if subpath.startswith("/"):
117 subpath = subpath[1:]
118 library_path = os.path.join(U1LIBRARYPATH, subpath)
119 # convert path to URI. Don't use urllib for this; Python and
120 # glib escape URLs differently. gio does it the glib way.
121 return Gio.File.new_for_path(library_path).get_uri()
122
123 def download_finished(self, source, path):
124 """A file is finished downloading"""
125 library_uri = self._udf_path_to_library_uri(path)
126 # Import the URI
127 if not self.db.entry_lookup_by_location(library_uri):
128 self.db.add_uri(library_uri)
129
130 def play_library(self, source, path):
131 """Switch to and start playing a song from the library"""
132 uri = self._udf_path_to_library_uri(path)
133 entry = self.db.entry_lookup_by_location(uri)
134 if not entry:
135 print("couldn't find entry: %s" % uri)
136 return
137 libsrc = self.shell.props.library_source
138 artist_view, album_view = libsrc.get_property_views()[0:2]
139 song_view = libsrc.get_entry_view()
140 artist = entry.get_string(RB.RhythmDBPropType.ARTIST)
141 album = entry.get_string(RB.RhythmDBPropType.ALBUM)
142 self.shell.props.display_page_tree.select(libsrc)
143 artist_view.set_selection([artist])
144 album_view.set_selection([album])
145 song_view.scroll_to_entry(entry)
146 player = self.shell.get_property('shell-player')
147 player.stop()
148 player.play_entry(entry, libsrc)
149
150 def play_preview_mp3(self, source, url, title):
151 """Play a passed mp3; signal handler for preview-mp3 signal."""
152 # create an entry, don't save it, and play it
153 entry = RB.RhythmDBEntry.new(self.db, self.entry_type, url)
154 self.db.entry_set(entry, RB.RhythmDBPropType.TITLE, title)
155 player = self.shell.get_property('shell-player')
156 player.stop()
157 player.play_entry(entry, self.source)
158
159
160class U1Source(RB.Source):
161 """A Rhythmbox source widget for the U1 Music Store."""
162 # gproperties required so that rb.Source is instantiable
163 __gproperties__ = {
164 str('plugin'): (GObject.GObject, str('plugin'), str('plugin'),
165 GObject.PARAM_WRITABLE | GObject.PARAM_CONSTRUCT_ONLY),
166 }
167 # we have the preview-mp3 signal; we receive it from the widget, and
168 # re-emit it so that the plugin gets it, because the plugin actually
169 # plays the mp3
170 __gsignals__ = {
171 str("preview-mp3"): (GObject.SIGNAL_RUN_FIRST,
172 GObject.TYPE_NONE, (str, str)),
173 str("play-library"): (GObject.SIGNAL_RUN_FIRST,
174 GObject.TYPE_NONE, (str,)),
175 str("download-finished"): (GObject.SIGNAL_RUN_FIRST,
176 GObject.TYPE_NONE, (str,)),
177 str("url-loaded"): (GObject.SIGNAL_RUN_FIRST,
178 GObject.TYPE_NONE, (str,)),
179 }
180
181 def __init__(self):
182 RB.Source.__init__(self, name=_("Ubuntu One"))
183 self.browser = MUSIC_STORE_WIDGET
184 self.__activated = False
185 self.__plugin = None
186 self.add_music_store_widget()
187
188 def do_impl_activate(self):
189 """Source startup."""
190 if self.__activated:
191 return
192 self.__activated = True
193 RB.Source.do_impl_activate(self)
194
195 def do_impl_want_uri(self, uri):
196 """I want to handle u1ms URLs"""
197 if uri.startswith("u1ms://"):
198 return 100
199 return 0
200
201 def do_impl_add_uri(self, uri, title, genre, callback=None,
202 callback_data=None, destroy_data=None):
203 """Handle a u1ms URL"""
204 if not uri.startswith("u1ms://"):
205 return
206 uri_to_use = uri.replace("u1ms://", "http://")
207 # pylint: disable=E1101
208 shell = self.get_property("shell")
209 shell.props.display_page_tree.select(self)
210 self.browser.load_store_link(uri_to_use)
211 if callback is not None:
212 callback(callback_data)
213 if destroy_data is not None:
214 destroy_data(callback_data)
215
216 def add_music_store_widget(self):
217 """Display the music store widget in Rhythmbox."""
218 # pylint: disable=E1101
219 if self.browser.get_property('parent') is None:
220 self.add(self.browser)
221 else:
222 self.browser.reparent(self)
223 self.browser.show()
224 self.show()
225 self.browser.set_property("visible", True)
226 self.browser.connect("preview-mp3",
227 self.re_emit_preview)
228 self.browser.connect("play-library",
229 self.re_emit_playlibrary)
230 self.browser.connect("download-finished",
231 self.re_emit_downloadfinished)
232 self.browser.connect("url-loaded",
233 self.re_emit_urlloaded)
234
235 def do_impl_can_pause(self):
236 """Implementation can pause.
237 If we don't handle this, Rhythmbox segfaults."""
238 return True # so we can pause, else we segfault
239
240 def re_emit_preview(self, widget, url, title):
241 """Handle the preview-mp3 signal and re-emit it."""
242 # pylint: disable=E1101
243 self.emit("preview-mp3", url, title)
244
245 def re_emit_playlibrary(self, widget, path):
246 """Handle the play-library signal and re-emit it."""
247 # pylint: disable=E1101
248 self.emit("play-library", path)
249
250 def re_emit_downloadfinished(self, widget, path):
251 """Handle the download-finished signal and re-emit it."""
252 # pylint: disable=E1101
253 self.emit("download-finished", path)
254
255 def re_emit_urlloaded(self, widget, url):
256 """Handle the url-loaded signal and re-emit it."""
257 # pylint: disable=E1101
258 self.emit("url-loaded", url)
259
260 def do_set_property(self, prop, value):
261 """Allow property settings to handle the plug-in call."""
262 if prop.name == 'plugin':
263 self.__plugin = value
264 else:
265 raise AttributeError('unknown property %s' % prop.name)
2660
=== modified file 'ubuntuone/ubuntuone.py'
--- ubuntuone/ubuntuone.py 2012-08-24 19:36:25 +0000
+++ ubuntuone/ubuntuone.py 2013-01-08 20:17:25 +0000
@@ -16,13 +16,14 @@
1616
17from __future__ import print_function, unicode_literals17from __future__ import print_function, unicode_literals
1818
19# pylint: disable=E061119import os
20
21from dbus import SessionBus, DBusException
22from dirspec.utils import user_home
20from gi.repository import Gio, GObject, Peas23from gi.repository import Gio, GObject, Peas
21# pylint: enable=E0611
2224
23# pylint: disable=W040325U1LIBRARYPATH = os.path.join(user_home, '.ubuntuone',
24from MusicStoreWidget import U1MusicStoreWidget, U1LIBRARYPATH26 'Purchased from Ubuntu One')
25# pylint: enable=W0403
2627
2728
28class UbuntuOnePlugin (GObject.GObject, Peas.Activatable):29class UbuntuOnePlugin (GObject.GObject, Peas.Activatable):
@@ -32,14 +33,19 @@
3233
33 def __init__(self):34 def __init__(self):
34 GObject.GObject.__init__(self)35 GObject.GObject.__init__(self)
36 self.db = None
37
38 # Connect to the session bus
39 self._signal = None
40 try:
41 self._bus = SessionBus()
42 except DBusException:
43 return
3544
36 # RhythmDB settings so we can handle changes45 # RhythmDB settings so we can handle changes
37 self.rdbconf = Gio.Settings('org.gnome.rhythmbox.rhythmdb')46 self.rdbconf = Gio.Settings('org.gnome.rhythmbox.rhythmdb')
38 self.rdbconf.connect('changed::locations', self._locations_changed)47 self.rdbconf.connect('changed::locations', self._locations_changed)
3948
40 # The Music Store itself
41 self.music_store_widget = U1MusicStoreWidget(plugin=self)
42
43 def _locations_changed(self, *args, **kwargs):49 def _locations_changed(self, *args, **kwargs):
44 """Handle the locations setting being changed."""50 """Handle the locations setting being changed."""
45 libraries = self.rdbconf.get_strv('locations')51 libraries = self.rdbconf.get_strv('locations')
@@ -57,12 +63,40 @@
57 libraries.remove(unescaped_path)63 libraries.remove(unescaped_path)
58 self.rdbconf.set_strv('locations', libraries)64 self.rdbconf.set_strv('locations', libraries)
5965
66 def download_finished(self, path, info):
67 """A file is finished downloading"""
68 if not path.startswith(U1LIBRARYPATH):
69 return
70
71 # convert path to URI. Don't use urllib for this; Python and
72 # glib escape URLs differently. gio does it the glib way.
73 library_uri = Gio.File.new_for_path(path).get_uri()
74
75 # Import the URI
76 if not self.db.entry_lookup_by_location(library_uri):
77 self.db.add_uri(library_uri)
78
60 def do_activate(self):79 def do_activate(self):
61 """Plug-in startup."""80 """Plug-in startup."""
62 # Add the Ubuntu One purchased music directory if not already added81 # Add the Ubuntu One purchased music directory if not already added
63 self._locations_changed()82 self._locations_changed()
64 self.music_store_widget.activate(self.object)83 # Get a reference to the db
84 self.db = self.object.get_property('db')
85
86 # Connect to the download finished from syncdaemon
87 try:
88 self._bus.add_signal_receiver(self.download_finished,
89 signal_name='DownloadFinished')
90 except DBusException:
91 return
6592
66 def do_deactivate(self):93 def do_deactivate(self):
67 """Plug-in shutdown."""94 """Plug-in shutdown."""
68 self.music_store_widget.deactivate(self.object)95 del self.db
96
97 # Disconnect the signal handler for downloads
98 try:
99 self.bus.remove_signal_handler(self.download_finished,
100 signal_name='DownloadFinished')
101 except DBusException:
102 return

Subscribers

People subscribed via source and target branches

to all changes: