From: <ny...@us...> - 2007-02-22 16:17:50
|
Revision: 384 http://svn.sourceforge.net/pmplib/?rev=384&view=rev Author: nyaochi Date: 2007-02-22 08:08:29 -0800 (Thu, 22 Feb 2007) Log Message: ----------- Incremental commit. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/ipod.c trunk/pmplib/lib/pmp_ipod/ipod.h trunk/pmplib/lib/pmp_ipod/itunesdb.c trunk/pmplib/lib/pmp_ipod/itunesdb.h trunk/pmplib/lib/pmp_ipod/pmp_ipod.c Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-21 17:36:23 UTC (rev 383) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-22 16:08:29 UTC (rev 384) @@ -1,5 +1,5 @@ /* - * iPod + * iPod Manupulation library. * * Copyright (c) 2005-2007 Naoaki Okazaki * @@ -32,12 +32,61 @@ #include <string.h> #endif/*HAVE_STRING_H*/ #include <pmplib/ucs2char.h> +#include <pmplib/pmp.h> #include "serialize.h" #include "util.h" #include "ipod.h" #include "itunesdb.h" +#define COMP(a, b) ((a)>(b))-((a)<(b)) + +static const ipod_descriptor_t g_model_descriptions[] = { + { + "apple_ipod", "Apple", "iPod", "UM", + "---", "---", + "iPod_Control\\iTunes\\iTunesDB", + ".mp3\0", + {PMPCODEC_MPEGLAYER3, 0, 0, 0, 0, 0, 0, 0}, + "iPod_Control", "iPod_Control\\Music", "Playlists", + }, + { + NULL, NULL, NULL, NULL, + NULL, NULL, + NULL, + NULL, + {0, 0, 0, 0, 0, 0, 0, 0}, + NULL, NULL, NULL, + }, +}; + +const ipod_descriptor_t* ipod_detect(const ucs2char_t* path_to_device, const char *id) +{ + const ipod_descriptor_t* md = NULL; + + // Find a suitable model for the device. + md = g_model_descriptions; + for (;md->id;++md) { + if (id && *id) { + // Match the device identifier. + if (strcmp(md->id, id) == 0) { + break; + } + } + } + return md->id ? md : NULL; +} + +const ipod_descriptor_t* ipod_next_descriptor(const ipod_descriptor_t* md) +{ + if (md) { + ++md; + return md->id ? md : NULL; + } else { + return g_model_descriptions; + } +} + void ipod_init(ipod_t* ipod) { ipod->itunesdb = calloc(1, sizeof(itunesdb_chunk_t)); @@ -46,6 +95,7 @@ void ipod_finish(ipod_t* ipod) { itunesdb_finish(ipod->itunesdb); + free(ipod->itunesdb); } result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb) @@ -79,3 +129,332 @@ serialize_finish(&sio); return 0; } + +static int set_music_record(itunesdb_chunk_t* mhit, const pmp_music_record_t* rec, uint32_t uid) +{ + itunesdb_chunk_t* mhod = NULL; + chunk_mhit_t* mhit_data = (chunk_mhit_t*)mhit->data; + + mhit_data->uid = uid; + mhit_data->visible = 1; + mhit_data->filetype = 0x4D503320; + mhit_data->type1 = 0x01; + mhit_data->type2 = 0x01; + mhit_data->compilation = 0; + mhit_data->rating = 0; + mhit_data->last_modified = rec->ts_update; + mhit_data->filesize = rec->filesize; + mhit_data->duration = rec->duration * 1000; + mhit_data->track_number = rec->track_number; + mhit_data->total_tracks = 100; + mhit_data->year = 2000; + mhit_data->bitrate = rec->bitrate / 1000; + mhit_data->samplerate = rec->sample_rate; + mhit_data->date_added = rec->ts_import; + mhit_data->dbid = 0; + mhit_data->unk9 = 0xFFFF; + mhit_data->unk14_1 = 12; + mhit_data->is_played = 2; + mhit_data->unk27 = 1; + mhit_data->media_type = 1; + + /* Construct an "mhod" chunk for title. */ + if (rec->title && *rec->title) { + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "title"); + itunesdb_set_mhod_string(mhod, rec->title); + } + } + + /* Construct an "mhod" chunk for artist. */ + if (rec->artist && *rec->artist) { + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "artist"); + itunesdb_set_mhod_string(mhod, rec->artist); + } + } + + /* Construct an "mhod" chunk for album. */ + if (rec->album && *rec->album) { + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "album"); + itunesdb_set_mhod_string(mhod, rec->album); + } + } + + /* Construct an "mhod" chunk for filetype. */ + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "filetype"); + itunesdb_set_mhod_string(mhod, L"MPEG Audio file"); + } + + /* Construct an "mhod" chunk for comment. */ + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "comment"); + itunesdb_set_mhod_string(mhod, L"Some comment"); + } + + /* Construct an "mhod" chunk for location. */ + if (rec->filename && *rec->filename) { + mhod = itunesdb_new_child(mhit); + if (mhod) { + ucs2char_t pathname[MAX_PATH], *p = NULL; + itunesdb_init(mhod, "mhod", "location"); + ucs2cpy(pathname, rec->filename); + for (p = pathname;*p;++p) { + if (*p == PATHCHAR) *p = ':'; + } + itunesdb_set_mhod_string(mhod, pathname); + } + } + + mhit_data->num_children = mhit->num_children; + return 0; +} + +static int comp_title(const void *_x, const void *_y) +{ + const sorted_index_t *xi = (const sorted_index_t*)_x; + const sorted_index_t *yi = (const sorted_index_t*)_y; + const pmp_music_record_t* base = (const pmp_music_record_t*)xi->base; + const pmp_music_record_t* x = &base[xi->index]; + const pmp_music_record_t* y = &base[yi->index]; + + return ucs2cmp(x->title, y->title); +} + +static int comp_album(const void *_x, const void *_y) +{ + int ret = 0; + const sorted_index_t *xi = (const sorted_index_t*)_x; + const sorted_index_t *yi = (const sorted_index_t*)_y; + const pmp_music_record_t* base = (const pmp_music_record_t*)xi->base; + const pmp_music_record_t* x = &base[xi->index]; + const pmp_music_record_t* y = &base[yi->index]; + + ret = ucs2cmp(x->album, y->album); + if (ret == 0) { + ret = COMP(x->track_number, y->track_number); + if (ret == 0) { + return ucs2cmp(x->title, y->title); + } + } + return ret; +} + +static int comp_artist(const void *_x, const void *_y) +{ + int ret = 0; + const sorted_index_t *xi = (const sorted_index_t*)_x; + const sorted_index_t *yi = (const sorted_index_t*)_y; + const pmp_music_record_t* base = (const pmp_music_record_t*)xi->base; + const pmp_music_record_t* x = &base[xi->index]; + const pmp_music_record_t* y = &base[yi->index]; + + ret = ucs2cmp(x->artist, y->artist); + if (ret == 0) { + return comp_album(_x, _y); + } + return ret; +} + +static int comp_genre(const void *_x, const void *_y) +{ + int ret = 0; + const sorted_index_t *xi = (const sorted_index_t*)_x; + const sorted_index_t *yi = (const sorted_index_t*)_y; + const pmp_music_record_t* base = (const pmp_music_record_t*)xi->base; + const pmp_music_record_t* x = &base[xi->index]; + const pmp_music_record_t* y = &base[yi->index]; + + ret = ucs2cmp(x->genre, y->genre); + if (ret == 0) { + return comp_artist(_x, _y); + } + return ret; +} + +static int comp_composer(const void *_x, const void *_y) +{ + int ret = 0; + const sorted_index_t *xi = (const sorted_index_t*)_x; + const sorted_index_t *yi = (const sorted_index_t*)_y; + const pmp_music_record_t* base = (const pmp_music_record_t*)xi->base; + const pmp_music_record_t* x = &base[xi->index]; + const pmp_music_record_t* y = &base[yi->index]; + + ret = ucs2cmp(x->composer, y->composer); + if (ret == 0) { + return ucs2cmp(x->title, y->title); + } + return ret; +} + +static int set_master_playlist(itunesdb_chunk_t* mhyp, const pmp_music_record_t* records, int num_records) +{ + int i; + itunesdb_chunk_t *mhod = NULL, *mhip = NULL; + chunk_mhyp_t* mhyp_data = (chunk_mhyp_t*)mhyp->data; + sorted_index_t* si = (sorted_index_t*)calloc(num_records, sizeof(sorted_index_t)); + + if (!si) { + return 1; + } else { + for (i = 0;i < num_records;++i) { + si[i].base = records; + si[i].index = i; + } + } + + mhyp_data->flag_master = 1; + mhyp_data->id = 0x7520EA5FA870F9EA; + mhyp_data->unk3 = 0; + mhyp_data->unk4 = 1; + mhyp_data->sort_order = 1; + + /* Construct an "mhod" chunk for title. */ + mhod = itunesdb_new_child(mhyp); + if (mhod) { + itunesdb_init(mhod, "mhod", "title"); + itunesdb_set_mhod_string(mhod, L"Nyaopod"); + } + + /* Construct an "mhod" chunk for title index. */ + mhod = itunesdb_new_child(mhyp); + if (mhod) { + itunesdb_init(mhod, "mhod", "index"); + qsort(si, num_records, sizeof(si[0]), comp_title); + itunesdb_set_mhod_index(mhod, 0x03, si, num_records); + } + + /* Construct an "mhod" chunk for album index. */ + mhod = itunesdb_new_child(mhyp); + if (mhod) { + itunesdb_init(mhod, "mhod", "index"); + qsort(si, num_records, sizeof(si[0]), comp_album); + itunesdb_set_mhod_index(mhod, 0x04, si, num_records); + } + + /* Construct an "mhod" chunk for artist index. */ + mhod = itunesdb_new_child(mhyp); + if (mhod) { + itunesdb_init(mhod, "mhod", "index"); + qsort(si, num_records, sizeof(si[0]), comp_artist); + itunesdb_set_mhod_index(mhod, 0x05, si, num_records); + } + + /* Construct an "mhod" chunk for genre index. */ + mhod = itunesdb_new_child(mhyp); + if (mhod) { + itunesdb_init(mhod, "mhod", "index"); + qsort(si, num_records, sizeof(si[0]), comp_genre); + itunesdb_set_mhod_index(mhod, 0x06, si, num_records); + } + + /* Construct an "mhod" chunk for composer index. */ + mhod = itunesdb_new_child(mhyp); + if (mhod) { + itunesdb_init(mhod, "mhod", "index"); + qsort(si, num_records, sizeof(si[0]), comp_composer); + itunesdb_set_mhod_index(mhod, 0x12, si, num_records); + } + + /* End of the series of "mhod" chunks. */ + mhyp_data->num_mhod = mhyp->num_children; + + /* */ + for (i = 0;i < num_records;++i) { + mhip = itunesdb_new_child(mhyp); + if (mhip) { + chunk_mhip_t* mhip_data = NULL; + itunesdb_init(mhip, "mhip", NULL); + mhip_data = (chunk_mhip_t*)mhip->data; + + mhip_data->flag_podcast_group = 0; + mhip_data->track_id = i; + mhip_data->group_id = i + num_records; + + mhod = itunesdb_new_child(mhip); + if (mhod) { + itunesdb_init(mhod, "mhod", "playlist_order"); + itunesdb_set_mhod_playlist_order(mhod, i+1); + } + + mhip_data->num_mhod = mhip->num_children; + } + } + + mhyp_data->num_mhip = mhyp->num_children - mhyp_data->num_mhod; + return 0; +} + +result_t ipod_set(ipod_t* ipod, const pmp_music_record_t* records, int num_records, const pmp_playlist_t* playlists, int num_playlists) +{ + int i; + itunesdb_chunk_t mhbd, *mhsd = NULL; + itunesdb_chunk_t *mhlt = NULL, *mhit = NULL; + itunesdb_chunk_t *mhlp = NULL, *mhyp = NULL; + + /* Construct "mhbd" chunk. */ + itunesdb_init(&mhbd, "mhbd", NULL); + + /* Construct "mhsd" chunk with track type. */ + mhsd = itunesdb_new_child(&mhbd); + if (mhsd) { + chunk_mhsd_t* mhsd_data = NULL; + itunesdb_init(mhsd, "mhsd", NULL); + mhsd_data = (chunk_mhsd_t*)mhsd->data; + mhsd_data->type = 1; /* track type. */ + + /* Construct "mhlt" chunk. */ + mhlt = itunesdb_new_child(mhsd); + if (mhlt) { + itunesdb_init(mhlt, "mhlt", NULL); + mhlt->num_children = num_records; + + /* For all records... */ + for (i = 0;i < num_records;++i) { + const pmp_music_record_t* rec = &records[i]; + + /* Construct "mhit" chunk. */ + mhit = itunesdb_new_child(mhlt); + if (mhit) { + itunesdb_init(mhit, "mhit", NULL); + + /* This will fill "mhit" chunk and create "mhod" chunks. */ + set_music_record(mhit, rec, i); + } + } + } + } + + /* Construct "mhsd" chunk with playlist type. */ + mhsd = itunesdb_new_child(&mhbd); + if (mhsd) { + chunk_mhsd_t* mhsd_data = NULL; + itunesdb_init(mhsd, "mhsd", NULL); + mhsd_data = (chunk_mhsd_t*)mhsd->data; + mhsd_data->type = 2; /* playlist type. */ + + /* Construct "mhlp" chunk. */ + mhlp = itunesdb_new_child(mhsd); + if (mhlp) { + itunesdb_init(mhlp, "mhlp", NULL); + mhlp->num_children = 1; + + mhyp = itunesdb_new_child(mhlp); + if (mhyp) { + chunk_mhyp_t* mhyp_data = NULL; + itunesdb_init(mhyp, "mhyp", NULL); + mhyp_data = (chunk_mhyp_t*)mhyp->data; + + set_master_playlist(mhyp, records, num_records); + } + } + } +} Modified: trunk/pmplib/lib/pmp_ipod/ipod.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-21 17:36:23 UTC (rev 383) +++ trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-22 16:08:29 UTC (rev 384) @@ -1,6 +1,44 @@ +/* + * iPod Manupulation library. + * + * Copyright (c) 2005-2007 Naoaki Okazaki + * + * This library 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 library 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +/* $Id$ */ + #ifndef __IPOD_H__ #define __IPOD_H__ +typedef struct { + const char *id; + const char *manufacturer; + const char *name; + const char *mode; + const char *min_version; + const char *max_version; + const char *itunesdb_filename; + const char *extensions; + uint32_t codecs[8]; + const char *path_to_system; + const char *path_to_music; + const char *path_to_playlist; +} ipod_descriptor_t; + struct tag_itunesdb_chunk; typedef struct tag_itunesdb_chunk itunesdb_chunk_t; @@ -8,6 +46,9 @@ itunesdb_chunk_t* itunesdb; } ipod_t; +const ipod_descriptor_t* ipod_detect(const ucs2char_t* path_to_device, const char *id); +const ipod_descriptor_t* ipod_next_descriptor(const ipod_descriptor_t* md); + void ipod_init(ipod_t* ipod); void ipod_finish(ipod_t* ipod); result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb); Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-21 17:36:23 UTC (rev 383) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-22 16:08:29 UTC (rev 384) @@ -46,16 +46,31 @@ memset(chunk, 0, sizeof(*chunk)); } -static int mhbd_init(itunesdb_chunk_t* chunk, int dataonly) +static int mhbd_init(itunesdb_chunk_t* chunk, int def) { - if (!dataonly) { + chunk_mhbd_t* mhbd = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhbd", 4); chunk->size = sizeof(chunk_mhbd_t) + 12; chunk->overall_size = chunk->size; } - chunk->data = calloc(1, sizeof(chunk_mhbd_t)); - return chunk->data ? 0 : 1; + + mhbd = (chunk_mhbd_t*)calloc(1, sizeof(chunk_mhbd_t)); + if (def && mhbd) { + mhbd->unknown1 = 1; + mhbd->version = 0x13; /* iTunes 7 */ + mhbd->num_children = 0; + mhbd->identifier = 0x8CD2513B66EF2541; + mhbd->unknown2 = 2; + mhbd->unknown3 = 611; + mhbd->unknown4 = 0xBCD054CD8C063208; + mhbd->language[0] = 'j'; + mhbd->language[1] = 'a'; + } + chunk->data = mhbd; + return mhbd ? 0 : 1; } static int mhbd_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) @@ -78,16 +93,24 @@ -static mhsd_init(itunesdb_chunk_t* chunk, int dataonly) +static mhsd_init(itunesdb_chunk_t* chunk, int def) { - if (!dataonly) { + chunk_mhsd_t* mhsd = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhsd", 4); chunk->size = sizeof(chunk_mhsd_t) + 12; chunk->overall_size = chunk->size; } - chunk->data = calloc(1, sizeof(chunk_mhsd_t)); - return chunk->data ? 0 : 1; + + mhsd = (chunk_mhsd_t*)calloc(1, sizeof(chunk_mhsd_t)); + if (mhsd && def) { + mhsd->type = 0; /* Initialize type 0 for now. */ + } + + chunk->data = mhsd; + return mhsd ? 0 : 1; } static int mhsd_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) @@ -102,16 +125,20 @@ -static mhlt_init(itunesdb_chunk_t* chunk, int dataonly) +static mhlt_init(itunesdb_chunk_t* chunk, int def) { - if (!dataonly) { + chunk_mhlt_t* mhlt = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhlt", 4); chunk->size = 0; /* stands for number of children for "mhlt" chunk. */ chunk->overall_size = sizeof(chunk_mhlt_t) + 12; } - chunk->data = calloc(1, sizeof(chunk_mhlt_t)); - return chunk->data ? 0 : 1; + mhlt = (chunk_mhlt_t*)calloc(1, sizeof(chunk_mhlt_t)); + + chunk->data = mhlt; + return mhlt ? 0 : 1; } static int mhlt_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) @@ -125,16 +152,24 @@ -static mhit_init(itunesdb_chunk_t* chunk, int dataonly) +static mhit_init(itunesdb_chunk_t* chunk, int def) { - if (!dataonly) { + chunk_mhit_t* mhit = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhit", 4); chunk->size = sizeof(chunk_mhit_t) + 12; chunk->overall_size = chunk->size; } - chunk->data = calloc(1, sizeof(chunk_mhit_t)); - return chunk->data ? 0 : 1; + + mhit = (chunk_mhit_t*)calloc(1, sizeof(chunk_mhit_t)); + if (mhit && def) { + mhit->visible = 1; /* Visible by default. */ + } + + chunk->data = mhit; + return mhit ? 0 : 1; } static int mhit_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) @@ -221,16 +256,20 @@ -static mhlp_init(itunesdb_chunk_t* chunk, int dataonly) +static mhlp_init(itunesdb_chunk_t* chunk, int def) { - if (!dataonly) { + chunk_mhlp_t* mhlp = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhlp", 4); chunk->size = 0; /* stands for number of children for "mhlt" chunk. */ chunk->overall_size = sizeof(chunk_mhlp_t) + 12; } - chunk->data = calloc(1, sizeof(chunk_mhlp_t)); - return chunk->data ? 0 : 1; + + mhlp = (chunk_mhlp_t*)calloc(1, sizeof(chunk_mhlp_t)); + chunk->data = mhlp; + return mhlp ? 0 : 1; } static int mhlp_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) @@ -244,16 +283,20 @@ -static mhyp_init(itunesdb_chunk_t* chunk, int dataonly) +static mhyp_init(itunesdb_chunk_t* chunk, int def) { - if (dataonly) { + chunk_mhyp_t* mhyp = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhyp", 4); chunk->size = sizeof(chunk_mhyp_t) + 12; chunk->overall_size = chunk->size; } - chunk->data = calloc(1, sizeof(chunk_mhyp_t)); - return chunk->data ? 0 : 1; + + mhyp = (chunk_mhyp_t*)calloc(1, sizeof(chunk_mhyp_t)); + chunk->data = mhyp; + return mhyp ? 0 : 1; } static int mhyp_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) @@ -279,28 +322,32 @@ -static mhip_init(itunesdb_chunk_t* chunk, int dataonly) +static mhip_init(itunesdb_chunk_t* chunk, int def) { - if (!dataonly) { + chunk_mhip_t* mhip = NULL; + + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhip", 4); chunk->size = sizeof(chunk_mhip_t) + 12; chunk->overall_size = chunk->size; } - chunk->data = calloc(1, sizeof(chunk_mhip_t)); - return chunk->data ? 0 : 1; + + mhip = (chunk_mhip_t*)calloc(1, sizeof(chunk_mhip_t)); + chunk->data = mhip; + return mhip ? 0 : 1; } static int mhip_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { - chunk_mhip_t* mhyp = (chunk_mhip_t*)chunk->data; + chunk_mhip_t* mhip = (chunk_mhip_t*)chunk->data; - if (serialize_uint32le(sio, "num_mhod", "%u", &mhyp->num_mhod)) return 1; - if (serialize_uint32le(sio, "flag_podcast_group", "%X", &mhyp->flag_podcast_group)) return 1; - if (serialize_uint32le(sio, "group_id", "%u", &mhyp->group_id)) return 1; - if (serialize_uint32le(sio, "track_id", "%u", &mhyp->track_id)) return 1; - if (serialize_uint32le(sio, "timestamp", "%u", &mhyp->timestamp)) return 1; - if (serialize_uint32le(sio, "podcast_parent", "%u", &mhyp->podcast_parent)) return 1; + if (serialize_uint32le(sio, "num_mhod", "%u", &mhip->num_mhod)) return 1; + if (serialize_uint32le(sio, "flag_podcast_group", "%X", &mhip->flag_podcast_group)) return 1; + if (serialize_uint32le(sio, "group_id", "%u", &mhip->group_id)) return 1; + if (serialize_uint32le(sio, "track_id", "%u", &mhip->track_id)) return 1; + if (serialize_uint32le(sio, "timestamp", "%u", &mhip->timestamp)) return 1; + if (serialize_uint32le(sio, "podcast_parent", "%u", &mhip->podcast_parent)) return 1; return 0; } @@ -448,28 +495,29 @@ return 0; } +static const itunesdb_mhoddecl_t mds[] = { + {1, "title", 0, mhod_string_finish, mhod_string_serialize}, + {2, "location", 0, mhod_string_finish, mhod_string_serialize}, + {3, "album", 0, mhod_string_finish, mhod_string_serialize}, + {4, "artist", 0, mhod_string_finish, mhod_string_serialize}, + {5, "genre", 0, mhod_string_finish, mhod_string_serialize}, + {6, "filetype", 0, mhod_string_finish, mhod_string_serialize}, + {7, "EQ setting", 0, mhod_string_finish, mhod_string_serialize}, + {8, "comment", 0, mhod_string_finish, mhod_string_serialize}, + {9, "category", 0, mhod_string_finish, mhod_string_serialize}, + {12, "composer", 0, mhod_string_finish, mhod_string_serialize}, + {13, "grouping", 0, mhod_string_finish, mhod_string_serialize}, + {14, "description", 0, mhod_string_finish, mhod_string_serialize}, + {15, "podcast_enclosure_url", 0, mhod_url_finish, mhod_url_serialize}, + {16, "podcast_rss_url", 0, mhod_url_finish, mhod_url_serialize}, + {52, "index", 0, mhod_index_finish, mhod_index_serialize}, + {100, "playlist_column", 0x288, mhod_playlist_column_finish, mhod_playlist_column_serialize}, + {100, "playlist_order", 0x2C, mhod_playlist_order_finish, mhod_playlist_order_serialize}, + {0, NULL, 0, NULL}, +}; + static const itunesdb_mhoddecl_t* find_mhoddecl(itunesdb_chunk_t* chunk) { - static const itunesdb_mhoddecl_t mds[] = { - {1, "title", 0, mhod_string_finish, mhod_string_serialize}, - {2, "location", 0, mhod_string_finish, mhod_string_serialize}, - {3, "album", 0, mhod_string_finish, mhod_string_serialize}, - {4, "artist", 0, mhod_string_finish, mhod_string_serialize}, - {5, "genre", 0, mhod_string_finish, mhod_string_serialize}, - {6, "filetype", 0, mhod_string_finish, mhod_string_serialize}, - {7, "EQ setting", 0, mhod_string_finish, mhod_string_serialize}, - {8, "comment", 0, mhod_string_finish, mhod_string_serialize}, - {9, "category", 0, mhod_string_finish, mhod_string_serialize}, - {12, "composer", 0, mhod_string_finish, mhod_string_serialize}, - {13, "grouping", 0, mhod_string_finish, mhod_string_serialize}, - {14, "description", 0, mhod_string_finish, mhod_string_serialize}, - {15, "podcast_enclosure_url", 0, mhod_url_finish, mhod_url_serialize}, - {16, "podcast_rss_url", 0, mhod_url_finish, mhod_url_serialize}, - {52, "index", 0, mhod_index_finish, mhod_index_serialize}, - {100, "playlist_column", 0x288, mhod_playlist_column_finish, mhod_playlist_column_serialize}, - {100, "playlist_order", 0x2C, mhod_playlist_order_finish, mhod_playlist_order_serialize}, - {0, NULL, 0, NULL}, - }; const itunesdb_mhoddecl_t* decl = mds; chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; @@ -484,9 +532,22 @@ return NULL; } -static int mhod_init(itunesdb_chunk_t* chunk, int dataonly) +static const itunesdb_mhoddecl_t* find_mhoddecl_by_name(const char *name) { - if (!dataonly) { + const itunesdb_mhoddecl_t* decl = mds; + + while (decl->name) { + if (strcmp(decl->name, name) == 0) { + return decl; + } + ++decl; + } + return NULL; +} + +static int mhod_init(itunesdb_chunk_t* chunk, int def) +{ + if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhod", 4); chunk->size = 0x18; @@ -529,7 +590,7 @@ } -static const itunesdb_chunkdecl_t* find_chunkdecl(itunesdb_chunk_t* chunk) +static const itunesdb_chunkdecl_t* find_chunkdecl(const int8_t* name) { static const itunesdb_chunkdecl_t cds[] = { {"mhbd", mhbd_init, chunk_finish, mhbd_serialize}, @@ -545,7 +606,7 @@ const itunesdb_chunkdecl_t* decl = cds; while (decl->name) { - if (strncmp(decl->name, chunk->id, 4) == 0) { + if (strncmp(decl->name, name, 4) == 0) { return decl; } ++decl; @@ -553,6 +614,25 @@ return NULL; } +int itunesdb_init(itunesdb_chunk_t* chunk, const char *name, const char *subtype) +{ + const itunesdb_chunkdecl_t* decl = find_chunkdecl((int8_t*)name); + if (decl) { + decl->init(chunk, 1); + if (strncmp(name, "mhod", 4) == 0) { + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + const itunesdb_mhoddecl_t* decl2 = find_mhoddecl_by_name(subtype); + if (decl2) { + chunk->overall_size = decl2->overall_size; + mhod->type = decl2->type; + } + } + return 0; + } else { + return 1; + } +} + void itunesdb_finish(itunesdb_chunk_t* chunk) { uint32_t i; @@ -562,7 +642,7 @@ itunesdb_finish(&chunk->childlen[i]); } - decl = find_chunkdecl(chunk); + decl = find_chunkdecl(chunk->id); if (decl) { decl->finish(chunk); } @@ -588,7 +668,7 @@ fprintf(sio->fp, "overall_size: %d\n", chunk->overall_size); /* Show fields in the chunk data */ - decl = find_chunkdecl(chunk); + decl = find_chunkdecl(chunk->id); if (decl) { decl->serialize(chunk, sio); } else { @@ -627,9 +707,9 @@ if (serialize_uint32le(sio, "overall_size", "%d", &chunk->overall_size)) return 1; /* Read the chunk data if this chunk is 'known' */ - decl = find_chunkdecl(chunk); + decl = find_chunkdecl(chunk->id); if (decl) { - if (decl->init(chunk, 1) == 0) { + if (decl->init(chunk, 0) == 0) { if (decl->serialize(chunk, sio)) return 1; } } @@ -661,7 +741,6 @@ chunk->num_children = 0; chunk->childlen = NULL; while (sio->offset - begin < chunk->overall_size) { - chunk->num_children; chunk->childlen = realloc(chunk->childlen, sizeof(itunesdb_chunk_t) * (chunk->num_children + 1)); memset(&chunk->childlen[chunk->num_children], 0, sizeof(itunesdb_chunk_t)); itunesdb_read(&chunk->childlen[chunk->num_children], sio); @@ -671,3 +750,70 @@ return 0; } + +itunesdb_chunk_t* itunesdb_new_child(itunesdb_chunk_t* chunk) +{ + chunk->childlen = (itunesdb_chunk_t*)realloc( + chunk->childlen, sizeof(itunesdb_chunk_t) * (chunk->num_children + 1)); + if (chunk->childlen) { + itunesdb_chunk_t* child = &chunk->childlen[chunk->num_children]; + memset(child, 0, sizeof(itunesdb_chunk_t)); + ++chunk->num_children; + return child; + } else { + return NULL; + } +} + +int itunesdb_set_mhod_string(itunesdb_chunk_t* chunk, const ucs2char_t* value) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_string_t* str = &mhod->data.str; + + /* Make sure this is an "mhod" chunk. */ + if (strncmp(chunk->id, "mhod", 4) != 0) { + return 1; + } + + /* Store the string value. */ + str->position = 1; + str->size = ucs2len(value) * sizeof(ucs2char_t); + str->unknown = 1; + str->value = ucs2ndup(value, 512); + return 0; +} + +int itunesdb_set_mhod_index(itunesdb_chunk_t* chunk, uint32_t type, sorted_index_t* si, uint32_t n) +{ + uint32_t i; + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_index_t* index = &mhod->data.index; + + /* Make sure this is an "mhod" chunk. */ + if (strncmp(chunk->id, "mhod", 4) != 0) { + return 1; + } + + /* Store the index. */ + index->type = type; + index->num_entries = n; + index->entries = (uint32_t*)calloc(n, sizeof(uint32_t)); + for (i = 0;i < n;++i) { + index->entries[i] = si[i].index; + } + return 0; +} + +int itunesdb_set_mhod_playlist_order(itunesdb_chunk_t* chunk, uint32_t order) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_playlist_order_t* po = &mhod->data.po; + + /* Make sure this is an "mhod" chunk. */ + if (strncmp(chunk->id, "mhod", 4) != 0) { + return 1; + } + + po->position = order; + return 0; +} Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-21 17:36:23 UTC (rev 383) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-22 16:08:29 UTC (rev 384) @@ -237,8 +237,20 @@ int (*serialize)(itunesdb_chunk_t* chunk, serializer_t* sio); } itunesdb_chunkdecl_t; -void itunesdb_finish(itunesdb_chunk_t* mhbd); -int itunesdb_repr(itunesdb_chunk_t* mhbd, size_t index, serializer_t* sio); -int itunesdb_read(itunesdb_chunk_t* mhbd, serializer_t* sio); +typedef struct { + uint32_t index; + const void* base; +} sorted_index_t; +int itunesdb_init(itunesdb_chunk_t* chunk, const char *name, const char *subtype); +itunesdb_chunk_t* itunesdb_new_child(itunesdb_chunk_t* chunk); +void itunesdb_finish(itunesdb_chunk_t* chunk); + +int itunesdb_set_mhod_string(itunesdb_chunk_t* chunk, const ucs2char_t* str); +int itunesdb_set_mhod_index(itunesdb_chunk_t* chunk, uint32_t type, sorted_index_t* si, uint32_t n); +int itunesdb_set_mhod_playlist_order(itunesdb_chunk_t* chunk, uint32_t order); + +int itunesdb_repr(itunesdb_chunk_t* chunk, size_t index, serializer_t* sio); +int itunesdb_read(itunesdb_chunk_t* chunk, serializer_t* sio); + #endif/*__ITUNESDB_H__*/ Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-21 17:36:23 UTC (rev 383) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-22 16:08:29 UTC (rev 384) @@ -47,40 +47,6 @@ typedef struct { - const char *id; - const char *manufacturer; - const char *name; - const char *mode; - const char *min_version; - const char *max_version; - const char *itunesdb_filename; - const char *extensions; - uint32_t codecs[8]; - const char *path_to_system; - const char *path_to_music; - const char *path_to_playlist; -} ipod_descriptor_t; - -static const ipod_descriptor_t g_model_descriptions[] = { - { - "apple_ipod", "Apple", "iPod", "UM", - "---", "---", - "iPod_Control\\iTunes\\iTunesDB", - ".mp3\0", - {PMPCODEC_MPEGLAYER3, 0, 0, 0, 0, 0, 0, 0}, - "iPod_Control", "iPod_Control\\Music", "Playlists", - }, - { - NULL, NULL, NULL, NULL, - NULL, NULL, - NULL, - NULL, - {0, 0, 0, 0, 0, 0, 0, 0}, - NULL, NULL, NULL, - }, -}; - -typedef struct { const ipod_descriptor_t* decl; } pmp_internal_t; @@ -108,18 +74,6 @@ #define COMP(a, b) ((a)>(b))-((a)<(b)) -static char* strip(char *str) -{ - char *p = str + strlen(str) - 1; - while (*str && isspace(*str)) { - str++; - } - while (str <= p && isspace(*p)) { - *p-- = 0; - } - return str; -} - static const char *strcpy_if_empty(char *dst, const char *src) { return *dst ? dst : strcpy(dst, src); @@ -204,31 +158,13 @@ } -static int compare_version(const char *x, const char *y) -{ - char *p = NULL, *q = NULL; - for (;;) { - long a = strtol(x, &p, 10); - long b = strtol(y, &q, 10); - int value = COMP(a, b); - if (value != 0) { - return value; - } - if (!*p || !*q || *p != *q) { - return COMP(*p, *q); - } - x = p+1; - y = q+1; - } -} - PMPIPODAPI result_t pmp_enumerate_devid(pmplib_enumerate_devid_callback_t callback, void *instance) { - const ipod_descriptor_t* md = g_model_descriptions; - for (;md->id;++md) { + const ipod_descriptor_t* md = NULL; + while (md = ipod_next_descriptor(md)) { callback(instance, md->id); } return 0; @@ -249,22 +185,11 @@ *ptr_pmp = 0; // Find a suitable model for the device. - md = g_model_descriptions; - for (;md->id;++md) { - if (id && *id) { - // Match the device identifier. - if (strcmp(md->id, id) == 0) { - // This will fill some members in decl. - //detect_model(path_to_device, md, &info); - set_device_info(id, path_to_device, md, &info); - break; - } - } - } - - if (!md->id) { + md = ipod_detect(path_to_device, id); + if (!md) { return PMPERR_DEVICENOTFOUND; } + set_device_info(id, path_to_device, md, &info); // Allocate PMP class instance. pmp = (pmp_t*)calloc(1, sizeof(pmp_t)); @@ -475,16 +400,16 @@ static uint32_t pmpmusic_close(pmp_music_t* music) { - //ip3db_t ip3db; + ipod_t ipod; result_t ret = 0; pmp_t* pmp = music->pmp; pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; - /* - // Initialize IP3DB. - ip3db_init(&ip3db); + // Initialize ipod library. + ipod_init(&ipod); if (pmp->flag & PMPOF_MUSIC_DB_WRITE) { + /* int i; ucs2char_t dat[MAX_PATH], dic[MAX_PATH], idx[MAX_PATH]; ip3db_music_record_t* records = NULL; @@ -554,10 +479,11 @@ ip3db_record_finish(&ip3db, &records[i]); } free(records); + */ } - ip3db_finish(&ip3db); - */ +exit_this: + ipod_finish(&ipod); return ret; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |