cowbell r42 - in trunk: . base base/services gui gui/services



Author: btaylor
Date: Tue Jun  3 05:01:58 2008
New Revision: 42
URL: http://svn.gnome.org/viewvc/cowbell?rev=42&view=rev

Log:
2008-06-02  Brad Taylor  <brad getcoded net>
	
	* gui/MainWindow.cs:
	* gui/services/AlbumArtworkCacheService.cs:
	* gui/AlbumCoverImage.cs:
	* gui/Makefile.am:
	* base/services/IMetadataProxyService.cs:
	* base/services/MetadataProxyService.cs
	* base/services/IAlbumArtworkCacheService.cs:
	* base/ArtworkProxyPriorityAttribute.cs:
	* base/MusicBrainzMetadataProxy.cs:
	* base/IMetadataProxy.cs:
	* base/IArtworkProxy.cs:
	* base/Makefile.am: Restructure/refactor code to add a new
	  AlbumArtworkCacheService which will handle all caching and saving of
	  album artwork.  Rework AlbumCoverImage to use this awesome new
	  abstraction.



Added:
   trunk/base/ArtworkProxyPriorityAttribute.cs
   trunk/base/IArtworkProxy.cs
   trunk/base/services/IAlbumArtworkCacheService.cs
   trunk/gui/services/AlbumArtworkCacheService.cs
Modified:
   trunk/ChangeLog
   trunk/base/IMetadataProxy.cs
   trunk/base/Makefile.am
   trunk/base/MusicBrainzMetadataProxy.cs
   trunk/base/services/IMetadataProxyService.cs
   trunk/base/services/MetadataProxyService.cs
   trunk/gui/AlbumCoverImage.cs
   trunk/gui/MainWindow.cs
   trunk/gui/Makefile.am

