Merge lp:~chipaca/rhythmbox-ubuntuone/brown-paper-bags into lp:rhythmbox-ubuntuone

Proposed by John Lenton
Status: Merged
Merge reported by: Rodrigo Moya
Merged at revision: not available
Proposed branch: lp:~chipaca/rhythmbox-ubuntuone/brown-paper-bags
Merge into: lp:rhythmbox-ubuntuone
Diff against target: 424 lines (+6/-400)
1 file modified
umusicstore/__init__.py (+6/-400)
To merge this branch: bzr merge lp:~chipaca/rhythmbox-ubuntuone/brown-paper-bags
Reviewer Review Type Date Requested Status
Ubuntu One Control Tower Pending
Review via email: mp+30575@code.launchpad.net

Description of the change

resolved the conflict

To post a comment you must log in.
Revision history for this message
Rodrigo Moya (rodrigo-moya) wrote :

Sorry, didn't see this branch last night, so applied it manually to trunk and did a new release, so marking this as merged

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'umusicstore/__init__.py'
2--- umusicstore/__init__.py 2010-06-08 15:19:02 +0000
3+++ umusicstore/__init__.py 2010-07-21 20:25:57 +0000
4@@ -16,29 +16,14 @@
5 #
6 # Authored by Stuart Langridge <stuart.langridge@canonical.com>
7
8-import gtk, gobject, os, urllib, gconf, stat, urlparse, gio
9-import gst, gst.pbutils
10-import aptdaemon.client
11-from aptdaemon.enums import *
12-from aptdaemon.gtkwidgets import AptErrorDialog, \
13- AptProgressBar
14-import rb, rhythmdb
15-from ubuntuone.gtkwidgets import MusicStore as U1MusicStore
16+
17+import gconf
18 from MusicStoreWidget import U1MusicStoreWidget
19 from U1MSLinks import U1MSLinkProvider
20-import xdg.BaseDirectory
21-import dbus.exceptions
22-
23-import gettext
24-from gettext import lgettext as _
25-gettext.bindtextdomain("rhythmbox-ubuntuone-music-store", "/usr/share/locale")
26-gettext.textdomain("rhythmbox-ubuntuone-music-store")
27-
28-MUSIC_STORE_WIDGET = U1MusicStore() # keep this around for later
29-U1LIBRARYPATH = MUSIC_STORE_WIDGET.get_library_location()
30-RB_LIBRARY_LOCATIONS = "/apps/rhythmbox/library_locations"
31-U1_CONFIG_PATH = "/apps/rhythmbox/plugins/umusicstore"
32-U1_FIRST_TIME_FLAG_ENTRY = U1_CONFIG_PATH + "/first_time_flag"
33+
34+U1_FIRST_TIME_FLAG_ENTRY = "/apps/rhythmbox/plugins/umusicstore/first_time_flag"
35+
36+import rb
37
38 class U1MusicStorePlugin (rb.Plugin):
39 """The Ubuntu One Music Store."""
40@@ -67,384 +52,5 @@
41
42 def deactivate(self, shell):
43 """Plugin shutdown."""
44-<<<<<<< TREE
45- # remove source
46- self.source.delete_thyself()
47- # remove the library, if it's empty
48- try:
49- filecount = len(os.listdir(self.U1_LIBRARY_SYMLINK))
50- except OSError:
51- # symlink is dangling
52- # so they never downloaded anything
53- filecount = 0
54- if filecount == 0:
55- client = gconf.client_get_default()
56- libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING)
57- if self.u1_library_path_url in libraries:
58- client.notify_remove(self.library_adder)
59- libraries.remove(self.u1_library_path_url)
60- client.set_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING, libraries)
61- # delete held references
62- del self.db
63- del self.source
64- del self.shell
65-
66- def url_loaded(self, source, url):
67- """A URL is loaded in the plugin"""
68- print "URL loaded:", url
69- if urlparse.urlparse(url).scheme == "https":
70- pass
71- else:
72- pass
73-
74- def _udf_path_to_library_uri(self, path):
75- """Calculate the path in the library.
76- Since the library is accessed via the created symlink, but the path
77- passed to us is to a file in the actual music store UDF, we need to
78- work out the path inside the library, i.e., what the path to that file
79- is via the symlink."""
80-
81- if path.startswith(U1LIBRARYPATH):
82- subpath = path[len(U1LIBRARYPATH):]
83- else:
84- subpath = path
85- if subpath.startswith("/"): subpath = subpath[1:]
86- library_path = os.path.join(self.U1_LIBRARY_SYMLINK, subpath)
87- # convert path to URI. Don't use urllib for this; Python and
88- # glib escape URLs differently. gio does it the glib way.
89- library_uri = gio.File(library_path).get_uri()
90- return library_uri
91-
92- def download_finished(self, source, path):
93- """A file is finished downloading"""
94- library_uri = self._udf_path_to_library_uri(path)
95- # Import the URI
96- if not self.shell.props.db.entry_lookup_by_location(library_uri):
97- self.db.add_uri(library_uri)
98-
99- def play_library(self, source, path):
100- """Switch to and start playing a song from the library"""
101- uri = self._udf_path_to_library_uri(path)
102- entry = self.shell.props.db.entry_lookup_by_location(uri)
103- if not entry:
104- print "couldn't find entry", uri
105- return
106- libsrc = self.shell.props.library_source
107- genre_view, artist_view, album_view = libsrc.get_property_views()
108- song_view = libsrc.get_entry_view()
109- artist = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ARTIST)
110- album = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ALBUM)
111- self.shell.props.sourcelist.select(libsrc)
112- artist_view.set_selection([artist])
113- album_view.set_selection([album])
114- song_view.scroll_to_entry(entry)
115- player = self.shell.get_player()
116- player.stop()
117- player.play()
118- player.play_entry(entry, libsrc)
119-
120- def play_preview_mp3(self, source, url, title):
121- """Play a passed mp3; signal handler for preview-mp3 signal."""
122- # create an entry, don't save it, and play it
123- entry = self.shell.props.db.entry_lookup_by_location(url)
124- if entry is None:
125- entry = self.shell.props.db.entry_new(self.entry_type, url)
126- self.shell.props.db.set(entry, rhythmdb.PROP_TITLE, title)
127- player = self.shell.get_player()
128- player.stop()
129- player.play()
130- player.play_entry(entry, self.source)
131- # FIXME delete this entry when it finishes playing. Don't know how yet.
132-
133- def add_u1_library(self):
134- """Add the U1 library if not listed in RB and re-add if changed."""
135- u1_library_path_folder = xdg.BaseDirectory.save_data_path("ubuntuone")
136- # Ensure that we can write to the folder, because syncdaemon creates it
137- # with no write permissions
138- os.chmod(u1_library_path_folder,
139- os.stat(u1_library_path_folder)[stat.ST_MODE] | stat.S_IWUSR)
140- # Translators: this is the name under Music for U1 music in Rhythmbox
141- u1_library_path = os.path.join(u1_library_path_folder, _("Purchased from Ubuntu One"))
142- if not os.path.islink(u1_library_path):
143- if not os.path.exists(u1_library_path):
144- print "Attempting to symlink %s to %s" % (U1LIBRARYPATH,
145- u1_library_path)
146- os.symlink(U1LIBRARYPATH, u1_library_path)
147- else:
148- # something that isn't a symlink already exists. That's not
149- # supposed to happen.
150- # Write a warning and carry on.
151- print ("Warning: library location %s existed. It should have "
152- "been a symlink to %s, and it wasn't. This isn't supposed "
153- "to happen. Carrying on anyway, on the assumption that "
154- "you know what you're doing. If this is a problem, then "
155- "delete or rename %s.") % (u1_library_path, U1LIBRARYPATH,
156- u1_library_path)
157- self.u1_library_path_url = "file://%s" % urllib.quote(u1_library_path)
158- self.U1_LIBRARY_SYMLINK = u1_library_path
159- client = gconf.client_get_default()
160- self._add_u1_library_if_not_present(client)
161- self._remove_old_u1_library_if_present(client)
162- # Watch for changes to the gconf key and re-add the library
163- self.library_adder = client.notify_add(RB_LIBRARY_LOCATIONS,
164- self._add_u1_library_if_not_present)
165-
166- def _add_u1_library_if_not_present(self, client, *args, **kwargs):
167- """Check for the U1 library and add to libraries list."""
168- libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING)
169- if self.u1_library_path_url not in libraries:
170- libraries.append(self.u1_library_path_url)
171- client.set_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING, libraries)
172-
173- def _remove_old_u1_library_if_present(self, client, *args, **kwargs):
174- """Check for the old U1 library and remove it from libraries list."""
175- libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING)
176- removed = False
177- # originally, this was the library path. Someone might have this.
178- old_path = "file://%s" % os.path.expanduser("~/.ubuntuone/musicstore")
179- if old_path in libraries:
180- libraries.remove(old_path)
181- removed = True
182- # Then, this was the library path, which we put into gconf unescaped
183- actual_udf_path_unescaped = "file://%s" % U1LIBRARYPATH
184- if actual_udf_path_unescaped in libraries:
185- libraries.remove(actual_udf_path_unescaped)
186- removed = True
187- # In theory, no-one should have the escaped path, but let's check
188- actual_udf_path_escaped = "file://%s" % U1LIBRARYPATH
189- if actual_udf_path_escaped in libraries:
190- libraries.remove(actual_udf_path_escaped)
191- removed = True
192- # Also, remove any library which is in .local/share and *isn't*
193- # the current library. This caters for people who got the library
194- # created under one name (say, English) and then had it created
195- # under another (say, after a translation to Dutch)
196- u1_library_path_folder = xdg.BaseDirectory.save_data_path("ubuntuone")
197- u1_library_path_folder_url = "file://%s" % urllib.quote(u1_library_path_folder)
198- symlink_url = "file://" + urllib.quote(self.U1_LIBRARY_SYMLINK)
199- for l in libraries:
200- if l.startswith(u1_library_path_folder_url) and l != symlink_url:
201- libraries.remove(l)
202- # and delete the symlink itself
203- symlink_to_remove = urllib.unquote(l[7:])
204- os.unlink(symlink_to_remove)
205- removed = True
206- if removed:
207- client.set_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING, libraries)
208-
209-class U1Source(rb.Source):
210- """A Rhythmbox source widget for the U1 Music Store."""
211- # gproperties required so that rb.Source is instantiable
212- __gproperties__ = {
213- 'plugin': (rb.Plugin, 'plugin', 'plugin',
214- gobject.PARAM_WRITABLE|gobject.PARAM_CONSTRUCT_ONLY),
215- }
216- # we have the preview-mp3 signal; we receive it from the widget, and re-emit
217- # it so that the plugin gets it, because the plugin actually plays the mp3
218- __gsignals__ = {
219- "preview-mp3": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str, str)),
220- "play-library": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str,)),
221- "download-finished": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str,)),
222- "url-loaded": (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (str,)),
223- }
224-
225- def __init__(self):
226- rb.Source.__init__(self, name=_("Ubuntu One"))
227- self.__activated = False
228-
229- def do_impl_activate(self):
230- """Source startup."""
231- if self.__activated: return
232- self.__activated = True
233- self.test_can_play_mp3()
234- rb.Source.do_impl_activate (self)
235-
236- def test_can_play_mp3(self):
237- """Can the user play mp3s? Start a GStreamer pipeline to check."""
238- mp3pth = os.path.realpath(os.path.join(
239- os.path.split(__file__)[0], "empty.mp3"))
240- uri = "file://%s" % urllib.quote("%s" % mp3pth)
241- self.install_pipeline = gst.parse_launch(
242- 'uridecodebin uri=%s ! fakesink' % uri)
243- bus = self.install_pipeline.get_bus()
244- bus.add_signal_watch()
245- bus.connect("message::element", self._got_element_msg)
246- bus.connect("message::eos", self._got_end_of_stream)
247- self.install_pipeline.set_state(gst.STATE_PLAYING)
248-
249- def _got_element_msg(self, bus, msg):
250- """Handler for element messages from the check-mp3 pipeline.
251- GStreamer throws a "plugin-missing" element message if the
252- user does not have the right codecs to play a file."""
253- plugin_missing = gst.pbutils.is_missing_plugin_message(msg)
254- if plugin_missing:
255- self.install_pipeline.set_state(gst.STATE_NULL)
256- self.install_mp3_playback()
257-
258- def _got_end_of_stream(self, bus, msg):
259- """Handler for end of stream from the check-mp3 pipeline.
260- If we reach the end of the stream, mp3 playback is enabled."""
261- self.install_pipeline.set_state(gst.STATE_NULL)
262- if os.environ.has_key("U1INSTALLMP3ANYWAY"):
263- # override the decision not to install the package
264- self.install_mp3_playback()
265- else:
266- self.add_music_store_widget()
267-
268- def install_mp3_playback(self):
269- """Use aptdaemon to install the Fluendo mp3 playback codec package."""
270- self.install_box = gtk.Alignment(xscale=0.0, yscale=0.0, xalign=0.5,
271- yalign=0.5)
272- self.install_vbox = gtk.VBox()
273- self.install_label_head = gtk.Label()
274- self.install_label_head.set_use_markup(True)
275- not_installed = _("MP3 plugins are not installed")
276- self.install_label_head.set_markup('<span weight="bold" size="larger">'
277- '%s</span>' % not_installed)
278- self.install_label_head.set_alignment(0.0, 0.5)
279- self.install_label_body = gtk.Label()
280- self.install_label_body.set_text(_('To listen to your purchased songs'
281- ', you need to install MP3 plugins. Click below to install them.'))
282- self.install_label_body.set_alignment(0.0, 0.5)
283- self.install_label_eula = gtk.Label()
284- # EULA text copied from /var/lib/dpkg/info/gstreamer0.10-fluendo-plugins-mp3-partner.templates
285- # The partner package shows the EULA itself on installations, but
286- # aptdaemon installations work like DEBIAN_FRONTEND=noninteractive
287- # so we show the EULA here. (This also avoids a popup window.)
288- # EULA text is not translatable; do not wrap it with gettext!
289- self.install_label_eula.set_markup(
290- "<small>MPEG Layer-3 audio decoding technology notice\n"
291- "MPEG Layer-3 audio decoding technology licensed "
292- "from Fraunhofer IIS and Thomson\n"
293- "This product cannot be installed in product other than Personal "
294- "Computers sold for general purpose usage, and not for set-top "
295- "boxes, embedded PC, PC which are sold and customized for "
296- "mainly audio or multimedia playback and/or registration, "
297- "unless the seller has received a license by Fraunhofer IIS"
298- "and Thomson and pay the relevant royalties to them.</small>")
299- self.install_label_eula.set_alignment(0.0, 0.5)
300- self.install_label_eula.set_size_request(400,200)
301- self.install_label_eula.set_line_wrap(True)
302- self.install_hbtn = gtk.HButtonBox()
303- self.install_hbtn.set_layout(gtk.BUTTONBOX_END)
304- self.install_button = gtk.Button(label=_("Install MP3 plugins"))
305- self.install_button.connect("clicked", self._start_mp3_install)
306- self.install_hbtn.add(self.install_button)
307- self.install_vbox.pack_start(self.install_label_head, expand=False)
308- self.install_vbox.pack_start(self.install_label_body, expand=False,
309- padding=12)
310- self.install_vbox.pack_start(self.install_hbtn, expand=False)
311- self.install_vbox.pack_start(self.install_label_eula, expand=False,
312- padding=12)
313- self.install_box.add(self.install_vbox)
314- self.install_box.show_all()
315- self.add(self.install_box)
316-
317- def _start_mp3_install(self, btn):
318- """Add the 'partner' repository and update the package list from it."""
319- self.ac = aptdaemon.client.AptClient()
320- try:
321- self.ac.add_repository("deb","http://archive.canonical.com/", "lucid", ["partner"])
322- except dbus.exceptions.DBusException, e:
323- if e.get_dbus_name() == "org.freedesktop.PolicyKit.Error.NotAuthorized":
324- # user cancelled, so exit from here so they can press the button again
325- return
326- self.ac.update_cache(reply_handler=self._finish_updating_packages,
327- error_handler=self._on_error)
328-
329- def _finish_updating_packages(self, transaction):
330- """Now that partner is added, install our mp3 codec package."""
331- self.update_progress = AptProgressBar(transaction)
332- self.update_progress.show()
333- self.install_label_head.set_text("")
334- self.install_label_body.set_text(_("Finding MP3 plugins"))
335- self.install_label_eula.hide()
336- self.install_hbtn.hide()
337- self.install_vbox.pack_start(self.update_progress, expand=False)
338- transaction.run(reply_handler=lambda: True,
339- error_handler=self._on_error)
340- self.ac.install_packages(["gstreamer0.10-fluendo-plugins-mp3-partner"],
341- reply_handler=self._run_transaction,
342- error_handler=self._on_error)
343-
344- def _run_transaction(self, transaction):
345- """Show progress of aptdaemon package installation."""
346- self.update_progress.hide()
347- self.install_progress = AptProgressBar(transaction)
348- self.install_progress.show()
349- self.install_label_head.set_text("")
350- self.install_label_body.set_text(_("Installing MP3 plugins"))
351- self.install_label_eula.hide()
352- self.install_hbtn.hide()
353- self.install_vbox.pack_start(self.install_progress, expand=False)
354- transaction.run(reply_handler=lambda: True,
355- error_handler=self._on_error)
356- transaction.connect("finished", self._finished)
357-
358- def _finished(self, trans, exit_code):
359- """Aptdaemon package installation finished; show music store."""
360- if exit_code == 0 or exit_code == 2: # 0: success, 2: already installed
361- self.remove(self.install_box)
362- gst.update_registry()
363- self.add_music_store_widget()
364- else:
365- self._on_error("Could not find the "
366- "gstreamer0.10-fluendo-plugins-mp3-partner package.")
367-
368- def _on_error(self, error):
369- """Error handler for aptdaemon."""
370- print error
371- problem_installing = _("There was a problem installing, sorry")
372- self.install_label_head.set_markup('<span weight="bold" size="larger">'
373- '%s</span>' % problem_installing)
374- self.install_label_body.set_text(_('Check your internet connection and '
375- 'try again.'))
376- if getattr(self, "install_progress"):
377- self.install_progress.hide()
378- self.install_hbtn.show()
379-
380- def add_music_store_widget(self):
381- """Display the music store widget in Rhythmbox."""
382- self.browser = MUSIC_STORE_WIDGET
383- self.add(self.browser)
384- self.show_all()
385- self.browser.set_no_show_all(True)
386- self.browser.set_property("visible", True)
387- self.browser.connect("preview-mp3", self.re_emit_preview)
388- self.browser.connect("play-library", self.re_emit_playlibrary)
389- self.browser.connect("download-finished", self.re_emit_downloadfinished)
390- self.browser.connect("url-loaded", self.re_emit_urlloaded)
391-
392- def do_impl_can_pause(self):
393- """Implementation can pause.
394- If we don't handle this, Rhythmbox segfaults."""
395- return True # so we can pause, else we segfault
396-
397- def re_emit_preview(self, widget, url, title):
398- """Handle the preview-mp3 signal and re-emit it to the rb.Plugin."""
399- self.emit("preview-mp3", url, title)
400-
401- def re_emit_playlibrary(self, widget, path):
402- """Handle the play-library signal and re-emit it to the rb.Plugin."""
403- self.emit("play-library", path)
404-
405- def re_emit_downloadfinished(self, widget, path):
406- """Handle the download-finished signal and re-emit it to the rb.Plugin."""
407- self.emit("download-finished", path)
408-
409- def re_emit_urlloaded(self, widget, url):
410- """Handle the url-loaded signal and re-emit it to the rb.Plugin."""
411- self.emit("url-loaded", url)
412-
413- def do_set_property(self, property, value):
414- """Allow property settings to handle the plugin call."""
415- if property.name == 'plugin':
416- self.__plugin = value
417- else:
418- raise AttributeError, 'unknown property %s' % property.name
419-
420-=======
421 self.music_store_widget.deactivate(shell)
422 self.music_store_links_provider.deactivate(shell)
423->>>>>>> MERGE-SOURCE
424-

Subscribers

People subscribed via source and target branches