From: <ny...@us...> - 2006-12-27 19:04:23
|
Revision: 209 http://svn.sourceforge.net/pmplib/?rev=209&view=rev Author: nyaochi Date: 2006-12-27 11:04:23 -0800 (Wed, 27 Dec 2006) Log Message: ----------- More source code clean-up. Added comments in dat.c Modified Paths: -------------- trunk/pmplib/lib/pmp_iriverplus3/dat.c trunk/pmplib/lib/pmp_iriverplus3/dat.h trunk/pmplib/lib/pmp_iriverplus3/ip3db.c Modified: trunk/pmplib/lib/pmp_iriverplus3/dat.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/dat.c 2006-12-27 17:24:52 UTC (rev 208) +++ trunk/pmplib/lib/pmp_iriverplus3/dat.c 2006-12-27 19:04:23 UTC (rev 209) @@ -75,7 +75,11 @@ uint8_t *p = block; uint32_t offset; - /* Serialize offset address of this entry. */ + /* + * Serialize offset address of this entry. + * entry->offset: The offset address in the whole db.dat buffer (e.g., 0x00020123) + * offset (written in db.dat): The one within the chunk (e.g., 0x00000123) + */ if (is_storing) { offset = entry->offset - start; q -= serialize_uint32be(q, &offset, is_storing); @@ -151,12 +155,6 @@ memset(list, 0, sizeof(*list)); } -static dat_entry_t *dat_list_expand(dat_list_t* list) -{ - list->entries = (dat_entry_t*)realloc(list->entries, sizeof(dat_entry_t) * (list->num_entries+1)); - return &list->entries[list->num_entries++]; -} - static void dat_list_finish(dat_list_t* list) { uint32_t i; @@ -164,28 +162,35 @@ dat_entry_finish(&list->entries[i]); } free(list->entries); - dat_list_init(list); + memset(list, 0, sizeof(*list)); } +static dat_entry_t *dat_list_expand(dat_list_t* list) +{ + list->entries = (dat_entry_t*)realloc(list->entries, sizeof(dat_entry_t) * (list->num_entries+1)); + return &list->entries[list->num_entries++]; +} + static size_t dat_list_serialize(dat_list_t* list, const dic_table_t* dic_list, uint8_t* buffer, uint32_t start, int is_storing) { uint32_t i; uint8_t *p = buffer + start; uint8_t *q = buffer + start + 0x00020000 - sizeof(uint32_t); - /* Serialize the header (with a dummy size for writing). */ if (!is_storing) { + /* Read the header. */ p += serialize_uint32be(p, &list->size, is_storing); p += serialize_uint32be(p, &list->num_entries, is_storing); p += serialize_uint32be(p, &list->unknown1, is_storing); p += serialize_uint32be(p, &list->unknown2, is_storing); } else { + /* Skip the header for now when writing. */ p += sizeof(uint32_t) * 4; } - /* Initialize fields when reading. */ + /* Initialize fields according to db.dic when reading. */ if (!is_storing) { - free(list->entries); + dat_list_finish(list); list->entries = (dat_entry_t*)calloc(list->num_entries, sizeof(dat_entry_t)); for (i = 0;i < list->num_entries;++i) { dat_entry_init(&list->entries[i], dic_list); @@ -201,6 +206,7 @@ } if (is_storing) { + /* Compute the block size and write the header. */ list->size = (uint32_t)(p - (buffer + start)); p = buffer + start; p += serialize_uint32be(p, &list->size, is_storing); @@ -208,6 +214,7 @@ p += serialize_uint32be(p, &list->unknown1, is_storing); p += serialize_uint32be(p, &list->unknown2, is_storing); } + return (size_t)(list->size); } @@ -250,9 +257,12 @@ static size_t dat_serialize(dat_t* dat, const dic_t* dic, uint8_t* buffer, int is_storing) { if (is_storing) { + /* For writing a music chunk only. + * Empty filepath and filename fields as iriver plus 3 does. + */ int i; - ucs2char_t empty[] = {0}; for (i = 0;i < dat->musics.num_entries;++i) { + static const ucs2char_t empty[] = {0}; dat_entry_t* entry = &dat->musics.entries[i]; ip3db_variant_set_str(&entry->fields[IP3DBF_MUSIC_FILEPATH], empty); ip3db_variant_set_str(&entry->fields[IP3DBF_MUSIC_FILENAME], empty); @@ -316,24 +326,7 @@ fprintf(fp, "}\n"); } -typedef struct { - const ip3db_music_record_t* base; - int index; -} ip3db_sort_index_t; -static int comp_pathname(const void *__x, const void *__y) -{ - const ip3db_sort_index_t* _x = (const ip3db_sort_index_t*)__x; - const ip3db_sort_index_t* _y = (const ip3db_sort_index_t*)__y; - const ip3db_variant_t* x = _x->base[_x->index]; - const ip3db_variant_t* y = _y->base[_y->index]; - int ret = ucs2cmp(x[IP3DBF_MUSIC_FILEPATH].value.str, y[IP3DBF_MUSIC_FILEPATH].value.str); - if (ret == 0) { - return ucs2cmp(x[IP3DBF_MUSIC_FILENAME].value.str, y[IP3DBF_MUSIC_FILENAME].value.str); - } else { - return ret; - } -} typedef struct { ucs2char_t* path; @@ -392,15 +385,62 @@ return &dc->elems[i]; } + + +typedef struct { + const ip3db_music_record_t* base; + int index; +} sort_index_t; + +static int comp_pathname(const void *__x, const void *__y) +{ + const sort_index_t* _x = (const sort_index_t*)__x; + const sort_index_t* _y = (const sort_index_t*)__y; + const ip3db_variant_t* x = _x->base[_x->index]; + const ip3db_variant_t* y = _y->base[_y->index]; + int ret = ucs2cmp(x[IP3DBF_MUSIC_FILEPATH].value.str, y[IP3DBF_MUSIC_FILEPATH].value.str); + if (ret == 0) { + return ucs2cmp(x[IP3DBF_MUSIC_FILENAME].value.str, y[IP3DBF_MUSIC_FILENAME].value.str); + } else { + return ret; + } +} + + + static const ucs2char_t* skip_one_directory(const ucs2char_t* path) { ucs2char_t* p = ucs2chr(path, '/'); return p ? p+1 : NULL; } +void dat_set(dat_t* dat, dic_t* dic, const ip3db_music_record_t* records, int num_records) +{ + /* Procedure: + * 1) Construct the object chunk and attach music records with Object UIDs. + * Because the object chunk stores a tree structure of path names, we need to + * split a path name to elements and allocate an Object UID to each element. + * For example, the path name "/Music/Beatles/Love/01_love.ogg" will generate + * five objects each of which links to the object of the parent directory: + * - UID=0xFFFFFFFF: "/a/" (root directory; FileType = 0) + * - UID=1 : "Music/" (FileType = 1) + * - UID=2 : "Beatles/" (FileType = 1) + * - UID=3 : "Love/" (FileType = 1) + * - UID=4 : "01_love.ogg" (FileType = 2) + * In order to convert a list of path names to the tree structure, this + * implementation sorts the path names in alphabetical order and finds new + * path elements by using a directory queue (dircache_t). + * + * 3) Attach Object UIDs for file names (FileType = 2) to music records. + * These UIDs are stored in records in the music chunk so that the player + * can refer to the path/file name of a music track quickly. + * + * 4) Construct the music chunk by basically duplicating the records. + * + * Now the content of db.dat is ready. Note that the path character in db.dat + * is not '\\' but '/'. + */ -void dat_construct(dat_t* dat, dic_t* dic, const ip3db_music_record_t* records, int num_records) -{ int i, j; dat_entry_t* entry; uint32_t uid = 0; @@ -409,8 +449,8 @@ static const ucs2char_t ucs2cs_root[] = {'/', 0}; dat_list_t* dato = &dat->objects; dat_list_t* datm = &dat->musics; + sort_index_t *si = (sort_index_t*)malloc(sizeof(sort_index_t) * num_records); dircache_t dc; - ip3db_sort_index_t *si = (ip3db_sort_index_t*)malloc(sizeof(ip3db_sort_index_t) * num_records); dircache_init(&dc); @@ -427,31 +467,42 @@ /* Register the root node to the directory cache. */ dircache_push(&dc, ucs2cs_root, uid_root); + /* Sort the records in alphabetical order of their path names. */ for (i = 0;i < num_records;++i) { si[i].base = records; si[i].index = i; } qsort(si, num_records, sizeof(si[0]), comp_pathname); + /* Loop for the records. */ for (i = 0;i < num_records;++i) { + /* + * Split a path name into two parts: a prefix that have already been + * registered in the Object table: and a postfix that is being registered + * as Object records. + */ const ip3db_variant_t* record = records[si[i].index]; const ucs2char_t* path = record[IP3DBF_MUSIC_FILEPATH].value.str; const ucs2char_t* file = record[IP3DBF_MUSIC_FILENAME].value.str; int i = dircache_findprefix(&dc, path); const dircache_element_t* com = dircache_get(&dc, i); - const ucs2char_t* p = path + ucs2len(com->path); - uint32_t puid = com->uid; + const ucs2char_t* p = path + ucs2len(com->path); /* the prefix */ + uint32_t puid = com->uid; /* the UID of the parent directory of the postfix */ + /* Discard directory portions that do not share a prefix with the target. */ dircache_pop(&dc, i); + /* Create objects one by one for the directory portions in the postfix. */ while (p && *p) { ucs2char_t tmp[MAX_PATH]; const ucs2char_t* q = skip_one_directory(p); uid = dato->num_entries; + /* A directory element (e.g., "Beatles/") */ ucs2ncpy(tmp, p, q-p); tmp[q-p] = 0; + /* Create a new object. */ entry = dat_list_expand(dato); dat_entry_init(entry, &dic->objects); ip3db_variant_set_dword(&entry->fields[IP3DBF_OBJECTS_UID], uid); @@ -459,11 +510,15 @@ ip3db_variant_set_word(&entry->fields[IP3DBF_OBJECTS_FILETYPE], 1); ip3db_variant_set_str(&entry->fields[IP3DBF_OBJECTS_OBJECTNAME], tmp); + /* Register the fullpath (e.g., "/Music/eatles/" in the dircache. */ ucs2ncpy(tmp, path, q-path); tmp[q-path] = 0; dircache_push(&dc, tmp, uid); + /* Store the current UID for children. */ puid = uid; + + /* Move to the next portion. */ p = q; } Modified: trunk/pmplib/lib/pmp_iriverplus3/dat.h =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/dat.h 2006-12-27 17:24:52 UTC (rev 208) +++ trunk/pmplib/lib/pmp_iriverplus3/dat.h 2006-12-27 19:04:23 UTC (rev 209) @@ -49,6 +49,6 @@ int dat_read(dat_t* dat, const dic_t* dic, FILE *fpi); int dat_write(dat_t* dat, const dic_t* dic, FILE *fpo); void dat_dump(dat_t* dat, const dic_t* dic, FILE *fp); -void dat_construct(dat_t* dat, dic_t* dic, const ip3db_music_record_t* records, int num_records); +void dat_set(dat_t* dat, dic_t* dic, const ip3db_music_record_t* records, int num_records); #endif/*__IP3DB_DAT_H__*/ Modified: trunk/pmplib/lib/pmp_iriverplus3/ip3db.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/ip3db.c 2006-12-27 17:24:52 UTC (rev 208) +++ trunk/pmplib/lib/pmp_iriverplus3/ip3db.c 2006-12-27 19:04:23 UTC (rev 209) @@ -198,8 +198,8 @@ result_t ip3db_set(ip3db_t* db, const ip3db_music_record_t* records, int num_records) { - /* Construct Objects table in db.dat */ - dat_construct(db->dat, db->dic, records, num_records); + /* Set music records to dat_t. */ + dat_set(db->dat, db->dic, records, num_records); return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |