banshee r4474 - in trunk/banshee: . src/Core/Banshee.Services/Banshee.Sources src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp src/Dap/Banshee.Dap/Banshee.Dap src/Libraries/Mtp src/Libraries/Mtp/Mtp



Author: gburt
Date: Fri Sep  5 19:31:10 2008
New Revision: 4474
URL: http://svn.gnome.org/viewvc/banshee?rev=4474&view=rev

Log:
2008-09-05  Gabriel Burt  <gabriel burt gmail com>

	* src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs: Create a
	HyenaSqliteCommand to reuse for adding tracks to playlists - should be
	faster.

	* src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs: Load and save
	playlists on MTP devices.

	* src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs: Save the
	Mtp.Track's ID in the ExternalID column, cleanup cruft.

	* src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs: Don't add empty
	playlists to devices.

	* src/Core/Banshee.Services/Banshee.Sources/SourceManager.cs: Fix
	gui-thread issue.

	* src/Libraries/Mtp/Mtp/Folder.cs: Override ToString for debugging.

	* src/Libraries/Mtp/Mtp/Album.cs: Factor a lot of code that's useful for
	the Playlist class into AbstractTrackList, subclass from it.

	* src/Libraries/Mtp/Makefile.am:
	* src/Libraries/Mtp/Mtp/AbstractTrackList.cs: Factored out code from Album

	* src/Libraries/Mtp/Mtp/MtpDevice.cs: Add GetPlaylists () method.

	* src/Libraries/Mtp/Mtp/Playlist.cs: Subclass from AbstractTrackList,
	implement required methods, add to build.



Added:
   trunk/banshee/src/Libraries/Mtp/Mtp/AbstractTrackList.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceManager.cs
   trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
   trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs
   trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
   trunk/banshee/src/Libraries/Mtp/Makefile.am
   trunk/banshee/src/Libraries/Mtp/Mtp/Album.cs
   trunk/banshee/src/Libraries/Mtp/Mtp/Folder.cs
   trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs
   trunk/banshee/src/Libraries/Mtp/Mtp/Playlist.cs

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceManager.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceManager.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/SourceManager.cs	Fri Sep  5 19:31:10 2008
@@ -185,7 +185,6 @@
 
         public void RemoveSource (Source source, bool recursivelyDispose)
         {
-            Banshee.Base.ThreadAssist.AssertInMainThread ();
             if(source == null || !ContainsSource (source)) {
                 return;
             }
@@ -211,16 +210,18 @@
                 }
             }
 
-            if(source == active_source) {
-                SetActiveSource(default_source);
-            }
-                
-            SourceEventHandler handler = SourceRemoved;
-            if(handler != null) {
-                SourceEventArgs args = new SourceEventArgs();
-                args.Source = source;
-                handler(args);
-            }
+            Banshee.Base.ThreadAssist.ProxyToMain (delegate {
+                if(source == active_source) {
+                    SetActiveSource(default_source);
+                }
+
+                SourceEventHandler handler = SourceRemoved;
+                if(handler != null) {
+                    SourceEventArgs args = new SourceEventArgs();
+                    args.Source = source;
+                    handler(args);
+                }
+            });
         }
         
         public void RemoveSource(Type type)

Modified: trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Ipod/Banshee.Dap.Ipod/IpodSource.cs	Fri Sep  5 19:31:10 2008
@@ -211,8 +211,9 @@
                     }
                 }
 