Added: trunk/base/ArtworkProxyPriorityAttribute.cs
==============================================================================
--- (empty file)
+++ trunk/base/ArtworkProxyPriorityAttribute.cs	Tue Jun  3 05:01:58 2008
@@ -0,0 +1,40 @@
+/*
+ * cowbell
+ * Copyright (c) 2008 Brad Taylor
+ *
+ * This file is part of cowbell.
+ *
+ * cowbell is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * cowbell is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with cowbell; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using System;
+using System.Reflection;
+
+namespace Cowbell.Base
+{
+	[AttributeUsage (AttributeTargets.Class, AllowMultiple = true)]
+	public class ArtworkProxyPriorityAttribute : Attribute
+	{
+		private int priority;
+		public int Priority {
+			get { return priority; }
+		}
+	
+		public ArtworkProxyPriorityAttribute (int priority)
+		{
+			this.priority = priority;
+		}
+	}
+}

Added: trunk/base/IArtworkProxy.cs
==============================================================================
--- (empty file)
+++ trunk/base/IArtworkProxy.cs	Tue Jun  3 05:01:58 2008
@@ -0,0 +1,31 @@
+/*
+ * cowbell
+ * Copyright (c) 2008 Brad Taylor
+ *
+ * This file is part of cowbell.
+ *
+ * cowbell is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * cowbell is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with cowbell; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using System;
+
+namespace Cowbell.Base
+{
+	public interface IArtworkProxy
+	{
+		byte[] FetchAlbumArtwork ();
+	}
+
+}

Modified: trunk/base/IMetadataProxy.cs
==============================================================================
--- trunk/base/IMetadataProxy.cs	(original)
+++ trunk/base/IMetadataProxy.cs	Tue Jun  3 05:01:58 2008
@@ -26,7 +26,6 @@
 	public interface IMetadataProxy
 	{
 		MetadataImportStatus Import ();
-		byte[] FetchAlbumArtwork ();
 	}
 
 }

Modified: trunk/base/Makefile.am
==============================================================================
--- trunk/base/Makefile.am	(original)
+++ trunk/base/Makefile.am	Tue Jun  3 05:01:58 2008
@@ -14,6 +14,7 @@
 services/MetadataProxyService.cs \
 services/XmlPreferencesService.cs \
 services/IPreferencesService.cs  \
+services/IAlbumArtworkCacheService.cs  \
 MusicBrainzMetadataProxy.cs \
 Batch.cs \
 Catalog.cs \
@@ -23,7 +24,9 @@
 FilenamePattern.cs \
 Globals.cs \
 IMetadataProxy.cs \
+IArtworkProxy.cs \
 IService.cs \
+ArtworkProxyPriorityAttribute.cs \
 MetadataProxyPriorityAttribute.cs \
 ServiceManager.cs \
 Debug.cs \

Modified: trunk/base/MusicBrainzMetadataProxy.cs
==============================================================================
--- trunk/base/MusicBrainzMetadataProxy.cs	(original)
+++ trunk/base/MusicBrainzMetadataProxy.cs	Tue Jun  3 05:01:58 2008
@@ -31,7 +31,8 @@
 namespace Cowbell.Base
 {
 	[MetadataProxyPriority (20)]
-	public class MusicBrainzMetadataProxy : IMetadataProxy
+	[ArtworkProxyPriority (20)]
+	public class MusicBrainzMetadataProxy : IMetadataProxy, IArtworkProxy
 	{
 #region public methods
 		public MusicBrainzMetadataProxy ()

Added: trunk/base/services/IAlbumArtworkCacheService.cs
==============================================================================
--- (empty file)
+++ trunk/base/services/IAlbumArtworkCacheService.cs	Tue Jun  3 05:01:58 2008
@@ -0,0 +1,46 @@
+/*
+ * cowbell
+ * Copyright (c) 2008 Brad Taylor
+ *
+ * This file is part of cowbell.
+ *
+ * cowbell is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * cowbell is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with cowbell; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using System;
+
+namespace Cowbell.Base
+{
+	public delegate void ArtworkChangedHandler (object o, ArtworkChangedArgs args);
+
+	public interface IAlbumArtworkCacheService : IService
+	{
+		event ArtworkChangedHandler ArtworkChanged;
+
+		void SaveCurrentArtwork (string filename, string type);
+	}
+
+	public class ArtworkChangedArgs : EventArgs
+	{
+		public object ImageData;
+		public bool IsLoading;
+
+		public ArtworkChangedArgs (bool loading, object data)
+		{
+			ImageData = data;
+			IsLoading = loading;
+		}
+	}
+}

Modified: trunk/base/services/IMetadataProxyService.cs
==============================================================================
--- trunk/base/services/IMetadataProxyService.cs	(original)
+++ trunk/base/services/IMetadataProxyService.cs	Tue Jun  3 05:01:58 2008
@@ -24,22 +24,10 @@
 namespace Cowbell.Base
 {
 	public delegate void MetadataImportCompletedHandler (object o, MetadataImportCompletedArgs args);
-	public delegate void ArtworkDownloadCompletedHandler (object o, ArtworkDownloadCompletedArgs args);
 
 	public interface IMetadataProxyService : IService
 	{
 		void FetchMetadata (MetadataImportCompletedHandler import_completed);
-		void FetchAlbumArtwork (ArtworkDownloadCompletedHandler download_completed);
-	}
-
-	public class ArtworkDownloadCompletedArgs : EventArgs
-	{
-		public byte[] Data;
-
-		public ArtworkDownloadCompletedArgs (byte[] data)
-		{
-			this.Data = data;
-		}
 	}
 
 	public class MetadataImportCompletedArgs : EventArgs

Modified: trunk/base/services/MetadataProxyService.cs
==============================================================================
--- trunk/base/services/MetadataProxyService.cs	(original)
+++ trunk/base/services/MetadataProxyService.cs	Tue Jun  3 05:01:58 2008
@@ -54,18 +54,6 @@
 			});
 		}
 
-		public void FetchAlbumArtwork (ArtworkDownloadCompletedHandler download_completed)
-		{
-			if (download_completed == null) {
-				throw new ArgumentNullException ("download_completed");
-			}
-
-			this.download_completed = download_completed;
-
-			dispatch_svc.BackgroundDispatch (new FetchArtworkHandler (WorkerFetchAlbumArtwork),
-			                                 new object[0]);
-		}
-
 		/**
 		 * Scans all external MetadataServices for matches to the
 		 * current tracks.  When finished, import_completed is invoked
@@ -88,29 +76,12 @@
 
 #region private fields
 		private List<DictionaryEntry> proxies = new List<DictionaryEntry> ();
-		private ArtworkDownloadCompletedHandler download_completed = null;
 		private MetadataImportCompletedHandler import_completed = null;
 
 		private IDispatchService dispatch_svc;
 #endregion
 
 #region private methods
-		private void WorkerFetchAlbumArtwork ()
-		{
-			byte[] data = null;
-			for (int i = 0; i < proxies.Count; i++) {
-				IMetadataProxy p = (IMetadataProxy)proxies[i].Value;
-
-				data = p.FetchAlbumArtwork ();
-				if (data != null && data.Length > 0) {
-					break;
-				}
-			}
-
-			dispatch_svc.GuiDispatch (download_completed, new object[] {
-				this, new ArtworkDownloadCompletedArgs (data) });
-		}
-
 		private void WorkerFetchMetadata ()
 		{
 			MetadataImportStatus max_status = MetadataImportStatus.NetworkError;
@@ -135,7 +106,6 @@
 
 #region private delegates
 		private delegate void FetchMetadataHandler ();
-		private delegate void FetchArtworkHandler ();
 #endregion
 	}
 }

Modified: trunk/gui/AlbumCoverImage.cs
==============================================================================
--- trunk/gui/AlbumCoverImage.cs	(original)
+++ trunk/gui/AlbumCoverImage.cs	Tue Jun  3 05:01:58 2008
@@ -31,7 +31,7 @@
 
 using Cowbell.Base;
 
-namespace Cowbell
+namespace Cowbell.Gui
 {
 	/*
 	 * Sean Connery: Well, the game is afoot. I'll take anal bum cover for 7,000.
@@ -45,13 +45,10 @@
 #region public methods
 		public AlbumCoverImage ()
 		{
-			db_svc = (IDatabaseService)ServiceManager.GetService (
-					typeof (IDatabaseService));
-			prx_svc = (IMetadataProxyService)ServiceManager.GetService (
-					typeof (IMetadataProxyService));
-
-			pixbuf = null;
-			UserPixbuf = false;
+			art_cache_svc
+				= (AlbumArtworkCacheService)ServiceManager.GetService (
+					typeof (AlbumArtworkCacheService));
+			art_cache_svc.ArtworkChanged += new ArtworkChangedHandler (OnArtworkChanged);
 
 			loadingcover = new Gdk.Pixbuf (null, "loading-cover.png");
 			defaultcover = new Gdk.Pixbuf (null, "default-cover.png");
@@ -59,11 +56,6 @@
 			image = new Gtk.Image ();
 			image.Pixbuf = defaultcover;
 
-			covers = new Hashtable ();
-			covers.Add ("0", defaultcover);
-			
-			large_covers = new Hashtable ();
-
 			Gtk.Drag.DestSet (this, DestDefaults.All, CoverDragEntries, Gdk.DragAction.Copy);
 			DragDataReceived += new DragDataReceivedHandler (DragDataReceivedCb);
 
@@ -71,19 +63,8 @@
 			image.Show ();
 		}
 
-		public void Save (string filename)
-		{
-			if (large_covers.ContainsKey (stamp)) {
-				((Pixbuf)large_covers[stamp]).Save (filename, "jpeg");
-			}
-		}
-
 		public bool CheckFilesystemForAlbumArt (string path)
 		{
-			if (UserPixbuf) {
-				return false;
-			}
-
 			foreach (string file in CoverFilenames)
 			{
 				FileInfo cover = new FileInfo (System.IO.Path.Combine (path, file));
@@ -91,61 +72,13 @@
 				if (cover.Exists) {
 					Pixbuf buf = BeautifyPixbuf (new Pixbuf (cover.ToString ()));					
 					if (buf != null) {
-						UserPixbuf = true;
-						original = buf;
-						Refresh ();
+						art_cache_svc.CacheArtwork (buf);
 						return true;
 					}
 				}	
 			}
 			return false;
 		}
-
-		public void Refresh ()
-		{
-			image.Pixbuf = original;
-		}
-
-		public void Download ()
-		{
-			stamp = GetStamp (db_svc.GlobalData);
-			if (UserPixbuf) {
-				return;
-			}
-
-			if (covers.ContainsKey (stamp)) {
-				original = covers[stamp] as Pixbuf;
-				if (original == null) {
-					ShowDefaultCover ();
-					return;
-				}
-				Refresh ();
-				return;
-			}
-
-			// We're already loading
-			if (original == loadingcover) {
-				return;
-			}
-
-			ShowLoadingCover ();
-		
-			prx_svc.FetchAlbumArtwork (
-				new ArtworkDownloadCompletedHandler (
-					OnArtworkDownloadComplete));
-		}
-
-		public void ShowDefaultCover ()
-		{
-			original = defaultcover;
-			Refresh ();
-		}
-
-		public void Clear ()
-		{
-			ShowDefaultCover ();
-			UserPixbuf = false;
-		}
 #endregion
 
 #region private fields
@@ -154,15 +87,6 @@
 		private static Pixbuf defaultcover;
 		private static Pixbuf loadingcover;
 
-		private Pixbuf pixbuf;
-		private Pixbuf original;
-		private string stamp;
-
-		private Hashtable covers;
-		private Hashtable large_covers;
-		
-		private bool UserPixbuf;
-
 		private static TargetEntry[] CoverDragEntries = new TargetEntry[] {
 			new TargetEntry ("text/uri-list", 0, (uint)TargetType.UriList),
 			new TargetEntry ("x-special/gnome-icon-list", 0, (uint)TargetType.UriList),
@@ -183,50 +107,29 @@
 			Uri
 		};
 		
-		private IDatabaseService db_svc;
-		private IMetadataProxyService prx_svc;
+		private AlbumArtworkCacheService art_cache_svc;
 #endregion
 
 #region private methods
-		private void ShowLoadingCover ()
-		{
-			original = loadingcover;
-			Refresh ();
-		}
-
-		private void OnArtworkDownloadComplete (object o, ArtworkDownloadCompletedArgs args)
+		private void OnArtworkChanged (object o, ArtworkChangedArgs args)
 		{
-			byte[] bytes = args.Data;
-			try {
-				if (bytes != null && bytes.Length > 0) {
-					pixbuf = new Gdk.Pixbuf (bytes);
-				}
-			} catch (Exception e) {
-				pixbuf = null;
-
-				Debug.WriteLine (e.Message);
-				Debug.WriteLine (e.StackTrace);
+Console.WriteLine ("OnArtworkChanged: loading? {0}, data == null? {1}", args.IsLoading, (args.ImageData == null));
+			Gdk.Pixbuf pixbuf = null;
+			if (args.IsLoading) {
+				pixbuf = loadingcover;
+				goto Done;
 			}
 
-			GLib.Idle.Add (new GLib.IdleHandler (ProcessCoverDownload));
-		}
+			Gdk.Pixbuf data = args.ImageData as Gdk.Pixbuf;
+			if (data == null) {
+				pixbuf = defaultcover;
+				goto Done;
+			}
 
-		private bool ProcessCoverDownload ()
-		{
-			lock (this) {
-				if (pixbuf == null) {
-					original = null;
-					covers[stamp] = null;
-					ShowDefaultCover ();
-					return false;
-				}
+			pixbuf = BeautifyPixbuf (data);
 
-				large_covers[stamp] = pixbuf;
-				original = BeautifyPixbuf (pixbuf);
-				covers[stamp] = original; 
-				Refresh ();
-			}
-			return false;
+Done:
+			image.Pixbuf = pixbuf;
 		}
 
 		private Pixbuf BeautifyPixbuf (Pixbuf cover)
@@ -262,22 +165,10 @@
 			return border;
 		}
 
-		private Pixbuf GetCoverLocal (string path)
-		{
-			Pixbuf cover;
-
-			try {
-				cover = new Pixbuf (path);
-			} catch {
-				return null;
-			}
-
-			return cover;
-		}
-
 		/* DnD Callbacks mostly stolen from Jorn Baayen */
 		private void DragDataReceivedCb (object o, DragDataReceivedArgs args)
 		{
+			Gdk.Pixbuf pixbuf = null;
 			string selectiondata;
 			bool success = false;
 			string[] tokens;
@@ -301,8 +192,7 @@
 				}
 
 				try {
-					original = new Gdk.Pixbuf (bytes);
-					UserPixbuf = true;
+					pixbuf = new Gdk.Pixbuf (bytes);
 					success = true;
 				} catch { }
 
@@ -317,31 +207,19 @@
 			
 				success = false;
 				try {
-					original = GetCoverLocal (path);
-					UserPixbuf = true;
+					pixbuf = new Pixbuf (path);
 					success = true;
 				} catch { }
 
 				break;
 			}
 
-			if (success) {
-				large_covers[stamp] = original;
-				original = BeautifyPixbuf (original);
-				covers[stamp] = original;
-				Refresh ();
+			if (success && pixbuf != null) {
+				art_cache_svc.CacheArtwork (pixbuf);
 			}
 	
 			Gtk.Drag.Finish (args.Context, success, false, args.Time);
 		}
-
-		private string GetStamp (Song s)
-		{
-			if (s != null) {
-				return s.ArtistAlbumStamp;
-			}
-			return "0";
-		}
 #endregion
 	}
 }

Modified: trunk/gui/MainWindow.cs
==============================================================================
--- trunk/gui/MainWindow.cs	(original)
+++ trunk/gui/MainWindow.cs	Tue Jun  3 05:01:58 2008
@@ -46,6 +46,7 @@
 			ServiceManager.RegisterService (new GLibDispatchService ());
 			ServiceManager.RegisterService (new FilesystemService ());
 			ServiceManager.RegisterService (new MetadataProxyService ());
+			ServiceManager.RegisterService (new AlbumArtworkCacheService ());
 
 			CliParser parser = new CliParser (Globals.AppName,
 			                                  Catalog.GetString ("An elegant music organizer."),
@@ -122,11 +123,6 @@
 			MultipleArtistCheckBox.Toggled += new EventHandler (OnMultipleArtistCheckBoxToggled);
 			MultipleDiscCheckBox.Toggled += new EventHandler (OnMultipleDiscCheckBoxToggled);
 
-			ArtistEntry.FocusOutEvent += new FocusOutEventHandler (OnEntryFocusOutEvent);
-			AlbumEntry.FocusOutEvent += new FocusOutEventHandler (OnEntryFocusOutEvent);
-			YearEntry.FocusOutEvent += new FocusOutEventHandler (OnEntryFocusOutEvent);
-			GenreComboBox.FocusOutEvent += new FocusOutEventHandler (OnEntryFocusOutEvent);
-
 			about.Activated += new EventHandler (OnHelpAboutActivate);
 			open.Activated += new EventHandler (OnFileOpenActivate);
 			save.Activated += new EventHandler (OnFileSaveActivate);
@@ -136,8 +132,6 @@
 			preferences.Activated += new EventHandler (OnEditPreferencesActivate);
 			clear_list.Activated += new EventHandler (OnEditClearListActivate);
 
-			GLib.Timeout.Add (3000, new GLib.TimeoutHandler (OnCoverImageUpdateTimeout));
-
 			window.ShowAll ();
 			Freeze ();
 		}
