diff options
| author | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2005-09-19 10:30:50 +0000 |
|---|---|---|
| committer | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2005-09-19 10:30:50 +0000 |
| commit | d5215748b2ccd40a92cd3ffbcd1dcf907c797798 (patch) | |
| tree | b98944ba47d504e70fdb04bf7f858c7be365b4d7 /src/db-artwork-parser.c | |
| parent | 4289045ca3ccab8a59754bc68ff150649c381b95 (diff) | |
| download | libgpod-d5215748b2ccd40a92cd3ffbcd1dcf907c797798.tar.gz libgpod-d5215748b2ccd40a92cd3ffbcd1dcf907c797798.tar.xz libgpod-d5215748b2ccd40a92cd3ffbcd1dcf907c797798.zip | |
* applied patch provided by Christophe Fergeau <teuf at gnome.org>
for artwork database support (read-only).
git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1093 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src/db-artwork-parser.c')
| -rw-r--r-- | src/db-artwork-parser.c | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c new file mode 100644 index 0000000..69f3b83 --- /dev/null +++ b/src/db-artwork-parser.c @@ -0,0 +1,398 @@ +/* + * Copyright (C) 2005 Christophe Fergeau + * + * + * The code contained in this file is free software; you can redistribute + * it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this code; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * iTunes and iPod are trademarks of Apple + * + * This product is not supported/written/published by Apple! + * + */ + +#include "itdb.h" +#include "db-artwork-debug.h" +#include "db-artwork-parser.h" +#include "db-image-parser.h" +#include "db-itunes-parser.h" +#include "db-parse-context.h" +/*#include "image-parser.h"*/ + +typedef int (*ParseListItem)(DBParseContext *ctx, Itdb_iTunesDB *db, GError *error); + +static Itdb_Track * +get_song_by_dbid (Itdb_iTunesDB *db, guint64 id) +{ + GList *it; + + for (it = db->tracks; it != NULL; it = it->next) { + Itdb_Track *song; + + song = (Itdb_Track*)it->data; + if (song->dbid == id) { + return song; + } + } + return NULL; +} + + +static int +parse_mhif (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) +{ + MhifHeader *mhif; + + mhif = db_parse_context_get_m_header (ctx, MhifHeader, "mhif"); + if (mhif == NULL) { + return -1; + } + dump_mhif (mhif); + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhif->total_len)); + return 0; +} + +#ifdef DEBUG_ARTWORKDB +static int +parse_mhod_3 (DBParseContext *ctx, GError *error) +{ + MhodHeader *mhod; + MhodHeaderArtworkType3 *mhod3; + + mhod = db_parse_context_get_m_header (ctx, MhodHeader, "mhod"); + if (mhod == NULL) { + return -1; + } + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhod->total_len)); + + if (GINT_FROM_LE (mhod->total_len) < sizeof (MhodHeaderArtworkType3)){ + return -1; + } + mhod3 = (MhodHeaderArtworkType3*)mhod; + dump_mhod_type_3 (mhod3); + if ((GINT_FROM_LE (mhod3->type) & 0xff) != MHOD_TYPE_ALBUM) { + return -1; + } + + return 0; +} +#endif + +#define FULL_THUMB_SIDE_LEN 0x8c +#define NOW_PLAYING_THUMB_SIDE_LEN 0x38 + +static int +parse_mhni (DBParseContext *ctx, iPodSong *song, GError *error) +{ + MhniHeader *mhni; + int width; + int height; + + mhni = db_parse_context_get_m_header (ctx, MhniHeader, "mhni"); + if (mhni == NULL) { + return -1; + } + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhni->total_len)); + + dump_mhni (mhni); +#ifdef DEBUG_ARTWORKDB + { + DBParseContext *mhod_ctx; + + /* No information useful to us in mhod type 3, do not parse + * it in non-debug mode + */ + mhod_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len); + if (mhod_ctx == NULL) { + return -1; + } + parse_mhod_3 (mhod_ctx, NULL); + g_free (mhod_ctx); + } +#else + width = (GINT_FROM_LE (mhni->image_dimensions) & 0xffff0000) >> 16; + height = (GINT_FROM_LE (mhni->image_dimensions) & 0x0000ffff); + + if ((width == FULL_THUMB_SIDE_LEN) || (width == FULL_THUMB_SIDE_LEN)) { + song->full_size_thumbnail = ipod_image_new_from_mhni (mhni, song->itdb->mountpoint); + } else if ((width == NOW_PLAYING_THUMB_SIDE_LEN) || (width == NOW_PLAYING_THUMB_SIDE_LEN)) { + song->now_playing_thumbnail = ipod_image_new_from_mhni (mhni, song->itdb->mountpoint); + } else { + g_print ("Unrecognized image size: %08x\n", + GINT_FROM_LE (mhni->image_dimensions)); + } +#endif + return 0; +} + +static int +parse_mhod (DBParseContext *ctx, iPodSong *song, GError *error) +{ + MhodHeader *mhod; + DBParseContext *mhni_ctx; + + mhod = db_parse_context_get_m_header (ctx, MhodHeader, "mhod"); + if (mhod == NULL) { + return -1; + } + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhod->total_len)); + dump_mhod (mhod); + + if (GINT_FROM_LE (mhod->type) != MHOD_TYPE_LOCATION) { + return -1; + } + + mhni_ctx = db_parse_context_get_sub_context (ctx, ctx->header_len); + if (mhni_ctx == NULL) { + return -1; + } + parse_mhni (mhni_ctx, song, NULL); + g_free (mhni_ctx); + + return 0; +} + + +static int +parse_mhii (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error) +{ + MhiiHeader *mhii; + DBParseContext *mhod_ctx; + int num_children; + off_t cur_offset; + iPodSong *song; + + mhii = db_parse_context_get_m_header (ctx, MhiiHeader, "mhii"); + if (mhii == NULL) { + return -1; + } + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhii->total_len)); + + dump_mhii (mhii); + +#ifdef DEBUG_ARTWORKDB + song = NULL; +#else + song = get_song_by_dbid (db, GINT64_FROM_LE (mhii->song_id)); + if (song == NULL) { + return -1; + } + + song->orig_image = ipod_image_new_from_mhii (mhii); +#endif + + cur_offset = ctx->header_len; + mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + num_children = GINT_FROM_LE (mhii->num_children); + while ((num_children > 0) && (mhod_ctx != NULL)) { + parse_mhod (mhod_ctx, song, NULL); + num_children--; + cur_offset += mhod_ctx->total_len; + g_free (mhod_ctx); + mhod_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + } + + return 0; +} + + +static int +parse_mhl (DBParseContext *ctx, Itdb_iTunesDB *db, GError *error, + const char *id, ParseListItem parse_child) +{ + MhlHeader *mhl; + int num_children; + DBParseContext *mhi_ctx; + off_t cur_offset; + + mhl = db_parse_context_get_m_header (ctx, MhlHeader, id); + if (mhl == NULL) { + return -1; + } + + dump_mhl (mhl, id); + + num_children = GINT_FROM_LE (mhl->num_children); + if (num_children < 0) { + return -1; + } + + cur_offset = ctx->header_len; + mhi_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + while ((num_children > 0) && (mhi_ctx != NULL)) { + if (parse_child != NULL) { + parse_child (mhi_ctx, db, NULL); + } + num_children--; + cur_offset += mhi_ctx->total_len; + g_free (mhi_ctx); + mhi_ctx = db_parse_context_get_sub_context (ctx, cur_offset); + } + + return 0; + +} + + +static int +parse_mhsd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) +{ + MhsdHeader *mhsd; + + mhsd = db_parse_context_get_m_header (ctx, MhsdHeader, "mhsd"); + if (mhsd == NULL) { + return -1; + } + + db_parse_context_set_total_len (ctx, GINT_FROM_LE (mhsd->total_len)); + dump_mhsd (mhsd); + switch (GINT_FROM_LE (mhsd->index)) { + case MHSD_IMAGE_LIST: { + DBParseContext *mhli_context; + mhli_context = db_parse_context_get_next_child (ctx); + parse_mhl (mhli_context, db, NULL, "mhli", parse_mhii); + g_free (mhli_context); + break; + } + case MHSD_ALBUM_LIST: { + DBParseContext *mhla_context; + mhla_context = db_parse_context_get_next_child (ctx); + parse_mhl (mhla_context, db, NULL, "mhla", NULL); + g_free (mhla_context); + break; + } + case MHSD_FILE_LIST: { + DBParseContext *mhlf_context; + mhlf_context = db_parse_context_get_next_child (ctx); + parse_mhl (mhlf_context, db, NULL, "mhlf", parse_mhif); + g_free (mhlf_context); + break; + } + default: + g_warning ("Unexpected mhsd index: %d\n", + GINT_FROM_LE (mhsd->index)); + return -1; + break; + } + + return 0; +} + +/* Database Object */ +static int +parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) +{ + MhfdHeader *mhfd; + DBParseContext *mhsd_context; + unsigned int cur_pos; + + mhfd = db_parse_context_get_m_header (ctx, MhfdHeader, "mhfd"); + if (mhfd == NULL) { + return -1; + } + + /* Sanity check */ + g_assert (GINT_FROM_LE (mhfd->total_len) == ctx->total_len); + dump_mhfd (mhfd); + cur_pos = ctx->header_len; + + mhsd_context = db_parse_context_get_sub_context (ctx, cur_pos); + if (mhsd_context == NULL) { + return -1; + } + parse_mhsd (mhsd_context, db, NULL); + cur_pos += mhsd_context->total_len; + g_free (mhsd_context); + + mhsd_context = db_parse_context_get_sub_context (ctx, cur_pos); + if (mhsd_context == NULL) { + return -1; + } + parse_mhsd (mhsd_context, db, NULL); + cur_pos += mhsd_context->total_len; + g_free (mhsd_context); + + mhsd_context = db_parse_context_get_sub_context (ctx, cur_pos); + if (mhsd_context == NULL) { + return -1; + } + parse_mhsd (mhsd_context, db, NULL); + cur_pos += mhsd_context->total_len; + g_free (mhsd_context); + + return 0; +} + + +G_GNUC_INTERNAL char * +ipod_db_get_artwork_db_path (Itdb_iTunesDB *db) +{ + return g_build_filename (G_DIR_SEPARATOR_S, db->mountpoint, + "iPod_Control", "Artwork", "ArtworkDB", + NULL); +} + + +static char * +ipod_db_get_photo_db_path (const char *mount_point) +{ + g_return_val_if_fail (mount_point != NULL, NULL); + return g_build_filename (G_DIR_SEPARATOR_S, mount_point, + "Photos", "Photo Database", + NULL); +} + + +int +ipod_parse_artwork_db (Itdb_iTunesDB *db) +{ + DBParseContext *ctx; + char *filename; + + filename = ipod_db_get_artwork_db_path (db); + ctx = db_parse_context_new_from_file (filename); + g_free (filename); + if (ctx == NULL) { + goto error; + } + + parse_mhfd (ctx, db, NULL); + g_free (ctx); + return 0; + + error: + /* FIXME: needs to destroy ctx and to release the mmap'ed memory*/ + return -1; +} + +int +ipod_parse_photo_db (const char *mount_point) +{ + DBParseContext *ctx; + char *filename; + + filename = ipod_db_get_photo_db_path (mount_point); + if (filename == NULL) { + return -1; + } + ctx = db_parse_context_new_from_file (filename); + g_free (filename); + if (ctx == NULL) { + return -1; + } + + parse_mhfd (ctx, NULL, NULL); + g_free (ctx); + return 0; +} |
