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