diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/Artwork.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/Artwork.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/Artwork.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/Artwork.cs 2010-09-30 00:44:31.000000000 +0800
@@ -26,15 +26,15 @@
namespace native {
[StructLayout (LayoutKind.Sequential)]
internal struct Itdb_Artwork {
- public IntPtr thumbnail;
- public uint id;
- public ulong dbid;
- public int unk028;
- public uint rating;
- public int unk036;
- public IntPtr creation_date;
- public IntPtr digitized_date;
- public uint artwork_size;
+ public IntPtr thumbnail;
+ public uint id;
+ public ulong dbid;
+ public int unk028;
+ public uint rating;
+ public int unk036;
+ public IntPtr creation_date;
+ public IntPtr digitized_date;
+ public uint artwork_size;
// Ignore the rest
[DllImport ("gpod")]
@@ -64,20 +64,20 @@
}
public unsafe class Artwork : GPodBase {
- public Thumbnail Thumbnail { get { return new Thumbnail(((Itdb_Artwork *) Native)->thumbnail); }
- set { ((Itdb_Artwork *) Native)->thumbnail = HandleRef.ToIntPtr(value.Handle); } }
- public uint Rating { get { return ((Itdb_Artwork *) Native)->rating / 20; }
- set { ((Itdb_Artwork *) Native)->rating = (value > 5 ? 5 : value) * 20; } }
- public DateTime TimeCreated { get { return Artwork.time_tToDateTime (((Itdb_Artwork *) Native)->creation_date); }
- set { ((Itdb_Artwork *) Native)->creation_date = Artwork.DateTimeTotime_t(value); } }
+ public Thumbnail Thumbnail { get { return new Thumbnail(((Itdb_Artwork *) Native)->thumbnail); }
+ set { ((Itdb_Artwork *) Native)->thumbnail = HandleRef.ToIntPtr(value.Handle); } }
+ public uint Rating { get { return ((Itdb_Artwork *) Native)->rating / 20; }
+ set { ((Itdb_Artwork *) Native)->rating = (value > 5 ? 5 : value) * 20; } }
+ public DateTime TimeCreated { get { return Artwork.time_tToDateTime (((Itdb_Artwork *) Native)->creation_date); }
+ set { ((Itdb_Artwork *) Native)->creation_date = Artwork.DateTimeTotime_t(value); } }
public DateTime TimeDigitized { get { return Artwork.time_tToDateTime (((Itdb_Artwork *) Native)->digitized_date); }
- set { ((Itdb_Artwork *) Native)->digitized_date = Artwork.DateTimeTotime_t(value); } }
- public uint Size { get { return ((Itdb_Artwork *) Native)->artwork_size; }
- set { ((Itdb_Artwork *) Native)->artwork_size = value; } }
+ set { ((Itdb_Artwork *) Native)->digitized_date = Artwork.DateTimeTotime_t(value); } }
+ public uint Size { get { return ((Itdb_Artwork *) Native)->artwork_size; }
+ set { ((Itdb_Artwork *) Native)->artwork_size = value; } }
public Artwork(IntPtr handle, bool borrowed) : base(handle, borrowed) {}
public Artwork(IntPtr handle) : base(handle) {}
- public Artwork() : base(Itdb_Artwork.itdb_artwork_new (), false) {}
+ public Artwork() : base(Itdb_Artwork.itdb_artwork_new(), false) {}
public Artwork(Artwork other) : base(Itdb_Artwork.itdb_artwork_duplicate(other.Handle), false) {}
protected override void Destroy() { Itdb_Artwork.itdb_artwork_free(Handle); }
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/Chapter.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/Chapter.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/Chapter.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/Chapter.cs 2010-09-30 00:44:31.000000000 +0800
@@ -24,9 +24,9 @@
namespace native {
[StructLayout (LayoutKind.Sequential)]
internal struct Itdb_Chapter {
- public uint startpos;
- public IntPtr chaptertitle;
- // Ignore the rest
+ public uint startpos;
+ public IntPtr chaptertitle;
+ // Ignore the rest
[DllImport ("gpod")]
internal static extern IntPtr itdb_chapter_new();
@@ -60,4 +60,4 @@
set { var x = (Itdb_Chapter *) Native; ReplaceStringUTF8 (ref x->chaptertitle, value); }
}
}
-}
\ No newline at end of file
+}
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/ChapterData.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/ChapterData.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/ChapterData.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/ChapterData.cs 2010-09-30 00:44:31.000000000 +0800
@@ -26,7 +26,7 @@
namespace native {
internal struct Itdb_ChapterData {
public IntPtr chapters;
- // Ignore the rest
+ // Ignore the rest
[DllImport ("gpod")]
internal static extern IntPtr itdb_chapterdata_new();
@@ -59,6 +59,12 @@
this[index].SetBorrowed(false); // We're creating a new object here, so just deallocate the old one
Itdb_ChapterData.itdb_chapterdata_add_chapter(handle, item.StartPosition, item.Title);
}
+
+ protected unsafe override GLib.List List {
+ get {
+ return new GLib.List(((Itdb_ChapterData *) handle.Handle)->chapters, typeof(Chapter));
+ }
+ }
}
public unsafe class ChapterData : GPodBase {
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/Device.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/Device.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/Device.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/Device.cs 2010-09-30 00:44:31.000000000 +0800
@@ -71,11 +71,11 @@
/* According to teuf, SysInfo is crusty and probably not needed
* public class SysInfo {
HandleRef Handle;
- public SysInfo(HandleRef handle) { Handle = handle; }
- public bool Read() { return Itdb_Device.itdb_device_read_sysinfo(Handle); }
- public string Get(string field) { return Itdb_Device.itdb_device_get_sysinfo(Handle, field); }
- public void Set(string field, string val) { Itdb_Device.itdb_device_set_sysinfo(Handle, field, val); }
- public bool Write() {
+ public SysInfo(HandleRef handle) { Handle = handle; }
+ public bool Read() { return Itdb_Device.itdb_device_read_sysinfo(Handle); }
+ public string Get(string field) { return Itdb_Device.itdb_device_get_sysinfo(Handle, field); }
+ public void Set(string field, string val) { Itdb_Device.itdb_device_set_sysinfo(Handle, field, val); }
+ public bool Write() {
IntPtr gerror;
bool res = Itdb_Device.itdb_device_write_sysinfo(Handle, out gerror);
if (gerror != IntPtr.Zero)
@@ -85,20 +85,20 @@
}*/
public unsafe class Device : GPodBase {
- public bool SupportsArtwork { get { return Itdb_Device.itdb_device_supports_artwork(Handle); } }
- public bool SupportsChapterImage { get { return Itdb_Device.itdb_device_supports_chapter_image(Handle); } }
- public bool SupportsPhoto { get { return Itdb_Device.itdb_device_supports_photo(Handle); } }
- public bool SupportsPodcast { get { return Itdb_Device.itdb_device_supports_podcast(Handle); } }
- public bool SupportsVideo { get { return Itdb_Device.itdb_device_supports_video(Handle); } }
- //public SysInfo SysInfo { get { return new SysInfo(Handle); } }
- public IpodInfo IpodInfo { get { return IpodInfo.Find (Itdb_Device.itdb_device_get_ipod_info(Handle)); } }
- public string Mountpoint { get { return PtrToStringUTF8 (((Itdb_Device *)Native)->mountpoint); }
- set { Itdb_Device.itdb_device_set_mountpoint(Handle, value); } }
+ public bool SupportsArtwork { get { return Itdb_Device.itdb_device_supports_artwork(Handle); } }
+ public bool SupportsChapterImage { get { return Itdb_Device.itdb_device_supports_chapter_image(Handle); } }
+ public bool SupportsPhoto { get { return Itdb_Device.itdb_device_supports_photo(Handle); } }
+ public bool SupportsPodcast { get { return Itdb_Device.itdb_device_supports_podcast(Handle); } }
+ public bool SupportsVideo { get { return Itdb_Device.itdb_device_supports_video(Handle); } }
+ //public SysInfo SysInfo { get { return new SysInfo(Handle); } }
+ public IpodInfo IpodInfo { get { return IpodInfo.Find (Itdb_Device.itdb_device_get_ipod_info(Handle)); } }
+ public string Mountpoint { get { return PtrToStringUTF8 (((Itdb_Device *)Native)->mountpoint); }
+ set { Itdb_Device.itdb_device_set_mountpoint(Handle, value); } }
- public Device(IntPtr handle, bool borrowed) : base(handle, borrowed) {}
- public Device(IntPtr handle) : base(handle) {}
- public Device() : base(Itdb_Device.itdb_device_new(), false) {}
- public Device(string mountpoint) : this() { Mountpoint = mountpoint; }
+ public Device(IntPtr handle, bool borrowed) : base(handle, borrowed) {}
+ public Device(IntPtr handle) : base(handle) {}
+ public Device() : base(Itdb_Device.itdb_device_new(), false) {}
+ public Device(string mountpoint) : this() { Mountpoint = mountpoint; }
protected override void Destroy() { Itdb_Device.itdb_device_free(Handle); }
}
}
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/GPodBase.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/GPodBase.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/GPodBase.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/GPodBase.cs 2010-09-30 00:44:31.000000000 +0800
@@ -28,27 +28,38 @@
public abstract class GPodBase : IGPodBase, IDisposable {
- protected static string PtrToStringUTF8 (IntPtr ptr)
+ protected static string PtrToStringUTF8(IntPtr ptr)
{
- return GLib.Marshaller.Utf8PtrToString (ptr);
+ return GLib.Marshaller.Utf8PtrToString(ptr);
}
- protected static void ReplaceStringUTF8 (ref IntPtr ptr, string str)
+ protected static void ReplaceStringUTF8(ref IntPtr ptr, string str)
{
- GLib.Marshaller.Free (ptr);
- ptr = GLib.Marshaller.StringToPtrGStrdup (str);
+ GLib.Marshaller.Free(ptr);
+ ptr = GLib.Marshaller.StringToPtrGStrdup(str);
}
- protected static IntPtr DateTimeTotime_t (DateTime time) {
- return GLib.Marshaller.DateTimeTotime_t (time);
+ static DateTime local_epoch = new DateTime(1970, 1, 1, 0, 0, 0);
+ static int utc_offset = (int) (TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)).TotalSeconds;
+
+ public static IntPtr DateTimeTotime_t(DateTime time)
+ {
+ // The itunes database uses a 32bit signed value, so enforce that here to avoid
+ // overflow issues. We still need to represent time with an IntPtr though as
+ // that's what libgpod publicly exposes
+ return new IntPtr(((int)time.Subtract(local_epoch).TotalSeconds) - utc_offset);
}
-
- protected static DateTime time_tToDateTime (IntPtr time_t) {
- return GLib.Marshaller.time_tToDateTime (time_t);
+
+ public static DateTime time_tToDateTime(IntPtr time_t)
+ {
+ // The itunes database uses a 32bit signed value, so enforce that here to avoid
+ // overflow issues. We still need to represent time with an IntPtr though as
+ // that's what libgpod publicly exposes
+ return local_epoch.AddSeconds(time_t.ToInt32() + utc_offset);
}
internal IntPtr Native {
- get { return HandleRef.ToIntPtr (Handle); }
+ get { return HandleRef.ToIntPtr(Handle); }
}
IntPtr IGPodBase.Native {
@@ -61,16 +72,16 @@
public GPodBase(IntPtr handle) : this(handle, true) {}
public GPodBase(IntPtr handle, bool borrowed) {
Borrowed = borrowed;
- Handle = new HandleRef (this, handle);
+ Handle = new HandleRef(this, handle);
}
~GPodBase() { if (!Borrowed) Destroy(); }
public void SetBorrowed(bool borrowed) { Borrowed = borrowed; }
protected abstract void Destroy();
- public void Dispose ()
+ public void Dispose()
{
if (!Borrowed)
- Destroy ();
+ Destroy();
}
}
}
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/GPodList.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/GPodList.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/GPodList.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/GPodList.cs 2010-09-30 00:44:31.000000000 +0800
@@ -20,48 +20,52 @@
using System;
using System.Collections;
using System.Collections.Generic;
+ using System.Linq;
using System.Runtime.InteropServices;
using GLib;
internal abstract class GPodList : IList where T : IGPodBase {
- private class GPodListEnumerator : IEnumerator {
- private System.Collections.IEnumerator enumerator;
- public GPodListEnumerator(System.Collections.IEnumerator enumerator) { this.enumerator = enumerator; }
- public T Current { get { return (T) enumerator.Current; } }
- object IEnumerator.Current { get { return enumerator.Current; } }
- public bool MoveNext() { return enumerator.MoveNext(); }
- public void Reset() { enumerator.Reset(); }
- public void Dispose() { }
- }
protected HandleRef handle;
- protected List list;
+ protected abstract GLib.List List {
+ get;
+ }
protected bool owner;
- public GPodList(bool owner, HandleRef handle, List list) { this.handle = handle; this.list = list; this.owner = owner; }
- public GPodList(HandleRef handle, List list) : this(false, handle, list) {}
- public GPodList(bool owner, HandleRef handle, IntPtr listp) : this(owner, handle, new List(listp, typeof(T))) {}
- public GPodList(HandleRef handle, IntPtr listp) : this(false, handle, listp) {}
+ public GPodList(bool owner, HandleRef handle, List list) { this.handle = handle; this.owner = owner; }
+ public GPodList(HandleRef handle, List list) : this(false, handle, list) {}
+ public GPodList(bool owner, HandleRef handle, IntPtr listp) : this(owner, handle, null) {}
+ public GPodList(HandleRef handle, IntPtr listp) : this(false, handle, listp) {}
- public int Count { get { return list.Count; } }
+ public int Count { get { return List.Count; } }
public bool IsReadOnly { get { return false; } }
- public T this[int index] { get { return (T) list[index]; }
- set { RemoveAt(index); Insert(index, value); } }
+ public T this[int index] { get { return (T) List[index]; }
+ set { RemoveAt(index); Insert(index, value); } }
- public void Add(T item) { DoAdd (-1, item); if (owner) item.SetBorrowed(true); }
- public void Clear() { list.Empty(); }
- public void CopyTo(T[] array, int arrayIndex) { list.CopyTo(array, arrayIndex); }
- public IEnumerator GetEnumerator() { return new GPodListEnumerator(list.GetEnumerator()); }
+ public void Add(T item) { DoAdd (-1, item); if (owner) item.SetBorrowed(true); }
+ public void Clear() { /* Ensure we invoke DoUnlink */ while (Count > 0) RemoveAt (0); }
+ public void CopyTo(T[] array, int arrayIndex) { List.CopyTo(array, arrayIndex); }
+ public IEnumerator GetEnumerator() {
+ // Make an explicit copy of the list here to avoid memory
+ // corruption issues. What was happening is that managed land was
+ // instantiating a GLib.List from the native pointer, then if an
+ // item was unlinked from the native list, the GList in managed
+ // land would now be pointing at freed memory and would randomly
+ // blow up or crash. We work around this by instantiating a
+ // GLib.List every time and copying everything out immediately.
+ foreach (T t in List.Cast ().ToArray ())
+ yield return t;
+ }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
public bool Contains(T item) {
- return IndexOf (item) != -1;
+ return IndexOf(item) != -1;
}
public int IndexOf(T item) {
int i = 0;
foreach (T t in this) {
- if (object.ReferenceEquals (t, item) || t.Native == item.Native)
+ if (object.ReferenceEquals(t, item) || t.Native == item.Native)
return i;
i++;
}
@@ -88,4 +92,4 @@
protected abstract void DoAdd(int index, T item);
protected abstract void DoUnlink(int index);
}
-}
\ No newline at end of file
+}
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/IpodInfo.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/IpodInfo.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/IpodInfo.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/IpodInfo.cs 2010-09-30 00:44:31.000000000 +0800
@@ -123,23 +123,22 @@
}
public sealed unsafe class IpodInfo : GPodBase {
- public static IpodInfo[] Table = GetTable ();
+ public static IpodInfo[] Table = GetTable();
static unsafe IpodInfo[] GetTable() {
Itdb_IpodInfo *table = (Itdb_IpodInfo *) Itdb_IpodInfo.itdb_info_get_ipod_info_table();
- List retval = new List ();
+ List retval = new List();
while (true) {
Itdb_IpodInfo *item = &table [retval.Count];
if (item->model_number == IntPtr.Zero)
break;
- retval.Add (new IpodInfo ((IntPtr)item, true));
+ retval.Add(new IpodInfo((IntPtr)item, true));
}
- return retval.ToArray ();
+ return retval.ToArray();
}
- internal static IpodInfo Find (IntPtr native)
- {
+ internal static IpodInfo Find(IntPtr native) {
for (int i = 0; i < Table.Length; i++)
if (Table [i].Native == native)
return Table [i];
@@ -156,7 +155,7 @@
}
public string GenerationString {
- get { return PtrToStringUTF8 (Itdb_IpodInfo.itdb_info_get_ipod_generation_string(this.Generation)); }
+ get { return PtrToStringUTF8(Itdb_IpodInfo.itdb_info_get_ipod_generation_string(this.Generation)); }
}
public IpodModel Model {
@@ -164,28 +163,17 @@
}
public string ModelNumber {
- get { return PtrToStringUTF8 (((Itdb_IpodInfo *) Native)->model_number); }
+ get { return PtrToStringUTF8(((Itdb_IpodInfo *) Native)->model_number); }
}
public string ModelString {
- get { return PtrToStringUTF8 (Itdb_IpodInfo.itdb_info_get_ipod_model_name_string(this.Model)); }
+ get { return PtrToStringUTF8(Itdb_IpodInfo.itdb_info_get_ipod_model_name_string(this.Model)); }
}
- IpodInfo (IntPtr handle, bool borrowed)
- : base (handle, borrowed)
- {
-
- }
-
- IpodInfo (IntPtr handle)
- : base (handle)
- {
-
- }
-
- protected override void Destroy()
- {
+ IpodInfo (IntPtr handle, bool borrowed) : base (handle, borrowed) {}
+ IpodInfo (IntPtr handle) : base (handle) {}
+ protected override void Destroy() {
// No need to free anything as it's a static array in native code.
}
}
-}
\ No newline at end of file
+}
diff -Nru libgpod-0.7.94/bindings/mono/libgpod-sharp/ITDB.cs libgpod-0.7.95/bindings/mono/libgpod-sharp/ITDB.cs
--- libgpod-0.7.94/bindings/mono/libgpod-sharp/ITDB.cs 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/bindings/mono/libgpod-sharp/ITDB.cs 2010-09-30 00:44:31.000000000 +0800
@@ -26,28 +26,28 @@
namespace native {
internal struct Itdb_iTunesDB {
public IntPtr tracks;
- public IntPtr playlists;
- public IntPtr filename;
- public IntPtr device;
+ public IntPtr playlists;
+ public IntPtr filename;
+ public IntPtr device;
// Ignore everything else
[DllImport ("gpod")]
internal static extern IntPtr itdb_new();
[DllImport ("gpod")]
- internal static extern string itdb_cp_get_dest_filename (IntPtr track, string mountpoint, string filename, ref IntPtr error);
+ internal static extern string itdb_cp_get_dest_filename(IntPtr track, string mountpoint, string filename, ref IntPtr error);
[DllImport ("gpod")]
- internal static extern bool itdb_cp_track_to_ipod (HandleRef track, string filename, ref IntPtr error);
+ internal static extern bool itdb_cp_track_to_ipod(HandleRef track, string filename, ref IntPtr error);
[DllImport ("gpod")]
internal static extern void itdb_free(HandleRef itdb);
[DllImport ("gpod")]
- internal static extern string itdb_get_control_dir (string mountpoint);
+ internal static extern string itdb_get_control_dir(string mountpoint);
[DllImport ("gpod")]
- internal static extern string itdb_get_music_dir (string mountpoint);
+ internal static extern string itdb_get_music_dir(string mountpoint);
[DllImport ("gpod")]
internal static extern IntPtr itdb_parse(string mountpoint, out IntPtr gerror);
@@ -89,10 +89,10 @@
internal static extern IntPtr itdb_playlist_by_name(HandleRef itdb, string name);
[DllImport ("gpod")]
- internal static extern bool itdb_start_sync (IntPtr itdb);
+ internal static extern bool itdb_start_sync(IntPtr itdb);
[DllImport ("gpod")]
- internal static extern bool itdb_stop_sync (IntPtr itdb);
+ internal static extern bool itdb_stop_sync(IntPtr itdb);
}
}
@@ -100,12 +100,23 @@
public ITDBTrackList(bool owner, HandleRef handle, IntPtr list) : base(owner, handle, list) {}
protected override void DoAdd(int index, Track item) { Itdb_iTunesDB.itdb_track_add(this.handle, item.Handle, index); }
protected override void DoUnlink(int index) { Itdb_iTunesDB.itdb_track_unlink(this[index].Handle); }
+ protected unsafe override GLib.List List {
+ get {
+ return new GLib.List(((Itdb_iTunesDB *) handle.Handle)->tracks, typeof(Track));
+ }
+ }
}
internal class ITDBPlaylistList : GPodList {
public ITDBPlaylistList(bool owner, HandleRef handle, IntPtr list) : base(owner, handle, list) {}
protected override void DoAdd(int index, Playlist item) { Itdb_iTunesDB.itdb_playlist_add(this.handle, item.Handle, index); }
protected override void DoUnlink(int index) { Itdb_iTunesDB.itdb_playlist_unlink(this[index].Handle); }
+
+ protected unsafe override GLib.List List {
+ get {
+ return new GLib.List(((Itdb_iTunesDB *) handle.Handle)->playlists, typeof(Playlist));
+ }
+ }
}
public unsafe class ITDB : GPodBase {
@@ -117,63 +128,68 @@
return res;
}
- public static string GetLocalPath (Device device, Track track)
- {
- string ipodPath = track.IpodPath.Replace (":", "/").Substring (1);
- return System.IO.Path.Combine (device.Mountpoint, ipodPath);
+ public static string GetLocalPath(Device device, Track track) {
+ string ipodPath = track.IpodPath.Replace(":", "/").Substring(1);
+ return System.IO.Path.Combine(device.Mountpoint, ipodPath);
}
- public static string GetDestFileName (Device device, string localFile)
- {
- // itdb_cp_get_dest_filename (HandleRef track, string mountpoint, string filename, ref IntPtr error);
+ public static string GetDestFileName(Device device, string localFile) {
+ // itdb_cp_get_dest_filename(HandleRef track, string mountpoint, string filename, ref IntPtr error);
IntPtr error = IntPtr.Zero;
- string result = Itdb_iTunesDB.itdb_cp_get_dest_filename (IntPtr.Zero, device.Mountpoint, localFile, ref error);
+ string result = Itdb_iTunesDB.itdb_cp_get_dest_filename(IntPtr.Zero, device.Mountpoint, localFile, ref error);
if (error != IntPtr.Zero)
- throw new GException (error);
+ throw new GException(error);
return result;
}
- public static string GetControlPath (Device device)
- {
- return Itdb_iTunesDB.itdb_get_control_dir (device.Mountpoint);
- }
-
- public static string GetMusicPath (Device device)
- {
- return Itdb_iTunesDB.itdb_get_music_dir (device.Mountpoint);
- }
-
- public IList
+
+Calls to itdb_start_sync must be paired with calls to itdb_stop_sync. Nesting
+is allowed.
+
@@ -297,6 +301,10 @@
(but is safe to be used). On iPhones and iPod Touch this will hide the
"Sync in progress" screen.
+
+Calls to itdb_stop_sync must be paired with calls to itdb_start_sync. Nesting
+is allowed, and only the final itdb_stop_sync will actually stop the sync.
+
diff -Nru libgpod-0.7.94/docs/reference/html/libgpod-Tracks.html libgpod-0.7.95/docs/reference/html/libgpod-Tracks.html
--- libgpod-0.7.94/docs/reference/html/libgpod-Tracks.html 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/html/libgpod-Tracks.html 2010-09-30 01:10:58.000000000 +0800
@@ -1050,18 +1050,18 @@
enum Itdb_Mediatype
typedef enum
{
- ITDB_MEDIATYPE_AUDIO = 0x000001,
- ITDB_MEDIATYPE_MOVIE = 0x000002,
- ITDB_MEDIATYPE_PODCAST = 0x000004,
- ITDB_MEDIATYPE_AUDIOBOOK = 0x000008,
- ITDB_MEDIATYPE_MUSICVIDEO = 0x000020,
- ITDB_MEDIATYPE_TVSHOW = 0x000040,
- ITDB_MEDIATYPE_RINGTONE = 0x004000,
- ITDB_MEDIATYPE_RENTAL = 0x008000,
- ITDB_MEDIATYPE_ITUNES_EXTRA = 0x010000,
- ITDB_MEDIATYPE_MEMO = 0x100000,
- ITDB_MEDIATYPE_ITUNES_U = 0x200000,
- ITDB_MEDIATYPE_EPUB_BOOK = 0x400000
+ ITDB_MEDIATYPE_AUDIO = (1 << 0),
+ ITDB_MEDIATYPE_MOVIE = (1 << 1),
+ ITDB_MEDIATYPE_PODCAST = (1 << 2),
+ ITDB_MEDIATYPE_AUDIOBOOK = (1 << 3),
+ ITDB_MEDIATYPE_MUSICVIDEO = (1 << 5),
+ ITDB_MEDIATYPE_TVSHOW = (1 << 6),
+ ITDB_MEDIATYPE_RINGTONE = (1 << 14),
+ ITDB_MEDIATYPE_RENTAL = (1 << 15),
+ ITDB_MEDIATYPE_ITUNES_EXTRA = (1 << 16),
+ ITDB_MEDIATYPE_MEMO = (1 << 20),
+ ITDB_MEDIATYPE_ITUNES_U = (1 << 21),
+ ITDB_MEDIATYPE_EPUB_BOOK = (1 << 22)
} Itdb_Mediatype;
@@ -1070,7 +1070,11 @@
The mediatype is used to determine what menu a track appears under. For
example, setting the mediatype to ITDB_MEDIATYPE_PODCAST makes the track
-appear on the Podcast menu.
+appear on the Podcast menu. Media type is a bitfield, so it can be a
+binary combination of these constants, make sure to use binary operators
+when you want to operate on media types (eg use a binary AND in
+preference over a straight == when you want to test if a track has a
+given media type).
@@ -1132,7 +1136,8 @@
ITDB_MEDIATYPE_EPUB_BOOK
|
- |
+
+ |
diff -Nru libgpod-0.7.94/docs/reference/tmpl/artwork.sgml libgpod-0.7.95/docs/reference/tmpl/artwork.sgml
--- libgpod-0.7.94/docs/reference/tmpl/artwork.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/artwork.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -19,6 +19,9 @@
+
+
+
@@ -47,6 +50,7 @@
+@void:
@Returns:
diff -Nru libgpod-0.7.94/docs/reference/tmpl/chapterdata.sgml libgpod-0.7.95/docs/reference/tmpl/chapterdata.sgml
--- libgpod-0.7.94/docs/reference/tmpl/chapterdata.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/chapterdata.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -18,6 +18,9 @@
+
+
+
@@ -49,6 +52,7 @@
+@void:
@Returns:
@@ -74,6 +78,7 @@
+@void:
@Returns:
diff -Nru libgpod-0.7.94/docs/reference/tmpl/device.sgml libgpod-0.7.95/docs/reference/tmpl/device.sgml
--- libgpod-0.7.94/docs/reference/tmpl/device.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/device.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -17,6 +17,9 @@
+
+
+
@@ -30,12 +33,14 @@
@sysinfo_changed:
@timezone_shift:
@iphone_sync_context:
+@iphone_sync_nest_level:
+@void:
@Returns:
@@ -130,6 +135,7 @@
+@void:
@Returns:
@@ -167,6 +173,10 @@
@ITDB_IPOD_GENERATION_CLASSIC_3:
@ITDB_IPOD_GENERATION_NANO_5:
@ITDB_IPOD_GENERATION_TOUCH_3:
+@ITDB_IPOD_GENERATION_IPAD_1:
+@ITDB_IPOD_GENERATION_IPHONE_4:
+@ITDB_IPOD_GENERATION_TOUCH_4:
+@ITDB_IPOD_GENERATION_NANO_6:
@@ -222,6 +232,9 @@
@ITDB_IPOD_MODEL_SHUFFLE_BLACK:
@ITDB_IPOD_MODEL_IPHONE_WHITE:
@ITDB_IPOD_MODEL_IPHONE_BLACK:
+@ITDB_IPOD_MODEL_SHUFFLE_GOLD:
+@ITDB_IPOD_MODEL_SHUFFLE_STAINLESS:
+@ITDB_IPOD_MODEL_IPAD:
@@ -247,10 +260,10 @@
@back_color:
@display_width:
@interlaced:
-@align_row_bytes:
@color_adjustment:
@gamma:
@associated_format:
+@row_bytes_alignment:
diff -Nru libgpod-0.7.94/docs/reference/tmpl/Internal.sgml libgpod-0.7.95/docs/reference/tmpl/Internal.sgml
--- libgpod-0.7.94/docs/reference/tmpl/Internal.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/Internal.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -17,3 +17,6 @@
+
+
+
diff -Nru libgpod-0.7.94/docs/reference/tmpl/itunesdb-copying.sgml libgpod-0.7.95/docs/reference/tmpl/itunesdb-copying.sgml
--- libgpod-0.7.94/docs/reference/tmpl/itunesdb-copying.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/itunesdb-copying.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -18,6 +18,9 @@
+
+
+
diff -Nru libgpod-0.7.94/docs/reference/tmpl/itunesdb-db.sgml libgpod-0.7.95/docs/reference/tmpl/itunesdb-db.sgml
--- libgpod-0.7.94/docs/reference/tmpl/itunesdb-db.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/itunesdb-db.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -89,6 +89,9 @@
+
+
+
@@ -143,6 +146,7 @@
+@void:
@Returns:
diff -Nru libgpod-0.7.94/docs/reference/tmpl/itunesdb-lowlevel.sgml libgpod-0.7.95/docs/reference/tmpl/itunesdb-lowlevel.sgml
--- libgpod-0.7.94/docs/reference/tmpl/itunesdb-lowlevel.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/itunesdb-lowlevel.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -18,6 +18,9 @@
+
+
+
diff -Nru libgpod-0.7.94/docs/reference/tmpl/itunesdb-time.sgml libgpod-0.7.95/docs/reference/tmpl/itunesdb-time.sgml
--- libgpod-0.7.94/docs/reference/tmpl/itunesdb-time.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/itunesdb-time.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -24,11 +24,15 @@
+
+
+
+@void:
@Returns:
diff -Nru libgpod-0.7.94/docs/reference/tmpl/photodb.sgml libgpod-0.7.95/docs/reference/tmpl/photodb.sgml
--- libgpod-0.7.94/docs/reference/tmpl/photodb.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/photodb.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -91,6 +91,9 @@
+
+
+
diff -Nru libgpod-0.7.94/docs/reference/tmpl/playlists.sgml libgpod-0.7.95/docs/reference/tmpl/playlists.sgml
--- libgpod-0.7.94/docs/reference/tmpl/playlists.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/playlists.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -19,6 +19,9 @@
+
+
+
diff -Nru libgpod-0.7.94/docs/reference/tmpl/smart-playlists.sgml libgpod-0.7.95/docs/reference/tmpl/smart-playlists.sgml
--- libgpod-0.7.94/docs/reference/tmpl/smart-playlists.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/smart-playlists.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -17,6 +17,9 @@
+
+
+
@@ -275,6 +278,7 @@
+@void:
@Returns:
diff -Nru libgpod-0.7.94/docs/reference/tmpl/track.sgml libgpod-0.7.95/docs/reference/tmpl/track.sgml
--- libgpod-0.7.94/docs/reference/tmpl/track.sgml 2010-09-01 05:10:59.000000000 +0800
+++ libgpod-0.7.95/docs/reference/tmpl/track.sgml 2010-09-30 01:10:58.000000000 +0800
@@ -18,6 +18,9 @@
+
+
+
@@ -171,6 +174,7 @@
@ITDB_MEDIATYPE_ITUNES_EXTRA:
@ITDB_MEDIATYPE_MEMO:
@ITDB_MEDIATYPE_ITUNES_U:
+@ITDB_MEDIATYPE_EPUB_BOOK:
@@ -184,6 +188,7 @@
+@void:
@Returns:
diff -Nru libgpod-0.7.94/NEWS libgpod-0.7.95/NEWS
--- libgpod-0.7.94/NEWS 2010-09-01 05:03:28.000000000 +0800
+++ libgpod-0.7.95/NEWS 2010-09-30 01:08:23.000000000 +0800
@@ -1,4 +1,30 @@
-Overview of changes in libgpod 0.7.93
+Overview of changes in libgpod 0.7.95
+=====================================
+
+For information about iPhone/iPod Touch/iPod Nano 5g support, please read
+carefully the overview of libgpod 0.7.90 below. The iPhone 4, iPod Touch 4
+and the iPad aren't supported, other iOS4 devices might work. The Nano 6g
+(Touch Nano) isn't supported either.
+
+This release brings some improvements to the generation of the sqlite
+databases (used by iOS devices), in particular improved playcounts handling.
+It also adds some bug fixes to the mono bindings.
+
+* improved support for sqlite databases (Joel Smith)
+* bug fixes and playlist support for mono bindings (Alan McGovern, Gabriel
+ Burt, Nathaniel McCallum)
+* small itdb_start_sync/itdb_stop_sync behaviour change, now the calls need
+ to be paired, but itdb_start_sync can be called N times, and the "Sync in
+ Progress" screen will only go away after the Nth call to itdb_stop_sync
+ (Hector Martin)
+* be more smart when auto-guessing whether to use iPod_Control or
+ iTunes_Control (Whitney Young)
+* improve error handling in itdb_init and itdb_write, before that there
+ were error cases that were not properly reported to the caller (Christophe
+ Fergeau)
+
+
+Overview of changes in libgpod 0.7.94
=====================================
For information about iPhone/iPod Touch/iPod Nano 5g support, please read
diff -Nru libgpod-0.7.94/src/itdb_device.c libgpod-0.7.95/src/itdb_device.c
--- libgpod-0.7.94/src/itdb_device.c 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/src/itdb_device.c 2010-09-30 00:44:31.000000000 +0800
@@ -268,6 +268,23 @@
{"C074", 16, ITDB_IPOD_MODEL_NANO_RED, ITDB_IPOD_GENERATION_NANO_5, 14},
{"C075", 16, ITDB_IPOD_MODEL_NANO_PINK, ITDB_IPOD_GENERATION_NANO_5, 14},
+ /* iPod nano touch (Sixth Generation) */
+ {"C525", 8, ITDB_IPOD_MODEL_NANO_SILVER, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C688", 8, ITDB_IPOD_MODEL_NANO_BLACK, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C689", 8, ITDB_IPOD_MODEL_NANO_BLUE, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C690", 8, ITDB_IPOD_MODEL_NANO_GREEN, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C691", 8, ITDB_IPOD_MODEL_NANO_ORANGE, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C692", 8, ITDB_IPOD_MODEL_NANO_PINK, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C693", 8, ITDB_IPOD_MODEL_NANO_RED, ITDB_IPOD_GENERATION_NANO_6, 14},
+
+ {"C526", 16, ITDB_IPOD_MODEL_NANO_SILVER, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C694", 16, ITDB_IPOD_MODEL_NANO_BLACK, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C695", 16, ITDB_IPOD_MODEL_NANO_BLUE, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C696", 16, ITDB_IPOD_MODEL_NANO_GREEN, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C697", 16, ITDB_IPOD_MODEL_NANO_ORANGE, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C698", 16, ITDB_IPOD_MODEL_NANO_PINK, ITDB_IPOD_GENERATION_NANO_6, 14},
+ {"C699", 16, ITDB_IPOD_MODEL_NANO_RED, ITDB_IPOD_GENERATION_NANO_6, 14},
+
/* iPod Touch 1st gen */
{"A623", 8, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_1, 50},
{"A627", 16, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_1, 50},
@@ -286,6 +303,11 @@
{"C008", 32, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_3, 50},
{"C011", 64, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_3, 50},
+ /* iPod Touch 4th gen */
+ {"C540", 8, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_4, 50},
+ {"C544", 32, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_4, 50},
+ {"C547", 64, ITDB_IPOD_MODEL_TOUCH_SILVER, ITDB_IPOD_GENERATION_TOUCH_4, 50},
+
/* iPhone */
{"A501", 4, ITDB_IPOD_MODEL_IPHONE_1, ITDB_IPOD_GENERATION_IPHONE_1, 50},
{"A712", 8, ITDB_IPOD_MODEL_IPHONE_1, ITDB_IPOD_GENERATION_IPHONE_1, 50},
@@ -672,6 +694,7 @@
{ "YX7", "B228" }, /* 1GB Blue Shuffle 2g */
{ "YX9", "B225" }, /* 1GB Silver Shuffle 2g */
{ "8CQ", "C167" }, /* 1GB Gold Shuffle 2g */
+ { "1ZH", "B518" }, /* 2GB Silver Shuffle 2g */
{ "UNA", "A350" },
{ "UNB", "A350" },
{ "UPR", "A352" },
@@ -791,6 +814,8 @@
{ "73A", "C074" }, /* 16GB Red Nano 5g */
{ "73B", "C075" }, /* 16GB Pink Nano 5g */
+ { "CMN", "C525" }, /* 8GB Silver Nano 6g */
+
{ "A1S", "C306" }, /* 2GB Silver Shuffle 4g */
{ "A78", "C323" }, /* 2GB Black Shuffle 4g */
{ "ALB", "C381" }, /* 2GB Green Shuffle 4g */
@@ -808,9 +833,11 @@
{ "0JW", "B376" }, /* 32GB Silver iPod Touch (1st gen) */
{ "201", "B528" }, /* 8GB Silver iPod Touch (2nd gen) */
{ "203", "B531" }, /* 16GB Silver iPod Touch (2nd gen) */
- { "75J", "C086" }, /* 8GB Silver iPod Touch (3rd gen) */
- { "6K2", "C008" }, /* 32GB Silver iPod Touch (3rd gen) */
- { "6K4", "C011" }, /* 64GB Silver iPod Touch (3rd gen) */
+ { "75J", "C086" }, /* 8GB iPod Touch (3rd gen) */
+ { "6K2", "C008" }, /* 32GB iPod Touch (3rd gen) */
+ { "6K4", "C011" }, /* 64GB iPod Touch (3rd gen) */
+ { "CP7", "C540" }, /* 8GB iPod Touch (4th gen) */
+ { "CP9", "C544" }, /* 32GB iPod Touch (4th gen) */
{ "VR0", "A501" }, /* 4GB Silver iPhone 1st gen */
{ "WH8", "A712" }, /* 8GB Silver iPhone */
@@ -1338,9 +1365,11 @@
case ITDB_IPOD_GENERATION_CLASSIC_3:
return FALSE;
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
@@ -1396,12 +1425,14 @@
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
case ITDB_IPOD_GENERATION_CLASSIC_1:
case ITDB_IPOD_GENERATION_CLASSIC_2:
case ITDB_IPOD_GENERATION_CLASSIC_3:
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
@@ -1700,6 +1731,7 @@
case ITDB_IPOD_GENERATION_SHUFFLE_4:
case ITDB_IPOD_GENERATION_NANO_1:
case ITDB_IPOD_GENERATION_NANO_2:
+ case ITDB_IPOD_GENERATION_NANO_6:
return FALSE;
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
@@ -1712,6 +1744,7 @@
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
@@ -1838,6 +1871,8 @@
case ITDB_IPOD_GENERATION_IPAD_1:
case ITDB_IPOD_GENERATION_IPHONE_4:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
+ case ITDB_IPOD_GENERATION_NANO_6:
return ITDB_CHECKSUM_HASHAB;
case ITDB_IPOD_GENERATION_UNKNOWN:
@@ -2063,6 +2098,7 @@
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
case ITDB_IPOD_GENERATION_SHUFFLE_1:
case ITDB_IPOD_GENERATION_SHUFFLE_2:
case ITDB_IPOD_GENERATION_SHUFFLE_3:
@@ -2075,6 +2111,7 @@
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
@@ -2111,6 +2148,7 @@
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
case ITDB_IPOD_GENERATION_VIDEO_1:
case ITDB_IPOD_GENERATION_VIDEO_2:
case ITDB_IPOD_GENERATION_CLASSIC_1:
@@ -2119,6 +2157,7 @@
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
@@ -2157,6 +2196,7 @@
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
case ITDB_IPOD_GENERATION_SHUFFLE_1:
case ITDB_IPOD_GENERATION_SHUFFLE_2:
case ITDB_IPOD_GENERATION_SHUFFLE_3:
@@ -2170,6 +2210,7 @@
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
@@ -2209,6 +2250,7 @@
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
case ITDB_IPOD_GENERATION_VIDEO_1:
case ITDB_IPOD_GENERATION_VIDEO_2:
case ITDB_IPOD_GENERATION_CLASSIC_1:
@@ -2217,6 +2259,7 @@
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
case ITDB_IPOD_GENERATION_IPHONE_3:
diff -Nru libgpod-0.7.94/src/itdb_device.h libgpod-0.7.95/src/itdb_device.h
--- libgpod-0.7.94/src/itdb_device.h 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/src/itdb_device.h 2010-09-30 00:44:31.000000000 +0800
@@ -98,6 +98,8 @@
* and UTC
* @iphone_sync_context:Private data passed as is to libimobiledevice by
* itdb_start/stop_sync
+ * @iphone_sync_nest_level: Nesting count for itdb_start/stop_sync calls
+ * itdb_start/stop_sync
*
* Structure representing an iPod device
*
@@ -113,6 +115,7 @@
gboolean sysinfo_changed;
gint timezone_shift;
void *iphone_sync_context;
+ int iphone_sync_nest_level;
};
/**
diff -Nru libgpod-0.7.94/src/itdb.h libgpod-0.7.95/src/itdb.h
--- libgpod-0.7.94/src/itdb.h 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/src/itdb.h 2010-09-30 00:44:31.000000000 +0800
@@ -120,6 +120,7 @@
* @ITDB_IPOD_GENERATION_TOUCH_1: First Generation iPod Touch
* @ITDB_IPOD_GENERATION_TOUCH_2: Second Generation iPod Touch
* @ITDB_IPOD_GENERATION_TOUCH_3: Third Generation iPod Touch
+ * @ITDB_IPOD_GENERATION_TOUCH_4: Fourth Generation iPod Touch
* @ITDB_IPOD_GENERATION_IPHONE_1: First Generation iPhone
* @ITDB_IPOD_GENERATION_IPHONE_2: Second Generation iPhone (aka iPhone 3G)
* @ITDB_IPOD_GENERATION_IPHONE_3: Third Generation iPhone (aka iPhone 3GS)
@@ -163,7 +164,9 @@
ITDB_IPOD_GENERATION_NANO_5,
ITDB_IPOD_GENERATION_TOUCH_3,
ITDB_IPOD_GENERATION_IPAD_1,
- ITDB_IPOD_GENERATION_IPHONE_4
+ ITDB_IPOD_GENERATION_IPHONE_4,
+ ITDB_IPOD_GENERATION_TOUCH_4,
+ ITDB_IPOD_GENERATION_NANO_6
} Itdb_IpodGeneration;
/**
@@ -1230,9 +1233,11 @@
* @ITDB_MEDIATYPE_AUDIO: Audio files
* @ITDB_MEDIATYPE_MOVIE: Movies
* @ITDB_MEDIATYPE_PODCAST: Podcasts
+ * @ITDB_MEDIATYPE_VIDEO_PODCAST: Video Podcasts
* @ITDB_MEDIATYPE_AUDIOBOOK: Audio books
* @ITDB_MEDIATYPE_MUSICVIDEO: Music videos
* @ITDB_MEDIATYPE_TVSHOW: TV Shows
+ * @ITDB_MEDIATYPE_MUSIC_TVSHOW: TV Shows (also show in Music)
* @ITDB_MEDIATYPE_RINGTONE: Ringtone
* @ITDB_MEDIATYPE_RENTAL: Rental
* @ITDB_MEDIATYPE_ITUNES_EXTRA: ?
@@ -1243,26 +1248,36 @@
*
* The mediatype is used to determine what menu a track appears under. For
* example, setting the mediatype to #ITDB_MEDIATYPE_PODCAST makes the track
- * appear on the Podcast menu.
+ * appear on the Podcast menu. Media type is a bitfield, so it can be a
+ * binary combination of these constants, make sure to use binary operators
+ * when you want to operate on media types (eg use a binary AND in
+ * preference over a straight == when you want to test if a track has a
+ * given media type).
*
* Since: 0.5.0
*/
typedef enum
{
- ITDB_MEDIATYPE_AUDIO = 0x000001,
- ITDB_MEDIATYPE_MOVIE = 0x000002,
- ITDB_MEDIATYPE_PODCAST = 0x000004,
- ITDB_MEDIATYPE_AUDIOBOOK = 0x000008,
- ITDB_MEDIATYPE_MUSICVIDEO = 0x000020,
- ITDB_MEDIATYPE_TVSHOW = 0x000040,
- ITDB_MEDIATYPE_RINGTONE = 0x004000,
- ITDB_MEDIATYPE_RENTAL = 0x008000,
- ITDB_MEDIATYPE_ITUNES_EXTRA = 0x010000,
- ITDB_MEDIATYPE_MEMO = 0x100000,
- ITDB_MEDIATYPE_ITUNES_U = 0x200000,
- ITDB_MEDIATYPE_EPUB_BOOK = 0x400000
+ ITDB_MEDIATYPE_AUDIO = (1 << 0),
+ ITDB_MEDIATYPE_MOVIE = (1 << 1),
+ ITDB_MEDIATYPE_PODCAST = (1 << 2),
+ ITDB_MEDIATYPE_AUDIOBOOK = (1 << 3),
+ ITDB_MEDIATYPE_MUSICVIDEO = (1 << 5),
+ ITDB_MEDIATYPE_TVSHOW = (1 << 6),
+ ITDB_MEDIATYPE_RINGTONE = (1 << 14),
+ ITDB_MEDIATYPE_RENTAL = (1 << 15),
+ ITDB_MEDIATYPE_ITUNES_EXTRA = (1 << 16),
+ ITDB_MEDIATYPE_MEMO = (1 << 20),
+ ITDB_MEDIATYPE_ITUNES_U = (1 << 21),
+ ITDB_MEDIATYPE_EPUB_BOOK = (1 << 22)
} Itdb_Mediatype;
+/* Known compound media types which have been observed in iPod databases.
+ * This list is in no way exhaustive, and these constants are only helpers,
+ * there's nothing wrong with not using them.
+ */
+#define ITDB_MEDIATYPE_VIDEO_PODCAST (ITDB_MEDIATYPE_MOVIE | ITDB_MEDIATYPE_PODCAST)
+#define ITDB_MEDIATYPE_MUSIC_TVSHOW (ITDB_MEDIATYPE_MUSICVIDEO | ITDB_MEDIATYPE_TVSHOW)
typedef struct _Itdb_Track_Private Itdb_Track_Private;
/**
* Itdb_Track:
@@ -1747,9 +1762,20 @@
ITDB_FILE_ERROR_ITDB_CORRUPT
} ItdbFileError;
+typedef enum
+{
+ ITDB_ERROR_SEEK,
+ ITDB_ERROR_CORRUPT,
+ ITDB_ERROR_NOTFOUND,
+ ITDB_ERROR_RENAME,
+ ITDB_ERROR_ITDB_CORRUPT,
+ ITDB_ERROR_SQLITE
+} ItdbError;
+
/* Error domain */
-#define ITDB_FILE_ERROR itdb_file_error_quark ()
+#define ITDB_ERROR itdb_file_error_quark ()
+#define ITDB_FILE_ERROR ITDB_ERROR
GQuark itdb_file_error_quark (void);
diff -Nru libgpod-0.7.94/src/itdb_hash72.c libgpod-0.7.95/src/itdb_hash72.c
--- libgpod-0.7.94/src/itdb_hash72.c 2010-02-07 23:30:02.000000000 +0800
+++ libgpod-0.7.95/src/itdb_hash72.c 2010-09-30 00:44:31.000000000 +0800
@@ -311,12 +311,17 @@
gboolean itdb_hash72_compute_hash_for_sha1 (const Itdb_Device *device,
const guchar sha1[20],
- guchar signature[46])
+ guchar signature[46],
+ GError **error)
{
struct Hash78Info *hash_info;
hash_info = read_hash_info (device);
if (hash_info == NULL) {
+ if (error != NULL) {
+ g_set_error (error, ITDB_FILE_ERROR, ITDB_FILE_ERROR_NOTFOUND,
+ "Can't write iPod database because of missing HashInfo file");
+ }
return FALSE;
}
hash_generate (signature, sha1, hash_info->iv, hash_info->rndpart);
@@ -341,5 +346,5 @@
header = (MhbdHeader *)itdb_data;
header->hashing_scheme = GUINT16_FROM_LE (ITDB_CHECKSUM_HASH72);
itdb_hash72_compute_itunesdb_sha1 (itdb_data, itdb_len, sha1);
- return itdb_hash72_compute_hash_for_sha1 (device, sha1, header->hash72);
+ return itdb_hash72_compute_hash_for_sha1 (device, sha1, header->hash72, error);
}
diff -Nru libgpod-0.7.94/src/itdb_itunesdb.c libgpod-0.7.95/src/itdb_itunesdb.c
--- libgpod-0.7.94/src/itdb_itunesdb.c 2010-09-01 05:00:23.000000000 +0800
+++ libgpod-0.7.95/src/itdb_itunesdb.c 2010-09-30 00:44:31.000000000 +0800
@@ -111,12 +111,14 @@
#include "itdb_device.h"
#include "itdb_private.h"
#include "itdb_zlib.h"
+#include "itdb_plist.h"
#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -904,7 +906,7 @@
}
-/* called by init_playcounts */
+/* called by playcounts_init */
static gboolean playcounts_read (FImport *fimp, FContents *cts)
{
GList* playcounts = NULL;
@@ -1015,7 +1017,7 @@
}
-/* called by init_playcounts */
+/* called by playcounts_init */
static gboolean itunesstats_read (FImport *fimp, FContents *cts)
{
GList* playcounts = NULL;
@@ -1117,7 +1119,84 @@
return TRUE;
}
+static gint64 playcounts_plist_get_gint64 (GHashTable *track_dict,
+ const char *key)
+{
+ GValue *value;
+
+ value = g_hash_table_lookup (track_dict, key);
+ if (value && G_VALUE_HOLDS (value, G_TYPE_INT64)) {
+ return g_value_get_int64 (value);
+ }
+
+ return 0;
+}
+
+/* called by playcounts_init */
+static gboolean playcounts_plist_read (FImport *fimp, GValue *plist_data)
+{
+ GHashTable *playcounts;
+ struct playcount *playcount;
+ GHashTable *pc_dict, *track_dict;
+ GValue *to_parse;
+ GValueArray *array;
+ gint i;
+ guint32 mac_time;
+ guint64 *dbid;
+ g_return_val_if_fail (G_VALUE_HOLDS (plist_data, G_TYPE_HASH_TABLE), FALSE);
+ pc_dict = g_value_get_boxed (plist_data);
+
+ to_parse = g_hash_table_lookup (pc_dict, "tracks");
+ if (to_parse == NULL) {
+ return FALSE;
+ }
+ if (!G_VALUE_HOLDS (to_parse, G_TYPE_VALUE_ARRAY)) {
+ return FALSE;
+ }
+
+ playcounts = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, g_free);
+
+ array = (GValueArray*)g_value_get_boxed (to_parse);
+ for (i = 0; i < array->n_values; i++) {
+ if (!G_VALUE_HOLDS (g_value_array_get_nth (array, i), G_TYPE_HASH_TABLE)) {
+ continue;
+ }
+
+ track_dict = g_value_get_boxed (g_value_array_get_nth (array, i));
+ if (track_dict == NULL)
+ continue;
+
+ to_parse = g_hash_table_lookup (track_dict, "persistentID");
+ if (!to_parse)
+ continue;
+
+ dbid = g_new0 (guint64, 1);
+ if (!G_VALUE_HOLDS (to_parse, G_TYPE_INT64))
+ continue;
+ *dbid = g_value_get_int64 (to_parse);
+ playcount = g_new0 (struct playcount, 1);
+ g_hash_table_insert (playcounts, dbid, playcount);
+
+ playcount->bookmark_time = playcounts_plist_get_gint64 (track_dict, "bookmarkTimeInMS");
+ playcount->playcount = playcounts_plist_get_gint64 (track_dict, "playCount");
+ mac_time = playcounts_plist_get_gint64 (track_dict, "playMacOSDate");
+ playcount->time_played = device_time_mac_to_time_t (fimp->itdb->device, mac_time);
+ playcount->skipcount = playcounts_plist_get_gint64 (track_dict, "skipCount");
+ mac_time = playcounts_plist_get_gint64 (track_dict, "skipMacOSDate");
+ playcount->last_skipped = device_time_mac_to_time_t (fimp->itdb->device, mac_time);
+ playcount->rating = playcounts_plist_get_gint64 (track_dict, "userRating");
+ if (!playcount->rating)
+ playcount->rating = NO_PLAYCOUNT;
+
+ to_parse = g_hash_table_lookup (track_dict, "playedState");
+ if (to_parse && G_VALUE_HOLDS (to_parse, G_TYPE_BOOLEAN)) {
+ ; /* What do we do with this? */
+ }
+ }
+ fimp->pcounts2 = playcounts;
+ return TRUE;
+}
/* Read the Play Count file (formed by adding "Play Counts" to the
* directory component of fimp->itdb->itdb_filename) and set up the
@@ -1132,10 +1211,12 @@
{
const gchar *plc[] = {"Play Counts", NULL};
const gchar *ist[] = {"iTunesStats", NULL};
- gchar *plcname, *dirname, *istname;
+ const gchar *plcpl[] = {"PlayCounts.plist", NULL};
+ gchar *plcname, *dirname, *istname, *plcplname;
gboolean result=TRUE;
struct stat filestat;
FContents *cts;
+ GValue *plist_data;
g_return_val_if_fail (fimp, FALSE);
g_return_val_if_fail (!fimp->error, FALSE);
@@ -1147,6 +1228,7 @@
plcname = itdb_resolve_path (dirname, plc);
istname = itdb_resolve_path (dirname, ist);
+ plcplname = itdb_resolve_path (dirname, plcpl);
g_free (dirname);
@@ -1189,9 +1271,28 @@
}
}
}
+ else if (plcplname)
+ {
+ /* skip if PlayCounts.plist file has zero-length */
+ stat (plcplname, &filestat);
+ if (filestat.st_size > 0)
+ {
+ plist_data = itdb_plist_parse_from_file (plcplname, &fimp->error);
+ if (plist_data)
+ {
+ result = playcounts_plist_read (fimp, plist_data);
+ g_value_unset (plist_data);
+ }
+ else
+ {
+ result = FALSE;
+ }
+ }
+ }
g_free (plcname);
g_free (istname);
+ g_free (plcplname);
return result;
}
@@ -1207,6 +1308,9 @@
g_list_free (fimp->pos_glist);
g_list_free (fimp->tracks);
playcounts_free (fimp);
+ if (fimp->pcounts2 != NULL) {
+ g_hash_table_destroy (fimp->pcounts2);
+ }
g_free (fimp);
}
}
@@ -1530,26 +1634,33 @@
if (check_header_seek (cts, "chap", seek+4))
{
guint32 length;
+ guint32 childlength;
guint32 startpos;
+ guint32 children;
+ gint j;
gunichar2 *string_utf16;
startpos = get32bint (cts, seek+8);
+ children = get32bint (cts, seek+12);
seek += 20;
- if (check_header_seek (cts, "name", seek+4))
+ for (j=0; jpcounts2)
+ {
+ playcount = g_hash_table_lookup (fimp->pcounts2, &track->dbid);
+ free_playcount = FALSE;
+ }
if (playcount)
{
if (playcount->rating != NO_PLAYCOUNT)
@@ -2586,8 +2704,8 @@
track->skipcount += playcount->skipcount;
track->recent_skipcount = playcount->skipcount;
-
- g_free (playcount);
+ if (free_playcount)
+ g_free (playcount);
}
fimp->tracks = g_list_prepend(fimp->tracks, track);
return seek;
@@ -4195,6 +4313,56 @@
g_list_free (coltracks);
}
+static void
+itdb_chapterdata_build_chapter_blob_internal (WContents *cts,
+ Itdb_Chapterdata *chapterdata)
+{
+ gulong atom_len_seek;
+ gint numchapters;
+ GList *ch_gl = NULL;
+ /* printf("[%s] -- inserting into \"chapter\"\n", __func__); */
+
+ numchapters = g_list_length (chapterdata->chapters);
+
+ put32lint (cts, chapterdata->unk024); /* unknown */
+ put32lint (cts, chapterdata->unk028); /* unknown */
+ put32lint (cts, chapterdata->unk032); /* unknown */
+ atom_len_seek = cts->pos; /* needed to fix length */
+ put32bint (cts, -1); /* total length of sean atom, fix later */
+ put_header (cts, "sean");
+ put32bint (cts, 1); /* unknown */
+ put32bint (cts, numchapters+1); /* children */
+ put32bint (cts, 0); /* unknown */
+ for (ch_gl=chapterdata->chapters; ch_gl; ch_gl=ch_gl->next)
+ {
+ gunichar2 *title_utf16;
+ Itdb_Chapter *chapter = ch_gl->data;
+ glong len;
+ title_utf16 = g_utf8_to_utf16 (chapter->chaptertitle, -1, NULL, &len, NULL);
+ fixup_big_utf16 (title_utf16);
+ put32bint (cts, 42+2*len); /* total length */
+ put_header (cts, "chap");
+ put32bint (cts, chapter->startpos); /* should we check if startpos=0 here? */
+ put32bint (cts, 1); /* children */
+ put32bint (cts, 0); /* unknown */
+ put32bint (cts, 22+2*len); /* length */
+ put_header (cts, "name");
+ put32bint (cts, 1); /* unknown */
+ put32_n0 (cts, 2); /* unknown */
+ put16bint (cts, len);
+ put_data (cts, (gchar *)title_utf16, 2*len);
+ g_free (title_utf16);
+ }
+ put32bint (cts, 28); /* size */
+ put_header (cts, "hedr");
+ put32bint (cts, 1); /* unknown */
+ put32bint (cts, 0); /* children */
+ put32_n0 (cts, 2); /* unknown */
+ put32bint (cts, 1); /* unknown */
+
+ put32bint_seek (cts, cts->pos-atom_len_seek, atom_len_seek); /* size */
+}
+
/* Write out one mhod header.
type: see enum of MHMOD_IDs;
data: utf8 string for text items
@@ -4306,54 +4474,12 @@
g_return_if_fail (mhod->data.chapterdata);
{
gulong header_seek = cts->pos; /* needed to fix length */
- GList *gl;
- gint numchapters = g_list_length (mhod->data.chapterdata->chapters);
put_header (cts, "mhod"); /* header */
put32lint (cts, 24); /* header size */
put32lint (cts, -1); /* total length, fix later */
put32lint (cts, mhod->type); /* entry type */
put32_n0 (cts, 2); /* unknown */
- put32lint (cts, mhod->data.chapterdata->unk024); /* unknown */
- put32lint (cts, mhod->data.chapterdata->unk028); /* unknown */
- put32lint (cts, mhod->data.chapterdata->unk032); /* unknown */
- put32bint (cts, -1); /* total length of sean atom, fix later */
- put_header (cts, "sean");
- put32bint (cts, 1); /* unknown */
- put32bint (cts, numchapters+1); /* children */
- put32bint (cts, 0); /* unknown */
- for (gl=mhod->data.chapterdata->chapters; gl; gl=gl->next)
- {
- gunichar2 *title_utf16;
- Itdb_Chapter *chapter = gl->data;
-/* gint len = strlen(chapter->chaptertitle); */
- glong len;
- title_utf16 = NULL;
- title_utf16 = g_utf8_to_utf16 (chapter->chaptertitle,
- -1,NULL,&len,NULL);
- fixup_big_utf16 (title_utf16);
- put32bint (cts, 42+2*len); /* total length */
- put_header (cts, "chap");
- put32bint (cts, chapter->startpos); /* should we check if startpos=0 here? */
- put32bint (cts, 1); /* children */
- put32bint (cts, 0); /* unknown */
- put32bint (cts, 22+2*len); /* length */
- put_header (cts, "name");
- put32bint (cts, 1); /* unknown */
- put32_n0 (cts, 2); /* unknown */
- put16bint (cts, len);
- put_data (cts, (gchar *)title_utf16, 2*len);
- g_free (title_utf16);
-
- }
- put32bint (cts, 28); /* size */
- put_header (cts, "hedr");
- put32bint (cts, 1); /* unknown */
- put32bint (cts, 0); /* children */
- put32_n0 (cts, 2); /* unknown */
- put32bint (cts, 1); /* unknown */
-
-
- put32bint_seek (cts, cts->pos-(header_seek+36), header_seek+36); /* fix length of sean atom */
+ itdb_chapterdata_build_chapter_blob_internal (cts, mhod->data.chapterdata);
fix_header (cts, header_seek);
}
break;
@@ -5761,15 +5887,6 @@
goto err;
}
- /* write albums (mhsd type 4) */
- if (!write_mhsd_albums (fexp)) {
- g_set_error (&fexp->error,
- ITDB_FILE_ERROR,
- ITDB_FILE_ERROR_ITDB_CORRUPT,
- _("Error writing list of albums (mhsd type 4)"));
- goto err;
- }
-
/* write special podcast version mhsd (mhsd type 3) */
if (!fexp->error && !write_mhsd_playlists (fexp, 3)) {
g_set_error (&fexp->error,
@@ -5787,6 +5904,14 @@
goto err;
}
+ /* write albums (mhsd type 4) */
+ if (!write_mhsd_albums (fexp)) {
+ g_set_error (&fexp->error,
+ ITDB_FILE_ERROR,
+ ITDB_FILE_ERROR_ITDB_CORRUPT,
+ _("Error writing list of albums (mhsd type 4)"));
+ goto err;
+ }
/* write artists (mhsd type 8) */
if (!fexp->error && !write_mhsd_artists (fexp)) {
g_set_error (&fexp->error,
@@ -5984,6 +6109,9 @@
* but on iPhones and iPod Touch this makes sure the "Sync in progress" screen
* is shown for the whole duration of the writing process.
*
+ * Calls to itdb_start_sync must be paired with calls to itdb_stop_sync. Nesting
+ * is allowed.
+ *
* Returns: TRUE on success, FALSE on error
*/
gboolean itdb_start_sync (Itdb_iTunesDB *itdb)
@@ -5992,14 +6120,12 @@
g_return_val_if_fail (itdb->device != NULL, FALSE);
#ifdef HAVE_LIBIMOBILEDEVICE
- g_return_val_if_fail (itdb->device->iphone_sync_context == NULL, FALSE);
+ if (itdb->device->iphone_sync_context != NULL) {
+ itdb->device->iphone_sync_nest_level++;
+ return TRUE;
+ }
if (itdb_device_is_iphone_family (itdb->device)) {
int sync_status;
-
- if (itdb->device->iphone_sync_context != NULL) {
- /* already locked */
- return TRUE;
- }
sync_status = itdb_iphone_start_sync (itdb->device,
&itdb->device->iphone_sync_context);
if (sync_status == 0) {
@@ -6022,11 +6148,21 @@
* (but is safe to be used). On iPhones and iPod Touch this will hide the
* "Sync in progress" screen.
*
+ * Calls to itdb_stop_sync must be paired with calls to itdb_start_sync. Nesting
+ * is allowed, and only the final itdb_stop_sync will actually stop the sync.
+ *
* Returns: TRUE on success, FALSE on error
*/
gboolean itdb_stop_sync (Itdb_iTunesDB *itdb)
{
+ g_return_val_if_fail (itdb != NULL, FALSE);
+ g_return_val_if_fail (itdb->device != NULL, FALSE);
+
#ifdef HAVE_LIBIMOBILEDEVICE
+ if (itdb->device->iphone_sync_nest_level) {
+ itdb->device->iphone_sync_nest_level--;
+ return TRUE;
+ }
if (itdb_device_is_iphone_family (itdb->device)) {
int sync_status;
if (itdb->device->iphone_sync_context == NULL) {
@@ -6336,8 +6472,8 @@
put32lint_seek(cts, cts->pos, track_seek);
g_return_val_if_fail (write_rths(cts, track), FALSE);
- if (track->mediatype == ITDB_MEDIATYPE_AUDIOBOOK ||
- track->mediatype == ITDB_MEDIATYPE_PODCAST)
+ if ((track->mediatype & ITDB_MEDIATYPE_AUDIOBOOK) ||
+ (track->mediatype & ITDB_MEDIATYPE_PODCAST))
nonstdtrackcnt++;
/* Go to the offset for the next track */
@@ -6405,8 +6541,8 @@
id = tr->dbid;
ctr = current_track->data;
/* Count the number of podcasts and audiobooks for later use */
- if (tr->mediatype == ITDB_MEDIATYPE_AUDIOBOOK ||
- tr->mediatype == ITDB_MEDIATYPE_PODCAST)
+ if ((tr->mediatype & ITDB_MEDIATYPE_AUDIOBOOK) ||
+ (tr->mediatype & ITDB_MEDIATYPE_PODCAST))
nonstdtrackcnt++;
while( id != ctr->dbid)
@@ -7456,12 +7592,20 @@
*/
gchar *itdb_get_control_dir (const gchar *mountpoint)
{
+ gchar *p_iphone[] = {"iTunes_Control", NULL};
gchar *p_ipod[] = {"iPod_Control", NULL};
gchar *p_mobile[] = {"iTunes", "iTunes_Control", NULL};
- gchar *p_iphone[] = {"iTunes_Control", NULL};
/* Use an array with all possibilities, so further extension will
- be easy */
- gchar **paths[] = {p_ipod, p_mobile, p_iphone, NULL};
+ be easy. It is important that checking for the iTunes_Control
+ directory be done before the iPod_Control directory because
+ some devices actually have both directories. The iTunes_Control
+ directory is correct in these cases. This happens for devices
+ that Apple shipped with the iPod_Control as the control directory
+ and later switched to iTunes_Control instead. iTunes appears to
+ remove files from the old iPod_Control directory but leave the
+ directory structure intact. Finding this empty directory structure
+ first will result in a failure to find files. */
+ gchar **paths[] = {p_iphone, p_ipod, p_mobile, NULL};
gchar ***ptr;
gchar *result = NULL;
@@ -7887,6 +8031,38 @@
return TRUE;
}
+/**
+ * itdb_chapterdata_build_chapter_blob:
+ * @chapterdata: Itdb_Chapterdata pointer of chapter data to be encoded
+ *
+ * Creates an iTunesDB binary blob of chapter data from @chapterdata.
+ * This helper function is used by both mk_mhod() in itdb_itunesdb.c
+ * and mk_Extras() in itdb_sqlite.c, so take care when updating to
+ * maintain compatibility with both chapterdata blobs.
+ *
+ * NOTE: Caller must call g_byte_array_free(chapter_blob, TRUE) on the
+ * returned chapter_blob
+ *
+ * Returns: a binary itdb blob of chapter data (to be freed by the caller)
+ *
+ * Since: 0.7.95
+ */
+G_GNUC_INTERNAL GByteArray *itdb_chapterdata_build_chapter_blob(Itdb_Chapterdata *chapterdata, gboolean reversed)
+{
+ WContents *cts;
+ GByteArray * chapter_blob = NULL;
+
+ cts = wcontents_new("");
+ cts->reversed = reversed;
+ cts->pos = 0;
+
+ itdb_chapterdata_build_chapter_blob_internal (cts, chapterdata);
+
+ chapter_blob = g_byte_array_sized_new(cts->pos);
+ g_byte_array_append(chapter_blob, (guint8 *)cts->contents, cts->pos);
+ wcontents_free(cts);
+ return chapter_blob;
+}
/*------------------------------------------------------------------*\
@@ -7940,6 +8116,35 @@
return device->mountpoint;
}
+static gchar *itdb_device_get_control_dir (const Itdb_Device *device)
+{
+ Itdb_IpodInfo const *info = NULL;
+ char *podpath;
+
+ podpath = itdb_get_control_dir (device->mountpoint);
+ if (podpath != NULL) {
+ return podpath;
+ }
+
+ /* The device doesn't already have an iPod_Control directory, let's try
+ * to get which one is appropriate to use
+ */
+ info = itdb_device_get_ipod_info (device);
+
+ if (itdb_device_is_shuffle (device)) {
+ podpath = g_build_filename (device->mountpoint, "iPod_Control", NULL);
+ } else if (itdb_device_is_iphone_family (device)) {
+ podpath = g_build_filename (device->mountpoint,"iTunes_Control", NULL);
+ } else if (info->ipod_model == ITDB_IPOD_MODEL_MOBILE_1) {
+ podpath = g_build_filename (device->mountpoint,
+ "iTunes", "iTunes_Control",
+ NULL);
+ } else {
+ podpath = g_build_filename (device->mountpoint, "iPod_Control", NULL);
+ }
+
+ return podpath;
+}
/*------------------------------------------------------------------*\
@@ -7953,38 +8158,19 @@
gboolean result;
gchar *pbuf;
gint i, dirnum;
- Itdb_IpodInfo const *info = NULL;
- gboolean calconnotes, devicefile;
gchar *podpath;
+ gchar *model_number;
+ Itdb_IpodInfo const *info = NULL;
g_return_val_if_fail (device, FALSE);
mp = device->mountpoint;
- g_return_val_if_fail (mp, FALSE);
+ info = itdb_device_get_ipod_info (device);
- /* Retrieve the model from the device information */
- info = itdb_device_get_ipod_info(device);
-
- if (itdb_device_is_shuffle (device)) {
- podpath = g_strdup ("iPod_Control");
- calconnotes = FALSE;
- devicefile = TRUE;
- } else if (itdb_device_is_iphone_family (device)) {
- podpath = g_strdup ("iTunes_Control");
- calconnotes = FALSE;
- devicefile = TRUE;
- } else if (info->ipod_model == ITDB_IPOD_MODEL_MOBILE_1) {
- podpath = g_build_filename ("iTunes", "iTunes_Control", NULL);
- calconnotes = FALSE;
- devicefile = TRUE;
- } else {
- podpath = g_strdup ("iPod_Control");
- calconnotes = TRUE;
- devicefile = TRUE;
- }
+ g_return_val_if_fail (mp, FALSE);
/* Construct the Control directory */
- pbuf = g_build_filename (mp, podpath, NULL);
+ pbuf = itdb_device_get_control_dir (device);
if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
{
if (g_mkdir_with_parents(pbuf, 0777) != 0)
@@ -7993,9 +8179,13 @@
}
}
g_free (pbuf);
+ podpath = itdb_get_control_dir (mp);
+ if (!podpath) {
+ goto error_dir;
+ }
/* Construct the Music directory inside the Control directory */
- pbuf = g_build_filename (mp, podpath, "Music", NULL);
+ pbuf = g_build_filename (podpath, "Music", NULL);
if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
{
if((g_mkdir(pbuf, 0777) != 0))
@@ -8006,7 +8196,7 @@
g_free (pbuf);
/* Construct the iTunes directory inside the Control directory */
- pbuf = g_build_filename (mp, podpath, "iTunes", NULL);
+ pbuf = g_build_filename (podpath, "iTunes", NULL);
if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
{
if((g_mkdir(pbuf, 0777) != 0))
@@ -8022,7 +8212,7 @@
if (itdb_device_supports_artwork(device) ||
(info->ipod_model == ITDB_IPOD_MODEL_UNKNOWN))
{
- pbuf = g_build_filename (mp, podpath, "Artwork", NULL);
+ pbuf = g_build_filename (podpath, "Artwork", NULL);
if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
{
if((g_mkdir(pbuf, 0777) != 0)) {
@@ -8064,7 +8254,7 @@
for(i = 0; i < dirnum; i++)
{
gchar *num = g_strdup_printf ("F%02d", i);
- pbuf = g_build_filename (mp, podpath, "Music", num, NULL);
+ pbuf = g_build_filename (podpath, "Music", num, NULL);
g_free (num);
if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
{
@@ -8077,7 +8267,8 @@
}
/* Build Calendar directory for models requiring it */
- if (calconnotes)
+ if (!itdb_device_is_iphone_family (device)
+ && !itdb_device_is_shuffle (device))
{
pbuf = g_build_filename (mp, "Calendars", NULL);
if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
@@ -8112,33 +8303,28 @@
}
/* Construct a Device directory file for special models */
- if (devicefile)
+ pbuf = g_build_filename (podpath, "Device", NULL);
+ if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
{
- gchar *model_number;
-
- pbuf = g_build_filename (mp, podpath, "Device", NULL);
- if (!g_file_test (pbuf, G_FILE_TEST_EXISTS))
- {
- if((g_mkdir(pbuf, 0777) != 0))
- {
- goto error_dir;
- }
- }
- g_free (pbuf);
+ if((g_mkdir(pbuf, 0777) != 0))
+ {
+ goto error_dir;
+ }
+ }
+ g_free (pbuf);
- model_number = itdb_device_get_sysinfo (device, "ModelNumStr");
- /* Construct a SysInfo file */
- if (model_number && (strlen (model_number) != 0))
- {
- pbuf = NULL;
- if (!itdb_device_write_sysinfo (device, error))
- {
- g_free (model_number);
- goto error_dir;
- }
- }
- g_free (model_number);
+ model_number = itdb_device_get_sysinfo (device, "ModelNumStr");
+ /* Construct a SysInfo file */
+ if (model_number && (strlen (model_number) != 0))
+ {
+ pbuf = NULL;
+ if (!itdb_device_write_sysinfo (device, error))
+ {
+ g_free (model_number);
+ goto error_dir;
+ }
}
+ g_free (model_number);
pbuf = NULL;
error_dir:
diff -Nru libgpod-0.7.94/src/itdb_playlist.c libgpod-0.7.95/src/itdb_playlist.c
--- libgpod-0.7.94/src/itdb_playlist.c 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/src/itdb_playlist.c 2010-09-30 00:44:31.000000000 +0800
@@ -1595,7 +1595,7 @@
for (tl = pl->members; tl; tl = tl->next)
{
track = tl->data;
- if (track->mediatype != ITDB_MEDIATYPE_AUDIOBOOK)
+ if (!(track->mediatype & ITDB_MEDIATYPE_AUDIOBOOK))
{
return FALSE;
}
diff -Nru libgpod-0.7.94/src/itdb_plist.c libgpod-0.7.95/src/itdb_plist.c
--- libgpod-0.7.94/src/itdb_plist.c 2010-09-01 05:00:23.000000000 +0800
+++ libgpod-0.7.95/src/itdb_plist.c 2010-09-20 21:45:04.000000000 +0800
@@ -37,7 +37,7 @@
* in GValue. The types are mapped in the following way:
* - => G_TYPE_STRING (char*)
* - => G_TYPE_DOUBLE (double)
- * - => G_TYPE_INT (gint)
+ * - => G_TYPE_INT64 (gint64)
* - , => G_TYPE_BOOLEAN (gboolean)
* - => G_TYPE_GSTRING (GString *)
* - => G_TYPE_VALUE_ARRAY (GValueArray *)
@@ -82,11 +82,11 @@
{
char *str_val;
char *end_ptr;
- gint int_val;
+ gint64 int_val;
GValue *value;
str_val = (char *)xmlNodeGetContent(a_node);
- int_val = strtol (str_val, &end_ptr, 0);
+ int_val = strtoll (str_val, &end_ptr, 0);
if (*end_ptr != '\0') {
g_set_error (error, ITDB_DEVICE_ERROR, ITDB_DEVICE_ERROR_XML_PARSING,
"invalid integer value: %s", str_val);
@@ -96,8 +96,8 @@
xmlFree (str_val);
value = g_new0(GValue, 1);
- g_value_init(value, G_TYPE_INT);
- g_value_set_int (value, int_val);
+ g_value_init(value, G_TYPE_INT64);
+ g_value_set_int64 (value, int_val);
return value;
}
diff -Nru libgpod-0.7.94/src/itdb_private.h libgpod-0.7.95/src/itdb_private.h
--- libgpod-0.7.94/src/itdb_private.h 2010-09-01 05:00:23.000000000 +0800
+++ libgpod-0.7.95/src/itdb_private.h 2010-09-30 00:44:31.000000000 +0800
@@ -91,6 +91,7 @@
GList *pos_glist; /* temporary list to store position indicators */
GList *tracks; /* temporary list to store tracks */
GList *playcounts; /* contents of Play Counts file */
+ GHashTable *pcounts2;/* contents of the PlayCounts.plist file */
GTree *idtree; /* temporary tree with track id tree */
GError *error; /* where to report errors to */
} FImport;
@@ -240,7 +241,12 @@
GError **error);
G_GNUC_INTERNAL gboolean itdb_hash72_compute_hash_for_sha1 (const Itdb_Device *device,
const guchar sha1[20],
- guchar signature[46]);
+ guchar signature[46],
+ GError **error);
+
+G_GNUC_INTERNAL GByteArray *itdb_chapterdata_build_chapter_blob(Itdb_Chapterdata *chapterdata,
+ gboolean reversed);
+
#ifdef HAVE_LIBIMOBILEDEVICE
G_GNUC_INTERNAL int itdb_iphone_start_sync(Itdb_Device *device, void **prepdata);
G_GNUC_INTERNAL int itdb_iphone_stop_sync(void *sync_ctx);
diff -Nru libgpod-0.7.94/src/itdb_sqlite.c libgpod-0.7.95/src/itdb_sqlite.c
--- libgpod-0.7.94/src/itdb_sqlite.c 2010-09-01 05:00:23.000000000 +0800
+++ libgpod-0.7.95/src/itdb_sqlite.c 2010-09-30 00:44:34.000000000 +0800
@@ -361,8 +361,10 @@
int rebuild = 0;
gchar *dbf = NULL;
sqlite3 *db = NULL;
+ sqlite3_stmt *stmt_chapter = NULL;
char *errmsg = NULL;
struct stat fst;
+ GList *gl = NULL;
dbf = g_build_filename(outpath, "Extras.itdb", NULL);
printf("[%s] Processing '%s'\n", __func__, dbf);
@@ -398,10 +400,13 @@
}
sqlite3_exec(db, "BEGIN;", NULL, NULL, NULL);
+ if (SQLITE_OK != sqlite3_prepare_v2(db, "INSERT INTO \"chapter\" VALUES(?,?);", -1, &stmt_chapter, NULL)) {
+ fprintf(stderr, "[%s] sqlite3_prepare error: %s\n", __func__, sqlite3_errmsg(db));
+ goto leave;
+ }
/* kill all entries in 'chapter' as they will be re-inserted */
- /* TODO: we do not support this in the moment, so don't touch this */
- /*if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM chapter;", NULL, NULL, &errmsg)) {
+ if (SQLITE_OK != sqlite3_exec(db, "DELETE FROM chapter;", NULL, NULL, &errmsg)) {
fprintf(stderr, "[%s] sqlite3_exec error: %s\n", __func__, sqlite3_errmsg(db));
if (errmsg) {
fprintf(stderr, "[%s] additional error information: %s\n", __func__, errmsg);
@@ -409,7 +414,7 @@
errmsg = NULL;
}
goto leave;
- }*/
+ }
/* kill all entries in 'lyrics' as they will be re-inserted */
/* TODO: we do not support this in the moment, so don't touch this */
@@ -423,11 +428,38 @@
goto leave;
}*/
+ for (gl = itdb->tracks; gl; gl = gl->next) {
+ Itdb_Track *track = gl->data;
+ if (track->chapterdata) {
+ int idx = 0;
+ GByteArray *chapter_blob = itdb_chapterdata_build_chapter_blob(track->chapterdata, FALSE);
+ /* printf("[%s] -- inserting into \"chapter\"\n", __func__); */
+ res = sqlite3_reset(stmt_chapter);
+ if (res != SQLITE_OK) {
+ fprintf(stderr, "[%s] 1 sqlite3_reset returned %d\n", __func__, res);
+ }
+ /* item_pid INTEGER NOT NULL */
+ sqlite3_bind_int64(stmt_chapter, ++idx, track->dbid);
+ /* data BLOB */
+ sqlite3_bind_blob(stmt_chapter, ++idx, chapter_blob->data, chapter_blob->len, SQLITE_TRANSIENT);
+
+ res = sqlite3_step(stmt_chapter);
+ if (res == SQLITE_DONE) {
+ /* expected result */
+ } else {
+ fprintf(stderr, "[%s] 8 sqlite3_step returned %d\n", __func__, res);
+ }
+ g_byte_array_free(chapter_blob, TRUE);
+ }
+ }
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
res = 0;
printf("[%s] done.\n", __func__);
leave:
+ if (stmt_chapter) {
+ sqlite3_finalize(stmt_chapter);
+ }
if (db) {
sqlite3_close(db);
}
@@ -1264,11 +1296,11 @@
/* series_name TEXT */
sqlite3_bind_text(stmt_video_info, ++idx, track->tvshow, -1, SQLITE_STATIC);
/* sort_series_name TEXT */
- sqlite3_bind_text(stmt_video_info, ++idx, track->sort_tvshow, -1, SQLITE_STATIC);
+ bind_first_text(stmt_item, ++idx, 2, track->sort_tvshow, track->tvshow);
/* episode_id TEXT */
sqlite3_bind_text(stmt_video_info, ++idx, track->tvepisode, -1, SQLITE_STATIC);
/* episode_sort_id INTEGER */
- sqlite3_bind_int(stmt_video_info, ++idx, track->episode_nr);
+ sqlite3_bind_int(stmt_video_info, ++idx, track->season_nr << 16 | track->episode_nr);
/* network_name TEXT */
sqlite3_bind_text(stmt_video_info, ++idx, track->tvnetwork, -1, SQLITE_STATIC);
/* extended_content_rating TEXT */
@@ -1876,7 +1908,7 @@
final_sha1 = &g_array_index(cbk, guchar, CBK_HEADER_SIZE);
cbk_hash72 = &g_array_index(cbk, guchar, 0);
success = itdb_hash72_compute_hash_for_sha1 (itdb->device, final_sha1,
- cbk_hash72);
+ cbk_hash72, NULL);
if (!success) {
g_array_free(cbk, TRUE);
return FALSE;
@@ -1924,38 +1956,41 @@
return 0;
}
-static int ensure_itlp_dir_exists(const char *itlpdir)
+static int ensure_itlp_dir_exists(const char *itlpdir, GError **error)
{
/* check if directory exists */
if (!g_file_test(itlpdir, G_FILE_TEST_EXISTS)) {
if (g_mkdir(itlpdir, 0755) != 0) {
- fprintf(stderr, "Could not create directory '%s': %s\n", itlpdir, strerror(errno));
- return FALSE;
+ g_set_error (error, G_FILE_ERROR,
+ g_file_error_from_errno(errno),
+ "Could not create directory '%s': %s",
+ itlpdir, strerror(errno));
+ return FALSE;
}
} else if (!g_file_test(itlpdir, G_FILE_TEST_IS_DIR)) {
- fprintf(stderr, "'%s' is not a directory as it should be!\n", itlpdir);
- return FALSE;
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOTDIR,
+ "'%s' is not a directory as it should be",
+ itlpdir);
+ return FALSE;
}
return TRUE;
}
-static int copy_itdb_file(gchar *from_dir, gchar *to_dir, gchar *fname)
+static int copy_itdb_file(const gchar *from_dir, const gchar *to_dir,
+ const gchar *fname, GError **error)
{
int res = 0;
gchar *srcname = g_build_filename(from_dir, fname, NULL);
gchar *dstname = g_build_filename(to_dir, fname, NULL);
- GError *error = NULL;
- if (itdb_cp(srcname, dstname, &error)) {
+ if (itdb_cp(srcname, dstname, error)) {
fprintf(stderr, "itdbprep: copying '%s'\n", fname);
res++;
}
-
- if (error) {
- fprintf(stderr, "Error copying '%s' to '%s': %s\n", srcname, dstname, error->message);
- g_error_free(error);
+ if (error && *error) {
+ fprintf(stderr, "Error copying '%s' to '%s': %s\n", srcname, dstname, (*error)->message);
}
if (srcname) {
@@ -2009,7 +2044,7 @@
printf("itlp directory='%s'\n", itlpdir);
- if (!ensure_itlp_dir_exists(itlpdir)) {
+ if (!ensure_itlp_dir_exists(itlpdir, &fexp->error)) {
res = -1;
goto leave;
}
@@ -2023,7 +2058,9 @@
tmpdir = g_build_path(g_get_tmp_dir(), tmpnam(NULL), NULL);
if (g_mkdir(tmpdir, 0755) != 0) {
- fprintf(stderr, "Could not create temporary directory '%s': %s\n", tmpdir, strerror(errno));
+ g_set_error (&fexp->error, G_FILE_ERROR, g_file_error_from_errno(errno),
+ "Could not create temporary directory '%s': %s",
+ tmpdir, strerror(errno));
res = -1;
goto leave;
}
@@ -2031,19 +2068,31 @@
/* generate itdb files in temporary directory */
if (build_itdb_files(fexp->itdb, fexp->albums, fexp->artists, fexp->composers, tmpdir,
itdb_device_get_uuid(fexp->itdb->device)) != 0) {
+ g_set_error (&fexp->error, ITDB_ERROR, ITDB_ERROR_SQLITE,
+ "Failed to generate sqlite database");
res = -1;
goto leave;
} else {
/* copy files */
- int cpcnt = 0;
- cpcnt += copy_itdb_file(tmpdir, itlpdir, "Dynamic.itdb");
- cpcnt += copy_itdb_file(tmpdir, itlpdir, "Extras.itdb");
- cpcnt += copy_itdb_file(tmpdir, itlpdir, "Genius.itdb");
- cpcnt += copy_itdb_file(tmpdir, itlpdir, "Library.itdb");
- cpcnt += copy_itdb_file(tmpdir, itlpdir, "Locations.itdb");
- cpcnt += copy_itdb_file(tmpdir, itlpdir, "Locations.itdb.cbk");
- if (cpcnt != 6) {
- res = -1;
+ const char *itdb_files[] = { "Dynamic.itdb", "Extras.itdb",
+ "Genius.itdb", "Library.itdb",
+ "Locations.itdb", "Locations.itdb.cbk",
+ NULL };
+ const char **file;
+ GError *error = NULL;
+ g_assert (fexp->error == NULL);
+ for (file = itdb_files; *file != NULL; file++) {
+ copy_itdb_file(tmpdir, itlpdir, *file, &error);
+ if (error) {
+ res = -1;
+ /* only the last error will be reported, but this way we
+ * copy as many files as possible even when errors occur
+ */
+ g_clear_error (&fexp->error);
+ g_propagate_error (&fexp->error, error);
+ }
+ }
+ if (fexp->error) {
goto leave;
}
}
diff -Nru libgpod-0.7.94/src/itdb_sysinfo_extended_parser.c libgpod-0.7.95/src/itdb_sysinfo_extended_parser.c
--- libgpod-0.7.94/src/itdb_sysinfo_extended_parser.c 2010-09-01 05:00:23.000000000 +0800
+++ libgpod-0.7.95/src/itdb_sysinfo_extended_parser.c 2010-09-20 21:45:04.000000000 +0800
@@ -111,7 +111,7 @@
gboolean sqlite_db;
};
-static gint get_int (GHashTable *dict, const char *key)
+static gint64 get_int64 (GHashTable *dict, const char *key)
{
GValue *val;
@@ -119,10 +119,10 @@
if (val == NULL) {
return 0;
}
- if (!G_VALUE_HOLDS_INT (val)) {
+ if (!G_VALUE_HOLDS_INT64 (val)) {
return 0;
}
- return g_value_get_int (val);
+ return g_value_get_int64 (val);
}
static gdouble get_double (GHashTable *dict, const char *key)
@@ -177,8 +177,8 @@
static const DictFieldMapping sysinfo_ipod_properties_fields_mapping[] = {
{ "BuildID", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, build_id) },
{ "ConnectedBus", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, connected_bus) },
- { "MaxTransferSpeed", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, max_transfer_speed) },
- { "FamilyID", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, family_id) },
+ { "MaxTransferSpeed", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, max_transfer_speed) },
+ { "FamilyID", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, family_id) },
{ "ProductType", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, product_type) },
{ "FireWireGUID", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, firewire_guid) },
{ "FireWireVersion", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, firewire_version) },
@@ -186,17 +186,17 @@
{ "MinITunesVersion", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, min_itunes_version) },
{ "PlaylistFoldersSupported", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, playlist_folders_supported) },
{ "SerialNumber", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, serial_number) },
- { "UpdaterFamilyID", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, updater_family_id) },
+ { "UpdaterFamilyID", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, updater_family_id) },
{ "VisibleBuildID", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, visible_build_id) },
- { "OEMID", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, oem_id) },
- { "OEMU", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, oem_u) },
- { "DBVersion", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, db_version) },
+ { "OEMID", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, oem_id) },
+ { "OEMU", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, oem_u) },
+ { "DBVersion", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, db_version) },
{ "MinBuildID", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, min_build_id) },
{ "Language", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, language) },
{ "VoiceMemosSupported", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, voice_memos_supported) },
- { "UpdateMethod", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, update_method) },
- { "MaxFWBlocks", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, max_fw_blocks) },
- { "FWPartSize", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, fw_part_size) },
+ { "UpdateMethod", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, update_method) },
+ { "MaxFWBlocks", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, max_fw_blocks) },
+ { "FWPartSize", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, fw_part_size) },
{ "AutoRebootAfterFirmwareUpdate", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, auto_reboot_after_firmware_update) },
{ "VolumeFormat", G_TYPE_STRING, G_STRUCT_OFFSET (SysInfoIpodProperties, volume_format) },
{ "ForcedDiskMode", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, forced_disk_mode) },
@@ -207,27 +207,27 @@
{ "CanHibernate", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, can_hibernate) },
{ "CameWithCD", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, came_with_cd) },
{ "SupportsSparseArtwork", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, supports_sparse_artwork) },
- { "MaxThumbFileSize", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, max_thumb_file_size) },
- { "RAM", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, ram) },
- { "HotPlugState", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, hotplug_state) },
- { "BatteryPollInterval", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, battery_poll_interval) },
+ { "MaxThumbFileSize", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, max_thumb_file_size) },
+ { "RAM", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, ram) },
+ { "HotPlugState", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, hotplug_state) },
+ { "BatteryPollInterval", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, battery_poll_interval) },
{ "SortFieldsSupported", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, sort_fields_supported) },
{ "vCardWithJPEGSupported", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, vcard_with_jpeg_supported) },
- { "MaxFileSizeInGB", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, max_file_size_in_gb) },
- { "MaxTracks", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, max_tracks) },
- { "GamesPlatformID", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, games_platform_id) },
- { "GamesPlatformVersion", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, games_platform_version) },
- { "RentalClockBias", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, rental_clock_bias) },
+ { "MaxFileSizeInGB", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, max_file_size_in_gb) },
+ { "MaxTracks", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, max_tracks) },
+ { "GamesPlatformID", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, games_platform_id) },
+ { "GamesPlatformVersion", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, games_platform_version) },
+ { "RentalClockBias", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, rental_clock_bias) },
{ "SQLiteDB", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (SysInfoIpodProperties, sqlite_db) },
- { "ShadowDBVersion", G_TYPE_INT, G_STRUCT_OFFSET (SysInfoIpodProperties, shadowdb_version) },
+ { "ShadowDBVersion", G_TYPE_INT64, G_STRUCT_OFFSET (SysInfoIpodProperties, shadowdb_version) },
{ NULL, G_TYPE_NONE, 0 }
};
static const DictFieldMapping sysinfo_image_format_fields_mapping[] = {
- { "FormatId", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, format_id) },
- { "DisplayWidth", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, display_width) },
- { "RenderWidth", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, width) },
- { "RenderHeight", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, height) },
+ { "FormatId", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, format_id) },
+ { "DisplayWidth", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, display_width) },
+ { "RenderWidth", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, width) },
+ { "RenderHeight", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, height) },
/* PixelFormat needs to be converted to ItdbThumbFormat, this is special-cased
* in g_value_to_image_format */
/* { "PixelFormat", G_TYPE_STRING, G_STRUCT_OFFSET (Itdb_ArtworkFormat, format) },*/
@@ -236,14 +236,14 @@
/* AlignRowBytes is an older version of RowBytesAlignment, it's equivalent
* to a value of 4 for RowBytesAlignemnt */
/* { "AlignRowBytes", G_TYPE_BOOLEAN, G_STRUCT_OFFSET (Itdb_ArtworkFormat, align_row_bytes) },*/
- { "Rotation", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, rotation) },
+ { "Rotation", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, rotation) },
/* BackColor needs to be converted to a gint, this is special-cased
* in g_value_to_image_format */
-/* { "BackColor", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, back_color) }, */
- { "ColorAdjustment", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, color_adjustment) },
+/* { "BackColor", G_TYPE_INT64 G_STRUCT_OFFSET (Itdb_ArtworkFormat, back_color) }, */
+ { "ColorAdjustment", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, color_adjustment) },
{ "GammaAdjustment", G_TYPE_DOUBLE, G_STRUCT_OFFSET (Itdb_ArtworkFormat, gamma) },
- { "AssociatedFormat", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, associated_format) },
- { "RowBytesAlignment", G_TYPE_INT, G_STRUCT_OFFSET (Itdb_ArtworkFormat, row_bytes_alignment) },
+ { "AssociatedFormat", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, associated_format) },
+ { "RowBytesAlignment", G_TYPE_INT64, G_STRUCT_OFFSET (Itdb_ArtworkFormat, row_bytes_alignment) },
{ NULL, G_TYPE_NONE, 0 }
};
@@ -262,10 +262,10 @@
g_return_if_fail (it != NULL);
while (it->name != NULL) {
switch (it->type) {
- case G_TYPE_INT: {
+ case G_TYPE_INT64: {
gint *field;
field = G_STRUCT_MEMBER_P (struct_ptr, it->offset);
- *field = get_int (dict, it->name);
+ *field = get_int64 (dict, it->name);
break;
}
@@ -340,7 +340,7 @@
g_return_if_fail (it != NULL);
while (it->name != NULL) {
switch (it->type) {
- case G_TYPE_INT: {
+ case G_TYPE_INT64: {
gint *field;
field = G_STRUCT_MEMBER_P (struct_ptr, it->offset);
g_print ("%s: %d\n", it->name, *field);
diff -Nru libgpod-0.7.94/src/itdb_tzinfo.c libgpod-0.7.95/src/itdb_tzinfo.c
--- libgpod-0.7.94/src/itdb_tzinfo.c 2010-04-05 05:00:15.000000000 +0800
+++ libgpod-0.7.95/src/itdb_tzinfo.c 2010-09-30 00:44:31.000000000 +0800
@@ -47,6 +47,7 @@
static gboolean parse_tzdata (const char *tzname, time_t start, time_t end,
int *offset, gboolean *has_dst, int *dst_offset);
+/* Mac epoch is 1st January 1904 00:00 in local time */
G_GNUC_INTERNAL time_t device_time_mac_to_time_t (Itdb_Device *device, guint64 mactime)
{
g_return_val_if_fail (device, 0);
diff -Nru libgpod-0.7.94/tools/generic-callout.c libgpod-0.7.95/tools/generic-callout.c
--- libgpod-0.7.94/tools/generic-callout.c 2010-08-31 05:40:32.000000000 +0800
+++ libgpod-0.7.95/tools/generic-callout.c 2010-09-30 00:44:31.000000000 +0800
@@ -129,6 +129,7 @@
case ITDB_IPOD_GENERATION_NANO_3:
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
return g_strdup ("nano");
case ITDB_IPOD_GENERATION_VIDEO_1:
case ITDB_IPOD_GENERATION_VIDEO_2:
@@ -140,6 +141,7 @@
case ITDB_IPOD_GENERATION_TOUCH_1:
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
return g_strdup ("touch");
case ITDB_IPOD_GENERATION_IPHONE_1:
case ITDB_IPOD_GENERATION_IPHONE_2:
@@ -196,6 +198,8 @@
return 4.0;
case ITDB_IPOD_GENERATION_NANO_5:
return 5.0;
+ case ITDB_IPOD_GENERATION_NANO_6:
+ return 6.0;
case ITDB_IPOD_GENERATION_VIDEO_1:
return 5.0;
case ITDB_IPOD_GENERATION_VIDEO_2:
@@ -211,6 +215,8 @@
return 2.0;
case ITDB_IPOD_GENERATION_TOUCH_3:
return 3.0;
+ case ITDB_IPOD_GENERATION_TOUCH_4:
+ return 4.0;
case ITDB_IPOD_GENERATION_IPHONE_1:
return 1.0;
case ITDB_IPOD_GENERATION_IPHONE_2:
@@ -386,6 +392,7 @@
case ITDB_IPOD_GENERATION_NANO_4:
case ITDB_IPOD_GENERATION_NANO_5:
+ case ITDB_IPOD_GENERATION_NANO_6:
/* FIXME: set the correct icon name once it's added to
* gnome-icon-theme-extras
*/
@@ -412,6 +419,7 @@
return g_strconcat (prefix, "ipod-touch", NULL);
case ITDB_IPOD_GENERATION_TOUCH_2:
case ITDB_IPOD_GENERATION_TOUCH_3:
+ case ITDB_IPOD_GENERATION_TOUCH_4:
return g_strconcat (prefix, "ipod-touch-2g", NULL);
case ITDB_IPOD_GENERATION_IPHONE_1:
return g_strdup ("phone-apple-iphone");