[0;33m=== added file 'artdisplay2/EmbeddedArtSearch.py'
[0m[0;31m--- artdisplay2/EmbeddedArtSearch.py	1970-01-01 00:00:00 +0000
[0m[0;32m+++ artdisplay2/EmbeddedArtSearch.py	2007-11-17 00:07:36 +0000
[0m[0;35m@@ -0,0 +1,103 @@
[0m[0;32m+# -*- Mode: python; coding: utf-8; tab-width: 8; indent-tabs-mode: t; -*- 
[0m[0;32m+#
[0m[0;32m+# Copyright (C) 2007 - John Millikin <jmillikin@gmail.com>
[0m[0;32m+#
[0m[0;32m+# This program is free software; you can redistribute it and/or modify
[0m[0;32m+# it under the terms of the GNU General Public License as published by
[0m[0;32m+# the Free Software Foundation; either version 2, or (at your option)
[0m[0;32m+# any later version.
[0m[0;32m+# 
[0m[0;32m+# This program is distributed in the hope that it will be useful,
[0m[0;32m+# but WITHOUT ANY WARRANTY; without even the implied warranty of
[0m[0;32m+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
[0m[0;32m+# GNU General Public License for more details.
[0m[0;32m+#
[0m[0;32m+# You should have received a copy of the GNU General Public License
[0m[0;32m+# along with this program; if not, write to the Free Software
[0m[0;32m+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA.
[0m[0;32m+
[0m[0;32m+import os
[0m[0;32m+import gnomevfs
[0m[0;32m+
[0m[0;32m+import codecs
[0m[0;32m+import pygst
[0m[0;32m+pygst.require ("0.10")
[0m[0;32m+import gst
[0m[0;32m+
[0m[0;32m+def extended_comment_to_dict (comments):
[0m[0;32m+	def split (comment):
[0m[0;32m+		key, value = comment.split ('=', 1)
[0m[0;32m+		return key.upper (), value
[0m[0;32m+		
[0m[0;32m+	return dict (split (comment) for comment in comments)
[0m[0;32m+	
[0m[0;32m+def on_message(bus, message, pipeline, on_found_data):
[0m[0;32m+	t = message.type
[0m[0;32m+	if t == gst.MESSAGE_EOS:
[0m[0;32m+		pipeline.set_state(gst.STATE_NULL)
[0m[0;32m+		on_found_data (None)
[0m[0;32m+		
[0m[0;32m+	elif t == gst.MESSAGE_ERROR:
[0m[0;32m+		pipeline.set_state(gst.STATE_NULL)
[0m[0;32m+		err, debug = message.parse_error()
[0m[0;32m+		print "Error: %s" % err, debug
[0m[0;32m+		on_found_data (None)
[0m[0;32m+		
[0m[0;32m+	elif t == gst.MESSAGE_TAG:
[0m[0;32m+		pipeline.set_state(gst.STATE_NULL)
[0m[0;32m+		tags = message.structure
[0m[0;32m+		if tags.has_field ('image'):
[0m[0;32m+			on_found_data (tags['image'])
[0m[0;32m+		elif tags.has_field ('extended-comment'):
[0m[0;32m+			extended = extended_comment_to_dict (tags['extended-comment'])
[0m[0;32m+			if 'COVERART' in extended:
[0m[0;32m+				decoder = codecs.getdecoder ('base64')
[0m[0;32m+				on_found_data (decoder (extended['COVERART'])[0])
[0m[0;32m+				
[0m[0;32m+def build_pipeline (uri, on_found_data):
[0m[0;32m+	pipeline = gst.Pipeline ("pipeline")
[0m[0;32m+	source = gst.element_factory_make ("gnomevfssrc", None)
[0m[0;32m+	decoder = gst.element_factory_make ("decodebin", None)
[0m[0;32m+	audiosink = gst.element_factory_make ("fakesink", None)
[0m[0;32m+	
[0m[0;32m+	source.set_property ('location', uri)
[0m[0;32m+	decoder.connect ('new-decoded-pad',
[0m[0;32m+	                 lambda dbin, pad, islast: pad.link (audiosink.get_pad ('sink')))
[0m[0;32m+	
[0m[0;32m+	pipeline.add (source)
[0m[0;32m+	pipeline.add (decoder)
[0m[0;32m+	pipeline.add (audiosink)
[0m[0;32m+	
[0m[0;32m+	gst.element_link_many (source, decoder)
[0m[0;32m+	bus = pipeline.get_bus ()
[0m[0;32m+	bus.add_signal_watch ()
[0m[0;32m+	bus.connect ('message', on_message, pipeline, on_found_data)
[0m[0;32m+	pipeline.set_state (gst.STATE_PLAYING)
[0m[0;32m+	status, state, pending = pipeline.get_state ()
[0m[0;32m+	
[0m[0;32m+	if state != gst.STATE_PLAYING:
[0m[0;32m+		print 'Error reading embedded art for %r' % (filename)
[0m[0;32m+		on_found_data (None)
[0m[0;32m+		
[0m[0;32m+class EmbeddedArtSearch (object):
[0m[0;32m+	def __init__ (self, loader):
[0m[0;32m+		self.loader = loader
[0m[0;32m+		
[0m[0;32m+	def search (self, db, entry, on_search_completed_cb, *args):
[0m[0;32m+		def on_found_data (image_data):
[0m[0;32m+			on_search_completed_cb (self, entry, [image_data], *args)
[0m[0;32m+			
[0m[0;32m+		try:
[0m[0;32m+			uri = gnomevfs.URI (entry.get_playback_uri())
[0m[0;32m+			print 'searching for embedded art for %r' % (uri)
[0m[0;32m+			build_pipeline (uri, on_found_data)
[0m[0;32m+		except StandardError:
[0m[0;32m+			on_found_data (None)
[0m[0;32m+			
[0m[0;32m+	def search_next (self):
[0m[0;32m+		return False
[0m[0;32m+		
[0m[0;32m+	def get_best_match_urls (self, search_results):
[0m[0;32m+		for image_data in search_results:
[0m[0;32m+			yield image_data, None
[0m[0;32m+			
[0m[0;30m
[0m[0;33m=== modified file 'artdisplay2/CoverArtDatabase.py'
[0m[0;31m--- artdisplay2/CoverArtDatabase.py	2007-11-17 00:10:51 +0000
[0m[0;32m+++ artdisplay2/CoverArtDatabase.py	2007-11-17 00:11:22 +0000
[0m[0;35m@@ -26,8 +26,9 @@
[0m[0;30m from PodcastCoverArtSearch import PodcastCoverArtSearch
[0m[0;30m from AmazonCoverArtSearch import AmazonCoverArtSearch
[0m[0;30m from LocalCoverArtSearch import LocalCoverArtSearch
[0m[0;32m+from EmbeddedArtSearch import EmbeddedArtSearch
[0m[0;30m 
[0m[0;31m-ART_SEARCHES_LOCAL = [LocalCoverArtSearch]
[0m[0;32m+ART_SEARCHES_LOCAL = [EmbeddedArtSearch, LocalCoverArtSearch]
[0m[0;30m ART_SEARCHES_REMOTE = [PodcastCoverArtSearch, AmazonCoverArtSearch]
[0m[0;30m ART_FOLDER = '~/.gnome2/rhythmbox/covers'
[0m[0;30m ART_CACHE_EXTENSION = 'jpg'
[0m[0;30m
[0m