diff options
author | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2007-03-23 11:58:04 +0000 |
---|---|---|
committer | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2007-03-23 11:58:04 +0000 |
commit | 981d62180356fe0393c49564db37e8e6551da349 (patch) | |
tree | 121729837c9480a3f9f83271e68318664ec8cce0 | |
parent | 381a8506b44322399e05452f88d1ef3ae9f0b58f (diff) | |
download | libgpod-981d62180356fe0393c49564db37e8e6551da349.tar.gz libgpod-981d62180356fe0393c49564db37e8e6551da349.tar.xz libgpod-981d62180356fe0393c49564db37e8e6551da349.zip |
* src/itdb_itunesdb.c: Write out MHOD52 hunks after master
playlist. This speeds up the iPod interface when browsing titles
or albums etc. because the iPod won't have to sort through the
track list.
git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1408 f01d2545-417e-4e96-918e-98f8d0dbbcb6
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | src/itdb_itunesdb.c | 266 |
2 files changed, 266 insertions, 7 deletions
@@ -1,3 +1,10 @@ +2007-03-23 Jorg Schuler <jcsjcs at users.sourceforge.net> + + * src/itdb_itunesdb.c: Write out MHOD52 hunks after master + playlist. This speeds up the iPod interface when browsing titles + or albums etc. because the iPod won't have to sort through the + track list. + 2007-03-22 Jorg Schuler <jcsjcs at users.sourceforge.net> * src/itdb_itunesdb.c (write_playlist): corrected what is written diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c index d08644e..e0b2c0c 100644 --- a/src/itdb_itunesdb.c +++ b/src/itdb_itunesdb.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2007-03-22 22:53:36 jcs> +/* Time-stamp: <2007-03-23 20:49:29 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -220,6 +220,32 @@ enum MHOD_ID { }; +/* Used as first iPod ID when renumbering (re-assigning) the iPod + (track) IDs before writing out the iTunesDB. */ +static const gint FIRST_IPOD_ID=52; + + +enum MHOD52_SORTTYPE { + MHOD52_SORTTYPE_TITLE = 0x03, + MHOD52_SORTTYPE_ALBUM = 0x04, + MHOD52_SORTTYPE_ARTIST = 0x05, + MHOD52_SORTTYPE_GENRE = 0x07, + MHOD52_SORTTYPE_COMPOSER = 0x12 +}; + +struct mhod52track +{ + gchar *album; + gchar *title; + gchar *artist; + gchar *genre; + gchar *composer; + gint track_nr; + gint cd_nr; + gint index; + gint numtracks; +}; + struct _MHODData { gboolean valid; @@ -232,7 +258,12 @@ struct _MHODData Itdb_Track *chapterdata_track; /* for writing chapterdata */ SPLPref *splpref; SPLRules *splrules; + GList *mhod52info; } data; + union + { + enum MHOD52_SORTTYPE mhod52sorttype; + } data2; }; typedef struct _MHODData MHODData; @@ -3667,7 +3698,29 @@ static void mk_mhod (WContents *cts, MHODData *mhod) } break; case MHOD_ID_LIBPLAYLISTINDEX: - g_warning (_("Cannot write mhod of type %d\n"), mhod->type); + g_return_if_fail (mhod->data.mhod52info); + g_return_if_fail (mhod->data.mhod52info->data); + { + struct mhod52track *ct = mhod->data.mhod52info->data; + gint numtracks = ct->numtracks; + GList *gl; + + put_header (cts, "mhod"); /* header */ + put32lint (cts, 24); /* size of header */ + put32lint (cts, 4*numtracks+72); /* size of header + body */ + put32lint (cts, mhod->type); /* type of the mhod */ + put32_n0 (cts, 2); /* unknown */ + /* end of header, start of data */ + put32lint (cts, mhod->data2.mhod52sorttype); /* sort type */ + put32lint (cts, numtracks); /* number of entries */ + put32_n0 (cts, 10); /* unknown */ + for (gl=mhod->data.mhod52info; gl; gl=gl->next) + { + ct = gl->data; + g_return_if_fail (ct); + put32lint (cts, ct->index); + } + } break; } } @@ -4118,6 +4171,182 @@ static gboolean write_podcast_mhips (FExport *fexp, } +static gint mhod52_sort_title (const struct mhod52track *a, const struct mhod52track *b) +{ + return strcmp (a->title, b->title); +} + + +static gint mhod52_sort_album (const struct mhod52track *a, const struct mhod52track *b) +{ + gint result; + + result = strcmp (a->album, b->album); + if (result == 0) + result = a->cd_nr - b->cd_nr; + if (result == 0) + result = a->track_nr - b->track_nr; + if (result == 0) + result = strcmp (a->title, b->title); + return result; +} + +static gint mhod52_sort_artist (struct mhod52track *a, struct mhod52track *b) +{ + gint result; + + result = strcmp (a->artist, b->artist); + if (result == 0) + result = strcmp (a->album, b->album); + if (result == 0) + result = a->cd_nr - b->cd_nr; + if (result == 0) + result = a->track_nr - b->track_nr; + if (result == 0) + result = strcmp (a->title, b->title); + return result; +} + +static gint mhod52_sort_genre (struct mhod52track *a, struct mhod52track *b) +{ + gint result; + + result = strcmp (a->genre, b->genre); + if (result == 0) + result = strcmp (a->artist, b->artist); + if (result == 0) + result = strcmp (a->album, b->album); + if (result == 0) + result = a->cd_nr - b->cd_nr; + if (result == 0) + result = a->track_nr - b->track_nr; + if (result == 0) + result = strcmp (a->title, b->title); + return result; +} + +static gint mhod52_sort_composer (struct mhod52track *a, struct mhod52track *b) +{ + gint result; + + result = strcmp (a->composer, b->composer); + if (result == 0) + result = strcmp (a->title, b->title); + return result; +} + + +/* Create a new list containing all tracks but with collate keys + instead of the actual strings (title, artist, album, genre, + composer) */ +static GList *mhod52_make_collate_keys (GList *tracks) +{ + gint numtracks = g_list_length (tracks); + GList *gl, *coltracks = NULL; + gint index=0; + + for (gl=tracks; gl; gl=gl->next) + { + struct mhod52track *ct; + Itdb_Track *tr = gl->data; + g_return_val_if_fail (tr, NULL); + + ct = g_new0 (struct mhod52track, 1); + coltracks = g_list_prepend (coltracks, ct); + + if (tr->album) + ct->album = g_utf8_collate_key (tr->album, -1); + else + ct->album = g_strdup (""); + if (tr->title) + ct->title = g_utf8_collate_key (tr->title, -1); + else + ct->title = g_strdup (""); + if (tr->artist) + ct->artist = g_utf8_collate_key (tr->artist, -1); + else + ct->artist = g_strdup (""); + if (tr->genre) + ct->genre = g_utf8_collate_key (tr->genre, -1); + else + ct->genre = g_strdup (""); + 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; + ct->index = index++; + } + return coltracks; +} + + +/* Free all memory used up by the collate keys */ +static void mhod52_free_collate_keys (GList *coltracks) +{ + GList *gl; + + for (gl=coltracks; gl; gl=gl->next) + { + struct mhod52track *ct = gl->data; + g_return_if_fail (ct); + g_free (ct->album); + g_free (ct->title); + g_free (ct->artist); + g_free (ct->genre); + g_free (ct->composer); + g_free (ct); + } + g_list_free (coltracks); +} + + +/* Write a MHOD52 containing a sorted list of all tracks. Will change + the order of @coltracks and return the new list! */ +static GList *mk_mhod52 (WContents *cts, GList *coltracks, + enum MHOD52_SORTTYPE sorttype) +{ + MHODData mhod; + + gpointer compfunc = NULL; + + g_return_val_if_fail (cts, coltracks); + + switch (sorttype) + { + case MHOD52_SORTTYPE_TITLE: + compfunc = mhod52_sort_title; + break; + case MHOD52_SORTTYPE_ALBUM: + compfunc = mhod52_sort_album; + break; + case MHOD52_SORTTYPE_ARTIST: + compfunc = mhod52_sort_artist; + break; + case MHOD52_SORTTYPE_GENRE: + compfunc = mhod52_sort_genre; + break; + case MHOD52_SORTTYPE_COMPOSER: + compfunc = mhod52_sort_composer; + break; + } + g_return_val_if_fail (compfunc, coltracks); + + /* sort the tracks */ + coltracks = g_list_sort (coltracks, compfunc); + + /* Write the mhod52 */ + mhod.valid = TRUE; + mhod.type = MHOD_ID_LIBPLAYLISTINDEX; + mhod.data.mhod52info = coltracks; + mhod.data2.mhod52sorttype = sorttype; + mk_mhod (cts, &mhod); + + return coltracks; +} + /* corresponds to mk_mhyp */ /* mhsd_type: 2: write normal playlists @@ -4130,6 +4359,7 @@ static gboolean write_playlist (FExport *fexp, WContents *cts; gboolean result = TRUE; MHODData mhod; + gint mhodnum; g_return_val_if_fail (fexp, FALSE); g_return_val_if_fail (fexp->itdb, FALSE); @@ -4146,10 +4376,19 @@ static gboolean write_playlist (FExport *fexp, put_header (cts, "mhyp"); /* header */ put32lint (cts, 108); /* length */ put32lint (cts, -1); /* size -> later */ + mhodnum = 2; if (pl->is_spl) - put32lint (cts, 4); /* nr of mhods */ + { /* 2 more SPL MHODs */ + mhodnum += 2; + } else - put32lint (cts, 2); /* nr of mhods */ + { + if ((pl->type == ITDB_PL_TYPE_MPL) && pl->members) + { /* 5 more MHOD 52 lists */ + mhodnum += 5; + } + } + put32lint (cts, mhodnum); /* nr of mhods */ /* number of tracks in plist */ put32lint (cts, -1); /* number of mhips -> later */ put8int (cts, pl->type); /* 1 = main, 0 = visible */ @@ -4170,7 +4409,20 @@ static gboolean write_playlist (FExport *fexp, mk_mhod (cts, &mhod); mk_long_mhod_id_playlist (fexp, pl); - if (pl->is_spl) + if ((pl->type == ITDB_PL_TYPE_MPL) && pl->members) + { /* write out the MHOD 52 lists */ + /* We have to sort all tracks five times. To speed this up, + translate the utf8 keys into collate_keys and use the + faster strcmp() for comparison */ + GList *coltracks = mhod52_make_collate_keys (pl->members); + coltracks = mk_mhod52 (cts, coltracks, MHOD52_SORTTYPE_TITLE); + coltracks = mk_mhod52 (cts, coltracks, MHOD52_SORTTYPE_ALBUM); + coltracks = mk_mhod52 (cts, coltracks, MHOD52_SORTTYPE_ARTIST); + coltracks = mk_mhod52 (cts, coltracks, MHOD52_SORTTYPE_GENRE); + coltracks = mk_mhod52 (cts, coltracks, MHOD52_SORTTYPE_COMPOSER); + mhod52_free_collate_keys (coltracks); + } + else if (pl->is_spl) { /* write the smart rules */ mhod.type = MHOD_ID_SPLPREF; mhod.data.splpref = &pl->splpref; @@ -4213,7 +4465,7 @@ static gboolean write_mhsd_playlists (FExport *fexp, guint32 mhsd_type) mk_mhsd (fexp, mhsd_type); /* write header */ /* write header with nr. of playlists */ mk_mhlp (fexp); - for(gl=fexp->itdb->playlists; gl; gl=gl->next) + for (gl=fexp->itdb->playlists; gl; gl=gl->next) { Itdb_Playlist *pl = gl->data; g_return_val_if_fail (pl, FALSE); @@ -4330,7 +4582,7 @@ static void reassign_ids (FExport *fexp) itdb->tracks = g_list_prepend (itdb->tracks, track); } - fexp->next_id = 52; + fexp->next_id = FIRST_IPOD_ID; /* assign unique IDs */ for (gl=itdb->tracks; gl; gl=gl->next) |