summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog40
-rw-r--r--docs/reference/tmpl/device.sgml19
-rw-r--r--docs/reference/tmpl/itunesdb-time.sgml7
-rw-r--r--docs/reference/tmpl/libgpod-unused.sgml16
-rw-r--r--docs/reference/tmpl/track.sgml2
-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
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/test-ls.c32
15 files changed, 435 insertions, 181 deletions
diff --git a/ChangeLog b/ChangeLog
index a6038ad..62fbf65 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,43 @@
+2007-04-27 Jorg Schuler <jcsjcs at users.sourceforge.net>
+
+ * 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.
+
+
2007-04-15 Todd Zullinger <tmzullinger at users.sourceforge.net>
* bindings/python/ipod.py: use the mac-style path for
diff --git a/docs/reference/tmpl/device.sgml b/docs/reference/tmpl/device.sgml
index 6ca9191..4323e53 100644
--- a/docs/reference/tmpl/device.sgml
+++ b/docs/reference/tmpl/device.sgml
@@ -27,6 +27,7 @@ These functions are for reading and setting information about the iPod.
@byte_order:
@sysinfo:
@sysinfo_changed:
+@timezone_shift:
<!-- ##### FUNCTION itdb_device_new ##### -->
<para>
@@ -101,24 +102,6 @@ These functions are for reading and setting information about the iPod.
@Returns:
-<!-- ##### FUNCTION itdb_device_supports_artwork ##### -->
-<para>
-
-</para>
-
-@device:
-@Returns:
-
-
-<!-- ##### FUNCTION itdb_device_supports_photo ##### -->
-<para>
-
-</para>
-
-@device:
-@Returns:
-
-
<!-- ##### FUNCTION itdb_info_get_ipod_info_table ##### -->
<para>
diff --git a/docs/reference/tmpl/itunesdb-time.sgml b/docs/reference/tmpl/itunesdb-time.sgml
index 3f75abb..aeee4fb 100644
--- a/docs/reference/tmpl/itunesdb-time.sgml
+++ b/docs/reference/tmpl/itunesdb-time.sgml
@@ -6,7 +6,10 @@ Helper functions to convert between Epoch time and Mac (iPod) time
<!-- ##### SECTION Long_Description ##### -->
<para>
-The functions provide conversion between Epoch time and Mac (iPod) time
+The functions provide conversion between Epoch time and Mac (iPod) time. These
+functions are now obsolete and should no longer be used, libgpod automatically
+converts to/from Epoch time and iPod time when writing/reading the iPod
+databases
</para>
<!-- ##### SECTION See_Also ##### -->
@@ -30,7 +33,7 @@ The functions provide conversion between Epoch time and Mac (iPod) time
</para>
-@mactime:
+@time:
@Returns:
diff --git a/docs/reference/tmpl/libgpod-unused.sgml b/docs/reference/tmpl/libgpod-unused.sgml
index aaf7c7f..ebb16c4 100644
--- a/docs/reference/tmpl/libgpod-unused.sgml
+++ b/docs/reference/tmpl/libgpod-unused.sgml
@@ -153,6 +153,22 @@ iTunesDB
</para>
+<!-- ##### FUNCTION itdb_device_supports_artwork ##### -->
+<para>
+
+</para>
+
+@device:
+@Returns:
+
+<!-- ##### FUNCTION itdb_device_supports_photo ##### -->
+<para>
+
+</para>
+
+@device:
+@Returns:
+
<!-- ##### FUNCTION itdb_file_error_quark ##### -->
<para>
diff --git a/docs/reference/tmpl/track.sgml b/docs/reference/tmpl/track.sgml
index 658d51e..95c2550 100644
--- a/docs/reference/tmpl/track.sgml
+++ b/docs/reference/tmpl/track.sgml
@@ -59,8 +59,8 @@ information about an iPod track.
@volume:
@soundcheck:
@time_added:
-@time_played:
@time_modified:
+@time_played:
@bookmark_time:
@rating:
@playcount:
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
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e77f83b..4d3e89f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,5 +1,5 @@
if HAVE_GDKPIXBUF
-TESTTHUMBS=test-thumbnails test-write-thumbnails test-photos
+TESTTHUMBS=test-thumbnails test-write-thumbnails test-photos get-timezone
test_thumbnails_SOURCES = test-covers.c
test_thumbnails_CFLAGS = $(AM_CFLAGS)
@@ -33,6 +33,8 @@ test_ls_LDADD =
test_init_ipod_SOURCES = test-init-ipod.c
test_init_ipod_LDADD =
+get_timezone_SOURCES = get-timezone.c
+
noinst_PROGRAMS=test-itdb test-ls $(TESTTHUMBS) $(TESTTAGLIB) $(TESTMISC)
INCLUDES=$(LIBGPOD_CFLAGS) -I$(top_srcdir)/src -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\"
diff --git a/tests/test-ls.c b/tests/test-ls.c
index f37bc43..635ce44 100644
--- a/tests/test-ls.c
+++ b/tests/test-ls.c
@@ -37,6 +37,36 @@
#define LOCALDB "/.gtkpod/local_0.itdb"
static void
+display_recently_played (Itdb_iTunesDB *db)
+{
+ Itdb_Playlist *mpl = itdb_playlist_mpl (db);
+ GList *it;
+
+ g_print ("Recently played:\n");
+ for (it = mpl->members; it != NULL; it = it->next) {
+ Itdb_Track *track = (Itdb_Track*)it->data;
+
+ if (track->recent_playcount != 0) {
+ char date[30];
+ time_t track_time = itdb_time_mac_to_host (track->time_played);
+
+ g_print ("%s - %s - %s:\n",
+ track->artist, track->album, track->title);
+ strftime (date, sizeof (date), "%D %H:%M:%S",
+ gmtime (&track_time));
+ g_print ("\tUTC: %s\n", date);
+ strftime (date, sizeof (date), "%D %H:%M:%S",
+ localtime (&track_time));
+ g_print ("\tlocal: %s\n", date);
+ g_print ("track: %ld ", track_time);
+ time (&track_time);
+ g_print ("current: %ld\n", track_time);
+ g_print ("\n");
+ }
+ }
+}
+
+static void
display_track (Itdb_Track *track, const char *prefix)
{
g_print ("%s%s - %s - %s\n", prefix,
@@ -131,6 +161,8 @@ main (int argc, char *argv[])
g_error_free (error);
error = NULL;
}
+
+ display_recently_played (itdb);
}
itdb_free (itdb);