Commits

Guillermo Szeliga committed bcd1056

Album art cover retrieval tested and integrated

  • Participants
  • Parent commits fb99d58

Comments (0)

Files changed (8)

File longtang/actors/outbound/amazon/albumcoverart.py

 
     def receive(self, message):
         if isinstance(message, messages.LookupCoverArt):
-            self.logger().info(u'Downloading album art from {0} - {1} .....'.format(message.artist(), message.album()), None)
+            self.logger().debug(u'Downloading album art from "{0} - {1}" .....'.format(message.artist(), message.album()), None)
 
-        try:
-            node = self.__api.item_search('Music', ResponseGroup='Images', Keywords='{0} {1}'.format(message.artist() , message.album()), AssociateTag='ws')
-        except Exception , e:
-            # try just the album
-            node = self.__api.item_search('Music', ResponseGroup='Images', Keywords='{0}'.format(message.album()), AssociateTag='ws')
+            result=None
 
-        target_local_file=os.path.join(message.target_dir_path(), 'cover.jpg')
+            try:
+                result = self.__api.item_search('Music', ResponseGroup='Images', Keywords='{0} {1}'.format(message.artist() , message.album()), AssociateTag='ws')
+            except Exception , e:
+                # try just the album
+                try:
+                    result = self.__api.item_search('Music', ResponseGroup='Images', Keywords='{0}'.format(message.album()), AssociateTag='ws')
+                except Exception, e:
+                    self.logger().error(u'Album art search from "{0} - {1}" failed: {2}'.format(message.artist(), message.album(), e), None)                    
 
-        block_sz = 8192
+            if result is not None:
 
-        for item in node:
+                target_local_file=os.path.join(message.target_dir_path(), 'cover.jpg')
 
-            try:
-                url=str(item.ImageSets.ImageSet.LargeImage.URL)
-            except:
-                url=str(item.ImageSets.ImageSet.MediumImage.URL)
+                block_sz = 8192
+
+                for item in result:
+
+                    try:
+                        url=str(item.ImageSets.ImageSet.LargeImage.URL)
+                    except:
+                        url=str(item.ImageSets.ImageSet.MediumImage.URL)
+
+                    #print(etree.tostring(item, pretty_print=True))
+
+                    with open(target_local_file, 'wb') as target:
 
-            #print(etree.tostring(item, pretty_print=True))
+                        try:
+                            fh = urllib2.urlopen(url)
 
-            with open(target_local_file, 'wb') as target:
+                            while True:
+                                buffer = fh.read(block_sz)
+                                
+                                if not buffer:
+                                    break
 
-                fh = urllib2.urlopen(url)
+                                target.write(buffer)
 
-                while True:
-                    buffer = fh.read(block_sz)
-                    
-                    if not buffer:
-                        break
+                            fh.close()
+                            
+                            self.sender().tell(messages.CoverArtFound(message.artist(), message.album(), target_local_file), self.myself())
 
-                    target.write(buffer)
+                            self.logger().info(u'Album art from "{0} - {1}" successfully downloaded.'.format(message.artist(), message.album()), None)
 
-                fh.close()
+                        except urllib2.URLError, e:
+                            self.logger().error(u'Album art retrieval from "{0} - {1}" failed: {2}'.format(message.artist(), message.album(), e), None)
+                            self.sender().tell(messages.CoverArtRetrievalFailed(message.artist(), message.album()), self.myself())
 
-            break
+                    break
+            else:
+                self.logger().error(u'Album art from "{0} - {1}" was not found.'.format(message.artist(), message.album()), None)
+                self.sender().tell(messages.CoverArtRetrievalFailed(message.artist(), message.album()), self.myself())

File longtang/actors/outbound/amazon/messages.py

 
 class CoverArtFound(messages.ActorMessage):
 
