Author: jwilcox
Date: 2006-06-16 20:05:19 -0400 (Fri, 16 Jun 2006)
New Revision: 61817

Added:
   trunk/ipod-sharp/src/ObjectDumper.cs
Modified:
   trunk/ipod-sharp/ChangeLog
   trunk/ipod-sharp/src/Device.cs
   trunk/ipod-sharp/src/Makefile.am
   trunk/ipod-sharp/src/PhotoDatabase.cs
   trunk/ipod-sharp/src/TrackDatabase.cs
Log:
2006-06-16  James Willcox  <[EMAIL PROTECTED]>

        * src/PhotoDatabase.cs: more write fixes.  It can now read/write the
        art and photo database without corruption.



Modified: trunk/ipod-sharp/ChangeLog
===================================================================
--- trunk/ipod-sharp/ChangeLog  2006-06-16 22:14:53 UTC (rev 61816)
+++ trunk/ipod-sharp/ChangeLog  2006-06-17 00:05:19 UTC (rev 61817)
@@ -1,5 +1,10 @@
 2006-06-16  James Willcox  <[EMAIL PROTECTED]>
 
+       * src/PhotoDatabase.cs: more write fixes.  It can now read/write the
+       art and photo database without corruption.
+
+2006-06-16  James Willcox  <[EMAIL PROTECTED]>
+
        * fix the test cases
 
 2006-06-16  James Willcox  <[EMAIL PROTECTED]>

Modified: trunk/ipod-sharp/src/Device.cs
===================================================================
--- trunk/ipod-sharp/src/Device.cs      2006-06-16 22:14:53 UTC (rev 61816)
+++ trunk/ipod-sharp/src/Device.cs      2006-06-17 00:05:19 UTC (rev 61817)
@@ -294,6 +294,11 @@
             }
         }
 