@@ -301,9 +295,6 @@
 				 * language, let me know. */
 				Runtime.Message.ShowError (String.Format (Catalog.GetString ("You have just imported {0} songs, generally more than one album worth of music.\n\nCowbell is intended for tagging just one album at a time, and will not work effectively if given more than one album.  To tag multiple albums at a time, Cowbell has a batch tagging mode, enabled by passing \"--batch\" on the console.\n\nIf you are only trying to tag one album, you can safely ignore this message."), Runtime.Database.Count));
 			}
-
-			cover.Clear ();
-			OnCoverImageUpdateTimeout ();
 		}
 
 		private void OnFileSaveActivate (object o, EventArgs args)
@@ -357,7 +348,6 @@
 		{
 			Runtime.Database.Clear ();
 			Runtime.Database.GlobalData = new Song ();
-			cover.Clear ();
 			Runtime.Dirty = false;
 
 			Runtime.Database.MultipleArtists = false;
@@ -402,11 +392,6 @@
 			save.Sensitive = true;
 		}
 
-		private void OnEntryFocusOutEvent (object o, FocusOutEventArgs args)
-		{
-			OnCoverImageUpdateTimeout ();
-		}
-
 		private void OnMultipleArtistCheckBoxToggled (object o, EventArgs args)
 		{
 			Runtime.Database.MultipleArtists = ((ToggleButton)o).Active;
@@ -419,7 +404,6 @@
 
 		private void OnMultipleArtistsChanged ()
 		{
-			OnCoverImageUpdateTimeout ();
 			ArtistEntry.Sensitive = !Runtime.Database.MultipleArtists;
 			
 			/* Prevent circular eventing badness */
@@ -438,12 +422,6 @@
 			MultipleDiscCheckBox.Toggled += new EventHandler (OnMultipleDiscCheckBoxToggled);
 		}
 
-		private bool OnCoverImageUpdateTimeout ()
-		{
-			cover.Download ();
-			return true;
-		}
-
 		private void OnUnhandledException (object o, UnhandledExceptionEventArgs args)
 		{
 			UnhandledExceptionDialog d = new UnhandledExceptionDialog ((Exception)args.ExceptionObject);

Modified: trunk/gui/Makefile.am
==============================================================================
--- trunk/gui/Makefile.am	(original)
+++ trunk/gui/Makefile.am	Tue Jun  3 05:01:58 2008
@@ -23,6 +23,7 @@
 services/GLibDispatchService.cs \
 services/GtkMessageService.cs \
 services/MainWindowService.cs \
+services/AlbumArtworkCacheService.cs \
 AboutDialog.cs \
 AlbumCoverImage.cs \
 ErrorDialog.cs \

Added: trunk/gui/services/AlbumArtworkCacheService.cs
==============================================================================
--- (empty file)
+++ trunk/gui/services/AlbumArtworkCacheService.cs	Tue Jun  3 05:01:58 2008
@@ -0,0 +1,209 @@
+/*
+ * cowbell
+ * Copyright (c) 2008 Brad Taylor
+ *
+ * This file is part of cowbell.
+ *
+ * cowbell is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * cowbell is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with cowbell; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+using Gdk;
+using System;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+
+using Cowbell.Base;
+
+namespace Cowbell.Gui
+{
+	public class AlbumArtworkCacheService : IAlbumArtworkCacheService
+	{
+#region public events
+		public event ArtworkChangedHandler ArtworkChanged;
+#endregion
+
+#region public methods
+		public void Load ()
+		{
+			dispatch_svc = (IDispatchService)ServiceManager.GetService (
+					typeof (IDispatchService));
+			db_svc = (IDatabaseService)ServiceManager.GetService (
+					typeof (IDatabaseService));
+	
+			db_svc.GlobalDataModified += new VoidHandler (OnGlobalDataModified);
+
+			Assembly asm = Assembly.GetCallingAssembly ();
+			foreach (Type t in asm.GetTypes ())
+			{
+				foreach (Attribute a in Attribute.GetCustomAttributes (t))
+				{
+					if (a.GetType () == typeof (ArtworkProxyPriorityAttribute)) {
+						int priority = ((ArtworkProxyPriorityAttribute)a).Priority;
+
+						IArtworkProxy p = (IArtworkProxy)Activator.CreateInstance (t);
+						proxies.Add (new DictionaryEntry (priority, p));
+					}
+				}
+			}
+
+			proxies.Sort (delegate (DictionaryEntry a, DictionaryEntry b) {
+				return ((IComparable)a.Key).CompareTo (b.Key);
+			});
+
+			// By default, if we have no album/artist loaded, send
+			// back null to the gui
+			artwork["0"] = null;
+		}
+
+		public void CacheArtwork (Gdk.Pixbuf data)
+		{
+			artwork[CurrentStamp] = data;
+
+			if (ArtworkChanged != null) {
+				ArtworkChanged (this, new ArtworkChangedArgs (false, data));
+			}
+		}
+
+		public void SaveCurrentArtwork (string filename, string type)
+		{
+			string stamp = CurrentStamp;
+			if (!artwork.ContainsKey (stamp)) {
+				// nothing to save
+				return;
+			}
+
+			Gdk.Pixbuf pixbuf = artwork[stamp];
+			if (pixbuf == null) {
+				// nothing to save
+				return;
+			}
+
+			pixbuf.Save (filename, type);
+		}
+#endregion
+
+#region private delegates
+		private delegate void FetchArtworkHandler (string stamp);
+		private delegate void DownloadCompleteHandler (string stamp, byte[] data);
+#endregion
+
+#region private delegates
+		private string CurrentStamp {
+			get { return GetStamp (db_svc.GlobalData); }
+		}
+#endregion
+
+#region private fields
+		private IDatabaseService db_svc;
+		private IDispatchService dispatch_svc;
+
+		private List<DictionaryEntry> proxies = new List<DictionaryEntry> ();
+		private Dictionary<string, Gdk.Pixbuf> artwork = new Dictionary<string, Gdk.Pixbuf> ();
+		
+		private uint timeout_id = 0;
+#endregion
+
+#region private methods
+		private void OnGlobalDataModified ()
+		{
+			if (timeout_id > 0) {
+				GLib.Source.Remove (timeout_id);
+			}
+
+			// Rate-limit updates
+			timeout_id = GLib.Timeout.Add (500, new GLib.TimeoutHandler (OnGlobalDataModifiedTimeout));
+		}
+
+		private bool OnGlobalDataModifiedTimeout ()
+		{
+			timeout_id = 0;
+
+			string stamp = CurrentStamp;
+Console.WriteLine ("OnGlobalDataModified: {0}", stamp);
+
+			// return the artwork if we've already cached it
+			if (artwork.ContainsKey (stamp)) {
+				if (ArtworkChanged != null) {
+					ArtworkChanged (this, new ArtworkChangedArgs (false, artwork[stamp]));
+				}
+				return false;
+			}
+
+			// if not, start downloading
+			dispatch_svc.BackgroundDispatch (new FetchArtworkHandler (WorkerFetchAlbumArtwork),
+			                                 new object[] { stamp });
+
+			// notify that we're loading
+			if (ArtworkChanged != null) {
+				ArtworkChanged (this, new ArtworkChangedArgs (true, null));
+			}
+
+			return false;
+		}
+
+		private void WorkerFetchAlbumArtwork (string stamp)
+		{
+Console.WriteLine ("WorkerFetchAlbumArtwork");
+			byte[] data = null;
+			for (int i = 0; i < proxies.Count; i++) {
+Console.WriteLine ("Got a proxy!");
+				IArtworkProxy p = (IArtworkProxy)proxies[i].Value;
+
+				data = p.FetchAlbumArtwork ();
+				if (data != null && data.Length > 0) {
+					break;
+				}
+			}
+
+			dispatch_svc.GuiDispatch (new DownloadCompleteHandler (OnArtworkDownloadComplete),
+			                          new object[] { stamp, data });
+		}
+
+		private void OnArtworkDownloadComplete (string stamp, byte[] data)
+		{
+			Gdk.Pixbuf pixbuf = null;
+			try {
+				if (data != null && data.Length > 0) {
+					pixbuf = new Gdk.Pixbuf (data);
+				}
+			} catch (Exception e) {
+				Debug.WriteLine (e.Message);
+				Debug.WriteLine (e.StackTrace);
+			}
+
+			artwork[CurrentStamp] = pixbuf;
+
+			if (stamp != CurrentStamp) {
+				// old data, don't fire the event, but still
+				// put it in your pocket for safe keeping
+				return;
+			}
+
+			if (ArtworkChanged != null) {
+				ArtworkChanged (this, new ArtworkChangedArgs (false, pixbuf));
+			}
+		}
+
+		private string GetStamp (Song s)
+		{
+			if (s != null) {
+				return s.ArtistAlbumStamp;
+			}
+			return "0";
+		}
+#endregion
+	}
+}



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