-	def __init__(self, artist, album, target_dir_path):
-		messages.ActorMessage.__init__(self)
+	def __init__(self, artist, album, cover_path):
+		messages.ActorMessage.__init__(self)
+		self.__artist=artist
+		self.__album=album
+		self.__cover_path=cover_path
+
+	def artist(self):
+		return self.__artist
+
+	def album(self):
+		return self.__album
+
+	def cover_path(self):
+		return self.__cover_path
+
+class CoverArtRetrievalFailed(messages.ActorMessage):
+
+	def __init__(self, artist, album):
+		messages.ActorMessage.__init__(self)
+		self.__artist=artist
+		self.__album=album
+
+	def artist(self):
+		self.__artist
+
+	def album(self):
+		self.__album

File longtang/actors/outbound/amazon/test/test_albumcoverart.py

 
 class TestAlbumCoverArtActor(unittest.TestCase):
 
+	def setUp(self):
+
+		global tmpdir
+
+		tmpdir=actorstestutils.create_tmp_dir(suffix='_albumart')
+
+	def tearDown(self):
+		actorstestutils.remove_dir_content(tmpdir)
+
 	def test_single_file_match(self):
 
-		coverart_tester = actorstestutils.TestActorBuilder().with_type(albumcoverart.AlbumCoverArtActor).build()
+		coverart_tester = actorstestutils.TestActorBuilder().with_type(albumcoverart.AlbumCoverArtActor) \
+															.verbosity(None) \
+															.build()
+
+		coverart_tester.tell(messages.LookupCoverArt('Carcass', 'Swansong', tmpdir))
 
-		coverart_tester.tell(messages.LookupCoverArt('Carcass', 'Swansong', '/tmp'))
+		assert_that(coverart_tester.inspector().num_instances(messages.CoverArtFound), is_(equal_to(1)), 'Total amount of CoverArtFound messages received is wrong')
 
-		assert_that(coverart_tester.inspector().num_instances(messages.CoverArtFound), is_(equal_to(1)), 'Total amount of FileMetadataFound messages received is wrong')
+		message = coverart_tester.inspector().first(messages.CoverArtFound)
+		assert_that(os.path.isfile(message.cover_path()), is_(equal_to(True)),'Cover file does not exist')		

File longtang/actors/supervisors/filepackaging/configuration.py

+class FilePackagingConfiguration():
+	
+	def __init__(self):
+		self.__offline_mode=None
+
+	@property
+	def offline_mode(self):
+		return self.__offline_mode
+
+	@offline_mode.setter
+	def offline_mode(self, value):
+		self.__offline_mode = value
+
+class FilePackagingConfigurationBuilder():
+
+	def __init__(self):
+		self.__offline_mode=False
+
+	def offline_mode(self, value):
+		self.__offline_mode=value
+		return self
+
+	def build(self):
+		config = FilePackagingConfiguration()
+
+		config.offline_mode=self.__offline_mode
+
+		return config

File longtang/actors/supervisors/filepackaging/factory.py

+import filepackaging
+
+from longtang.system import domain
+
+class FilePackagingSupervisorFactory(domain.ActorFactory):
+	def __init__(self, config):
+		self.__config = config
+
+	def create(self, unique_id, system_ref):
+		return filepackaging.FilePackagingSupervisor(self.__config, system_ref, unique_id)

File longtang/actors/supervisors/filepackaging/filepackaging.py

 from longtang.actors.filesystem import filemanager, foldermanager, messages as filesystem_messages
 from longtang.actors.media.id3tag import id3tagwriter, messages as id3tag_messages
 from longtang.actors.tracking import facade
+from longtang.actors.outbound.amazon import albumcoverart, messages as coverart_messages
 
 class FilePackagingSupervisor(actors.Actor):
 
+	def __init__(self, config, system_ref, unique_id):
+		actors.Actor.__init__(self, system_ref, unique_id)
+
+		self.__config=config
+
 	def pre_setup(self):
 		
 		self.logger().info('Initializing actors...')
 		self.__file_tagger_ref = self.context().from_type(id3tagwriter.ID3TagWriterActor,'id3-file-tagger-actor')
 
 		self.logger().info('Creating id3-file-tagger-actor ....... DONE')
+
+		self.__coverart_ref = self.context().from_type(albumcoverart.AlbumCoverArtActor,'cover-art-actor')
+
+		self.logger().info('Creating cover-art-actor ....... DONE')
 	
 	def receive(self, message):
 		if isinstance(message, messages.PerformFilePackaging):
 			facade.MediaTrackingFacade.from_context(self.context()).notify(message.tracking(), events.PackagingStarted())
 			self.context().get_by_id('id3-folder-manager-actor').tell(filesystem_messages.CreateFolderFromMetadata(message.source_file(),\
 																													message.metadata(), \
-																													message.target_dir(), message.tracking()), self)
+																													message.target_dir(),\
+																													message.tracking()), self)
 
 		elif isinstance(message, filesystem_messages.FolderFromMetadataSuccessfullyCreated):
 
 			facade.MediaTrackingFacade.from_context(self.context()).notify(message.tracking(), events.TargetFolderCreated())
 			self.context().get_by_id('id3-file-manager-actor').tell(filesystem_messages.CopyFileTo(message.source_file(),\
 																									message.metadata(),\
-																									message.new_dir_path(), message.tracking()), self)
+																									message.new_dir_path(),\
+																									message.tracking()), self)
+
+			if not self.__config.offline_mode:
+				self.context().get_by_id('cover-art-actor').tell(coverart_messages.LookupCoverArt(	message.metadata().artist, \
+																									message.metadata().album, \
+																									message.new_dir_path()), self)
+
 		elif isinstance(message, filesystem_messages.FileSuccessfullyCopied):
 
 			self.logger().info('Media file succesfully copied', message.tracking())

File longtang/actors/supervisors/filepackaging/test/test_filepackaging.py

 import os
 
 from hamcrest import *
-from longtang.actors.supervisors.filepackaging import filepackaging, messages
+from longtang.actors.supervisors.filepackaging import filepackaging, messages, configuration, factory
 from longtang.system import system
 from longtang.actors import actorstestutils
 from longtang.common import domain as common_domain
 
 	def test_creation(self):
 
+		config = configuration.FilePackagingConfigurationBuilder().offline_mode(False).build()
+
 		actor_system = system.ActorSystem()
-		filepackaging_actor = actor_system.from_type(filepackaging.FilePackagingSupervisor,'file-packaging-supervisor')
+		filepackaging_actor = actor_system.with_factory(factory.FilePackagingSupervisorFactory(config),'file-packaging-supervisor')
 
 		try:
 			assert_that(actor_system.find_by_id('file-packaging-supervisor'), is_not(None), 'File packaging supervisor does not exist within system')
 
 	def test_file_packaging(self):
 
+		config = configuration.FilePackagingConfigurationBuilder().offline_mode(False).build()
+
 		data_dir = os.path.join(actorstestutils.current_dirpath(__file__), 'data')
 		source_file = os.path.join(data_dir, 'with_id3taginfo.mp3')
 
 		metadata_builder = common_domain.FileMetadataBuilder()
 		metadata = metadata_builder.artist('My Test Artist').title('My Test Title').album('My Test Album').track_number('7').build()
 		
-		filepackaging_actor = actorstestutils.TestActorBuilder().with_type(filepackaging.FilePackagingSupervisor)\
+		filepackaging_actor = actorstestutils.TestActorBuilder().with_factory(factory.FilePackagingSupervisorFactory(config))\
 															.with_id('test-filepackaging')\
 															.termination_moratorium(10)\
 															.terminate_system(False)\
 
 	def test_file_packaging_copy_failure(self):
 
+		config = configuration.FilePackagingConfigurationBuilder().offline_mode(False).build()
+
 		data_dir = os.path.join(actorstestutils.current_dirpath(__file__), 'data')
 		source_file = os.path.join(data_dir, 'nonexisting_id3taginfo.mp3')
 
 		metadata_builder = common_domain.FileMetadataBuilder()
 		metadata = metadata_builder.artist('My Test Artist').title('My Test Title').album('My Test Album').track_number('7').build()
 		
-		filepackaging_actor = actorstestutils.TestActorBuilder().with_type(filepackaging.FilePackagingSupervisor)\
+		filepackaging_actor = actorstestutils.TestActorBuilder().with_factory(factory.FilePackagingSupervisorFactory(config))\
 															.with_id('test-filepackaging-failure')\
 															.termination_moratorium(10)\
 															.terminate_system(False)\
 
 	def test_file_packaging_folder_creation_failure(self):
 
+		config = configuration.FilePackagingConfigurationBuilder().offline_mode(False).build()
+
+
 		data_dir = os.path.join(actorstestutils.current_dirpath(__file__), 'data')
 		source_file = os.path.join(data_dir, 'with_id3taginfo.mp3')
 
 		metadata_builder = common_domain.FileMetadataBuilder()
 		metadata = metadata_builder.artist('My Test Artist').title('My Test Title').album('My Test Album').track_number('7').build()
 		
-		filepackaging_actor = actorstestutils.TestActorBuilder().with_type(filepackaging.FilePackagingSupervisor)\
+		filepackaging_actor = actorstestutils.TestActorBuilder().with_factory(factory.FilePackagingSupervisorFactory(config))\
 															.with_id('test-filepackaging-failure')\
 															.termination_moratorium(10)\
 															.terminate_system(False)\
 
 	def test_file_packaging_metadata_writting_failure(self):
 
+		config = configuration.FilePackagingConfigurationBuilder().offline_mode(False).build()
+
 		data_dir = os.path.join(actorstestutils.current_dirpath(__file__), 'data')
 		source_file = os.path.join(data_dir, 'with_id3taginfo.mp3')
 
 		metadata_builder = common_domain.FileMetadataBuilder()
 		metadata = metadata_builder.artist('My Test Artist').title('My Test Title').album(None).track_number('7').build()
 		
-		filepackaging_actor = actorstestutils.TestActorBuilder().with_type(filepackaging.FilePackagingSupervisor)\
+		filepackaging_actor = actorstestutils.TestActorBuilder().with_factory(factory.FilePackagingSupervisorFactory(config))\
 															.with_id('test-filepackaging-failure')\
 															.termination_moratorium(10)\
 															.terminate_system(False)\

File longtang/actors/supervisors/flowconductor/flowconductor.py

 
 from longtang.actors import actors
 from longtang.actors.inbound import filepoller, messages as fp_messages
-from longtang.actors.supervisors.filepackaging import filepackaging, messages as packaging_messages
+from longtang.actors.supervisors.filepackaging import filepackaging, messages as packaging_messages, factory as packaging_factory, configuration as packaging_config 
 from longtang.actors.supervisors.id3taghandler import id3taghandler, messages as id3tag_messages, factory, configuration as id3tag_config
 
 class FlowConductorSupervisor(actors.Actor):
 		self.logger().info('Initializing actors...')
 
 		self.logger().info('Initializing filepackaging-actor...')
-		self.__filepackaging_ref = self.context().from_type(filepackaging.FilePackagingSupervisor,'filepackaging-actor')
+
+		packagingconfig = packaging_config.FilePackagingConfigurationBuilder().offline_mode(self.__config.offline_mode)\
+																		  		.build()
+
+		self.__filepackaging_ref = self.context().with_factory(packaging_factory.FilePackagingSupervisorFactory(packagingconfig),'filepackaging-actor')
 
 		id3tagconfig = id3tag_config.Id3TagHandlerConfigurationBuilder().override_tags(self.__config.override_tags)\
 																		  .offline_mode(self.__config.offline_mode)\