|
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.
|