From: <ny...@us...> - 2007-02-23 06:22:53
|
Revision: 385 http://svn.sourceforge.net/pmplib/?rev=385&view=rev Author: nyaochi Date: 2007-02-22 22:22:53 -0800 (Thu, 22 Feb 2007) Log Message: ----------- Memorial commit: implemented the database generation for iPod. It's still in the early stage (lack of MP4 support, MP3 gapless playback, update mode, playlists, etc), but iTunesDB was recognized by iPod and iTunes. 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 trunk/pmplib/lib/pmp_ipod/serialize.c Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 06:22:53 UTC (rev 385) @@ -121,6 +121,22 @@ } } +result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb) +{ + FILE *fp = NULL; + serializer_t sio; + + serialize_init_write(&sio, 0x10000); + itunesdb_write(ipod->itunesdb, &sio); + + fp = ucs2fopen(itunesdb, "wb"); + fwrite(sio.base, 1, sio.offset, fp); + fclose(fp); + + serialize_finish(&sio); + return 0; +} + result_t ipod_dump(ipod_t* ipod, FILE *fpo) { serializer_t sio; @@ -185,6 +201,15 @@ } } + /* Construct an "mhod" chunk for album. */ + if (rec->genre && *rec->genre) { + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "genre"); + itunesdb_set_mhod_string(mhod, rec->genre); + } + } + /* Construct an "mhod" chunk for filetype. */ mhod = itunesdb_new_child(mhit); if (mhod) { @@ -205,7 +230,7 @@ if (mhod) { ucs2char_t pathname[MAX_PATH], *p = NULL; itunesdb_init(mhod, "mhod", "location"); - ucs2cpy(pathname, rec->filename); + ucs2cpy(pathname, rec->filename + 2); for (p = pathname;*p;++p) { if (*p == PATHCHAR) *p = ':'; } @@ -217,6 +242,17 @@ return 0; } +static int comp_string(const ucs2char_t* x, const ucs2char_t*y) +{ + int ret = 0; + if (!x || !*x) { + ret = ((!y || !*y) ? 0 : 1); + } else { + ret = ((!y || !*y) ? -1 : ucs2icmp(x, y)); + } + return ret; +} + static int comp_title(const void *_x, const void *_y) { const sorted_index_t *xi = (const sorted_index_t*)_x; @@ -225,7 +261,7 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - return ucs2cmp(x->title, y->title); + return comp_string(x->title, y->title); } static int comp_album(const void *_x, const void *_y) @@ -237,11 +273,11 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->album, y->album); + ret = comp_string(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 comp_string(x->title, y->title); } } return ret; @@ -256,7 +292,7 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->artist, y->artist); + ret = comp_string(x->artist, y->artist); if (ret == 0) { return comp_album(_x, _y); } @@ -272,7 +308,7 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->genre, y->genre); + ret = comp_string(x->genre, y->genre); if (ret == 0) { return comp_artist(_x, _y); } @@ -288,9 +324,9 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->composer, y->composer); + ret = comp_string(x->composer, y->composer); if (ret == 0) { - return ucs2cmp(x->title, y->title); + return comp_string(x->title, y->title); } return ret; } @@ -396,15 +432,19 @@ 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 *mhbd = NULL, *mhsd = NULL; itunesdb_chunk_t *mhlt = NULL, *mhit = NULL; itunesdb_chunk_t *mhlp = NULL, *mhyp = NULL; + chunk_mhbd_t* mhbd_data = NULL; /* Construct "mhbd" chunk. */ - itunesdb_init(&mhbd, "mhbd", NULL); + mhbd = (itunesdb_chunk_t*)calloc(1, sizeof(itunesdb_chunk_t)); + memset(mhbd, 0, sizeof(*mhbd)); + itunesdb_init(mhbd, "mhbd", NULL); + mhbd_data = (chunk_mhbd_t*)mhbd->data; /* Construct "mhsd" chunk with track type. */ - mhsd = itunesdb_new_child(&mhbd); + mhsd = itunesdb_new_child(mhbd); if (mhsd) { chunk_mhsd_t* mhsd_data = NULL; itunesdb_init(mhsd, "mhsd", NULL); @@ -415,7 +455,6 @@ 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) { @@ -434,7 +473,7 @@ } /* Construct "mhsd" chunk with playlist type. */ - mhsd = itunesdb_new_child(&mhbd); + mhsd = itunesdb_new_child(mhbd); if (mhsd) { chunk_mhsd_t* mhsd_data = NULL; itunesdb_init(mhsd, "mhsd", NULL); @@ -445,7 +484,6 @@ mhlp = itunesdb_new_child(mhsd); if (mhlp) { itunesdb_init(mhlp, "mhlp", NULL); - mhlp->num_children = 1; mhyp = itunesdb_new_child(mhlp); if (mhyp) { @@ -457,4 +495,9 @@ } } } + + mhbd_data->num_children = mhbd->num_children; + + ipod->itunesdb = mhbd; + return 0; } Modified: trunk/pmplib/lib/pmp_ipod/ipod.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-23 06:22:53 UTC (rev 385) @@ -24,6 +24,8 @@ #ifndef __IPOD_H__ #define __IPOD_H__ +#include <pmplib/pmp.h> + typedef struct { const char *id; const char *manufacturer; @@ -51,7 +53,9 @@ void ipod_init(ipod_t* ipod); void ipod_finish(ipod_t* ipod); +result_t ipod_set(ipod_t* ipod, const pmp_music_record_t* records, int num_records, const pmp_playlist_t* playlists, int num_playlists); result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb); +result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb); result_t ipod_dump(ipod_t* ipod, FILE *fpo); #endif/*__IPOD_H__*/ Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-23 06:22:53 UTC (rev 385) @@ -53,7 +53,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhbd", 4); - chunk->size = sizeof(chunk_mhbd_t) + 12; + chunk->size = 104; chunk->overall_size = chunk->size; } @@ -100,7 +100,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhsd", 4); - chunk->size = sizeof(chunk_mhsd_t) + 12; + chunk->size = 96; chunk->overall_size = chunk->size; } @@ -132,8 +132,8 @@ 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->size = 92; + chunk->overall_size = 0; /* stands for number of children for "mhlt" chunk. */ } mhlt = (chunk_mhlt_t*)calloc(1, sizeof(chunk_mhlt_t)); @@ -159,7 +159,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhit", 4); - chunk->size = sizeof(chunk_mhit_t) + 12; + chunk->size = 328; chunk->overall_size = chunk->size; } @@ -263,8 +263,8 @@ 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->size = 92; + chunk->overall_size = 0; } mhlp = (chunk_mhlp_t*)calloc(1, sizeof(chunk_mhlp_t)); @@ -290,7 +290,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhyp", 4); - chunk->size = sizeof(chunk_mhyp_t) + 12; + chunk->size = 108; chunk->overall_size = chunk->size; } @@ -329,7 +329,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhip", 4); - chunk->size = sizeof(chunk_mhip_t) + 12; + chunk->size = 76; chunk->overall_size = chunk->size; } @@ -550,7 +550,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhod", 4); - chunk->size = 0x18; + chunk->size = 24; chunk->overall_size = chunk->size; } chunk->data = calloc(1, sizeof(chunk_mhod_t)); @@ -751,6 +751,53 @@ return 0; } +int itunesdb_write(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + uint32_t i, offset = 0; + uint8_t zero = 0; + const itunesdb_chunkdecl_t* decl = NULL; + + /* Store the offset position of this chunk for the future use of rewind. */ + chunk->offset = serialize_tell(sio); + + /* Write the chunk ID and header information. The overall_size may be incorrect at this moment. */ + if (serialize_uint8_array(sio, "id", "%c ", chunk->id, sizeof(chunk->id))) return 1; + if (serialize_uint32le(sio, "size", "%d", &chunk->size)) return 1; + if (serialize_uint32le(sio, "overall_size", "%d", &chunk->overall_size)) return 1; + + /* Write the chunk data if this chunk is 'known' */ + decl = find_chunkdecl(chunk->id); + if (decl) { + if (decl->serialize(chunk, sio)) return 1; + } + + /* Pad 0x00 in the rest of file header. */ + for (i = serialize_tell(sio);i < chunk->offset + chunk->size;++i) { + serialize_uint8(sio, NULL, NULL, &zero); + } + + /* Write children for this chunk. */ + for (i = 0;i < chunk->num_children;++i) { + itunesdb_write(&chunk->childlen[i], sio); + } + + /* Calculate chunk->overall_size. */ + if (strncmp(chunk->id, "mhlt", 4) == 0 || strncmp(chunk->id, "mhlp", 4) == 0) { + /* chunk->overall_size represents the number of children for "mhlt" and "mhlp" chunks */ + chunk->overall_size = chunk->num_children; + } else { + /* chunk->overall_size represents the size in bytes of this chunk */ + chunk->overall_size = serialize_tell(sio) - chunk->offset; + } + + offset = serialize_tell(sio); + serialize_seek(sio, chunk->offset + 2 * sizeof(uint32_t)); + if (serialize_uint32le(sio, "overall_size", "%d", &chunk->overall_size)) return 1; + serialize_seek(sio, offset); + + return 0; +} + itunesdb_chunk_t* itunesdb_new_child(itunesdb_chunk_t* chunk) { chunk->childlen = (itunesdb_chunk_t*)realloc( Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-23 06:22:53 UTC (rev 385) @@ -252,5 +252,6 @@ int itunesdb_repr(itunesdb_chunk_t* chunk, size_t index, serializer_t* sio); int itunesdb_read(itunesdb_chunk_t* chunk, serializer_t* sio); +int itunesdb_write(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-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-23 06:22:53 UTC (rev 385) @@ -404,82 +404,18 @@ result_t ret = 0; pmp_t* pmp = music->pmp; pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + ucs2char_t itunesdb[MAX_PATH]; // 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; + // Read the music database. + set_filenames(itunesdb, music->pmp); - // Allocate an array of music records. - records = (ip3db_music_record_t*)malloc(sizeof(ip3db_music_record_t) * pmpmi->num_records); - - // Build an array of IP3DB records. - for (i = 0;i < pmpmi->num_records;++i) { - const pmp_music_record_t* src = &pmpmi->records[i]; - ip3db_variant_t* dst = records[i]; - - ip3db_record_init(&ip3db, &records[i]); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_FILEPATH], filepath_changeroot(src->filename, pmp->info.path_to_root)); - filepath_remove_filespec(dst[IP3DBF_MUSIC_FILEPATH].value.str); - filepath_addslash(dst[IP3DBF_MUSIC_FILEPATH].value.str); - filepath_slash(dst[IP3DBF_MUSIC_FILEPATH].value.str); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_FILENAME], filepath_skippath(src->filename)); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_ARTIST], src->artist); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_ALBUM], src->album); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_GENRE], src->genre); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_TITLE], src->title); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_DURATION], src->duration); - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_RATING], (uint16_t)src->rating); - switch (src->codec) { - case PMPCODEC_MPEGLAYER3: - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 0); - break; - case PMPCODEC_VORBIS: - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 3); - break; - case PMPCODEC_WMA: - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 5); - break; - } - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_TRACKNUMBER], (uint16_t)src->track_number); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_BITRATE], src->bitrate); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_CLUSA], src->ts_update); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_UID], (uint32_t)i+1); - } - - // Register records (and playlists) to the database. - if (pmp->flag & PMPOF_MUSIC_PL_WRITE) { - ip3db_set( - &ip3db, - (const ip3db_music_record_t*)records, - pmpmi->num_records, - pmpmi->playlists, - pmpmi->num_playlists - ); - } else { - ip3db_set( - &ip3db, - (const ip3db_music_record_t*)records, - pmpmi->num_records, - NULL, - 0 - ); - } - - // Write out the music database. - set_filenames(dat, dic, idx, pmp); - ret = ip3db_write(&ip3db, dat, dic, idx); - - // Free IP3DB records. - for (i = 0;i < pmpmi->num_records;++i) { - ip3db_record_finish(&ip3db, &records[i]); - } - free(records); - */ + if (pmp->flag & PMPOF_MUSIC_DB_WRITE) { + ipod_set(&ipod, pmpmi->records, pmpmi->num_records, pmpmi->playlists, pmpmi->num_playlists); + ipod_write(&ipod, itunesdb); + ipod_dump(&ipod, stdout); } exit_this: Modified: trunk/pmplib/lib/pmp_ipod/serialize.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-23 06:22:53 UTC (rev 385) @@ -270,9 +270,7 @@ int serialize_seek(serializer_t* sio, size_t offset) { - if (sio->mode < 0) { - sio->offset = offset; - } + sio->offset = offset; return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |