From: <ny...@us...> - 2007-02-28 08:17:04
|
Revision: 401 http://svn.sourceforge.net/pmplib/?rev=401&view=rev Author: nyaochi Date: 2007-02-28 00:17:04 -0800 (Wed, 28 Feb 2007) Log Message: ----------- Added reader/dumper for "Play Count" file. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/ipod.c trunk/pmplib/lib/pmp_ipod/ipod.h trunk/pmplib/lib/pmp_ipod/pmp_ipod.c trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj Added Paths: ----------- trunk/pmplib/lib/pmp_ipod/playcounts.c trunk/pmplib/lib/pmp_ipod/playcounts.h Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-27 15:20:57 UTC (rev 400) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-28 08:17:04 UTC (rev 401) @@ -39,6 +39,7 @@ #include "ipod.h" #include "ipodprop.h" #include "itunesdb.h" +#include "playcounts.h" #define COMP(a, b) ((a)>(b))-((a)<(b)) @@ -47,6 +48,7 @@ "apple_ipod", "Apple", "iPod", "UM", "---", "---", "iPod_Control\\iTunes\\iTunesDB", + "iPod_Control\\iTunes\\Play Counts", ".mp3\0.m4a\0", {PMPCODEC_MPEGLAYER3, PMPCODEC_MPEG4AUDIO, 0, 0, 0, 0, 0, 0}, "iPod_Control", "iPod_Control\\Music", "Playlists", @@ -56,6 +58,7 @@ NULL, NULL, NULL, NULL, + NULL, {0, 0, 0, 0, 0, 0, 0, 0}, NULL, NULL, NULL, }, @@ -155,19 +158,23 @@ void ipod_init(ipod_t* ipod) { - ipod->itunesdb = calloc(1, sizeof(itunesdb_chunk_t)); + ipod->itunesdb = (itunesdb_chunk_t*)calloc(1, sizeof(itunesdb_chunk_t)); + ipod->pcs = (playcounts_t*)calloc(1, sizeof(playcounts_t)); } void ipod_finish(ipod_t* ipod) { + playcounts_finish(ipod->pcs); itunesdb_finish(ipod->itunesdb); + free(ipod->pcs); free(ipod->itunesdb); } -result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb) +result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb, const ucs2char_t* playcounts) { FILE *fp = NULL; + /* Read iTunesDB. */ fp = ucs2fopen(itunesdb, "rb"); if (fp) { serializer_t sio; @@ -179,12 +186,28 @@ serialize_init_read(&sio, buffer, (size_t)size); itunesdb_read(ipod->itunesdb, &sio); - serialize_finish(&sio); + serialize_finish(&sio); /* This will free the buffer. */ + } else { + return 1; + } - return 0; + /* Read "Play Counts". */ + fp = ucs2fopen(playcounts, "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); + playcounts_serialize(ipod->pcs, &sio); + serialize_finish(&sio); /* This will free the buffer. */ } else { return 1; } + return 0; } result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb) @@ -212,7 +235,15 @@ { serializer_t sio; serialize_init_dump(&sio, fpo, 2); + + fprintf(fpo, "[iTunesDB]\n"); itunesdb_repr(ipod->itunesdb, 0, &sio); + fprintf(fpo, "\n"); + + fprintf(fpo, "[Play Counts]\n"); + playcounts_serialize(ipod->pcs, &sio); + fprintf(fpo, "\n"); + serialize_finish(&sio); return 0; } Modified: trunk/pmplib/lib/pmp_ipod/ipod.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-27 15:20:57 UTC (rev 400) +++ trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-28 08:17:04 UTC (rev 401) @@ -34,6 +34,7 @@ const char *min_version; const char *max_version; const char *itunesdb_filename; + const char *playcounts_filename; const char *extensions; uint32_t codecs[8]; const char *path_to_system; @@ -44,8 +45,12 @@ struct tag_itunesdb_chunk; typedef struct tag_itunesdb_chunk itunesdb_chunk_t; +struct tag_playcounts; +typedef struct tag_playcounts playcounts_t; + typedef struct { itunesdb_chunk_t* itunesdb; + playcounts_t* pcs; } ipod_t; const ipod_descriptor_t* ipod_detect(const ucs2char_t* path_to_device, const char *id, pmp_device_information_t* ptr_info); @@ -54,7 +59,7 @@ 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_read(ipod_t* ipod, const ucs2char_t* itunesdb, const ucs2char_t* playcounts); result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb); result_t ipod_dump(ipod_t* ipod, FILE *fpo); Added: trunk/pmplib/lib/pmp_ipod/playcounts.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/playcounts.c (rev 0) +++ trunk/pmplib/lib/pmp_ipod/playcounts.c 2007-02-28 08:17:04 UTC (rev 401) @@ -0,0 +1,147 @@ +/* + * Reader and dumper for "Play Counts" file. + * + * 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 "playcounts.h" + +static void playcount_init(playcount_entry_t* entry) +{ + memset(entry, 0, sizeof(*entry)); +} + +static int playcount_serialize(playcount_entry_t* entry, const playcounts_t* pcs, serializer_t* sio) +{ + size_t begin = serialize_tell(sio); + + if (serialize_uint32le(sio, "play_count", "%u", &entry->play_count)) return 1; + if (serialize_uint32le(sio, "last_played", "%u", &entry->last_played)) return 1; + if (serialize_uint32le(sio, "audio_bookmark", "%u", &entry->audio_bookmark)) return 1; + + if (serialize_reading(sio) && begin + pcs->entry_size <= serialize_tell(sio)) return 0; + if (serialize_uint32le(sio, "rating", "%u", &entry->rating)) return 1; + + if (serialize_reading(sio) && begin + pcs->entry_size <= serialize_tell(sio)) return 0; + if (serialize_uint32le(sio, "unknown", "%u", &entry->unknown)) return 1; + + if (serialize_reading(sio) && begin + pcs->entry_size <= serialize_tell(sio)) return 0; + if (serialize_uint32le(sio, "skip_count", "%u", &entry->skip_count)) return 1; + if (serialize_uint32le(sio, "last_skipped", "%u", &entry->last_skipped)) return 1; + + /* Padding data if any. */ + if (serialize_reading(sio)) { + if (serialize_tell(sio) < begin + pcs->entry_size) { + entry->padding_size = pcs->entry_size - (serialize_tell(sio) - begin); + entry->padding = (uint8_t*)calloc(entry->padding_size, 1); + } + } + if (entry->padding) { + if (serialize_uint8_array(sio, "padding", "%02X ", entry->padding, entry->padding_size)) return 1; + } + + return 0; +} + +void playcounts_init(playcounts_t* pcs) +{ + memset(pcs, 0, sizeof(*pcs)); + strncpy(pcs->id, "mhdp", 4); + pcs->header_size = 0x60; + pcs->entry_size = 0x1C; +} + +void playcounts_finish(playcounts_t* pcs) +{ + free(pcs->entries); +} + +int playcounts_serialize(playcounts_t* pcs, serializer_t* sio) +{ + uint32_t i; + size_t begin = serialize_tell(sio); + + if (serialize_reading(sio)) { + if (serialize_uint8_array(sio, "id", "%c ", pcs->id, sizeof(pcs->id))) return 1; + } else if (serialize_dumping(sio)) { + serialize_indent(sio); + fprintf(sio->fp, "Chunk %c%c%c%c = {\n", pcs->id[0], pcs->id[1], pcs->id[2], pcs->id[3]); + } + serialize_indent_ascend(sio); + + if (serialize_uint32le(sio, "header_size", "%u", &pcs->header_size)) return 1; + if (serialize_uint32le(sio, "entry_size", "%u", &pcs->entry_size)) return 1; + if (serialize_uint32le(sio, "num_entries", "%u", &pcs->num_entries)) return 1; + + /* Padding data if any. */ + if (serialize_reading(sio)) { + if (serialize_tell(sio) < begin + pcs->header_size) { + pcs->padding_size = pcs->header_size - (serialize_tell(sio) - begin); + pcs->padding = (uint8_t*)calloc(pcs->padding_size, 1); + } + } + if (pcs->padding) { + if (serialize_uint8_array(sio, "padding", "%02X ", pcs->padding, pcs->padding_size)) return 1; + } + + if (serialize_reading(sio)) { + pcs->entries = (playcount_entry_t*)calloc(pcs->num_entries, sizeof(playcount_entry_t)); + for (i = 0;i < pcs->num_entries;++i) { + playcount_init(&pcs->entries[i]); + } + } + + for (i = 0;i < pcs->num_entries;++i) { + if (serialize_dumping(sio)) { + serialize_indent(sio); + fprintf(sio->fp, "entry (%d) = {\n", i); + serialize_indent_ascend(sio); + } + if (playcount_serialize(&pcs->entries[i], pcs, sio)) return 1; + if (serialize_dumping(sio)) { + serialize_indent_descend(sio); + serialize_indent(sio); + fprintf(sio->fp, "}\n"); + } + } + + serialize_indent_descend(sio); + if (serialize_dumping(sio)) { + serialize_indent(sio); + fprintf(sio->fp, "}\n"); + } + + return 0; +} Property changes on: trunk/pmplib/lib/pmp_ipod/playcounts.c ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/playcounts.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/playcounts.h (rev 0) +++ trunk/pmplib/lib/pmp_ipod/playcounts.h 2007-02-28 08:17:04 UTC (rev 401) @@ -0,0 +1,54 @@ +/* + * Reader and dumper for "Play Counts" file. + * + * 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 __PLAYCOUNTS_H__ +#define __PLAYCOUNTS_H__ + +typedef struct { + uint32_t play_count; + uint32_t last_played; + uint32_t audio_bookmark; + uint32_t rating; + uint32_t unknown; + uint32_t skip_count; + uint32_t last_skipped; + + int32_t padding_size; + uint8_t* padding; +} playcount_entry_t; + +struct tag_playcounts { + int8_t id[4]; + uint32_t header_size; + uint32_t entry_size; + uint32_t num_entries; + int32_t padding_size; + uint8_t* padding; + playcount_entry_t* entries; +}; + +void playcounts_init(playcounts_t* pcs); +void playcounts_finish(playcounts_t* pcs); +int playcounts_serialize(playcounts_t* pcs, serializer_t* sio); + +#endif/*__PLAYCOUNTS_H__*/ Property changes on: trunk/pmplib/lib/pmp_ipod/playcounts.h ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-27 15:20:57 UTC (rev 400) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-28 08:17:04 UTC (rev 401) @@ -145,16 +145,25 @@ memset(info, 0, sizeof(*info)); } -static void set_filenames(ucs2char_t *itunesdb, pmp_t *pmp) +static void set_filenames(ucs2char_t *itunesdb, ucs2char_t* playcounts, 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); + if (itunesdb) { + ucs2cpy(itunesdb, pmp->info.path_to_root); + filepath_addslash(itunesdb); + ucs2 = mbsdupucs2(pmpi->decl->itunesdb_filename); + ucs2cat(itunesdb, ucs2); + ucs2free(ucs2); + } + if (playcounts) { + ucs2cpy(playcounts, pmp->info.path_to_root); + filepath_addslash(playcounts); + ucs2 = mbsdupucs2(pmpi->decl->playcounts_filename); + ucs2cat(playcounts, ucs2); + ucs2free(ucs2); + } } @@ -404,13 +413,13 @@ 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]; + ucs2char_t itunesdb[MAX_PATH], playcounts[MAX_PATH]; // Initialize ipod library. ipod_init(&ipod); // Read the music database. - set_filenames(itunesdb, music->pmp); + set_filenames(itunesdb, playcounts, music->pmp); if (pmp->flag & PMPOF_MUSIC_DB_WRITE) { ipod_set(&ipod, pmpmi->records, pmpmi->num_records, pmpmi->playlists, pmpmi->num_playlists); @@ -458,14 +467,14 @@ { ipod_t ipod; result_t ret = 0; - ucs2char_t itunesdb[MAX_PATH]; + ucs2char_t itunesdb[MAX_PATH], playcounts[MAX_PATH]; // Initialize IP3DB. ipod_init(&ipod); // Read the music database. - set_filenames(itunesdb, music->pmp); - ret = ipod_read(&ipod, itunesdb); + set_filenames(itunesdb, playcounts, music->pmp); + ret = ipod_read(&ipod, itunesdb, playcounts); if (ret) { goto exit_this; } Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-27 15:20:57 UTC (rev 400) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-28 08:17:04 UTC (rev 401) @@ -186,6 +186,10 @@ > </File> <File + RelativePath=".\playcounts.c" + > + </File> + <File RelativePath=".\pmp_ipod.c" > </File> @@ -216,6 +220,10 @@ > </File> <File + RelativePath=".\playcounts.h" + > + </File> + <File RelativePath=".\serialize.h" > </File> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |