[rhythmbox] magnatune: use gnome-keyring via g-i, other fixes (bug #661957)



commit 53563b040c7e0ad86d5e079a5e6aa7ff2f8666e5
Author: Jonathan Matthew <jonathan d14n org>
Date:   Sun Feb 5 19:28:11 2012 +1000

    magnatune: use gnome-keyring via g-i, other fixes (bug #661957)
    
    The plugin now works well enough to be enabled again.  Some things
    probably still don't work.

 plugins/magnatune/MagnatuneSource.py |  123 ++++++++++++++++------------------
 plugins/magnatune/Makefile.am        |   14 ++--
 plugins/magnatune/magnatune.py       |   95 +++++++++++++-------------
 3 files changed, 111 insertions(+), 121 deletions(-)
---
diff --git a/plugins/magnatune/MagnatuneSource.py b/plugins/magnatune/MagnatuneSource.py
index d269bbe..b1a9920 100644
--- a/plugins/magnatune/MagnatuneSource.py
+++ b/plugins/magnatune/MagnatuneSource.py
@@ -31,12 +31,10 @@ import urllib
 import urlparse
 import threading
 import zipfile
-import gnomekeyring as keyring
 
 import rb
 from gi.repository import RB
-from gi.repository import GObject, Gtk, Gio
-# XXX use GnomeKeyring when introspection is available
+from gi.repository import GObject, Gtk, Gdk, Gio, GnomeKeyring
 
 from TrackListHandler import TrackListHandler
 from BuyAlbumHandler import BuyAlbumHandler, MagnatunePurchaseError
@@ -47,7 +45,7 @@ gettext.install('rhythmbox', RB.locale_dir())
 magnatune_partner_id = "rhythmbox"
 
 # URIs
-magnatune_song_info_uri = Gio.file_new_for_uri("http://magnatune.com/info/song_info_xml.zip";)
+magnatune_song_info_uri = "http://magnatune.com/info/song_info_xml.zip";
 magnatune_buy_album_uri = "https://magnatune.com/buy/choose?";
 magnatune_api_download_uri = "http://%s:%s download magnatune com/buy/membership_free_dl_xml?"
 
@@ -87,7 +85,7 @@ class MagnatuneSource(RB.BrowserSource):
 		self.__downloads = {} # keeps track of download progress for each file
 		self.__cancellables = {} # keeps track of Gio.Cancellable objects so we can abort album downloads
 
-		self.__art_store = RB.ExtDB("album-art")
+		self.__art_store = RB.ExtDB(name="album-art")
 
 	#
 	# RBSource methods
@@ -115,11 +113,6 @@ class MagnatuneSource(RB.BrowserSource):
 			qm = self.props.query_model
 			return (qm.compute_status_normal("%d song", "%d songs"), None, 2.0)
 
-	def do_get_ui_actions(self):
-		return ["MagnatuneDownloadAlbum",
-			"MagnatuneArtistInfo",
-			"MagnatuneCancelDownload"]
-
 	def do_selected(self):
 		if not self.__activated:
 			shell = self.props.shell
@@ -144,10 +137,10 @@ class MagnatuneSource(RB.BrowserSource):
 	def do_impl_can_delete(self):
 		return False
 
-	def do_impl_pack_paned(self, paned):
+	def do_pack_content(self, content):
 		self.__paned_box = Gtk.VBox(homogeneous=False, spacing=5)
 		self.pack_start(self.__paned_box, True, True, 0)
-		self.__paned_box.pack_start(paned, True, True, 0)
+		self.__paned_box.pack_start(content, True, True, 0)
 
 
 	def do_delete_thyself(self):
@@ -179,7 +172,7 @@ class MagnatuneSource(RB.BrowserSource):
 		urls = set([])
 
 		for tr in tracks:
-			sku = self.__sku_dict[self.__db.entry_get_string(tr, RB.RhythmDBPropType.LOCATION)]
+			sku = self.__sku_dict[tr.get_string(RB.RhythmDBPropType.LOCATION)]
 			url = self.__home_dict[sku]
 			if url not in urls:
 				Gtk.show_uri(screen, url, Gdk.CURRENT_TIME)
@@ -191,14 +184,14 @@ class MagnatuneSource(RB.BrowserSource):
 		urls = set([])
 
 		for tr in tracks:
-			sku = self.__sku_dict[self.__db.entry_get_string(tr, RB.RhythmDBPropType.LOCATION)]
+			sku = self.__sku_dict[tr.get_string(RB.RhythmDBPropType.LOCATION)]
 			url = magnatune_buy_album_uri + urllib.urlencode({ 'sku': sku, 'ref': magnatune_partner_id })
 			if url not in urls:
 				Gtk.show_uri(screen, url, Gdk.CURRENT_TIME)
 				urls.add(url)
 
 	def download_album(self):
-		if selt.__settings['account_type'] != 'download':
+		if selt.__settings['account-type'] != 'download':
 			# The user doesn't have a download account, so redirect them to the purchase page.
 			self.purchase_redirect()
 			return
@@ -216,7 +209,7 @@ class MagnatuneSource(RB.BrowserSource):
 		skus = []
 
 		for track in tracks:
-			sku = self.__sku_dict[self.__db.entry_get_string(track, RB.RhythmDBPropType.LOCATION)]
+			sku = self.__sku_dict[track.get_string(RB.RhythmDBPropType.LOCATION)]
 			if sku in skus:
 				continue
 			skus.append(sku)
@@ -241,19 +234,17 @@ class MagnatuneSource(RB.BrowserSource):
 						return info.filename;
 				return None
 
-			def download_progress(complete, total):
+			def download_progress(copy, complete, total, self):
 				self.__load_progress = (complete, total)
 				self.__notify_status_changed()
 
-			def download_finished(uri, result):
-				try:
-					success = uri.copy_finish(result)
-				except:
-					success = False
-
+			def download_finished(copy, success, self):
 				if not success:
+					print "catalog download failed"
+					print copy.get_error()
 					return
 
+				print "catalog download successful"
 				# done downloading, unzip to real location
 				catalog_zip = zipfile.ZipFile(magnatune_song_info_temp)
 				catalog = open(magnatune_song_info, 'w')
@@ -266,7 +257,8 @@ class MagnatuneSource(RB.BrowserSource):
 				catalog.close()
 				catalog_zip.close()
 
-				dest.delete()
+				df = Gio.file_new_for_path(magnatune_song_info_temp)
+				df.delete(None)
 				self.__updating = False
 				self.__catalogue_loader = None
 				self.__notify_status_changed()
@@ -276,46 +268,23 @@ class MagnatuneSource(RB.BrowserSource):
 
 			self.__updating = True
 
-			dest = Gio.file_new_for_path(magnatune_song_info_temp)
-			self.__catalogue_loader = Gio.Cancellable()
 			try:
-				# For some reason, Gio.FileCopyFlags.OVERWRITE doesn't work for copy_async
-				dest.delete()
+				df = Gio.file_new_for_path(magnatune_song_info_temp)
+				df.delete(None)
 			except:
 				pass
-			magnatune_song_info_uri.copy_async(dest,
-			                                   download_finished,
-							   progress_callback=download_progress,
-							   flags=Gio.FileCopyFlags.OVERWRITE,
-							   cancellable=self.__catalogue_loader)
+			self.__catalog_loader = RB.AsyncCopy()
+			self.__catalog_loader.set_progress(download_progress, self)
+			self.__catalog_loader.start(magnatune_song_info_uri, magnatune_song_info_temp, download_finished, self)
 
 		def load_catalogue():
-			def got_items(result, items):
-				account_type = self.__settings['account_type']
-				username = ""
-				password = ""
-				if account_type == 'none':
-					pass
-				elif result is not None or len(items) == 0:
-					RB.error_dialog(title = _("Couldn't get account details"),
-							message = str(result))
-					return
-				else:
-					try:
-						username, password = items[0].secret.split('\n')
-					except ValueError: # Couldn't parse secret, possibly because it's empty
-						pass
-				parser = xml.sax.make_parser()
-				parser.setContentHandler(TrackListHandler(self.__db, self.__entry_type, self.__sku_dict, self.__home_dict, self.__art_dict, account_type, username, password))
-
-				self.__catalogue_loader = rb.ChunkLoader()
-				self.__catalogue_loader.get_url_chunks(magnatune_song_info, 64*1024, True, catalogue_chunk_cb, parser)
 
-			def catalogue_chunk_cb(result, total, parser):
-				if not result or isinstance(result, Exception):
-					if result:
+			def catalogue_chunk_cb(loader, data, total, parser):
+				if data is None:
+					error = loader.get_error()
+					if error:
 						# report error somehow?
-						print "error loading catalogue: %s" % result
+						print "error loading catalogue: %s" % error
 
 					try:
 						parser.close()
@@ -329,7 +298,7 @@ class MagnatuneSource(RB.BrowserSource):
 
 					# restart in-progress downloads
 					# (doesn't really belong here)
-					for f in magnatune_in_progress_dir.enumerate_children('standard::name'):
+					for f in magnatune_in_progress_dir.enumerate_children('standard::name', Gio.FileQueryInfoFlags.NONE, None):
 						name = f.get_name()
 						if not name.startswith("in_progress_"):
 							continue
@@ -338,18 +307,19 @@ class MagnatuneSource(RB.BrowserSource):
 						self.__download_album(Gio.file_new_for_uri(uri), name[12:])
 				else:
 					# hack around some weird chars that show up in the catalogue for some reason
-					result = result.replace("\x19", "'")
-					result = result.replace("\x13", "-")
+					data = str(data.str)
+					data = data.replace("\x19", "'")
+					data = data.replace("\x13", "-")
 
 					# argh.
-					result = result.replace("Rock & Roll", "Rock &amp; Roll")
+					data = data.replace("Rock & Roll", "Rock &amp; Roll")
 
 					try:
-						parser.feed(result)
+						parser.feed(data)
 					except xml.sax.SAXParseException, e:
 						print "error parsing catalogue: %s" % e
 
-					load_size['size'] += len(result)
+					load_size['size'] += len(data)
 					self.__load_progress = (load_size['size'], total)
 
 				self.__notify_status_changed()
@@ -361,11 +331,34 @@ class MagnatuneSource(RB.BrowserSource):
 			self.__notify_status_changed()
 
 			load_size = {'size': 0}
-			keyring.find_items(keyring.ITEM_GENERIC_SECRET, {'rhythmbox-plugin': 'magnatune'}, got_items)
+			account_type = self.__settings['account-type']
+			username = ""
+			password = ""
+
+			if account_type != 'none':
+				attributes = GnomeKeyring.attribute_list_new()
+				GnomeKeyring.attribute_list_append_string(attributes, "rhythmbox-plugin", "magnatune")
+				(result, items) = GnomeKeyring.find_items_sync(GnomeKeyring.ItemType.GENERIC_SECRET, attributes)
+				if result is not GnomeKeyring.Result.OK or len(items) == 0:
+					RB.error_dialog(title = _("Couldn't get account details"),
+							message = GnomeKeyring.result_to_message(result))
+					account_type = 'none'
+				else:
+					try:
+						username, password = items[0].get_secret().split('\n')
+					except ValueError: # Couldn't parse secret, possibly because it's empty
+						account_type = 'none'
+
+			parser = xml.sax.make_parser()
+			parser.setContentHandler(TrackListHandler(self.__db, self.__entry_type, self.__sku_dict, self.__home_dict, self.__art_dict, account_type, username, password))
+
+			self.__catalogue_loader = RB.ChunkLoader()
+			self.__catalogue_loader.set_callback(catalogue_chunk_cb, parser)
+			self.__catalogue_loader.start(magnatune_song_info, 64*1024)
 
 
 		self.__catalogue_check = rb.UpdateCheck()
-		self.__catalogue_check.check_for_update(magnatune_song_info, magnatune_song_info_uri.get_uri(), update_cb)
+		self.__catalogue_check.check_for_update(magnatune_song_info, magnatune_song_info_uri, update_cb)
 
 
 	def __show_loading_screen(self, show):
diff --git a/plugins/magnatune/Makefile.am b/plugins/magnatune/Makefile.am
index effb8bd..1fa6861 100644
--- a/plugins/magnatune/Makefile.am
+++ b/plugins/magnatune/Makefile.am
@@ -1,22 +1,20 @@
 # Magnatune Store Python Plugin
 
-# this plugin is disabled until we can access gnome-keyring
-
 plugindir = $(PLUGINDIR)/magnatune
 plugindatadir = $(PLUGINDATADIR)/magnatune
-noinst_PYTHON =                       \
+plugin_PYTHON =                       \
        MagnatuneSource.py             \
        BuyAlbumHandler.py             \
        TrackListHandler.py            \
        magnatune.py
 
-# %.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
-# plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)
+%.plugin: %.plugin.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
+plugin_DATA = $(plugin_in_files:.plugin.in=.plugin)
 
 plugin_in_files = magnatune.plugin.in
 
 gtkbuilderdir = $(plugindatadir)
-noinst_DATA =	\
+gtkbuilder_DATA =	\
 		magnatune-loading.ui			\
 		magnatune-prefs.ui			\
 		magnatune_logo_color_small.png		\
@@ -26,8 +24,8 @@ themedir = $(pkgdatadir)/icons/hicolor
 size = 24x24
 context = places
 icondir = $(themedir)/$(size)/$(context)
-noinst_DATA += icons/hicolor/$(size)/$(context)/magnatune.png
+icon_DATA = icons/hicolor/$(size)/$(context)/magnatune.png
 
-EXTRA_DIST = $(plugin_in_files) $(gtkbuilder_DATA) $(icon_DATA) $(noinst_DATA)
+EXTRA_DIST = $(plugin_in_files) $(gtkbuilder_DATA) $(icon_DATA)
 CLEANFILES = $(plugin_DATA)
 DISTCLEANFILES = $(plugin_DATA)
diff --git a/plugins/magnatune/magnatune.py b/plugins/magnatune/magnatune.py
index a10d4e7..d0cc371 100644
--- a/plugins/magnatune/magnatune.py
+++ b/plugins/magnatune/magnatune.py
@@ -31,12 +31,10 @@ import sys, os.path
 import xml
 import datetime
 import string
-import gnomekeyring as keyring
 
 import rb
 from gi.repository import RB
-from gi.repository import GObject, Gtk, Gio, Peas, PeasGtk
-# XXX use GnomeKeyring when available
+from gi.repository import GObject, Gtk, Gio, Peas, PeasGtk, GnomeKeyring
 
 from MagnatuneSource import MagnatuneSource
 
@@ -57,6 +55,11 @@ popup_ui = """
     <separator/>
     <menuitem name="PropertiesLibraryPopup" action="MusicProperties"/>
   </popup>
+  <toolbar name="MagnatuneToolBar">
+    <toolitem name="MagnatuneDownloadAlbumToolbar" action="MagnatuneDownloadAlbum"/>
+    <toolitem name="MagnatuneArtistInfoToolbar" action="MagnatuneArtistInfo"/>
+    <toolitem name="MagnatuneCancelDownloadToolbar" action="MagnatuneCancelDownload"/>
+  </toolbar>
 </ui>
 """
 
@@ -102,7 +105,8 @@ class Magnatune(GObject.GObject, Peas.Activatable):
 					  pixbuf=icon,
 					  plugin=self,
 					  settings=settings.get_child("source"),
-					  name=_("Magnatune"))
+					  name=_("Magnatune"),
+					  toolbar_path="/MagnatuneToolBar")
 
 		shell.register_entry_type_for_source(self.source, self.entry_type)
 		shell.append_display_page(self.source, group)
@@ -168,41 +172,6 @@ class MagnatuneConfig(GObject.GObject, PeasGtk.Configurable):
 			'item': None
 		}
 
-		def got_items(result, items):
-			def created_item(result, id):
-				if result is None: # Item successfully created
-					keyring_data['id'] = id
-					keyring.item_get_info(None, id, got_item)
-				else:
-					print "Couldn't create keyring item: " + str(result)
-					fill_account_details()
-					dialog.present()
-			def got_item(result, item):
-				if result is None: # Item retrieved successfully
-					keyring_data['item'] = item
-				else:
-					print "Couldn't retrieve keyring item: " + str(result)
-				fill_account_details()
-				dialog.present()
-
-
-			if result is None and len(items) != 0: # Got list of search results
-				keyring_data['id'] = items[0].item_id
-				keyring.item_get_info(None, keyring_data['id'], got_item)
-			elif result == keyring.NoMatchError or len(items) == 0: # No items were found, so we'll create one
-				keyring.item_create(None,
-				                    keyring.ITEM_GENERIC_SECRET,
-				                    "Rhythmbox: Magnatune account information",
-				                    {'rhythmbox-plugin': 'magnatune'},
-				                    "", # Empty secret for now
-				                    True,
-				                    created_item)
-			else: # Some other error occurred
-				print "Couldn't access keyring: " + str(result)
-				fill_account_details()
-				dialog.present()
-
-
 		def fill_account_details():
 			account_type = self.settings['account_type']
 			builder.get_object("no_account_radio").set_active(account_type == "none")
@@ -253,16 +222,16 @@ class MagnatuneConfig(GObject.GObject, PeasGtk.Configurable):
 			builder.get_object("account_changed_label").show()
 
 		def close_button_pressed(x, y):
-			try:
-				if keyring_data['id'] and keyring_data['item']:
-					# The async version is not in the python bindings, grr...
-					keyring.item_set_info_sync(None, keyring_data['id'], keyring_data['item'])
-				else:
+			if keyring_data['id'] and keyring_data['item']:
+				result = GnomeKeyring.item_set_info_sync(None,
+									 keyring_data['id'],
+									 keyring_data['item'])
+				if result != GnomeKeyring.Result.OK:
 					RB.error_dialog(title = _("Couldn't store account information"),
-							message = _("There was a problem accessing the keyring. Check the debug output for more information."))
-			except Exception, e:
+							message = GnomeKeyring.result_to_message(result))
+			else:
 				RB.error_dialog(title = _("Couldn't store account information"),
-						message = str(e))
+						message = _("There was a problem accessing the keyring. Check the debug output for more information."))
 			dialog.hide()
 
 		def format_selection_changed(self, button):
@@ -289,5 +258,35 @@ class MagnatuneConfig(GObject.GObject, PeasGtk.Configurable):
 		builder.connect_signals(self.configure_callback_dic)
 		dialog.connect("response", close_button_pressed)
 
-		keyring.find_items(keyring.ITEM_GENERIC_SECRET, {'rhythmbox-plugin': 'magnatune'}, got_items)
+		attributes = GnomeKeyring.attribute_list_new()
+		GnomeKeyring.attribute_list_append_string(attributes, "rhythmbox-plugin", "magnatune")
+		(result, items) = GnomeKeyring.find_items_sync(GnomeKeyring.ItemType.GENERIC_SECRET, attributes)
+		if result == GnomeKeyring.Result.OK and len(items) != 0:
+			keyring_data['id'] = items[0].item_id
+			(result, item) = GnomeKeyring.item_get_info_sync(None, keyring_data['id'])
+			if result == GnomeKeyring.Result.OK:
+				keyring_data['item'] = item
+			else:
+				print "Couldn't get keyring item: " + GnomeKeyring.result_to_message(result)
+
+		elif result == GnomeKeyring.Result.NO_MATCH or len(items) == 0:
+			# no item found, so create a new one
+			result = GnomeKeyring.item_create_sync(None,
+							       GnomeKeyring.ItemType.GENERIC_SECRET,
+							       "Rhythmbox: Magnatune account information",
+							       attributes,
+							       "",	# Empty secret for now
+							       True)
+			if result == GnomeKeyring.Result.OK:
+				keyring_data['id'] = id
+				(result, item) = GnomeKeyring.item_get_info_sync(None, id)
+				if result == GnomeKeyring.Result.OK:
+					keyring_data['item'] = item
+			else:
+				print "Couldn't create keyring item: " + GnomeKeyring.result_to_message(result)
+		else:
+			print "Couldn't access keyring: " + str(result)
+
+		fill_account_details()
+		dialog.present()
 		return dialog



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]