+        internal bool IsBE {
+            get { return ControlPath.EndsWith ("iTunes_Control"); }
+        }
+
+
         public static new GLib.GType GType { 
             get {
                 IntPtr raw_ret = ipod_device_get_type();
@@ -323,7 +328,7 @@
             //FIXME: refuse if the device lacks photo capability
 
             if (photos == null)
-                photos = new PhotoDatabase (this, createFresh);
+                photos = new PhotoDatabase (this, true, createFresh);
         }
         
         public void LoadTrackDatabase () {

Modified: trunk/ipod-sharp/src/Makefile.am
===================================================================
--- trunk/ipod-sharp/src/Makefile.am    2006-06-16 22:14:53 UTC (rev 61816)
+++ trunk/ipod-sharp/src/Makefile.am    2006-06-17 00:05:19 UTC (rev 61817)
@@ -29,6 +29,7 @@
        $(srcdir)/Initializer.cs        \
        $(srcdir)/PhotoDatabase.cs              \
        $(srcdir)/Playlist.cs           \
+       $(srcdir)/ObjectDumper.cs               \
        $(srcdir)/Thumbnail.cs          \
        $(srcdir)/Track.cs              \
        $(srcdir)/TrackDatabase.cs \

Added: trunk/ipod-sharp/src/ObjectDumper.cs
===================================================================
--- trunk/ipod-sharp/src/ObjectDumper.cs        2006-06-16 22:14:53 UTC (rev 
61816)
+++ trunk/ipod-sharp/src/ObjectDumper.cs        2006-06-17 00:05:19 UTC (rev 
61817)
@@ -0,0 +1,124 @@
+
+using System;
+using System.Collections;
+using System.Reflection;
+
+namespace IPod {
+
+    internal class ObjectDumper {
+
+        public static void Dump (object o) {
+            Dump (o, 0, new ArrayList ());
+        }
+
+        private static string Pad (int level, string msg, params object[] 
args) {
+            string val = String.Format (msg, args);
+            return val.PadLeft ((level * 4) + val.Length);
+        }
+
+        private static void Dump (object o, int level, ArrayList previous) {
+            Type type = null;
+
+            if (o != null) {
+                type = o.GetType ();
+            }
+            
+            Dump (o, type, null, level, previous);
+        }
+        
+        private static void Dump (object o, Type type, string name, int level, 
ArrayList previous) {
+            if (o == null) {
+                Console.WriteLine (Pad (level, "{0} ({1}): (null)", name, 
type.Name));
+                return;
+            }
+
+            if (previous.Contains (o)) {
+                return;
+            }
+
+            previous.Add (o);
+
+            if (type.IsPrimitive || o is string) {
+                DumpPrimitive (o, type, name, level, previous);
+            } else {
+                DumpComposite (o, type, name, level, previous);
+            }
+        }
+
+        private static void DumpPrimitive (object o, Type type, string name, 
int level, ArrayList previous) {
+            if (name != null) {
+                Console.WriteLine (Pad (level, "{0} ({1}): {2}", name, 
type.Name, o));
+            } else {
+                Console.WriteLine (Pad (level, "({0}) {1}", type.Name, o));
+            }
+        }
+
+        private static void DumpComposite (object o, Type type, string name, 
int level, ArrayList previous) {
+
+            if (name != null) {
+                Console.WriteLine (Pad (level, "{0} ({1}):", name, type.Name));
+            } else {
+                Console.WriteLine (Pad (level, "({0})", type.Name));
+            }
+
+            if (o is IDictionary) {
+                DumpDictionary ((IDictionary) o, level, previous);
+            } else if (o is ICollection) {
+                DumpCollection ((ICollection) o, level, previous);
+            } else {
+                MemberInfo[] members = o.GetType ().GetMembers 
(BindingFlags.Instance | BindingFlags.Public |
+                                                                
BindingFlags.NonPublic);
+                
+                foreach (MemberInfo member in members) {
+                    try {
+                        DumpMember (o, member, level, previous);
+                    } catch {}
+                }
+            }
+        }
+
+        private static void DumpCollection (ICollection collection, int level, 
ArrayList previous) {
+            foreach (object child in collection) {
+                Dump (child, level + 1, previous);
+            }
+        }
+
+        private static void DumpDictionary (IDictionary dictionary, int level, 
ArrayList previous) {
+            foreach (object key in dictionary.Keys) {
+                Console.WriteLine (Pad (level + 1, "[{0}] ({1}):", key, 
key.GetType ().Name));
+
+                Dump (dictionary[key], level + 2, previous);
+            }
+        }
+
+        private static void DumpMember (object o, MemberInfo member, int 
level, ArrayList previous) {
+            if (member is MethodInfo || member is ConstructorInfo ||
+                member is EventInfo)
+                return;
+
+            if (member is FieldInfo) {
+                FieldInfo field = (FieldInfo) member;
+
+                string name = member.Name;
+                if ((field.Attributes & FieldAttributes.Public) == 0) {
+                    name = "#" + name;
+                }
+                
+                Dump (field.GetValue (o), field.FieldType, name, level + 1, 
previous);
+            } else if (member is PropertyInfo) {
+                PropertyInfo prop = (PropertyInfo) member;
+
+                if (prop.GetIndexParameters ().Length == 0 && prop.CanRead) {
+                    string name = member.Name;
+                    MethodInfo getter = prop.GetGetMethod ();
+
+                    if ((getter.Attributes & MethodAttributes.Public) == 0) {
+                        name = "#" + name;
+                    }
+                    
+                    Dump (prop.GetValue (o, null), prop.PropertyType, name, 
level + 1, previous);
+                }
+            }
+        }
+    }
+}

Modified: trunk/ipod-sharp/src/PhotoDatabase.cs
===================================================================
--- trunk/ipod-sharp/src/PhotoDatabase.cs       2006-06-16 22:14:53 UTC (rev 
61816)
+++ trunk/ipod-sharp/src/PhotoDatabase.cs       2006-06-17 00:05:19 UTC (rev 
61817)
@@ -9,6 +9,8 @@
 
     internal abstract class PhotoDbRecord : Record {
 
+        protected int recordPadding = PadLength;
+
         public PhotoDbRecord (bool isbe) : base (isbe) {
         }
         
@@ -38,6 +40,10 @@
             data = stream.GetBuffer ();
             writer.Close ();
         }
+
+        protected override void WritePadding (BinaryWriter writer) {
+            writer.Write (new byte[recordPadding]);
+        }
     }
 
     internal class DataFileRecord : PhotoDbRecord {
@@ -45,7 +51,6 @@
         private int unknownOne;
         private int unknownTwo;
         private int unknownThree;
-        private int unknownFour;
         private long unknownFive;
         private long unknownSix;
         private int unknownSeven = 2;
@@ -92,6 +97,8 @@
             unknownTen = ToInt32 (body, 48);
             unknownEleven = ToInt32 (body, 52);
 
+            recordPadding = body.Length - 56;
+
             for (int i = 0; i < numChildren; i++) {
                 PhotoDataSetRecord ds = new PhotoDataSetRecord (IsBE);
                 ds.Read (reader);
@@ -106,8 +113,8 @@
             SaveChildren (children,  out childBytes, out childLen);
 
             WriteName (writer);
-            writer.Write (68 + PadLength);
-            writer.Write (68 + PadLength + childLen);
+            writer.Write (68 + recordPadding);
+            writer.Write (68 + recordPadding + childLen);
             writer.Write (unknownOne);
             writer.Write (unknownTwo);
             writer.Write (children.Count);
@@ -147,6 +154,8 @@
             byte[] body = reader.ReadBytes (this.HeaderOne - 12);
             Index = (PhotoDataSetIndex) ToInt32 (body, 0);
 
+            recordPadding = body.Length - 4;
+
             switch (Index) {
             case PhotoDataSetIndex.ImageList:
                 Data = new ImageListRecord (IsBE);
@@ -171,8 +180,8 @@
 
             SaveChild (Data, out childBytes, out childLen);
             WriteName (writer);
-            writer.Write (16 + PadLength);
-            writer.Write (16 + PadLength + childLen);
+            writer.Write (16 + recordPadding);
+            writer.Write (16 + recordPadding + childLen);
             writer.Write ((int) Index);
             WritePadding (writer);
             writer.Write (childBytes, 0, childLen);
@@ -205,7 +214,8 @@
             base.Read (reader);
 
             if (HeaderOne - 12 > 0) {
-                reader.ReadBytes (HeaderOne - 12);
+                byte[] body = reader.ReadBytes (HeaderOne - 12);
+                recordPadding = body.Length;
             }
 
             albums.Clear ();
@@ -224,7 +234,7 @@
 
             SaveChildren (albums, out childBytes, out childLen);
             WriteName (writer);
-            writer.Write (12 + PadLength);
+            writer.Write (12 + recordPadding);
             writer.Write (albums.Count);
             WritePadding (writer);
             writer.Write (childBytes, 0, childLen);
@@ -289,6 +299,7 @@
             unknownOne = ToInt32 (body, 12);
             unknownTwo = ToInt16 (body, 16);
             IsMaster = body[18] == (byte) 1;
+
             PlayMusic = body[19] == (byte) 1;
             Repeat = body[20] == (byte) 1;
             Random = body[21] == (byte) 1;
@@ -301,9 +312,12 @@
             TrackId = ToInt64 (body, 40);
             PreviousPlaylistId = ToInt32 (body, 48);
 
+            recordPadding = body.Length - 52;
+
             for (int i = 0; i < numDataObjects; i++) {
                 PhotoDetailRecord detail = new PhotoDetailRecord (IsBE);
                 detail.Read (reader);
+                detail.BrokenChildPadding = true;
 
                 if (i == 0) {
                     nameRecord = detail;
@@ -329,14 +343,14 @@
             SaveChildren (items, out childBytes, out childLen);
 
             WriteName (writer);
-            writer.Write (64 + PadLength);
-            writer.Write (64 + PadLength + detailLen + childLen);
+            writer.Write (64 + recordPadding);
+            writer.Write (64 + recordPadding + detailLen + childLen);
             writer.Write (1);
             writer.Write (items.Count);
             writer.Write (PlaylistId);
             writer.Write (unknownOne);
             writer.Write (unknownTwo);
-            writer.Write (IsMaster ? (byte) 1 : (byte) 0);
+            writer.Write (IsMaster ? (byte) 1 : (byte) 6);
             writer.Write (PlayMusic ? (byte) 1 : (byte) 0);
             writer.Write (Repeat ? (byte) 1 : (byte) 0);
             writer.Write (Random ? (byte) 1 : (byte) 0);
@@ -372,12 +386,14 @@
 
             unknownOne = ToInt32 (body, 0);
             ImageId = ToInt32 (body, 4);
+
+            recordPadding = body.Length - 8;
         }
 
         public override void Save (BinaryWriter writer) {
             WriteName (writer);
-            writer.Write (20 + PadLength);
-            writer.Write (20 + PadLength);
+            writer.Write (20 + recordPadding);
+            writer.Write (20 + recordPadding);
             writer.Write (unknownOne);
             writer.Write (ImageId);
             WritePadding (writer);
@@ -410,8 +426,10 @@
         public override void Read (BinaryReader reader) {
             base.Read (reader);
 
-            reader.ReadBytes (this.HeaderOne - 12);
+            byte[] body = reader.ReadBytes (this.HeaderOne - 12);
 
+            recordPadding = body.Length;
+
             for (int i = 0; i < this.HeaderTwo; i++) {
                 ImageItemRecord item = new ImageItemRecord (IsBE);
                 item.Read (reader);
@@ -427,7 +445,7 @@
             SaveChildren (items, out childBytes, out childLen);
 
             WriteName (writer);
-            writer.Write (12 + PadLength);
+            writer.Write (12 + recordPadding);
             writer.Write (items.Count);
             WritePadding (writer);
             writer.Write (childBytes, 0, childLen);
@@ -448,6 +466,8 @@
         public ImageNameRecord ImageName;
         public string Value;
 
+        public bool BrokenChildPadding = false;
+
         public PhotoDetailRecord (bool isbe) : base (isbe) {
             this.Name = "mhod";
         }
@@ -466,6 +486,7 @@
 
             byte[] body = reader.ReadBytes (this.HeaderOne - 12);
             Type = (PhotoDetailType) ToInt16 (body, 0);
+            short childPadding = ToInt16 (body, 2);
 
             switch (Type) {
             case PhotoDetailType.ThumbnailContainer:
@@ -503,7 +524,7 @@
 
         private void WriteString (BinaryWriter writer, byte[] bytes, int 
padding, bool utf16) {
             writer.Write (bytes.Length);
-            writer.Write (utf16 ? 2 : 0);
+            writer.Write (utf16 ? 2 : 1);
             writer.Write (0);
             writer.Write (bytes);
             writer.Write (new byte[padding]);
@@ -534,7 +555,7 @@
             childPadding = 0;
 
             if (Type == PhotoDetailType.FileName || Type == 
PhotoDetailType.String) {
-                int totalLength = 16 + PadLength + childLen;
+                int totalLength = 16 + recordPadding + childLen;
                 while (totalLength%4 != 0) {
                     totalLength++;
                     childPadding++;
@@ -542,10 +563,16 @@
             }
 
             WriteName (writer);
-            writer.Write (16 + PadLength);
-            writer.Write (16 + PadLength + childLen + childPadding);
+            writer.Write (16 + recordPadding);
+            writer.Write (16 + recordPadding + childLen + childPadding);
             writer.Write ((short) Type);
-            writer.Write ((short) 2);
+
+            if (BrokenChildPadding) {
+                writer.Write (Utility.Swap ((short) childPadding));
+            } else {
+                writer.Write ((short) childPadding);
+            }
+            
             WritePadding (writer);
 
             switch (Type) {
@@ -602,6 +629,8 @@
             ImageHeight = ToInt16 (body, 20);
             ImageWidth = ToInt16 (body, 22);
 
+            recordPadding = body.Length - 24;
+
             for (int i = 0; i < numChildren; i++) {
                 PhotoDetailRecord detail = new PhotoDetailRecord (IsBE);
                 detail.Read (reader);
@@ -616,11 +645,12 @@
             byte[] childBytes;
             int childLen;
 
+            fileDetail.BrokenChildPadding = true;
             SaveChild (fileDetail, out childBytes, out childLen);
 
             WriteName (writer);
-            writer.Write (36 + PadLength);
-            writer.Write (36 + PadLength + childLen);
+            writer.Write (36 + recordPadding);
+            writer.Write (36 + recordPadding + childLen);
             writer.Write (1);
             writer.Write (CorrelationID);
             writer.Write (ThumbnailOffset);
@@ -682,6 +712,8 @@
             DigitizedDate = Utility.MacTimeToDate (ToUInt32 (body, 32));
             sourceImageSize = ToInt32 (body, 36);
 
+            recordPadding = body.Length - 40;
+
             for (int i = 0; i < numChildren; i++) {
                 PhotoDetailRecord detail = new PhotoDetailRecord (IsBE);
                 detail.Read (reader);
@@ -705,14 +737,14 @@
             }
 
             if (fullName != null) {
-                details.Add (new PhotoDetailRecord (IsBE, fullName, 
PhotoDetailType.ImageContainer));
+                details.Insert (0, new PhotoDetailRecord (IsBE, fullName, 
PhotoDetailType.ImageContainer));
             }
             
             SaveChildren (details, out childBytes, out childLen);
 
             WriteName (writer);
-            writer.Write (52 + PadLength);
-            writer.Write (52 + PadLength + childLen);
+            writer.Write (52 + recordPadding);
+            writer.Write (52 + recordPadding + childLen);
             writer.Write (details.Count);
             writer.Write (Id);
             writer.Write (TrackId);
@@ -743,7 +775,8 @@
             base.Read (reader);
 
             if (HeaderOne - 12 > 0) {
-                reader.ReadBytes (HeaderOne - 12);
+                byte[] body = reader.ReadBytes (HeaderOne - 12);
+                recordPadding = body.Length;
             }
             
             int numChildren = HeaderTwo;
@@ -761,7 +794,7 @@
             SaveChildren (files, out childBytes, out childLen);
 
             WriteName (writer);
-            writer.Write (12 + PadLength);
+            writer.Write (12 + recordPadding);
             writer.Write (files.Count);
             WritePadding (writer);
             writer.Write (childBytes, 0, childLen);
@@ -787,12 +820,14 @@
             unknownOne = ToInt32 (body, 0);
             CorrelationId = ToInt32 (body, 4);
             ImageSize = ToInt32 (body, 8);
+
+            recordPadding = body.Length - 12;
         }
 
         public override void Save (BinaryWriter writer) {
             WriteName (writer);
-            writer.Write (24 + PadLength);
-            writer.Write (24 + PadLength);
+            writer.Write (24 + recordPadding);
+            writer.Write (24 + recordPadding);
             writer.Write (unknownOne);
             writer.Write (CorrelationId);
             writer.Write (ImageSize);
@@ -806,12 +841,17 @@
         private Dictionary<int, Image> images = new Dictionary<int, Image> ();
         private List<Album> albums = new List<Album> ();
         private DataFileRecord dfr;
+        private bool isPhoto;
 
         private Album masterAlbum;
 
         private string PhotoDbPath {
             get {
-                return device.MountPoint + "/Photos/Photo Database";
+                if (isPhoto) {
+                    return device.MountPoint + "/Photos/Photo Database";
+                } else {
+                    return device.ControlPath + "/Artwork/ArtworkDB";
+                }
             }
         }
 
@@ -831,23 +871,26 @@
             }
         }
         
-        internal PhotoDatabase (Device device) : this (device, false) {
-        }
-
-        internal PhotoDatabase (Device device, bool createFresh) {
+        internal PhotoDatabase (Device device, bool isPhoto, bool createFresh) 
{
             this.device = device;
+            this.isPhoto = isPhoto;
 
-            // FIXME: do something with createFresh
+            if(createFresh && File.Exists (PhotoDbPath)) {
+                File.Copy (PhotoDbPath, PhotoDbBackupPath, true);
+            }
 
-            Reload ();
+            Reload (createFresh);
         }
 
-        public void Reload () {
+        public void Reload (bool createFresh) {
             images.Clear ();
             albums.Clear ();
             
-            dfr = new DataFileRecord (false);
+            dfr = new DataFileRecord (device.IsBE);
 
+            if (createFresh)
+                return;
+
             using (BinaryReader reader = new BinaryReader (File.Open 
(PhotoDbPath, FileMode.Open))) {
                 dfr.Read (reader);
 

Modified: trunk/ipod-sharp/src/TrackDatabase.cs
===================================================================
--- trunk/ipod-sharp/src/TrackDatabase.cs       2006-06-16 22:14:53 UTC (rev 
61816)
+++ trunk/ipod-sharp/src/TrackDatabase.cs       2006-06-17 00:05:19 UTC (rev 
61817)
@@ -29,7 +29,7 @@
             writer.Write (nameBytes);
         }
 
-        protected void WritePadding (BinaryWriter writer) {
+        protected virtual void WritePadding (BinaryWriter writer) {
             writer.Write (new byte[PadLength]);
         }
 
@@ -1521,7 +1521,7 @@
         private Random random = new Random();
         private Device device;
 
-        private string controlPath;
+        private PhotoDatabase artdb;
 
         public event EventHandler SaveStarted;
         public event SaveProgressHandler SaveProgressChanged;
@@ -1593,8 +1593,10 @@
             if(createFresh && File.Exists(TrackDbPath)) {
                 File.Copy (TrackDbPath, TrackDbBackupPath, true);
             }
-            
+
             Reload (createFresh);
+
+            artdb = new PhotoDatabase (device, false, createFresh);
         }
         
         
@@ -1698,7 +1700,8 @@
             Clear ();
 
             // This blows, we need to use the device model number or something
-            bool useBE = ControlPath.EndsWith ("iTunes_Control");
+            bool useBE = device.IsBE;
+            //ControlPath.EndsWith ("iTunes_Control");
                 
             if (!File.Exists (TrackDbPath) || createFresh) {
                 dbrec = new DatabaseRecord (useBE);
@@ -1881,6 +1884,9 @@
                     }
                 }
 
+                // Save artwork database
+                artdb.Save ();
+
                 // Save the shuffle tracks db (will only create if device is 
shuffle);
                 try {
                     ShuffleTrackDatabase.Save (device);

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to