banshee r4991 - in branches/banshee/stable: . src/Core/Banshee.Services/Banshee.MediaEngine src/Core/Banshee.Services/Banshee.Streaming src/Core/Banshee.ThickClient/Banshee.Gui src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Core/Banshee.Widgets/Banshee.Widgets src/Libraries/Mtp/Mtp



Author: gburt
Date: Fri Jan 30 21:22:37 2009
New Revision: 4991
URL: http://svn.gnome.org/viewvc/banshee?rev=4991&view=rev

Log:
2009-01-30  Gabriel Burt  <gabriel burt gmail com>

	* src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs: Show the
	pause/stop button when Loading/Loaded.

	* src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedSeekSlider.cs:
	Handle Loading player state, set Live property on the position label, and
	use the position label's enum state property instead of a handful of bools

	* src/Core/Banshee.Services/Banshee.Streaming/RadioTrackInfo.cs: Start
	playing internet radio playlists in a separate thread to avoid blocking
	the UI (BGO #548040, BNC #376532).  Handle the case where the user
	presses stop or switches to a different track while we're
	downloading/processing the playlist file (previously we would have started
	playing once ready, even if the user had already moved on).  Also, fix
	bug where errors reported by the MediaEngine (GStreamer) weren't shown to
	the user.

	* src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs: If the
	engine is in PlayerState.Contacting, don't Close/stop since this is a
	state we set in managed land for loading internet radio tracks.

	* src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs:
	Add Start/EndSynthesizeContacting internal methods for use by
	RadioTrackInfo - basically a hack until we move the playlist loading logic
	from RadioTrackInfo to the PlayerENgine to get UI bits updated
	appropriately.  Fix IsPlaying to include Contacting/Loading/Loaded, so
	that TogglePlaying will Pause if in any of those states (not just if in
	the Playing state), and Play only when in Ready, Idle, or Paused.

	* src/Core/Banshee.Widgets/Banshee.Widgets/StreamPositionLabel.cs: Use an
	enum to track the player state instead of a handful of bools.  Show the
	"Contacting..." label when inthe Loading state (for now - will change to
	Loading... in a separate patch).

	* src/Core/Banshee.Widgets/Banshee.Widgets/SeekSlider.cs: If the new Value
	is more than the Duration, set the Duration to MaxValue so that the slider
	stays at the left side of the Range, avoiding the glitchy-looking UI going
	from Idle (where the slider is all the way left) to playing radio (where
	it was all the way right).



Modified:
   branches/banshee/stable/   (props changed)
   branches/banshee/stable/ChangeLog
   branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
   branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
   branches/banshee/stable/src/Core/Banshee.Services/Banshee.Streaming/RadioTrackInfo.cs
   branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedSeekSlider.cs
   branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs
   branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/SeekSlider.cs
   branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/StreamPositionLabel.cs
   branches/banshee/stable/src/Libraries/Mtp/Mtp/File.cs
   branches/banshee/stable/src/Libraries/Mtp/Mtp/Playlist.cs
   branches/banshee/stable/src/Libraries/Mtp/Mtp/Track.cs

Modified: branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngine.cs	Fri Jan 30 21:22:37 2009
@@ -90,7 +90,7 @@
 
         private void HandleOpen (SafeUri uri)
         {
-            if (current_state != PlayerState.Idle && current_state != PlayerState.NotReady) {
+            if (current_state != PlayerState.Idle && current_state != PlayerState.NotReady && current_state != PlayerState.Contacting) {
                 Close (false);
             }
         
@@ -106,7 +106,7 @@
         public abstract void Play ();
 
         public abstract void Pause ();
-        
+
         public virtual void VideoExpose (IntPtr window, bool direct)
         {
             throw new NotImplementedException ("Engine must implement VideoExpose since this method only gets called when SupportsVideo is true");

Modified: branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.Services/Banshee.MediaEngine/PlayerEngineService.cs	Fri Jan 30 21:22:37 2009
@@ -55,6 +55,7 @@
         private PlayerEngine pending_engine;
         private object pending_playback_for_not_ready;
         private bool pending_playback_for_not_ready_play;
+        private TrackInfo synthesized_contacting_track;
 
         private string preferred_engine_id = null;
 
@@ -339,9 +340,9 @@
                 // If we're at least 50% done playing a song, mark it as played, otherwise as skipped
                 // If the Length <= 0, assume the song was finished and increment its play count
                 if (active_engine.Length <= 0 || active_engine.Position >= active_engine.Length / 2) {
-                    active_engine.CurrentTrack.IncrementPlayCount ();
+                    CurrentTrack.IncrementPlayCount ();
                 } else {
-                    active_engine.CurrentTrack.IncrementSkipCount ();
+                    CurrentTrack.IncrementSkipCount ();
                 }
                 incremented_last_played = true;
             }
@@ -406,12 +407,32 @@
                 active_engine.Pause ();
             }
         }
+
+        // For use by RadioTrackInfo
+        // TODO remove this method once RadioTrackInfo playlist downloading/parsing logic moved here?
+        internal void StartSynthesizeContacting (TrackInfo track)
+        {
+            //OnStateChanged (PlayerState.Contacting);
+            RaiseEvent (new PlayerEventStateChangeArgs (CurrentState, PlayerState.Contacting));
+            synthesized_contacting_track = track;
+        }
+
+        internal void EndSynthesizeContacting (TrackInfo track, bool idle)
+        {
+            if (track == synthesized_contacting_track) {
+                synthesized_contacting_track = null;
+
+                if (idle) {
+                    RaiseEvent (new PlayerEventStateChangeArgs (PlayerState.Contacting, PlayerState.Idle));
+                }
+            }
+        }
         
         public void TogglePlaying ()
         {
-            if (CurrentState == PlayerState.Playing) {
+            if (IsPlaying ()) {
                 Pause ();
-            } else {
+            } else if (CurrentState != PlayerState.NotReady) {
                 Play ();
             }
         }
@@ -439,7 +460,9 @@
         {
             return CurrentState == PlayerState.Playing || 
                 CurrentState == PlayerState.Paused || 
-                CurrentState == PlayerState.Loaded;
+                CurrentState == PlayerState.Loaded ||
+                CurrentState == PlayerState.Loading ||
+                CurrentState == PlayerState.Contacting;
         }
 
         private void CheckPending ()
@@ -455,7 +478,7 @@
         }
     
         public TrackInfo CurrentTrack {
-            get { return active_engine.CurrentTrack; }
+            get { return active_engine.CurrentTrack ?? synthesized_contacting_track; }
         }
         
         private Dictionary<string, object> dbus_sucks;
@@ -481,7 +504,7 @@
         }
         
         public PlayerState CurrentState {
-            get { return active_engine.CurrentState; }
+            get { return synthesized_contacting_track != null ? PlayerState.Contacting : active_engine.CurrentState; }
         }
         
         string IPlayerEngineService.CurrentState {
@@ -531,11 +554,11 @@
                 uint length = active_engine.Length;
                 if (length > 0) {
                     return length;
-                } else if (active_engine.CurrentTrack == null) {
+                } else if (CurrentTrack == null) {
                     return 0;
                 }
                 
-                return (uint) active_engine.CurrentTrack.Duration.TotalSeconds;
+                return (uint) CurrentTrack.Duration.TotalSeconds;
             }
         }
     

Modified: branches/banshee/stable/src/Core/Banshee.Services/Banshee.Streaming/RadioTrackInfo.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.Services/Banshee.Streaming/RadioTrackInfo.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.Services/Banshee.Streaming/RadioTrackInfo.cs	Fri Jan 30 21:22:37 2009
@@ -37,6 +37,8 @@
 using Banshee.Base;
 using Banshee.Collection;
 using Banshee.ServiceStack;
+using Banshee.MediaEngine;
+using Banshee.PlaybackController;
 using Banshee.Playlists.Formats;
  
 namespace Banshee.Streaming
@@ -75,11 +77,13 @@
             try {
                 RadioTrackInfo radio_track = new RadioTrackInfo (uri);
                 radio_track.ParsingPlaylistEvent += delegate {
-                    if (radio_track.PlaybackError != StreamPlaybackError.None) {
-                        Log.Error (Catalog.GetString ("Error opening stream"), 
-                            Catalog.GetString ("Could not open stream or playlist"), true);
-                        radio_track = null;
-                    }
+                    ThreadAssist.ProxyToMain (delegate {
+                        if (radio_track.PlaybackError != StreamPlaybackError.None) {
+                            Log.Error (Catalog.GetString ("Error opening stream"), 
+                                Catalog.GetString ("Could not open stream or playlist"), true);
+                            radio_track = null;
+                        }
+                    });
                 };
                 
                 return radio_track;
@@ -98,6 +102,7 @@
         private int stream_index = 0;
         private bool loaded = false;
         private bool parsing_playlist = false;
+        private bool trying_to_play;
         
         private TrackInfo parent_track;
         public TrackInfo ParentTrack {
@@ -135,14 +140,67 @@
 
         public void Play()
         {
-            if(!loaded) {
-                OnParsingPlaylistStarted();
-                ThreadPool.QueueUserWorkItem(delegate {
-                    LoadStreamUris();
-                });
+            if (trying_to_play) {
                 return;
             }
-            
+
+            trying_to_play = true;
+
+            if (loaded) {
+                PlayCore ();
+            } else {
+                // Stop playing until we load this radio station and play it
+                ServiceManager.PlayerEngine.Close ();
+
+                ServiceManager.PlayerEngine.TrackIntercept += OnTrackIntercept;
+
+                // Tell the seek slider that we're connecting
+                // TODO move all this playlist-downloading/parsing logic into PlayerEngine?
+                ServiceManager.PlayerEngine.StartSynthesizeContacting (this);
+
+                OnParsingPlaylistStarted ();
+                ThreadPool.QueueUserWorkItem (delegate {
+                    try {
+                        LoadStreamUris ();
+                    } catch (Exception e) {
+                        trying_to_play = false;
+                        Log.Exception (this.ToString (), e);
+                        SavePlaybackError (StreamPlaybackError.Unknown);
+                        OnParsingPlaylistFinished ();
+                        ServiceManager.PlayerEngine.Close ();
+                    }
+                });
+            }
+        }
+
+        public override StreamPlaybackError PlaybackError {
+            get { return ParentTrack == null ? base.PlaybackError : ParentTrack.PlaybackError; }
+            set {
+                if (value != StreamPlaybackError.None) {
+                    ServiceManager.PlayerEngine.EndSynthesizeContacting (this, true);
+                }
+
+                if (ParentTrack == null) {
+                    base.PlaybackError = value;
+                } else {
+                    ParentTrack.PlaybackError = value;
+                }
+            }
+        }
+
+        public new void SavePlaybackError (StreamPlaybackError value)
+        {
+            PlaybackError = value;
+            Save ();
+            if (ParentTrack != null) {
+                ParentTrack.Save ();
+            }
+        }
+
+        private void PlayCore ()
+        {
+            ServiceManager.PlayerEngine.EndSynthesizeContacting (this, false);
+
             if(track != null) {
                 TrackTitle = track.Title;
                 ArtistName = track.Creator;
@@ -158,6 +216,8 @@
                     ServiceManager.PlayerEngine.OpenPlay(this);
                 }
             }
+
+            trying_to_play = false;
         }
         
         public bool PlayNextStream()
@@ -167,6 +227,7 @@
                 Play();
                 return true;
             }
+            ServiceManager.PlaybackController.StopWhenFinished = true;
             return false;
         }
 
@@ -177,9 +238,10 @@
                 Play();
                 return true;
             }
+            ServiceManager.PlaybackController.StopWhenFinished = true;
             return false;
         }
-        
+
         private void LoadStreamUris()
         {
             lock(stream_uris) {
@@ -193,19 +255,31 @@
                 
                 loaded = true;
             }
-            
-            ThreadAssist.ProxyToMain(delegate {
-                OnParsingPlaylistFinished();
-                Play();
-            });
+
+            ServiceManager.PlayerEngine.TrackIntercept -= OnTrackIntercept;
+            OnParsingPlaylistFinished();
+
+            if (ServiceManager.PlayerEngine.CurrentTrack == this) {
+                PlayCore();
+            } else {
+                trying_to_play = false;
+            }
+        }
+
+        private bool OnTrackIntercept (TrackInfo track)
+        {
+            if (track != this && track != ParentTrack) {
+                ServiceManager.PlayerEngine.EndSynthesizeContacting (this, false);
+                ServiceManager.PlayerEngine.TrackIntercept -= OnTrackIntercept;
+            }
+            return false;
         }
         
         private void LoadStreamUri(string uri)
         {
             try {
-                Log.Debug("Attempting to parse radio playlist", uri);
                 PlaylistParser parser = new PlaylistParser();
-                if(parser.Parse(new SafeUri(uri))) {
+                if (parser.Parse(new SafeUri(uri))) {
                     foreach(Dictionary<string, object> element in parser.Elements) {
                         if(element.ContainsKey("uri")) {
                             stream_uris.Add(new SafeUri(((Uri)element["uri"]).AbsoluteUri));
@@ -214,12 +288,14 @@
                 } else {
                     stream_uris.Add(new SafeUri(uri));
                 }
-            } catch(System.Net.WebException) {
-                SavePlaybackError (StreamPlaybackError.ResourceNotFound);
-            } catch(Exception e) {
-                Console.WriteLine(e);
+                Log.DebugFormat ("Parsed {0} URIs out of {1}", stream_uris.Count, this);
+            } catch (System.Net.WebException e) {
+                Hyena.Log.Exception (this.ToString (), e);
                 SavePlaybackError (StreamPlaybackError.ResourceNotFound);
-            }   
+            } catch (Exception e) {
+                Hyena.Log.Exception (this.ToString (), e);
+                SavePlaybackError (StreamPlaybackError.Unknown);
+            }
         }
         
         private void OnParsingPlaylistStarted()

Modified: branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedSeekSlider.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedSeekSlider.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/ConnectedSeekSlider.cs	Fri Jan 30 21:22:37 2009
@@ -128,33 +128,41 @@
                     OnPlayerEngineTick ();
                     break;
                 case PlayerEvent.StartOfStream:
-                    stream_position_label.IsBuffering = false;
-                    seek_slider.CanSeek = true;
+                    stream_position_label.StreamState = StreamLabelState.Playing;
+                    seek_slider.CanSeek = ServiceManager.PlayerEngine.CanSeek;
                     break;
                 case PlayerEvent.Buffering:
                     PlayerEventBufferingArgs buffering = (PlayerEventBufferingArgs)args;
                     if (buffering.Progress >= 1.0) {
-                        stream_position_label.IsBuffering = false;
+                        stream_position_label.StreamState = StreamLabelState.Playing;
                         break;
                     }
                     
-                    stream_position_label.IsBuffering = true;
+                    stream_position_label.StreamState = StreamLabelState.Buffering;
                     stream_position_label.BufferingProgress = buffering.Progress;
                     seek_slider.SetIdle ();
                     break;
                 case PlayerEvent.StateChange:
                     switch (((PlayerEventStateChangeArgs)args).Current) {
                         case PlayerState.Contacting:
-                            stream_position_label.IsContacting = true;
+                            transitioning = false;
+                            stream_position_label.StreamState = StreamLabelState.Contacting;
                             seek_slider.SetIdle ();
                             break;
+                        case PlayerState.Loading:
+                            transitioning = false;
+                            if (((PlayerEventStateChangeArgs)args).Previous == PlayerState.Contacting) {
+                                stream_position_label.StreamState = StreamLabelState.Loading;
+                                seek_slider.SetIdle ();
+                            }
+                            break;
                         case PlayerState.Idle:
                             seek_slider.CanSeek = false;
                             if (!transitioning) {
+                                stream_position_label.StreamState = StreamLabelState.Idle;
                                 seek_slider.Duration = 0;
                                 seek_slider.SeekValue = 0;
                                 seek_slider.SetIdle ();
-                                stream_position_label.IsContacting = false;
                             }
                             break;
                         default:
@@ -171,12 +179,13 @@
                 return;
             }
             
-            uint stream_length = ServiceManager.PlayerEngine.Length;
-            uint stream_position = ServiceManager.PlayerEngine.Position;
-            stream_position_label.IsContacting = false;
+            stream_position_label.StreamState = StreamLabelState.Playing;
+            Banshee.Collection.TrackInfo track = ServiceManager.PlayerEngine.CurrentTrack;
+            stream_position_label.IsLive = track == null ? false : track.IsLive;
+            stream_position_label.StreamState = StreamLabelState.Playing;
+            seek_slider.Duration = ServiceManager.PlayerEngine.Length;
+            seek_slider.SeekValue = ServiceManager.PlayerEngine.Position;
             seek_slider.CanSeek = ServiceManager.PlayerEngine.CanSeek;
-            seek_slider.Duration = stream_length;
-            seek_slider.SeekValue = stream_position;
         }
         
         private void OnSeekRequested (object o, EventArgs args)

Modified: branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackActions.cs	Fri Jan 30 21:22:37 2009
@@ -143,8 +143,10 @@
 
             switch (args.Current) {
                 case PlayerState.Contacting:
+                case PlayerState.Loading:
+                case PlayerState.Loaded:
                 case PlayerState.Playing:
-                    ShowPlayAction ();
+                    ShowStopAction ();
                     break;
                 case PlayerState.Paused:
                     ShowPlay ();
@@ -169,10 +171,13 @@
                 this["RestartSongAction"].Sensitive = false;
                 this["SeekToAction"].Sensitive = false;
             }
+
+            // Disable all actions while NotReady
+            Sensitive = args.Current != PlayerState.NotReady;
         }
         
-        private void ShowPlayAction ()
-        { 
+        private void ShowStopAction ()
+        {
             if (ServiceManager.PlayerEngine.CanPause) {
                 ShowPause ();
             } else {

Modified: branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/SeekSlider.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/SeekSlider.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/SeekSlider.cs	Fri Jan 30 21:22:37 2009
@@ -107,10 +107,12 @@
                 raise_seek_requested = false;
                 
                 if(value > Duration) {
-                    Duration = value;
+                    Duration = Int64.MaxValue;
+                    Value = value;
+                } else {
+                    Value = value;
                 }
-                
-                Value = value;
+
                 raise_seek_requested = true;
             }
         }

Modified: branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/StreamPositionLabel.cs
==============================================================================
--- branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/StreamPositionLabel.cs	(original)
+++ branches/banshee/stable/src/Core/Banshee.Widgets/Banshee.Widgets/StreamPositionLabel.cs	Fri Jan 30 21:22:37 2009
@@ -32,14 +32,22 @@
 
 namespace Banshee.Widgets
 {
+    public enum StreamLabelState {
+        Idle,
+        Contacting,
+        Loading,
+        Buffering,
+        Playing
+    }
+
     public class StreamPositionLabel : Alignment
     {
         private double buffering_progress;
-        private bool is_buffering;
-        private bool is_contacting;
+        private bool is_live;
         private SeekSlider seekRange;
         private string format_string = "<small>{0}</small>";
         private Pango.Layout layout;
+        private StreamLabelState state;
         
         public StreamPositionLabel (SeekSlider seekRange) : base (0.0f, 0.0f, 1.0f, 1.0f)
         {
@@ -101,7 +109,7 @@
             int bar_width = (int)((double)Allocation.Width * buffering_progress);
             bool render_bar = false;
             
-            if (bar_width > 0 && is_buffering) {
+            if (bar_width > 0 && IsBuffering) {
                 bar_width -= 2 * Style.XThickness;
                 render_bar = true;
                 
@@ -146,15 +154,20 @@
                 return;
             }
             
-            if (is_buffering) {
+            if (IsBuffering) {
                 double progress = buffering_progress * 100.0;
                 UpdateLabel (String.Format ("{0}: {1}%", Catalog.GetString("Buffering"), progress.ToString ("0.0")));
-            } else if (is_contacting) {
+            } else if (IsContacting) {
                 UpdateLabel (contacting);
-            } else if (seekRange.Value == 0 && seekRange.Duration == 0) {
+            } else if (IsLoading) {
+                // TODO replace w/ "Loading..." after string freeze
+                UpdateLabel (contacting);
+            } else if (IsIdle) {
                 UpdateLabel (idle);
-            } else if (seekRange.Value == seekRange.Duration) {
+            } else if (seekRange.Duration == Int64.MaxValue) {
                 UpdateLabel (FormatDuration ((long)seekRange.Value));
+            } else if (seekRange.Value == 0 && seekRange.Duration == 0) {
+                // nop
             } else {
                 UpdateLabel (String.Format (Catalog.GetString ("{0} of {1}"),
                     FormatDuration ((long)seekRange.Value), FormatDuration ((long)seekRange.Adjustment.Upper)));
@@ -193,22 +206,38 @@
             }
         }
         
+        public bool IsIdle {
+            get { return StreamState == StreamLabelState.Idle; }
+        }
+
         public bool IsBuffering {
-            get { return is_buffering; }
+            get { return StreamState == StreamLabelState.Buffering; }
+        }
+        
+        public bool IsContacting {
+            get { return StreamState == StreamLabelState.Contacting; }
+        }
+
+        public bool IsLoading {
+            get { return StreamState == StreamLabelState.Loading; }
+        }
+
+        public StreamLabelState StreamState {
+            get { return state; }
             set { 
-                if (is_buffering != value) {
-                    is_buffering = value;
+                if (state != value) {
+                    state = value;
                     UpdateLabel ();
                     QueueDraw ();
                 }
             }
         }
-        
-        public bool IsContacting {
-            get { return is_contacting; }
+
+        public bool IsLive {
+            get { return is_live; }
             set { 
-                if (is_contacting != value) {
-                    is_contacting = value;
+                if (is_live != value) {
+                    is_live = value;
                     UpdateLabel ();
                     QueueDraw ();
                 }

Modified: branches/banshee/stable/src/Libraries/Mtp/Mtp/File.cs
==============================================================================
--- branches/banshee/stable/src/Libraries/Mtp/Mtp/File.cs	(original)
+++ branches/banshee/stable/src/Libraries/Mtp/Mtp/File.cs	Fri Jan 30 21:22:37 2009
@@ -32,30 +32,26 @@
 
 namespace Mtp
 {
-
-        // File Management
 		[DllImport("libmtp.dll")]
 		private static extern IntPtr LIBMTP_new_file_t (); // LIBMTP_file_t *
+
 		[DllImport("libmtp.dll")]
 		private static extern void LIBMTP_destroy_file_t (ref File file); // LIBMTP_file_t *
+
 		[DllImport("libmtp.dll")]
 		private static extern string LIBMTP_Get_Filetype_Description (FileType type); // char const *
+
 		[DllImport("libmtp.dll")]
 		private static extern IntPtr LIBMTP_Get_Filelisting (MtpDeviceHandle handle); // LIBMTP_file_t *
+
 		[DllImport("libmtp.dll")]
 		private static extern IntPtr LIBMTP_Get_Filelisting_With_Callback (MtpDeviceHandle handle, ProgressFunction function, IntPtr data); // LIBMTP_file_t *
+
 		[DllImport("libmtp.dll")]
 		private static extern IntPtr LIBMTP_Get_Filemetadata (MtpDeviceHandle handle, uint fileid); // LIBMTP_file_t *
-		[DllImport("libmtp.dll")]
-		private static extern int LIBMTP_Get_File_To_File (MtpDeviceHandle handle, uint fileId, string path, ProgressFunction function, IntPtr data);
 
 		[DllImport("libmtp.dll")]
-		private static extern int LIBMTP_Send_File_From_File (MtpDeviceHandle handle, string path, ref File fileData, ProgressFunction function, IntPtr data, uint parentHandle);
-		//int LIBMTP_Get_File_To_File_Descriptor (MtpDeviceHandle handle, uint32_t const, int const, ProgressFunction function, void const *const)
-		//int 	LIBMTP_Send_File_From_File_Descriptor (MtpDeviceHandle handle, int const, LIBMTP_file_t *const, ProgressFunction function, void const *const, uint32_t const)
-
-		//[DllImport("libmtp.dll")]
-		//public static extern IntPtr LIBMTP_new_filesampledata_t (); // LIBMTP_filesampledata_t *
+		private static extern int LIBMTP_Get_File_To_File (MtpDeviceHandle handle, uint fileId, string path, ProgressFunction function, IntPtr data);
 
 		[DllImport("libmtp.dll")]
 		public static extern void LIBMTP_destroy_filesampledata_t (ref FileSampleData data); // LIBMTP_filesampledata_t *
@@ -71,6 +67,9 @@
 	{
 		public int item_id;
 		public int parent_id;
+#ifdef LIBMTP8
+		public int storage_id;
+#endif
 		[MarshalAs(UnmanagedType.LPStr)]public string filename;
 		public long filesize;
 		public FileType filetype;

Modified: branches/banshee/stable/src/Libraries/Mtp/Mtp/Playlist.cs
==============================================================================
--- branches/banshee/stable/src/Libraries/Mtp/Mtp/Playlist.cs	(original)
+++ branches/banshee/stable/src/Libraries/Mtp/Mtp/Playlist.cs	Fri Jan 30 21:22:37 2009
@@ -67,7 +67,12 @@
         protected override int Create ()
         {
             // TODO replace 0 w/ the folder id of the playlists folder?
+#if LIBMTP8
+            playlist.parent_id = Device.PlaylistFolder.FolderId;
+            return LIBMTP_Create_New_Playlist (Device.Handle, ref playlist);
+#else
             return LIBMTP_Create_New_Playlist (Device.Handle, ref playlist, Device.PlaylistFolder.FolderId);
+#endif
         }
 
         protected override int Update ()
@@ -81,29 +86,32 @@
         }
 
         // Playlist Management
-        [DllImport("libmtp.dll")]
-        internal static extern IntPtr LIBMTP_new_playlist_t (); // LIBMTP_playlist_t*
 
-        [DllImport("libmtp.dll")]
-        internal static extern void LIBMTP_destroy_playlist_t (ref PlaylistStruct playlist);
+        //[DllImport("libmtp.dll")]
+        //private static extern void LIBMTP_destroy_playlist_t (ref PlaylistStruct playlist);
 
         [DllImport("libmtp.dll")]
         internal static extern IntPtr LIBMTP_Get_Playlist_List (MtpDeviceHandle handle); // LIBMTP_playlist_t*
 
         [DllImport("libmtp.dll")]
-        internal static extern IntPtr LIBMTP_Get_Playlist (MtpDeviceHandle handle, uint playlistId); // LIBMTP_playlist_t*
-
-        [DllImport("libmtp.dll")]
-        internal static extern int LIBMTP_Create_New_Playlist (MtpDeviceHandle handle, ref PlaylistStruct metadata, uint parentHandle);
+#if LIBMTP8
+        private static extern int LIBMTP_Create_New_Playlist (MtpDeviceHandle handle, ref PlaylistStruct metadata);
+#else
+        private static extern int LIBMTP_Create_New_Playlist (MtpDeviceHandle handle, ref PlaylistStruct metadata, uint parentHandle);
+#endif
 
         [DllImport("libmtp.dll")]
-        internal static extern int LIBMTP_Update_Playlist (MtpDeviceHandle handle, ref PlaylistStruct playlist);
+        private static extern int LIBMTP_Update_Playlist (MtpDeviceHandle handle, ref PlaylistStruct playlist);
     }
 
 	[StructLayout(LayoutKind.Sequential)]
 	internal struct PlaylistStruct
 	{
 		public uint playlist_id;
+#if LIBMTP8
+		public uint parent_id;
+		public uint storage_id;
+#endif
 
 		[MarshalAs(UnmanagedType.LPStr)]
         public string Name;

Modified: branches/banshee/stable/src/Libraries/Mtp/Mtp/Track.cs
==============================================================================
--- branches/banshee/stable/src/Libraries/Mtp/Mtp/Track.cs	(original)
+++ branches/banshee/stable/src/Libraries/Mtp/Mtp/Track.cs	Fri Jan 30 21:22:37 2009
@@ -217,6 +217,7 @@
 		internal static void SendTrack (MtpDeviceHandle handle, string path, ref TrackStruct metadata, ProgressFunction callback, IntPtr data, uint parent)
 		{
 #if LIBMTP8
+            metadata.parent_id = parent;
 			if (LIBMTP_Send_Track_From_File (handle, path, ref metadata, callback, data) != 0)
 #else
 			if (LIBMTP_Send_Track_From_File (handle, path, ref metadata, callback, data, parent) != 0)



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