You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
(2) |
Apr
(4) |
May
(6) |
Jun
(56) |
Jul
(101) |
Aug
(14) |
Sep
|
Oct
(1) |
Nov
|
Dec
(40) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(66) |
Feb
(106) |
Mar
(1) |
Apr
(2) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
(10) |
Oct
(7) |
Nov
|
Dec
|
2008 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <ny...@us...> - 2007-02-27 15:20:57
|
Revision: 400 http://svn.sourceforge.net/pmplib/?rev=400&view=rev Author: nyaochi Date: 2007-02-27 07:20:57 -0800 (Tue, 27 Feb 2007) Log Message: ----------- Implemented playlist conversion for iPod players. Modified Paths: -------------- trunk/pmplib/frontend/easypmp/cui/main.c trunk/pmplib/lib/pmp_ipod/ipod.c trunk/pmplib/lib/pmp_ipod/pmp_ipod.c Modified: trunk/pmplib/frontend/easypmp/cui/main.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/main.c 2007-02-27 14:29:36 UTC (rev 399) +++ trunk/pmplib/frontend/easypmp/cui/main.c 2007-02-27 15:20:57 UTC (rev 400) @@ -472,12 +472,7 @@ // Convert playlists. if (opt.verb & MODE_PLAYLIST) { - if (opt.verb & MODE_SETTLE) { - // Playlist referring to music_links. - easypmp_playlist(pmp, &playlists, &music_links, &opt, records, num_records, easypmp_progress, NULL); - } else { - easypmp_playlist(pmp, &playlists, &musics, &opt, records, num_records, easypmp_progress, NULL); - } + easypmp_playlist(pmp, &playlists, &musics, &opt, records, num_records, easypmp_progress, NULL); } // Dump the database if specified. Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-27 14:29:36 UTC (rev 399) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-27 15:20:57 UTC (rev 400) @@ -434,6 +434,7 @@ 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)); + const static ucs2char_t ucs2cs_master[] = {'M','a','s','t','e','r',0}; if (!si) { return 1; @@ -454,7 +455,7 @@ mhod = itunesdb_new_child(mhyp); if (mhod) { itunesdb_init(mhod, "mhod", "title"); - itunesdb_set_mhod_string(mhod, L"Nyaopod"); + itunesdb_set_mhod_string(mhod, ucs2cs_master); } /* Construct an "mhod" chunk for title index. */ @@ -526,6 +527,70 @@ return 0; } +static uint32_t get_record_index(const ucs2char_t* filename, const pmp_music_record_t* records, int num_records) +{ + uint32_t i; + + for (i = 0;i < num_records;++i) { + if (ucs2icmp(records[i].filename, filename) == 0) { + break; + } + } + return i; +} + +static int set_playlist(itunesdb_chunk_t* mhyp, const pmp_playlist_t* playlist, 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; + + mhyp_data->flag_master = 0; + 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, playlist->name); + } + + /* End of "mhod" chunk(s). */ + mhyp_data->num_mhod = mhyp->num_children; + + /* */ + for (i = 0;i < playlist->num_entries;++i) { + uint32_t index = get_record_index(playlist->entries[i], records, num_records); + + if (index < num_records) { + 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 = index; + mhip_data->group_id = index + 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; @@ -582,19 +647,27 @@ if (mhlp) { itunesdb_init(mhlp, "mhlp", NULL); + /* Create a master playlist. */ 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); } + + /* Create user's playlists. */ + for (i = 0;i < num_playlists;++i) { + mhyp = itunesdb_new_child(mhlp); + if (mhyp) { + chunk_mhyp_t* mhyp_data = NULL; + itunesdb_init(mhyp, "mhyp", NULL); + set_playlist(mhyp, &playlists[i], records, num_records); + } + } } } mhbd_data->num_children = mhbd->num_children; - ipod->itunesdb = mhbd; return 0; } Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-27 14:29:36 UTC (rev 399) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-27 15:20:57 UTC (rev 400) @@ -482,5 +482,15 @@ static result_t pmpmusic_set_playlists(pmp_music_t* music, const pmp_playlist_t* playlists, uint32_t num_playlists) { - return PMPERR_NOTIMPLIMENTED; + pmp_t* pmp = music->pmp; + pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + + /* Free playlists attached to pmpmi. */ + pmplib_playlists_finish(pmpmi->playlists, pmpmi->num_playlists); + + /* Allocate new playlists. */ + pmpmi->playlists = (pmp_playlist_t*)ucs2malloc(sizeof(pmp_playlist_t) * num_playlists); + pmpmi->num_playlists = num_playlists; + pmplib_playlists_clone(pmpmi->playlists, playlists, num_playlists); + return 0;; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-27 14:29:39
|
Revision: 399 http://svn.sourceforge.net/pmplib/?rev=399&view=rev Author: nyaochi Date: 2007-02-27 06:29:36 -0800 (Tue, 27 Feb 2007) Log Message: ----------- Fixed a bug in settlement operation. Modified Paths: -------------- trunk/pmplib/frontend/easypmp/common/settle.c trunk/pmplib/lib/filepath/filepath_win32.c Modified: trunk/pmplib/frontend/easypmp/common/settle.c =================================================================== --- trunk/pmplib/frontend/easypmp/common/settle.c 2007-02-27 14:15:54 UTC (rev 398) +++ trunk/pmplib/frontend/easypmp/common/settle.c 2007-02-27 14:29:36 UTC (rev 399) @@ -20,7 +20,7 @@ * */ -/* $Id:$ */ +/* $Id$ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -103,13 +103,17 @@ } n = 0; - for (i = 0;i < musics->num_elements;++i) { + i = 0; + while (i < musics->num_elements) { ucs2cpy(music, musics->elements[i].name); // Check the existence of a link referring to the music file. for (j = 0;j < music_links->num_elements;++j) { // Obtain the filename pointed by this link. ucs2cpy(link, music_links->elements[j].name); + if (i == 20) { + i = 20; + } if (filepath_followlink(link, target) == 0) { if (ucs2icmp(music, target) == 0) { break; @@ -121,28 +125,31 @@ if (j == music_links->num_elements) { filepath_removefile(music); remove_file_from_list(musics, i); - --i; if (progress(instance, EASYPMPP_REMOVE_UNREF|EASYPMPSP_PROGRESS, n, 0, music) != 0) { result = EASYPMPE_CANCEL; goto error_exit; } n++; + } else { + ++i; } } - for (i = 0;i < music_links->num_elements;++i) { + i = 0; + while (i < music_links->num_elements) { ucs2cpy(link, music_links->elements[j].name); if (filepath_followlink(link, target) != 0) { filepath_removelinkfile(link); remove_file_from_list(music_links, i); - --i; if (progress(instance, EASYPMPP_REMOVE_UNREF|EASYPMPSP_PROGRESS, n, 0, music) != 0) { result = EASYPMPE_CANCEL; goto error_exit; } n++; + } else { + ++i; } } @@ -160,7 +167,8 @@ } n = 0; - for (i = 0;i < musics_unsettled->num_elements;++i) { + i = 0; + while (i < musics_unsettled->num_elements) { // Source music file. ucs2cpy(music, musics_unsettled->elements[i].name); @@ -181,7 +189,6 @@ filepath_movefile(music, target); add_file_to_list(musics, target); remove_file_from_list(musics_unsettled, i); - --i; // Create a symbolic link (or shortcut) from the source to the destination. filepath_linkfile(target, music); @@ -207,7 +214,8 @@ } n = 0; - for (i = 0;i < music_links->num_elements;++i) { + i = 0; + while (i < music_links->num_elements) { // Source music link. ucs2cpy(link, music_links->elements[i].name); @@ -228,13 +236,14 @@ // Remove the link file. filepath_removelinkfile(link); remove_file_from_list(music_links, i); - --i; if (progress(instance, EASYPMPP_UNSETTLE|EASYPMPSP_PROGRESS, n, 0, music) != 0) { result = EASYPMPE_CANCEL; goto error_exit; } n++; + } else { + ++i; } } Modified: trunk/pmplib/lib/filepath/filepath_win32.c =================================================================== --- trunk/pmplib/lib/filepath/filepath_win32.c 2007-02-27 14:15:54 UTC (rev 398) +++ trunk/pmplib/lib/filepath/filepath_win32.c 2007-02-27 14:29:36 UTC (rev 399) @@ -280,6 +280,7 @@ fgets(buff, sizeof(buff)-1, fp); utf8toucs2(target, MAX_PATH, buff, strlen(buff)+1); filepath_combinepath(org, MAX_PATH, link, target); + fclose(fp); return 0; } else { return -1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-27 14:18:07
|
Revision: 398 http://svn.sourceforge.net/pmplib/?rev=398&view=rev Author: nyaochi Date: 2007-02-27 06:15:54 -0800 (Tue, 27 Feb 2007) Log Message: ----------- Automatic detection of iPod player by issuing SCSI INQUIRY commands to the device. The detection mechanism is based on the information available at: http://www.ipodlinux.org/Device_Information This code might not work with iPod generation 3 or earlier. The routine to manipulate SCSI devices uses SPTI WinNT API (for Windows 2000/XP/Vista). This code will not run on Win9x environments. The source code "ipodprop_win32spti.c" requires Windows DDK to be compiled; I generated ipodprop_win32spti.lib for those who do not install DDK. 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/ipodprop.h trunk/pmplib/lib/pmp_ipod/win32spti/ trunk/pmplib/lib/pmp_ipod/win32spti/README.txt trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.c trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.lib trunk/pmplib/lib/pmp_ipod/win32spti/makefile trunk/pmplib/lib/pmp_ipod/win32spti/sources Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-27 09:45:39 UTC (rev 397) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-27 14:15:54 UTC (rev 398) @@ -37,6 +37,7 @@ #include "serialize.h" #include "util.h" #include "ipod.h" +#include "ipodprop.h" #include "itunesdb.h" #define COMP(a, b) ((a)>(b))-((a)<(b)) @@ -60,8 +61,66 @@ }, }; -const ipod_descriptor_t* ipod_detect(const ucs2char_t* path_to_device, const char *id) +static int get_string_value(const char *xml, const char *key, char *value, size_t size) { + char *p, *q, *r; + char *keystr = (char*)alloca(strlen(key) + 5 + 6 + 1); + static const char *xeo_string = "<string>"; + static const char *xee_string = "</string>"; + + sprintf(keystr, "<key>%s</key>", key); + p = strstr(xml, keystr); + if (p) { + q = strstr(p += strlen(keystr), xeo_string); + if (q) { + r = strstr(q += strlen(xeo_string), xee_string); + if (r && (size_t)(r - q) < size) { + strncpy(value, q, r-q); + value[r-q] = 0; + return 0; + } + } + } + return -1; +} + +static int detect_model( + const ucs2char_t* path_to_device, + const ipod_descriptor_t* md, + pmp_device_information_t* ptr_info + ) +{ + int ret = 0; + ipodprop_t ip; + char *path = ucs2dupmbs(path_to_device); + + ipodprop_init(&ip); + + if (ipodprop_get(path, &ip) == 0) { + if (ip.vendor && strncmp(ip.vendor, "Apple", 5) == 0 && + ip.product && strncmp(ip.product, "iPod", 4) == 0) { + /* This is iPod. */ + ret = 1; + + /* Obtain the version number from the XML. */ + if (ip.info) { + get_string_value(ip.info, "VisibleBuildID", (char*)ptr_info->decl.version, PMP_DECLSIZE); + get_string_value(ip.info, "Language", (char*)ptr_info->decl.language, PMP_DECLSIZE); + } + } + } + + ipodprop_finish(&ip); + ucs2free(path); + return ret; +} + +const ipod_descriptor_t* ipod_detect( + const ucs2char_t* path_to_device, + const char *id, + pmp_device_information_t* ptr_info + ) +{ const ipod_descriptor_t* md = NULL; // Find a suitable model for the device. @@ -70,8 +129,15 @@ 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, ptr_info); break; } + } else { + // Detect the model automatically. + if (detect_model(path_to_device, md, ptr_info)) { + break; + } } } return md->id ? md : NULL; @@ -123,6 +189,7 @@ result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb) { + result_t ret = 0; FILE *fp = NULL; serializer_t sio; @@ -130,11 +197,15 @@ itunesdb_write(ipod->itunesdb, &sio); fp = ucs2fopen(itunesdb, "wb"); - fwrite(sio.base, 1, sio.offset, fp); - fclose(fp); + if (fp) { + fwrite(sio.base, 1, sio.offset, fp); + fclose(fp); + } else { + ret = PMPERR_OPENFORWRITE; + } serialize_finish(&sio); - return 0; + return ret; } result_t ipod_dump(ipod_t* ipod, FILE *fpo) Modified: trunk/pmplib/lib/pmp_ipod/ipod.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-27 09:45:39 UTC (rev 397) +++ trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-27 14:15:54 UTC (rev 398) @@ -48,7 +48,7 @@ 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_detect(const ucs2char_t* path_to_device, const char *id, pmp_device_information_t* ptr_info); const ipod_descriptor_t* ipod_next_descriptor(const ipod_descriptor_t* md); void ipod_init(ipod_t* ipod); Added: trunk/pmplib/lib/pmp_ipod/ipodprop.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipodprop.h (rev 0) +++ trunk/pmplib/lib/pmp_ipod/ipodprop.h 2007-02-27 14:15:54 UTC (rev 398) @@ -0,0 +1,45 @@ +/* + * iPod property retrieval. + * + * Copyright (c) 2005-2007 Naoaki Okazaki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* $Id:$ */ + +#ifndef __IPODPROP_H__ +#define __IPODPROP_H__ + +#ifdef _WIN32 +#define IPODPROPAPI __cdecl +#else +#define IPODPROPAPI +#endif/*_WIN32*/ + +typedef struct { + char* vendor; + char* product; + char* revision; + char* info; +} ipodprop_t; + +void IPODPROPAPI ipodprop_init(ipodprop_t *prop); +void IPODPROPAPI ipodprop_finish(ipodprop_t *prop); +int IPODPROPAPI ipodprop_get(const char *path_to_root, ipodprop_t *prop); + +#endif/*__IPODPROP_H__*/ Property changes on: trunk/pmplib/lib/pmp_ipod/ipodprop.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 09:45:39 UTC (rev 397) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-27 14:15:54 UTC (rev 398) @@ -185,7 +185,7 @@ *ptr_pmp = 0; // Find a suitable model for the device. - md = ipod_detect(path_to_device, id); + md = ipod_detect(path_to_device, id, &info); if (!md) { return PMPERR_DEVICENOTFOUND; } Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-27 09:45:39 UTC (rev 397) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-27 14:15:54 UTC (rev 398) @@ -61,6 +61,7 @@ /> <Tool Name="VCLinkerTool" + AdditionalDependencies=".\win32spti\ipodprop_win32spti.lib shlwapi.lib" LinkIncremental="2" GenerateDebugInformation="true" SubSystem="2" @@ -193,10 +194,6 @@ > </File> <File - RelativePath=".\settledb.c" - > - </File> - <File RelativePath=".\util.c" > </File> @@ -211,15 +208,15 @@ > </File> <File - RelativePath=".\itunesdb.h" + RelativePath=".\ipodprop.h" > </File> <File - RelativePath=".\serialize.h" + RelativePath=".\itunesdb.h" > </File> <File - RelativePath=".\settledb.h" + RelativePath=".\serialize.h" > </File> <File Added: trunk/pmplib/lib/pmp_ipod/win32spti/README.txt =================================================================== --- trunk/pmplib/lib/pmp_ipod/win32spti/README.txt (rev 0) +++ trunk/pmplib/lib/pmp_ipod/win32spti/README.txt 2007-02-27 14:15:54 UTC (rev 398) @@ -0,0 +1 @@ +This source code requires Microsoft Windows DDK to be compiled. Property changes on: trunk/pmplib/lib/pmp_ipod/win32spti/README.txt ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Added: trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.c (rev 0) +++ trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.c 2007-02-27 14:15:54 UTC (rev 398) @@ -0,0 +1,286 @@ +/* + * iPod property retrieval through Win32 SPTI (for 2000/XP/Vista). + * + * Copyright (c) 2005-2007 Naoaki Okazaki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* I used the following information to access to the property of + * iPod players: + * http://www.ipodlinux.org/Device_Information + * + * This source code is based on the sample program found in Windows + * DDK, Enumdisk.c written by Raju Ramanathan. + */ + +/* $Id:$ */ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <windows.h> +#include <shlwapi.h> +#include <devioctl.h> +#include <ntdddisk.h> +#include <ntddscsi.h> + +#include "../ipodprop.h" + + + +#define CDB6GENERIC_LENGTH 6 +#define CDB10GENERIC_LENGTH 10 + +#define SCSIOP_INQUIRY 0x12 + +typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS { + SCSI_PASS_THROUGH Spt; + ULONG Filler; + UCHAR SenseBuf[32]; + UCHAR DataBuf[512]; +} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; + + + +void __cdecl ipodprop_init(ipodprop_t *prop) +{ + memset(prop, 0, sizeof(*prop)); +} + +void __cdecl ipodprop_finish(ipodprop_t *prop) +{ + free(prop->vendor); + free(prop->product); + free(prop->revision); + free(prop->info); + memset(prop, 0, sizeof(*prop)); +} + +int __cdecl ipodprop_get(const char *path_to_root, ipodprop_t *prop) +{ + int ret = 0; + DWORD i; + int j, k, n; + BOOL status; + UCHAR *p, outBuf[512]; + STORAGE_PROPERTY_QUERY query; + PSTORAGE_DEVICE_DESCRIPTOR devDesc; + SCSI_PASS_THROUGH_WITH_BUFFERS sptwb; + HANDLE hDevice = INVALID_HANDLE_VALUE; + ULONG length = 0, returned = 0; + int num_pages = 0; + UCHAR pages[256]; + size_t info_size = 0; + CHAR drive[7]; + + memset(pages, 0, sizeof(pages)); + + /* Obtain the drive letter. */ + drive[0] = '\\'; + drive[1] = '\\'; + drive[2] = '.'; + drive[3] = '\\'; + drive[4] = 'A' + PathGetDriveNumber(path_to_root); + drive[5] = ':'; + drive[6] = 0; + + /* Open the device. */ + hDevice = CreateFile( + drive, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if (hDevice == INVALID_HANDLE_VALUE) { + ret = -1; + goto error_exit; + } + + /* Query the property of the device. */ + query.PropertyId = StorageDeviceProperty; + query.QueryType = PropertyStandardQuery; + status = DeviceIoControl( + hDevice, + IOCTL_STORAGE_QUERY_PROPERTY, + &query, + sizeof(STORAGE_PROPERTY_QUERY), + &outBuf, + 512, + &returned, + NULL + ); + if (!status) { + ret = -1; + goto error_exit; + } + + /* Obtain vendor, product and revision of the device. */ + devDesc = (PSTORAGE_DEVICE_DESCRIPTOR)outBuf; + p = (PUCHAR)outBuf; + if (devDesc->VendorIdOffset && p[devDesc->VendorIdOffset]) { + for (n = 0, i = devDesc->VendorIdOffset;p[i] && i < returned;i++) { + n++; + } + prop->vendor = (char*)calloc(n+1, sizeof(char)); + strncpy(prop->vendor, &p[devDesc->VendorIdOffset], n); + } + if (devDesc->ProductIdOffset && p[devDesc->ProductIdOffset]) { + for (n = 0, i = devDesc->ProductIdOffset;p[i] && i < returned;i++) { + n++; + } + prop->product = (char*)calloc(n+1, sizeof(char)); + strncpy(prop->product, &p[devDesc->ProductIdOffset], n); + } + + if ( devDesc->ProductRevisionOffset && p[devDesc->ProductRevisionOffset] ) { + for (n = 0, i = devDesc->ProductRevisionOffset;p[i] && i < returned;i++) { + n++; + } + prop->revision = (char*)calloc(n+1, sizeof(char)); + strncpy(prop->revision, &p[devDesc->ProductRevisionOffset], n); + } + + /* Access to SCSI INQUIRY page 0xC0. */ + ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS)); + sptwb.Spt.Length = sizeof(SCSI_PASS_THROUGH); + sptwb.Spt.PathId = 0; + sptwb.Spt.TargetId = 1; + sptwb.Spt.Lun = 0; + sptwb.Spt.CdbLength = CDB6GENERIC_LENGTH; + sptwb.Spt.SenseInfoLength = 24; + sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN; + sptwb.Spt.DataTransferLength = 255; + sptwb.Spt.TimeOutValue = 2; + sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,DataBuf); + sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,SenseBuf); + sptwb.Spt.Cdb[0] = SCSIOP_INQUIRY; + sptwb.Spt.Cdb[1] = 0x01; + sptwb.Spt.Cdb[2] = 0xC0; + sptwb.Spt.Cdb[4] = 255; + length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,DataBuf) + sptwb.Spt.DataTransferLength; + + status = DeviceIoControl(hDevice, + IOCTL_SCSI_PASS_THROUGH, + &sptwb, + sizeof(SCSI_PASS_THROUGH), + &sptwb, + length, + &returned, + FALSE + ); + + if (!status) { + ret = -1; + goto error_exit; + } + + /* Obtain the number of pages and list of pages. */ + num_pages = (int)sptwb.DataBuf[3]; + for (j = 0;j < num_pages;++j) { + pages[j] = sptwb.DataBuf[j+4]; + } + + /* Access to all pages available. */ + for (j = 0;j < num_pages;++j) { + ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS)); + sptwb.Spt.Length = sizeof(SCSI_PASS_THROUGH); + sptwb.Spt.PathId = 0; + sptwb.Spt.TargetId = 1; + sptwb.Spt.Lun = 0; + sptwb.Spt.CdbLength = CDB6GENERIC_LENGTH; + sptwb.Spt.SenseInfoLength = 24; + sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN; + sptwb.Spt.DataTransferLength = 255; + sptwb.Spt.TimeOutValue = 2; + sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,DataBuf); + sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,SenseBuf); + sptwb.Spt.Cdb[0] = SCSIOP_INQUIRY; + sptwb.Spt.Cdb[1] = 0x01; + sptwb.Spt.Cdb[2] = pages[j]; + sptwb.Spt.Cdb[4] = 255; + length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,DataBuf) + + sptwb.Spt.DataTransferLength; + + status = DeviceIoControl(hDevice, + IOCTL_SCSI_PASS_THROUGH, + &sptwb, + sizeof(SCSI_PASS_THROUGH), + &sptwb, + length, + &returned, + FALSE + ); + + if (!status) { + ret = -1; + goto error_exit; + } + + /* Obtain the number of characters in this page. */ + n = (int)sptwb.DataBuf[3]; + /* Expand the buffer storing the information. */ + prop->info = realloc(prop->info, sizeof(char) * (info_size + n + 1)); + /* Storing the information in the current page. */ + for (k = 0;k < n;++k) { + prop->info[info_size+k] = sptwb.DataBuf[k+4]; + } + info_size += n; + prop->info[info_size] = 0; + } + + if (!CloseHandle(hDevice)) { + ret = -1; + goto error_exit; + } + return 0; + +error_exit: + free(prop->vendor); + free(prop->product); + free(prop->revision); + free(prop->info); + memset(prop, 0, sizeof(*prop)); + if (hDevice != INVALID_HANDLE_VALUE) { + CloseHandle(hDevice); + } + return ret; +} + +#if 0 +int __cdecl main(int argc, char *argv[]) +{ + ipodprop_t prop; + + ipodprop_init(&prop); + + if (ipodprop_get("D:\\", &prop) == 0) { + if (prop.vendor) printf("Vendor: %s\n", prop.vendor); + if (prop.product) printf("Product: %s\n", prop.product); + if (prop.revision) printf("Revision: %s\n", prop.revision); + if (prop.info) printf("Info:\n%s\n", prop.info); + } + + ipodprop_finish(&prop); + + return 0; +} +#endif Property changes on: trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.c ___________________________________________________________________ Name: svn:keywords + Id Added: trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.lib =================================================================== (Binary files differ) Property changes on: trunk/pmplib/lib/pmp_ipod/win32spti/ipodprop_win32spti.lib ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/pmplib/lib/pmp_ipod/win32spti/makefile =================================================================== --- trunk/pmplib/lib/pmp_ipod/win32spti/makefile (rev 0) +++ trunk/pmplib/lib/pmp_ipod/win32spti/makefile 2007-02-27 14:15:54 UTC (rev 398) @@ -0,0 +1,8 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def + Added: trunk/pmplib/lib/pmp_ipod/win32spti/sources =================================================================== --- trunk/pmplib/lib/pmp_ipod/win32spti/sources (rev 0) +++ trunk/pmplib/lib/pmp_ipod/win32spti/sources 2007-02-27 14:15:54 UTC (rev 398) @@ -0,0 +1,8 @@ +TARGETNAME=ipodprop_win32spti +TARGETTYPE=LIBRARY + +TARGETPATH=obj + +TARGETLIBS=$(DDK_LIB_PATH)\user32.lib $(DDK_LIB_PATH)\shlwapi.lib + +SOURCES=ipodprop_win32spti.c This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-27 09:45:40
|
Revision: 397 http://svn.sourceforge.net/pmplib/?rev=397&view=rev Author: nyaochi Date: 2007-02-27 01:45:39 -0800 (Tue, 27 Feb 2007) Log Message: ----------- More for iPod support. The POSIX version has been broken. - Added "settle" operation for iPods (*1) - Added symbolic-link emulation represented by M3U8 playlist (*2) - Changed the structure of easypmp_filename_t for the convenience. - Diaplay the codec name of MPEG4 AAC - Option remapping: -s (--setvar) to -a (--setvar) - Option remapping: -x (--help-variable) to -H (--help-variable) *1 Settlement of media files This operation was introduced for Apple iPod players to bring them into the world of EasyPMP. Apple iPods for Windows are actually UMS/MSC device like other players supported by PMPlib, but has the strong requirement for the names of media files: a filename should be something like "F01\ABCD.m4a". In other words, we cannot name music files arbitrarily unlike other UMS/MSC players. In order to solve this problem, the operation "settle" (-s, --settle) was introduced to move/rename media files to the locations/names that are suitable for Apple iPods. At the same time, EasyPMP leaves symbolic links (*2) pointing to the settled music files from their original locations. Take the following example where a user places his/her music files under \Music directory of an iPod. [unsettled music files] \Music\RazorLight\RazorLight\01_In The Morning.m4a \Music\RazorLight\RazorLight\02_Who Needs Love.m4a \Music\RazorLight\RazorLight\03_Hold On.m4a \Music\RazorLight\RazorLight\04_America.m4a After EasyPMP performs a settle operation, the directory structure will be changed as follows. [music links] \Music\RazorLight\RazorLight\01_In The Morning.m4a.m3u8 (--> F02\JDEW.m4a) \Music\RazorLight\RazorLight\02_Who Needs Love.m4a.m3u8 (--> F05\IEJV.m4a) \Music\RazorLight\RazorLight\03_Hold On.m4a.m3u8 (--> F00\ESAV.m4a) \Music\RazorLight\RazorLight\04_America.m4a.m3u8 (--> F03\AWQM.m4a) [settled music files] \iPod_Control\Music\F02\JDEW.m4a \iPod_Control\Music\F05\IEJV.m4a \iPod_Control\Music\F00\ESAV.m4a \iPod_Control\Music\F03\AWQM.m4a This directory structure is perfectly compatible for the iPod player. In addition, the user can still listen to the music through M3U8 playlists placed in the \Music directory. If the user would like to remove the file "02_Who Needs Love.m4a" that was moved to "F05\IEJV.m4a", he/she can simply delete "02_Who Needs Love.m4a.m3u8" and run EasyPMP with -E (--remove-unref) option; EasyPMP will delete "F05\IEJV.m4a", which is not pointed by any symbolic links in the \Music directory. In this way, the user does not have to find out the location of settled music files at all. If the user would like to restore the original music files from the settled files, he or she may run EasyPMP with -x (--unsettle) option. This will take back to the original state of the directory structure. *2 Symbolic link emulation for FAT32 Symbolic (or hard) link is not supported by FAT32. EasyPMP supports symbolic links emulated by M3U8 playlists. The content of an M3U8 playlist is mere the reference to a settled media file. The name of an M3U8 symbolic link must be "(original_name).m3u8)", e.g., "01_track.m4a.m3u8". Modified Paths: -------------- trunk/pmplib/frontend/easypmp/common/database.c trunk/pmplib/frontend/easypmp/common/easypmp.h trunk/pmplib/frontend/easypmp/common/enumerate.c trunk/pmplib/frontend/easypmp/common/playlist.c trunk/pmplib/frontend/easypmp/cui/device.c trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj trunk/pmplib/frontend/easypmp/cui/main.c trunk/pmplib/frontend/easypmp/cui/option.c trunk/pmplib/include/pmplib/filepath.h trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/filepath/filepath.vcproj trunk/pmplib/lib/filepath/filepath_win32.c trunk/pmplib/lib/pmp_ipod/pmp_ipod.c trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj trunk/pmplib/lib/ucs2/ucs2char.c trunk/pmplib/lib/ucs2/ucs2char_win32.c Added Paths: ----------- trunk/pmplib/frontend/easypmp/common/settle.c Modified: trunk/pmplib/frontend/easypmp/common/database.c =================================================================== --- trunk/pmplib/frontend/easypmp/common/database.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/common/database.c 2007-02-27 09:45:39 UTC (rev 397) @@ -165,10 +165,9 @@ int is_skipping = 0; easypmp_filename_t* target = &fl->elements[i]; pmp_music_record_t* record = &records[i]; - ucs2char_t filename[MAX_PATH]; + const ucs2char_t* filename = target->name; uint32_t timestamp = 0; - filepath_combinepath(filename, MAX_PATH, target->pathname, target->filename); timestamp = (uint32_t)filepath_mtime(filename); // Report the progress. Modified: trunk/pmplib/frontend/easypmp/common/easypmp.h =================================================================== --- trunk/pmplib/frontend/easypmp/common/easypmp.h 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/common/easypmp.h 2007-02-27 09:45:39 UTC (rev 397) @@ -38,11 +38,14 @@ enum { EASYPMPP_START = 0x00010000, EASYPMPP_OPEN = 0x00020000, - EASYPMPP_MUSIC_GMI = 0x00030000, - EASYPMPP_MUSIC_UPDATE = 0x00040000, - EASYPMPP_PLAYLIST_CONVERT = 0x02050000, - EASYPMPP_CLOSE = 0x00060000, - EASYPMPP_END = 0x00070000, + EASYPMPP_REMOVE_UNREF = 0x00030000, + EASYPMPP_SETTLE = 0x00040000, + EASYPMPP_UNSETTLE = 0x00050000, + EASYPMPP_MUSIC_GMI = 0x00060000, + EASYPMPP_MUSIC_UPDATE = 0x00070000, + EASYPMPP_PLAYLIST_CONVERT = 0x02080000, + EASYPMPP_CLOSE = 0x00090000, + EASYPMPP_END = 0x000A0000, EASYPMPSP_START = 0x00000001, EASYPMPSP_PROGRESS = 0x00000002, @@ -70,19 +73,22 @@ #define MAKE_PMP_ERROR(code) (((code) << 16) | EASYPMPE_PMPERROR) enum { - MODE_NONE = 0, - MODE_DATABASE = 0x00000001, + MODE_NONE = 0, + MODE_DATABASE = 0x00000001, MODE_DATABASE_UPDATE = 0x00000002, MODE_DATABASE_REPR = 0x00000004, - MODE_PLAYLIST = 0x00000010, + MODE_PLAYLIST = 0x00000010, MODE_PLAYLIST_RECONVERT = 0x00000100, - MODE_PLAYLIST_FIND = 0x00000200, - MODE_PLAYLIST_SKIP = 0x00000400, - MODE_PLAYLIST_JSPL = 0x00000800, - MODE_LIST_DEVICES = 0x00001000, - MODE_HELP = 0x00010000, - MODE_HELP_VARIABLE = 0x00020000, - MODE_VERSION = 0x00040000, + MODE_PLAYLIST_FIND = 0x00000200, + MODE_PLAYLIST_SKIP = 0x00000400, + MODE_PLAYLIST_JSPL = 0x00000800, + MODE_SETTLE = 0x00001000, + MODE_UNSETTLE = 0x00002000, + MODE_REMOVE_UNREF = 0x00004000, + MODE_LIST_DEVICES = 0x00010000, + MODE_HELP = 0x00100000, + MODE_HELP_VARIABLE = 0x00200000, + MODE_VERSION = 0x00400000, }; typedef struct { @@ -100,13 +106,13 @@ ucs2char_t* path_to_pmp_music; ucs2char_t* path_to_pmp_playlist; + ucs2char_t* path_to_unsettled_music; ucs2char_t* path_to_playlist_source; int subdir_playlist_source; } option_t; typedef struct { - ucs2char_t pathname[MAX_PATH]; - ucs2char_t filename[MAX_PATH]; + ucs2char_t name[MAX_PATH]; } easypmp_filename_t; typedef struct { @@ -121,19 +127,30 @@ int phase, int param_int, double param_float, - ucs2char_t* param_str + const ucs2char_t* param_str ); int easypmp_enumerate_music( easypmp_filelist_t* fl, pmp_t* pmp, + const ucs2char_t* relative_path, const option_t* opt, easypmp_enumerate_progress_t proc, void *instance ); int +easypmp_enumerate_music_links( + easypmp_filelist_t* fl, + pmp_t* pmp, + const ucs2char_t* relative_path, + const option_t* opt, + easypmp_enumerate_progress_t proc, + void *instance + ); + +int easypmp_enumerate_playlist( easypmp_filelist_t* fl, pmp_t* pmp, @@ -176,6 +193,16 @@ easypmp_filelist_t* fl ); +int easypmp_settle( + pmp_t* pmp, + easypmp_filelist_t* musics, + easypmp_filelist_t* musics_unsettled, + easypmp_filelist_t* music_links, + const option_t* opt, + easypmp_progress_t progress, + void *instance + ); + /** @} */ #ifdef __cplusplus Modified: trunk/pmplib/frontend/easypmp/common/enumerate.c =================================================================== --- trunk/pmplib/frontend/easypmp/common/enumerate.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/common/enumerate.c 2007-02-27 09:45:39 UTC (rev 397) @@ -77,8 +77,7 @@ // Set path and file. new_filename = &fl->elements[fl->num_elements++]; - ucs2cpy(new_filename->pathname, found_path); - ucs2cpy(new_filename->filename, found_file); + filepath_combinepath(new_filename->name, MAX_PATH, found_path, found_file); } else { // Exit if the filename does not have a supported extension. return 0; @@ -96,6 +95,7 @@ easypmp_enumerate_music( easypmp_filelist_t* fl, pmp_t* pmp, + const ucs2char_t* relative_path, const option_t* opt, easypmp_enumerate_progress_t proc, void *instance @@ -105,7 +105,7 @@ ucs2char_t music_path[MAX_PATH]; // Decode the music path prefix for system path separators - filepath_combinepath(music_path, MAX_PATH, pmp->info.path_to_root, pmp->info.path_to_music); + filepath_combinepath(music_path, MAX_PATH, pmp->info.path_to_root, relative_path); filepath_addslash(music_path); filepath_decode(music_path); @@ -127,6 +127,96 @@ ); } +static int found_music_link_file(void *instance, const ucs2char_t* found_path, const ucs2char_t* found_file) +{ + uint32_t i; + enumerate_dat_t* ed = (enumerate_dat_t*)instance; + pmp_t* pmp = ed->pmp; + pmp_music_t* pmp_music = ed->pmp->music; + easypmp_filelist_t* fl = ed->fl; + ucs2char_t *filename = alloca(sizeof(ucs2char_t) * (ucs2len(found_file)+1)); + + if (!filepath_is_link(found_file)) { + // Not a link file. + return 0; + } + + // Remove the extension of link. + ucs2cpy(filename, found_file); + filepath_remove_extension(filename); + + // Check if the file has an extension supported by the target player. + for (i = 0;i < pmp->info.num_audio_extensions;++i) { + if (filepath_hasext(filename, pmp->info.audio_extensions[i])) { + break; + } + } + + if (i != pmp->info.num_audio_extensions) { + // Supported music file. + easypmp_filename_t* new_filename = NULL; + + // Expand the target array. + fl->elements = (easypmp_filename_t*)realloc( + fl->elements, + sizeof(easypmp_filename_t) * (fl->num_elements+1) + ); + if (!fl->elements) { + return -1; + } + + // Set path and file. + new_filename = &fl->elements[fl->num_elements++]; + filepath_combinepath(new_filename->name, MAX_PATH, found_path, filename); + } else { + // Exit if the filename does not have a supported extension. + return 0; + } + + // Report the progress. + if (ed->proc) { + ed->proc(ed->instance, found_path, found_file, fl->num_elements); + } + + return 0; +} + +int +easypmp_enumerate_music_links( + easypmp_filelist_t* fl, + pmp_t* pmp, + const ucs2char_t* relative_path, + const option_t* opt, + easypmp_enumerate_progress_t proc, + void *instance + ) +{ + enumerate_dat_t ed; + ucs2char_t music_path[MAX_PATH]; + + // Decode the music path prefix for system path separators + filepath_combinepath(music_path, MAX_PATH, pmp->info.path_to_root, relative_path); + filepath_addslash(music_path); + filepath_decode(music_path); + + fl->num_elements = 0; + fl->elements = NULL; + + memset(&ed, 0, sizeof(ed)); + ed.opt = opt; + ed.fl = fl; + ed.pmp = pmp; + ed.proc = proc; + ed.instance = instance; + + return find_file( + music_path, + 1, + found_music_link_file, + &ed + ); +} + static int found_playlist_file(void *instance, const ucs2char_t* found_path, const ucs2char_t* found_file) { enumerate_dat_t* ed = (enumerate_dat_t*)instance; @@ -149,8 +239,7 @@ // Set path and file. new_filename = &fl->elements[fl->num_elements++]; - ucs2cpy(new_filename->pathname, found_path); - ucs2cpy(new_filename->filename, found_file); + filepath_combinepath(new_filename->name, MAX_PATH, found_path, found_file); } else { // Exit if the filename does not have a supported extension. return 0; Modified: trunk/pmplib/frontend/easypmp/common/playlist.c =================================================================== --- trunk/pmplib/frontend/easypmp/common/playlist.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/common/playlist.c 2007-02-27 09:45:39 UTC (rev 397) @@ -92,8 +92,9 @@ goto error_exit; } for (i = 0;i < musics->num_elements;++i) { - ucs2cpy(mediafiles[i].path, musics->elements[i].pathname); - ucs2cpy(mediafiles[i].file, musics->elements[i].filename); + ucs2cpy(mediafiles[i].path, musics->elements[i].name); + filepath_remove_filespec(mediafiles[i].path); + ucs2cpy(mediafiles[i].file, filepath_skippath(musics->elements[i].name)); } // Prepare playlist conversion for finding music files. @@ -115,9 +116,10 @@ int n = 0; // Generate the source filename - ucs2cpy(plf_path, plf->pathname); + ucs2cpy(plf_path, plf->name); + filepath_remove_filespec(plf_path); filepath_decode(plf_path); - filepath_combinepath(src, MAX_PATH, plf_path, plf->filename); + filepath_combinepath(src, MAX_PATH, plf_path, filepath_skippath(plf->name)); // Report the source filename. if (progress(instance, EASYPMPP_PLAYLIST_CONVERT | EASYPMPSP_PROGRESS, i, 0, src) != 0) { Added: trunk/pmplib/frontend/easypmp/common/settle.c =================================================================== --- trunk/pmplib/frontend/easypmp/common/settle.c (rev 0) +++ trunk/pmplib/frontend/easypmp/common/settle.c 2007-02-27 09:45:39 UTC (rev 397) @@ -0,0 +1,249 @@ +/* + * EasyPMP settlement operation (currently for iPod). + * + * Copyright (c) 2005-2007 Naoaki Okazaki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* $Id:$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ +#ifdef HAVE_STRING_H +#include <string.h> +#endif/*HAVE_STRING_H*/ + +#include <os.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <pmplib/ucs2char.h> +#include <pmplib/filepath.h> +#include <pmplib/pmp.h> +#include <gmi.h> +#include <easypmp.h> + +static void generate_filename(ucs2char_t* filename) +{ + ucs2char_t* p = filename; + *p++ = 'F'; + *p++ = '0'; + *p++ = '0' + (rand() % 10); + *p++ = PATHCHAR; + *p++ = 'A' + (rand() % 26); + *p++ = 'A' + (rand() % 26); + *p++ = 'A' + (rand() % 26); + *p++ = 'A' + (rand() % 26); + *p++ = 0; +} + +static int remove_file_from_list(easypmp_filelist_t* list, int i) +{ + memmove(&list->elements[i], &list->elements[i+1], sizeof(easypmp_filename_t) * (list->num_elements - 1 - i)); + list->elements = (easypmp_filename_t*)realloc( + list->elements, + sizeof(easypmp_filename_t) * (--list->num_elements) + ); + return list->elements == NULL ? -1 : 0; +} + +static int add_file_to_list(easypmp_filelist_t* list, const ucs2char_t* filename) +{ + list->elements = (easypmp_filename_t*)realloc( + list->elements, + sizeof(easypmp_filename_t) * (list->num_elements+1) + ); + if (!list->elements) { + return -1; + } + ucs2cpy(list->elements[list->num_elements++].name, filename); + return 0; +} + +int easypmp_settle( + pmp_t* pmp, + easypmp_filelist_t* musics, + easypmp_filelist_t* musics_unsettled, + easypmp_filelist_t* music_links, + const option_t* opt, + easypmp_progress_t progress, + void *instance + ) +{ + int result = 0; + uint32_t i, j, n; + ucs2char_t link[MAX_PATH]; + ucs2char_t target[MAX_PATH]; + ucs2char_t music[MAX_PATH]; + ucs2char_t directory[MAX_PATH]; + + srand(time(NULL)); + + // Remove music files that are not pointed by any links. + if (opt->verb & MODE_REMOVE_UNREF) { + if (progress(instance, EASYPMPP_REMOVE_UNREF|EASYPMPSP_START, 0, 0, NULL) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + + n = 0; + for (i = 0;i < musics->num_elements;++i) { + ucs2cpy(music, musics->elements[i].name); + + // Check the existence of a link referring to the music file. + for (j = 0;j < music_links->num_elements;++j) { + // Obtain the filename pointed by this link. + ucs2cpy(link, music_links->elements[j].name); + if (filepath_followlink(link, target) == 0) { + if (ucs2icmp(music, target) == 0) { + break; + } + } + } + + // Remove the music file if no link is referring to the file. + if (j == music_links->num_elements) { + filepath_removefile(music); + remove_file_from_list(musics, i); + --i; + + if (progress(instance, EASYPMPP_REMOVE_UNREF|EASYPMPSP_PROGRESS, n, 0, music) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + n++; + } + } + + for (i = 0;i < music_links->num_elements;++i) { + ucs2cpy(link, music_links->elements[j].name); + if (filepath_followlink(link, target) != 0) { + filepath_removelinkfile(link); + remove_file_from_list(music_links, i); + --i; + + if (progress(instance, EASYPMPP_REMOVE_UNREF|EASYPMPSP_PROGRESS, n, 0, music) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + n++; + } + } + + if (progress(instance, EASYPMPP_REMOVE_UNREF|EASYPMPSP_END, n, 0, NULL) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + } + + // Settle media files to the internal location suitable for the player. + if (opt->verb & MODE_SETTLE) { + if (progress(instance, EASYPMPP_SETTLE|EASYPMPSP_START, 0, 0, NULL) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + + n = 0; + for (i = 0;i < musics_unsettled->num_elements;++i) { + // Source music file. + ucs2cpy(music, musics_unsettled->elements[i].name); + + // Destination music file. + do { + filepath_combinepath(target, MAX_PATH, pmp->info.path_to_root, pmp->info.path_to_music); + filepath_addslash(target); + generate_filename(target + ucs2len(target)); + filepath_add_extension(target, filepath_extract_extension(music)); + } while (filepath_file_exists(target)); + + // Create the directories for the destination music file. + ucs2cpy(directory, target); + filepath_remove_filespec(directory); + filepath_createdirs(directory); + + // Move the source file to the destination. + filepath_movefile(music, target); + add_file_to_list(musics, target); + remove_file_from_list(musics_unsettled, i); + --i; + + // Create a symbolic link (or shortcut) from the source to the destination. + filepath_linkfile(target, music); + add_file_to_list(music_links, music); + + if (progress(instance, EASYPMPP_SETTLE|EASYPMPSP_PROGRESS, n, 0, music) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + n++; + } + + if (progress(instance, EASYPMPP_SETTLE|EASYPMPSP_END, n, 0, NULL) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + } + + if (opt->verb & MODE_UNSETTLE) { + if (progress(instance, EASYPMPP_UNSETTLE|EASYPMPSP_START, 0, 0, NULL) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + + n = 0; + for (i = 0;i < music_links->num_elements;++i) { + // Source music link. + ucs2cpy(link, music_links->elements[i].name); + + // Follow the link. + if (filepath_followlink(link, target) == 0) { + // Restore the music file in the original location. + filepath_movefile(target, link); + add_file_to_list(musics_unsettled, link); + + // Remove the settled music file from the music list. + for (j = 0;j < musics->num_elements;++j) { + if (ucs2cmp(musics->elements[j].name, link) == 0) { + remove_file_from_list(musics, j); + break; + } + } + + // Remove the link file. + filepath_removelinkfile(link); + remove_file_from_list(music_links, i); + --i; + + if (progress(instance, EASYPMPP_UNSETTLE|EASYPMPSP_PROGRESS, n, 0, music) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + n++; + } + } + + if (progress(instance, EASYPMPP_UNSETTLE|EASYPMPSP_END, n, 0, NULL) != 0) { + result = EASYPMPE_CANCEL; + goto error_exit; + } + } + +error_exit: + return result; +} Property changes on: trunk/pmplib/frontend/easypmp/common/settle.c ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Modified: trunk/pmplib/frontend/easypmp/cui/device.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/device.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/cui/device.c 2007-02-27 09:45:39 UTC (rev 397) @@ -35,11 +35,6 @@ #include "util.h" -/** - * \addtogroup cui - * @{ - */ - // Display a path name using the given string format. void device_show_path(FILE *fp, const char* const format, const ucs2char_t* const path) { @@ -65,10 +60,11 @@ fprintf(fp, " Audio codec(s): "); for (i = 0;i < pmp->info.num_audio_codecs;++i) { switch (pmp->info.audio_codecs[i]) { - case PMPCODEC_MPEGLAYER3: fputs("MP3", fp); break; - case PMPCODEC_WMA: fputs("WMA", fp); break; + case PMPCODEC_MPEGLAYER3: fputs("MP3", fp); break; + case PMPCODEC_MPEG4AUDIO: fputs("AAC (MP4)", fp); break; + case PMPCODEC_WMA: fputs("WMA", fp); break; case PMPCODEC_VORBIS: fputs("Ogg Vorbis", fp); break; - case PMPCODEC_WAV: fputs("WAV", fp); break; + case PMPCODEC_WAV: fputs("WAV", fp); break; } if (i != pmp->info.num_audio_codecs-1) fputs(", ", fp); } @@ -102,4 +98,3 @@ { pmplib_enumerate_devid(pmplib, enumerate_devid_callback, pmplib); } -/** @} */ Modified: trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj =================================================================== --- trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/cui/easypmp_cui.vcproj 2007-02-27 09:45:39 UTC (rev 397) @@ -4,6 +4,7 @@ Version="8.00" Name="easypmp_cui" ProjectGUID="{FA1F30D4-6100-4379-8506-6CFE023B0AE7}" + RootNamespace="easypmp_cui" Keyword="Win32Proj" > <Platforms> @@ -255,6 +256,10 @@ RelativePath="..\common\playlist.c" > </File> + <File + RelativePath="..\common\settle.c" + > + </File> </Filter> </Files> <Globals> Modified: trunk/pmplib/frontend/easypmp/cui/main.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/main.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/cui/main.c 2007-02-27 09:45:39 UTC (rev 397) @@ -84,7 +84,7 @@ int phase, int param_int, double param_float, - ucs2char_t* param_str + const ucs2char_t* param_str ) { FILE *fpo = stdout; @@ -108,6 +108,42 @@ case EASYPMPP_END: break; + case EASYPMPP_REMOVE_UNREF|EASYPMPSP_START: + fprintf(fpo, "Removing media files if they are pointed from no links\n"); + break; + case EASYPMPP_REMOVE_UNREF|EASYPMPSP_PROGRESS: + easypmp_progress_num_str(fpo, param_int+1, filepath_skippath(param_str)); + break; + case EASYPMPP_REMOVE_UNREF|EASYPMPSP_END: + console_clearln(fpo); + fprintf(fpo, " %d files were removed\n", param_int); + fprintf(fpo, "\n"); + break; + + case EASYPMPP_SETTLE|EASYPMPSP_START: + fprintf(fpo, "Settling media files to the internal location suitable for the player\n"); + break; + case EASYPMPP_SETTLE|EASYPMPSP_PROGRESS: + easypmp_progress_num_str(fpo, param_int+1, filepath_skippath(param_str)); + break; + case EASYPMPP_SETTLE|EASYPMPSP_END: + console_clearln(fpo); + fprintf(fpo, " %d files were settled\n", param_int); + fprintf(fpo, "\n"); + break; + + case EASYPMPP_UNSETTLE|EASYPMPSP_START: + fprintf(fpo, "Restoring media files from the internal location of the player\n"); + break; + case EASYPMPP_UNSETTLE|EASYPMPSP_PROGRESS: + easypmp_progress_num_str(fpo, param_int+1, filepath_skippath(param_str)); + break; + case EASYPMPP_UNSETTLE|EASYPMPSP_END: + console_clearln(fpo); + fprintf(fpo, " %d files were restored\n", param_int); + fprintf(fpo, "\n"); + break; + case EASYPMPP_MUSIC_GMI|EASYPMPSP_START: fprintf(fpo, "Obtaining media information from %d files\n", param_int); break; @@ -196,6 +232,7 @@ pmp_t* pmp = NULL; pmplib_t* pmplib = NULL; easypmp_filelist_t musics, playlists; + easypmp_filelist_t musics_unsettled, music_links; pmp_music_record_t* records = NULL; uint32_t num_records = 0; uint32_t openflag = 0; @@ -369,17 +406,43 @@ // Enumerate music files for database and playlist modes. memset(&musics, 0, sizeof(musics)); - if ((opt.verb & MODE_DATABASE) || (opt.verb & MODE_PLAYLIST)) { + if (opt.verb & (MODE_DATABASE|MODE_PLAYLIST|MODE_SETTLE|MODE_UNSETTLE|MODE_REMOVE_UNREF)) { fprintf(fpo, "Enumerating music files in "); fputucs2str_path(fpo, pmp->info.path_to_root); fputucs2str_path(fpo, pmp->info.path_to_music); fprintf(fpo, "\n"); - easypmp_enumerate_music(&musics, pmp, &opt, easypmp_enumerate_progress, NULL); + easypmp_enumerate_music(&musics, pmp, pmp->info.path_to_music, &opt, easypmp_enumerate_progress, NULL); console_clearln(fpo); fprintf(fpo, " %d music files were found\n", musics.num_elements); fprintf(fpo, "\n"); } + // Enumerate unsettled music files. + memset(&musics_unsettled, 0, sizeof(musics_unsettled)); + if (opt.verb & (MODE_SETTLE|MODE_UNSETTLE|MODE_REMOVE_UNREF)) { + fprintf(fpo, "Enumerating unsettled music files in "); + fputucs2str_path(fpo, pmp->info.path_to_root); + fputucs2str_path(fpo, opt.path_to_unsettled_music); + fprintf(fpo, "\n"); + easypmp_enumerate_music(&musics_unsettled, pmp, opt.path_to_unsettled_music, &opt, easypmp_enumerate_progress, NULL); + console_clearln(fpo); + fprintf(fpo, " %d music files were found\n", musics_unsettled.num_elements); + fprintf(fpo, "\n"); + } + + // Enumerate music links. + memset(&music_links, 0, sizeof(music_links)); + if (opt.verb & (MODE_SETTLE|MODE_UNSETTLE|MODE_REMOVE_UNREF)) { + fprintf(fpo, "Enumerating music links in "); + fputucs2str_path(fpo, pmp->info.path_to_root); + fputucs2str_path(fpo, opt.path_to_unsettled_music); + fprintf(fpo, "\n"); + easypmp_enumerate_music_links(&music_links, pmp, opt.path_to_unsettled_music, &opt, easypmp_enumerate_progress, NULL); + console_clearln(fpo); + fprintf(fpo, " %d music links were found\n", music_links.num_elements); + fprintf(fpo, "\n"); + } + // Enumerate playlist files for playlist mode. memset(&playlists, 0, sizeof(playlists)); if (opt.verb & MODE_PLAYLIST) { @@ -397,14 +460,24 @@ fprintf(fpo, "\n"); } + // Settle/unsettle media files (mostly for iPods). + if (opt.verb & (MODE_SETTLE|MODE_UNSETTLE|MODE_REMOVE_UNREF)) { + easypmp_settle(pmp, &musics, &musics_unsettled, &music_links, &opt, easypmp_progress, NULL); + } + // Update database entries for database mode and JSPL playlists. - if ((opt.verb & MODE_DATABASE) || (opt.verb & MODE_PLAYLIST_JSPL)) { + if (opt.verb & (MODE_DATABASE|MODE_PLAYLIST_JSPL)) { easypmp_database(pmp, &musics, &opt, &records, &num_records, easypmp_progress, NULL); } // Convert playlists. if (opt.verb & MODE_PLAYLIST) { - easypmp_playlist(pmp, &playlists, &musics, &opt, records, num_records, easypmp_progress, NULL); + if (opt.verb & MODE_SETTLE) { + // Playlist referring to music_links. + easypmp_playlist(pmp, &playlists, &music_links, &opt, records, num_records, easypmp_progress, NULL); + } else { + easypmp_playlist(pmp, &playlists, &musics, &opt, records, num_records, easypmp_progress, NULL); + } } // Dump the database if specified. @@ -450,5 +523,9 @@ pmplib = NULL; } option_finish(&opt); +#ifdef _WIN32 + CoUninitialize(); +#endif/*_WIN32*/ + return ret; } Modified: trunk/pmplib/frontend/easypmp/cui/option.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/option.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/frontend/easypmp/cui/option.c 2007-02-27 09:45:39 UTC (rev 397) @@ -79,10 +79,15 @@ fprintf(fp, " -f, --find-missing Correct playlists with corrupt references to media files\n"); fprintf(fp, " -i, --ignore-missing Continue a conversion even if a media file is missing\n"); fprintf(fp, "\n"); + fprintf(fp, "Settlement options (mostly for iPods):\n"); + fprintf(fp, " -s, --settle Settle media files in the location suitable for players\n"); + fprintf(fp, " -x, --unsettle Restore media files in the original location\n"); + fprintf(fp, " -E, --delete-unref Propagate the removal of links to the actual media files\n"); + fprintf(fp, "\n"); fprintf(fp, "Player options:\n"); fprintf(fp, " -l, --list-device Show the list of supported devices and exit\n"); fprintf(fp, " -d, --device Specify a device identifier for the player\n"); - fprintf(fp, " -s, --set=NAME:VALUE Set a variable NAME to VALUE\n"); + fprintf(fp, " -a, --set=NAME:VALUE Set a variable NAME to VALUE\n"); fprintf(fp, "\n"); #ifndef _WIN32 fprintf(fp, "Language-specific options:\n"); @@ -93,7 +98,7 @@ fprintf(fp, "Miscellaneous options:\n"); fprintf(fp, " -v, --version Show version number and exit\n"); fprintf(fp, " -h, --help Show this help message and exit\n"); - fprintf(fp, " -x, --help-variable Show the list of variables and exit\n"); + fprintf(fp, " -H, --help-variable Show the list of variables and exit\n"); } void option_usage_variable(FILE* fp) @@ -109,12 +114,14 @@ void option_init(option_t* opt) { + static const ucs2char_t path[] = {'M','u','s','i','c',0}; memset(opt, 0, sizeof(*opt)); // Set default values here. opt->media_info_source = GMIF_TAG; opt->system_encoding = strdup(ucs2getenc()); opt->music_encoding = strdup("ISO-8859-1"); + opt->path_to_unsettled_music = ucs2dup(path); } void option_finish(option_t* opt) @@ -146,10 +153,10 @@ int this_option_optind = optind ? optind : 1; int option_index = 0; static const struct option long_options[] = { - {"create", no_argument, 0, 'c'}, - {"update", no_argument, 0, 'u'}, - {"source", required_argument, 0, 'z'}, - {"repr", no_argument, 0, 'R'}, + {"create", no_argument, 0, 'c'}, + {"update", no_argument, 0, 'u'}, + {"source", required_argument, 0, 'z'}, + {"repr", no_argument, 0, 'R'}, {"repr-level", required_argument, 0, 'L'}, {"strip-words", required_argument, 0, 't'}, {"playlist", no_argument, 0, 'p'}, @@ -157,22 +164,25 @@ {"reconvert", no_argument, 0, 'r'}, {"find-missing", no_argument, 0, 'f'}, {"ignore-missing", no_argument, 0, 'i'}, + {"settle", no_argument, 0, 's'}, + {"unsettle", no_argument, 0, 'x'}, + {"delete-unref", no_argument, 0, 'E'}, {"list-device", no_argument, 0, 'l'}, - {"device", required_argument, 0, 'd'}, - {"set", required_argument, 0, 's'}, + {"device", required_argument, 0, 'd'}, + {"set", required_argument, 0, 'a'}, #ifndef _WIN32 {"encoding", required_argument, 0, 'e'}, {"tagencoding", required_argument, 0, 'w'}, #endif/*_WIN32*/ - {"version", no_argument, 0, 'v'}, - {"help", no_argument, 0, 'h'}, - {"help-variable", no_argument, 0, 'x'}, + {"version", no_argument, 0, 'v'}, + {"help", no_argument, 0, 'h'}, + {"help-variable", no_argument, 0, 'H'}, {NULL, 0, 0, 0} }; #ifndef _WIN32 - int c = getopt_long(argc, argv, "cuz:RL:t:pP:rfild:xs:e:w:vh", long_options, &option_index); + int c = getopt_long(argc, argv, "cuz:RL:t:pP:rfisxEld:a:e:w:vhH", long_options, &option_index); #else - int c = getopt_long(argc, argv, "cuz:RL:t:pP:rfild:xs:vh", long_options, &option_index); + int c = getopt_long(argc, argv, "cuz:RL:t:pP:rfisxEld:a:vhH", long_options, &option_index); #endif/*_WIN32*/ if (c == -1) { break; @@ -230,13 +240,23 @@ opt->verb |= MODE_PLAYLIST_SKIP; break; + case 's': + opt->verb |= MODE_SETTLE; + break; + case 'x': + opt->verb |= MODE_UNSETTLE; + break; + case 'E': + opt->verb |= MODE_REMOVE_UNREF; + break; + case 'l': opt->verb |= MODE_LIST_DEVICES; break; case 'd': strcpy(opt->model, optarg); break; - case 's': + case 'a': if (strncmp("pmp_music:", optarg, 10) == 0) { ucs2free(opt->path_to_pmp_music); opt->path_to_pmp_music = mbsdupucs2(optarg+10); @@ -265,7 +285,7 @@ case 'h': opt->verb |= MODE_HELP; break; - case 'x': + case 'H': opt->verb |= MODE_HELP_VARIABLE; break; case '?': Modified: trunk/pmplib/include/pmplib/filepath.h =================================================================== --- trunk/pmplib/include/pmplib/filepath.h 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/include/pmplib/filepath.h 2007-02-27 09:45:39 UTC (rev 397) @@ -154,6 +154,8 @@ */ FILEPATHAPI const ucs2char_t* filepath_skipadirectory(const ucs2char_t* path); +FILEPATHAPI const ucs2char_t* filepath_extract_extension(const ucs2char_t* path); + /** * Add a file extension to the end of a string. * @@ -277,6 +279,14 @@ FILEPATHAPI int filepath_is_dir(const ucs2char_t *path); /** + * Test if a filepath name is a link to another file. + * + * @param path The filepath name to be tested. + * @retval int True or false. + */ +FILEPATHAPI int filepath_is_link(const ucs2char_t *path); + +/** * Test if a filepath name represents a relative path. * * @param path The filepath name to be tested. @@ -324,6 +334,8 @@ */ FILEPATHAPI uint32_t filepath_size(const ucs2char_t *filename); +FILEPATHAPI int filepath_createdirs(const ucs2char_t* filename); + /** * Remove a file. * @@ -341,6 +353,35 @@ */ FILEPATHAPI int filepath_copyfile(const ucs2char_t* src, const ucs2char_t* dst); +/** + * Move a file. + * + * @param src The name of a source file to be moved. + * @param dst The name of a destination to be created. + * @retval int True if succeeded, false otherwise. + */ +FILEPATHAPI int filepath_movefile(const ucs2char_t* src, const ucs2char_t* dst); + +/** + * Create a link to a file. + * + * @param src The name of a source file to be linked. + * @param link The name of a link file to be created. + * @retval int True if succeeded, false otherwise. + */ +FILEPATHAPI int filepath_linkfile(const ucs2char_t* src, const ucs2char_t* link); + +/** + * Remove a link file. + * + * @param file The name of a link file to be removed. + * @retval int True if succeeded, false otherwise. + */ +FILEPATHAPI int filepath_removelinkfile(const ucs2char_t* file); + +FILEPATHAPI int filepath_followlink(const ucs2char_t* link, ucs2char_t* org); + + /** @} */ Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-27 09:45:39 UTC (rev 397) @@ -203,7 +203,7 @@ ucs2char_t path_to_root[MAX_PATH]; /** Relative path to the system directory from the root. */ ucs2char_t path_to_system[MAX_PATH]; - /** Relative path to the music directory from the root. */ + /** Relative path to the directory for settled music files. */ ucs2char_t path_to_music[MAX_PATH]; /** Relative path to the playlist directory from the root. */ ucs2char_t path_to_playlist[MAX_PATH]; Modified: trunk/pmplib/lib/filepath/filepath.vcproj =================================================================== --- trunk/pmplib/lib/filepath/filepath.vcproj 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/lib/filepath/filepath.vcproj 2007-02-27 09:45:39 UTC (rev 397) @@ -4,6 +4,7 @@ Version="8.00" Name="filepath" ProjectGUID="{AA8DA82B-C209-4ABE-ABA1-22352962426D}" + RootNamespace="filepath" Keyword="Win32Proj" > <Platforms> Modified: trunk/pmplib/lib/filepath/filepath_win32.c =================================================================== --- trunk/pmplib/lib/filepath/filepath_win32.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/lib/filepath/filepath_win32.c 2007-02-27 09:45:39 UTC (rev 397) @@ -31,11 +31,15 @@ #include <sys/stat.h> #include <windows.h> +#include <shlobj.h> #include <shlwapi.h> +#pragma comment(lib, "shell32.lib") +#pragma comment(lib, "shlwapi.lib") #include <pmplib/filepath.h> -#pragma comment(lib, "shlwapi.lib") +static const ucs2char_t ucs2cs_link_ext[] = {'.','m','3','u','8',0}; + int find_file(const ucs2char_t* path, int recursive, filepath_findfile_callback callback, void *instance) { HANDLE hFile = INVALID_HANDLE_VALUE; @@ -133,6 +137,12 @@ return p ? p+1 : NULL; } +const ucs2char_t* filepath_extract_extension(const ucs2char_t* path) +{ + ucs2char_t* p = ucs2rchr(path, '.'); + return p ? p : path; +} + void filepath_strippath(ucs2char_t* path) { PathStripPathW(path); @@ -206,17 +216,88 @@ return ret; } +int filepath_createdirs(const ucs2char_t* filename) +{ + return SHCreateDirectoryExW(NULL, (LPCWSTR)filename, NULL) == ERROR_SUCCESS ? 0 : 1; +} + int filepath_copyfile(const ucs2char_t* src, const ucs2char_t* dst) { return CopyFileW(src, dst, FALSE) ? 0 : -1; } +int filepath_movefile(const ucs2char_t* src, const ucs2char_t* dst) +{ + return MoveFileW(src, dst) ? 0 : -1; +} + int filepath_removefile(const ucs2char_t* file) { SetFileAttributesW(file, FILE_ATTRIBUTE_NORMAL); return DeleteFileW(file); } +int filepath_linkfile(const ucs2char_t* target, const ucs2char_t* link) +{ + /* Create a m3u8 playlist with the target file. */ + FILE *fp = NULL; + ucs2char_t* _link = alloca(sizeof(ucs2char_t) * (ucs2len(link) + ucs2len(ucs2cs_link_ext) + 1)); + + /* Add ".m3u8" extension. */ + ucs2cpy(_link, link); + ucs2cat(_link, ucs2cs_link_ext); + + /* Write the */ + fp = ucs2fopen(_link, "w"); + if (fp) { + char *utf8 = ucs2duputf8((const ucs2char_t*)PathSkipRootW((LPCWSTR)target)); + fputc('\\', fp); + fputs(utf8, fp); + ucs2free(utf8); + fclose(fp); + return 0; + } else { + return -1; + } +} + +int filepath_followlink(const ucs2char_t* link, ucs2char_t* org) +{ + /* Create a m3u8 playlist with the target file. */ + FILE *fp = NULL; + ucs2char_t* _link = (ucs2char_t*)alloca( + sizeof(ucs2char_t) * (ucs2len(link) + ucs2len(ucs2cs_link_ext) + 1)); + + /* Add ".m3u8" extension. */ + ucs2cpy(_link, link); + ucs2cat(_link, ucs2cs_link_ext); + + /* Write the */ + fp = ucs2fopen(_link, "r"); + if (fp) { + char buff[MAX_PATH*4]; + ucs2char_t target[MAX_PATH]; + fgets(buff, sizeof(buff)-1, fp); + utf8toucs2(target, MAX_PATH, buff, strlen(buff)+1); + filepath_combinepath(org, MAX_PATH, link, target); + return 0; + } else { + return -1; + } +} + +int filepath_removelinkfile(const ucs2char_t* file) +{ + ucs2char_t* _link = (ucs2char_t*)alloca( + sizeof(ucs2char_t) * (ucs2len(file) + ucs2len(ucs2cs_link_ext) + 1)); + + /* Add ".m3u8" extension. */ + ucs2cpy(_link, file); + ucs2cat(_link, ucs2cs_link_ext); + + return filepath_removefile(_link); +} + int filepath_encode(ucs2char_t* path) { /* Does nothing for WIN32. */ @@ -260,3 +341,8 @@ } return 0; } + +int filepath_is_link(const ucs2char_t *path) +{ + return filepath_hasext(path, ucs2cs_link_ext); +} Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-27 09:45:39 UTC (rev 397) @@ -415,7 +415,6 @@ if (pmp->flag & PMPOF_MUSIC_DB_WRITE) { ipod_set(&ipod, pmpmi->records, pmpmi->num_records, pmpmi->playlists, pmpmi->num_playlists); ipod_write(&ipod, itunesdb); - ipod_dump(&ipod, stdout); } exit_this: Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.vcproj 2007-02-27 09:45:39 UTC (rev 397) @@ -193,6 +193,10 @@ > </File> <File + RelativePath=".\settledb.c" + > + </File> + <File RelativePath=".\util.c" > </File> @@ -215,6 +219,10 @@ > </File> <File + RelativePath=".\settledb.h" + > + </File> + <File RelativePath=".\util.h" > </File> Modified: trunk/pmplib/lib/ucs2/ucs2char.c =================================================================== --- trunk/pmplib/lib/ucs2/ucs2char.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/lib/ucs2/ucs2char.c 2007-02-27 09:45:39 UTC (rev 397) @@ -410,3 +410,13 @@ } return dst; } + +char *ucs2duputf8(const ucs2char_t *ucs2str) +{ + size_t mbs_size = ucs2toutf8(NULL, 0, ucs2str, ucs2len(ucs2str)) + 1; + char* dst = (char *)malloc(mbs_size * sizeof(char)); + if (dst) { + ucs2toutf8(dst, mbs_size, ucs2str, ucs2len(ucs2str)+1); + } + return dst; +} Modified: trunk/pmplib/lib/ucs2/ucs2char_win32.c =================================================================== --- trunk/pmplib/lib/ucs2/ucs2char_win32.c 2007-02-25 14:16:32 UTC (rev 396) +++ trunk/pmplib/lib/ucs2/ucs2char_win32.c 2007-02-27 09:45:39 UTC (rev 397) @@ -99,8 +99,13 @@ return MultiByteToWideChar(CP_UTF8, 0, mbstr, (int)mbs_len, ucs2str, (int)ucs_len); } +size_t ucs2toutf8(char *mbstr, size_t mbs_len, const ucs2char_t *ucs2str, size_t ucs_len) +{ + return WideCharToMultiByte(CP_UTF8, 0, ucs2str, (int)ucs_len, mbstr, (int)mbs_len, NULL, NULL); +} + wchar_t* mbsdupwcs(const char *mbstr) { /* Just call mbsdupucs2(). */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-25 14:16:37
|
Revision: 396 http://svn.sourceforge.net/pmplib/?rev=396&view=rev Author: nyaochi Date: 2007-02-25 06:16:32 -0800 (Sun, 25 Feb 2007) Log Message: ----------- Fix some bugs in MP4 metadata reader. Modified Paths: -------------- trunk/pmplib/lib/gmi/gmi_mp4v2.c Modified: trunk/pmplib/lib/gmi/gmi_mp4v2.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_mp4v2.c 2007-02-24 17:17:22 UTC (rev 395) +++ trunk/pmplib/lib/gmi/gmi_mp4v2.c 2007-02-25 14:16:32 UTC (rev 396) @@ -96,30 +96,32 @@ } if (MP4GetMetadataName(mp4file, &value) && value != NULL) { + ucs2free(info->title); info->title = utf8dupucs2(value); free(value); } if (MP4GetMetadataArtist(mp4file, &value) && value != NULL) { + ucs2free(info->artist); info->artist = utf8dupucs2(value); free(value); } if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL) { + ucs2free(info->album); info->album = utf8dupucs2(value); free(value); } - if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL) { - info->album = utf8dupucs2(value); - free(value); - } if (MP4GetMetadataWriter(mp4file, &value) && value != NULL) { + ucs2free(info->composer); info->composer = utf8dupucs2(value); free(value); } if (MP4GetMetadataGenre(mp4file, &value) && value != NULL) { + ucs2free(info->genre); info->genre = utf8dupucs2(value); free(value); } if (MP4GetMetadataYear(mp4file, &value) && value != NULL) { + ucs2free(info->date); info->date = utf8dupucs2(value); free(value); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <suc...@us...> - 2007-02-24 17:17:22
|
Revision: 395 http://svn.sourceforge.net/pmplib/?rev=395&view=rev Author: sucknblow Date: 2007-02-24 09:17:22 -0800 (Sat, 24 Feb 2007) Log Message: ----------- No global vars appear in api docs. Remove dead link Modified Paths: -------------- trunk/pmplib/doc/pmplib-head.html Modified: trunk/pmplib/doc/pmplib-head.html =================================================================== --- trunk/pmplib/doc/pmplib-head.html 2007-02-24 11:19:50 UTC (rev 394) +++ trunk/pmplib/doc/pmplib-head.html 2007-02-24 17:17:22 UTC (rev 395) @@ -29,7 +29,6 @@ <li><a href="globals.html">All</a></li> <ul> <li><a href="globals_func.html">Functions</a></li> -<li><a href="globals_vars.html">Global variables</a></li> <li><a href="globals_eval.html">Enumeration Constants</a></li> <li><a href="globals_type.html">Typedefs</a></li> <li><a href="globals_defs.html">Preprocessor Definitions</a></li> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-24 11:19:50
|
Revision: 394 http://svn.sourceforge.net/pmplib/?rev=394&view=rev Author: nyaochi Date: 2007-02-24 03:19:50 -0800 (Sat, 24 Feb 2007) Log Message: ----------- Initial attempt to support MPEG4 files (m4a). The libgmi now has the dependency to libmp4v2: http://mpeg4ip.net/ http://resare.com/libmp4v2/ Still Win32 version only at this moment. Modified Paths: -------------- trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/gmi/gmi.c trunk/pmplib/lib/gmi/gmi.vcproj trunk/pmplib/lib/gmi/gmi_vorbis.c trunk/pmplib/lib/pmp_ipod/ipod.c Added Paths: ----------- trunk/pmplib/lib/gmi/contrib/mp4v2/ trunk/pmplib/lib/gmi/contrib/mp4v2/mp4.h trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip.h trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_version.h trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_win32.h trunk/pmplib/lib/gmi/contrib/mp4v2/win32/ trunk/pmplib/lib/gmi/contrib/mp4v2/win32/libmp4v260.lib trunk/pmplib/lib/gmi/contrib/mp4v2/win32/libmp4v260d.lib trunk/pmplib/lib/gmi/gmi_mp4v2.c Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-23 09:38:48 UTC (rev 393) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-24 11:19:50 UTC (rev 394) @@ -129,6 +129,8 @@ #define PMPCODEC_NONE PMPFOURCC(' ',' ',' ',' ') /** MPEG Audio Layer III. */ #define PMPCODEC_MPEGLAYER3 PMPFOURCC('M','P','A','3') +/** MPEG 4. */ +#define PMPCODEC_MPEG4AUDIO PMPFOURCC('M','P','4','A') /** Windows Media Audio. */ #define PMPCODEC_WMA PMPFOURCC('W','M','A',' ') /** Ogg Vorbis. */ @@ -340,6 +342,13 @@ ucs2char_t *artist; /** + * Album artist name. + * e.g., "Various" + * @assert @code album_artist != NULL @endcode + */ + ucs2char_t *album_artist; + + /** * Composer. * e.g., "John Lennon" * @assert @code composer != NULL @endcode @@ -368,6 +377,12 @@ ucs2char_t *date; /** + * Compilation flag. + * e.g., 1 for compilation album. + */ + uint8_t is_compilation; + + /** * FourCC representation of the codec. * e.g., PMPCODEC_MPEGLAYER3 */ Added: trunk/pmplib/lib/gmi/contrib/mp4v2/mp4.h =================================================================== --- trunk/pmplib/lib/gmi/contrib/mp4v2/mp4.h (rev 0) +++ trunk/pmplib/lib/gmi/contrib/mp4v2/mp4.h 2007-02-24 11:19:50 UTC (rev 394) @@ -0,0 +1,1222 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2005. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dm...@ci... + * Alix Marchandise-Franquet al...@ci... + * Ximpo Group Ltd. mp...@xi... + * Bill May wm...@ci... + */ + +#ifndef __MP4_INCLUDED__ +#define __MP4_INCLUDED__ + +/* include system and project specific headers */ +#include "mpeg4ip.h" + +#include <math.h> /* to define float HUGE_VAL and/or NAN */ +#ifndef NAN +#define NAN HUGE_VAL +#endif + +#ifdef __cplusplus +/* exploit C++ ability of default values for function parameters */ +#define DEFAULT(x) =x +#else +#define DEFAULT(x) +#endif + +/* MP4 API types */ +typedef void* MP4FileHandle; +typedef u_int32_t MP4TrackId; +typedef u_int32_t MP4SampleId; +typedef u_int64_t MP4Timestamp; +typedef u_int64_t MP4Duration; +typedef u_int32_t MP4EditId; + +/* Invalid values for API types */ +#define MP4_INVALID_FILE_HANDLE ((MP4FileHandle)NULL) +#define MP4_INVALID_TRACK_ID ((MP4TrackId)0) +#define MP4_INVALID_SAMPLE_ID ((MP4SampleId)0) +#define MP4_INVALID_TIMESTAMP ((MP4Timestamp)-1) +#define MP4_INVALID_DURATION ((MP4Duration)-1) +#define MP4_INVALID_EDIT_ID ((MP4EditId)0) + +/* Macros to test for API type validity */ +#define MP4_IS_VALID_FILE_HANDLE(x) ((x) != MP4_INVALID_FILE_HANDLE) +#define MP4_IS_VALID_TRACK_ID(x) ((x) != MP4_INVALID_TRACK_ID) +#define MP4_IS_VALID_SAMPLE_ID(x) ((x) != MP4_INVALID_SAMPLE_ID) +#define MP4_IS_VALID_TIMESTAMP(x) ((x) != MP4_INVALID_TIMESTAMP) +#define MP4_IS_VALID_DURATION(x) ((x) != MP4_INVALID_DURATION) +#define MP4_IS_VALID_EDIT_ID(x) ((x) != MP4_INVALID_EDIT_ID) + +/* MP4 verbosity levels - e.g. MP4SetVerbosity() */ +#define MP4_DETAILS_ALL 0xFFFFFFFF +#define MP4_DETAILS_ERROR 0x00000001 +#define MP4_DETAILS_WARNING 0x00000002 +#define MP4_DETAILS_READ 0x00000004 +#define MP4_DETAILS_WRITE 0x00000008 +#define MP4_DETAILS_FIND 0x00000010 +#define MP4_DETAILS_TABLE 0x00000020 +#define MP4_DETAILS_SAMPLE 0x00000040 +#define MP4_DETAILS_HINT 0x00000080 +#define MP4_DETAILS_ISMA 0x00000100 +#define MP4_DETAILS_EDIT 0x00000200 + +#define MP4_DETAILS_READ_ALL \ + (MP4_DETAILS_READ | MP4_DETAILS_TABLE | MP4_DETAILS_SAMPLE) +#define MP4_DETAILS_WRITE_ALL \ + (MP4_DETAILS_WRITE | MP4_DETAILS_TABLE | MP4_DETAILS_SAMPLE) + +/* + * MP4 Known track type names - e.g. MP4GetNumberOfTracks(type) + * + * Note this first group of track types should be created + * via the MP4Add<Type>Track() functions, and not MP4AddTrack(type) + */ +#define MP4_OD_TRACK_TYPE "odsm" +#define MP4_SCENE_TRACK_TYPE "sdsm" +#define MP4_AUDIO_TRACK_TYPE "soun" +#define MP4_VIDEO_TRACK_TYPE "vide" +#define MP4_HINT_TRACK_TYPE "hint" +#define MP4_CNTL_TRACK_TYPE "cntl" +/* + * This second set of track types should be created + * via MP4AddSystemsTrack(type) + */ +#define MP4_CLOCK_TRACK_TYPE "crsm" +#define MP4_MPEG7_TRACK_TYPE "m7sm" +#define MP4_OCI_TRACK_TYPE "ocsm" +#define MP4_IPMP_TRACK_TYPE "ipsm" +#define MP4_MPEGJ_TRACK_TYPE "mjsm" + +#define MP4_IS_VIDEO_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_VIDEO_TRACK_TYPE)) + +#define MP4_IS_AUDIO_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_AUDIO_TRACK_TYPE)) + +#define MP4_IS_CNTL_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_CNTL_TRACK_TYPE)) + +#define MP4_IS_OD_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_OD_TRACK_TYPE)) + +#define MP4_IS_SCENE_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_SCENE_TRACK_TYPE)) + +#define MP4_IS_HINT_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_HINT_TRACK_TYPE)) + +#define MP4_IS_SYSTEMS_TRACK_TYPE(type) \ + (!strcasecmp(type, MP4_CLOCK_TRACK_TYPE) \ + || !strcasecmp(type, MP4_MPEG7_TRACK_TYPE) \ + || !strcasecmp(type, MP4_OCI_TRACK_TYPE) \ + || !strcasecmp(type, MP4_IPMP_TRACK_TYPE) \ + || !strcasecmp(type, MP4_MPEGJ_TRACK_TYPE)) + +/* MP4 Audio track types - see MP4AddAudioTrack()*/ +#define MP4_INVALID_AUDIO_TYPE 0x00 +#define MP4_MPEG1_AUDIO_TYPE 0x6B +#define MP4_MPEG2_AUDIO_TYPE 0x69 +#define MP4_MP3_AUDIO_TYPE MP4_MPEG2_AUDIO_TYPE +#define MP4_MPEG2_AAC_MAIN_AUDIO_TYPE 0x66 +#define MP4_MPEG2_AAC_LC_AUDIO_TYPE 0x67 +#define MP4_MPEG2_AAC_SSR_AUDIO_TYPE 0x68 +#define MP4_MPEG2_AAC_AUDIO_TYPE MP4_MPEG2_AAC_MAIN_AUDIO_TYPE +#define MP4_MPEG4_AUDIO_TYPE 0x40 +#define MP4_PRIVATE_AUDIO_TYPE 0xC0 +#define MP4_PCM16_LITTLE_ENDIAN_AUDIO_TYPE 0xE0 /* a private definition */ +#define MP4_VORBIS_AUDIO_TYPE 0xE1 /* a private definition */ +#define MP4_AC3_AUDIO_TYPE 0xE2 /* a private definition */ +#define MP4_ALAW_AUDIO_TYPE 0xE3 /* a private definition */ +#define MP4_ULAW_AUDIO_TYPE 0xE4 /* a private definition */ +#define MP4_G723_AUDIO_TYPE 0xE5 /* a private definition */ +#define MP4_PCM16_BIG_ENDIAN_AUDIO_TYPE 0xE6 /* a private definition */ + +/* MP4 MPEG-4 Audio types from 14496-3 Table 1.5.1 */ +#define MP4_MPEG4_INVALID_AUDIO_TYPE 0 +#define MP4_MPEG4_AAC_MAIN_AUDIO_TYPE 1 +#define MP4_MPEG4_AAC_LC_AUDIO_TYPE 2 +#define MP4_MPEG4_AAC_SSR_AUDIO_TYPE 3 +#define MP4_MPEG4_AAC_LTP_AUDIO_TYPE 4 +#define MP4_MPEG4_AAC_HE_AUDIO_TYPE 5 +#define MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE 6 +#define MP4_MPEG4_CELP_AUDIO_TYPE 8 +#define MP4_MPEG4_HVXC_AUDIO_TYPE 9 +#define MP4_MPEG4_TTSI_AUDIO_TYPE 12 +#define MP4_MPEG4_MAIN_SYNTHETIC_AUDIO_TYPE 13 +#define MP4_MPEG4_WAVETABLE_AUDIO_TYPE 14 +#define MP4_MPEG4_MIDI_AUDIO_TYPE 15 +#define MP4_MPEG4_ALGORITHMIC_FX_AUDIO_TYPE 16 + +/* MP4 Audio type utilities following common usage */ +#define MP4_IS_MP3_AUDIO_TYPE(type) \ + ((type) == MP4_MPEG1_AUDIO_TYPE || (type) == MP4_MPEG2_AUDIO_TYPE) + +#define MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \ + (((type) >= MP4_MPEG2_AAC_MAIN_AUDIO_TYPE \ + && (type) <= MP4_MPEG2_AAC_SSR_AUDIO_TYPE)) + +#define MP4_IS_MPEG4_AAC_AUDIO_TYPE(mpeg4Type) \ + (((mpeg4Type) >= MP4_MPEG4_AAC_MAIN_AUDIO_TYPE \ + && (mpeg4Type) <= MP4_MPEG4_AAC_HE_AUDIO_TYPE) \ + || (mpeg4Type) == MP4_MPEG4_AAC_SCALABLE_AUDIO_TYPE \ + || (mpeg4Type) == 17) + +#define MP4_IS_AAC_AUDIO_TYPE(type) \ + (MP4_IS_MPEG2_AAC_AUDIO_TYPE(type) \ + || (type) == MP4_MPEG4_AUDIO_TYPE) + +/* MP4 Video track types - see MP4AddVideoTrack() */ +#define MP4_INVALID_VIDEO_TYPE 0x00 +#define MP4_MPEG1_VIDEO_TYPE 0x6A +#define MP4_MPEG2_SIMPLE_VIDEO_TYPE 0x60 +#define MP4_MPEG2_MAIN_VIDEO_TYPE 0x61 +#define MP4_MPEG2_SNR_VIDEO_TYPE 0x62 +#define MP4_MPEG2_SPATIAL_VIDEO_TYPE 0x63 +#define MP4_MPEG2_HIGH_VIDEO_TYPE 0x64 +#define MP4_MPEG2_442_VIDEO_TYPE 0x65 +#define MP4_MPEG2_VIDEO_TYPE MP4_MPEG2_MAIN_VIDEO_TYPE +#define MP4_MPEG4_VIDEO_TYPE 0x20 +#define MP4_JPEG_VIDEO_TYPE 0x6C +#define MP4_PRIVATE_VIDEO_TYPE 0xD0 +#define MP4_YUV12_VIDEO_TYPE 0xF0 /* a private definition */ +#define MP4_H263_VIDEO_TYPE 0xF2 /* a private definition */ +#define MP4_H261_VIDEO_TYPE 0xF3 /* a private definition */ + +/* MP4 Video type utilities */ +#define MP4_IS_MPEG1_VIDEO_TYPE(type) \ + ((type) == MP4_MPEG1_VIDEO_TYPE) + +#define MP4_IS_MPEG2_VIDEO_TYPE(type) \ + (((type) >= MP4_MPEG2_SIMPLE_VIDEO_TYPE \ + && (type) <= MP4_MPEG2_442_VIDEO_TYPE) \ + || MP4_IS_MPEG1_VIDEO_TYPE(type)) + +#define MP4_IS_MPEG4_VIDEO_TYPE(type) \ + ((type) == MP4_MPEG4_VIDEO_TYPE) + +/* Mpeg4 Visual Profile Defines - ISO/IEC 14496-2:2001/Amd.2:2002(E) */ +#define MPEG4_SP_L1 (0x1) +#define MPEG4_SP_L2 (0x2) +#define MPEG4_SP_L3 (0x3) +#define MPEG4_SP_L0 (0x8) +#define MPEG4_SSP_L1 (0x11) +#define MPEG4_SSP_L2 (0x12) +#define MPEG4_CP_L1 (0x21) +#define MPEG4_CP_L2 (0x22) +#define MPEG4_MP_L2 (0x32) +#define MPEG4_MP_L3 (0x33) +#define MPEG4_MP_L4 (0x34) +#define MPEG4_NBP_L2 (0x42) +#define MPEG4_STP_L1 (0x51) +#define MPEG4_SFAP_L1 (0x61) +#define MPEG4_SFAP_L2 (0x62) +#define MPEG4_SFBAP_L1 (0x63) +#define MPEG4_SFBAP_L2 (0x64) +#define MPEG4_BATP_L1 (0x71) +#define MPEG4_BATP_L2 (0x72) +#define MPEG4_HP_L1 (0x81) +#define MPEG4_HP_L2 (0x82) +#define MPEG4_ARTSP_L1 (0x91) +#define MPEG4_ARTSP_L2 (0x92) +#define MPEG4_ARTSP_L3 (0x93) +#define MPEG4_ARTSP_L4 (0x94) +#define MPEG4_CSP_L1 (0xa1) +#define MPEG4_CSP_L2 (0xa2) +#define MPEG4_CSP_L3 (0xa3) +#define MPEG4_ACEP_L1 (0xb1) +#define MPEG4_ACEP_L2 (0xb2) +#define MPEG4_ACEP_L3 (0xb3) +#define MPEG4_ACEP_L4 (0xb4) +#define MPEG4_ACP_L1 (0xc1) +#define MPEG4_ACP_L2 (0xc2) +#define MPEG4_AST_L1 (0xd1) +#define MPEG4_AST_L2 (0xd2) +#define MPEG4_AST_L3 (0xd3) +#define MPEG4_S_STUDIO_P_L1 (0xe1) +#define MPEG4_S_STUDIO_P_L2 (0xe2) +#define MPEG4_S_STUDIO_P_L3 (0xe3) +#define MPEG4_S_STUDIO_P_L4 (0xe4) +#define MPEG4_C_STUDIO_P_L1 (0xe5) +#define MPEG4_C_STUDIO_P_L2 (0xe6) +#define MPEG4_C_STUDIO_P_L3 (0xe7) +#define MPEG4_C_STUDIO_P_L4 (0xe8) +#define MPEG4_ASP_L0 (0xF0) +#define MPEG4_ASP_L1 (0xF1) +#define MPEG4_ASP_L2 (0xF2) +#define MPEG4_ASP_L3 (0xF3) +#define MPEG4_ASP_L4 (0xF4) +#define MPEG4_ASP_L5 (0xF5) +#define MPEG4_ASP_L3B (0xF7) +#define MPEG4_FGSP_L0 (0xf8) +#define MPEG4_FGSP_L1 (0xf9) +#define MPEG4_FGSP_L2 (0xfa) +#define MPEG4_FGSP_L3 (0xfb) +#define MPEG4_FGSP_L4 (0xfc) +#define MPEG4_FGSP_L5 (0xfd) + +/* MP4 API declarations */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* file operations */ +#define MP4_CREATE_64BIT_DATA (0x01) +#define MP4_CREATE_64BIT_TIME (0x02) // Quicktime is not compatible with this +#define MP4_CREATE_64BIT (MP4_CREATE_64BIT_DATA | MP4_CREATE_64BIT_TIME) +#define MP4_CREATE_EXTENSIBLE_FORMAT (0x04) + +MP4FileHandle MP4Create( + const char* fileName, + u_int32_t verbosity DEFAULT(0), + u_int32_t flags DEFAULT(0)); +MP4FileHandle MP4CreateEx( + const char *fileName, + u_int32_t verbosity DEFAULT(0), + u_int32_t flags DEFAULT(0), + int add_ftyp DEFAULT(1), + int add_iods DEFAULT(1), + char* majorBrand DEFAULT(0), + u_int32_t minorVersion DEFAULT(0), + char** supportedBrands DEFAULT(0), + u_int32_t supportedBrandsCount DEFAULT(0)); + +MP4FileHandle MP4Modify( + const char* fileName, + u_int32_t verbosity DEFAULT(0), + u_int32_t flags DEFAULT(0)); + +MP4FileHandle MP4Read( + const char* fileName, + u_int32_t verbosity DEFAULT(0)); + +bool MP4Close( + MP4FileHandle hFile); + +bool MP4Optimize( + const char* existingFileName, + const char* newFileName DEFAULT(NULL), + u_int32_t verbosity DEFAULT(0)); + +bool MP4Dump( + MP4FileHandle hFile, + FILE* pDumpFile DEFAULT(NULL), + bool dumpImplicits DEFAULT(0)); + +char* MP4Info( + MP4FileHandle hFile, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID)); + +char* MP4FileInfo( + const char* fileName, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID)); + +/* file properties */ + +/* specific file properties */ + +u_int32_t MP4GetVerbosity(MP4FileHandle hFile); + +bool MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity); + +MP4Duration MP4GetDuration(MP4FileHandle hFile); + +u_int32_t MP4GetTimeScale(MP4FileHandle hFile); + +bool MP4SetTimeScale(MP4FileHandle hFile, u_int32_t value); + +u_int8_t MP4GetODProfileLevel(MP4FileHandle hFile); + +bool MP4SetODProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetSceneProfileLevel(MP4FileHandle hFile); + +bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile, + MP4TrackId trackId DEFAULT(MP4_INVALID_TRACK_ID)); + +bool MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile); + +bool MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value); + +u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile); + +bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value); + +/* generic file properties */ +bool MP4HaveAtom(MP4FileHandle hFile, + const char *atomName); + +bool MP4GetIntegerProperty( + MP4FileHandle hFile, + const char* propName, + u_int64_t *retval ); + + +bool MP4GetFloatProperty( + MP4FileHandle hFile, + const char* propName, + float *retvalue); + +bool MP4GetStringProperty( + MP4FileHandle hFile, + const char* propName, + const char **retvalue); + +bool MP4GetBytesProperty( + MP4FileHandle hFile, + const char* propName, + u_int8_t** ppValue, + u_int32_t* pValueSize); + +bool MP4SetIntegerProperty( + MP4FileHandle hFile, + const char* propName, + int64_t value); + +bool MP4SetFloatProperty( + MP4FileHandle hFile, + const char* propName, + float value); + +bool MP4SetStringProperty( + MP4FileHandle hFile, const char* propName, const char* value); + +bool MP4SetBytesProperty( + MP4FileHandle hFile, const char* propName, + const u_int8_t* pValue, u_int32_t valueSize); + +/* track operations */ + +MP4TrackId MP4AddTrack( + MP4FileHandle hFile, + const char* type); + +MP4TrackId MP4AddSystemsTrack( + MP4FileHandle hFile, + const char* type); + +MP4TrackId MP4AddODTrack( + MP4FileHandle hFile); + +MP4TrackId MP4AddSceneTrack( + MP4FileHandle hFile); + +MP4TrackId MP4AddAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE)); + +typedef struct mp4v2_ismacryp_session_params { + u_int32_t scheme_type; + u_int16_t scheme_version; + u_int8_t key_ind_len; + u_int8_t iv_len; + u_int8_t selective_enc; + char *kms_uri; +} mp4v2_ismacrypParams; + + +MP4TrackId MP4AddEncAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + mp4v2_ismacrypParams *icPp, + u_int8_t audioType DEFAULT(MP4_MPEG4_AUDIO_TYPE)); +MP4TrackId MP4AddAmrAudioTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + u_int16_t modeSet, + u_int8_t modeChangePeriod, + u_int8_t framesPerSample, + bool isAmrWB); + +void MP4SetAmrVendor( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t vendor); + +void MP4SetAmrDecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t decoderVersion); + +void MP4SetAmrModeSet(MP4FileHandle hFile, MP4TrackId trakId, uint16_t modeSet); +uint16_t MP4GetAmrModeSet(MP4FileHandle hFile, MP4TrackId trackId); + +MP4TrackId MP4AddHrefTrack(MP4FileHandle hFile, + uint32_t timeScale, + MP4Duration sampleDuration); + +MP4TrackId MP4AddVideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE)); + +MP4TrackId MP4AddEncVideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + mp4v2_ismacrypParams *icPp, + u_int8_t videoType DEFAULT(MP4_MPEG4_VIDEO_TYPE)); + +MP4TrackId MP4AddH264VideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + uint8_t AVCProfileIndication, + uint8_t profile_compat, + uint8_t AVCLevelIndication, + uint8_t sampleLenFieldSizeMinusOne); +bool MP4AddH264SequenceParameterSet(MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pSequence, + uint16_t sequenceLen); +bool MP4AddH264PictureParameterSet(MP4FileHandle hFile, + MP4TrackId trackId, + const uint8_t *pPict, + uint16_t pictLen); +void MP4SetH263Vendor( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t vendor); + +void MP4SetH263DecoderVersion( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t decoderVersion); + +void MP4SetH263Bitrates( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t avgBitrate, + u_int32_t maxBitrate); + +MP4TrackId MP4AddH263VideoTrack( + MP4FileHandle hFile, + u_int32_t timeScale, + MP4Duration sampleDuration, + u_int16_t width, + u_int16_t height, + u_int8_t h263Level, + u_int8_t h263Profile, + u_int32_t avgBitrate, + u_int32_t maxBitrate); + +MP4TrackId MP4AddHintTrack( + MP4FileHandle hFile, + MP4TrackId refTrackId); + +MP4TrackId MP4CloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +MP4TrackId MP4EncAndCloneTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams *icPp, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +MP4TrackId MP4CopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +typedef u_int32_t (*encryptFunc_t)(u_int32_t, u_int32_t, u_int8_t*, u_int32_t*, u_int8_t **); + +MP4TrackId MP4EncAndCopyTrack( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + mp4v2_ismacrypParams *icPp, + encryptFunc_t encfcnp, + u_int32_t encfcnparam1, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + bool applyEdits DEFAULT(false), + MP4TrackId dstHintTrackReferenceTrack DEFAULT(MP4_INVALID_TRACK_ID)); + +bool MP4DeleteTrack( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int32_t MP4GetNumberOfTracks( + MP4FileHandle hFile, + const char* type DEFAULT(NULL), + u_int8_t subType DEFAULT(0)); + +MP4TrackId MP4FindTrackId( + MP4FileHandle hFile, + u_int16_t index, + const char* type DEFAULT(NULL), + u_int8_t subType DEFAULT(0)); + +u_int16_t MP4FindTrackIndex( + MP4FileHandle hFile, + MP4TrackId trackId); + +/* track properties */ + +/* specific track properties */ + +bool MP4HaveTrackAtom(MP4FileHandle hFile, + MP4TrackId trackId, + const char *atomname); + +const char* MP4GetTrackType( + MP4FileHandle hFile, + MP4TrackId trackId); + +const char *MP4GetTrackMediaDataName(MP4FileHandle hFile, + MP4TrackId trackId); +MP4Duration MP4GetTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int32_t MP4GetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId); + +bool MP4SetTrackTimeScale( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int32_t value); + +u_int8_t MP4GetTrackAudioMpeg4Type( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int8_t MP4GetTrackEsdsObjectTypeId( + MP4FileHandle hFile, + MP4TrackId trackId); + +/* returns MP4_INVALID_DURATION if track samples do not have a fixed duration */ +MP4Duration MP4GetTrackFixedSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int32_t MP4GetTrackBitRate( + MP4FileHandle hFile, + MP4TrackId trackId); + +bool MP4GetTrackVideoMetadata(MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t **ppConfig, + uint32_t *pConfigSize); + +bool MP4GetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int8_t** ppConfig, + u_int32_t* pConfigSize); + +bool MP4SetTrackESConfiguration( + MP4FileHandle hFile, + MP4TrackId trackId, + const u_int8_t* pConfig, + u_int32_t configSize); + +/* h264 information routines */ +bool MP4GetTrackH264ProfileLevel(MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t *pProfile, + uint8_t *pLevel); +bool MP4GetTrackH264SeqPictHeaders(MP4FileHandle hFile, + MP4TrackId trackId, + uint8_t ***pSeqHeaders, + uint32_t **pSeqHeaderSize, + uint8_t ***pPictHeader, + uint32_t **pPictHeaderSize); +bool MP4GetTrackH264LengthSize(MP4FileHandle hFile, + MP4TrackId trackId, + uint32_t *pLength); +MP4SampleId MP4GetTrackNumberOfSamples( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int16_t MP4GetTrackVideoWidth( + MP4FileHandle hFile, + MP4TrackId trackId); + +u_int16_t MP4GetTrackVideoHeight( + MP4FileHandle hFile, + MP4TrackId trackId); + +double MP4GetTrackVideoFrameRate( + MP4FileHandle hFile, + MP4TrackId trackId); + +int MP4GetTrackAudioChannels(MP4FileHandle hFile, + MP4TrackId trackId); + +bool MP4IsIsmaCrypMediaTrack( + MP4FileHandle hFile, + MP4TrackId trackId); + +/* generic track properties */ + +bool MP4HaveTrackAtom(MP4FileHandle hFile, + MP4TrackId trackId, + const char *atomName); + +bool MP4GetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + u_int64_t *retvalue); + +bool MP4GetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float *ret_value); + +bool MP4GetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char **retvalue); + +bool MP4GetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + u_int8_t** ppValue, + u_int32_t* pValueSize); + +bool MP4SetTrackIntegerProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + int64_t value); + +bool MP4SetTrackFloatProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + float value); + +bool MP4SetTrackStringProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const char* value); + +bool MP4SetTrackBytesProperty( + MP4FileHandle hFile, + MP4TrackId trackId, + const char* propName, + const u_int8_t* pValue, + u_int32_t valueSize); + +/* sample operations */ + +bool MP4ReadSample( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + /* input/output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL)); + +/* uses (unedited) time to specify sample instead of sample id */ +bool MP4ReadSampleFromTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* input/output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL)); + +bool MP4WriteSample( + MP4FileHandle hFile, + MP4TrackId trackId, + const u_int8_t* pBytes, + u_int32_t numBytes, + MP4Duration duration DEFAULT(MP4_INVALID_DURATION), + MP4Duration renderingOffset DEFAULT(0), + bool isSyncSample DEFAULT(true)); + +bool MP4CopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID), + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION)); + +bool MP4EncAndCopySample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + encryptFunc_t encfcnp, + u_int32_t encfcnparam1, + MP4FileHandle dstFile DEFAULT(MP4_INVALID_FILE_HANDLE), + MP4TrackId dstTrackId DEFAULT(MP4_INVALID_TRACK_ID), + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION)); + +/* Note this function is not yet implemented */ +bool MP4ReferenceSample( + MP4FileHandle srcFile, + MP4TrackId srcTrackId, + MP4SampleId srcSampleId, + MP4FileHandle dstFile, + MP4TrackId dstTrackId, + MP4Duration dstSampleDuration DEFAULT(MP4_INVALID_DURATION)); + +u_int32_t MP4GetSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +u_int32_t MP4GetTrackMaxSampleSize( + MP4FileHandle hFile, + MP4TrackId trackId); + +MP4SampleId MP4GetSampleIdFromTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + bool wantSyncSample DEFAULT(false)); + +MP4Timestamp MP4GetSampleTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +MP4Duration MP4GetSampleDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +MP4Duration MP4GetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +bool MP4SetSampleRenderingOffset( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId, + MP4Duration renderingOffset); + +int8_t MP4GetSampleSync( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4SampleId sampleId); + +/* rtp hint track operations */ + +bool MP4GetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + char** ppPayloadName DEFAULT(NULL), + u_int8_t* pPayloadNumber DEFAULT(NULL), + u_int16_t* pMaxPayloadSize DEFAULT(NULL), + char **ppEncodingParams DEFAULT(NULL)); + +#define MP4_SET_DYNAMIC_PAYLOAD 0xff + +bool MP4SetHintTrackRtpPayload( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* pPayloadName, + u_int8_t* pPayloadNumber, + u_int16_t maxPayloadSize DEFAULT(0), + const char *encode_params DEFAULT(NULL), + bool include_rtp_map DEFAULT(true), + bool include_mpeg4_esid DEFAULT(true)); + +const char* MP4GetSessionSdp( + MP4FileHandle hFile); + +bool MP4SetSessionSdp( + MP4FileHandle hFile, + const char* sdpString); + +bool MP4AppendSessionSdp( + MP4FileHandle hFile, + const char* sdpString); + +const char* MP4GetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4SetHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString); + +bool MP4AppendHintTrackSdp( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const char* sdpString); + +MP4TrackId MP4GetHintTrackReferenceTrackId( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4ReadRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId hintSampleId, + u_int16_t* pNumPackets DEFAULT(NULL)); + +u_int16_t MP4GetRtpHintNumberOfPackets( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +int8_t MP4GetRtpPacketBFrame( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex); + +int32_t MP4GetRtpPacketTransmitOffset( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex); + +bool MP4ReadRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + u_int16_t packetIndex, + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + u_int32_t ssrc DEFAULT(0), + bool includeHeader DEFAULT(true), + bool includePayload DEFAULT(true)); + +MP4Timestamp MP4GetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4SetRtpTimestampStart( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Timestamp rtpStart); + +bool MP4AddRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4AddRtpVideoHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool isBframe DEFAULT(false), + u_int32_t timestampOffset DEFAULT(0)); + +bool MP4AddRtpPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + bool setMbit DEFAULT(false), + int32_t transmitOffset DEFAULT(0)); + +bool MP4AddRtpImmediateData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + const u_int8_t* pBytes, + u_int32_t numBytes); + +bool MP4AddRtpSampleData( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4SampleId sampleId, + u_int32_t dataOffset, + u_int32_t dataLength); + +bool MP4AddRtpESConfigurationPacket( + MP4FileHandle hFile, + MP4TrackId hintTrackId); + +bool MP4WriteRtpHint( + MP4FileHandle hFile, + MP4TrackId hintTrackId, + MP4Duration duration, + bool isSyncSample DEFAULT(true)); + +/* 3GP specific utilities */ + +bool MP4Make3GPCompliant( + const char* fileName, + u_int32_t verbosity DEFAULT(0), + char* majorBrand DEFAULT(0), + u_int32_t minorVersion DEFAULT(0), + char** supportedBrands DEFAULT(NULL), + u_int32_t supportedBrandsCount DEFAULT(0), + bool deleteIodsAtom DEFAULT(true)); + +/* ISMA specific utilities */ + +bool MP4MakeIsmaCompliant(const char* fileName, + u_int32_t verbosity DEFAULT(0), + bool addIsmaComplianceSdp DEFAULT(true)); + +char* MP4MakeIsmaSdpIod( + u_int8_t videoProfile, + u_int32_t videoBitrate, + u_int8_t* videoConfig, + u_int32_t videoConfigLength, + u_int8_t audioProfile, + u_int32_t audioBitrate, + u_int8_t* audioConfig, + u_int32_t audioConfigLength, + u_int32_t verbosity DEFAULT(0)); + +/* edit list */ + +/* NOTE this section of functionality + * has not yet been fully tested + */ + +MP4EditId MP4AddTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID), + MP4Timestamp startTime DEFAULT(0), + MP4Duration duration DEFAULT(0), + bool dwell DEFAULT(false)); + +bool MP4DeleteTrackEdit( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +u_int32_t MP4GetTrackNumberOfEdits( + MP4FileHandle hFile, + MP4TrackId trackId); + +MP4Timestamp MP4GetTrackEditStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +MP4Duration MP4GetTrackEditTotalDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId DEFAULT(MP4_INVALID_EDIT_ID)); + +MP4Timestamp MP4GetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +bool MP4SetTrackEditMediaStart( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Timestamp startTime); + +MP4Duration MP4GetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +bool MP4SetTrackEditDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + MP4Duration duration); + +int8_t MP4GetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId); + +bool MP4SetTrackEditDwell( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4EditId editId, + bool dwell); + +bool MP4ReadSampleFromEditTime( + /* input parameters */ + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + /* input/output parameters */ + u_int8_t** ppBytes, + u_int32_t* pNumBytes, + /* output parameters */ + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL), + MP4Duration* pRenderingOffset DEFAULT(NULL), + bool* pIsSyncSample DEFAULT(NULL)); + +MP4SampleId MP4GetSampleIdFromEditTime( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp when, + MP4Timestamp* pStartTime DEFAULT(NULL), + MP4Duration* pDuration DEFAULT(NULL)); +/* iTunes metadata handling */ +bool MP4MetadataDelete(MP4FileHandle hFile); +bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index, + const char** ppName, + u_int8_t** ppValue, u_int32_t* pValueSize); +bool MP4SetMetadataName(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataName(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataName(MP4FileHandle hFile); +bool MP4SetMetadataArtist(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataArtist(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataArtist(MP4FileHandle hFile); +bool MP4SetMetadataWriter(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataWriter(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataWriter(MP4FileHandle hFile); +bool MP4SetMetadataComment(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataComment(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataComment(MP4FileHandle hFile); +bool MP4SetMetadataTool(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataTool(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataTool(MP4FileHandle hFile); +bool MP4SetMetadataYear(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataYear(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataYear(MP4FileHandle hFile); +bool MP4SetMetadataAlbum(MP4FileHandle hFile, const char* value); +bool MP4GetMetadataAlbum(MP4FileHandle hFile, char** value); +bool MP4DeleteMetadataAlbum(MP4FileHandle hFile); +bool MP4SetMetadataTrack(MP4FileHandle hFile, + u_int16_t track, u_int16_t totalTracks); +bool MP4GetMetadataTrack(MP4FileHandle hFile, + u_int16_t* track, u_int16_t* totalTracks); +bool MP4DeleteMetadataTrack(MP4FileHandle hFile); +bool MP4SetMetadataDisk(MP4FileHandle hFile, + u_int16_t disk, u_int16_t totalDisks); +bool MP4GetMetadataDisk(MP4FileHandle hFile, + u_int16_t* disk, u_int16_t* totalDisks); +bool MP4DeleteMetadataDisk(MP4FileHandle hFile); +bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre); +bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre); +bool MP4DeleteMetadataGenre(MP4FileHandle hFile); +bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping); +bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping); +bool MP4DeleteMetadataGrouping(MP4FileHandle hFile); +bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo); +bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo); +bool MP4DeleteMetadataTempo(MP4FileHandle hFile); +bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl); +bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl); +bool MP4DeleteMetadataCompilation(MP4FileHandle hFile); +bool MP4SetMetadataCoverArt(MP4FileHandle hFile, + u_int8_t *coverArt, u_int32_t size); +bool MP4GetMetadataCoverArt(MP4FileHandle hFile, + u_int8_t **coverArt, u_int32_t* size); +u_int32_t MP4GetMetadataCoverArtCount(MP4FileHandle hFile); +bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile); +bool MP4SetMetadataFreeForm(MP4FileHandle hFile, char *name, + u_int8_t* pValue, u_int32_t valueSize); +bool MP4GetMetadataFreeForm(MP4FileHandle hFile, char *name, + u_int8_t** pValue, u_int32_t* valueSize); +bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, char *name); + + +/* time conversion utilties */ + +/* predefined values for timeScale parameter below */ +#define MP4_SECONDS_TIME_SCALE 1 +#define MP4_MILLISECONDS_TIME_SCALE 1000 +#define MP4_MICROSECONDS_TIME_SCALE 1000000 +#define MP4_NANOSECONDS_TIME_SCALE 1000000000 + +#define MP4_SECS_TIME_SCALE MP4_SECONDS_TIME_SCALE +#define MP4_MSECS_TIME_SCALE MP4_MILLISECONDS_TIME_SCALE +#define MP4_USECS_TIME_SCALE MP4_MICROSECONDS_TIME_SCALE +#define MP4_NSECS_TIME_SCALE MP4_NANOSECONDS_TIME_SCALE + +u_int64_t MP4ConvertFromMovieDuration( + MP4FileHandle hFile, + MP4Duration duration, + u_int32_t timeScale); + +u_int64_t MP4ConvertFromTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Timestamp timeStamp, + u_int32_t timeScale); + +MP4Timestamp MP4ConvertToTrackTimestamp( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int64_t timeStamp, + u_int32_t timeScale); + +u_int64_t MP4ConvertFromTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + MP4Duration duration, + u_int32_t timeScale); + +MP4Duration MP4ConvertToTrackDuration( + MP4FileHandle hFile, + MP4TrackId trackId, + u_int64_t duration, + u_int32_t timeScale); + +char* MP4BinaryToBase16( + const u_int8_t* pData, + u_int32_t dataSize); + +char* MP4BinaryToBase64( + const u_int8_t* pData, + u_int32_t dataSize); + +uint8_t *Base64ToBinary(const char *pData, + uint32_t decodeSize, + uint32_t *pDataSize); + +#ifdef __cplusplus +} +#endif + +/* undefined our utlity macro to avoid conflicts */ +#undef DEFAULT + +#endif /* __MP4_INCLUDED__ */ Added: trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip.h =================================================================== --- trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip.h (rev 0) +++ trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip.h 2007-02-24 11:19:50 UTC (rev 394) @@ -0,0 +1,335 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2000-2005. All Rights Reserved. + * + * Contributor(s): + * Dave Mackie dm...@ci... + * Bill May wm...@ci... + */ + +#ifndef __MPEG4IP_INCLUDED__ +#define __MPEG4IP_INCLUDED__ + +/* project wide applicable stuff here */ + + +#ifndef _WIN32 +#ifdef PACKAGE_BUGREPORT +#define TEMP_PACKAGE_BUGREPORT PACKAGE_BUGREPORT +#define TEMP_PACKAGE_NAME PACKAGE_NAME +#define TEMP_PACKAGE_STRING PACKAGE_STRING +#define TEMP_PACKAGE_TARNAME PACKAGE_TARNAME +#define TEMP_PACKAGE_VERSION PACKAGE_VERSION +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#include <mpeg4ip_config.h> +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#define PACKAGE_BUGREPORT TEMP_PACKAGE_BUGREPORT +#define PACKAGE_NAME TEMP_PACKAGE_NAME +#define PACKAGE_STRING TEMP_PACKAGE_STRING +#define PACKAGE_TARNAME TEMP_PACKAGE_TARNAME +#define PACKAGE_VERSION TEMP_PACKAGE_VERSION +#else +#include <mpeg4ip_config.h> +#endif +#endif + +// the mpeg4ip_package and mpeg4ip_version are always in this +// file +#include "mpeg4ip_version.h" + +#ifdef _WIN32 +#include "mpeg4ip_win32.h" +#include "mpeg4ip_version.h" +#else /* UNIX */ +/***************************************************************************** + * UNIX LIKE DEFINES BELOW THIS POINT + *****************************************************************************/ +#ifdef sun +#include <sys/feature_tests.h> +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#else +#ifndef sun +#if _FILE_OFFSET_BITS < 64 + #error File offset bits is already set to non-64 value +#endif +#endif +#endif + +#ifndef _LARGEFILE_SOURCE +#define _LARGEFILE_SOURCE +#endif +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#endif +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif +#if !defined(HAVE_INTTYPES_H) && !defined(HAVE_STDINT_H) +#error "Don't have stdint.h or inttypes.h - no way to get uint8_t" +#endif + +#include <unistd.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <syslog.h> +#include <string.h> +#include <ctype.h> +#include <netdb.h> +#include <sys/stat.h> +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#else +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#else +#include <time.h> +#endif +#endif +#include <sys/param.h> + +#ifdef __cplusplus +extern "C" { +#endif +char *strcasestr(const char *haystack, const char *needle); +#ifdef __cplusplus +} +#endif + +#define OPEN_RDWR O_RDWR +#define OPEN_CREAT O_CREAT +#define OPEN_RDONLY O_RDONLY + +#define closesocket close +#define IOSBINARY ios::bin + +#if SIZEOF_LONG == 8 +#define MAX_UINT64 -1LU +#define D64F "ld" +#define U64F "lu" +#define X64F "lx" + +#define TO_D64(a) (a##L) +#define TO_U64(a) (a##LU) +#else +#define MAX_UINT64 -1LLU +#define D64F "lld" +#define U64F "llu" +#define X64F "llx" + +#define TO_D64(a) (a##LL) +#define TO_U64(a) (a##LLU) +#endif + +#ifdef HAVE_FPOS_T___POS +#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)((fpos).__pos) +#define VAR_TO_FPOS(fpos, var) (fpos).__pos = (var) +#else +#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(fpos) +#define VAR_TO_FPOS(fpos, var) (fpos) = (var) +#endif + +#define FOPEN_READ_BINARY "r" +#define FOPEN_WRITE_BINARY "w" +#define UINT64_TO_DOUBLE(a) ((double)(a)) +#endif /* define unix */ + +/***************************************************************************** + * Generic type includes used in the whole package * + *****************************************************************************/ +#define D64 "%"D64F +#define U64 "%"U64F +#define X64 "%"X64F + +#define M_LLU TO_U64(1000) +#define M_64 TO_U64(1000) +#define LLU U64 + +#include <stdarg.h> +typedef void (*error_msg_func_t)(int loglevel, + const char *lib, + const char *fmt, + va_list ap); +typedef void (*lib_message_func_t)(int loglevel, + const char *lib, + const char *fmt, + ...); +#ifndef HAVE_IN_PORT_T +typedef uint16_t in_port_t; +#endif + +#ifndef HAVE_SOCKLEN_T +typedef unsigned int socklen_t; +#endif + +#ifdef sun +#include <limits.h> +#define u_int8_t uint8_t +#define u_int16_t uint16_t +#define u_int32_t uint32_t +#define u_int64_t uint64_t +#define __STRING(expr) #expr +#endif + +#ifndef HAVE_STRSEP +#ifdef __cplusplus +extern "C" { +#endif +char *strsep(char **strp, const char *delim); +#ifdef __cplusplus +} +#endif +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE (-1) +#endif + +#define MALLOC_STRUCTURE(a) ((a *)malloc(sizeof(a))) + +#define CHECK_AND_FREE(a) if ((a) != NULL) { free((void *)(a)); (a) = NULL;} + +#define NUM_ELEMENTS_IN_ARRAY(name) ((sizeof((name))) / (sizeof(*(name)))) + +#define ADV_SPACE(a) {while (isspace(*(a)) && (*(a) != '\0'))(a)++;} + +#ifndef HAVE_GTK +typedef char gchar; +typedef unsigned char guchar; + +typedef int gint; +typedef unsigned int guint; + +typedef long glong; +typedef unsigned long gulong; + +typedef double gdouble; + +typedef int gboolean; + +typedef int16_t gint16; +typedef uint16_t guint16; + +typedef int32_t gint32; +typedef uint32_t guint32; + +typedef int64_t gint64; +typedef uint64_t guint64; + +typedef uint8_t guint8; +typedef int8_t gint8; + +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef __cplusplus + +#ifndef bool + #if SIZEOF_BOOL == 8 + typedef uint64_t bool; + #else + #if SIZEOF_BOOL == 4 + typedef uint32_t bool; + #else + #if SIZEOF_BOOL == 2 + typedef uint16_t bool; + #else + typedef unsigned char bool; + #endif + #endif + #endif + #ifndef false + #define false FALSE + #endif + #ifndef true + #define true TRUE + #endif +#endif + +#endif + +#ifndef ROUND +# ifdef HAVE_RINT +# define ROUND(f) rint(f) +# else +# define ROUND(f) (int)(floor((f) + 0.5)) +# endif +#endif + +#ifndef INT16_MAX +# define INT16_MAX (32767) +#endif +#ifndef INT16_MIN +# define INT16_MIN (-32767-1) +#endif + +#ifndef UINT32_MAX +# define UINT32_MAX (4294967295U) +#endif + +#ifndef UINT64_MAX +# define UINT64_MAX TO_U64(0xffffffffffffffff) +#endif + +typedef enum audio_format_t { + AUDIO_FMT_U8 = 0, + AUDIO_FMT_S8, + AUDIO_FMT_U16LSB, + AUDIO_FMT_S16LSB, + AUDIO_FMT_U16MSB, + AUDIO_FMT_S16MSB, + AUDIO_FMT_U16, + AUDIO_FMT_S16, + AUDIO_FMT_FLOAT, + AUDIO_FMT_HW_AC3, +} audio_format_t; + +#endif /* __MPEG4IP_INCLUDED__ */ + Added: trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_version.h =================================================================== --- trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_version.h (rev 0) +++ trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_version.h 2007-02-24 11:19:50 UTC (rev 394) @@ -0,0 +1,6 @@ +#define MPEG4IP_PACKAGE "mpeg4ip" +#define MPEG4IP_VERSION "1.5.0.1" +#define MPEG4IP_MAJOR_VERSION 0x1 +#define MPEG4IP_MINOR_VERSION 0x5 +#define MPEG4IP_CVS_VERSION 0x01 +#define MPEG4IP_HEX_VERSION ((MPEG4IP_MAJOR_VERSION << 16) | (MPEG4IP_MINOR_VERSION << 8) | MPEG4IP_CVS_VERSION) Added: trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_win32.h =================================================================== --- trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_win32.h (rev 0) +++ trunk/pmplib/lib/gmi/contrib/mp4v2/mpeg4ip_win32.h 2007-02-24 11:19:50 UTC (rev 394) @@ -0,0 +1,130 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2005. All Rights Reserved. + * + * Contributor(s): + * Bill May wm...@ci... + */ +/* windows defines */ +#ifndef __MPEG4IP_WIN32_H__ +#define __MPEG4IP_WIN32_H__ +#define HAVE_IN_PORT_T +#define HAVE_SOCKLEN_T +#define NEED_SDL_VIDEO_IN_MAIN_THREAD +#define _WIN32_WINNT 0x0400 +#define _WINSOCKAPI_ +#define _INTEGRAL_MAX_BITS 64 +#include <windows.h> +#include <winsock2.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <time.h> +#include <limits.h> + +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int64 u_int64_t; +typedef unsigned __int32 u_int32_t; +typedef unsigned __int16 u_int16_t; +typedef unsigned __int8 u_int8_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +typedef __int16 int16_t; +typedef __int8 int8_t; +typedef unsigned short in_port_t; +typedef int socklen_t; +typedef int ssize_t; +typedef unsigned int uint; +#define snprintf _snprintf +#define strncasecmp _strnicmp +#define strcasecmp _stricmp + +#include <io.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#define write _write +#define lseek _lseek +#define close _close +#define open _open +#define access _access +#define vsnprintf _vsnprintf +#define stat _stati64 +#define fstat _fstati64 +#define F_OK 0 +#define OPEN_RDWR (_O_RDWR | _O_BINARY) +#define OPEN_CREAT (_O_CREAT | _O_BINARY) +#define OPEN_RDONLY (_O_RDONLY | _O_BINARY) +#define srandom srand +#define random rand + +#define IOSBINARY ios::binary + +#ifdef __cplusplus +extern "C" { +#endif +int gettimeofday(struct timeval *t, void *); +#ifdef __cplusplus +} +#endif + +#define PATH_MAX MAX_PATH +#define MAX_UINT64 -1 +#define D64F "I64d" +#define U64F "I64u" +#define X64F "I64x" + +#define TO_D64(a) (a##I64) +#define TO_U64(a) (a##UI64) + +#define LOG_EMERG 0 +#define LOG_ALERT 1 +#define LOG_CRIT 2 +#define LOG_ERR 3 +#define LOG_WARNING 4 +#define LOG_NOTICE 5 +#define LOG_INFO 6 +#define LOG_DEBUG 7 + +#if !__STDC__ && _INTEGRAL_MAX_BITS >= 64 +#define VAR_TO_FPOS(fpos, var) (fpos) = (var) +#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)(fpos) +#else +#define VAR_TO_FPOS(fpos, var) (fpos).lopart = ((var) & UINT_MAX); (fpos).hipart = ((var) >> 32) +#define FPOS_TO_VAR(fpos, typed, var) (var) = (typed)((uint64_t)((fpos).hipart ) << 32 | (fpos).lopart) +#endif + +#define __STRING(expr) #expr + +#define FOPEN_READ_BINARY "rb" +#define FOPEN_WRITE_BINARY "wb" + +#define UINT64_TO_DOUBLE(a) ((double)((int64_t)(a))) +#ifdef __cplusplus +extern "C" { +#endif +char *strcasestr(const char *haystack, const char *needle); +#ifdef __cplusplus +} +#endif + + +#define SIZEOF_BOOL 1 + +#endif Added: trunk/pmplib/lib/gmi/contrib/mp4v2/win32/libmp4v260.lib =================================================================== (Binary files differ) Property changes on: trunk/pmplib/lib/gmi/contrib/mp4v2/win32/libmp4v260.lib ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Added: trunk/pmplib/lib/gmi/contrib/mp4v2/win32/libmp4v260d.lib =================================================================== (Binary files differ) Property changes on: trunk/pmplib/lib/gmi/contrib/mp4v2/win32/libmp4v260d.lib ___________________________________________________________________ Name: svn:mime-type + application/octet-stream Modified: trunk/pmplib/lib/gmi/gmi.c =================================================================== --- trunk/pmplib/lib/gmi/gmi.c 2007-02-23 09:38:48 UTC (rev 393) +++ trunk/pmplib/lib/gmi/gmi.c 2007-02-24 11:19:50 UTC (rev 394) @@ -39,6 +39,9 @@ int gmi_mp3(media_info_t* info, const ucs2char_t *filename, const char *charset); static const ucs2char_t ucs2cs_ext_mp3[] = {'.','m','p','3',0}; +int gmi_mp4v2(media_info_t* info, const ucs2char_t *filename, const char *charset); +static const ucs2char_t ucs2cs_ext_m4a[] = {'.','m','4','a',0}; + int gmi_wma(media_info_t* info, const ucs2char_t *filename, const char *charset); static const ucs2char_t ucs2cs_ext_wma[] = {'.','w','m','a',0}; @@ -55,6 +58,7 @@ static gmi_exports_t gmi_exports[] = { {gmi_mp3, ucs2cs_ext_mp3}, + {gmi_mp4v2, ucs2cs_ext_m4a}, {gmi_wma, ucs2cs_ext_wma}, {gmi_vorbis, ucs2cs_ext_ogg}, {gmi_wav, ucs2cs_ext_wav}, Modified: trunk/pmplib/lib/gmi/gmi.vcproj =================================================================== --- trunk/pmplib/lib/gmi/gmi.vcproj 2007-02-23 09:38:48 UTC (rev 393) +++ trunk/pmplib/lib/gmi/gmi.vcproj 2007-02-24 11:19:50 UTC (rev 394) @@ -4,6 +4,7 @@ Version="8.00" Name="gmi" ProjectGUID="{3575EFC2-9051-467A-BEB4-E71E2F8664D7}" + RootNamespace="gmi" Keyword="Win32Proj" > <Platforms> @@ -40,7 +41,7 @@ <Tool Name="VCCLCompilerTool" Optimization="0" - AdditionalIncludeDirectories="$(SolutionDir)include,contrib,contrib\id3tag" + AdditionalIncludeDirectories="$(SolutionDir)include,contrib,contrib\id3tag,contrib\mp4v2" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;GMI_EXPORTS" MinimalRebuild="true" BasicRuntimeChecks="3" @@ -61,7 +62,7 @@ /> <Tool Name="VCLinkerTool" - AdditionalDependencies=".\contrib\id3tag\win32\libid3tagd.lib .\contrib\id3tag\win32\zlibd.lib .\contrib\ogg\win32\ogg_static_d.lib .\contrib\vorbis\win32\vorbis_static_d.lib .\contrib\vorbis\win32\vorbisfile_static_d.lib" + AdditionalDependencies=".\contrib\id3tag\win32\libid3tagd.lib .\contrib\id3tag\win32\zlibd.lib .\contrib\ogg\win32\ogg_static_d.lib .\contrib\vorbis\win32\vorbis_static_d.lib .\contrib\vorbis\win32\vorbisfile_static_d.lib .\contrib\mp4v2\win32\libmp4v260d.lib" OutputFile="$(OutDir)/gmi.dll" LinkIncremental="2" GenerateDebugInformation="true" @@ -192,6 +193,10 @@ > </File> <File + RelativePath=".\gmi_mp4v2.c" + > + </File> + <File RelativePath=".\gmi_vorbis.c" > </File> Added: trunk/pmplib/lib/gmi/gmi_mp4v2.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_mp4v2.c (rev 0) +++ trunk/pmplib/lib/gmi/gmi_mp4v2.c 2007-02-24 11:19:50 UTC (rev 394) @@ -0,0 +1,142 @@ +/* + * Tag and audio information retrieval by libmp4v2 + * + * Copyright (c) 2005-2007 Naoaki Okazaki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit + * http://www.gnu.org/copyleft/gpl.html . + * + */ + +/* $Id:$ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif/*HAVE_CONFIG_H*/ + +#if defined(WIN32) +/* In Win32 version of libmp4v2, <mp4.h> header also includes <winsock2.h> + * header, which cannot coexist with <winsock.h>. Defining _WINSOCKAPI_ will + * prevent from <winsock.h> being referred to by <windows.h>, which is also + * referred to by <os.h> header (Win32 only). Therefore, this definition + * must be placed before including <os.h>. + */ +#define _WINSOCKAPI_ +/* Add Winsock2 library */ +#pragma comment(lib, "ws2_32.lib") +#endif/*defined(WIN32)*/ + +#include <os.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <pmplib/ucs2char.h> +#include <gmi.h> + +#include <mp4.h> + +#ifdef WIN32 +/* Taken from mpeg4ip-1.5.0.1/lib/gnu/need_for_win32.c */ +#include <sys/timeb.h> + +int gettimeofday (struct timeval *t, void *foo) +{ + struct _timeb temp; + _ftime(&temp); + t->tv_sec = temp.time; + t->tv_usec = temp.millitm * 1000; + return (0); +} +#endif/*WIN32*/ + + + +int gmi_mp4v2(media_info_t* info, const ucs2char_t *filename, const char *charset) +{ + int ret = 0; + uint32_t i, num_tracks = 0; + uint16_t numvalue, numvalue2; + char *value = ucs2dupmbs(filename); + MP4FileHandle mp4file = MP4_INVALID_FILE_HANDLE; + + mp4file = MP4Read(value, 0); + ucs2free(value); + if (mp4file == MP4_INVALID_FILE_HANDLE) { + ret = -1; + goto error_exit; + } + + num_tracks = MP4GetNumberOfTracks(mp4file, NULL, 0); + for (i = 0;i < num_tracks;++i) { + uint32_t tid = MP4FindTrackId(mp4file, (u_int16_t)i, NULL, 0); + const char *type = MP4GetTrackType(mp4file, tid); + + if (type && strcmp(type, MP4_AUDIO_TRACK_TYPE) == 0) { + MP4Duration duration = MP4GetTrackDuration(mp4file, tid); + info->num_samples = (uint64_t)duration; + info->duration = MP4ConvertFromTrackDuration(mp4file, tid, duration, MP4_MSECS_TIME_SCALE); + info->sample_rate = MP4GetTrackTimeScale(mp4file, tid); + info->bitrate = MP4GetTrackBitRate(mp4file, tid); + } + } + + if (MP4GetMetadataName(mp4file, &value) && value != NULL) { + info->title = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataArtist(mp4file, &value) && value != NULL) { + info->artist = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL) { + info->album = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataAlbum(mp4file, &value) && value != NULL) { + info->album = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataWriter(mp4file, &value) && value != NULL) { + info->composer = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataGenre(mp4file, &value) && value != NULL) { + info->genre = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataYear(mp4file, &value) && value != NULL) { + info->date = utf8dupucs2(value); + free(value); + } + if (MP4GetMetadataTrack(mp4file, &numvalue, &numvalue2)) { + info->track_number = numvalue; + info->total_tracks = numvalue2; + } + if (MP4GetMetadataDisk(mp4file, &numvalue, &numvalue2)) { + info->disc_number = numvalue; + info->total_discs = numvalue2; + } + + info->codec = PMPCODEC_MPEG4AUDIO; + +error_exit: + if (mp4file != MP4_INVALID_FILE_HANDLE) { + MP4Close(mp4file); + } + return ret; +} Modified: trunk/pmplib/lib/gmi/gmi_vorbis.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 09:38:48 UTC (rev 393) +++ trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-24 11:19:50 UTC (rev 394) @@ -58,10 +58,6 @@ vorbis_comment* vc = NULL; /* Set the pathname and filename. */ - /* - info->filename = ucs2dup(filename); - info->filesize = filepath_size(filename); - */ /* Open the target file. */ fp = ucs2fopen(filename, "rb"); Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:38:48 UTC (rev 393) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-24 11:19:50 UTC (rev 394) @@ -46,8 +46,8 @@ "apple_ipod", "Apple", "iPod", "UM", "---", "---", "iPod_Control\\iTunes\\iTunesDB", - ".mp3\0", - {PMPCODEC_MPEGLAYER3, 0, 0, 0, 0, 0, 0, 0}, + ".mp3\0.m4a\0", + {PMPCODEC_MPEGLAYER3, PMPCODEC_MPEG4AUDIO, 0, 0, 0, 0, 0, 0}, "iPod_Control", "iPod_Control\\Music", "Playlists", }, { @@ -164,7 +164,7 @@ mhit_data->type2 = 0x01; break; } - mhit_data->compilation = 0; + mhit_data->compilation = rec->is_compilation ? 1 : 0; mhit_data->rating = 0; mhit_data->last_modified = rec->ts_update; mhit_data->filesize = rec->filesize; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 09:38:47
|
Revision: 393 http://svn.sourceforge.net/pmplib/?rev=393&view=rev Author: nyaochi Date: 2007-02-23 01:38:48 -0800 (Fri, 23 Feb 2007) Log Message: ----------- Sort tracks in numerical order of disc numbers. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/ipod.c Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:37:33 UTC (rev 392) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:38:48 UTC (rev 393) @@ -298,9 +298,12 @@ ret = comp_string(x->album, y->album); if (ret == 0) { - ret = COMP(x->track_number, y->track_number); + ret = COMP(x->disc_number, y->disc_number); if (ret == 0) { - return comp_string(x->title, y->title); + ret = COMP(x->track_number, y->track_number); + if (ret == 0) { + return comp_string(x->title, y->title); + } } } return ret; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 09:37:32
|
Revision: 392 http://svn.sourceforge.net/pmplib/?rev=392&view=rev Author: nyaochi Date: 2007-02-23 01:37:33 -0800 (Fri, 23 Feb 2007) Log Message: ----------- Added disc_number and total_discs fields to pmp_music_record_t although libgmi does not set them at this moment. Modified Paths: -------------- trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/pmp_ipod/ipod.c Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-23 09:23:01 UTC (rev 391) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-23 09:37:33 UTC (rev 392) @@ -398,6 +398,18 @@ uint32_t total_tracks; /** + * Disc number. + * e.g., 1 + */ + uint32_t disc_number; + + /** + * Total number of discs in this series. + * e.g., 2 + */ + uint32_t total_discs; + + /** * Sample rate in [Hz]. * e.g., 44100 */ Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:23:01 UTC (rev 391) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:37:33 UTC (rev 392) @@ -174,6 +174,8 @@ mhit_data->year = 2000; mhit_data->bitrate = rec->bitrate / 1000; mhit_data->samplerate = rec->sample_rate; + mhit_data->disc_number = rec->disc_number; + mhit_data->total_discs = rec->total_discs; mhit_data->date_added = rec->ts_import; mhit_data->dbid = 0; mhit_data->unk9 = 0xFFFF; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 09:23:00
|
Revision: 391 http://svn.sourceforge.net/pmplib/?rev=391&view=rev Author: nyaochi Date: 2007-02-23 01:23:01 -0800 (Fri, 23 Feb 2007) Log Message: ----------- Added total_tracks field to pmp_music_record_t. Modified Paths: -------------- trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/gmi/gmi_mp3.c trunk/pmplib/lib/gmi/gmi_vorbis.c trunk/pmplib/lib/pmp_ipod/ipod.c Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-23 09:12:10 UTC (rev 390) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-23 09:23:01 UTC (rev 391) @@ -392,6 +392,12 @@ uint32_t track_number; /** + * Total number of tracks in this disc. + * e.g., 12 + */ + uint32_t total_tracks; + + /** * Sample rate in [Hz]. * e.g., 44100 */ Modified: trunk/pmplib/lib/gmi/gmi_mp3.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 09:12:10 UTC (rev 390) +++ trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 09:23:01 UTC (rev 391) @@ -375,9 +375,17 @@ /* Obtain track number first. */ ucs2 = get_frame_value(id3tag, "TRCK", charset); if (ucs2 && *ucs2) { - info->track_number = ucs2toi(ucs2); + ucs2char_t* p = ucs2chr(ucs2, '/'); + if (p) { + info->track_number = ucs2toi(ucs2); + info->total_tracks = ucs2toi(p+1); + } else { + info->track_number = ucs2toi(ucs2); + info->total_tracks = 0; + } } else { info->track_number = 0; + info->total_tracks = 0; } ucs2free(ucs2); Modified: trunk/pmplib/lib/gmi/gmi_vorbis.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 09:12:10 UTC (rev 390) +++ trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 09:23:01 UTC (rev 391) @@ -114,7 +114,17 @@ } else if (strncasecmp(fieldvalue, "GENRE=", 6) == 0) { info->genre = utf8dupucs2(fieldvalue+6); } else if (strncasecmp(fieldvalue, "TRACKNUMBER=", 12) == 0) { - info->track_number = atoi(fieldvalue+12); + char* value = fieldvalue+12; + char* p = strchr(value, '/'); + if (p) { + info->track_number = atoi(value); + info->total_tracks = atoi(p+1); + } else { + info->track_number = atoi(value); + info->total_tracks = 0; + } + } else if (strncasecmp(fieldvalue, "TOTALTRACKS=", 12) == 0) { + info->total_tracks = atoi(fieldvalue+12); } else if (strncasecmp(fieldvalue, "DATE=", 5) == 0) { info->date = utf8dupucs2(fieldvalue+5); } Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:12:10 UTC (rev 390) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:23:01 UTC (rev 391) @@ -170,7 +170,7 @@ mhit_data->filesize = rec->filesize; mhit_data->duration = rec->duration; mhit_data->track_number = rec->track_number; - mhit_data->total_tracks = 100; + mhit_data->total_tracks = rec->total_tracks; mhit_data->year = 2000; mhit_data->bitrate = rec->bitrate / 1000; mhit_data->samplerate = rec->sample_rate; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 09:12:09
|
Revision: 390 http://svn.sourceforge.net/pmplib/?rev=390&view=rev Author: nyaochi Date: 2007-02-23 01:12:10 -0800 (Fri, 23 Feb 2007) Log Message: ----------- - duration in pmp_music_record_t is now represented in miliseconds. - added num_samples in pmp_music_record_t Modified Paths: -------------- trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/gmi/gmi_mp3.c trunk/pmplib/lib/gmi/gmi_vorbis.c trunk/pmplib/lib/gmi/gmi_wav.c trunk/pmplib/lib/gmi/gmi_wma.c trunk/pmplib/lib/pmp_ipod/ipod.c trunk/pmplib/lib/pmp_iriverplus2/ip2db.c trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c trunk/pmplib/lib/pmp_portalplayer1/model_iriver_h10.c trunk/pmplib/lib/pmp_portalplayer1/model_medion_mdjuke220.c trunk/pmplib/lib/pmp_portalplayer1/model_msi_megaplayer.c trunk/pmplib/lib/pmp_portalplayer1/model_samsung.c trunk/pmplib/lib/pmp_portalplayer1/model_sirius_s50.c Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-23 09:12:10 UTC (rev 390) @@ -410,6 +410,12 @@ uint32_t duration; /** + * Number of samples. + * e.g., 260*44100. + */ + uint64_t num_samples; + + /** * File size in bytes. * e.g., 4160000 */ Modified: trunk/pmplib/lib/gmi/gmi_mp3.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 09:12:10 UTC (rev 390) @@ -480,7 +480,8 @@ int channels = mp3header.channel_mode == 3 ? 1 : 2; info->sample_rate = mp3header.sample_rate; info->bitrate = mp3header.bitrate; - info->duration = mp3header.duration; + info->duration = (uint32_t)(mp3header.duration * 1000.0); + info->num_samples = (uint64_t)mp3header.samples_per_frame * mp3header.number_of_frames; switch (mp3header.version) { case 0: info->codec_version = 100; Modified: trunk/pmplib/lib/gmi/gmi_vorbis.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 09:12:10 UTC (rev 390) @@ -51,6 +51,7 @@ int i, ret = 0; long lval = 0; double dval = 0; + ogg_int64_t llval = 0; FILE *fp = NULL; OggVorbis_File vf; vorbis_info *vi = NULL; @@ -90,14 +91,17 @@ } info->bitrate = (uint32_t)lval; - /* Obtain duration. */ - dval = ov_time_total(&vf, -1); - if (dval < 0) { + /* Obtain the number of samples. */ + llval = ov_pcm_total(&vf, -1); + if (llval < 0) { ov_clear(&vf); goto error_exit; } - info->duration = (uint32_t)dval; + info->num_samples = (uint64_t)llval; + /* Compute duration. */ + info->duration = (uint32_t)((double)info->num_samples * 1000.0 / info->sample_rate); + vc = ov_comment(&vf, -1); for (i = 0;i < vc->comments;++i) { const char *fieldvalue = vc->user_comments[i]; Modified: trunk/pmplib/lib/gmi/gmi_wav.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_wav.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/gmi/gmi_wav.c 2007-02-23 09:12:10 UTC (rev 390) @@ -226,7 +226,8 @@ info->bitrate = channels * sample_bits * info->sample_rate; break; case 0x61746164: - info->duration = (uint32_t)((double)ch.size * 8.0 / info->bitrate); + info->num_samples = (uint64_t)((double)ch.size * 8.0 / channels / sample_bits); + info->duration = (uint32_t)((double)ch.size * 8.0 * 1000.0 / info->bitrate); break; case 0x5453494C: ret |= read_uint32le(&tmp32, fp); Modified: trunk/pmplib/lib/gmi/gmi_wma.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_wma.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/gmi/gmi_wma.c 2007-02-23 09:12:10 UTC (rev 390) @@ -251,7 +251,7 @@ duration += duration_high * 429.4967296; duration -= preroll_low / 1000.0; duration -= (preroll_high / 4294967.296); - info->duration = (uint32_t)duration; + info->duration = (uint32_t)(duration * 1000.0); } else if (guid_equals(guid, g_guid_stream_properties)) { @@ -516,6 +516,7 @@ info->codec = PMPCODEC_WMA; info->codec_version = 1; /* Set 1 for now. */ info->is_vbr = 1; /* Set 1 for now. */ + info->num_samples = (uint64_t)((double)info->duration * info->sample_rate / 1000); } return ret; } Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 09:12:10 UTC (rev 390) @@ -168,7 +168,7 @@ mhit_data->rating = 0; mhit_data->last_modified = rec->ts_update; mhit_data->filesize = rec->filesize; - mhit_data->duration = rec->duration * 1000; + mhit_data->duration = rec->duration; mhit_data->track_number = rec->track_number; mhit_data->total_tracks = 100; mhit_data->year = 2000; @@ -193,6 +193,7 @@ mhit_data->is_played = 2; mhit_data->unk27 = 1; mhit_data->media_type = 1; + mhit_data->num_samples = rec->num_samples; /* Construct an "mhod" chunk for title. */ if (rec->title && *rec->title) { Modified: trunk/pmplib/lib/pmp_iriverplus2/ip2db.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus2/ip2db.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_iriverplus2/ip2db.c 2007-02-23 09:12:10 UTC (rev 390) @@ -212,7 +212,7 @@ dst->year = ucs2toi(src->date); } dst->filesize = src->filesize; - dst->duration = src->duration; + dst->duration = src->duration / 1000; dst->sample_rate = src->sample_rate; dst->bitrate = src->bitrate; dst->timestamp = src->ts_update; @@ -297,7 +297,7 @@ dst->track_number = src.track_number; dst->sample_rate = src.sample_rate; dst->bitrate = src.bitrate; - dst->duration = src.duration; + dst->duration = src.duration * 1000; dst->filesize = src.filesize; dst->ts_update = src.timestamp; dst->rating = src.rating; Modified: trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c 2007-02-23 09:12:10 UTC (rev 390) @@ -541,7 +541,7 @@ } 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->duration = src[IP3DBF_MUSIC_DURATION].value.dword * 1000; dst->ts_update = src[IP3DBF_MUSIC_CLUSA].value.dword; dst->rating = src[IP3DBF_MUSIC_RATING].value.word; } @@ -585,7 +585,7 @@ 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_dword(&dst[IP3DBF_MUSIC_DURATION], src->duration / 1000); ip3db_variant_set_word(&dst[IP3DBF_MUSIC_RATING], (uint16_t)src->rating); switch (src->codec) { case PMPCODEC_MPEGLAYER3: Modified: trunk/pmplib/lib/pmp_portalplayer1/model_iriver_h10.c =================================================================== --- trunk/pmplib/lib/pmp_portalplayer1/model_iriver_h10.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_portalplayer1/model_iriver_h10.c 2007-02-23 09:12:10 UTC (rev 390) @@ -119,7 +119,7 @@ dst->fields[PP1DB_DATFIELD_YEAR].value.dword = ucs2toi(src->date); } dst->fields[PP1DB_DATFIELD_FILESIZE].value.dword = src->filesize; - dst->fields[PP1DB_DATFIELD_DURATION].value.dword = src->duration; + dst->fields[PP1DB_DATFIELD_DURATION].value.dword = src->duration / 1000; dst->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword = src->sample_rate; dst->fields[PP1DB_DATFIELD_BITRATE].value.dword = src->bitrate; dst->fields[PP1DB_DATFIELD_UNKNOWN4].value.dword = 0; @@ -168,7 +168,7 @@ dst->track_number = src->fields[PP1DB_DATFIELD_TRACKNUMBER].value.dword; dst->sample_rate = src->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword; dst->bitrate = src->fields[PP1DB_DATFIELD_BITRATE].value.dword; - dst->duration = src->fields[PP1DB_DATFIELD_DURATION].value.dword; + dst->duration = src->fields[PP1DB_DATFIELD_DURATION].value.dword * 1000; dst->filesize = src->fields[PP1DB_DATFIELD_FILESIZE].value.dword; dst->ts_update = src->fields[PP1DB_DATFIELD_UNKNOWN6].value.dword; dst->rating = src->fields[PP1DB_DATFIELD_RATING].value.dword; Modified: trunk/pmplib/lib/pmp_portalplayer1/model_medion_mdjuke220.c =================================================================== --- trunk/pmplib/lib/pmp_portalplayer1/model_medion_mdjuke220.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_portalplayer1/model_medion_mdjuke220.c 2007-02-23 09:12:10 UTC (rev 390) @@ -96,7 +96,7 @@ dst->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword = src->sample_rate; memset(duration, 0, sizeof(duration)); - itoucs2(src->duration, duration, 10); + itoucs2(src->duration / 1000, duration, 10); dst->fields[PP1DB_DATFIELD_DURATION].value.str = ucs2dup(duration); dst->fields[PP1DB_DATFIELD_ARTIST].value.str = ucs2dup(src->artist ? src->artist : ucs2cs_unknown); @@ -134,7 +134,7 @@ dst->bitrate = src->fields[PP1DB_DATFIELD_BITRATE].value.dword; dst->sample_rate = src->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword; - dst->duration = ucs2toi(src->fields[PP1DB_DATFIELD_DURATION].value.str); + dst->duration = ucs2toi(src->fields[PP1DB_DATFIELD_DURATION].value.str) * 1000; dst->artist = ucs2dup(src->fields[PP1DB_DATFIELD_ARTIST].value.str); dst->album = ucs2dup(src->fields[PP1DB_DATFIELD_ALBUM].value.str); Modified: trunk/pmplib/lib/pmp_portalplayer1/model_msi_megaplayer.c =================================================================== --- trunk/pmplib/lib/pmp_portalplayer1/model_msi_megaplayer.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_portalplayer1/model_msi_megaplayer.c 2007-02-23 09:12:10 UTC (rev 390) @@ -93,7 +93,7 @@ dst->fields[PP1DB_DATFIELD_FORMAT].value.dword = 0; dst->fields[PP1DB_DATFIELD_BITRATE].value.dword = src->bitrate; dst->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword = src->sample_rate; - itoucs2(src->duration, tmp, 10); + itoucs2(src->duration / 1000, tmp, 10); dst->fields[PP1DB_DATFIELD_DURATION].value.str = ucs2dup(tmp); dst->fields[PP1DB_DATFIELD_ARTIST].value.str = ucs2dup(src->artist ? src->artist : ucs2cs_unknown); dst->fields[PP1DB_DATFIELD_ALBUM].value.str = ucs2dup(src->album ? src->album : ucs2cs_unknown); @@ -129,7 +129,7 @@ dst->bitrate = src->fields[PP1DB_DATFIELD_BITRATE].value.dword; dst->sample_rate = src->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword; - dst->duration = ucs2toi(src->fields[PP1DB_DATFIELD_DURATION].value.str); + dst->duration = ucs2toi(src->fields[PP1DB_DATFIELD_DURATION].value.str) * 1000; dst->artist = ucs2dup(src->fields[PP1DB_DATFIELD_ARTIST].value.str); dst->album = ucs2dup(src->fields[PP1DB_DATFIELD_ALBUM].value.str); dst->genre = ucs2dup(src->fields[PP1DB_DATFIELD_GENRE].value.str); Modified: trunk/pmplib/lib/pmp_portalplayer1/model_samsung.c =================================================================== --- trunk/pmplib/lib/pmp_portalplayer1/model_samsung.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_portalplayer1/model_samsung.c 2007-02-23 09:12:10 UTC (rev 390) @@ -100,7 +100,7 @@ dst->fields[PP1DB_DATFIELD_FORMAT].value.dword = 0; dst->fields[PP1DB_DATFIELD_BITRATE].value.dword = src->bitrate; dst->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword = src->sample_rate; - dst->fields[PP1DB_DATFIELD_DURATION].value.dword = src->duration; + dst->fields[PP1DB_DATFIELD_DURATION].value.dword = src->duration / 1000; dst->fields[PP1DB_DATFIELD_ARTIST].value.str = ucs2dup(src->artist ? src->artist : ucs2cs_unknown); dst->fields[PP1DB_DATFIELD_ALBUM].value.str = ucs2dup(src->album ? src->album : ucs2cs_unknown); dst->fields[PP1DB_DATFIELD_GENRE].value.str = ucs2dup(src->genre ? src->genre : ucs2cs_unknown); @@ -139,7 +139,7 @@ dst->bitrate = src->fields[PP1DB_DATFIELD_BITRATE].value.dword; dst->sample_rate = src->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword; - dst->duration = src->fields[PP1DB_DATFIELD_DURATION].value.dword; + dst->duration = src->fields[PP1DB_DATFIELD_DURATION].value.dword * 1000; dst->artist = ucs2dup(src->fields[PP1DB_DATFIELD_ARTIST].value.str); dst->album = ucs2dup(src->fields[PP1DB_DATFIELD_ALBUM].value.str); Modified: trunk/pmplib/lib/pmp_portalplayer1/model_sirius_s50.c =================================================================== --- trunk/pmplib/lib/pmp_portalplayer1/model_sirius_s50.c 2007-02-23 08:43:34 UTC (rev 389) +++ trunk/pmplib/lib/pmp_portalplayer1/model_sirius_s50.c 2007-02-23 09:12:10 UTC (rev 390) @@ -113,7 +113,7 @@ dst->fields[PP1DB_DATFIELD_FORMAT].value.dword = 0; dst->fields[PP1DB_DATFIELD_BITRATE].value.dword = src->bitrate; dst->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword = src->sample_rate; - dst->fields[PP1DB_DATFIELD_DURATION].value.dword = src->duration; + dst->fields[PP1DB_DATFIELD_DURATION].value.dword = src->duration / 1000; dst->fields[PP1DB_DATFIELD_ARTIST].value.str = ucs2dup(src->artist ? src->artist : ucs2cs_unknown); dst->fields[PP1DB_DATFIELD_ALBUM].value.str = ucs2dup(src->album ? src->album : ucs2cs_unknown); dst->fields[PP1DB_DATFIELD_GENRE].value.str = ucs2dup(src->genre ? src->genre : ucs2cs_unknown); @@ -157,7 +157,7 @@ dst->bitrate = src->fields[PP1DB_DATFIELD_BITRATE].value.dword; dst->sample_rate = src->fields[PP1DB_DATFIELD_SAMPLERATE].value.dword; - dst->duration = src->fields[PP1DB_DATFIELD_DURATION].value.dword; + dst->duration = src->fields[PP1DB_DATFIELD_DURATION].value.dword * 1000; dst->artist = ucs2dup(src->fields[PP1DB_DATFIELD_ARTIST].value.str); dst->album = ucs2dup(src->fields[PP1DB_DATFIELD_ALBUM].value.str); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 08:43:33
|
Revision: 389 http://svn.sourceforge.net/pmplib/?rev=389&view=rev Author: nyaochi Date: 2007-02-23 00:43:34 -0800 (Fri, 23 Feb 2007) Log Message: ----------- Added is_vbr flag to pmp_music_record_t. Modified Paths: -------------- trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/gmi/gmi_mp3.c trunk/pmplib/lib/gmi/gmi_vorbis.c trunk/pmplib/lib/gmi/gmi_wav.c trunk/pmplib/lib/gmi/gmi_wma.c trunk/pmplib/lib/pmp_ipod/ipod.c Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-23 08:28:19 UTC (rev 388) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-23 08:43:34 UTC (rev 389) @@ -380,6 +380,12 @@ uint32_t codec_version; /** + * VBR flag. + * e.g., 1 for MP3 VBR files. + */ + uint8_t is_vbr; + + /** * Track number. * e.g., 1 */ Modified: trunk/pmplib/lib/gmi/gmi_mp3.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 08:28:19 UTC (rev 388) +++ trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 08:43:34 UTC (rev 389) @@ -54,6 +54,8 @@ int frame_size; /**< size of the frame in bytes */ int samples_per_frame; /**< number of audio samples in the frame */ + int is_vbr; /**< true if VBR. */ + /* From Xing VBR header for VBR files, From file size for CBR files. */ int number_of_frames; /**< number of frames */ int data_size; /**< data size. */ @@ -248,9 +250,11 @@ double bitrate = header->data_size * 8.0 / duration; header->duration = (int)duration; header->bitrate = (int)bitrate; + header->is_vbr = 1; } else { double duration = (double)header->samples_per_frame * header->number_of_frames / header->sample_rate; header->duration = (int)duration; + header->is_vbr = 0; } /* Exit with success. */ @@ -488,6 +492,7 @@ info->codec_version = 205; break; } + info->is_vbr = mp3header.is_vbr; } id3_file_close(id3file); /* This will call fclose(fp); */ Modified: trunk/pmplib/lib/gmi/gmi_vorbis.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 08:28:19 UTC (rev 388) +++ trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 08:43:34 UTC (rev 389) @@ -118,7 +118,8 @@ info->codec = PMPCODEC_VORBIS; info->codec_version = 1; - + info->is_vbr = 1; /* Most Ogg Vorbis files are encoded in VBR. */ + // Clear the decoders buffers, also closes fp. ov_clear(&vf); Modified: trunk/pmplib/lib/gmi/gmi_wav.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_wav.c 2007-02-23 08:28:19 UTC (rev 388) +++ trunk/pmplib/lib/gmi/gmi_wav.c 2007-02-23 08:43:34 UTC (rev 389) @@ -261,6 +261,7 @@ if (ret == 0) { info->codec = PMPCODEC_WAV; info->codec_version = 1; + info->is_vbr = 0; } return ret; } Modified: trunk/pmplib/lib/gmi/gmi_wma.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_wma.c 2007-02-23 08:28:19 UTC (rev 388) +++ trunk/pmplib/lib/gmi/gmi_wma.c 2007-02-23 08:43:34 UTC (rev 389) @@ -515,6 +515,7 @@ if (ret == 0) { info->codec = PMPCODEC_WMA; info->codec_version = 1; /* Set 1 for now. */ + info->is_vbr = 1; /* Set 1 for now. */ } return ret; } Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 08:28:19 UTC (rev 388) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 08:43:34 UTC (rev 389) @@ -156,10 +156,14 @@ switch (rec->codec) { case PMPCODEC_MPEGLAYER3: mhit_data->filetype = 0x4D503320; + mhit_data->type1 = rec->is_vbr ? 0x01 : 0x00; + mhit_data->type2 = rec->is_vbr ? 0x01 : 0x00; break; + default: + mhit_data->type1 = 0x01; + mhit_data->type2 = 0x01; + break; } - mhit_data->type1 = 0x01; - mhit_data->type2 = 0x01; mhit_data->compilation = 0; mhit_data->rating = 0; mhit_data->last_modified = rec->ts_update; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 08:28:18
|
Revision: 388 http://svn.sourceforge.net/pmplib/?rev=388&view=rev Author: nyaochi Date: 2007-02-23 00:28:19 -0800 (Fri, 23 Feb 2007) Log Message: ----------- Added the version number of codecs to pmp_music_record_t. Modified Paths: -------------- trunk/pmplib/include/pmplib/pmp.h trunk/pmplib/lib/gmi/gmi_mp3.c trunk/pmplib/lib/gmi/gmi_vorbis.c trunk/pmplib/lib/gmi/gmi_wav.c trunk/pmplib/lib/gmi/gmi_wma.c trunk/pmplib/lib/pmp_ipod/ipod.c Modified: trunk/pmplib/include/pmplib/pmp.h =================================================================== --- trunk/pmplib/include/pmplib/pmp.h 2007-02-23 07:46:45 UTC (rev 387) +++ trunk/pmplib/include/pmplib/pmp.h 2007-02-23 08:28:19 UTC (rev 388) @@ -128,11 +128,11 @@ /** Unknown codec. */ #define PMPCODEC_NONE PMPFOURCC(' ',' ',' ',' ') /** MPEG Audio Layer III. */ -#define PMPCODEC_MPEGLAYER3 PMPFOURCC('M','P','1','3') +#define PMPCODEC_MPEGLAYER3 PMPFOURCC('M','P','A','3') /** Windows Media Audio. */ #define PMPCODEC_WMA PMPFOURCC('W','M','A',' ') /** Ogg Vorbis. */ -#define PMPCODEC_VORBIS PMPFOURCC('O','V','1',' ') +#define PMPCODEC_VORBIS PMPFOURCC('O','g','g','V') /** Microsoft Riff WAVE. */ #define PMPCODEC_WAV PMPFOURCC('W','A','V','E') @@ -374,6 +374,12 @@ uint32_t codec; /** + * Codec version multiplied by 100. + * e.g., 100 for MPEG version 1. + */ + uint32_t codec_version; + + /** * Track number. * e.g., 1 */ Modified: trunk/pmplib/lib/gmi/gmi_mp3.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 07:46:45 UTC (rev 387) +++ trunk/pmplib/lib/gmi/gmi_mp3.c 2007-02-23 08:28:19 UTC (rev 388) @@ -477,6 +477,17 @@ info->sample_rate = mp3header.sample_rate; info->bitrate = mp3header.bitrate; info->duration = mp3header.duration; + switch (mp3header.version) { + case 0: + info->codec_version = 100; + break; + case 1: + info->codec_version = 200; + break; + case 2: + info->codec_version = 205; + break; + } } id3_file_close(id3file); /* This will call fclose(fp); */ Modified: trunk/pmplib/lib/gmi/gmi_vorbis.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 07:46:45 UTC (rev 387) +++ trunk/pmplib/lib/gmi/gmi_vorbis.c 2007-02-23 08:28:19 UTC (rev 388) @@ -117,6 +117,7 @@ } info->codec = PMPCODEC_VORBIS; + info->codec_version = 1; // Clear the decoders buffers, also closes fp. ov_clear(&vf); Modified: trunk/pmplib/lib/gmi/gmi_wav.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_wav.c 2007-02-23 07:46:45 UTC (rev 387) +++ trunk/pmplib/lib/gmi/gmi_wav.c 2007-02-23 08:28:19 UTC (rev 388) @@ -260,6 +260,7 @@ ret = get_riff_audio_info(info, filename, charset); if (ret == 0) { info->codec = PMPCODEC_WAV; + info->codec_version = 1; } return ret; } Modified: trunk/pmplib/lib/gmi/gmi_wma.c =================================================================== --- trunk/pmplib/lib/gmi/gmi_wma.c 2007-02-23 07:46:45 UTC (rev 387) +++ trunk/pmplib/lib/gmi/gmi_wma.c 2007-02-23 08:28:19 UTC (rev 388) @@ -514,6 +514,7 @@ ret = get_asf_audio_info(info, filename); if (ret == 0) { info->codec = PMPCODEC_WMA; + info->codec_version = 1; /* Set 1 for now. */ } return ret; } Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 07:46:45 UTC (rev 387) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 08:28:19 UTC (rev 388) @@ -153,7 +153,11 @@ mhit_data->uid = uid; mhit_data->visible = 1; - mhit_data->filetype = 0x4D503320; + switch (rec->codec) { + case PMPCODEC_MPEGLAYER3: + mhit_data->filetype = 0x4D503320; + break; + } mhit_data->type1 = 0x01; mhit_data->type2 = 0x01; mhit_data->compilation = 0; @@ -169,6 +173,18 @@ mhit_data->date_added = rec->ts_import; mhit_data->dbid = 0; mhit_data->unk9 = 0xFFFF; + switch (rec->codec) { + case PMPCODEC_MPEGLAYER3: + switch (rec->codec_version) { + case 200: mhit_data->unk14_1 = 0x0016; break; + case 205: mhit_data->unk14_1 = 0x0020; break; + default: mhit_data->unk14_1 = 0x000C; break; + } + break; + case PMPCODEC_WAV: + mhit_data->unk14_1 = 0x0000; + break; + } mhit_data->unk14_1 = 12; mhit_data->is_played = 2; mhit_data->unk27 = 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 07:46:47
|
Revision: 387 http://svn.sourceforge.net/pmplib/?rev=387&view=rev Author: nyaochi Date: 2007-02-22 23:46:45 -0800 (Thu, 22 Feb 2007) Log Message: ----------- Added some comments. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/itunesdb.c trunk/pmplib/lib/pmp_ipod/itunesdb.h Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-23 06:58:35 UTC (rev 386) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-23 07:46:45 UTC (rev 387) @@ -1,5 +1,5 @@ /* - * iTunesDB + * iTunesDB reader/writer/dumper. * * Copyright (c) 2005-2007 Naoaki Okazaki * @@ -43,6 +43,7 @@ static void chunk_finish(itunesdb_chunk_t* chunk) { free(chunk->data); + free(chunk->padding); memset(chunk, 0, sizeof(*chunk)); } @@ -54,14 +55,14 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhbd", 4); chunk->size = 104; - chunk->overall_size = chunk->size; + chunk->overall_size = 0; /* to be filled */ } 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->num_children = 0; /* to be filled */ mhbd->identifier = 0x8CD2513B66EF2541; mhbd->unknown2 = 2; mhbd->unknown3 = 611; @@ -100,12 +101,12 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhsd", 4); chunk->size = 96; - chunk->overall_size = chunk->size; + chunk->overall_size = 0; /* to be filled */ } mhsd = (chunk_mhsd_t*)calloc(1, sizeof(chunk_mhsd_t)); if (mhsd && def) { - mhsd->type = 0; /* Initialize type 0 for now. */ + mhsd->type = 0; /* to be filled */ } chunk->data = mhsd; @@ -131,7 +132,7 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhlt", 4); chunk->size = 92; - chunk->overall_size = 0; /* stands for number of children for "mhlt" chunk. */ + chunk->overall_size = 0; /* to be filled */ } mhlt = (chunk_mhlt_t*)calloc(1, sizeof(chunk_mhlt_t)); @@ -158,12 +159,13 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhit", 4); chunk->size = 328; - chunk->overall_size = chunk->size; + chunk->overall_size = 0; /* to be filled */ } mhit = (chunk_mhit_t*)calloc(1, sizeof(chunk_mhit_t)); if (mhit && def) { - mhit->visible = 1; /* Visible by default. */ + mhit->visible = 1; /* visible by default */ + /* other fields to be filled later */ } chunk->data = mhit; @@ -262,7 +264,7 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhlp", 4); chunk->size = 92; - chunk->overall_size = 0; + chunk->overall_size = 0; /* to be filled */ } mhlp = (chunk_mhlp_t*)calloc(1, sizeof(chunk_mhlp_t)); @@ -289,7 +291,7 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhyp", 4); chunk->size = 108; - chunk->overall_size = chunk->size; + chunk->overall_size = 0; /* to be filled */ } mhyp = (chunk_mhyp_t*)calloc(1, sizeof(chunk_mhyp_t)); @@ -327,7 +329,7 @@ memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhip", 4); chunk->size = 76; - chunk->overall_size = chunk->size; + chunk->overall_size = 0; /* to be filled */ } mhip = (chunk_mhip_t*)calloc(1, sizeof(chunk_mhip_t)); @@ -562,6 +564,7 @@ if (decl) { decl->finish(chunk); } + chunk_finish(chunk); } static int mhod_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-23 06:58:35 UTC (rev 386) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-23 07:46:45 UTC (rev 387) @@ -1,5 +1,5 @@ /* - * iTunesDB + * iTunesDB reader/writer/dumper. * * Copyright (c) 2005-2007 Naoaki Okazaki * @@ -19,7 +19,7 @@ * */ -/* $Id$ */ +/* $Id:$ */ #ifndef __ITUNESDB_H__ #define __ITUNESDB_H__ @@ -244,12 +244,52 @@ const void* base; } sorted_index_t; -int itunesdb_init(itunesdb_chunk_t* chunk, const char *name, const char *subtype); +/** + * Initialize a chunk with identifier and subtype (for "mhod" chunk) + * @param chunk The pointer to itunesdb_chunk_t to be initialized. + * @param identifer Chunk identifier. + * @param subtype Chunk sub-type for "mhod" chunk. + * @retval int zero if succeeded, otherwise nonzero. + */ +int itunesdb_init(itunesdb_chunk_t* chunk, const char *identifer, const char *subtype); + +/** + * Create a new chunk and append it to the children of the parent chunk. + * @param chunk The chunk where a new child will be appended. + * @retval itunesdb_chunk_t* Pointer to the new chunk if succeeded, otherwise NULL. + */ itunesdb_chunk_t* itunesdb_new_child(itunesdb_chunk_t* chunk); + +/** + * Uninitialize a chunk. + * @param chunk The pointer to itunesdb_chunk_t to be freed. + */ void itunesdb_finish(itunesdb_chunk_t* chunk); +/** + * Set UCS-2 string to "mhod" chunk. + * @param chunk The pointer to "mhod" chunk. + * @param str The pointer to UCS-2 string. + * @retval int zero if succeeded, otherwise nonzero. + */ 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); + +/** + * Set sorted index to "mhod" chunk. + * @param chunk The pointer to "mhod" chunk. + * @param sort_order The sort order. + * @param si The sorted index. + * @param n The number of entries in the sorted index. + * @retval int zero if succeeded, otherwise nonzero. + */ +int itunesdb_set_mhod_index(itunesdb_chunk_t* chunk, uint32_t sort_order, sorted_index_t* si, uint32_t n); + +/** + * Set ordinal value to "mhod" chunk. + * @param chunk The pointer to "mhod" chunk. + * @param order The ordinal value. + * @retval int zero if succeeded, otherwise nonzero. + */ 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); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 06:58:34
|
Revision: 386 http://svn.sourceforge.net/pmplib/?rev=386&view=rev Author: nyaochi Date: 2007-02-22 22:58:35 -0800 (Thu, 22 Feb 2007) Log Message: ----------- Compute the size of padded data automatically. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/itunesdb.c trunk/pmplib/lib/pmp_ipod/itunesdb.h trunk/pmplib/lib/pmp_ipod/serialize.c Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-23 06:22:53 UTC (rev 385) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-23 06:58:35 UTC (rev 386) @@ -86,7 +86,6 @@ if (serialize_uint64le(sio, "unknown4", "%016llX", &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; } @@ -118,7 +117,6 @@ 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; } @@ -145,7 +143,7 @@ { chunk_mhlt_t* mhlt = (chunk_mhlt_t*)chunk->data; - if (serialize_uint8_array(sio, "unknown1", "%02X ", mhlt->unknown1, sizeof(mhlt->unknown1))) return 1; + if (serialize_uint8(sio, "unknown", "%02X", &mhlt->unknown)) return 1; return 0; } @@ -276,7 +274,7 @@ { chunk_mhlp_t* mhlp = (chunk_mhlp_t*)chunk->data; - if (serialize_uint8_array(sio, "unknown1", "%02X ", mhlp->unknown1, sizeof(mhlp->unknown1))) return 1; + if (serialize_uint8(sio, "unknown", "%02X", &mhlp->unknown)) return 1; return 0; } @@ -315,7 +313,6 @@ 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; } @@ -490,7 +487,7 @@ chunk_mhod_playlist_order_t* po = &mhod->data.po; if (serialize_uint32le(sio, "position", "%u", &po->position)) return 1; - if (serialize_uint8_array(sio, "padding", "%02X ", po->padding, sizeof(po->padding))) return 1; + if (serialize_uint8_array(sio, "unknown", "%02X ", po->unknown, sizeof(po->unknown))) return 1; return 0; } @@ -676,6 +673,13 @@ fprintf(sio->fp, "!unknown_chunk!\n"); } + /* Show padded data. */ + if (chunk->padding && chunk->padding_size) { + char msg[128]; + sprintf(msg, "padding (%d)", chunk->padding_size); + if (serialize_uint8_array(sio, msg, "%02X ", chunk->padding, chunk->padding_size)) return 1; + } + /* Show number of children */ serialize_indent(sio); fprintf(sio->fp, "#children: %d\n", chunk->num_children); @@ -696,8 +700,8 @@ int itunesdb_read(itunesdb_chunk_t* chunk, serializer_t* sio) { - uint32_t i; - size_t begin = serialize_tell(sio); + uint32_t i, next; + uint32_t begin = (uint32_t)serialize_tell(sio); const itunesdb_chunkdecl_t* decl = NULL; /* Read the chunk ID and header information */ @@ -714,17 +718,27 @@ } } + /* Determine the size of padded data for this chunk. */ if (strncmp(chunk->id, "mhod", 4) == 0) { - uint32_t next = begin + chunk->overall_size; - if (next < serialize_tell(sio)) { - fprintf(stderr, "WARNING: backward seeking.\n"); - } - serialize_seek(sio, next); + next = begin + chunk->overall_size; + chunk->padding_size = next - serialize_tell(sio); } else { - uint32_t next = begin + chunk->size; - if (next < serialize_tell(sio)) { - fprintf(stderr, "WARNING: backward seeking.\n"); + next = begin + chunk->size; + chunk->padding_size = next - serialize_tell(sio); + } + + /* Read the padded data. */ + if (0 < chunk->padding_size) { + chunk->padding = (uint8_t*)calloc(chunk->padding_size, sizeof(uint8_t)); + if (chunk->padding) { + if (serialize_uint8_array(sio, "padding", "%02X ", chunk->padding, chunk->padding_size)) return 1; } + } else if (chunk->padding_size < 0) { + /* For some reason, we read too much data for this chunk. */ + fprintf(stderr, "WARNING: backward seeking.\n"); + chunk->padding_size = 0; + chunk->padding = NULL; + /* Rewind to the correct position. */ serialize_seek(sio, next); } @@ -758,7 +772,7 @@ const itunesdb_chunkdecl_t* decl = NULL; /* Store the offset position of this chunk for the future use of rewind. */ - chunk->offset = serialize_tell(sio); + chunk->offset = (uint32_t)serialize_tell(sio); /* Write the chunk ID and header information. The overall_size may be incorrect at this moment. */ if (serialize_uint8_array(sio, "id", "%c ", chunk->id, sizeof(chunk->id))) return 1; @@ -772,7 +786,7 @@ } /* Pad 0x00 in the rest of file header. */ - for (i = serialize_tell(sio);i < chunk->offset + chunk->size;++i) { + for (i = (uint32_t)serialize_tell(sio);i < chunk->offset + chunk->size;++i) { serialize_uint8(sio, NULL, NULL, &zero); } @@ -787,10 +801,10 @@ chunk->overall_size = chunk->num_children; } else { /* chunk->overall_size represents the size in bytes of this chunk */ - chunk->overall_size = serialize_tell(sio) - chunk->offset; + chunk->overall_size = (uint32_t)serialize_tell(sio) - chunk->offset; } - offset = serialize_tell(sio); + offset = (uint32_t)serialize_tell(sio); serialize_seek(sio, chunk->offset + 2 * sizeof(uint32_t)); if (serialize_uint32le(sio, "overall_size", "%d", &chunk->overall_size)) return 1; serialize_seek(sio, offset); @@ -824,7 +838,7 @@ /* Store the string value. */ str->position = 1; - str->size = ucs2len(value) * sizeof(ucs2char_t); + str->size = (uint32_t)(ucs2len(value) * sizeof(ucs2char_t)); str->unknown = 1; str->value = ucs2ndup(value, 512); return 0; Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-23 06:22:53 UTC (rev 385) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-23 06:58:35 UTC (rev 386) @@ -34,16 +34,14 @@ 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. */ + uint8_t unknown; /* zero padded. */ } chunk_mhlt_t; typedef struct { @@ -124,7 +122,7 @@ } chunk_mhit_t; typedef struct { - uint8_t unknown1[16*5]; /* zero padded. */ + uint8_t unknown; /* zero padded. */ } chunk_mhlp_t; typedef struct { @@ -140,7 +138,6 @@ uint16_t unk4; uint16_t flag_podcast; uint32_t sort_order; - uint8_t padding[0x3C]; } chunk_mhyp_t; typedef struct { @@ -194,7 +191,7 @@ typedef struct { uint32_t position; - uint8_t padding[16]; + uint8_t unknown[16]; } chunk_mhod_playlist_order_t; typedef struct { @@ -217,15 +214,20 @@ uint32_t overall_size; void* data; + uint32_t num_children; /* This field does not exist in iTunesDB. */ struct tag_itunesdb_chunk* childlen; + + int32_t padding_size; + uint8_t* padding; + uint32_t offset; /* This field does not exist in iTunesDB. */ }; typedef struct { uint32_t type; const char* name; - size_t overall_size; + uint32_t overall_size; void (*finish)(itunesdb_chunk_t* chunk); int (*serialize)(itunesdb_chunk_t* chunk, const char *name, serializer_t* sio); } itunesdb_mhoddecl_t; Modified: trunk/pmplib/lib/pmp_ipod/serialize.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-23 06:22:53 UTC (rev 385) +++ trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-23 06:58:35 UTC (rev 386) @@ -267,7 +267,6 @@ return 0; } - int serialize_seek(serializer_t* sio, size_t offset) { sio->offset = offset; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-23 06:22:53
|
Revision: 385 http://svn.sourceforge.net/pmplib/?rev=385&view=rev Author: nyaochi Date: 2007-02-22 22:22:53 -0800 (Thu, 22 Feb 2007) Log Message: ----------- Memorial commit: implemented the database generation for iPod. It's still in the early stage (lack of MP4 support, MP3 gapless playback, update mode, playlists, etc), but iTunesDB was recognized by iPod and iTunes. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/ipod.c trunk/pmplib/lib/pmp_ipod/ipod.h trunk/pmplib/lib/pmp_ipod/itunesdb.c trunk/pmplib/lib/pmp_ipod/itunesdb.h trunk/pmplib/lib/pmp_ipod/pmp_ipod.c trunk/pmplib/lib/pmp_ipod/serialize.c Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-23 06:22:53 UTC (rev 385) @@ -121,6 +121,22 @@ } } +result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb) +{ + FILE *fp = NULL; + serializer_t sio; + + serialize_init_write(&sio, 0x10000); + itunesdb_write(ipod->itunesdb, &sio); + + fp = ucs2fopen(itunesdb, "wb"); + fwrite(sio.base, 1, sio.offset, fp); + fclose(fp); + + serialize_finish(&sio); + return 0; +} + result_t ipod_dump(ipod_t* ipod, FILE *fpo) { serializer_t sio; @@ -185,6 +201,15 @@ } } + /* Construct an "mhod" chunk for album. */ + if (rec->genre && *rec->genre) { + mhod = itunesdb_new_child(mhit); + if (mhod) { + itunesdb_init(mhod, "mhod", "genre"); + itunesdb_set_mhod_string(mhod, rec->genre); + } + } + /* Construct an "mhod" chunk for filetype. */ mhod = itunesdb_new_child(mhit); if (mhod) { @@ -205,7 +230,7 @@ if (mhod) { ucs2char_t pathname[MAX_PATH], *p = NULL; itunesdb_init(mhod, "mhod", "location"); - ucs2cpy(pathname, rec->filename); + ucs2cpy(pathname, rec->filename + 2); for (p = pathname;*p;++p) { if (*p == PATHCHAR) *p = ':'; } @@ -217,6 +242,17 @@ return 0; } +static int comp_string(const ucs2char_t* x, const ucs2char_t*y) +{ + int ret = 0; + if (!x || !*x) { + ret = ((!y || !*y) ? 0 : 1); + } else { + ret = ((!y || !*y) ? -1 : ucs2icmp(x, y)); + } + return ret; +} + static int comp_title(const void *_x, const void *_y) { const sorted_index_t *xi = (const sorted_index_t*)_x; @@ -225,7 +261,7 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - return ucs2cmp(x->title, y->title); + return comp_string(x->title, y->title); } static int comp_album(const void *_x, const void *_y) @@ -237,11 +273,11 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->album, y->album); + ret = comp_string(x->album, y->album); if (ret == 0) { ret = COMP(x->track_number, y->track_number); if (ret == 0) { - return ucs2cmp(x->title, y->title); + return comp_string(x->title, y->title); } } return ret; @@ -256,7 +292,7 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->artist, y->artist); + ret = comp_string(x->artist, y->artist); if (ret == 0) { return comp_album(_x, _y); } @@ -272,7 +308,7 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->genre, y->genre); + ret = comp_string(x->genre, y->genre); if (ret == 0) { return comp_artist(_x, _y); } @@ -288,9 +324,9 @@ const pmp_music_record_t* x = &base[xi->index]; const pmp_music_record_t* y = &base[yi->index]; - ret = ucs2cmp(x->composer, y->composer); + ret = comp_string(x->composer, y->composer); if (ret == 0) { - return ucs2cmp(x->title, y->title); + return comp_string(x->title, y->title); } return ret; } @@ -396,15 +432,19 @@ result_t ipod_set(ipod_t* ipod, const pmp_music_record_t* records, int num_records, const pmp_playlist_t* playlists, int num_playlists) { int i; - itunesdb_chunk_t mhbd, *mhsd = NULL; + itunesdb_chunk_t *mhbd = NULL, *mhsd = NULL; itunesdb_chunk_t *mhlt = NULL, *mhit = NULL; itunesdb_chunk_t *mhlp = NULL, *mhyp = NULL; + chunk_mhbd_t* mhbd_data = NULL; /* Construct "mhbd" chunk. */ - itunesdb_init(&mhbd, "mhbd", NULL); + mhbd = (itunesdb_chunk_t*)calloc(1, sizeof(itunesdb_chunk_t)); + memset(mhbd, 0, sizeof(*mhbd)); + itunesdb_init(mhbd, "mhbd", NULL); + mhbd_data = (chunk_mhbd_t*)mhbd->data; /* Construct "mhsd" chunk with track type. */ - mhsd = itunesdb_new_child(&mhbd); + mhsd = itunesdb_new_child(mhbd); if (mhsd) { chunk_mhsd_t* mhsd_data = NULL; itunesdb_init(mhsd, "mhsd", NULL); @@ -415,7 +455,6 @@ mhlt = itunesdb_new_child(mhsd); if (mhlt) { itunesdb_init(mhlt, "mhlt", NULL); - mhlt->num_children = num_records; /* For all records... */ for (i = 0;i < num_records;++i) { @@ -434,7 +473,7 @@ } /* Construct "mhsd" chunk with playlist type. */ - mhsd = itunesdb_new_child(&mhbd); + mhsd = itunesdb_new_child(mhbd); if (mhsd) { chunk_mhsd_t* mhsd_data = NULL; itunesdb_init(mhsd, "mhsd", NULL); @@ -445,7 +484,6 @@ mhlp = itunesdb_new_child(mhsd); if (mhlp) { itunesdb_init(mhlp, "mhlp", NULL); - mhlp->num_children = 1; mhyp = itunesdb_new_child(mhlp); if (mhyp) { @@ -457,4 +495,9 @@ } } } + + mhbd_data->num_children = mhbd->num_children; + + ipod->itunesdb = mhbd; + return 0; } Modified: trunk/pmplib/lib/pmp_ipod/ipod.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/ipod.h 2007-02-23 06:22:53 UTC (rev 385) @@ -24,6 +24,8 @@ #ifndef __IPOD_H__ #define __IPOD_H__ +#include <pmplib/pmp.h> + typedef struct { const char *id; const char *manufacturer; @@ -51,7 +53,9 @@ void ipod_init(ipod_t* ipod); void ipod_finish(ipod_t* ipod); +result_t ipod_set(ipod_t* ipod, const pmp_music_record_t* records, int num_records, const pmp_playlist_t* playlists, int num_playlists); result_t ipod_read(ipod_t* ipod, const ucs2char_t* itunesdb); +result_t ipod_write(ipod_t* ipod, const ucs2char_t* itunesdb); result_t ipod_dump(ipod_t* ipod, FILE *fpo); #endif/*__IPOD_H__*/ Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-23 06:22:53 UTC (rev 385) @@ -53,7 +53,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhbd", 4); - chunk->size = sizeof(chunk_mhbd_t) + 12; + chunk->size = 104; chunk->overall_size = chunk->size; } @@ -100,7 +100,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhsd", 4); - chunk->size = sizeof(chunk_mhsd_t) + 12; + chunk->size = 96; chunk->overall_size = chunk->size; } @@ -132,8 +132,8 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhlt", 4); - chunk->size = 0; /* stands for number of children for "mhlt" chunk. */ - chunk->overall_size = sizeof(chunk_mhlt_t) + 12; + chunk->size = 92; + chunk->overall_size = 0; /* stands for number of children for "mhlt" chunk. */ } mhlt = (chunk_mhlt_t*)calloc(1, sizeof(chunk_mhlt_t)); @@ -159,7 +159,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhit", 4); - chunk->size = sizeof(chunk_mhit_t) + 12; + chunk->size = 328; chunk->overall_size = chunk->size; } @@ -263,8 +263,8 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhlp", 4); - chunk->size = 0; /* stands for number of children for "mhlt" chunk. */ - chunk->overall_size = sizeof(chunk_mhlp_t) + 12; + chunk->size = 92; + chunk->overall_size = 0; } mhlp = (chunk_mhlp_t*)calloc(1, sizeof(chunk_mhlp_t)); @@ -290,7 +290,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhyp", 4); - chunk->size = sizeof(chunk_mhyp_t) + 12; + chunk->size = 108; chunk->overall_size = chunk->size; } @@ -329,7 +329,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhip", 4); - chunk->size = sizeof(chunk_mhip_t) + 12; + chunk->size = 76; chunk->overall_size = chunk->size; } @@ -550,7 +550,7 @@ if (def) { memset(chunk, 0, sizeof(*chunk)); strncpy(chunk->id, "mhod", 4); - chunk->size = 0x18; + chunk->size = 24; chunk->overall_size = chunk->size; } chunk->data = calloc(1, sizeof(chunk_mhod_t)); @@ -751,6 +751,53 @@ return 0; } +int itunesdb_write(itunesdb_chunk_t* chunk, serializer_t* sio) +{ + uint32_t i, offset = 0; + uint8_t zero = 0; + const itunesdb_chunkdecl_t* decl = NULL; + + /* Store the offset position of this chunk for the future use of rewind. */ + chunk->offset = serialize_tell(sio); + + /* Write the chunk ID and header information. The overall_size may be incorrect at this moment. */ + if (serialize_uint8_array(sio, "id", "%c ", chunk->id, sizeof(chunk->id))) return 1; + if (serialize_uint32le(sio, "size", "%d", &chunk->size)) return 1; + if (serialize_uint32le(sio, "overall_size", "%d", &chunk->overall_size)) return 1; + + /* Write the chunk data if this chunk is 'known' */ + decl = find_chunkdecl(chunk->id); + if (decl) { + if (decl->serialize(chunk, sio)) return 1; + } + + /* Pad 0x00 in the rest of file header. */ + for (i = serialize_tell(sio);i < chunk->offset + chunk->size;++i) { + serialize_uint8(sio, NULL, NULL, &zero); + } + + /* Write children for this chunk. */ + for (i = 0;i < chunk->num_children;++i) { + itunesdb_write(&chunk->childlen[i], sio); + } + + /* Calculate chunk->overall_size. */ + if (strncmp(chunk->id, "mhlt", 4) == 0 || strncmp(chunk->id, "mhlp", 4) == 0) { + /* chunk->overall_size represents the number of children for "mhlt" and "mhlp" chunks */ + chunk->overall_size = chunk->num_children; + } else { + /* chunk->overall_size represents the size in bytes of this chunk */ + chunk->overall_size = serialize_tell(sio) - chunk->offset; + } + + offset = serialize_tell(sio); + serialize_seek(sio, chunk->offset + 2 * sizeof(uint32_t)); + if (serialize_uint32le(sio, "overall_size", "%d", &chunk->overall_size)) return 1; + serialize_seek(sio, offset); + + return 0; +} + itunesdb_chunk_t* itunesdb_new_child(itunesdb_chunk_t* chunk) { chunk->childlen = (itunesdb_chunk_t*)realloc( Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-23 06:22:53 UTC (rev 385) @@ -252,5 +252,6 @@ int itunesdb_repr(itunesdb_chunk_t* chunk, size_t index, serializer_t* sio); int itunesdb_read(itunesdb_chunk_t* chunk, serializer_t* sio); +int itunesdb_write(itunesdb_chunk_t* chunk, serializer_t* sio); #endif/*__ITUNESDB_H__*/ Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-23 06:22:53 UTC (rev 385) @@ -404,82 +404,18 @@ result_t ret = 0; pmp_t* pmp = music->pmp; pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + ucs2char_t itunesdb[MAX_PATH]; // Initialize ipod library. ipod_init(&ipod); - if (pmp->flag & PMPOF_MUSIC_DB_WRITE) { - /* - int i; - ucs2char_t dat[MAX_PATH], dic[MAX_PATH], idx[MAX_PATH]; - ip3db_music_record_t* records = NULL; + // Read the music database. + set_filenames(itunesdb, music->pmp); - // Allocate an array of music records. - records = (ip3db_music_record_t*)malloc(sizeof(ip3db_music_record_t) * pmpmi->num_records); - - // Build an array of IP3DB records. - for (i = 0;i < pmpmi->num_records;++i) { - const pmp_music_record_t* src = &pmpmi->records[i]; - ip3db_variant_t* dst = records[i]; - - ip3db_record_init(&ip3db, &records[i]); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_FILEPATH], filepath_changeroot(src->filename, pmp->info.path_to_root)); - filepath_remove_filespec(dst[IP3DBF_MUSIC_FILEPATH].value.str); - filepath_addslash(dst[IP3DBF_MUSIC_FILEPATH].value.str); - filepath_slash(dst[IP3DBF_MUSIC_FILEPATH].value.str); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_FILENAME], filepath_skippath(src->filename)); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_ARTIST], src->artist); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_ALBUM], src->album); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_GENRE], src->genre); - ip3db_variant_set_str(&dst[IP3DBF_MUSIC_TITLE], src->title); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_DURATION], src->duration); - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_RATING], (uint16_t)src->rating); - switch (src->codec) { - case PMPCODEC_MPEGLAYER3: - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 0); - break; - case PMPCODEC_VORBIS: - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 3); - break; - case PMPCODEC_WMA: - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 5); - break; - } - ip3db_variant_set_word(&dst[IP3DBF_MUSIC_TRACKNUMBER], (uint16_t)src->track_number); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_BITRATE], src->bitrate); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_CLUSA], src->ts_update); - ip3db_variant_set_dword(&dst[IP3DBF_MUSIC_UID], (uint32_t)i+1); - } - - // Register records (and playlists) to the database. - if (pmp->flag & PMPOF_MUSIC_PL_WRITE) { - ip3db_set( - &ip3db, - (const ip3db_music_record_t*)records, - pmpmi->num_records, - pmpmi->playlists, - pmpmi->num_playlists - ); - } else { - ip3db_set( - &ip3db, - (const ip3db_music_record_t*)records, - pmpmi->num_records, - NULL, - 0 - ); - } - - // Write out the music database. - set_filenames(dat, dic, idx, pmp); - ret = ip3db_write(&ip3db, dat, dic, idx); - - // Free IP3DB records. - for (i = 0;i < pmpmi->num_records;++i) { - ip3db_record_finish(&ip3db, &records[i]); - } - free(records); - */ + if (pmp->flag & PMPOF_MUSIC_DB_WRITE) { + ipod_set(&ipod, pmpmi->records, pmpmi->num_records, pmpmi->playlists, pmpmi->num_playlists); + ipod_write(&ipod, itunesdb); + ipod_dump(&ipod, stdout); } exit_this: Modified: trunk/pmplib/lib/pmp_ipod/serialize.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-22 16:08:29 UTC (rev 384) +++ trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-23 06:22:53 UTC (rev 385) @@ -270,9 +270,7 @@ int serialize_seek(serializer_t* sio, size_t offset) { - if (sio->mode < 0) { - sio->offset = offset; - } + sio->offset = offset; return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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. |
From: <ny...@us...> - 2007-02-21 17:36:25
|
Revision: 383 http://svn.sourceforge.net/pmplib/?rev=383&view=rev Author: nyaochi Date: 2007-02-21 09:36:23 -0800 (Wed, 21 Feb 2007) Log Message: ----------- Incremental commit: free allocated memory blocks. Modified Paths: -------------- trunk/pmplib/lib/pmp_ipod/ipod.c trunk/pmplib/lib/pmp_ipod/itunesdb.c trunk/pmplib/lib/pmp_ipod/itunesdb.h trunk/pmplib/lib/pmp_ipod/pmp_ipod.c trunk/pmplib/lib/pmp_ipod/serialize.c trunk/pmplib/lib/pmp_ipod/serialize.h Modified: trunk/pmplib/lib/pmp_ipod/ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-21 15:56:22 UTC (rev 382) +++ trunk/pmplib/lib/pmp_ipod/ipod.c 2007-02-21 17:36:23 UTC (rev 383) @@ -19,7 +19,7 @@ * */ -/* $Id:$ */ +/* $Id$ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -45,7 +45,7 @@ void ipod_finish(ipod_t* ipod) { - + itunesdb_finish(ipod->itunesdb); } 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 15:56:22 UTC (rev 382) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.c 2007-02-21 17:36:23 UTC (rev 383) @@ -19,7 +19,7 @@ * */ -/* $Id:$ */ +/* $Id$ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -38,6 +38,26 @@ #include "util.h" #include "itunesdb.h" + + +static void chunk_finish(itunesdb_chunk_t* chunk) +{ + free(chunk->data); + memset(chunk, 0, sizeof(*chunk)); +} + +static int mhbd_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + 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; +} + static int mhbd_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhbd_t* mhbd = (chunk_mhbd_t*)chunk->data; @@ -45,10 +65,10 @@ 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_uint64le(sio, "identifier", "%016llX", &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_uint64le(sio, "unknown4", "%016llX", &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; @@ -56,6 +76,20 @@ return 0; } + + +static mhsd_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + 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; +} + static int mhsd_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhsd_t* mhsd = (chunk_mhsd_t*)chunk->data; @@ -66,6 +100,20 @@ return 0; } + + +static mhlt_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + 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; +} + static int mhlt_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhlt_t* mhlt = (chunk_mhlt_t*)chunk->data; @@ -75,6 +123,20 @@ return 0; } + + +static mhit_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + 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; +} + static int mhit_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhit_t* mhit = (chunk_mhit_t*)chunk->data; @@ -108,7 +170,7 @@ 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_uint64le(sio, "dbid", "%016llX", &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; @@ -128,14 +190,14 @@ 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_uint64le(sio, "dbid2", "%016llX", &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_uint64le(sio, "num_samples", "%llu", &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; @@ -157,6 +219,20 @@ return 0; } + + +static mhlp_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + 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; +} + static int mhlp_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhlp_t* mhlp = (chunk_mhlp_t*)chunk->data; @@ -166,6 +242,20 @@ return 0; } + + +static mhyp_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (dataonly) { + 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; +} + static int mhyp_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhyp_t* mhyp = (chunk_mhyp_t*)chunk->data; @@ -177,7 +267,7 @@ 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_uint64le(sio, "id", "%016llX", &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; @@ -187,6 +277,20 @@ return 0; } + + +static mhip_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + 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; +} + static int mhip_serialize(itunesdb_chunk_t* chunk, serializer_t* sio) { chunk_mhip_t* mhyp = (chunk_mhip_t*)chunk->data; @@ -201,12 +305,20 @@ return 0; } + + +static void mhod_string_finish(itunesdb_chunk_t* chunk) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_string_t* string = &mhod->data.str; + ucs2free(string->value); + memset(string, 0, sizeof(*string)); +} + 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; @@ -216,26 +328,38 @@ return 0; } +static void mhod_url_finish(itunesdb_chunk_t* chunk) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_url_t* url = &mhod->data.url; + ucs2free(url->value); + memset(url, 0, sizeof(*url)); +} + 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; + if (serialize_utf8str_fixed(sio, name, "%s", &url->value, chunk->size - chunk->overall_size)) return 1; return 0; } +static void mhod_index_finish(itunesdb_chunk_t* chunk) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_index_t* index = &mhod->data.index; + ucs2free(index->entries); + memset(index, 0, sizeof(*index)); +} + 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; @@ -257,16 +381,22 @@ return 0; } +static void mhod_playlist_column_finish(itunesdb_chunk_t* chunk) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_playlist_column_t* pc = &mhod->data.pc; + ucs2free(pc->columns); + memset(pc, 0, sizeof(*pc)); +} + 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_uint64le(sio, "unk4", "%016llX", &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; @@ -294,19 +424,24 @@ 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; + if (serialize_uint64le(sio, fieldname, "%016llX", &def->padding)) return 1; } return 0; } +static void mhod_playlist_order_finish(itunesdb_chunk_t* chunk) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + chunk_mhod_playlist_order_t* po = &mhod->data.po; + memset(po, 0, sizeof(*po)); +} + 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; @@ -316,23 +451,23 @@ 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}, + {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; @@ -340,7 +475,7 @@ while (decl->name) { if (decl->type == mhod->type) { - if (decl->chunk_size == 0 || decl->chunk_size == chunk->chunk_size) { + if (decl->overall_size == 0 || decl->overall_size == chunk->overall_size) { return decl; } } @@ -349,12 +484,36 @@ return NULL; } +static int mhod_init(itunesdb_chunk_t* chunk, int dataonly) +{ + if (!dataonly) { + memset(chunk, 0, sizeof(*chunk)); + strncpy(chunk->id, "mhod", 4); + chunk->size = 0x18; + chunk->overall_size = chunk->size; + } + chunk->data = calloc(1, sizeof(chunk_mhod_t)); + return chunk->data ? 0 : 1; +} + +static void mhod_finish(itunesdb_chunk_t* chunk) +{ + chunk_mhod_t* mhod = (chunk_mhod_t*)chunk->data; + const itunesdb_mhoddecl_t* decl = NULL; + decl = find_mhoddecl(chunk); + if (decl) { + decl->finish(chunk); + } +} + 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; + if (serialize_uint32le(sio, "unk1", "%u", &mhod->unk1)) return 1; + if (serialize_uint32le(sio, "unk2", "%u", &mhod->unk2)) return 1; decl = find_mhoddecl(chunk); if (decl) { @@ -373,15 +532,15 @@ 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}, + {"mhbd", mhbd_init, chunk_finish, mhbd_serialize}, + {"mhsd", mhsd_init, chunk_finish, mhsd_serialize}, + {"mhlt", mhlt_init, chunk_finish, mhlt_serialize}, + {"mhit", mhit_init, chunk_finish, mhit_serialize}, + {"mhlp", mhlp_init, chunk_finish, mhlp_serialize}, + {"mhyp", mhyp_init, chunk_finish, mhyp_serialize}, + {"mhip", mhip_init, chunk_finish, mhip_serialize}, + {"mhod", mhod_init, mhod_finish, mhod_serialize}, + {NULL, NULL, NULL, NULL}, }; const itunesdb_chunkdecl_t* decl = cds; @@ -394,6 +553,21 @@ return NULL; } +void itunesdb_finish(itunesdb_chunk_t* chunk) +{ + uint32_t i; + const itunesdb_chunkdecl_t* decl = NULL; + + for (i = 0;i < chunk->num_children;++i) { + itunesdb_finish(&chunk->childlen[i]); + } + + decl = find_chunkdecl(chunk); + if (decl) { + decl->finish(chunk); + } +} + int itunesdb_repr(itunesdb_chunk_t* chunk, size_t index, serializer_t* sio) { uint32_t i; @@ -409,9 +583,9 @@ serialize_indent(sio); fprintf(sio->fp, "offset: %08X\n", chunk->offset); serialize_indent(sio); - fprintf(sio->fp, "data_size: %d\n", chunk->data_size); + fprintf(sio->fp, "size: %d\n", chunk->size); serialize_indent(sio); - fprintf(sio->fp, "chunk_size: %d\n", chunk->chunk_size); + fprintf(sio->fp, "overall_size: %d\n", chunk->overall_size); /* Show fields in the chunk data */ decl = find_chunkdecl(chunk); @@ -449,26 +623,25 @@ /* 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; + if (serialize_uint32le(sio, "size", "%d", &chunk->size)) return 1; + 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); if (decl) { - chunk->data = calloc(1, decl->data_size); - if (chunk->data) { + if (decl->init(chunk, 1) == 0) { if (decl->serialize(chunk, sio)) return 1; } } if (strncmp(chunk->id, "mhod", 4) == 0) { - uint32_t next = begin + chunk->chunk_size; + uint32_t next = begin + chunk->overall_size; if (next < serialize_tell(sio)) { fprintf(stderr, "WARNING: backward seeking.\n"); } serialize_seek(sio, next); } else { - uint32_t next = begin + chunk->data_size; + uint32_t next = begin + chunk->size; if (next < serialize_tell(sio)) { fprintf(stderr, "WARNING: backward seeking.\n"); } @@ -477,17 +650,17 @@ /* 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->overall_size represents the number of children for "mhlt" and "mhlp" chunks */ + chunk->num_children = chunk->overall_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->overall_size represents the size in bytes of this chunk */ chunk->num_children = 0; chunk->childlen = NULL; - while (sio->offset - begin < chunk->chunk_size) { + 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)); @@ -498,29 +671,3 @@ 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 Modified: trunk/pmplib/lib/pmp_ipod/itunesdb.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-21 15:56:22 UTC (rev 382) +++ trunk/pmplib/lib/pmp_ipod/itunesdb.h 2007-02-21 17:36:23 UTC (rev 383) @@ -19,7 +19,7 @@ * */ -/* $Id:$ */ +/* $Id$ */ #ifndef __ITUNESDB_H__ #define __ITUNESDB_H__ @@ -153,8 +153,6 @@ } chunk_mhip_t; typedef struct { - uint32_t unk1; - uint32_t unk2; uint32_t position; uint32_t size; uint32_t unknown; @@ -163,14 +161,10 @@ } 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]; @@ -199,14 +193,14 @@ } 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; + uint32_t unk1; + uint32_t unk2; union { chunk_mhod_string_t str; chunk_mhod_url_t url; @@ -219,8 +213,8 @@ struct tag_itunesdb_chunk { int8_t id[4]; - uint32_t data_size; - uint32_t chunk_size; + uint32_t size; + uint32_t overall_size; void* data; uint32_t num_children; /* This field does not exist in iTunesDB. */ @@ -231,17 +225,20 @@ typedef struct { uint32_t type; const char* name; - size_t chunk_size; + size_t overall_size; + void (*finish)(itunesdb_chunk_t* chunk); 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 (*init)(itunesdb_chunk_t* chunk, int dataonly); + void (*finish)(itunesdb_chunk_t* chunk); 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); +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); #endif/*__ITUNESDB_H__*/ Modified: trunk/pmplib/lib/pmp_ipod/pmp_ipod.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-21 15:56:22 UTC (rev 382) +++ trunk/pmplib/lib/pmp_ipod/pmp_ipod.c 2007-02-21 17:36:23 UTC (rev 383) @@ -19,7 +19,7 @@ * */ -/* $Id:$ */ +/* $Id$ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -63,7 +63,7 @@ static const ipod_descriptor_t g_model_descriptions[] = { { - "ipod", "Apple", "iPod", "UM", + "apple_ipod", "Apple", "iPod", "UM", "---", "---", "iPod_Control\\iTunes\\iTunesDB", ".mp3\0", Modified: trunk/pmplib/lib/pmp_ipod/serialize.c =================================================================== --- trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-21 15:56:22 UTC (rev 382) +++ trunk/pmplib/lib/pmp_ipod/serialize.c 2007-02-21 17:36:23 UTC (rev 383) @@ -251,7 +251,7 @@ serialize_uint8(sio, name, format, (uint8_t*)&str[i]); } } else if (sio->mode < 0) { - char* str = calloc(size+1, sizeof(char)); + char* str = (char*)ucs2calloc(sizeof(char) * (size+1)); for (i = 0;i < size;++i) { serialize_uint8(sio, name, format, (uint8_t*)&str[i]); } @@ -276,7 +276,7 @@ return 0; } -uint32_t serialize_tell(serializer_t* sio) +size_t serialize_tell(serializer_t* sio) { return sio->offset; } Modified: trunk/pmplib/lib/pmp_ipod/serialize.h =================================================================== --- trunk/pmplib/lib/pmp_ipod/serialize.h 2007-02-21 15:56:22 UTC (rev 382) +++ trunk/pmplib/lib/pmp_ipod/serialize.h 2007-02-21 17:36:23 UTC (rev 383) @@ -54,7 +54,7 @@ int serialize_utf8str_fixed(serializer_t* sio, const char *name, const char *format, char** value, size_t size); int serialize_seek(serializer_t* sio, size_t offset); -uint32_t serialize_tell(serializer_t* sio); +size_t serialize_tell(serializer_t* sio); void serialize_indent(serializer_t* sio); void serialize_indent_ascend(serializer_t* sio); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
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] |
From: <ny...@us...> - 2007-02-20 15:40:17
|
Revision: 381 http://svn.sourceforge.net/pmplib/?rev=381&view=rev Author: nyaochi Date: 2007-02-20 07:40:10 -0800 (Tue, 20 Feb 2007) Log Message: ----------- A trivial fix that may affect nothing. Modified Paths: -------------- trunk/pmplib/lib/pmp_iriverplus3/ip3db.c Modified: trunk/pmplib/lib/pmp_iriverplus3/ip3db.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/ip3db.c 2007-02-19 22:03:59 UTC (rev 380) +++ trunk/pmplib/lib/pmp_iriverplus3/ip3db.c 2007-02-20 15:40:10 UTC (rev 381) @@ -99,7 +99,7 @@ break; case IP3DBVT_STRING: ucs2free(dst->value.str); - dst->value.str = src->value.str ? ucs2dup(src->value.str) : 0; + dst->value.str = src->value.str ? ucs2dup(src->value.str) : ucs2calloc(sizeof(ucs2char_t)); break; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <suc...@us...> - 2007-02-19 22:04:09
|
Revision: 380 http://svn.sourceforge.net/pmplib/?rev=380&view=rev Author: sucknblow Date: 2007-02-19 14:03:59 -0800 (Mon, 19 Feb 2007) Log Message: ----------- Attempt to work around totally braindead mozilla packaging. Modified Paths: -------------- trunk/pmplib/configure.in trunk/pmplib/frontend/easypmp/cui/Makefile.am trunk/pmplib/m4/smjs.m4 Modified: trunk/pmplib/configure.in =================================================================== --- trunk/pmplib/configure.in 2007-02-18 19:07:28 UTC (rev 379) +++ trunk/pmplib/configure.in 2007-02-19 22:03:59 UTC (rev 380) @@ -221,6 +221,7 @@ AC_SUBST(VORBISFILE_LIBS) AC_SUBST(JS_CFLAGS) AC_SUBST(JS_LIBS) +AC_SUBST(JS_RPATH) AM_CONDITIONAL(have_jsapi, test -n "$JS_CFLAGS") AM_CONDITIONAL(have_getopt, test "$ac_cv_header_getopt_h" = "yes") Modified: trunk/pmplib/frontend/easypmp/cui/Makefile.am =================================================================== --- trunk/pmplib/frontend/easypmp/cui/Makefile.am 2007-02-18 19:07:28 UTC (rev 379) +++ trunk/pmplib/frontend/easypmp/cui/Makefile.am 2007-02-19 22:03:59 UTC (rev 380) @@ -28,7 +28,7 @@ AM_CFLAGS = @CFLAGS@ INCLUDES = @INCLUDES@ -AM_LDFLAGS = @LDFLAGS@ +AM_LDFLAGS = @LDFLAGS@ ${JS_RPATH} easypmp_CFLAGS = -DPMP_JSPL_DIR="\"$(prefix)/share/$(JSPL_DIR)/jspl\"" Modified: trunk/pmplib/m4/smjs.m4 =================================================================== --- trunk/pmplib/m4/smjs.m4 2007-02-18 19:07:28 UTC (rev 379) +++ trunk/pmplib/m4/smjs.m4 2007-02-19 22:03:59 UTC (rev 380) @@ -35,6 +35,39 @@ [#define XP_UNIX]) ]) +# Attempt to workaround totally brain-dead Mozilla packaging... +m4_define([spidermonkey_rpath],[ + saved_OPTERR="$OPTERR" + OPTERR=0 + saved_OPTIND="$OPTIND" + OPTIND=1 + saved_HAVE_GETOPTS="$HAVE_GETOPTS" + HAVE_GETOPTS= + JS_RPATH= + if test -n "$BASH_VERSION" -o "$ZSH_VERSION" ; then + HAVE_GETOPTS=yes + fi + if test "$HAVE_GETOPTS" = "yes" ; then + while getopts L:l: f `echo $JS_LIBS` ; do + case $f in + L) + if test "$OPTARG" != "/lib" -a "$OPTARG" != "/usr/lib" ; then + JS_RPATH="$JS_RPATH -Wl,--rpath \"$OPTARG\"" + fi + ;; + esac + done + else + JS_LIBDIR=`echo "$JS_LIBS "| sed 's/.*\(-L\([^" ]\|"[^"]*"\)*\) .*/\1/'` + if test "${JS_LIBDIR#-L}" != "${JS_LIBDIR}" ; then + JS_RPATH="$JS_RPATH -Wl,--rpath \"${JS_LIBDIR#-L}\"" + fi + fi + OPTERR="$saved_OPTERR" + OPTIND="$saved_OPTIND" + HAVE_GETOPTS="$saved_HAVE_GETOPTS" +]) + m4_define([spidermonkey_checkall], [if test x"$JS_CFLAGS" = x; then AC_MSG_NOTICE([looking for the Spidermonkey Javascript library in various places.]) @@ -124,6 +157,8 @@ fi AC_SUBST(JS_CFLAGS) AC_SUBST(JS_LIBS) + spidermonkey_rpath + AC_SUBST(JS_RPATH) ]) AC_DEFUN([AC_PATH_SPIDERMONKEY], This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <suc...@us...> - 2007-02-18 19:07:30
|
Revision: 379 http://svn.sourceforge.net/pmplib/?rev=379&view=rev Author: sucknblow Date: 2007-02-18 11:07:28 -0800 (Sun, 18 Feb 2007) Log Message: ----------- Update html version of manual page Modified Paths: -------------- trunk/webpage/easypmp.html Modified: trunk/webpage/easypmp.html =================================================================== --- trunk/webpage/easypmp.html 2007-02-18 18:42:22 UTC (rev 378) +++ trunk/webpage/easypmp.html 2007-02-18 19:07:28 UTC (rev 379) @@ -10,26 +10,29 @@ </dl> <a name="lbAB" id="lbAB"> </a> <h2>NAME</h2> -easypmp - create music databases used by portable media -players<br /> +easypmp - create music databases and playlists used by portable +media players<br /> <a name="lbAC" id="lbAC"> </a> <h2>SYNOPSIS</h2> -<b>easypmp</b> [<b>-c</b>|<b>-u</b>] [<b>-p</b>] [<b>-m</b>] -[<b>-t</b> <i>csv-word-list</i>] [<b>-R</b> [<b>-L</b> -<i>level</i>]] [<b>-d</b> <i>device-id</i>] -[<i>mount-point</i>]<br /> -<b>easypmp</b> [<b>-h</b>|<b>-v</b>|<b>-l</b>] +<b>easypmp</b> [<b>-c</b>|<b>-u</b>] [<b>-t</b> +<i>csv-word-list</i>] [<b>-p</b> [<b>-P</b> <i>source-dir</i>] +[<i>-r</i>] [<i>-f</i>] [<i>-i</i>]] [<b>-R</b> [<b>-L</b> +<i>level</i>]] [<b>-d</b> <i>device-id</i>] [<b>-s</b> +<i>name:value</i>] [<b>-e</b> <i>system-encoding</i>] [<b>-w</b> +<i>tag-encoding]</i> [<i>mount-point</i>]<br /> +<b>easypmp</b> [<b>-h</b>|<b>-x</b>|<b>-v</b>|<b>-l</b>] <p><a name="lbAD" id="lbAD"> </a></p> <h2>DESCRIPTION</h2> <b>easypmp</b> is a command line utility used to create and -maintain the music database on a variety of portable media players. +maintain the music database and playlists on a variety of portable +media players. <p>Many portable music players allow the user to browse tracks by artist, album, genre, predefined playlists etc. In order to do this efficiently, they require a database of track information. Without this database, the player may require the user to browse tracks using only the directory structure. <b>easypmp</b> exists to create -that database, based on the tracks and playlists that are stored on -the player.</p> +music database and playlists, based on the tracks and playlists +that are stored on the player.</p> <p>Normally, <b>easypmp</b> is able to detect the type of any supported media player automatically. It does so by comparing the files and directories found at the specified mount point with the @@ -60,8 +63,11 @@ iRiver H10 MTP (with emergency connect mode)</li> <li>iRiver H10Jr. UMS</li> <li>iRiver U10 UMS</li> +<li>iRiver E10 UMS</li> <li>MEDION MDJuke220 and MDJuke440</li> <li>Samsung YH-820, YH-920 and YH-925</li> +<li>MSI MEGA PLAYER 540</li> +<li>Philips HDD6320</li> </ul> <p>Note that some of the iRiver devices listed above may not support UMS as shipped. For example, in Europe and the United @@ -107,29 +113,46 @@ device the last time the database was updated. Thus this option is a faster way creating the music database when only a few tracks on the device have been changed since the database was last created or -updated. However, if the meta-data in existing files has changed, -this may not be reflected in the database when using this -option.</p> +updated. If the meta-data in existing files has changed, +<b>easypmp</b> tries to reflect the changes in the database even +when using this option.</p> </dd> <dt class="c1">-p, --playlist</dt> <dd>Many programs for playing music allow playlists to be created and saved on disk, ready to be played later. Such playlists -frequently have a <b>.m3u</b> extension. However, the playlists -saved by most programs cannot be used directly on portable media -players. Instead, it is necessary to convert (or `compile') each -playlist into a format that the media player can read. -<p>When the <b>-p</b>/<b>--playlist</b> option is specified, -<b>easypmp</b> will search the playlist directory on the device for -playlists that can be converted into a form that the media player -can read (see the <b>DESCRIPTION</b> section above for information -on how to determine the playlist directory for a particular media -player).</p> -</dd> -<dt class="c1">-m, --music</dt> -<dd>The <b>-m</b>/<b>--music</b> option is similar to the -<b>-p</b>/<b>--playlist</b> option. However, instead of searching -the playlist directory on the media player for playlists, it -searches in the music directory on the player instead.</dd> +frequently have a <b>.m3u</b> or <b>.pls</b> extension. However, +the playlists saved by most programs cannot be used directly on +portable media players. Instead, it is necessary to convert (or +`compile') each playlist into a format that the media player can +read. When the <b>-p</b>/<b>--playlist</b> option is specified, +<b>easypmp</b> will search the playlist directory on the device or +the directory specified by <b>-P</b>/<b>--playlist-source</b> +option for playlists that can be converted into a form that the +media player can read (see the <b>DESCRIPTION</b> section above for +information on how to determine the playlist directory for a +particular media player).</dd> +<dt><b>-P</b> <i>directory</i>, +--playlist-source=<i>directory</i></dt> +<dd>Specifies the location in which the source playlists are +stored. Changing the location to a directory on the computer means +on-the-fly playlist conversion without transferring source playlist +files on the device.</dd> +<dt class="c1">-r, --reconvert</dt> +<dd>Overwrite the existing playlists to force conversion.</dd> +<dt class="c1">-f, --find-missing</dt> +<dd>Find music files described in a playlist with broken +references. Setting this option tries to correct the location of a +music file referred to by a playlist by searching for the music +file in the music directories that have the same file name. Finding +two or more music files that have the target file name, +<b>easypmp</b> selects a music file with a path name that is the +most similar to the original one.</dd> +<dt class="c1">-i, --skip-missing</dt> +<dd>Skip missing music files in a playlist. Setting this option +indicates <b>easypmp</b> to continue the playlist conversion only +with music files found in the player. The default behavior for a +missing music file is to cancel the conversion for the +playlist.</dd> <dt class="c1">-R, --repr</dt> <dd>Output a textual representation of the music database on standard output. This option is seldom used: it may be useful for @@ -149,6 +172,21 @@ includes the `device identifier' for each device. For more information on the device identifier, see the <b>-d</b> option.</dd> +<dt><b>-s</b> <i>name</i>:<i>value</i>, +--set=<i>name</i>:<i>value</i></dt> +<dd>Overwrites the value of a variable set by the driver. The +following is the list of variables. +<dl compact="compact"> +<dd> +<dl compact="compact"> +<dt class="c1">pmp_music</dt> +<dd>Relative path to music directory from the mount point.</dd> +<dt class="c1">pmp_playlist</dt> +<dd>Relative path to playlist directory from the mount point.</dd> +</dl> +</dd> +</dl> +</dd> <dt><b>-d</b> <i>device-id</i>, --device=<i>device-id</i></dt> <dd>Specifies a device identifier for the player. The device identifier is used to determine where <b>easypmp</b> looks for @@ -181,8 +219,20 @@ modify music files, it only has an effect on the music database.</p> </dd> +<dt class="c1">-e, --encoding=system-encoding</dt> +<dd>Specify a character encoding used by the operating system. +<b>easypmp</b> converts path/file names from the specified encoding +into UCS-2 by using iconv. The default value is determined by the +automatic detection of the system character-encoding.</dd> +<dt class="c1">-w, --tagencoding=tag-encoding</dt> +<dd>Specify a character encoding for parsing non-unicode tags. +<b>easypmp</b> converts non-unicode tags embedded in ID3v1, ID3v2, +and Riff WAVE into UCS-2 encoding by using iconv. The default value +is "ISO-8859-1".</dd> <dt class="c1">-h, --help</dt> <dd>Show summary of options.</dd> +<dt class="c1">-x, --help-variable</dt> +<dd>Show the list of variables.</dd> <dt class="c1">-v, --version</dt> <dd>Show version of program.</dd> </dl> @@ -211,8 +261,9 @@ <p><br /> <a name="lbAH" id="lbAH"> </a></p> <h2>AUTHORS</h2> -<b>easypmp</b> was written by Nyaochi , who also wrote an initial -POSIX port using the Cygwin environment. +<b>easypmp</b> was written by Naoaki Okazaki <nyaochi at +users.sourceforge.net>, who also wrote an initial POSIX port +using the Cygwin environment. <p>This manual page was written by Martin Ellis , who also contributed bug fixes for the POSIX port.</p> -Time: 18:04:26 GMT, August 12, 2006 +Time: 19:10:45 GMT, February 18, 2007 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <suc...@us...> - 2007-02-18 18:42:37
|
Revision: 378 http://svn.sourceforge.net/pmplib/?rev=378&view=rev Author: sucknblow Date: 2007-02-18 10:42:22 -0800 (Sun, 18 Feb 2007) Log Message: ----------- KDEmail mail server seems to have died. New address Modified Paths: -------------- trunk/pmplib/AUTHORS trunk/pmplib/README trunk/pmplib/debian/changelog trunk/pmplib/debian/compat trunk/pmplib/debian/control trunk/pmplib/debian/copyright trunk/pmplib/debian/rules trunk/pmplib/frontend/easypmp/cui/console_posix.c trunk/pmplib/frontend/easypmp/cui/easypmp.1 trunk/pmplib/lib/filepath/filepath_posix.c trunk/pmplib/lib/filepath/rel2abs.c trunk/pmplib/lib/filepath/rel2abs.h trunk/webpage/about.xml Modified: trunk/pmplib/AUTHORS =================================================================== --- trunk/pmplib/AUTHORS 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/AUTHORS 2007-02-18 18:42:22 UTC (rev 378) @@ -1,2 +1,2 @@ Naoaki Okazaki <nyaochi at users sourceforge net> -Martin Ellis <mar...@kd...> +Martin Ellis <ma...@do...> Modified: trunk/pmplib/README =================================================================== --- trunk/pmplib/README 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/README 2007-02-18 18:42:22 UTC (rev 378) @@ -17,7 +17,7 @@ The following text applies to the programs and the pmp and gmi libraries. Copyright (c) 2005-2007 Naoaki Okazaki <nyaochi at users.sourceforge.net> - Copyright (c) 2006 Martin Ellis <mar...@kd...> + Copyright (c) 2006 Martin Ellis <ma...@do...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -39,7 +39,7 @@ lib/ucs2, lib/filepath, and lib/playlist directories. Copyright (c) 2005-2007 Naoaki Okazaki <nyaochi at users.sourceforge.net> - Copyright (c) 2006 Martin Ellis <mar...@kd...> + Copyright (c) 2006 Martin Ellis <ma...@do...> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License Modified: trunk/pmplib/debian/changelog =================================================================== --- trunk/pmplib/debian/changelog 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/debian/changelog 2007-02-18 18:42:22 UTC (rev 378) @@ -2,4 +2,4 @@ * Initial release Closes: #369975 - -- Martin Ellis <mar...@kd...> Sat, 29 Jul 2006 23:05:36 +0100 + -- Martin Ellis <ma...@do...> Sat, 29 Jul 2006 23:05:36 +0100 Modified: trunk/pmplib/debian/compat =================================================================== --- trunk/pmplib/debian/compat 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/debian/compat 2007-02-18 18:42:22 UTC (rev 378) @@ -1 +1 @@ -4 +5 Modified: trunk/pmplib/debian/control =================================================================== --- trunk/pmplib/debian/control 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/debian/control 2007-02-18 18:42:22 UTC (rev 378) @@ -1,8 +1,8 @@ Source: pmplib Section: sound Priority: extra -Maintainer: Martin Ellis <mar...@kd...> -Build-Depends: debhelper (>= 4.0.0), libvorbis-dev, libid3tag0-dev, libmozjs-dev +Maintainer: Martin Ellis <ma...@do...> +Build-Depends: debhelper (>= 5), libvorbis-dev, libid3tag0-dev, libmozjs-dev Standards-Version: 3.7.2 Package: easypmp @@ -47,7 +47,7 @@ Architecture: any Section: libs Depends: ${shlibs:Depends} -Description: library for creating playlists for portable media players +Description: library for creating databases and playlists for portable media players PMPlib is a library for creating and maintaining the music database and playlists for a variety of portable music players. . Modified: trunk/pmplib/debian/copyright =================================================================== --- trunk/pmplib/debian/copyright 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/debian/copyright 2007-02-18 18:42:22 UTC (rev 378) @@ -1,4 +1,4 @@ -This package was debianized by Martin Ellis <mar...@kd...> on +This package was debianized by Martin Ellis <ma...@do...> on Fri, 2 Jun 2006 18:43:00 +0100. It was downloaded from http://pmplib.sourceforge.net/ @@ -21,7 +21,7 @@ The following text applies to the programs and the pmp and gmi libraries. Copyright (c) 2005-2006 Nyaochi <ny...@ny...> - Copyright (c) 2006 Martin Ellis <mar...@kd...> + Copyright (c) 2006 Martin Ellis <ma...@do...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -46,7 +46,7 @@ lib/ucs2, lib/filepath, and lib/playlist directories. Copyright (c) 2005-2006 Nyaochi <ny...@ny...> - Copyright (c) 2006 Martin Ellis <mar...@kd...> + Copyright (c) 2006 Martin Ellis <ma...@do...> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License @@ -71,7 +71,7 @@ Copyright (c) 1997 Shigio Yamaguchi. All rights reserved. Copyright (c) 1999 Tama Communications Corporation. All rights reserved. -Copyright (c) 2006 Martin Ellis <mar...@kd...>. +Copyright (c) 2006 Martin Ellis <ma...@do...>. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -97,5 +97,5 @@ The Debian packaging is - Copyright (c) 2006-2007 Martin Ellis <mar...@kd...> + Copyright (c) 2006-2007 Martin Ellis <ma...@do...> and is licensed under the GPL, see above. Modified: trunk/pmplib/debian/rules =================================================================== --- trunk/pmplib/debian/rules 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/debian/rules 2007-02-18 18:42:22 UTC (rev 378) @@ -35,7 +35,6 @@ build-stamp: config.status dh_testdir $(MAKE) - #docbook-to-man debian/easypmp.sgml > easypmp.1 touch build-stamp clean: @@ -43,7 +42,6 @@ dh_testroot rm -f build-stamp - # Add here commands to clean up after the build process. -$(MAKE) distclean ifneq "$(wildcard /usr/share/misc/config.sub)" "" cp -f /usr/share/misc/config.sub config.sub @@ -51,9 +49,9 @@ ifneq "$(wildcard /usr/share/misc/config.guess)" "" cp -f /usr/share/misc/config.guess config.guess endif - dh_clean + install: build dh_testdir dh_testroot @@ -61,7 +59,6 @@ dh_installdirs $(MAKE) install DESTDIR=$(CURDIR)/debian/tmp - # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. Modified: trunk/pmplib/frontend/easypmp/cui/console_posix.c =================================================================== --- trunk/pmplib/frontend/easypmp/cui/console_posix.c 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/frontend/easypmp/cui/console_posix.c 2007-02-18 18:42:22 UTC (rev 378) @@ -1,7 +1,7 @@ /* * Miscellaneous utilities. * - * Copyright (c) 2006 Martin Ellis <mar...@kd...> + * Copyright (c) 2006 Martin Ellis <ma...@do...> * Copyright (c) 2006-2007 Naoaki Okazaki * * This program is free software; you can redistribute it and/or modify Modified: trunk/pmplib/frontend/easypmp/cui/easypmp.1 =================================================================== --- trunk/pmplib/frontend/easypmp/cui/easypmp.1 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/frontend/easypmp/cui/easypmp.1 2007-02-18 18:42:22 UTC (rev 378) @@ -290,5 +290,5 @@ who also wrote an initial POSIX port using the Cygwin environment. This manual page was written by Martin Ellis -<mar...@kd...>, +<ma...@do...>, who also contributed bug fixes for the POSIX port. Modified: trunk/pmplib/lib/filepath/filepath_posix.c =================================================================== --- trunk/pmplib/lib/filepath/filepath_posix.c 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/lib/filepath/filepath_posix.c 2007-02-18 18:42:22 UTC (rev 378) @@ -2,7 +2,7 @@ * File/path utility implemented with POSIX API. * * Copyright (c) 2005-2007 Naoaki Okazaki - * Copyright (c) 2006-2007 Martin Ellis <mar...@kd...> + * Copyright (c) 2006-2007 Martin Ellis <ma...@do...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Modified: trunk/pmplib/lib/filepath/rel2abs.c =================================================================== --- trunk/pmplib/lib/filepath/rel2abs.c 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/lib/filepath/rel2abs.c 2007-02-18 18:42:22 UTC (rev 378) @@ -1,7 +1,7 @@ /* * Copyright (c) 1997 Shigio Yamaguchi. All rights reserved. * Copyright (c) 1999 Tama Communications Corporation. All rights reserved. - * Copyright (c) 2006 Martin Ellis <mar...@kd...>. + * Copyright (c) 2006 Martin Ellis <ma...@do...>. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions Modified: trunk/pmplib/lib/filepath/rel2abs.h =================================================================== --- trunk/pmplib/lib/filepath/rel2abs.h 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/pmplib/lib/filepath/rel2abs.h 2007-02-18 18:42:22 UTC (rev 378) @@ -1,7 +1,7 @@ /* * Relative to absolute path name conversion function (signature). * - * Copyright (c) 2006 Martin Ellis <mar...@kd...> + * Copyright (c) 2006 Martin Ellis <ma...@do...> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by Modified: trunk/webpage/about.xml =================================================================== --- trunk/webpage/about.xml 2007-02-18 08:04:37 UTC (rev 377) +++ trunk/webpage/about.xml 2007-02-18 18:42:22 UTC (rev 378) @@ -36,7 +36,7 @@ <dt>Martin Ellis</dt> <dd> Project admin and core developer. Owns an iriver U10 [1GB].<br/> -<img src="http://martin.ellis.name/img/martin.ellis.kdemail.net.png" /> +<img src="http://martin.ellis.name/img/ma...@do...g" /> </dd> </dl> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-18 08:04:36
|
Revision: 377 http://svn.sourceforge.net/pmplib/?rev=377&view=rev Author: nyaochi Date: 2007-02-18 00:04:37 -0800 (Sun, 18 Feb 2007) Log Message: ----------- Reduce a warning in ucs2char_win32.c Modified Paths: -------------- trunk/pmplib/lib/ucs2/ucs2char_win32.c Modified: trunk/pmplib/lib/ucs2/ucs2char_win32.c =================================================================== --- trunk/pmplib/lib/ucs2/ucs2char_win32.c 2007-02-18 08:01:54 UTC (rev 376) +++ trunk/pmplib/lib/ucs2/ucs2char_win32.c 2007-02-18 08:04:37 UTC (rev 377) @@ -40,7 +40,7 @@ #endif static UINT g_codepage = CP_ACP; -static const char *g_encoding = ""; +static char g_encoding[128]; int ucs2init() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ny...@us...> - 2007-02-18 08:01:53
|
Revision: 376 http://svn.sourceforge.net/pmplib/?rev=376&view=rev Author: nyaochi Date: 2007-02-18 00:01:54 -0800 (Sun, 18 Feb 2007) Log Message: ----------- Bug fix for database dump in pmp_irivnavi. Modified Paths: -------------- trunk/pmplib/lib/pmp_irivnavi/pmp_irivnavi.c Modified: trunk/pmplib/lib/pmp_irivnavi/pmp_irivnavi.c =================================================================== --- trunk/pmplib/lib/pmp_irivnavi/pmp_irivnavi.c 2007-02-18 07:53:06 UTC (rev 375) +++ trunk/pmplib/lib/pmp_irivnavi/pmp_irivnavi.c 2007-02-18 08:01:54 UTC (rev 376) @@ -88,7 +88,6 @@ } pmp_internal_t; typedef struct { - irivnavi_t db; pmp_music_record_t* records; int num_records; pmp_playlist_t* playlists; @@ -343,6 +342,7 @@ uint32_t pmpmusic_open(pmp_music_t* music) { pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + irivnavi_t db; result_t ret = 0; FILE *fp = NULL; ucs2char_t filename[MAX_PATH]; @@ -354,7 +354,7 @@ static const ucs2char_t ucs2cs_wma[] = {'.','w','m','a',0}; static const ucs2char_t ucs2cs_wav[] = {'.','w','a','v',0}; - irivnavi_init(&pmpmi->db); + irivnavi_init(&db); if (music->pmp->flag & PMPOF_MUSIC_DB_READ) { // Open a database file in the root directory. @@ -388,23 +388,25 @@ fread(buffer, 1, size, fp); // Read the data from the buffer. - if (irivnavi_serialize(&pmpmi->db, buffer, 0) == 0) { + if (irivnavi_serialize(&db, buffer, 0) == 0) { ret = PMPERR_INCONSISTENCY; goto error_exit; } // Free the buffer and file. free(buffer); + buffer = NULL; fclose(fp); + fp = NULL; // - pmpmi->num_records = pmpmi->db.num_records; + pmpmi->num_records = db.num_records; pmpmi->records = (pmp_music_record_t*)ucs2malloc(sizeof(pmp_music_record_t) * pmpmi->num_records); for (i = 0, j = 0;i < pmpmi->num_records;++i) { size_t length = 0; ucs2char_t* tmp = NULL; - const record_t* src = &pmpmi->db.records[i]; + const record_t* src = &db.records[i]; pmp_music_record_t* dst = &pmpmi->records[j]; pmplib_record_init(dst); @@ -438,13 +440,13 @@ ++j; } } - irivnavi_finish(&pmpmi->db); + irivnavi_finish(&db); return 0; error_exit: free(buffer); if (fp) fclose(fp); - irivnavi_finish(&pmpmi->db); + irivnavi_finish(&db); return ret; } @@ -452,6 +454,7 @@ { int i, j; pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; + irivnavi_t db; result_t ret = 0; FILE *fp = NULL; ucs2char_t filename[MAX_PATH]; @@ -459,15 +462,11 @@ static const ucs2char_t ucs2cs_unknown[] = {'u','n','k','n','o','w','n',0}; static const ucs2char_t m3u_ext[] = {'.','m','3','u',0}; - irivnavi_init(&pmpmi->db); + irivnavi_init(&db); if (music->pmp->flag & PMPOF_MUSIC_DB_WRITE) { - // Clear the database. - irivnavi_finish(&pmpmi->db); - irivnavi_init(&pmpmi->db); - // Initialize the record array. - if (irivnavi_init_records(&pmpmi->db, pmpmi->num_records) != 0) { + if (irivnavi_init_records(&db, pmpmi->num_records) != 0) { ret = PMPERR_INSUFFICIENTMEMORY; goto error_exit; } @@ -475,7 +474,7 @@ // Convert records from pmp_music_record_t to ip2db_record_t. for (i = 0, j = 0;i < pmpmi->num_records;++i) { const pmp_music_record_t* src = &pmpmi->records[i]; - record_t* dst = &pmpmi->db.records[j]; + record_t* dst = &db.records[j]; // Set record fields. record_init(dst); @@ -489,7 +488,7 @@ ++j; } - pmpmi->db.num_records = pmpmi->num_records; + db.num_records = pmpmi->num_records; // Open a database file in the root directory. ucs2cpy(filename, music->pmp->info.path_to_root); @@ -502,23 +501,23 @@ goto error_exit; } - irivnavi_update(&pmpmi->db); + irivnavi_update(&db); // Allocate a buffer that stores the whole data. - buffer = (uint8_t*)malloc(pmpmi->db.size); + buffer = (uint8_t*)malloc(db.size); if (!buffer) { ret = PMPERR_INSUFFICIENTMEMORY; goto error_exit; } // Write the data to the buffer. - if (irivnavi_serialize(&pmpmi->db, buffer, 1) == 0) { + if (irivnavi_serialize(&db, buffer, 1) == 0) { ret = PMPERR_INCONSISTENCY; goto error_exit; } // Write at one time. - fwrite(buffer, 1, pmpmi->db.size, fp); + fwrite(buffer, 1, db.size, fp); free(buffer); fclose(fp); @@ -550,13 +549,13 @@ } } - irivnavi_finish(&pmpmi->db); + irivnavi_finish(&db); return 0; error_exit: free(buffer); if (fp) fclose(fp); - irivnavi_finish(&pmpmi->db); + irivnavi_finish(&db); return ret; } @@ -592,11 +591,67 @@ } } -static result_t pmpmusic_dump(pmp_music_t* music, FILE *fp, int level) +static result_t pmpmusic_dump(pmp_music_t* music, FILE *fpo, int level) { + irivnavi_t db; + result_t ret = 0; + long size = 0; + FILE *fpi = NULL; + uint8_t *buffer = NULL; + ucs2char_t filename[MAX_PATH]; pmp_music_internal_t* pmpmi = (pmp_music_internal_t*)music->instance; - irivnavi_repr(&pmpmi->db, fp, level); - return 0; + + irivnavi_init(&db); + + // Open a database file in the root directory. + ucs2cpy(filename, music->pmp->info.path_to_root); + filepath_addslash(filename); + ucs2cat(filename, ucs2cs_irivnavi_idb); + fpi = ucs2fopen(filename, "rb"); + if (!fpi) { + return PMPERR_OPENFORREAD; + } + + // Obtain the stream size. + if (fseek(fpi, 0, SEEK_END) != 0) { + return PMPERR_OPENFORREAD; + } + if ((size = ftell(fpi)) == -1) { + return PMPERR_OPENFORREAD; + } + if (fseek(fpi, 0, SEEK_SET) != 0) { + return PMPERR_OPENFORREAD; + } + + // Allocate a buffer that stores the whole data. + buffer = (uint8_t*)malloc(size); + if (!buffer) { + ret = PMPERR_INSUFFICIENTMEMORY; + goto error_exit; + } + + // Read at one time. + fread(buffer, 1, size, fpi); + + // Read the data from the buffer. + if (irivnavi_serialize(&db, buffer, 0) == 0) { + ret = PMPERR_INCONSISTENCY; + goto error_exit; + } + + // Free the buffer and file. + free(buffer); + buffer = NULL; + fclose(fpi); + fpi = NULL; + + irivnavi_repr(&db, fpo, level); + +error_exit: + free(buffer); + if (fpi) fclose(fpi); + irivnavi_finish(&db); + return ret; } static result_t pmpmusic_set_playlists(pmp_music_t* music, const pmp_playlist_t* playlists, uint32_t num_playlists) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |