summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJorg Schuler <jcsjcs@users.sourceforge.net>2007-04-27 14:09:59 +0000
committerJorg Schuler <jcsjcs@users.sourceforge.net>2007-04-27 14:09:59 +0000
commit4e34b34b9c9ea5df23548c86da080b700666f00f (patch)
tree3edd7b23d5848a943cfaa9a177800fc8f94f44e4 /src
parent0a8bf8b3ac053452aab77d6842b4f7ae475419e4 (diff)
downloadlibgpod-tmz-4e34b34b9c9ea5df23548c86da080b700666f00f.tar.gz
libgpod-tmz-4e34b34b9c9ea5df23548c86da080b700666f00f.tar.xz
libgpod-tmz-4e34b34b9c9ea5df23548c86da080b700666f00f.zip
* docs/reference/tmpl/device.sgml
docs/reference/tmpl/itunesdb-time.sgml docs/reference/tmpl/libgpod-unused.sgml docs/reference/tmpl/track.sgml src/db-artwork-parser.c src/db-artwork-writer.c src/db-itunes-parser.h src/itdb.h src/itdb_device.c src/itdb_device.h src/itdb_itunesdb.c src/itdb_private.h tests/Makefile.am: Christophe's patch for automatic correction of timestamps depending on which timezone the iPod is set to. ATTENTION DEVELOPERS: as a consequence all exported timestamps are no longer guint32 mac-type timestamps but standard time_t timestamps. This also includes the 64 bit timestamps in smart playlists. The following functions are therefore no longer needed and are deprecated: itdb_time_mac_to_host(), itdb_time_host_to_mac(): simply return the argument without changing it. Argument and return value are now both of type 'time_t'. itunesdb_time_get_mac_time(): returns the seconds passed since Epoch in seconds and is equivalent to time(NULL). These functions may be removed in a future version of libgpod. Programs linking to libgpod may need to be changed slightly if they made any assumptions on the type of timestamps used. This should be obvious through compile-time warnings. tests/test-ls.c: print a list of recently played tracks. git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1417 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src')
-rw-r--r--src/db-artwork-parser.c14
-rw-r--r--src/db-artwork-writer.c17
-rw-r--r--src/db-itunes-parser.h5
-rw-r--r--src/itdb.h28
-rw-r--r--src/itdb_device.c80
-rw-r--r--src/itdb_device.h9
-rw-r--r--src/itdb_itunesdb.c330
-rw-r--r--src/itdb_private.h13
8 files changed, 337 insertions, 159 deletions
diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c
index ecb4ce1..5474458 100644
--- a/src/db-artwork-parser.c
+++ b/src/db-artwork-parser.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 Christophe Fergeau
+ * Copyright (C) 2005-2007 Christophe Fergeau
*
*
* The code contained in this file is free software; you can redistribute
@@ -237,6 +237,8 @@ parse_mhii (DBParseContext *ctx, GError *error)
Itdb_PhotoDB *photodb;
Itdb_iTunesDB *itunesdb;
guint64 dbid;
+ guint64 mactime;
+ Itdb_iTunesDB *itdb = db_get_itunesdb (ctx->db);
mhii = db_parse_context_get_m_header (ctx, MhiiHeader, "mhii");
if (mhii == NULL)
@@ -277,11 +279,11 @@ parse_mhii (DBParseContext *ctx, GError *error)
artwork->unk028 = get_gint32 (mhii->unknown4, ctx->byte_order);
artwork->rating = get_gint32 (mhii->rating, ctx->byte_order);
artwork->unk036 = get_gint32 (mhii->unknown6, ctx->byte_order);
- artwork->creation_date = get_gint32 (mhii->orig_date, ctx->byte_order);
- artwork->digitized_date = get_gint32 (mhii->digitized_date,
- ctx->byte_order);
- artwork->artwork_size = get_gint32 (mhii->orig_img_size,
- ctx->byte_order);
+ mactime = get_gint32 (mhii->orig_date, ctx->byte_order);
+ artwork->creation_date = itdb_time_mac_to_time_t (itdb, mactime);
+ mactime = get_gint32 (mhii->digitized_date, ctx->byte_order);
+ artwork->digitized_date = itdb_time_mac_to_time_t (itdb, mactime);
+ artwork->artwork_size = get_gint32 (mhii->orig_img_size, ctx->byte_order);
if (song)
{
diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c
index ed1e012..f84915a 100644
--- a/src/db-artwork-writer.c
+++ b/src/db-artwork-writer.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 Christophe Fergeau
+ * Copyright (C) 2005-2007 Christophe Fergeau
*
*
* The code contained in this file is free software; you can redistribute
@@ -531,6 +531,8 @@ write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer)
GList *it = NULL;
Itdb_Track *song;
Itdb_Artwork *artwork;
+ guint64 mactime;
+ Itdb_iTunesDB *itdb = db_get_itunesdb (db);
mhii = (MhiiHeader *)init_header (buffer, "mhii", sizeof (MhiiHeader));
if (mhii == NULL) {
@@ -555,11 +557,14 @@ write_mhii (Itdb_DB *db, void *data, iPodBuffer *buffer)
mhii->unknown4 = get_gint32 (artwork->unk028, buffer->byte_order);
mhii->rating = get_gint32 (artwork->rating, buffer->byte_order);
mhii->unknown6 = get_gint32 (artwork->unk036, buffer->byte_order);
- mhii->orig_date = get_guint32 (artwork->creation_date, buffer->byte_order);
- mhii->digitized_date = get_guint32 (artwork->digitized_date,
- buffer->byte_order);
- mhii->orig_img_size = get_gint32 (artwork->artwork_size,
- buffer->byte_order);
+
+ mactime = itdb_time_time_t_to_mac (itdb, artwork->creation_date);
+ mhii->orig_date = get_guint32 (mactime, buffer->byte_order);
+
+ mactime = itdb_time_time_t_to_mac (itdb, artwork->digitized_date);
+ mhii->digitized_date = get_guint32 (mactime, buffer->byte_order);
+
+ mhii->orig_img_size = get_gint32 (artwork->artwork_size, buffer->byte_order);
it = artwork->thumbnails;
num_children = 0;
while (it != NULL) {
diff --git a/src/db-itunes-parser.h b/src/db-itunes-parser.h
index f32b452..74fdd03 100644
--- a/src/db-itunes-parser.h
+++ b/src/db-itunes-parser.h
@@ -1,6 +1,5 @@
-/* Time-stamp: <2007-02-24 21:36:04 jcs>
- *
- * Copyright (C) 2005 Christophe Fergeau
+/*
+ * Copyright (C) 2005-2007 Christophe Fergeau
*
*
* The code contained in this file is free software; you can redistribute
diff --git a/src/itdb.h b/src/itdb.h
index 6ef8a7f..447bb42 100644
--- a/src/itdb.h
+++ b/src/itdb.h
@@ -1,5 +1,5 @@
/*
-| Copyright (C) 2002-2006 Jorg Schuler <jcsjcs at users sourceforge net>
+| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
|
| URL: http://www.gtkpod.org/
@@ -461,10 +461,10 @@ struct _Itdb_Artwork {
gint32 unk028;
guint32 rating; /* Rating from iPhoto * 20 (PhotoDB only) */
gint32 unk036;
- guint32 creation_date; /* Date the image file was created
+ time_t creation_date; /* Date the image file was created
(creation date of image file (Mac type,
PhotoDB only) */
- guint32 digitized_date;/* Date the image was taken (EXIF
+ time_t digitized_date;/* Date the image was taken (EXIF
information, Mac type, PhotoDB only) */
guint32 artwork_size; /* Size in bytes of the original source
image (PhotoDB only -- don't touch in
@@ -554,7 +554,7 @@ struct _Itdb_Playlist
gint num; /* number of tracks in playlist */
GList *members; /* tracks in playlist (Track *) */
gboolean is_spl; /* smart playlist? */
- guint32 timestamp; /* timestamp of playlist creation */
+ time_t timestamp; /* timestamp of playlist creation */
guint64 id; /* playlist ID */
guint32 sortorder; /* How to sort playlist -- see below */
guint32 podcastflag; /* ITDB_PL_FLAG_NORM/_PODCAST */
@@ -694,9 +694,9 @@ struct _Itdb_Track
gint32 year; /* year */
gint32 volume; /* volume adjustment */
guint32 soundcheck; /* volume adjustment "soundcheck" */
- guint32 time_added; /* time when added (Mac type) */
- guint32 time_played; /* time of last play (Mac type) */
- guint32 time_modified; /* time of last modification (Mac type)*/
+ time_t time_added; /* time when added (Mac type) */
+ time_t time_modified; /* time of last modification (Mac type)*/
+ time_t time_played; /* time of last play (Mac type) */
guint32 bookmark_time; /* bookmark set for (AudioBook) in ms */
guint32 rating; /* star rating (stars * RATING_STEP (20)) */
guint32 playcount; /* number of times track was played */
@@ -756,11 +756,9 @@ struct _Itdb_Track
(like WAVE format), 0x1 for Audible. itdb
will try to set this when adding a new track */
guint32 unk132; /* unknown */
- guint32 time_released;/* date/time added to music store? definitely a
- timestamp, always appears to be a time of
- 0700 GMT. For podcasts: release date as
- displayed next to the title in the Podcast
- playlist */
+ time_t time_released;/* date/time added to music store?
+ For podcasts: release date as displayed next to the
+ title in the Podcast playlist */
guint16 unk144; /* unknown, but MP3 songs appear to be always
0x000c, AAC songs are always 0x0033, Audible
files are 0x0029, WAV files are 0x0. itdb
@@ -1111,9 +1109,9 @@ Itdb_Thumb *itdb_thumb_new (void);
gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb);
/* time functions */
-guint64 itdb_time_get_mac_time (void);
-time_t itdb_time_mac_to_host (guint64 mactime);
-guint64 itdb_time_host_to_mac (time_t time);
+time_t itdb_time_get_mac_time (void);
+time_t itdb_time_mac_to_host (time_t time);
+time_t itdb_time_host_to_mac (time_t time);
/* Initialize a blank ipod */
gboolean itdb_init_ipod (const gchar *mountpoint,
diff --git a/src/itdb_device.c b/src/itdb_device.c
index 35836fb..8c5b9fb 100644
--- a/src/itdb_device.c
+++ b/src/itdb_device.c
@@ -1,6 +1,5 @@
-/* Time-stamp: <27-mar-2007 10:09:48 teuf>
-|
-| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+/*
+| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
|
| URL: http://www.gtkpod.org/
@@ -268,6 +267,8 @@ static const Itdb_ArtworkFormat *ipod_artwork_info_table[] = {
};
+static void itdb_device_set_timezone_info (Itdb_Device *device);
+
/* Reset or create the SysInfo hash table */
static void itdb_device_reset_sysinfo (Itdb_Device *device)
{
@@ -328,8 +329,10 @@ void itdb_device_set_mountpoint (Itdb_Device *device, const gchar *mp)
g_free (device->mountpoint);
device->mountpoint = g_strdup (mp);
- if (mp)
+ if (mp) {
itdb_device_read_sysinfo (device);
+ itdb_device_set_timezone_info (device);
+ }
}
@@ -834,3 +837,72 @@ gboolean itdb_device_supports_photo (Itdb_Device *device)
return (it->type != -1);
}
+
+
+/* This function reads the timezone information from the iPod and sets it in
+ * the Itdb_Device structure. If an error occurs, the function returns silently
+ * and the timezone shift is set to 0
+ */
+static void itdb_device_set_timezone_info (Itdb_Device *device)
+{
+ const gchar *p_preferences[] = {"Preferences", NULL};
+ char *dev_path;
+ char *prefs_filename;
+ FILE *f;
+ gint32 timezone;
+ const int GMT_OFFSET = 0x19;
+ int result;
+
+ device->timezone_shift = 0;
+
+ if (device->mountpoint == NULL) {
+ /* Assumes the iPod is in the UTC timezone for those cases */
+ return;
+ }
+
+ dev_path = itdb_get_device_dir (device->mountpoint);
+
+ if (dev_path == NULL) {
+ return ;
+ }
+
+ prefs_filename = itdb_resolve_path (dev_path, p_preferences);
+ g_free (dev_path);
+
+ f = fopen (prefs_filename, "r");
+ if (f == NULL) {
+ g_free (prefs_filename);
+ return;
+ }
+
+ result = fseek (f, 0xB10, SEEK_SET);
+ if (result != 0) {
+ fclose (f);
+ g_free (prefs_filename);
+ return;
+ }
+
+ result = fread (&timezone, sizeof (timezone), 1, f);
+ if (result != 1) {
+ fclose (f);
+ g_free (prefs_filename);
+ return;
+ }
+
+ fclose (f);
+ g_free (prefs_filename);
+
+ timezone = GINT32_FROM_LE (timezone);
+ if ((timezone < 0) || (timezone > (2*12) << 1)) {
+ /* invalid timezone */
+ return;
+ }
+
+ timezone -= GMT_OFFSET;
+
+ device->timezone_shift = (timezone >> 1) * 3600;
+ if (timezone & 1) {
+ /* Adjust for DST */
+ device->timezone_shift += 3600;
+ }
+}
diff --git a/src/itdb_device.h b/src/itdb_device.h
index 0601ea4..bba6f48 100644
--- a/src/itdb_device.h
+++ b/src/itdb_device.h
@@ -1,6 +1,5 @@
-/* Time-stamp: <2006-11-12 23:03:35 jcs>
-|
-| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+/*
+| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
|
| URL: http://www.gtkpod.org/
@@ -71,6 +70,10 @@ struct _Itdb_Device
* in Device/SysInfo */
gboolean sysinfo_changed; /* Has the sysinfo hash been changed by
the user (itdb_set_sysinfo) */
+ gint timezone_shift; /* difference in seconds between the current
+ * timezone and UTC
+ */
+
};
struct _Itdb_ArtworkFormat
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index c2f9bcd..61bfb71 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -1,6 +1,5 @@
-/* Time-stamp: <27-mar-2007 10:06:21 teuf>
-|
-| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+/*
+| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
|
| URL: http://www.gtkpod.org/
@@ -271,7 +270,6 @@ typedef struct _MHODData MHODData;
/* Declarations */
static gboolean itdb_create_directories (Itdb_Device *device, GError **error);
-
/* ID for error domain */
GQuark itdb_file_error_quark (void)
{
@@ -939,6 +937,7 @@ static gboolean playcounts_read (FImport *fimp, FContents *cts)
CHECK_ERROR (fimp, FALSE);
for (i=0; i<entry_num; ++i)
{
+ gint32 mac_time;
struct playcount *playcount = g_new0 (struct playcount, 1);
glong seek = header_length + i*entry_length;
@@ -946,18 +945,10 @@ static gboolean playcounts_read (FImport *fimp, FContents *cts)
CHECK_ERROR (fimp, FALSE);
fimp->playcounts = g_list_append (fimp->playcounts, playcount);
- playcount->playcount = get32lint (cts, seek);
- playcount->time_played = get32lint (cts, seek+4);
+ playcount->playcount = get32lint (cts, seek);
+ mac_time = get32lint (cts, seek+4);
+ playcount->time_played = itdb_time_mac_to_time_t (fimp->itdb, mac_time);
playcount->bookmark_time = get32lint (cts, seek+8);
- /* NOTE:
- *
- * The iPod (firmware 1.3, 2.0, ...?) doesn't seem to use the
- * timezone information correctly -- no matter what you set
- * iPod's timezone to, it will always record as if it were set
- * to UTC -- we need to subtract the difference between
- * current timezone and UTC to get a correct
- * display. -- this should be done by the application were
- * necessary */
/* rating only exists if the entry length is at least 0x10 */
if (entry_length >= 0x10)
@@ -978,7 +969,10 @@ static gboolean playcounts_read (FImport *fimp, FContents *cts)
if (entry_length >= 0x1c)
{
playcount->skipcount = get32lint (cts, seek+20);
- playcount->last_skipped = get32lint (cts, seek+24);
+ mac_time = get32lint (cts, seek+24);
+ playcount->last_skipped = itdb_time_mac_to_time_t (fimp->itdb,
+ mac_time);
+
}
}
return TRUE;
@@ -1297,7 +1291,7 @@ static gint32 get_mhod_type (FContents *cts, glong seek, guint32 *ml)
.playlist_id/.string/.chapterdata/.splp/.splrs
*/
-static MHODData get_mhod (FContents *cts, glong mhod_seek, guint32 *ml)
+static MHODData get_mhod (FImport *fimp, glong mhod_seek, guint32 *ml)
{
gunichar2 *entry_utf16 = NULL;
MHODData result;
@@ -1306,7 +1300,10 @@ static MHODData get_mhod (FContents *cts, glong mhod_seek, guint32 *ml)
gint32 header_length;
guint32 string_type;
gulong seek;
-
+ FContents *cts;
+
+ cts = fimp->fcontents;
+
result.valid = FALSE;
result.type = -1;
g_return_val_if_fail (ml, result);
@@ -1517,6 +1514,19 @@ static MHODData get_mhod (FContents *cts, glong mhod_seek, guint32 *ml)
splr->unk060 = get32bint (cts, seek+60);
splr->unk064 = get32bint (cts, seek+64);
splr->unk068 = get32bint (cts, seek+68);
+
+ if (ft == splft_date) {
+ SPLActionType at;
+ at = itdb_splr_get_action_type (splr);
+ if ((at == splat_range_date) || (at == splat_date)) {
+ Itdb_iTunesDB *itdb = fimp->itdb;
+ splr->fromvalue = itdb_time_mac_to_time_t (itdb,
+ splr->fromvalue);
+ splr->tovalue = itdb_time_mac_to_time_t (itdb,
+ splr->tovalue);
+ }
+ }
+
break;
}
seek += length+4;
@@ -1557,9 +1567,12 @@ static MHODData get_mhod (FContents *cts, glong mhod_seek, guint32 *ml)
UTF8). After use you must free the string with g_free(). Returns
NULL if no string is avaible. *ml is set to -1 in case of error and
cts->error is set appropriately. */
-static gchar *get_mhod_string (FContents *cts, glong seek, guint32 *ml, gint32 *mty)
+static gchar *get_mhod_string (FImport *fimp, glong seek, guint32 *ml, gint32 *mty)
{
MHODData mhoddata;
+ FContents *cts;
+
+ cts = fimp->fcontents;
*mty = get_mhod_type (cts, seek, ml);
if (cts->error) return NULL;
@@ -1585,7 +1598,7 @@ static gchar *get_mhod_string (FContents *cts, glong seek, guint32 *ml, gint32 *
case MHOD_ID_TVNETWORK:
case MHOD_ID_ALBUMARTIST:
case MHOD_ID_KEYWORDS:
- mhoddata = get_mhod (cts, seek, ml);
+ mhoddata = get_mhod (fimp, seek, ml);
if ((*ml != -1) && mhoddata.valid)
return mhoddata.data.string;
else
@@ -1850,7 +1863,7 @@ static glong get_mhip (FImport *fimp, Itdb_Playlist *plitem,
if (mhod_type == MHOD_ID_PLAYLIST)
{
MHODData mhod;
- mhod = get_mhod (cts, mhod_seek, &mhod_len);
+ mhod = get_mhod (fimp, mhod_seek, &mhod_len);
CHECK_ERROR (fimp, -1);
pos = -1;
if (mhod.valid && first_entry)
@@ -1973,6 +1986,7 @@ static glong get_playlist (FImport *fimp, glong mhyp_seek)
plitem->flag2 = get8int (cts, mhyp_seek+22);
plitem->flag3 = get8int (cts, mhyp_seek+23);
plitem->timestamp = get32lint (cts, mhyp_seek+24);
+ plitem->timestamp = itdb_time_mac_to_time_t (fimp->itdb, plitem->timestamp);
plitem->id = get64lint (cts, mhyp_seek+28);
/* plitem->mhodcount = get32lint (cts, mhyp_seek+36); */
/* plitem->libmhodcount = get16lint (cts, mhyp_seek+40);*/
@@ -1996,7 +2010,7 @@ static glong get_playlist (FImport *fimp, glong mhyp_seek)
/* here we could do something about the playlist settings */
break;
case MHOD_ID_TITLE:
- mhod = get_mhod (cts, mhod_seek, &header_len);
+ mhod = get_mhod (fimp, mhod_seek, &header_len);
CHECK_ERROR (fimp, -1);
if (mhod.valid && mhod.data.string)
{
@@ -2007,7 +2021,7 @@ static glong get_playlist (FImport *fimp, glong mhyp_seek)
}
break;
case MHOD_ID_SPLPREF:
- mhod = get_mhod (cts, mhod_seek, &header_len);
+ mhod = get_mhod (fimp, mhod_seek, &header_len);
CHECK_ERROR (fimp, -1);
if (mhod.valid && mhod.data.splpref)
{
@@ -2019,7 +2033,7 @@ static glong get_playlist (FImport *fimp, glong mhyp_seek)
}
break;
case MHOD_ID_SPLRULES:
- mhod = get_mhod (cts, mhod_seek, &header_len);
+ mhod = get_mhod (fimp, mhod_seek, &header_len);
CHECK_ERROR (fimp, -1);
if (mhod.valid && mhod.data.splrules)
{
@@ -2178,6 +2192,8 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
track->compilation = get8int (cts, seek+30);
track->rating = get8int (cts, seek+31);
track->time_modified = get32lint(cts, seek+32); /* time added */
+ track->time_modified = itdb_time_mac_to_time_t (fimp->itdb,
+ track->time_modified);
track->size = get32lint(cts, seek+36); /* file size */
track->tracklen = get32lint(cts, seek+40); /* time */
track->track_nr = get32lint(cts, seek+44); /* track number */
@@ -2194,12 +2210,16 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
track->playcount = get32lint (cts, seek+80); /* playcount */
track->playcount2 = get32lint (cts, seek+84);
track->time_played = get32lint(cts, seek+88);/* last time played */
+ track->time_played = itdb_time_mac_to_time_t (fimp->itdb,
+ track->time_played);
track->cd_nr = get32lint(cts, seek+92); /* CD nr */
track->cds = get32lint(cts, seek+96); /* CD nr of.. */
/* Apple Store/Audible User ID (for DRM'ed files only, set to 0
otherwise). */
track->drm_userid = get32lint (cts, seek+100);
track->time_added = get32lint(cts, seek+104);/* last mod. time */
+ track->time_added = itdb_time_mac_to_time_t (fimp->itdb,
+ track->time_added);
track->bookmark_time = get32lint (cts, seek+108);/*time bookmarked*/
track->dbid = get64lint (cts, seek+112);
track->checked = get8int (cts, seek+120); /*Checked/Unchecked: 0/1*/
@@ -2213,6 +2233,8 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
track->unk132 = get32lint (cts, seek+132);
track->samplerate2 = get32lfloat (cts, seek+136);
track->time_released = get32lint (cts, seek+140);
+ track->time_released = itdb_time_mac_to_time_t (fimp->itdb,
+ track->time_released);
track->unk144 = get16lint (cts, seek+144);
track->unk146 = get16lint (cts, seek+146);
track->unk148 = get32lint (cts, seek+148);
@@ -2222,6 +2244,8 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
{
track->skipcount = get32lint (cts, seek+156);
track->last_skipped = get32lint (cts, seek+160);
+ track->last_skipped = itdb_time_mac_to_time_t (fimp->itdb,
+ track->last_skipped);
track->has_artwork = get8int (cts, seek+164);
track->skip_when_shuffling = get8int (cts, seek+165);
track->remember_playback_position = get8int (cts, seek+166);
@@ -2263,7 +2287,7 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
for (i=0; i<mhod_nums; ++i)
{
- entry_utf8 = get_mhod_string (cts, seek, &zip, &type);
+ entry_utf8 = get_mhod_string (fimp, seek, &zip, &type);
CHECK_ERROR (fimp, -1);
if (entry_utf8 != NULL)
{
@@ -2343,7 +2367,7 @@ static glong get_mhit (FImport *fimp, glong mhit_seek)
case MHOD_ID_CHAPTERDATA:
/* we just read the entire chapterdata info until we
have a better way to parse and represent it */
- mhod = get_mhod (cts, seek, &zip);
+ mhod = get_mhod (fimp, seek, &zip);
if (mhod.valid && mhod.data.chapterdata_raw)
{
track->chapterdata_raw = mhod.data.chapterdata_raw;
@@ -2804,6 +2828,42 @@ static void error_no_control_dir (const gchar *mp, GError **error)
}
#endif
+
+static gboolean
+itdb_parse_internal (Itdb_iTunesDB *itdb, GError **error)
+{
+ FImport *fimp;
+ gboolean success;
+
+ g_return_val_if_fail (itdb->filename != NULL, FALSE);
+
+ fimp = g_new0 (FImport, 1);
+ fimp->itdb = itdb;
+
+ fimp->fcontents = fcontents_read (itdb->filename, error);
+
+ if (fimp->fcontents)
+ {
+ if (playcounts_init (fimp))
+ {
+ if (parse_fimp (fimp))
+ {
+ if (read_OTG_playlists (fimp))
+ {
+ success = TRUE;
+ }
+ }
+ }
+ }
+
+ if (fimp->error)
+ g_propagate_error (error, fimp->error);
+
+ itdb_free_fimp (fimp);
+
+ return success;
+}
+
/**
* itdb_parse:
* @mp: mount point of the iPod (eg "/mnt/ipod) in local encoding
@@ -2823,6 +2883,7 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error)
Itdb_iTunesDB *itdb = NULL;
const gchar *db[] = {"iTunesDB", NULL};
+
itunes_dir = itdb_get_itunes_dir (mp);
if (!itunes_dir)
@@ -2832,13 +2893,24 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error)
}
filename = itdb_resolve_path (itunes_dir, db);
+ if (itdb != NULL) {
+ itdb_set_mountpoint (itdb, mp);
+ }
if (filename)
{
- itdb = itdb_parse_file (filename, error);
+ itdb = itdb_new ();
+
if (itdb)
{
- itdb_set_mountpoint (itdb, mp);
+ gboolean success;
+ itdb_set_mountpoint (itdb, mp);
+ itdb->filename = filename;
+ success = itdb_parse_internal (itdb, error);
+ if (!success) {
+ itdb_free (itdb);
+ itdb = NULL;
+ }
/* We don't test the return value of ipod_parse_artwork_db
* since the database content will be consistent even if
* we fail to get the various thumbnails, we ignore the
@@ -2863,7 +2935,6 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error)
ipod_parse_artwork_db (itdb);
}
- g_free (filename);
}
else
{
@@ -2879,6 +2950,7 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error)
return itdb;
}
+
/**
* itdb_parse_file:
* @filename: path to a file in iTunesDB format
@@ -2887,47 +2959,26 @@ Itdb_iTunesDB *itdb_parse (const gchar *mp, GError **error)
* Same as itunesdb_parse(), but filename is specified directly.
*
* Return value: a newly allocated #Itdb_iTunesDB struct holding the tracks and
- * the playlists present on the iPod at @mp, NULL if @mp isn't an iPod mount
- * point. If non-NULL, the #Itdb_iTunesDB is to be freed with itdb_free() when
- * it's no longer needed
+ * the playlists present in @filename, NULL if @filename isn't a parsable
+ * iTunesDB file. If non-NULL, the #Itdb_iTunesDB is to be freed with
+ * itdb_free() when it's no longer needed
**/
Itdb_iTunesDB *itdb_parse_file (const gchar *filename, GError **error)
{
- FImport *fimp;
Itdb_iTunesDB *itdb;
- gboolean success = FALSE;
+ gboolean success;
g_return_val_if_fail (filename, NULL);
- fimp = g_new0 (FImport, 1);
itdb = itdb_new ();
itdb->filename = g_strdup (filename);
- fimp->itdb = itdb;
-
- fimp->fcontents = fcontents_read (filename, error);
-
- if (fimp->fcontents)
- {
- if (playcounts_init (fimp))
- {
- if (parse_fimp (fimp))
- {
- if (read_OTG_playlists (fimp))
- {
- success = TRUE;
- }
- }
- }
- }
+ success = itdb_parse_internal (itdb, error);
if (!success)
{
itdb_free (itdb);
itdb = NULL;
- if (fimp->error)
- g_propagate_error (error, fimp->error);
}
- itdb_free_fimp (fimp);
return itdb;
}
@@ -3388,6 +3439,7 @@ static void mk_mhlt (FExport *fexp, guint32 num)
/* Write out the mhit header. Size will be written later */
static void mk_mhit (WContents *cts, Itdb_Track *track)
{
+ gint32 mac_time;
g_return_if_fail (cts);
g_return_if_fail (track);
@@ -3403,7 +3455,8 @@ static void mk_mhit (WContents *cts, Itdb_Track *track)
put8int (cts, track->type2);
put8int (cts, track->compilation);
put8int (cts, track->rating);
- put32lint (cts, track->time_modified); /* timestamp */
+ mac_time = itdb_time_time_t_to_mac (track->itdb, track->time_modified);
+ put32lint (cts, mac_time); /* timestamp */
put32lint (cts, track->size); /* filesize */
put32lint (cts, track->tracklen);/* length of track in ms */
put32lint (cts, track->track_nr);/* track number */
@@ -3419,11 +3472,13 @@ static void mk_mhit (WContents *cts, Itdb_Track *track)
put32lint (cts, track->playcount);/* playcount */
track->playcount2 = track->playcount;
put32lint (cts, track->playcount2);
- put32lint (cts, track->time_played); /* last time played */
+ mac_time = itdb_time_time_t_to_mac (track->itdb, track->time_played);
+ put32lint (cts, mac_time); /* last time played */
put32lint (cts, track->cd_nr); /* CD number */
put32lint (cts, track->cds); /* number of CDs */
put32lint (cts, track->drm_userid);
- put32lint (cts, track->time_added); /* timestamp */
+ mac_time = itdb_time_time_t_to_mac (track->itdb, track->time_added);
+ put32lint (cts, mac_time); /* timestamp */
put32lint (cts, track->bookmark_time);
put64lint (cts, track->dbid);
if (track->checked) put8int (cts, 1);
@@ -3435,14 +3490,16 @@ static void mk_mhit (WContents *cts, Itdb_Track *track)
put32lint (cts, track->artwork_size);
put32lint (cts, track->unk132);
put32lfloat (cts, track->samplerate2);
- put32lint (cts, track->time_released);
+ mac_time = itdb_time_time_t_to_mac (track->itdb, track->time_released);
+ put32lint (cts, mac_time);
put16lint (cts, track->unk144);
put16lint (cts, track->unk146);
put32lint (cts, track->unk148);
put32lint (cts, track->unk152);
/* since iTunesDB version 0x0c */
put32lint (cts, track->skipcount);
- put32lint (cts, track->last_skipped);
+ mac_time = itdb_time_time_t_to_mac (track->itdb, track->last_skipped);
+ put32lint (cts, mac_time);
put8int (cts, track->has_artwork);
put8int (cts, track->skip_when_shuffling);
put8int (cts, track->remember_playback_position);
@@ -3626,8 +3683,10 @@ static void mhod52_free_collate_keys (GList *coltracks)
position indicator for MHOD_ID_PLAYLIST
SPLPref for MHOD_ID_SPLPREF
SPLRules for MHOD_ID_SPLRULES */
-static void mk_mhod (WContents *cts, MHODData *mhod)
+static void mk_mhod (FExport *fexp, MHODData *mhod)
{
+ WContents *cts = fexp->wcontents;
+
g_return_if_fail (cts);
g_return_if_fail (mhod->valid);
@@ -3785,7 +3844,7 @@ static void mk_mhod (WContents *cts, MHODData *mhod)
itdb_splr_validate (splr);
put32bint (cts, splr->field);
put32bint (cts, splr->action);
- put32_n0 (cts, 11); /* unknown */
+ put32_n0 (cts, 11); /* unknown */
switch (ft)
{
case splft_string:
@@ -3801,19 +3860,36 @@ static void mk_mhod (WContents *cts, MHODData *mhod)
put_data (cts, (gchar *)entry_utf16, 2*len);
g_free (entry_utf16);
break;
- case splft_int:
case splft_date:
+ case splft_int:
case splft_boolean:
case splft_playlist:
case splft_unknown:
- case splft_binary_and:
+ case splft_binary_and: {
+ guint64 fromvalue;
+ guint64 tovalue;
+
+ fromvalue = splr->fromvalue;
+ tovalue = splr->tovalue;
+
+ if (ft == splft_date) {
+ SPLActionType at;
+ at = itdb_splr_get_action_type (splr);
+ if ((at == splat_range_date) || (at == splat_date)) {
+ Itdb_iTunesDB *itdb = fexp->itdb;
+ fromvalue = itdb_time_time_t_to_mac (itdb,
+ fromvalue);
+ tovalue = itdb_time_time_t_to_mac (itdb, tovalue);
+ }
+ }
+
/* write non-string-type rule */
put32bint (cts, 0x44); /* length of data */
/* data */
- put64bint (cts, splr->fromvalue);
+ put64bint (cts, fromvalue);
put64bint (cts, splr->fromdate);
put64bint (cts, splr->fromunits);
- put64bint (cts, splr->tovalue);
+ put64bint (cts, tovalue);
put64bint (cts, splr->todate);
put64bint (cts, splr->tounits);
put32bint (cts, splr->unk052);
@@ -3823,6 +3899,7 @@ static void mk_mhod (WContents *cts, MHODData *mhod)
put32bint (cts, splr->unk068);
break;
}
+ }
}
/* insert length of mhod junk */
fix_header (cts, header_seek);
@@ -3977,6 +4054,7 @@ static void mk_mhip (FExport *fexp,
put32lint (cts, podcastgroupflag); /* 16 */
put32lint (cts, podcastgroupid); /* 20 */
put32lint (cts, trackid); /* 24 */
+ timestamp = itdb_time_time_t_to_mac (fexp->itdb, timestamp);
put32lint (cts, timestamp); /* 28 */
put32lint (cts, podcastgroupref); /* 32 */
put32_n0 (cts, 10); /* 36 */
@@ -4017,140 +4095,140 @@ static gboolean write_mhsd_tracks (FExport *fexp)
{
mhod.type = MHOD_ID_TITLE;
mhod.data.string = track->title;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->ipod_path && *track->ipod_path)
{
mhod.type = MHOD_ID_PATH;
mhod.data.string = track->ipod_path;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->album && *track->album)
{
mhod.type = MHOD_ID_ALBUM;
mhod.data.string = track->album;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->artist && *track->artist)
{
mhod.type = MHOD_ID_ARTIST;
mhod.data.string = track->artist;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->genre && *track->genre)
{
mhod.type = MHOD_ID_GENRE;
mhod.data.string = track->genre;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->filetype && *track->filetype)
{
mhod.type = MHOD_ID_FILETYPE;
mhod.data.string = track->filetype;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->comment && *track->comment)
{
mhod.type = MHOD_ID_COMMENT;
mhod.data.string = track->comment;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->category && *track->category)
{
mhod.type = MHOD_ID_CATEGORY;
mhod.data.string = track->category;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->composer && *track->composer)
{
mhod.type = MHOD_ID_COMPOSER;
mhod.data.string = track->composer;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->grouping && *track->grouping)
{
mhod.type = MHOD_ID_GROUPING;
mhod.data.string = track->grouping;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->description && *track->description)
{
mhod.type = MHOD_ID_DESCRIPTION;
mhod.data.string = track->description;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->subtitle && *track->subtitle)
{
mhod.type = MHOD_ID_SUBTITLE;
mhod.data.string = track->subtitle;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->tvshow && *track->tvshow)
{
mhod.type = MHOD_ID_TVSHOW;
mhod.data.string = track->tvshow;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->tvepisode && *track->tvepisode)
{
mhod.type = MHOD_ID_TVEPISODE;
mhod.data.string = track->tvepisode;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->tvnetwork && *track->tvnetwork)
{
mhod.type = MHOD_ID_TVNETWORK;
mhod.data.string = track->tvnetwork;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->albumartist && *track->albumartist)
{
mhod.type = MHOD_ID_ALBUMARTIST;
mhod.data.string = track->albumartist;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->keywords && *track->keywords)
{
mhod.type = MHOD_ID_KEYWORDS;
mhod.data.string = track->keywords;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->podcasturl && *track->podcasturl)
{
mhod.type = MHOD_ID_PODCASTURL;
mhod.data.string = track->podcasturl;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->podcastrss && *track->podcastrss)
{
mhod.type = MHOD_ID_PODCASTRSS;
mhod.data.string = track->podcastrss;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
if (track->chapterdata_raw && track->chapterdata_raw_length)
{
mhod.type = MHOD_ID_CHAPTERDATA;
mhod.data.chapterdata_track = track;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
++mhod_num;
}
/* Fill in the missing items of the mhit header */
@@ -4191,7 +4269,7 @@ static gboolean write_playlist_mhips (FExport *fexp,
mhod.valid = TRUE;
mhod.type = MHOD_ID_PLAYLIST;
mhod.data.track_pos = i;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
/* note: with iTunes 4.9 the mhod is counted as a child to
mhip, so we have put the total length of the mhip and mhod
into the mhip header */
@@ -4247,7 +4325,7 @@ void write_one_podcast_group (gpointer key, gpointer value,
mhod.valid = TRUE;
mhod.type = MHOD_ID_TITLE;
mhod.data.string = album;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
fix_header (cts, mhip_seek);
/* write members */
@@ -4263,7 +4341,7 @@ void write_one_podcast_group (gpointer key, gpointer value,
mk_mhip (fexp, 1, 0, mhip_id, track->id, 0, groupid);
mhod.type = MHOD_ID_PLAYLIST;
mhod.data.track_pos = mhip_id;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
fix_header (cts, mhip_seek);
}
}
@@ -4340,6 +4418,7 @@ static gboolean write_playlist (FExport *fexp,
gboolean result = TRUE;
MHODData mhod;
gint mhodnum;
+ guint32 mac_time;
g_return_val_if_fail (fexp, FALSE);
g_return_val_if_fail (fexp->itdb, FALSE);
@@ -4375,7 +4454,8 @@ static gboolean write_playlist (FExport *fexp,
put8int (cts, pl->flag1); /* unknown */
put8int (cts, pl->flag2); /* unknown */
put8int (cts, pl->flag3); /* unknown */
- put32lint (cts, pl->timestamp);/* some timestamp */
+ mac_time = itdb_time_time_t_to_mac (fexp->itdb, pl->timestamp);
+ put32lint (cts, mac_time); /* some timestamp */
put64lint (cts, pl->id); /* 64 bit ID */
put32lint (cts, 0); /* unknown, always 0? */
put16lint (cts, 1); /* string mhod count (1) */
@@ -4386,7 +4466,7 @@ static gboolean write_playlist (FExport *fexp,
mhod.valid = TRUE;
mhod.type = MHOD_ID_TITLE;
mhod.data.string = pl->name;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mk_long_mhod_id_playlist (fexp, pl);
if ((pl->type == ITDB_PL_TYPE_MPL) && pl->members)
@@ -4398,26 +4478,26 @@ static gboolean write_playlist (FExport *fexp,
mhod.type = MHOD_ID_LIBPLAYLISTINDEX;
mhod.data.mhod52coltracks = mhod52_make_collate_keys (pl->members);
mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_TITLE;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_ALBUM;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_ARTIST;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_GENRE;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_COMPOSER;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mhod52_free_collate_keys (mhod.data.mhod52coltracks);
}
else if (pl->is_spl)
{ /* write the smart rules */
mhod.type = MHOD_ID_SPLPREF;
mhod.data.splpref = &pl->splpref;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
mhod.type = MHOD_ID_SPLRULES;
mhod.data.splrules = &pl->splrules;
- mk_mhod (cts, &mhod);
+ mk_mhod (fexp, &mhod);
}
if (itdb_playlist_is_podcasts(pl) && (mhsd_type == 3))
@@ -5820,17 +5900,21 @@ gchar *itdb_get_artworkdb_path (const gchar *mountpoint)
/**
* itdb_time_get_mac_time:
*
- * Gets the current time expressed in 'Mac' unit (ie in number of seconds since
- * 1/1/1904).
+ * Gets the current time in a format appropriate for storing in the libgpod
+ * data structures
*
- * Return value: current time in 'Mac' unit.
+ * Return value: current time
+ *
+ * Deprecated: kept for compatibility with older code, directly use
+ * g_get_current_time() or time(NULL) instead
**/
-guint64 itdb_time_get_mac_time (void)
+time_t itdb_time_get_mac_time (void)
{
GTimeVal time;
g_get_current_time (&time);
- return itdb_time_host_to_mac (time.tv_sec);
+
+ return time.tv_sec;
}
@@ -5838,33 +5922,45 @@ guint64 itdb_time_get_mac_time (void)
* itdb_time_mac_to_host:
* @mactime: time expressed in 'Mac' unit
*
- * Convert a Mac timestamp to host system time stamp -- modify
- * this function if necessary to port to host systems with different
- * start of Epoch.
- * A "0" time will not be converted.
+ * Converts a timestamp from libgpod format to host system timestamp.
*
* Return value: timestamp for the host system
+ *
+ * Deprecated: It's been kept for compatibility with older code, but this
+ * function is now a no-op
**/
-time_t itdb_time_mac_to_host (guint64 mactime)
+time_t itdb_time_mac_to_host (time_t mactime)
{
- if (mactime != 0) return (time_t)(mactime - 2082844800);
- else return (time_t)mactime;
+ return mactime;
}
-
/**
* itdb_time_host_to_mac:
* @time: time expressed in host unit
*
- * Convert host system timestamp to Mac time stamp -- modify
- * this function if necessary to port to host systems with different
- * start of Epoch
+ * Convert host system timestamp to libgpod format timestamp
+ *
+ * Return value: a libgpod timestamp
*
- * Return value: a Mac timestamp
+ * Deprecated: It's been kept for compatibility with older code, but this
+ * function is now a no-op
**/
-guint64 itdb_time_host_to_mac (time_t time)
+time_t itdb_time_host_to_mac (time_t timet)
+{
+ return timet;
+}
+
+time_t itdb_time_mac_to_time_t (Itdb_iTunesDB *db, guint64 mactime)
+{
+ if (mactime != 0) return (time_t)(mactime - 2082844800 - db->device->timezone_shift);
+ else return (time_t)mactime;
+}
+
+guint64 itdb_time_time_t_to_mac (Itdb_iTunesDB *db, time_t timet)
{
- return (guint64)(((gint64)time) + 2082844800);
+ if (timet != 0)
+ return ((guint64)timet) + 2082844800 + db->device->timezone_shift;
+ else return 0;
}
diff --git a/src/itdb_private.h b/src/itdb_private.h
index 1695f22..8fcbcea 100644
--- a/src/itdb_private.h
+++ b/src/itdb_private.h
@@ -1,6 +1,5 @@
-/* Time-stamp: <2007-01-06 20:46:59 jcs>
-|
-| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+/*
+| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
| Part of the gtkpod project.
|
| URL: http://www.gtkpod.org/
@@ -83,12 +82,12 @@ typedef struct
struct playcount {
guint32 playcount;
guint32 skipped; /* skipped (only for Shuffle's iTunesStats */
- guint32 time_played;
+ time_t time_played;
guint32 bookmark_time;
gint32 rating;
gint32 pc_unk16; /* unknown field in Play Counts file */
guint32 skipcount;
- guint32 last_skipped;
+ time_t last_skipped;
gint32 st_unk06; /* unknown field in iTunesStats file */
gint32 st_unk09; /* unknown field in iTunesStats file */
};
@@ -152,4 +151,8 @@ G_GNUC_INTERNAL gint itdb_get_free_photo_id ( Itdb_PhotoDB *db );
G_GNUC_INTERNAL Itdb_iTunesDB *db_get_itunesdb (Itdb_DB *db);
G_GNUC_INTERNAL Itdb_PhotoDB *db_get_photodb (Itdb_DB *db);
G_GNUC_INTERNAL gint itdb_thumb_get_byteorder (ItdbThumbFormat format);
+G_GNUC_INTERNAL time_t itdb_time_mac_to_time_t (Itdb_iTunesDB *db,
+ guint64 mactime);
+G_GNUC_INTERNAL guint64 itdb_time_time_t_to_mac (Itdb_iTunesDB *db,
+ time_t timet);
#endif