diff options
-rw-r--r-- | ChangeLog | 28 | ||||
-rw-r--r-- | docs/reference/tmpl/track.sgml | 11 | ||||
-rw-r--r-- | src/itdb.h | 119 | ||||
-rw-r--r-- | src/itdb_itunesdb.c | 255 | ||||
-rw-r--r-- | src/itdb_track.c | 25 |
5 files changed, 341 insertions, 97 deletions
@@ -1,8 +1,34 @@ 2007-04-28 Jorg Schuler <jcsjcs at users.sourceforge.net> * src/itdb.h: added padding to exported structures so new entries - can be added without loosing backward run-time compatibility. + can be added without loosing backward run-time compatibility. + * docs/reference/tmpl/track.sgml + src/itdb.h + src/itdb_itunesdb.c + src/itdb_track.c: Added the following fields to Itdb_Track: + + sort_artist + sort_title + sort_album + sort_albumartist + sort_composer + sort_tvshow + + These fields can (theoretically) be used to force a certain sort + order on the iPod when displaying by artist, album... + + Even though these fields are present in the iTunesDB, they are + discarded when reading the iTunesDB and applications must always + set them before writing the iTunesDB again. This is to avoid + that the fields 'artist' and 'sort_artist' accidentially get out + of sync. + + libgpod will automatically create a sort_artist key for you if + artist is of the type 'The Artist' and sort_artist is not + set. The sort key used in that case is 'Artist, The' (followed + by five time 0x01), even though sort_artist itself will not be + touched. 2007-04-27 Jorg Schuler <jcsjcs at users.sourceforge.net> diff --git a/docs/reference/tmpl/track.sgml b/docs/reference/tmpl/track.sgml index ffc0028..9f4be02 100644 --- a/docs/reference/tmpl/track.sgml +++ b/docs/reference/tmpl/track.sgml @@ -44,7 +44,12 @@ information about an iPod track. @tvnetwork: @albumartist: @keywords: -@reserved: +@sort_artist: +@sort_title: +@sort_album: +@sort_albumartist: +@sort_composer: +@sort_tvshow: @id: @size: @tracklen: @@ -132,6 +137,10 @@ information about an iPod track. @reserved_int6: @reserved1: @reserved2: +@reserved3: +@reserved4: +@reserved5: +@reserved6: @usertype: @userdata: @userdata_duplicate: @@ -53,7 +53,9 @@ G_BEGIN_DECLS typedef void (* ItdbUserDataDestroyFunc) (gpointer userdata); typedef gpointer (* ItdbUserDataDuplicateFunc) (gpointer userdata); +/* public structures */ typedef struct _Itdb_Device Itdb_Device; +typedef struct _Itdb_IpodInfo Itdb_IpodInfo; typedef struct _Itdb_Artwork Itdb_Artwork; typedef struct _Itdb_Thumb Itdb_Thumb; typedef struct _Itdb_SPLPref Itdb_SPLPref; @@ -64,7 +66,6 @@ typedef struct _Itdb_PhotoDB Itdb_PhotoDB; typedef struct _Itdb_Playlist Itdb_Playlist; typedef struct _Itdb_PhotoAlbum Itdb_PhotoAlbum; typedef struct _Itdb_Track Itdb_Track; -typedef struct _Itdb_IpodInfo Itdb_IpodInfo; /* ------------------------------------------------------------ *\ @@ -124,8 +125,8 @@ struct _Itdb_IpodInfo { iPod from scratch. */ const guint musicdirs; /* reserved for future use */ - const gint reserved_int1; - const gint reserved_int2; + const gint32 reserved_int1; + const gint32 reserved_int2; gconstpointer reserved1; gconstpointer reserved2; }; @@ -698,18 +699,18 @@ typedef enum about the iTunesDB and related files. */ struct _Itdb_Track { - Itdb_iTunesDB *itdb; /* pointer to iTunesDB (for convenience) */ - gchar *title; /* title (utf8) */ - gchar *ipod_path; /* name of file on iPod: uses ":" - instead of "/" */ - gchar *album; /* album (utf8) */ - gchar *artist; /* artist (utf8) */ - gchar *genre; /* genre (utf8) */ - gchar *filetype; /* eg. "MP3-File"...(utf8)*/ - gchar *comment; /* comment (utf8) */ - gchar *category; /* Category for podcast */ - gchar *composer; /* Composer (utf8) */ - gchar *grouping; /* ? (utf8) */ + Itdb_iTunesDB *itdb; /* pointer to iTunesDB (for convenience) */ + gchar *title; /* title (utf8) */ + gchar *ipod_path; /* name of file on iPod: uses ":" instead + of "/" and is relative to mountpoint */ + gchar *album; /* album (utf8) */ + gchar *artist; /* artist (utf8) */ + gchar *genre; /* genre (utf8) */ + gchar *filetype; /* eg. "MP3-File"...(utf8) */ + gchar *comment; /* comment (utf8) */ + gchar *category; /* Category for podcast */ + gchar *composer; /* Composer (utf8) */ + gchar *grouping; /* ? (utf8) */ gchar *description; /* see note for MHOD_ID in itdb_itunesdb.c */ gchar *podcasturl; /* see note for MHOD_ID in itdb_itunesdb.c */ gchar *podcastrss; /* see note for MHOD_ID in itdb_itunesdb.c */ @@ -721,55 +722,75 @@ struct _Itdb_Track gchar *tvnetwork; /* see note for MHOD_ID in itdb_itunesdb.c */ gchar *albumartist; /* see note for MHOD_ID in itdb_itunesdb.c */ gchar *keywords; /* see note for MHOD_ID in itdb_itunesdb.c */ - gchar *reserved; /* will probably be used for artistthe */ +/* the following 6 are new in libgpod 0.5.0... */ + /* You can set these strings to override the standard sortorder + suggested by libgpod. When set they take precedence over the + default 'artist', 'album'... fields. + + When reading the iTunesDB these fields are discarded, so you will + have to set them again before writing the iTunesDB. + + libgpod will automatically create an entry in the iTunesDB (but + not below) for sort_artist if 'artist' is something like "The + Artist" and sort_artist wasn't set by the application. In that + case 'Artist, The' followed by five 0x01 characters is used for + sorting and written to the iTunesDB. Why five 0x01 characters are + added is not completely understood, but analogous to what iTunes + does. libgpod will _not_ change the six fields below, however. */ + gchar *sort_artist; /* artist name (for sorting) */ + gchar *sort_title; /* title (for sorting) */ + gchar *sort_album; /* album (for sorting) */ + gchar *sort_albumartist; /* album artist (for sorting) */ + gchar *sort_composer; /* composer (for sorting) */ + gchar *sort_tvshow; /* tv show (for sorting) */ /* ... to here */ - guint32 id; /* unique ID of track */ - gint32 size; /* size of file in bytes */ - gint32 tracklen; /* Length of track in ms */ - gint32 cd_nr; /* CD number */ - gint32 cds; /* number of CDs */ - gint32 track_nr; /* track number */ - gint32 tracks; /* number of tracks */ - gint32 bitrate; /* bitrate */ - guint16 samplerate; /* samplerate (CD: 44100) */ + guint32 id; /* unique ID of track */ + gint32 size; /* size of file in bytes */ + gint32 tracklen; /* Length of track in ms */ + gint32 cd_nr; /* CD number */ + gint32 cds; /* number of CDs */ + gint32 track_nr; /* track number */ + gint32 tracks; /* number of tracks */ + gint32 bitrate; /* bitrate */ + guint16 samplerate; /* samplerate (CD: 44100) */ guint16 samplerate_low; /* in the iTunesDB the samplerate is multiplied by 0x10000 -- these are the - lower 16 bit, which are usually 0 */ - gint32 year; /* year */ - gint32 volume; /* volume adjustment */ - guint32 soundcheck; /* volume adjustment "soundcheck" */ - 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 */ + lower 16 bit, which are usually 0 */ + gint32 year; /* year */ + gint32 volume; /* volume adjustment */ + guint32 soundcheck; /* volume adjustment "soundcheck" */ + 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 */ guint32 playcount2; /* Also stores the play count of the song. Don't know if it ever differs from the above value. During sync itdb sets playcount2 to the same value as - playcount. */ - guint32 recent_playcount; /* times track was played since last sync */ - gboolean transferred; /* has file been transferred to iPod? */ - gint16 BPM; /* supposed to vary the playback speed */ + playcount. */ + guint32 recent_playcount; /* times track was played since last sync */ + gboolean transferred; /* has file been transferred to iPod? */ + gint16 BPM; /* supposed to vary the playback speed */ guint8 app_rating; /* star rating set by appl. (not * iPod). If the rating set on the iPod and the rating field above differ, the original rating is copied here and the new rating is stored above. */ guint8 type1; /* CBR MP3s and AAC are 0x00, VBR MP3s are - 0x01 */ - guint8 type2; /* MP3s are 0x01, AAC are 0x00 */ + 0x01 */ + guint8 type2; /* MP3s are 0x01, AAC are 0x00 */ guint8 compilation; guint32 starttime; guint32 stoptime; guint8 checked; /* 0x0: checkmark on track is set 0x1: not set */ - guint64 dbid; /* unique database ID */ + guint64 dbid; /* unique database ID */ guint32 drm_userid; /* Apple Store/Audible User ID (for DRM'ed - files only, set to 0 otherwise). */ + files only, set to 0 otherwise). */ guint32 visible; /* If this value is 1, the song is visible on the iPod. All other values cause - the file to be hidden. */ + the file to be hidden. */ guint32 filetype_marker; /* This appears to always be 0 on hard drive based iPods, but for the iTunesDB that is written to an iPod @@ -779,7 +800,7 @@ struct _Itdb_Track 0x4d503320 -> 0x4d = 'M', 0x50 = 'P', 0x33 = '3', 0x20 = <space>. (set to the filename extension by itdb when - copying track to iPod)*/ + copying track to iPod) */ guint16 artwork_count; /* The number of album artwork items associated with this song. libgpod updates this value when syncing */ @@ -788,12 +809,12 @@ struct _Itdb_Track converted to JPEG format. Observed in iPodDB version 0x0b and with an iPod Photo. libgpod updates this value when - syncing */ + syncing */ float samplerate2; /* The sample rate of the song expressed as an IEEE 32 bit floating point number. It's uncertain why this is here. itdb will set this when adding - a track */ + a track */ guint16 unk126; /* unknown, but always seems to be 0xffff for MP3/AAC songs, 0x0 for uncompressed songs @@ -924,6 +945,10 @@ struct _Itdb_Track gint32 reserved_int6; gpointer reserved1; gpointer reserved2; + gpointer reserved3; + gpointer reserved4; + gpointer reserved5; + gpointer reserved6; /* below is for use by application */ guint64 usertype; diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c index 248f3e0..9742bf2 100644 --- a/src/itdb_itunesdb.c +++ b/src/itdb_itunesdb.c @@ -168,46 +168,50 @@ enum MHOD_ID { MHOD_ID_FILETYPE = 6, /* MHOD_ID_EQSETTING = 7, */ MHOD_ID_COMMENT = 8, -/* Category - This is the category ("Technology", "Music", etc.) where - the podcast was located. Introduced in db version 0x0d. */ + /* Category - This is the category ("Technology", "Music", etc.) where + the podcast was located. Introduced in db version 0x0d. */ MHOD_ID_CATEGORY = 9, MHOD_ID_COMPOSER = 12, MHOD_ID_GROUPING = 13, -/* Description text (such as podcast show notes). Accessible by - wselecting the center button on the iPod, where this string is - displayed along with the song title, date, and - timestamp. Introduced in db version 0x0d. */ + /* Description text (such as podcast show notes). Accessible by + wselecting the center button on the iPod, where this string is + displayed along with the song title, date, and + timestamp. Introduced in db version 0x0d. */ MHOD_ID_DESCRIPTION = 14, -/* Podcast Enclosure URL. Note: this is either a UTF-8 or ASCII - encoded string (NOT UTF-16). Also, there is no mhod::length value - for this type. Introduced in db version 0x0d. */ + /* Podcast Enclosure URL. Note: this is either a UTF-8 or ASCII + encoded string (NOT UTF-16). Also, there is no mhod::length value + for this type. Introduced in db version 0x0d. */ MHOD_ID_PODCASTURL = 15, -/* Podcast RSS URL. Note: this is either a UTF-8 or ASCII encoded - string (NOT UTF-16). Also, there is no mhod::length value for this - type. Introduced in db version 0x0d. */ + /* Podcast RSS URL. Note: this is either a UTF-8 or ASCII encoded + string (NOT UTF-16). Also, there is no mhod::length value for this + type. Introduced in db version 0x0d. */ MHOD_ID_PODCASTRSS = 16, -/* Chapter data. This is a m4a-style entry that is used to display - subsongs within a mhit. Introduced in db version 0x0d. */ + /* Chapter data. This is a m4a-style entry that is used to display + subsongs within a mhit. Introduced in db version 0x0d. */ MHOD_ID_CHAPTERDATA = 17, -/* Subtitle (usually the same as Description). Introduced in db - version 0x0d. */ + /* Subtitle (usually the same as Description). Introduced in db + version 0x0d. */ MHOD_ID_SUBTITLE = 18, -/* Show (for TV Shows only). Introduced in db version 0x0d? */ + /* Show (for TV Shows only). Introduced in db version 0x0d? */ MHOD_ID_TVSHOW = 19, -/* Episode # (for TV Shows only). Introduced in db version 0x0d? */ + /* Episode # (for TV Shows only). Introduced in db version 0x0d? */ MHOD_ID_TVEPISODE = 20, -/* TV Network (for TV Shows only). Introduced in db version 0x0d? */ + /* TV Network (for TV Shows only). Introduced in db version 0x0d? */ MHOD_ID_TVNETWORK = 21, -/* Album Artist. Introduced in db version 0x13? */ + /* Album Artist. Introduced in db version 0x13? */ MHOD_ID_ALBUMARTIST = 22, -/* This only seems to appear if the Artist has "The" in front of it - (like "The Monkies") in which case it will be in the format "Artist, - The" and is followed by 5 0x01 UTF-16 characters. Introduced in db - version 0x13? */ -/* MHOD_ID_ARTISTTHE = 23, later */ -/* Appears to be a list of keywords pertaining to a track. Introduced - in db version 0x13? */ + /* Sort key for artist. */ + MHOD_ID_SORT_ARTIST = 23, + /* Appears to be a list of keywords pertaining to a track. Introduced + in db version 0x13? */ MHOD_ID_KEYWORDS = 24, + /* more sort keys, taking precedence over the standard entries if + present */ + MHOD_ID_SORT_TITLE = 27, + MHOD_ID_SORT_ALBUM = 28, + MHOD_ID_SORT_ALBUMARTIST = 29, + MHOD_ID_SORT_COMPOSER = 30, + MHOD_ID_SORT_TVSHOW = 31, MHOD_ID_SPLPREF = 50, /* settings for smart playlist */ MHOD_ID_SPLRULES = 51, /* rules for smart playlist */ MHOD_ID_LIBPLAYLISTINDEX = 52, /* Library Playlist Index */ @@ -1364,6 +1368,12 @@ static MHODData get_mhod (FImport *fimp, glong mhod_seek, guint32 *ml) case MHOD_ID_TVNETWORK: case MHOD_ID_ALBUMARTIST: case MHOD_ID_KEYWORDS: + case MHOD_ID_SORT_ARTIST: + case MHOD_ID_SORT_TITLE: + case MHOD_ID_SORT_ALBUM: + case MHOD_ID_SORT_ALBUMARTIST: + case MHOD_ID_SORT_COMPOSER: + case MHOD_ID_SORT_TVSHOW: /* type of string: 0x02: UTF8, 0x01 or 0x00: UTF16 LE */ string_type = get32lint (cts, seek); xl = get32lint (cts, seek+4); /* length of string */ @@ -1596,6 +1606,12 @@ static gchar *get_mhod_string (FImport *fimp, glong seek, guint32 *ml, gint32 *m case MHOD_ID_TVNETWORK: case MHOD_ID_ALBUMARTIST: case MHOD_ID_KEYWORDS: + case MHOD_ID_SORT_ARTIST: + case MHOD_ID_SORT_TITLE: + case MHOD_ID_SORT_ALBUM: + case MHOD_ID_SORT_ALBUMARTIST: + case MHOD_ID_SORT_COMPOSER: + case MHOD_ID_SORT_TVSHOW: mhoddata = get_mhod (fimp, seek, ml); if ((*ml != -1) && mhoddata.valid) return mhoddata.data.string; @@ -2061,6 +2077,12 @@ static glong get_playlist (FImport *fimp, glong mhyp_seek) case MHOD_ID_ALBUMARTIST: case MHOD_ID_KEYWORDS: case MHOD_ID_CHAPTERDATA: + case MHOD_ID_SORT_ARTIST: + case MHOD_ID_SORT_TITLE: + case MHOD_ID_SORT_ALBUM: + case MHOD_ID_SORT_ALBUMARTIST: + case MHOD_ID_SORT_COMPOSER: + case MHOD_ID_SORT_TVSHOW: /* these are not expected here */ break; case MHOD_ID_LIBPLAYLISTINDEX: @@ -2348,6 +2370,17 @@ static glong get_mhit (FImport *fimp, glong mhit_seek) case MHOD_ID_KEYWORDS: track->keywords = entry_utf8; break; + case MHOD_ID_SORT_ARTIST: + case MHOD_ID_SORT_TITLE: + case MHOD_ID_SORT_ALBUM: + case MHOD_ID_SORT_ALBUMARTIST: + case MHOD_ID_SORT_COMPOSER: + case MHOD_ID_SORT_TVSHOW: + /* we don't read those -- the application has to set + them before each export / libgpod will create the + sort_artist field before each export if not set */ + g_free (entry_utf8); + break; case MHOD_ID_SPLPREF: case MHOD_ID_SPLRULES: case MHOD_ID_LIBPLAYLISTINDEX: @@ -3543,6 +3576,45 @@ static void fix_mhit (WContents *cts, gulong mhit_seek, guint32 mhod_num) put32lint_seek (cts, mhod_num, mhit_seek+12); } +/* Returns: + - track->sort_artist if track->sort_artist is not NULL + + - 'Artist, The' if track->sort_artist is NULL and track->artist of + of type 'The Artist'. + + - NULL if track->sort_artist is NULL and track->artist is not of + type 'The Artist'. + + You must g_free() the returned string */ +static gchar *get_sort_artist (Itdb_Track *track) +{ + g_return_val_if_fail (track, NULL); + + if (track->sort_artist && *track->sort_artist) + { + return g_strdup (track->sort_artist); + } + + if (!(track->artist && *track->artist)) + { + return NULL; + } + + /* check if artist is of type 'The Artist' */ + if (g_ascii_strncasecmp ("The ", track->artist, 4) == 0) + { /* return 'Artist, The', followed by five 0x01 chars + (analogous to iTunes) */ + return g_strdup_printf ("%s, The%c%c%c%c%c", + track->artist+4, + 0x01, 0x01, 0x01, 0x01, 0x01); + } + + return NULL; +} + + + + static gint mhod52_sort_title (const struct mhod52track *a, const struct mhod52track *b) { return strcmp (a->title, b->title); @@ -3619,6 +3691,7 @@ static GList *mhod52_make_collate_keys (GList *tracks) for (gl=tracks; gl; gl=gl->next) { + gchar *str; struct mhod52track *ct; Itdb_Track *tr = gl->data; g_return_val_if_fail (tr, NULL); @@ -3626,26 +3699,74 @@ static GList *mhod52_make_collate_keys (GList *tracks) ct = g_new0 (struct mhod52track, 1); coltracks = g_list_prepend (coltracks, ct); - if (tr->album) + /* album */ + if (tr->sort_album) + { + ct->album = g_utf8_collate_key (tr->sort_album, -1); + } + else if (tr->album) + { ct->album = g_utf8_collate_key (tr->album, -1); + } else + { ct->album = g_strdup (""); - if (tr->title) + } + + /* title */ + if (tr->sort_title) + { + ct->title = g_utf8_collate_key (tr->sort_title, -1); + } + else if (tr->title) + { ct->title = g_utf8_collate_key (tr->title, -1); + } else + { ct->title = g_strdup (""); - if (tr->artist) + } + + /* artist */ + str = get_sort_artist (tr); + if (str) + { + ct->artist = g_utf8_collate_key (str, -1); + g_free (str); + } + else if (tr->artist) + { ct->artist = g_utf8_collate_key (tr->artist, -1); + } else + { ct->artist = g_strdup (""); + } + + /* genre */ if (tr->genre) + { ct->genre = g_utf8_collate_key (tr->genre, -1); + } else + { ct->genre = g_strdup (""); - if (tr->composer) + } + + /* composer */ + if (tr->sort_composer) + { + ct->composer = g_utf8_collate_key (tr->sort_composer, -1); + } + else if (tr->composer) + { ct->composer = g_utf8_collate_key (tr->composer, -1); + } else + { ct->composer = g_strdup (""); + } + ct->track_nr = tr->track_nr; ct->cd_nr = tr->cd_nr; ct->numtracks = numtracks; @@ -3707,6 +3828,12 @@ static void mk_mhod (FExport *fexp, MHODData *mhod) case MHOD_ID_TVNETWORK: case MHOD_ID_ALBUMARTIST: case MHOD_ID_KEYWORDS: + case MHOD_ID_SORT_ARTIST: + case MHOD_ID_SORT_TITLE: + case MHOD_ID_SORT_ALBUM: + case MHOD_ID_SORT_ALBUMARTIST: + case MHOD_ID_SORT_COMPOSER: + case MHOD_ID_SORT_TVSHOW: g_return_if_fail (mhod->data.string); /* normal iTunesDBs seem to take utf16 strings), endian-inversed iTunesDBs seem to take utf8 strings */ @@ -4084,6 +4211,7 @@ static gboolean write_mhsd_tracks (FExport *fexp) guint32 mhod_num = 0; gulong mhit_seek = cts->pos; MHODData mhod; + gchar *str; g_return_val_if_fail (track, FALSE); @@ -4223,6 +4351,50 @@ static gboolean write_mhsd_tracks (FExport *fexp) mk_mhod (fexp, &mhod); ++mhod_num; } + str = get_sort_artist (track); + if (str) + { + mhod.type = MHOD_ID_SORT_ARTIST; + mhod.data.string = str; + mk_mhod (fexp, &mhod); + ++mhod_num; + g_free (str); + } + if (track->sort_title && *track->sort_title) + { + mhod.type = MHOD_ID_SORT_TITLE; + mhod.data.string = track->sort_title; + mk_mhod (fexp, &mhod); + ++mhod_num; + } + if (track->sort_album && *track->sort_album) + { + mhod.type = MHOD_ID_SORT_ALBUM; + mhod.data.string = track->sort_album; + mk_mhod (fexp, &mhod); + ++mhod_num; + } + if (track->sort_albumartist && *track->sort_albumartist) + { + mhod.type = MHOD_ID_SORT_ALBUMARTIST; + mhod.data.string = track->sort_albumartist; + mk_mhod (fexp, &mhod); + ++mhod_num; + } + if (track->sort_composer && *track->sort_composer) + { + mhod.type = MHOD_ID_SORT_COMPOSER; + mhod.data.string = track->sort_composer; + mk_mhod (fexp, &mhod); + ++mhod_num; + } + if (track->sort_tvshow && *track->sort_tvshow) + { + mhod.type = MHOD_ID_SORT_TVSHOW; + mhod.data.string = track->sort_tvshow; + mk_mhod (fexp, &mhod); + ++mhod_num; + } if (track->chapterdata_raw && track->chapterdata_raw_length) { mhod.type = MHOD_ID_CHAPTERDATA; @@ -4617,9 +4789,10 @@ static void wcontents_free (WContents *cts) } -/* reassign the iPod IDs and make sure the itdb->tracks are in the - same order as the mpl */ -static void reassign_ids (FExport *fexp) +/* - reassign the iPod IDs + - make sure the itdb->tracks are in the same order as the mpl +*/ +static void prepare_itdb_for_write (FExport *fexp) { GList *gl; Itdb_iTunesDB *itdb; @@ -4639,18 +4812,20 @@ static void reassign_ids (FExport *fexp) for (gl=g_list_last(mpl->members); gl; gl=gl->prev) { + GList *link; Itdb_Track *track = gl->data; g_return_if_fail (track); - g_return_if_fail (g_list_find (itdb->tracks, track)); + link = g_list_find (itdb->tracks, track); + g_return_if_fail (link); /* move this track to the beginning of itdb_tracks */ - itdb->tracks = g_list_remove (itdb->tracks, track); + itdb->tracks = g_list_delete_link (itdb->tracks, link); itdb->tracks = g_list_prepend (itdb->tracks, track); } fexp->next_id = FIRST_IPOD_ID; - /* assign unique IDs */ + /* assign unique IDs and create sort keys */ for (gl=itdb->tracks; gl; gl=gl->next) { Itdb_Track *track = gl->data; @@ -4706,8 +4881,8 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename, cts->reversed = (itdb->device->byte_order == G_BIG_ENDIAN); - reassign_ids (fexp); - + prepare_itdb_for_write (fexp); + mk_mhbd (fexp, 3); /* three mhsds */ /* write tracklist */ if (write_mhsd_tracks (fexp)) @@ -5009,7 +5184,7 @@ gboolean itdb_shuffle_write_file (Itdb_iTunesDB *itdb, fexp->wcontents = wcontents_new (filename); cts = fexp->wcontents; - reassign_ids (fexp); + prepare_itdb_for_write (fexp); put24bint (cts, itdb_tracks_number (itdb)); put24bint (cts, 0x010600); diff --git a/src/itdb_track.c b/src/itdb_track.c index d7e7933..23cae60 100644 --- a/src/itdb_track.c +++ b/src/itdb_track.c @@ -1,5 +1,5 @@ /* -| 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/ @@ -247,14 +247,15 @@ void itdb_track_free (Itdb_Track *track) g_return_if_fail (track); g_free (track->title); - g_free (track->artist); + g_free (track->ipod_path); g_free (track->album); + g_free (track->artist); g_free (track->genre); - g_free (track->composer); - g_free (track->comment); g_free (track->filetype); - g_free (track->grouping); + g_free (track->comment); g_free (track->category); + g_free (track->composer); + g_free (track->grouping); g_free (track->description); g_free (track->podcasturl); g_free (track->podcastrss); @@ -264,12 +265,20 @@ void itdb_track_free (Itdb_Track *track) g_free (track->tvnetwork); g_free (track->albumartist); g_free (track->keywords); - g_free (track->ipod_path); + g_free (track->sort_artist); + g_free (track->sort_title); + g_free (track->sort_album); + g_free (track->sort_albumartist); + g_free (track->sort_composer); + g_free (track->sort_tvshow); + g_free (track->chapterdata_raw); - itdb_artwork_remove_thumbnails (track->artwork); - g_free (track->artwork); + + itdb_artwork_free (track->artwork); + if (track->userdata && track->userdata_destroy) (*track->userdata_destroy) (track->userdata); + g_free (track); } |