banshee r3590 - in trunk/banshee: . libbanshee src/Core/Banshee.Services/Banshee.Sources src/Extensions/Banshee.AudioCd/Banshee.AudioCd



Author: abock
Date: Sat Mar 29 22:40:30 2008
New Revision: 3590
URL: http://svn.gnome.org/viewvc/banshee?rev=3590&view=rev

Log:
2008-03-29  Aaron Bockover  <abock gnome org>

    * libbanshee/gst-playback-0.10.c: Actually set the pipeline to NULL, not
    PAUSED when stopping the pipeline so any resources locked by the pipeline
    are released

    * src/Core/Banshee.Services/Banshee.Sources/Source.cs: Added ClearMessages

    * src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs:
    Search for metadata using MusicBrainz

    * src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs:
    Show status messages when searching for metadata and ejecting; if the
    playing track is located on the disc that is to be ejected, stop the
    playback before ejecting to release the device lock

    * src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdTrackInfo.cs:
    Hold a reference to the model on each track in the model so it can
    be checked when ejecting



Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/libbanshee/gst-playback-0.10.c
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs
   trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
   trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdTrackInfo.cs

Modified: trunk/banshee/libbanshee/gst-playback-0.10.c
==============================================================================
--- trunk/banshee/libbanshee/gst-playback-0.10.c	(original)
+++ trunk/banshee/libbanshee/gst-playback-0.10.c	Sat Mar 29 22:40:30 2008
@@ -721,8 +721,8 @@
     g_return_if_fail(IS_GST_PLAYBACK(engine));
     gst_playback_stop_iterate_timeout(engine);
     if(GST_IS_ELEMENT(engine->playbin)) {
-        engine->target_state = GST_STATE_PAUSED;
-        gst_element_set_state(engine->playbin, GST_STATE_PAUSED);
+        engine->target_state = GST_STATE_NULL;
+        gst_element_set_state(engine->playbin, GST_STATE_NULL);
     }
 }
 

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Sat Mar 29 22:40:30 2008
@@ -235,6 +235,16 @@
             }
         }
         
+        protected virtual void ClearMessages ()
+        {
+            lock (this) {
+                if (messages.Count > 0) {
+                    messages.Clear ();
+                    OnMessageNotify ();
+                }
+            }
+        }
+        
         private void TestMessages ()
         {
             int count = 0;

Modified: trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdDiscModel.cs	Sat Mar 29 22:40:30 2008
@@ -27,9 +27,15 @@
 //
 
 using System;
-using Mono.Unix;
+using System.Threading;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
 
+using Mono.Unix;
 using MusicBrainz;
+
+using Hyena;
+using Banshee.Base;
 using Banshee.Hardware;
 using Banshee.Collection;
 
@@ -39,6 +45,21 @@
     {
         private IDiscVolume volume;
         
+        public event EventHandler MetadataQueryStarted;
+        public event EventHandler MetadataQueryFinished;
+        
+        private bool metadata_query_success;
+        private DateTime metadata_query_start_time;
+        
+        public bool MetadataQuerySuccess {
+            get { return metadata_query_success; }
+        }
+        
+        private TimeSpan duration;
+        public TimeSpan Duration {
+            get { return duration; }
+        }
+        
         public AudioCdDiscModel (IDiscVolume volume)
         {
             this.volume = volume;
@@ -47,13 +68,15 @@
         
         public void LoadModelFromDisc ()
         {
+            Clear ();
+        
             LocalDisc mb_disc = LocalDisc.GetFromDevice (volume.DeviceNode);
             if (mb_disc == null) {
                 throw new ApplicationException ("Could not read contents of the disc. Platform may not be supported.");
             }
             
             for (int i = 0, n = mb_disc.TrackDurations.Length; i < n; i++) {
-                AudioCdTrackInfo track = new AudioCdTrackInfo (volume.DeviceNode, i);
+                AudioCdTrackInfo track = new AudioCdTrackInfo (this, volume.DeviceNode, i);
                 track.TrackNumber = i + 1;
                 track.TrackCount = n;
                 track.Duration = TimeSpan.FromSeconds (mb_disc.TrackDurations[i]);
@@ -61,7 +84,98 @@
                 track.AlbumTitle = Catalog.GetString ("Unknown Album");
                 track.TrackTitle = String.Format(Catalog.GetString ("Track {0}"), track.TrackNumber);
                 Add (track);
+                
+                duration += track.Duration;
+            }
+            
+            Reload ();
+            
+            ThreadPool.QueueUserWorkItem (LoadDiscMetadata, mb_disc);
+        }
+        
+        private void LoadDiscMetadata (object state)
+        {
+            LocalDisc mb_disc = (LocalDisc)state;
+            
+            OnMetadataQueryStarted (mb_disc);
+            
+            ReleaseQueryParameters parameters = new ReleaseQueryParameters ();
+            parameters.DiscID = mb_disc.Id;
+            
+            Query<Release> results = Release.Query (parameters);
+            if (results == null) {
+                OnMetadataQueryFinished (false);
+                return;
+            }
+                
+            Release release = results.PerfectMatch ();
+            if (release == null) {
+                OnMetadataQueryFinished (false);
+                return;
             }
+            
+            ReadOnlyCollection<Track> tracks = release.Tracks;
+            if (tracks == null || tracks.Count != Count) {
+                OnMetadataQueryFinished (false);
+                return;
+            }
+            
+            disc_title = release.Title;
+            
+            int i = 0;
+            
+            // FIXME: Ugly hack to work around either a horrid design or a bug
+            // in mb-sharp; the track doesn't seem to get loaded from the web
+            // service until the properties are accessed on the object. This
+            // makes loading the metadata *waaaayyy* slower than it needs to be.
+            foreach (Track track in tracks) {
+                DevNull (track.Title);
+                DevNull (track.Artist.Name);
+            }
+            
+            foreach (Track track in tracks) {
+                // FIXME: Gather more details from MB to save to the DB
+                this[i].TrackTitle = track.Title;
+                this[i].ArtistName = track.Artist.Name;
+                this[i].AlbumTitle = release.Title;
+                i++;
+            }
+            
+            OnMetadataQueryFinished (true);
+        }
+        
+        private void DevNull (object o)
+        {
+        }
+        
+        private void OnMetadataQueryStarted (LocalDisc mb_disc)
+        {
+            metadata_query_success = false;
+            metadata_query_start_time = DateTime.Now;
+            Log.InformationFormat ("Querying MusicBrainz for Disc Release ({0})", mb_disc.Id);
+        
+            ThreadAssist.ProxyToMain (delegate { 
+                EventHandler handler = MetadataQueryStarted;
+                if (handler != null) {
+                    handler (this, EventArgs.Empty);
+                }
+            });
+        }
+        
+        private void OnMetadataQueryFinished (bool success)
+        {
+            metadata_query_success = success;
+            Log.InformationFormat ("Query finished (success: {0}, {1} seconds)", 
+                success, (DateTime.Now - metadata_query_start_time).TotalSeconds);
+            
+            ThreadAssist.ProxyToMain (delegate {
+                Reload ();
+                
+                EventHandler handler = MetadataQueryFinished;
+                if (handler != null) {
+                    handler (this, EventArgs.Empty);
+                }
+            });
         }
         
         public IDiscVolume Volume {

Modified: trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdSource.cs	Sat Mar 29 22:40:30 2008
@@ -27,18 +27,22 @@
 //
 
 using System;
+using System.Threading;
 using Mono.Unix;
 
 using Hyena;
+using Banshee.Base;
+using Banshee.ServiceStack;
 using Banshee.Sources;
 using Banshee.Collection;
 
 namespace Banshee.AudioCd
 {
-    public class AudioCdSource : Source, ITrackModelSource, IUnmapableSource, IDisposable
+    public class AudioCdSource : Source, ITrackModelSource, IUnmapableSource, IDurationAggregator, IDisposable
     {
         private AudioCdService service;
         private AudioCdDiscModel disc_model;
+        private SourceMessage query_message;
         
         public AudioCdSource (AudioCdService service, AudioCdDiscModel discModel) 
             : base (Catalog.GetString ("Audio CD"), discModel.Title, 200)
@@ -46,19 +50,78 @@
             this.service = service;
             this.disc_model = discModel;
             
+            disc_model.MetadataQueryStarted += OnMetadataQueryStarted;
+            disc_model.MetadataQueryFinished += OnMetadataQueryFinished;
             disc_model.LoadModelFromDisc ();
             
             Properties.SetStringList ("Icon.Name", "media-cdrom", "gnome-dev-cdrom-audio", "source-cd-audio");
             Properties.SetString ("UnmapSourceActionLabel", Catalog.GetString ("Eject Disc"));
         }
         
+        public TimeSpan Duration {
+            get { return disc_model.Duration; }
+        }
+        
         public void Dispose ()
         {
+            ClearMessages ();
+            disc_model.MetadataQueryStarted -= OnMetadataQueryStarted;
+            disc_model.MetadataQueryFinished -= OnMetadataQueryFinished;
+            service = null;
+            disc_model = null;
         }
         
         public AudioCdDiscModel DiscModel {
             get { return disc_model; }
         }
+        
+        private void OnMetadataQueryStarted (object o, EventArgs args)
+        {
+            if (query_message != null) {
+                DestroyQueryMessage ();
+            }
+            
+            query_message = new SourceMessage (this);
+            query_message.FreezeNotify ();
+            query_message.CanClose = false;
+            query_message.IsSpinning = true;
+            query_message.Text = Catalog.GetString ("Searching for CD metadata...");
+            query_message.ThawNotify ();
+            
+            PushMessage (query_message);
+        }
+        
+        private void OnMetadataQueryFinished (object o, EventArgs args)
+        {
+            if (disc_model.Title != Name) {
+                Name = disc_model.Title;
+                OnUpdated ();
+            }
+        
+            if (query_message == null) {
+                return;
+            }
+            
+            if (disc_model.MetadataQuerySuccess) {
+                DestroyQueryMessage ();
+                return;
+            }
+            
+            query_message.FreezeNotify ();
+            query_message.IsSpinning = false;
+            query_message.SetIconName ("dialog-error");
+            query_message.Text = Catalog.GetString ("Could not fetch metadata for CD.");
+            query_message.CanClose = true;
+            query_message.ThawNotify ();
+        }
+        
+        private void DestroyQueryMessage ()
+        {
+            if (query_message != null) {
+                RemoveMessage (query_message);
+                query_message = null;
+            }
+        }
 
 #region Source Overrides
 
@@ -134,18 +197,41 @@
 
         public bool Unmap ()
         {
-            System.Threading.ThreadPool.QueueUserWorkItem (delegate {
+            AudioCdTrackInfo playing_track = ServiceManager.PlayerEngine.CurrentTrack as AudioCdTrackInfo;
+            if (playing_track != null && playing_track.Model == disc_model) {
+                ServiceManager.PlayerEngine.Close ();
+            }
+            
+            SourceMessage eject_message = new SourceMessage (this);
+            eject_message.FreezeNotify ();
+            eject_message.IsSpinning = true;
+            eject_message.CanClose = false;
+            eject_message.Text = Catalog.GetString ("Ejecting audio CD...");
+            eject_message.ThawNotify ();
+            PushMessage (eject_message);
+        
+            ThreadPool.QueueUserWorkItem (delegate {
                 try {
                     disc_model.Volume.Unmount ();
                     disc_model.Volume.Eject ();
+                    
+                    ThreadAssist.ProxyToMain (delegate {
+                        service.UnmapDiscVolume (disc_model.Volume.Uuid);
+                        Dispose ();
+                    });
                 } catch (Exception e) {
-                    Log.Error (Catalog.GetString ("Could not eject Audio CD"), e.Message, true);
+                    ThreadAssist.ProxyToMain (delegate {
+                        ClearMessages ();
+                        eject_message.IsSpinning = false;
+                        eject_message.SetIconName ("dialog-error");
+                        eject_message.Text = String.Format (Catalog.GetString ("Could not eject audio CD: {0}"), e.Message);
+                        PushMessage (eject_message);
+                    });
+                    
                     Log.Exception (e);
                 }
             });
             
-            service.UnmapDiscVolume (disc_model.Volume.Uuid);
-            
             return true;
         }
 

Modified: trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdTrackInfo.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.AudioCd/Banshee.AudioCd/AudioCdTrackInfo.cs	Sat Mar 29 22:40:30 2008
@@ -35,12 +35,19 @@
 {
     public class AudioCdTrackInfo : TrackInfo
     {
-        public AudioCdTrackInfo (string deviceNode, int index)
+        public AudioCdTrackInfo (AudioCdDiscModel model, string deviceNode, int index)
         {
-            index_on_disc = index;            
+            this.model = model;
+            this.index_on_disc = index;
+            
             Uri = new SafeUri ("cdda://" + index_on_disc + "#" + deviceNode); 
         }
         
+        private AudioCdDiscModel model;
+        public AudioCdDiscModel Model {
+            get { return model; }
+        }
+        
         private int index_on_disc;
         public int IndexOnDisc {
             get { return index_on_disc; }



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