-                string insert_sql = @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID)
-                        SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND ExternalID = ?";
+                Hyena.Data.Sqlite.HyenaSqliteCommand insert_cmd = new Hyena.Data.Sqlite.HyenaSqliteCommand (
+                    @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID)
+                        SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND ExternalID = ?");
                 foreach (IPod.Playlist playlist in ipod_device.TrackDatabase.Playlists) {
                     if (playlist.IsOnTheGo) { // || playlist.IsPodcast) {
                         Console.WriteLine ("have playlist {0} with {1} items but ignoring b/c otg or podcast", playlist.Name, playlist.Tracks.Count);
@@ -223,7 +224,7 @@
                     // We use the IPod.Track.Id here b/c we just shoved it into ExternalID above when we loaded
                     // the tracks, however when we sync, the Track.Id values may/will change.
                     foreach (IPod.Track track in playlist.Tracks) {
-                        ServiceManager.DbConnection.Execute (insert_sql, pl_src.DbId, this.DbId, track.Id);
+                        ServiceManager.DbConnection.Execute (insert_cmd, pl_src.DbId, this.DbId, track.Id);
                     }
                     pl_src.UpdateCounts ();
                     AddChildSource (pl_src);

Modified: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpSource.cs	Fri Sep  5 19:31:10 2008
@@ -34,12 +34,14 @@
 using Hyena;
 using Hyena.Collections;
 using Mtp;
+using MTP = Mtp;
 
 using Banshee.Base;
 using Banshee.Dap;
 using Banshee.ServiceStack;
 using Banshee.Library;
 using Banshee.Sources;
+using Banshee.Playlist;
 using Banshee.Configuration;
 using Banshee.Collection;
 using Banshee.Collection.Database;
@@ -172,6 +174,21 @@
                         track_map[track.TrackId] = mtp_track;
                     }
                 }
+
+                Hyena.Data.Sqlite.HyenaSqliteCommand insert_cmd = new Hyena.Data.Sqlite.HyenaSqliteCommand (
+                    @"INSERT INTO CorePlaylistEntries (PlaylistID, TrackID)
+                        SELECT ?, TrackID FROM CoreTracks WHERE PrimarySourceID = ? AND ExternalID = ?");
+                foreach (MTP.Playlist playlist in mtp_device.GetPlaylists ()) {
+                    PlaylistSource pl_src = new PlaylistSource (playlist.Name, this.DbId);
+                    pl_src.Save ();
+                    // TODO a transaction would make sense here (when the threading issue is fixed)
+                    foreach (int id in playlist.TrackIds) {
+                        ServiceManager.DbConnection.Execute (insert_cmd, pl_src.DbId, this.DbId, id);
+                    }
+                    pl_src.UpdateCounts ();
+                    AddChildSource (pl_src);
+                }
+
             } catch (Exception e) {
                 Log.Exception (e);
             }
@@ -195,6 +212,33 @@
             }
         }
 
+        public override void SyncPlaylists ()
+        {
+            lock (mtp_device) {
+                List<MTP.Playlist> device_playlists = new List<MTP.Playlist> (mtp_device.GetPlaylists ());
+                foreach (MTP.Playlist playlist in device_playlists) {
+                    playlist.Remove ();
+                }
+                device_playlists.Clear ();
+    
+                // Add playlists from Banshee to the device
+                foreach (Source child in Children) {
+                    PlaylistSource from = child as PlaylistSource;
+                    if (from != null && from.Count > 0) {
+                        MTP.Playlist playlist = new MTP.Playlist (mtp_device, from.Name);
+                        foreach (int track_id in ServiceManager.DbConnection.QueryEnumerable<int> (String.Format (
+                            "SELECT CoreTracks.ExternalID FROM CoreTracks{0} WHERE {1}",
+                            from.DatabaseTrackModel.JoinFragment, from.DatabaseTrackModel.Condition)))
+                        {
+                            playlist.AddTrack (track_id);
+                        }
+                        playlist.Save ();
+                    }
+                }
+            }
+        }
+
+
         public override bool CanRename {
             get { return !(IsAdding || IsDeleting); }
         }
@@ -229,25 +273,25 @@
 
         public override long BytesUsed {
             get {
-				long count = 0;
+                long count = 0;
                 lock (mtp_device) {
                     foreach (DeviceStorage s in mtp_device.GetStorage ()) {
                         count += (long) s.MaxCapacity - (long) s.FreeSpaceInBytes;
                     }
                 }
-				return count;
+                return count;
             }
         }
         
         public override long BytesCapacity {
             get {
-				long count = 0;
+                long count = 0;
                 lock (mtp_device) {
                     foreach (DeviceStorage s in mtp_device.GetStorage ()) {
                         count += (long) s.MaxCapacity;
                     }
                 }
-				return count;
+                return count;
             }
         }
 
@@ -262,7 +306,6 @@
 
             Track mtp_track = TrackInfoToMtpTrack (track, fromUri);
             bool video = (track.MediaAttributes & TrackMediaAttributes.VideoStream) != 0;
-            Console.WriteLine ("Sending file {0}, is video? {1}", fromUri.LocalPath, video);
             lock (mtp_device) {
                 mtp_device.UploadTrack (fromUri.LocalPath, mtp_track, GetFolderForTrack (track), OnUploadProgress);
             }
@@ -302,12 +345,13 @@
 
         private Folder GetFolderForTrack (TrackInfo track)
         {
-            if (track.HasAttribute (TrackMediaAttributes.Podcast))
+            if (track.HasAttribute (TrackMediaAttributes.Podcast)) {
                 return mtp_device.PodcastFolder;
-            else if (track.HasAttribute (TrackMediaAttributes.VideoStream))
+            } else if (track.HasAttribute (TrackMediaAttributes.VideoStream)) {
                 return mtp_device.VideoFolder;
-            else
+            } else {
                 return mtp_device.MusicFolder;
+            }
         }
 
         private int OnUploadProgress (ulong sent, ulong total, IntPtr data)
@@ -330,7 +374,7 @@
                 if (album_cache.ContainsKey (key)) {
                     Album album = album_cache[key];
                     album.RemoveTrack (mtp_track);
-                    if (album.TrackCount == 0) {
+                    if (album.Count == 0) {
                         album.Remove ();
                         album_cache.Remove (key);
                     }
@@ -356,7 +400,6 @@
             }
 
             ServiceManager.SourceManager.RemoveSource (this);
-
             mtp_device = null;
             mtp_source = null;
         }

Modified: trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap.Mtp/Banshee.Dap.Mtp/MtpTrackInfo.cs	Fri Sep  5 19:31:10 2008
@@ -53,18 +53,20 @@
         }
         
         public MtpTrackInfo (MtpDevice device, Track file) : base()
-		{
+        {
             this.file = file;
-			
-			AlbumTitle = file.Album;
+            ExternalId = file.FileId;
+            
+            AlbumTitle = file.Album;
             ArtistName = file.Artist;
             Duration = TimeSpan.FromMilliseconds (file.Duration);
             Genre = file.Genre;
             PlayCount = file.UseCount < 0 ? 0 : (int) file.UseCount;
-            rating = file.Rating < 0 ? 0 : (file.Rating / 20);
+            Rating = file.Rating < 0 ? 0 : (file.Rating / 20);
             TrackTitle = file.Title;
             TrackNumber = file.TrackNumber < 0 ? 0 : (int)file.TrackNumber;
             Year = file.Year;
+            BitRate = (int)file.Bitrate;
             FileSize = (long)file.FileSize;
 
             MediaAttributes = TrackMediaAttributes.AudioStream;
@@ -73,67 +75,35 @@
                 SetAttributeIf (file.InFolder (device.MusicFolder), TrackMediaAttributes.Music);
                 SetAttributeIf (file.InFolder (device.VideoFolder), TrackMediaAttributes.VideoStream);
             }
-            // TODO set VideoStream for video podcast episodes
-            /*Profile profile = ServiceManager.Get<MediaProfileManager> ().GetProfileForExtension (System.IO.Path.GetExtension (file.FileName));
-            if (profile != null) {
-                profile.
-            }*/
-
+            
             // This can be implemented if there's enough people requesting it
             CanPlay = false;
             CanSaveToDatabase = true;
             //NeedSync = false;
 
             // TODO detect if this is a video file and set the MediaAttributes appropriately?
+            /*Profile profile = ServiceManager.Get<MediaProfileManager> ().GetProfileForExtension (System.IO.Path.GetExtension (file.FileName));
+            if (profile != null) {
+                profile.
+            }*/
 
-			// Set a URI even though it's not actually accessible through normal API's.
-			Uri = new SafeUri (GetPathFromMtpTrack (file));
+            // Set a URI even though it's not actually accessible through normal API's.
+            Uri = new SafeUri (GetPathFromMtpTrack (file));
         }
 
         internal static void ToMtpTrack (TrackInfo track, Track f)
         {
-			f.Album = track.AlbumTitle;
-			f.Artist = track.ArtistName;
-			f.Duration = (uint)track.Duration.TotalMilliseconds;
-			f.Genre = track.Genre;
-			f.Rating = (ushort)(track.Rating * 20);
-			f.Title = track.TrackTitle;
-			f.TrackNumber = (ushort)track.TrackNumber;
-			f.UseCount = (uint)track.PlayCount;
+            f.Album = track.AlbumTitle;
+            f.Artist = track.ArtistName;
+            f.Duration = (uint)track.Duration.TotalMilliseconds;
+            f.Genre = track.Genre;
+            f.Rating = (ushort)(track.Rating * 20);
+            f.Title = track.TrackTitle;
+            f.TrackNumber = (ushort)track.TrackNumber;
+            f.UseCount = (uint)track.PlayCount;
             f.Year = track.Year;
-		}
-        
-        /*public override bool Equals (object o)
-        {
-            MtpDapTrackInfo dapInfo = o as MtpDapTrackInfo;
-            return dapInfo == null ? false : Equals(dapInfo);
-        }
-        
-        // FIXME: Is this enough? Does it matter if i just match metadata?
-        public bool Equals(MtpDapTrackInfo info)
-        {
-			return this.file.Equals(info.file);
-            return info == null ? false
-             : this.album == info.album
-             && this.artist == info.artist
-             && this.title == info.title
-             && this.track_number == info.track_number;
+            //f.Bitrate = (uint)track.BitRate;
+            f.FileSize = (ulong)track.FileSize;
         }
-        
-        public override int GetHashCode ()
-        {
-            int result = 0;
-            result ^= (int)track_number;
-            if(album != null) result ^= album.GetHashCode();
-            if(artist != null) result ^= artist.GetHashCode();
-            if(title != null) result ^= title.GetHashCode();
-            
-            return result;
-        }*/
-        
-		/*protected override void WriteUpdate ()
-		{
-			OnChanged();
-		}*/
     }
 }

Modified: trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs
==============================================================================
--- trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs	(original)
+++ trunk/banshee/src/Dap/Banshee.Dap/Banshee.Dap/DapLibrarySync.cs	Fri Sep  5 19:31:10 2008
@@ -211,6 +211,9 @@
                     // as normal playlists
                     IList<AbstractPlaylistSource> playlists = GetSyncPlaylists ();
                     foreach (AbstractPlaylistSource from in playlists) {
+                        if (from.Count == 0) {
+                            continue;
+                        }
                         PlaylistSource to = new PlaylistSource (from.Name, sync.Dap.DbId);
                         to.Save ();
 
@@ -222,7 +225,7 @@
                                 from.DatabaseTrackModel.JoinFragment, from.DatabaseTrackModel.Condition),
                             to.DbId, sync.Dap.DbId
                         );
-                        to.DatabaseTrackModel.UpdateUnfilteredAggregates ();
+                        to.UpdateCounts ();
                         sync.Dap.AddChildSource (to);
                     }
                 }

Modified: trunk/banshee/src/Libraries/Mtp/Makefile.am
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Makefile.am	(original)
+++ trunk/banshee/src/Libraries/Mtp/Makefile.am	Fri Sep  5 19:31:10 2008
@@ -3,6 +3,7 @@
 LINK = $(REF_MTP)
 
 SOURCES =  \
+	Mtp/AbstractTrackList.cs \
 	Mtp/Album.cs \
 	Mtp/Error.cs \
 	Mtp/ErrorCode.cs \
@@ -10,6 +11,7 @@
 	Mtp/FileType.cs \
 	Mtp/Folder.cs \
 	Mtp/MtpDevice.cs \
+	Mtp/Playlist.cs \
 	Mtp/Track.cs
 
 if ENABLE_MTP

Added: trunk/banshee/src/Libraries/Mtp/Mtp/AbstractTrackList.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/AbstractTrackList.cs	Fri Sep  5 19:31:10 2008
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace Mtp
+{
+    public abstract class AbstractTrackList
+    {
+        private bool saved;
+        private List<int> track_ids;
+		private MtpDevice device;
+
+        public abstract uint Count { get; protected set; }
+        public abstract string Name { get; set; }
+        protected abstract IntPtr TracksPtr { get; set; }
+
+        protected abstract int Create ();
+        protected abstract int Update ();
+
+        public bool Saved { get { return saved; } }
+        protected MtpDevice Device { get { return device; } }
+
+        public IList<int> TrackIds {
+            get { return track_ids; }
+        }
+
+        public AbstractTrackList (MtpDevice device, string name)
+        {
+            this.device = device;
+            track_ids = new List<int> ();
+        }
+
+        internal AbstractTrackList (MtpDevice device, IntPtr tracks, uint count)
+        {
+            this.device = device;
+            this.saved = true;
+
+            if (tracks != IntPtr.Zero) {
+                int [] vals = new int [count];
+                Marshal.Copy ((IntPtr)tracks, (int[])vals, 0, (int)count);
+                track_ids = new List<int> (vals);
+            } else {
+                track_ids = new List<int> ();
+            }
+        }
+
+        public void AddTrack (Track track)
+        {
+            AddTrack ((int)track.FileId);
+        }
+
+        public void AddTrack (int track_id)
+        {
+            track_ids.Add (track_id);
+            Count++;
+        }
+
+        public void RemoveTrack (Track track)
+        {
+            RemoveTrack ((int)track.FileId);
+        }
+        
+        public void RemoveTrack (int track_id)
+        {
+            track_ids.Remove (track_id);
+            Count--;
+        }
+
+        public void ClearTracks ()
+        {
+            track_ids.Clear ();
+            Count = 0;
+        }
+
+        public virtual void Save ()
+        {
+            Count = (uint) track_ids.Count;
+            Console.WriteLine ("saving {0} {1} with {2} tracks", this.GetType(), this.Name, this.Count);
+
+            if (TracksPtr != IntPtr.Zero) {
+                Marshal.FreeHGlobal (TracksPtr);
+                TracksPtr = IntPtr.Zero;
+            }
+
+            if (Count == 0) {
+                TracksPtr = IntPtr.Zero;
+            } else {
+                TracksPtr = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (int)) * (int)Count);
+                Marshal.Copy (track_ids.ToArray (), 0, TracksPtr, (int)Count);
+            }
+
+            if (saved) {
+                saved = Update () == 0;
+            } else {
+                saved = Create () == 0;
+            }
+
+            if (TracksPtr != IntPtr.Zero) {
+                Marshal.FreeHGlobal (TracksPtr);
+                TracksPtr = IntPtr.Zero;
+            }
+        }
+    }
+}

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/Album.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/Album.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/Album.cs	Fri Sep  5 19:31:10 2008
@@ -33,26 +33,15 @@
 
 namespace Mtp
 {
-	public class Album
+	public class Album : AbstractTrackList
 	{
 		private AlbumStruct album;
-		private MtpDevice device;
-        private bool saved;
-        private List<int> track_ids;
 
         public uint AlbumId {
-            get { return saved ? album.album_id : 0; }
+            get { return Saved ? album.album_id : 0; }
         }
 
-        public List<int> TrackIds {
-            get { return track_ids; }
-        }
-
-        public bool Saved {
-            get { return saved; }
-        }
-
-        public string Name {
+        public override string Name {
             get { return album.name; }
             set {
                 album.name = value;
@@ -73,119 +62,79 @@
             }
         }
 
-        public uint TrackCount {
+        public override uint Count {
             get { return album.no_tracks; }
-            set {
+            protected set {
                 album.no_tracks = value;
             }
         }
 
-        public Album (MtpDevice device, string name, string artist, string genre)
+        protected override IntPtr TracksPtr {
+            get { return album.tracks; }
+            set { album.tracks = value; }
+        }
+
+        public Album (MtpDevice device, string name, string artist, string genre) : base (device, name)
         {
-            this.device = device;
             this.album = new AlbumStruct ();
-            this.album.tracks = IntPtr.Zero;
+            TracksPtr = IntPtr.Zero;
             Name = name;
             Artist = artist;
             Genre = genre;
-            TrackCount = 0;
-            track_ids = new List<int> ();
+            Count = 0;
         }
 
-        internal Album (MtpDevice device, AlbumStruct album)
+        internal Album (MtpDevice device, AlbumStruct album) : base (device, album.tracks, album.no_tracks)
         {
-            this.device = device;
             this.album = album;
-            this.saved = true;
-
-            if (album.tracks != IntPtr.Zero) {
-                int [] vals = new int [TrackCount];
-                Marshal.Copy ((IntPtr)album.tracks, (int[])vals, 0, (int)TrackCount);
-                track_ids = new List<int> (vals);
-            } else {
-                track_ids = new List<int> ();
-            }
         }
-        
-        public void Save ()
+
+        public override void Save ()
         {
             Save (null, 0, 0);
         }
 
         public void Save (byte [] cover_art, uint width, uint height)
         {
-            TrackCount = (uint) track_ids.Count;
-
-            if (album.tracks != IntPtr.Zero) {
-                Marshal.FreeHGlobal (album.tracks);
-                album.tracks = IntPtr.Zero;
-            }
-
-            if (TrackCount == 0) {
-                album.tracks = IntPtr.Zero;
-            } else {
-                album.tracks = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (int)) * (int)TrackCount);
-                Marshal.Copy (track_ids.ToArray (), 0, album.tracks, (int)TrackCount);
-            }
-
-            if (saved) {
-                saved = LIBMTP_Update_Album (device.Handle, ref album) == 0;
-            } else {
-                saved = LIBMTP_Create_New_Album (device.Handle, ref album, 0) == 0;
-            }
-
-            if (album.tracks != IntPtr.Zero) {
-                Marshal.FreeHGlobal (album.tracks);
-                album.tracks = IntPtr.Zero;
-            }
-
-            if (!saved)
-                return;
+            base.Save ();
+            if (Saved) {
+                if (cover_art == null) {
+                    return;
+                }
+                
+                FileSampleData cover = new FileSampleData ();
+                cover.data = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (byte)) * cover_art.Length);
+                Marshal.Copy (cover_art, 0, cover.data, cover_art.Length);
+                cover.size = (ulong)cover_art.Length;
+                cover.width = width;
+                cover.height = height;
+                cover.filetype = FileType.JPEG;
 
-            if (cover_art == null) {
-                return;
+                if (FileSample.LIBMTP_Send_Representative_Sample (Device.Handle, AlbumId, ref cover) != 0) {
+                    //Console.WriteLine ("failed to send representative sample file");
+                }
+                Marshal.FreeHGlobal (cover.data);
             }
-            
-            FileSampleData cover = new FileSampleData ();
-            cover.data = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (byte)) * cover_art.Length);
-            Marshal.Copy (cover_art, 0, cover.data, cover_art.Length);
-            cover.size = (ulong)cover_art.Length;
-            cover.width = width;
-            cover.height = height;
-            cover.filetype = FileType.JPEG;
-
-            if (FileSample.LIBMTP_Send_Representative_Sample (device.Handle, AlbumId, ref cover) != 0) {
-                //Console.WriteLine ("failed to send representative sample file");
-            }
-            Marshal.FreeHGlobal (cover.data);
         }
 
-        public void AddTrack (Track track)
+        protected override int Create ()
         {
-            track_ids.Add ((int)track.FileId);
-            TrackCount++;
+            return LIBMTP_Create_New_Album (Device.Handle, ref album, 0);
         }
 
-        public void RemoveTrack (Track track)
+        protected override int Update ()
         {
-            track_ids.Remove ((int)track.FileId);
-            TrackCount--;
+            return LIBMTP_Update_Album (Device.Handle, ref album);
         }
-
-        public void ClearTracks ()
-        {
-            track_ids.Clear ();
-            TrackCount = 0;
-        }
-
+        
         public void Remove ()
         {
-			MtpDevice.LIBMTP_Delete_Object(device.Handle, AlbumId);
+			MtpDevice.LIBMTP_Delete_Object(Device.Handle, AlbumId);
         }
 
         public override string ToString ()
         {
-            return String.Format ("Album < Id: {4}, '{0}' by '{1}', genre '{2}', tracks {3} >", Name, Artist, Genre, TrackCount, AlbumId);
+            return String.Format ("Album < Id: {4}, '{0}' by '{1}', genre '{2}', tracks {3} >", Name, Artist, Genre, Count, AlbumId);
         }
 
         public static Album GetById (MtpDevice device, uint id)

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/Folder.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/Folder.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/Folder.cs	Fri Sep  5 19:31:10 2008
@@ -112,6 +112,11 @@
 		{
 			MtpDevice.DeleteObject(device.Handle, FolderId);
 		}
+
+        public override string ToString ()
+        {
+            return String.Format ("{0} (id {1}, parent id {2})", Name, FolderId, ParentId);
+        }
 		
 		internal static List<Folder> GetRootFolders (MtpDevice device)
 		{

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/MtpDevice.cs	Fri Sep  5 19:31:10 2008
@@ -175,26 +175,38 @@
 
 			List<Track> tracks = new List<Track>();
 			
-			while (ptr != IntPtr.Zero)
-			{
+			while (ptr != IntPtr.Zero) {
 				TrackStruct track = (TrackStruct)Marshal.PtrToStructure(ptr, typeof(TrackStruct));
 				Track.DestroyTrack (ptr);
-				tracks.Add(new Track(track, this));
+				tracks.Add (new Track (track, this));
 				ptr = track.next;
 			}
 			
 			return tracks;
 		}
 
+        public List<Playlist> GetPlaylists ()
+        {
+            List<Playlist> playlists = new List<Playlist> ();
+
+			IntPtr ptr = Playlist.LIBMTP_Get_Playlist_List (Handle);
+			while (ptr != IntPtr.Zero) {
+				PlaylistStruct d = (PlaylistStruct)Marshal.PtrToStructure(ptr, typeof(PlaylistStruct));
+				playlists.Add (new Playlist (this, d));
+				ptr = d.next;
+			}
+			
+            return playlists;
+        }
+
         public List<Album> GetAlbums ()
         {
             List<Album> albums = new List<Album> ();
 
 			IntPtr ptr = Album.LIBMTP_Get_Album_List (Handle);
-			while (ptr != IntPtr.Zero)
-			{
+			while (ptr != IntPtr.Zero) {
 				AlbumStruct d = (AlbumStruct)Marshal.PtrToStructure(ptr, typeof(AlbumStruct));
-				albums.Add (new Album(this, d));
+				albums.Add (new Album (this, d));
 				ptr = d.next;
 			}
 			
@@ -205,10 +217,9 @@
 		{
 			List<DeviceStorage> storages = new List<DeviceStorage>();
 			IntPtr ptr = device.storage;
-			while (ptr != IntPtr.Zero)
-			{
+			while (ptr != IntPtr.Zero) {
 				DeviceStorage storage = (DeviceStorage)Marshal.PtrToStructure(ptr, typeof(DeviceStorage));
-				storages.Add(storage);
+				storages.Add (storage);
 				ptr = storage.Next;
 			}
 			return storages;

Modified: trunk/banshee/src/Libraries/Mtp/Mtp/Playlist.cs
==============================================================================
--- trunk/banshee/src/Libraries/Mtp/Mtp/Playlist.cs	(original)
+++ trunk/banshee/src/Libraries/Mtp/Mtp/Playlist.cs	Fri Sep  5 19:31:10 2008
@@ -32,36 +32,88 @@
 
 namespace Mtp
 {
+    public sealed class Playlist : AbstractTrackList
+    {
+        private PlaylistStruct playlist;
+
+        public override uint Count {
+            get { return playlist.no_tracks; }
+            protected set { playlist.no_tracks = value; }
+        }
+
+        public override string Name {
+            get { return playlist.Name; }
+            set { playlist.Name = value; }
+        }
+
+        protected override IntPtr TracksPtr {
+            get { return playlist.tracks; }
+            set { playlist.tracks = value; }
+        }
+
+        public Playlist (MtpDevice device, string name) : base (device, name)
+        {
+            this.playlist = new PlaylistStruct ();
+            TracksPtr = IntPtr.Zero;
+            Name = name;
+            Count = 0;
+        }
+
+        internal Playlist (MtpDevice device, PlaylistStruct playlist) : base (device, playlist.tracks, playlist.no_tracks)
+        {
+            this.playlist = playlist;
+        }
+
+        protected override int Create ()
+        {
+            // TODO replace 0 w/ the folder id of the playlists folder?
+            return LIBMTP_Create_New_Playlist (Device.Handle, ref playlist, Device.PlaylistFolder.FolderId);
+        }
+
+        protected override int Update ()
+        {
+            return LIBMTP_Update_Playlist (Device.Handle, ref playlist);
+        }
+
+        public void Remove ()
+        {
+            MtpDevice.LIBMTP_Delete_Object(Device.Handle, playlist.playlist_id);
+        }
+
         // Playlist Management
         [DllImport("libmtp.dll")]
-		private static extern IntPtr LIBMTP_new_playlist_t (); // LIBMTP_playlist_t*
+        internal static extern IntPtr LIBMTP_new_playlist_t (); // LIBMTP_playlist_t*
 
-		[DllImport("libmtp.dll")]
-		private static extern void LIBMTP_destroy_playlist_t (ref Playlist playlist);
+        [DllImport("libmtp.dll")]
+        internal static extern void LIBMTP_destroy_playlist_t (ref PlaylistStruct playlist);
 
-		[DllImport("libmtp.dll")]
-		private static extern IntPtr LIBMTP_Get_Playlist_List (MtpDeviceHandle handle); // LIBMTP_playlist_t*
+        [DllImport("libmtp.dll")]
+        internal static extern IntPtr LIBMTP_Get_Playlist_List (MtpDeviceHandle handle); // LIBMTP_playlist_t*
 
-		[DllImport("libmtp.dll")]
-		private static extern IntPtr LIBMTP_Get_Playlist (MtpDeviceHandle handle, uint playlistId); // LIBMTP_playlist_t*
+        [DllImport("libmtp.dll")]
+        internal static extern IntPtr LIBMTP_Get_Playlist (MtpDeviceHandle handle, uint playlistId); // LIBMTP_playlist_t*
 
-		[DllImport("libmtp.dll")]
-		private static extern int LIBMTP_Create_New_Playlist (MtpDeviceHandle handle, ref Playlist metadata, uint parentHandle);
+        [DllImport("libmtp.dll")]
+        internal static extern int LIBMTP_Create_New_Playlist (MtpDeviceHandle handle, ref PlaylistStruct metadata, uint parentHandle);
 
-		[DllImport("libmtp.dll")]
-		private static extern int LIBMTP_Update_Playlist (MtpDeviceHandle handle, ref Playlist playlist);
+        [DllImport("libmtp.dll")]
+        internal static extern int LIBMTP_Update_Playlist (MtpDeviceHandle handle, ref PlaylistStruct playlist);
+    }
 
 	[StructLayout(LayoutKind.Sequential)]
-	internal struct Playlist
+	internal struct PlaylistStruct
 	{
-		int playlist_id;
-		[MarshalAs(UnmanagedType.LPStr)] string name;
-		IntPtr tracks; // int*
-		int no_tracks;
-		IntPtr next;   // LIBMTP_playlist_t*
+		public uint playlist_id;
+
+		[MarshalAs(UnmanagedType.LPStr)]
+        public string Name;
+
+		public IntPtr tracks; // int*
+		public uint no_tracks;
+		public IntPtr next;   // LIBMTP_playlist_t*
 		
 		
-		public Playlist? Next
+		/*public Playlist? Next
 		{
 			get
 			{
@@ -69,6 +121,6 @@
 					return null;
 				return (Playlist)Marshal.PtrToStructure(next, typeof(Playlist));
 			}
-		}
+		}*/
 	}
 }



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