From: <ny...@us...> - 2007-02-21 15:56:22
|
Revision: 382 http://svn.sourceforge.net/pmplib/?rev=382&view=rev Author: nyaochi Date: 2007-02-21 07:56:22 -0800 (Wed, 21 Feb 2007) Log Message: ----------- Started to support Apple iPod in PMPlib. New driver module pmp_ipod was added. The code is in the very early stage of the development: only reading/dumping iTunesDB is working. Modified Paths: -------------- trunk/pmplib/include/pmplib/os_types.h trunk/pmplib/pmp.sln Added Paths: ----------- trunk/pmplib/lib/pmp_ipod/ 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/pmp_ipod.vcproj trunk/pmplib/lib/pmp_ipod/serialize.c trunk/pmplib/lib/pmp_ipod/serialize.h trunk/pmplib/lib/pmp_ipod/util.c trunk/pmplib/lib/pmp_ipod/util.h Modified: trunk/pmplib/include/pmplib/os_types.h =================================================================== --- trunk/pmplib/include/pmplib/os_types.h 2007-02-20 15:40:10 UTC (rev 381) +++ trunk/pmplib/include/pmplib/os_types.h 2007-02-21 15:56:22 UTC (rev 382) @@ -31,10 +31,12 @@ #include <sys/types.h> #else -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef int int32_t; -typedef unsigned short uint16_t; +typedef char int8_t; +typedef unsigned char uint8_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef unsigned __int64 uint64_t; #endif Added: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c (rev 0) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,81 @@ +/* + * iPod + * + * 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:$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ + +#include <os.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_STRING_H +#include <string.h> +#endif/*HAVE_STRING_H*/ +#include <pmplib/ucs2char.h> + +#include "serialize.h" +#include "util.h" +#include "ipod.h" +#include "itunesdb.h" + +void ipod_init(ipod_t* ipod) +{ + ipod->itunesdb = calloc(1, sizeof(itunesdb_chunk_t)); +} + +void ipod_finish(ipod_t* ipod) +{ + +} + +result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb) +{ + FILE *fp = NULL; + + fp = ucs2fopen(itunesdb, "rb"); + if (fp) { + serializer_t sio; + uint8_t* buffer = NULL; + long size = 0; + + fread_all(fp, &buffer, &size); + fclose(fp); + + serialize_init_read(&sio, buffer, (size_t)size); + itunesdb_read(ipod->itunesdb, &sio); + serialize_finish(&sio); + + return 0; + } else { + return 1; + } +} + +result_t ipod_dump(ipod_t* ipod, FILE *fpo) +{ + serializer_t sio; + serialize_init_dump(&sio, fpo, 2); + itunesdb_repr(ipod->itunesdb, 0, &sio); + serialize_finish(&sio); + return 0; +} Property changes on: trunk/pmplib/lib/pmp_ipod/ipod.c ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/ipod.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.h (rev 0) +++ trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,16 @@ +#ifndef __IPOD_H__ +#define __IPOD_H__ + +struct tag_itunesdb_chunk; +typedef struct tag_itunesdb_chunk itunesdb_chunk_t; + +typedef struct { + itunesdb_chunk_t* itunesdb; +} ipod_t; + +void ipod_init(ipod_t* ipod); +void ipod_finish(ipod_t* ipod); +result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb); +result_t ipod_dump(ipod_t* ipod, FILE *fpo); + +#endif/*__IPOD_H__*/ Property changes on: trunk/pmplib/lib/pmp_ipod/ipod.h ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/itunesdb.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.c (rev 0) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,526 @@ +/* + * iTunesDB + * + * 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:$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ + +#include <os.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_STRING_H +#include <string.h> +#endif/*HAVE_STRING_H*/ +#include <pmplib/ucs2char.h> + +#include "ipod.h" +#include "serialize.h" +#include "util.h" +#include "itunesdb.h" + +static int mhbd_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhbd_t* mhbd = (chunk_mhbd_t*)chunk->data; + + if (serialize_uint32le(sio, "unknown1", "%d", &mhbd->unknown1)) return 1; + if (serialize_uint32le(sio, "version", "%d", &mhbd->version)) return 1; + if (serialize_uint32le(sio, "num_children", "%d", &mhbd->num_children)) return 1; + if (serialize_uint64le(sio, "identifier", "%lX", &mhbd->identifier)) return 1; + if (serialize_uint16le(sio, "unkonwn2", "%d", &mhbd->unknown2)) return 1; + if (serialize_uint16le(sio, "unkonwn3", "%d", &mhbd->unknown3)) return 1; + if (serialize_uint64le(sio, "unknown4", "%lX", &mhbd->unknown4)) return 1; + if (serialize_uint8_array(sio, "unknown5", "%02X ", mhbd->unknown5, sizeof(mhbd->unknown5))) return 1; + if (serialize_uint8_array(sio, "language", "%c ", mhbd->language, sizeof(mhbd->language))) return 1; + if (serialize_uint8_array(sio, "unknown6", "%02X ", mhbd->unknown6, sizeof(mhbd->unknown6))) return 1; + + return 0; +} + +static int mhsd_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhsd_t* mhsd = (chunk_mhsd_t*)chunk->data; + + if (serialize_uint32le(sio, "type", "%d", &mhsd->type)) return 1; + if (serialize_uint8_array(sio, "unknown1", "%02X ", mhsd->unknown1, sizeof(mhsd->unknown1))) return 1; + + return 0; +} + +static int mhlt_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhlt_t* mhlt = (chunk_mhlt_t*)chunk->data; + + if (serialize_uint8_array(sio, "unknown1", "%02X ", mhlt->unknown1, sizeof(mhlt->unknown1))) return 1; + + return 0; +} + +static int mhit_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhit_t* mhit = (chunk_mhit_t*)chunk->data; + + if (serialize_uint32le(sio, "num_children", "%u", &mhit->num_children)) return 1; + if (serialize_uint32le(sio, "uid", "%u", &mhit->uid)) return 1; + if (serialize_uint32le(sio, "visible", "%u", &mhit->visible)) return 1; + if (serialize_uint32le(sio, "filetype", "%08X", &mhit->filetype)) return 1; + if (serialize_uint8(sio, "type1", "%02X", &mhit->type1)) return 1; + if (serialize_uint8(sio, "type2", "%02X", &mhit->type2)) return 1; + if (serialize_uint8(sio, "compilation", "%u", &mhit->compilation)) return 1; + if (serialize_uint8(sio, "rating", "%u", &mhit->type1)) return 1; + if (serialize_uint32le(sio, "last_modified", "%u", &mhit->last_modified)) return 1; + if (serialize_uint32le(sio, "filesize", "%u", &mhit->filesize)) return 1; + if (serialize_uint32le(sio, "duration", "%u", &mhit->duration)) return 1; + if (serialize_uint32le(sio, "track_number", "%u", &mhit->track_number)) return 1; + if (serialize_uint32le(sio, "total_tracks", "%u", &mhit->total_tracks)) return 1; + if (serialize_uint32le(sio, "year", "%u", &mhit->year)) return 1; + if (serialize_uint32le(sio, "bitrate", "%u", &mhit->bitrate)) return 1; + if (serialize_uint16le(sio, "unknown1", "%u", &mhit->unknown1)) return 1; + if (serialize_uint16le(sio, "samplerate", "%u", &mhit->samplerate)) return 1; + if (serialize_int32le(sio, "volume", "%d", &mhit->volume)) return 1; + if (serialize_uint32le(sio, "start_time", "%u", &mhit->start_time)) return 1; + if (serialize_uint32le(sio, "stop_time", "%u", &mhit->stop_time)) return 1; + if (serialize_uint32le(sio, "sound_check", "%u", &mhit->sound_check)) return 1; + if (serialize_uint32le(sio, "play_count", "%u", &mhit->play_count)) return 1; + if (serialize_uint32le(sio, "play_count2", "%u", &mhit->play_count2)) return 1; + if (serialize_uint32le(sio, "last_played", "%u", &mhit->last_played)) return 1; + if (serialize_uint32le(sio, "disc_number", "%u", &mhit->disc_number)) return 1; + if (serialize_uint32le(sio, "total_discs", "%u", &mhit->total_discs)) return 1; + if (serialize_uint32le(sio, "user_id", "%u", &mhit->user_id)) return 1; + if (serialize_uint32le(sio, "date_added", "%u", &mhit->date_added)) return 1; + if (serialize_uint32le(sio, "bookmark_time", "%u", &mhit->bookmark_time)) return 1; + if (serialize_uint64le(sio, "dbid", "%X", &mhit->dbid)) return 1; + if (serialize_uint8(sio, "is_checked", "%u", &mhit->is_checked)) return 1; + if (serialize_uint8(sio, "rating_itunes", "%u", &mhit->rating_itunes)) return 1; + if (serialize_uint16le(sio, "bpm", "%u", &mhit->bpm)) return 1; + if (serialize_uint16le(sio, "num_artworks", "%u", &mhit->num_artworks)) return 1; + if (serialize_uint16le(sio, "unk9", "%u", &mhit->unk9)) return 1; + if (serialize_uint32le(sio, "artwork_size", "%u", &mhit->artwork_size)) return 1; + if (serialize_uint32le(sio, "unk11", "%u", &mhit->unk11)) return 1; + if (serialize_uint32le(sio, "samplerate2", "%u", &mhit->samplerate2)) return 1; + if (serialize_uint32le(sio, "disc_released", "%u", &mhit->disc_released)) return 1; + if (serialize_uint16le(sio, "unk14_1", "%u", &mhit->unk14_1)) return 1; + if (serialize_uint16le(sio, "unk14_2", "%u", &mhit->unk14_2)) return 1; + if (serialize_uint32le(sio, "unk15", "%u", &mhit->unk15)) return 1; + if (serialize_uint32le(sio, "unk16", "%u", &mhit->unk16)) return 1; + if (serialize_uint32le(sio, "skip_count", "%u", &mhit->skip_count)) return 1; + if (serialize_uint32le(sio, "last_skipped", "%u", &mhit->last_skipped)) return 1; + if (serialize_uint8(sio, "has_artwork", "%u", &mhit->has_artwork)) return 1; + if (serialize_uint8(sio, "skip_when_shuffling", "%u", &mhit->skip_when_shuffling)) return 1; + if (serialize_uint8(sio, "remember_playback_position", "%u", &mhit->remember_playback_position)) return 1; + if (serialize_uint8(sio, "flag4", "%u", &mhit->flag4)) return 1; + if (serialize_uint64le(sio, "dbid2", "%X", &mhit->dbid2)) return 1; + if (serialize_uint8(sio, "has_lyrics", "%u", &mhit->has_lyrics)) return 1; + if (serialize_uint8(sio, "is_movie", "%u", &mhit->is_movie)) return 1; + if (serialize_uint8(sio, "is_played", "%u", &mhit->is_played)) return 1; + if (serialize_uint8(sio, "unk17", "%u", &mhit->unk17)) return 1; + if (serialize_uint32le(sio, "unk21", "%u", &mhit->unk21)) return 1; + if (serialize_int32le(sio, "encoder_delay", "%d", &mhit->encoder_delay)) return 1; + if (serialize_uint64le(sio, "num_samples", "%u", &mhit->num_samples)) return 1; + if (serialize_uint32le(sio, "unk25", "%u", &mhit->unk25)) return 1; + if (serialize_int32le(sio, "padding_samples", "%d", &mhit->padding_samples)) return 1; + if (serialize_uint32le(sio, "unk27", "%u", &mhit->unk27)) return 1; + if (serialize_uint32le(sio, "media_type", "%u", &mhit->media_type)) return 1; + if (serialize_uint32le(sio, "season_number", "%u", &mhit->season_number)) return 1; + if (serialize_uint32le(sio, "episode_number", "%u", &mhit->episode_number)) return 1; + if (serialize_uint32le(sio, "unk31", "%u", &mhit->unk31)) return 1; + if (serialize_uint32le(sio, "unk32", "%u", &mhit->unk32)) return 1; + if (serialize_uint32le(sio, "unk33", "%u", &mhit->unk33)) return 1; + if (serialize_uint32le(sio, "unk34", "%u", &mhit->unk34)) return 1; + if (serialize_uint32le(sio, "unk35", "%u", &mhit->unk35)) return 1; + if (serialize_uint32le(sio, "unk36", "%u", &mhit->unk36)) return 1; + if (serialize_uint32le(sio, "unk37", "%u", &mhit->unk37)) return 1; + if (serialize_uint32le(sio, "offset_last8th_frame", "%u", &mhit->offset_last8th_frame)) return 1; + if (serialize_uint32le(sio, "unk38", "%u", &mhit->unk38)) return 1; + if (serialize_uint16le(sio, "gapless_track", "%u", &mhit->gapless_track)) return 1; + if (serialize_uint16le(sio, "gapless_album", "%u", &mhit->gapless_album)) return 1; + + return 0; +} + +static int mhlp_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhlp_t* mhlp = (chunk_mhlp_t*)chunk->data; + + if (serialize_uint8_array(sio, "unknown1", "%02X ", mhlp->unknown1, sizeof(mhlp->unknown1))) return 1; + + return 0; +} + +static int mhyp_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhyp_t* mhyp = (chunk_mhyp_t*)chunk->data; + + if (serialize_uint32le(sio, "num_mhod", "%u", &mhyp->num_mhod)) return 1; + if (serialize_uint32le(sio, "num_mhip", "%u", &mhyp->num_mhip)) return 1; + if (serialize_uint8(sio, "flag_master", "%u", &mhyp->flag_master)) return 1; + if (serialize_uint8(sio, "flag_unkonwn1", "%u", &mhyp->flag_unkonwn1)) return 1; + if (serialize_uint8(sio, "flag_unkonwn2", "%u", &mhyp->flag_unkonwn2)) return 1; + if (serialize_uint8(sio, "flag_unkonwn3", "%u", &mhyp->flag_unkonwn3)) return 1; + if (serialize_uint32le(sio, "timestamp", "%u", &mhyp->timestamp)) return 1; + if (serialize_uint64le(sio, "id", "%u", &mhyp->id)) return 1; + if (serialize_uint32le(sio, "unk3", "%u", &mhyp->unk3)) return 1; + if (serialize_uint16le(sio, "unk4", "%u", &mhyp->unk4)) return 1; + if (serialize_uint16le(sio, "flag_podcast", "%u", &mhyp->flag_podcast)) return 1; + if (serialize_uint32le(sio, "sort_order", "%u", &mhyp->sort_order)) return 1; + if (serialize_uint8_array(sio, "padding", "%02X ", mhyp->padding, sizeof(mhyp->padding))) return 1; + + return 0; +} + +static int mhip_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhip_t* mhyp = (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; + + return 0; +} + +static int mhod_string_serialize(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio) +{ + chunk_mhod_string_t* string = &((chunk_mhod_t*)chunk->data)->data.str; + + if (serialize_uint32le(sio, "unk1", "%u", &string->unk1)) return 1; + if (serialize_uint32le(sio, "unk2", "%u", &string->unk2)) return 1; + if (serialize_uint32le(sio, "position", "%u", &string->position)) return 1; + if (serialize_uint32le(sio, "size", "%u", &string->size)) return 1; + if (serialize_uint32le(sio, "unknown", "%u", &string->unknown)) return 1; + if (serialize_uint32le(sio, "unk4", "%u", &string->unk4)) return 1; + if (serialize_ucs2lestr_fixed(sio, name, "%s", &string->value, string->size / sizeof(ucs2char_t))) return 1; + + return 0; +} + +static int mhod_url_serialize(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_url_t* url = &mhod->data.url; + + if (serialize_uint32le(sio, "unk1", "%u", &url->unk1)) return 1; + if (serialize_uint32le(sio, "unk2", "%u", &url->unk2)) return 1; + if (serialize_utf8str_fixed(sio, name, "%s", &url->value, chunk->data_size - chunk->chunk_size)) return 1; + + return 0; +} + +static int mhod_index_serialize(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio) +{ + uint32_t i; + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_index_t* index = &mhod->data.index; + + if (serialize_uint32le(sio, "unk1", "%u", &index->unk1)) return 1; + if (serialize_uint32le(sio, "unk2", "%u", &index->unk2)) return 1; + if (serialize_uint32le(sio, "type", "%u", &index->type)) return 1; + if (serialize_uint32le(sio, "num_entries", "%u", &index->num_entries)) return 1; + if (serialize_uint8_array(sio, "padding", "%02X ", index->padding, sizeof(index->padding))) return 1; + + /* Allocate array when reading. */ + if (serialize_reading(sio)) { + index->entries = calloc(index->num_entries, sizeof(uint32_t)); + if (!index->entries) { + return 1; + } + } + + for (i = 0;i < index->num_entries;++i) { + char fieldname[128]; + sprintf(fieldname, "entries[%d]", i); + if (serialize_uint32le(sio, fieldname, "%u", &index->entries[i])) return 1; + } + + return 0; +} + +static int mhod_playlist_column_serialize(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio) +{ + uint32_t i; + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_playlist_column_t* pc = &mhod->data.pc; + + if (serialize_uint32le(sio, "unk1", "%u", &pc->unk1)) return 1; + if (serialize_uint32le(sio, "unk2", "%u", &pc->unk2)) return 1; + if (serialize_uint32le(sio, "unk3", "%u", &pc->unk3)) return 1; + if (serialize_uint64le(sio, "unk4", "%u", &pc->unk4)) return 1; + if (serialize_uint32le(sio, "unk8", "%u", &pc->unk8)) return 1; + if (serialize_uint16le(sio, "unk9", "%u", &pc->unk9)) return 1; + if (serialize_uint16le(sio, "unk10", "%u", &pc->unk10)) return 1; + if (serialize_uint32le(sio, "sort_type", "%u", &pc->sort_type)) return 1; + if (serialize_uint32le(sio, "num_columns", "%u", &pc->num_columns)) return 1; + if (serialize_uint32le(sio, "unknown", "%u", &pc->unknown)) return 1; + + /* Allocate array when reading. */ + if (serialize_reading(sio)) { + pc->columns = (chunk_mhod_playlist_column_definition_t*)calloc( + pc->num_columns, sizeof(chunk_mhod_playlist_column_definition_t)); + if (!pc->columns) { + return 1; + } + } + + for (i = 0;i < pc->num_columns;++i) { + char fieldname[128]; + chunk_mhod_playlist_column_definition_t* def = &pc->columns[i]; + + sprintf(fieldname, "columns[%d].id", i); + if (serialize_uint16le(sio, fieldname, "%u", &def->id)) return 1; + sprintf(fieldname, "columns[%d].width", i); + if (serialize_uint16le(sio, fieldname, "%u", &def->width)) return 1; + sprintf(fieldname, "columns[%d].sort_direction", i); + if (serialize_uint32le(sio, fieldname, "%u", &def->sort_direction)) return 1; + sprintf(fieldname, "columns[%d].padding", i); + if (serialize_uint64le(sio, fieldname, "%u", &def->padding)) return 1; + } + + return 0; +} + +static int mhod_playlist_order_serialize(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_playlist_order_t* po = &mhod->data.po; + + if (serialize_uint32le(sio, "unk1", "%u", &po->unk1)) return 1; + if (serialize_uint32le(sio, "unk2", "%u", &po->unk2)) return 1; + if (serialize_uint32le(sio, "position", "%u", &po->position)) return 1; + if (serialize_uint8_array(sio, "padding", "%02X ", po->padding, sizeof(po->padding))) return 1; + + return 0; +} + +static const itunesdb_mhoddecl_t* find_mhoddecl(itunesdb_chunk_t* chunk) +{ + static const itunesdb_mhoddecl_t mds[] = { + {1, "title", 0, mhod_string_serialize}, + {2, "location", 0, mhod_string_serialize}, + {3, "album", 0, mhod_string_serialize}, + {4, "artist", 0, mhod_string_serialize}, + {5, "genre", 0, mhod_string_serialize}, + {6, "filetype", 0, mhod_string_serialize}, + {7, "EQ setting", 0, mhod_string_serialize}, + {8, "comment", 0, mhod_string_serialize}, + {9, "category", 0, mhod_string_serialize}, + {12, "composer", 0, mhod_string_serialize}, + {13, "grouping", 0, mhod_string_serialize}, + {14, "description", 0, mhod_string_serialize}, + {15, "podcast_enclosure_url", 0, mhod_url_serialize}, + {16, "podcast_rss_url", 0, mhod_url_serialize}, + {52, "index", 0, mhod_index_serialize}, + {100, "playlist_column", 0x288, mhod_playlist_column_serialize}, + {100, "playlist_order", 0x2C, mhod_playlist_order_serialize}, + {0, NULL, 0, NULL}, + }; + const itunesdb_mhoddecl_t* decl = mds; + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + + while (decl->name) { + if (decl->type == mhod->type) { + if (decl->chunk_size == 0 || decl->chunk_size == chunk->chunk_size) { + return decl; + } + } + ++decl; + } + return NULL; +} + +static int mhod_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + const itunesdb_mhoddecl_t* decl = NULL; + + if (serialize_uint32le(sio, "type", "%u", &mhod->type)) return 1; + + decl = find_mhoddecl(chunk); + if (decl) { + if (decl->serialize(chunk, decl->name, sio)) return 1; + } else { + if (serialize_dumping(sio)) { + serialize_indent(sio); + fprintf(sio->fp, "!unknown_mhod_type!\n"); + } + } + + return 0; +} + + +static const itunesdb_chunkdecl_t* find_chunkdecl(itunesdb_chunk_t* chunk) +{ + static const itunesdb_chunkdecl_t cds[] = { + {"mhbd", sizeof(chunk_mhbd_t), mhbd_serialize}, + {"mhsd", sizeof(chunk_mhsd_t), mhsd_serialize}, + {"mhlt", sizeof(chunk_mhlt_t), mhlt_serialize}, + {"mhit", sizeof(chunk_mhit_t), mhit_serialize}, + {"mhlp", sizeof(chunk_mhlp_t), mhlp_serialize}, + {"mhyp", sizeof(chunk_mhyp_t), mhyp_serialize}, + {"mhip", sizeof(chunk_mhip_t), mhip_serialize}, + {"mhod", sizeof(chunk_mhod_t), mhod_serialize}, + {NULL, 0, NULL}, + }; + const itunesdb_chunkdecl_t* decl = cds; + + while (decl->name) { + if (strncmp(decl->name, chunk->id, 4) == 0) { + return decl; + } + ++decl; + } + return NULL; +} + +int itunesdb_repr(itunesdb_chunk_t* chunk, size_t index, serializer_t* sio) +{ + uint32_t i; + itunesdb_chunk_t* child = NULL; + const itunesdb_chunkdecl_t* decl = NULL; + + /* Start of a chunk */ + serialize_indent(sio); + fprintf(sio->fp, "Chunk %c%c%c%c (%d) = {\n", chunk->id[0], chunk->id[1], chunk->id[2], chunk->id[3], index); + serialize_indent_ascend(sio); + + /* Show information of the chunk header */ + serialize_indent(sio); + fprintf(sio->fp, "offset: %08X\n", chunk->offset); + serialize_indent(sio); + fprintf(sio->fp, "data_size: %d\n", chunk->data_size); + serialize_indent(sio); + fprintf(sio->fp, "chunk_size: %d\n", chunk->chunk_size); + + /* Show fields in the chunk data */ + decl = find_chunkdecl(chunk); + if (decl) { + decl->serialize(chunk, sio); + } else { + serialize_indent(sio); + fprintf(sio->fp, "!unknown_chunk!\n"); + } + + /* Show number of children */ + serialize_indent(sio); + fprintf(sio->fp, "#children: %d\n", chunk->num_children); + + /* Descend to children */ + for (i = 0;i < chunk->num_children;++i) { + fputc('\n', sio->fp); + itunesdb_repr(&chunk->childlen[i], i, sio); + } + + /* End of the chunk */ + serialize_indent_descend(sio); + serialize_indent(sio); + fprintf(sio->fp, "}\n"); + + return 0; +} + +int itunesdb_read(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + uint32_t i; + size_t begin = serialize_tell(sio); + const itunesdb_chunkdecl_t* decl = NULL; + + /* Read the chunk ID and header information */ + chunk->offset = begin; + if (serialize_uint8_array(sio, "id", "%c ", chunk->id, sizeof(chunk->id))) return 1; + if (serialize_uint32le(sio, "data_size", "%d", &chunk->data_size)) return 1; + if (serialize_uint32le(sio, "chunk_size", "%d", &chunk->chunk_size)) return 1; + + /* Read the chunk data if this chunk is 'known' */ + decl = find_chunkdecl(chunk); + if (decl) { + chunk->data = calloc(1, decl->data_size); + if (chunk->data) { + if (decl->serialize(chunk, sio)) return 1; + } + } + + if (strncmp(chunk->id, "mhod", 4) == 0) { + uint32_t next = begin + chunk->chunk_size; + if (next < serialize_tell(sio)) { + fprintf(stderr, "WARNING: backward seeking.\n"); + } + serialize_seek(sio, next); + } else { + uint32_t next = begin + chunk->data_size; + if (next < serialize_tell(sio)) { + fprintf(stderr, "WARNING: backward seeking.\n"); + } + serialize_seek(sio, next); + } + + /* Read children for this chunk. */ + if (strncmp(chunk->id, "mhlt", 4) == 0 || strncmp(chunk->id, "mhlp", 4) == 0) { + /* chunk->chunk_size represents the number of children for "mhlt" and "mhlp" chunks */ + chunk->num_children = chunk->chunk_size; + chunk->childlen = (itunesdb_chunk_t*)calloc(chunk->num_children, sizeof(itunesdb_chunk_t)); + for (i = 0;i < chunk->num_children;++i) { + itunesdb_read(&chunk->childlen[i], sio); + } + } else { + /* chunk->chunk_size represents the size in bytes of this chunk */ + chunk->num_children = 0; + chunk->childlen = NULL; + while (sio->offset - begin < chunk->chunk_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); + ++chunk->num_children; + } + } + + return 0; +} + +#if 0 +int main(int argc, char *argv[]) +{ + FILE *fp = fopen("C:\\pmplib\\ipod_nano\\iPod_Control\\iTunes\\iTunesDB", "rb"); + if (fp) { + serializer_t sio; + uint8_t* buffer = NULL; + long size = 0; + itunesdb_chunk_t root; + + fread_all(fp, &buffer, &size); + fclose(fp); + + serialize_init_read(&sio, buffer, (size_t)size); + chunk_read(&root, &sio); + serialize_finish(&sio); + + serialize_init_dump(&sio, stdout, 2); + chunk_repr(&root, 0, &sio); + serialize_finish(&sio); + } + + return 0; +} +#endif \ No newline at end of file Property changes on: trunk/pmplib/lib/pmp_ipod/itunesdb.c ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h (rev 0) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,247 @@ +/* + * iTunesDB + * + * 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 __ITUNESDB_H__ +#define __ITUNESDB_H__ + +typedef struct { + uint32_t unknown1; /* always set to 1. */ + uint32_t version; + uint32_t num_children; + uint64_t identifier; + uint16_t unknown2; /* always set to 2. */ + uint16_t unknown3; /* 0x0263 */ + uint64_t unknown4; + uint8_t unknown5[26]; /* zero padded. */ + uint8_t language[2]; /* e.g., "en", "ja" */ + uint8_t unknown6[32]; /* zero padded. */ +} chunk_mhbd_t; + +typedef struct { + uint32_t type; /* 1 (track list), 2 (playlist list), or 3 (podcast list). */ + uint8_t unknown1[16*5]; /* zero padded. */ +} chunk_mhsd_t; + +typedef struct { + uint8_t unknown1[16*5]; /* zero padded. */ +} chunk_mhlt_t; + +typedef struct { + uint32_t num_children; + uint32_t uid; + uint32_t visible; + uint32_t filetype; + uint8_t type1; + uint8_t type2; + uint8_t compilation; + uint8_t rating; + uint32_t last_modified; + uint32_t filesize; + uint32_t duration; + uint32_t track_number; + uint32_t total_tracks; + uint32_t year; + uint32_t bitrate; /* in [kbps] */ + uint16_t unknown1; + uint16_t samplerate; /* in [Hz] */ + int32_t volume; + uint32_t start_time; + uint32_t stop_time; + uint32_t sound_check; + uint32_t play_count; + uint32_t play_count2; + uint32_t last_played; + uint32_t disc_number; + uint32_t total_discs; + uint32_t user_id; + uint32_t date_added; + uint32_t bookmark_time; + uint64_t dbid; + uint8_t is_checked; + uint8_t rating_itunes; + uint16_t bpm; + uint16_t num_artworks; + uint16_t unk9; + uint32_t artwork_size; + uint32_t unk11; + uint32_t samplerate2; + uint32_t disc_released; + uint16_t unk14_1; + uint16_t unk14_2; + uint32_t unk15; + uint32_t unk16; + uint32_t skip_count; + uint32_t last_skipped; + uint8_t has_artwork; + uint8_t skip_when_shuffling; + uint8_t remember_playback_position; + uint8_t flag4; + uint64_t dbid2; + uint8_t has_lyrics; + uint8_t is_movie; + uint8_t is_played; + uint8_t unk17; + uint32_t unk21; + int32_t encoder_delay; + uint64_t num_samples; + uint32_t unk25; + int32_t padding_samples; + uint32_t unk27; + uint32_t media_type; + uint32_t season_number; + uint32_t episode_number; + uint32_t unk31; + uint32_t unk32; + uint32_t unk33; + uint32_t unk34; + uint32_t unk35; + uint32_t unk36; + uint32_t unk37; + uint32_t offset_last8th_frame; + uint32_t unk38; + uint16_t gapless_track; + uint16_t gapless_album; +} chunk_mhit_t; + +typedef struct { + uint8_t unknown1[16*5]; /* zero padded. */ +} chunk_mhlp_t; + +typedef struct { + uint32_t num_mhod; + uint32_t num_mhip; + uint8_t flag_master; + uint8_t flag_unkonwn1; + uint8_t flag_unkonwn2; + uint8_t flag_unkonwn3; + uint32_t timestamp; + uint64_t id; + uint32_t unk3; + uint16_t unk4; + uint16_t flag_podcast; + uint32_t sort_order; + uint8_t padding[0x3C]; +} chunk_mhyp_t; + +typedef struct { + uint32_t num_mhod; + uint32_t flag_podcast_group; + uint32_t group_id; + uint32_t track_id; + uint32_t timestamp; + uint32_t podcast_parent; +} chunk_mhip_t; + +typedef struct { + uint32_t unk1; + uint32_t unk2; + uint32_t position; + uint32_t size; + uint32_t unknown; + uint32_t unk4; + ucs2char_t* value; +} chunk_mhod_string_t; + +typedef struct { + uint32_t unk1; + uint32_t unk2; + char* value; +} chunk_mhod_url_t; + +typedef struct { + uint32_t unk1; + uint32_t unk2; + uint32_t type; + uint32_t num_entries; + uint8_t padding[40]; + uint32_t* entries; +} chunk_mhod_index_t; + +typedef struct { + uint16_t id; + uint16_t width; + uint32_t sort_direction; + uint64_t padding; +} chunk_mhod_playlist_column_definition_t; + +typedef struct { + uint32_t unk1; + uint32_t unk2; + uint32_t unk3; + uint64_t unk4; + uint32_t unk8; + uint16_t unk9; + uint16_t unk10; + uint32_t sort_type; + uint32_t num_columns; + uint32_t unknown; + chunk_mhod_playlist_column_definition_t* columns; +} chunk_mhod_playlist_column_t; + +typedef struct { + uint32_t unk1; + uint32_t unk2; + uint32_t position; + uint8_t padding[16]; +} chunk_mhod_playlist_order_t; + +typedef struct { + uint32_t type; + union { + chunk_mhod_string_t str; + chunk_mhod_url_t url; + chunk_mhod_index_t index; + chunk_mhod_playlist_column_t pc; + chunk_mhod_playlist_order_t po; + } data; +} chunk_mhod_t; + + +struct tag_itunesdb_chunk { + int8_t id[4]; + uint32_t data_size; + uint32_t chunk_size; + + void* data; + uint32_t num_children; /* This field does not exist in iTunesDB. */ + struct tag_itunesdb_chunk* childlen; + uint32_t offset; /* This field does not exist in iTunesDB. */ +}; + +typedef struct { + uint32_t type; + const char* name; + size_t chunk_size; + int (*serialize)(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio); +} itunesdb_mhoddecl_t; + +typedef struct { + const char* name; + size_t data_size; + int (*serialize)(itunesdb_chunk_t* chunk, serializer_t* sio); +} itunesdb_chunkdecl_t; + +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__*/ Property changes on: trunk/pmplib/lib/pmp_ipod/itunesdb.h ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c (rev 0) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,625 @@ +/* + * PMP library implementation for Apple iPod series. + * + * 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:$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ + +#include <os.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_STRING_H +#include <string.h> +#endif/*HAVE_STRING_H*/ +#include <pmplib/ucs2char.h> +#include <pmplib/filepath.h> +#include <pmplib/pmp.h> + +#include "util.h" +#include "ipod.h" + +#ifdef PMP_IPOD_EXPORTS +#define PMPIPODAPI __declspec(dllexport) +#else +#define PMPIPODAPI +#endif + + +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[] = { + { + "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; + +typedef struct { + pmp_music_record_t* records; + int num_records; + pmp_playlist_t* playlists; + int num_playlists; +} pmp_music_internal_t; + +static uint32_t pmp_add_ref(pmp_t* pmp); +static uint32_t pmp_release(pmp_t* pmp); +static result_t pmp_open(pmp_t* pmp, uint32_t flag); +static result_t pmp_close(pmp_t* pmp); +static result_t pmp_create_instance_music(pmp_t* pmp, pmp_music_t** ptr_pmpdb); + +static uint32_t pmpmusic_release(pmp_music_t* music); +static uint32_t pmpmusic_open(pmp_music_t* music); +static uint32_t pmpmusic_close(pmp_music_t* music); +static result_t pmpmusic_set_records(pmp_music_t* music, const pmp_music_record_t* records, uint32_t num_records); +static result_t pmpmusic_get_records(pmp_music_t* music, pmp_music_record_t* records, uint32_t* num_records); +static result_t pmpmusic_dump(pmp_music_t* music, FILE *fp, int level); +static result_t pmpmusic_set_playlists(pmp_music_t* music, const pmp_playlist_t* playlists, uint32_t num_playlists); + + +#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); +} + +static void set_device_info( + const char *id, + const ucs2char_t* path_to_device, + const ipod_descriptor_t* md, + pmp_device_information_t* info + ) +{ + uint32_t n; + const char *p = NULL; + ucs2char_t* ucs2 = NULL; + pmp_device_description_t* decl = (pmp_device_description_t*)&info->decl; + + strcpy_if_empty(decl->id, id); + strcpy_if_empty(decl->manufacturer, md->manufacturer); + strcpy_if_empty(decl->name, md->name); + strcpy_if_empty(decl->mode, md->mode); + strcpy_if_empty(decl->min_version, md->min_version); + strcpy_if_empty(decl->max_version, md->max_version); + + ucs2cpy(info->path_to_root, path_to_device); + + ucs2 = mbsdupucs2(md->path_to_system); + ucs2cpy(info->path_to_system, ucs2); + ucs2free(ucs2); + + ucs2 = mbsdupucs2(md->path_to_music); + ucs2cpy(info->path_to_music, ucs2); + ucs2free(ucs2); + + ucs2 = mbsdupucs2(md->path_to_playlist); + ucs2cpy(info->path_to_playlist, ucs2); + ucs2free(ucs2); + + info->music_flag = PMPMF_SUPPORT | PMPMF_RECURSIVE; + info->playlist_flag = PMPPF_SUPPORT; + + // Audio codecs. + for (n = 0;md->codecs[n];++n) ; + info->num_audio_codecs = n; + info->audio_codecs = (uint32_t*)ucs2malloc(sizeof(uint32_t) * info->num_audio_codecs); + for (n = 0;n < info->num_audio_codecs;++n) { + info->audio_codecs[n] = md->codecs[n]; + } + + // Obtain the number of extensions separated by '\0' characters. + for (n = 0, p = md->extensions;*p;p += (strlen(p)+1)) { + n++; + } + info->num_audio_extensions = n; + info->audio_extensions = (ucs2char_t**)ucs2malloc(sizeof(ucs2char_t*) * info->num_audio_extensions); + for (n = 0, p = md->extensions;*p;p += (strlen(p)+1)) { + info->audio_extensions[n++] = mbsdupucs2(p); + } +} + +static void free_device_info(pmp_device_information_t* info) +{ + uint32_t i; + for (i = 0;i < info->num_audio_extensions;++i) { + ucs2free(info->audio_extensions[i]); + } + ucs2free(info->audio_codecs); + ucs2free(info->audio_extensions); + memset(info, 0, sizeof(*info)); +} + +static void set_filenames(ucs2char_t *itunesdb, pmp_t *pmp) +{ + ucs2char_t* ucs2 = NULL; + pmp_internal_t* pmpi = (pmp_internal_t*)pmp->instance; + + ucs2cpy(itunesdb, pmp->info.path_to_root); + filepath_addslash(itunesdb); + ucs2 = mbsdupucs2(pmpi->decl->itunesdb_filename); + ucs2cat(itunesdb, ucs2); + ucs2free(ucs2); +} + + +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) { + callback(instance, md->id); + } + return 0; +} + +PMPIPODAPI result_t pmp_create(pmp_t** ptr_pmp, const ucs2char_t* path_to_device, const char *id) +{ + result_t ret = 0; + pmp_t* pmp = NULL; + pmp_internal_t* pmpi = NULL; + const ipod_descriptor_t* md = NULL; + pmp_device_information_t info; + + // Initialize device information. + memset(&info, 0, sizeof(info)); + + // Return a NULL pointer by default. + *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) { + return PMPERR_DEVICENOTFOUND; + } + + // Allocate PMP class instance. + pmp = (pmp_t*)calloc(1, sizeof(pmp_t)); + if (!pmp) { + return PMPERR_INSUFFICIENTMEMORY; + } + + pmp->add_ref = pmp_add_ref; + pmp->release = pmp_release; + pmp->open = pmp_open; + pmp->close = pmp_close; + pmp->add_ref(pmp); + + // Allocate the internal variables. + pmpi = (pmp_internal_t*)calloc(1, sizeof(pmp_internal_t)); + if (!pmpi) { + free(pmp); + return PMPERR_INSUFFICIENTMEMORY; + } + pmpi->decl = md; + + // Initialize the internal variables. + pmp->instance = pmpi; + memcpy((pmp_device_information_t*)&pmp->info, &info, sizeof(info)); + + // Create music instance. + ret = pmp_create_instance_music(pmp, &pmp->music); + if (ret != 0) { + pmp_release(pmp); + return ret; + } + + // Prepare + *ptr_pmp = pmp; + return 0; +} + +static uint32_t pmp_add_ref(pmp_t* pmp) +{ + return pmplib_interlocked_increment(&pmp->ref_count); +} + +static uint32_t pmp_release(pmp_t* pmp) +{ + uint32_t count = pmplib_interlocked_decrement(&pmp->ref_count); + if (count == 0) { + pmpmusic_release(pmp->music); + free_device_info(&pmp->info); + free(pmp->instance); + free(pmp); + } + return count; +} + +static result_t pmp_open(pmp_t* pmp, uint32_t flag) +{ + result_t ret = 0; + + // Set the open flag. + pmp->flag = flag; + + // Open the music database. + ret = pmpmusic_open(pmp->music); + if (ret) { + return ret; + } + + return 0; +} + +static result_t pmp_close(pmp_t* pmp) +{ + result_t ret = 0; + + // Close the music database. + ret = pmpmusic_close(pmp->music); + if (ret) { + return ret; + } + + return 0; +} + +static result_t pmp_create_instance_music(pmp_t* pmp, pmp_music_t** ptr_music) +{ + pmp_music_t* music = NULL; + pmp_internal_t* pmpi = (pmp_internal_t*)pmp->instance; + pmp_music_internal_t* pmpmi = NULL; + + *ptr_music = 0; + + music = calloc(1, sizeof(pmp_music_t)); + if (!music) { + return PMPERR_INSUFFICIENTMEMORY; + } + + pmpmi = calloc(1, sizeof(pmp_music_internal_t)); + if (!pmpmi) { + free(music); + return PMPERR_INSUFFICIENTMEMORY; + } + + music->set_records = pmpmusic_set_records; + music->get_records = pmpmusic_get_records; + music->dump = pmpmusic_dump; + music->set_playlists = pmpmusic_set_playlists; + music->pmp = pmp; + music->instance = pmpmi; + + *ptr_music = music; + return 0; +} + + + + +static uint32_t pmpmusic_release(pmp_music_t* music) +{ + pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + pmplib_records_finish(pmpmi->records, pmpmi->num_records); + pmplib_playlists_finish(pmpmi->playlists, pmpmi->num_playlists); + free(pmpmi); + free(music); + return 0; +} + +static uint32_t pmpmusic_open(pmp_music_t* music) +{ + //ip3db_t ip3db; + 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); + + // Free the existing records. + pmplib_records_finish(pmpmi->records, pmpmi->num_records); + pmpmi->records = 0; + pmpmi->num_records = 0; + + // Open the music database if necessary. + if (pmp->flag & PMPOF_MUSIC_DB_READ) { + int i; + ucs2char_t dat[MAX_PATH], dic[MAX_PATH], idx[MAX_PATH]; + pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)pmp->music->instance; + + // Read the music database. + set_filenames(dat, dic, idx, pmp); + ret = ip3db_read(&ip3db, dat, dic, idx); + if (ret) { + goto exit_this; + } + + // The number of music records. + pmpmi->num_records = ip3db_num_records(&ip3db); + + // Allocate an array of the records. + pmpmi->records = (pmp_music_record_t*)malloc(sizeof(pmp_music_record_t) * pmpmi->num_records); + + // Convert IP3DB records to a pmp_music_record_t array. + for (i = 0;i < pmpmi->num_records;++i) { + const ip3db_variant_t* src = (const ip3db_variant_t*)ip3db_get_record(&ip3db, i); + pmp_music_record_t* dst = &pmpmi->records[i]; + size_t length = 0; + + pmplib_record_init(dst); + + length = ucs2len(pmp->info.path_to_root); + length += ucs2len(src[IP3DBF_MUSIC_FILEPATH].value.str); + length += ucs2len(src[IP3DBF_MUSIC_FILENAME].value.str); + dst->filename = (ucs2char_t*)ucs2malloc(sizeof(ucs2char_t) * (length+1)); + ucs2cpy(dst->filename, pmp->info.path_to_root); + ucs2cat(dst->filename, src[IP3DBF_MUSIC_FILEPATH].value.str+1); + ucs2cat(dst->filename, src[IP3DBF_MUSIC_FILENAME].value.str); + filepath_backslash(dst->filename); + + dst->title = ucs2dup(src[IP3DBF_MUSIC_TITLE].value.str); + dst->artist = ucs2dup(src[IP3DBF_MUSIC_ARTIST].value.str); + dst->album = ucs2dup(src[IP3DBF_MUSIC_ALBUM].value.str); + dst->genre = ucs2dup(src[IP3DBF_MUSIC_GENRE].value.str); + dst->date = ucs2dup(src[IP3DBF_MUSIC_ORGRELEASEDATE].value.str); + switch (src[IP3DBF_MUSIC_FILEFORMAT].value.word) { + case 0: + dst->codec = PMPCODEC_MPEGLAYER3; + break; + case 3: + dst->codec = PMPCODEC_VORBIS; + break; + case 5: + dst->codec = PMPCODEC_WMA; + break; + } + dst->track_number = src[IP3DBF_MUSIC_TRACKNUMBER].value.word; + dst->bitrate = src[IP3DBF_MUSIC_BITRATE].value.dword; + dst->duration = src[IP3DBF_MUSIC_DURATION].value.dword; + dst->ts_update = src[IP3DBF_MUSIC_CLUSA].value.dword; + dst->rating = src[IP3DBF_MUSIC_RATING].value.word; + } + } + */ + +exit_this: + //ip3db_finish(&ip3db); + return ret; +} + +static uint32_t pmpmusic_close(pmp_music_t* music) +{ + //ip3db_t ip3db; + 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); + + 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; + + // 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); + } + + ip3db_finish(&ip3db); + */ + return ret; +} + +static result_t pmpmusic_set_records(pmp_music_t* music, const pmp_music_record_t* records, uint32_t num_records) +{ + pmp_t* pmp = music->pmp; + pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + + /* Free records attached to pmpmi. */ + pmplib_records_finish(pmpmi->records, pmpmi->num_records); + + /* Allocate new records. */ + pmpmi->records = (pmp_music_record_t*)ucs2malloc(sizeof(pmp_music_record_t) * num_records); + pmpmi->num_records = num_records; + pmplib_records_clone(pmpmi->records, records, num_records); + + return 0; + } + +static result_t pmpmusic_get_records(pmp_music_t* music, pmp_music_record_t* records, uint32_t* num_records) +{ + pmp_t* pmp = music->pmp; + pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + + if (!records) { + *num_records = pmpmi->num_records; + return 0; + } else if (*num_records == pmpmi->num_records) { + pmplib_records_clone(records, pmpmi->records, pmpmi->num_records); + return 0; + } else { + return PMPERR_INSUFFICIENTMEMORY; + } +} + +static result_t pmpmusic_dump(pmp_music_t* music, FILE *fp, int level) +{ + ipod_t ipod; + result_t ret = 0; + ucs2char_t itunesdb[MAX_PATH]; + + // Initialize IP3DB. + ipod_init(&ipod); + + // Read the music database. + set_filenames(itunesdb, music->pmp); + ret = ipod_read(&ipod, itunesdb); + if (ret) { + goto exit_this; + } + + ret = ipod_dump(&ipod, fp); + if (ret) { + goto exit_this; + } + +exit_this: + ipod_finish(&ipod); + return ret; +} + +static result_t pmpmusic_set_playlists(pmp_music_t* music, const pmp_playlist_t* playlists, uint32_t num_playlists) +{ + return PMPERR_NOTIMPLIMENTED; +} Property changes on: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj (rev 0) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,231 @@ +<?xml version="1.0" encoding="shift_jis"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="pmp_ipod" + ProjectGUID="{529F5BE9-291E-4BCF-BE90-5E64B780340F}" + RootNamespace="pmp_ipod" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="$(SolutionDir)debug" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="$(SolutionDir)include" + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;PMP_IPOD_EXPORTS" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="2" + GenerateDebugInformation="true" + SubSystem="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="$(SolutionDir)release" + IntermediateDirectory="$(ConfigurationName)" + ConfigurationType="2" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="$(SolutionDir)include" + PreprocessorDefinitions="WIN32;_WINDOWS;_USRDLL;PMP_IPOD_EXPORTS" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLinkerTool" + LinkIncremental="1" + GenerateDebugInformation="true" + SubSystem="2" + OptimizeReferences="2" + EnableCOMDATFolding="2" + TargetMachine="1" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCManifestTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCAppVerifierTool" + /> + <Tool + Name="VCWebDeploymentTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="\x83\\x81[\x83X \x83t\x83@\x83C\x83\x8B" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath=".\ipod.c" + > + </File> + <File + RelativePath=".\itunesdb.c" + > + </File> + <File + RelativePath=".\pmp_ipod.c" + > + </File> + <File + RelativePath=".\serialize.c" + > + </File> + <File + RelativePath=".\util.c" + > + </File> + </Filter> + <Filter + Name="\x83w\x83b\x83_\x81[ \x83t\x83@\x83C\x83\x8B" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath=".\ipod.h" + > + </File> + <File + RelativePath=".\itunesdb.h" + > + </File> + <File + RelativePath=".\serialize.h" + > + </File> + <File + RelativePath=".\util.h" + > + </File> + </Filter> + <Filter + Name="\x83\x8A\x83\\x81[\x83X \x83t\x83@\x83C\x83\x8B" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Added: trunk/pmplib/lib/pmp_ipod/serialize.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/serialize.c (rev 0) +++ trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-21 15:56:22 UTC (rev 382) @@ -0,0 +1,303 @@ +/* + * Data serializer (with byte-order consideration). + * + * 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$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ + +#include <os.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pmplib/ucs2char.h> + +#include "util.h" +#include "serialize.h" + +static int check(serializer_t* sio, size_t size) +{ + if (0 < sio->mode) { + if (sio->size < sio->offset + size) { + sio->size += sio->unit; + sio->base = (uint8_t*)realloc(sio->base, sio->size); + if (!sio->base) { + return 1; + } + } + } else if (sio->mode < 0) { + if (sio->limit < sio->offset + size) { + return 1; + } + if (sio->size < sio->offset + size) { + return 1; + } + } + return 0; +} + +void serialize_init_read(serializer_t* sio, uint8_t* base, size_t size) +{ + memset(sio, 0, sizeof(*sio)); + sio->base = base; + sio->size = size; + sio->limit = size; + sio->mode = -1; +} + +void serialize_init_write(serializer_t* sio, size_t unit) +{ + memset(sio, 0, sizeof(*sio)); + sio->unit = unit; + sio->mode = 1; +} + +void serialize_init_dump(serializer_t* sio, FILE *fp, size_t unit) +{ + memset(sio, 0, sizeof(*sio)); + sio->fp = fp; + sio->unit = unit; + sio->mode = 0; +} + +void serialize_finish(serializer_t* sio) +{ + if (0 < sio->mode) { + free(sio->base); + } + memset(sio, 0, sizeof(*sio)); +} + + +int serialize_uint8(serializer_t* sio, const char *name, const char *format, uint8_t* value) +{ + if (check(sio, sizeof(uint8_t))) return 1; + + if (0 < sio->mode) { + sio->base[sio->offset++] = *value; + } else if (sio->mode < 0) { + *value = sio->base[sio->offset++]; + } else { + serialize_indent(sio); + fprintf(sio->fp, "%s: ", name); + fprintf(sio->fp, format, *value); + fputc('\n', sio->fp); + } + return 0; +} + +int serialize_uint8_array(serializer_t* sio, const char *name, const char *format, uint8_t* array, size_t length) +{ + size_t i; + + if (check(sio, length)) return 1; + + if (0 < sio->mode) { + for (i = 0;i < length;++i) { + sio->base[sio->offset++] = array[i]; + } + } else if (sio->mode < 0) { + for (i = 0;i < length;++i) { + array[i] = sio->base[sio->offset++]; + } + } else { + serialize_indent(sio); + fprintf(sio->fp, "%s: ", name); + for (i = 0;i < length;++i) { + fprintf(sio->fp, format, array[i]); + } + fputc('\n', sio->fp); + } + return 0; +} + +int serialize_uint16le(serializer_t* sio, const char *name, const char *format, uint16_t* value) +{ + if (check(sio, sizeof(uint16_t))) return 1; + + if (0 < sio->mode) { + sio->base[sio->offset++] = (uint8_t)(*value & 0xFF); + sio->base[sio->offset++] = (uint8_t)(*value >> 8); + } else if (sio->mode < 0) { + *value = ((uint16_t)sio->base[sio->offset++]); + *value |= ((uint16_t)sio->base[sio->offset++] << 8); + } else { + serialize_indent(sio); + fprintf(sio->fp, "%s: ", name); + fprintf(sio->fp, format, *value); + fputc('\n', sio->fp); + } + return 0; +} + +int serialize_uint32le(serializer_t* sio, const char *name, const char *format, uint32_t* value) +{ + if (check(sio, sizeof(uint32_t))) return 1; + + if (0 < sio->mode) { + sio->base[sio->offset++] = (uint8_t)(*value & 0xFF); + sio->base[sio->offset++] = (uint8_t)(*value >> 8); + sio->base[sio->offset++] = (uint8_t)(*value >> 16); + sio->base[sio->offset++] = (uint8_t)(*value >> 24); + } else if (sio->mode < 0) { + *value = ((uint32_t)sio->base[sio->offset++]); + *value |= ((uint32_t)sio->base[sio->offset++] << 8); + *value |= ((uint32_t)sio->base[sio->offset++] << 16); + *value |= ((uint32_t)sio->base[sio->offset++] << 24); + } else { + serialize_indent(sio); + fprintf(sio->fp, "%s: ", name); + fprintf(sio->fp, format, *value); + fputc('\n', sio->fp); + } + return 0; +} + +int serialize_int32le(serializer_t* sio, const char *name, const char *format, int32_t* value) +{ + return serialize_uint32le(sio, name, format, (uint32_t*)value); +} + +int serialize_uint64le(serializer_t* sio, const char *name, const char *format, uint64_t* value) +{ + if ... [truncated message content] |