From: <ny...@us...> - 2006-12-27 14:23:48
|
Revision: 204 http://svn.sourceforge.net/pmplib/?rev=204&view=rev Author: nyaochi Date: 2006-12-27 06:23:47 -0800 (Wed, 27 Dec 2006) Log Message: ----------- A number of bug-fixes. The iriver E10 player can successfully navigate tracks in the database generated by EasyPMP now. The player cannot display the song information for some reason, and I'm finding out the reason. Modified Paths: -------------- trunk/pmplib/lib/pmp_iriverplus3/dat.c trunk/pmplib/lib/pmp_iriverplus3/idx.c trunk/pmplib/lib/pmp_iriverplus3/ip3db.c trunk/pmplib/lib/pmp_iriverplus3/ip3db.h trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c Modified: trunk/pmplib/lib/pmp_iriverplus3/dat.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/dat.c 2006-12-27 11:40:38 UTC (rev 203) +++ trunk/pmplib/lib/pmp_iriverplus3/dat.c 2006-12-27 14:23:47 UTC (rev 204) @@ -70,13 +70,20 @@ memset(entry, 0, sizeof(*entry)); } -static size_t dat_entry_serialize(dat_entry_t* entry, uint8_t* block, uint8_t* q, int is_storing) +static size_t dat_entry_serialize(dat_entry_t* entry, uint8_t* block, uint8_t* q, uint32_t start, int is_storing) { int i; uint8_t *p = block; + uint32_t offset; /* Serialize offset address of this entry. */ - q -= serialize_uint32be(q, &entry->offset, is_storing); + if (is_storing) { + offset = entry->offset - start; + q -= serialize_uint32be(q, &offset, is_storing); + } else { + q -= serialize_uint32be(q, &offset, is_storing); + entry->offset = offset + start; + } /* Serialize all fields in this entry. */ for (i = 0;i < entry->num_fields;++i) { @@ -161,17 +168,21 @@ dat_list_init(list); } -static size_t dat_list_serialize(dat_list_t* list, const dic_table_t* dic_list, uint8_t* buffer, int is_storing) +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; - uint8_t *q = buffer + 0x00020000 - sizeof(uint32_t); + uint8_t *p = buffer + start; + uint8_t *q = buffer + start + 0x00020000 - sizeof(uint32_t); /* Serialize the header (with a dummy size for writing). */ - 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); + if (!is_storing) { + 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 { + p += sizeof(uint32_t) * 4; + } /* Initialize fields when reading. */ if (!is_storing) { @@ -186,17 +197,19 @@ for (i = 0;i < list->num_entries;++i) { dat_entry_t* entry = &list->entries[i]; entry->offset = (uint32_t)(p - buffer); /* compute the current offset address */ - p += dat_entry_serialize(entry, p, q, is_storing); + p += dat_entry_serialize(entry, p, q, start, is_storing); q -= sizeof(uint32_t); } - /* Write the final size when writing. */ if (is_storing) { - uint32_t size = (uint32_t)(p - buffer); - serialize_uint32be(buffer, &size, is_storing); + list->size = (uint32_t)(p - (buffer + start)); + p = buffer + start; + 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); } - - return (size_t)(p - buffer); + return (size_t)(list->size); } static void dat_list_dump(dat_list_t* list, const dic_table_t* dic_list, FILE *fp) @@ -237,8 +250,17 @@ size_t dat_serialize(dat_t* dat, const dic_t* dic, uint8_t* buffer, int is_storing) { - dat_list_serialize(&dat->objects, &dic->objects, buffer, is_storing); - dat_list_serialize(&dat->musics, &dic->music, buffer + 0x00020000, is_storing); + if (is_storing) { + int i; + ucs2char_t empty[] = {0}; + for (i = 0;i < dat->musics.num_entries;++i) { + 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); + } + } + dat_list_serialize(&dat->objects, &dic->objects, buffer, 0, is_storing); + dat_list_serialize(&dat->musics, &dic->music, buffer, 0x00020000, is_storing); return 0; } Modified: trunk/pmplib/lib/pmp_iriverplus3/idx.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/idx.c 2006-12-27 11:40:38 UTC (rev 203) +++ trunk/pmplib/lib/pmp_iriverplus3/idx.c 2006-12-27 14:23:47 UTC (rev 204) @@ -284,10 +284,10 @@ return COMP(*x, *y); } -static int avl_insert_key(avl_t* avl, const void* key, int type, uint32_t* offset, uint32_t* root) +static int avl_insert_key(avl_t* avl, const ip3db_variant_t* key, int type, uint32_t* offset, uint32_t* root) { int ret = 0; - static avl_comp_t comp[] = {NULL, avl_comp_byte, avl_comp_word, avl_comp_dword, avl_comp_ucs2string}; + static avl_comp_t comp[] = {NULL, avl_comp_ucs2string, avl_comp_byte, avl_comp_word, avl_comp_dword}; uint32_t offset_prev = avl_current(avl); uint32_t offset_this = avlnode_new(avl); size_t size = 0; @@ -295,20 +295,23 @@ switch (type) { case IP3DBVT_BYTE: - size = sizeof(uint8_t); + offset_key = avl_allocate(avl, sizeof(uint8_t)); + *((uint8_t*)avlnode(avl, offset_key)) = key->value.byte; break; case IP3DBVT_WORD: - size = sizeof(uint16_t); + offset_key = avl_allocate(avl, sizeof(uint16_t)); + *((uint16_t*)avlnode(avl, offset_key)) = key->value.word; break; case IP3DBVT_DWORD: - size = sizeof(uint32_t); + offset_key = avl_allocate(avl, sizeof(uint32_t)); + *((uint32_t*)avlnode(avl, offset_key)) = key->value.dword; break; case IP3DBVT_STRING: - size = (ucs2len((const ucs2char_t*)key) + 1) * sizeof(ucs2char_t); + offset_key = avl_allocate(avl, sizeof(ucs2char_t) * (ucs2len(key->value.str) + 1)); + ucs2cpy((ucs2char_t*)avlnode(avl, offset_key), key->value.str); break; } - offset_key = avl_allocate(avl, (uint32_t)size); memcpy(avlnode(avl, offset_key), key, size); ret = avl_insert(avl, root, &offset_this, comp[type]); if (ret != -1) { @@ -441,47 +444,55 @@ } } -static void to_be_avltree(avl_t* avl, uint32_t offset, dic_table_t* dic_table, int index, int level) +static uint32_t to_be_avltree(avl_t* avl, uint32_t offset, dic_table_t* dic_table, int index, int level) { - avlnode_t* nbe = avlnode(avl, offset); - avlnode_t node = *nbe; + avlnode_t* node = avlnode(avl, offset); int field = dic_table->indices[index].fields[level]; int type = dic_table->fields[field].type; + uint32_t height = 1; - /* Convert the current node. */ - to_uint32be(&nbe->left); - to_uint32be(&nbe->right); - to_uint32be(&nbe->balance); - to_uint32be(&nbe->tail); - /* Descend to the left node. */ - if (node.left) { - to_be_avltree(avl, node.left, dic_table, index, level); + if (node->left) { + uint32_t new_height = to_be_avltree(avl, node->left, dic_table, index, level) + 1; + if (height < new_height) { + height = new_height; + } } + /* Descend to the right node. */ + if (node->right) { + uint32_t new_height = to_be_avltree(avl, node->right, dic_table, index, level) + 1; + if (height < new_height) { + height = new_height; + } + } + + /* Overwrite the balance field with the height of the current node. */ + node->balance = height; + /* Convert the key value. */ switch (type) { case IP3DBVT_BYTE: break; case IP3DBVT_WORD: - to_uint16be((uint16_t*)(nbe+1)); + to_uint16be((uint16_t*)(node+1)); break; case IP3DBVT_DWORD: - to_uint32be((uint32_t*)(nbe+1)); + to_uint32be((uint32_t*)(node+1)); break; case IP3DBVT_STRING: - to_ucs2be_string((ucs2char_t*)(nbe+1)); + to_ucs2be_string((ucs2char_t*)(node+1)); break; } /* Convert the sub AVL trees or tail. */ - if (node.tail) { + if (node->tail) { if (level+1 < IP3DBIDX_MAX_KEYLEVEL && dic_table->indices[index].fields[level+1] != -1) { /* Convert the AVL tree in the next level. */ - to_be_avltree(avl, node.tail, dic_table, index, level+1); + to_be_avltree(avl, node->tail, dic_table, index, level+1); } else { /* Convert the tail. */ - avltail_t* tbe = (avltail_t*)avlnode(avl, node.tail); + avltail_t* tbe = (avltail_t*)avlnode(avl, node->tail); avltail_t tail = *tbe; for (;;) { from_uint32be(&tbe->next); @@ -495,10 +506,12 @@ } } - /* Descend to the right node. */ - if (node.right) { - to_be_avltree(avl, node.right, dic_table, index, level); - } + /* Convert the current node. */ + to_uint32be(&node->left); + to_uint32be(&node->right); + to_uint32be(&node->balance); + to_uint32be(&node->tail); + return height; } static void fprinti(FILE *fp, int n) @@ -526,6 +539,8 @@ fprinti(fpo, indent); fprintf(fpo, " right: 0x%08X\n", node->right); fprinti(fpo, indent); + fprintf(fpo, " height: 0x%08X\n", node->balance); + fprinti(fpo, indent); fprintf(fpo, " tail: 0x%08X\n", node->tail); fprinti(fpo, indent); fprintf(fpo, " key: "); @@ -658,6 +673,8 @@ int i; idx_header_t* header = (idx_header_t*)idx->buffer; + header->size = idx->avl->offset; + /* Convert the byte order of the header from big endian to the native one. */ to_uint32be(&header->size); to_uint32be(&header->unknown1); @@ -718,7 +735,7 @@ uint32_t offset = 0; int field = dictbl->indices[index].fields[level]; int type = dictbl->fields[field].type; - int ret = avl_insert_key(idx->avl, &entry->fields[field].value, type, &offset, root); + int ret = avl_insert_key(idx->avl, &entry->fields[field], type, &offset, root); if (level+1 < IP3DBIDX_MAX_KEYLEVEL && dictbl->indices[index].fields[level+1] != -1) { avlnode_t* node = avlnode(idx->avl, offset); idx_insert_dat(idx, dictbl, &node->tail, entry, index, level+1); @@ -752,13 +769,13 @@ idx->avl->size = idx->max_size; for (index = 0;index < dic->music.num_indices;++index) { - uint32_t root = dic_get_idxroot(dic, IP3DBIDX_MUSIC, index); + uint32_t root = 0; idx_construct_index(idx, &dic->music, &dat->musics, &root, index); dic_set_idxroot(dic, IP3DBIDX_MUSIC, index, root); } for (index = 0;index < dic->objects.num_indices;++index) { - uint32_t root = dic_get_idxroot(dic, IP3DBIDX_OBJECTS, index); + uint32_t root = 0; idx_construct_index(idx, &dic->objects, &dat->objects, &root, index); dic_set_idxroot(dic, IP3DBIDX_OBJECTS, index, root); } Modified: trunk/pmplib/lib/pmp_iriverplus3/ip3db.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/ip3db.c 2006-12-27 11:40:38 UTC (rev 203) +++ trunk/pmplib/lib/pmp_iriverplus3/ip3db.c 2006-12-27 14:23:47 UTC (rev 204) @@ -40,6 +40,9 @@ { memset(var, 0, sizeof(*var)); var->type = type; + if (var->type == IP3DBVT_STRING) { + var->value.str = mbsdupucs2(""); + } } void ip3db_variant_finish(ip3db_variant_t* var) @@ -204,6 +207,11 @@ ip3db_finish(db); return 1; } + + fp = ucs2fopen(dicfn, "wb"); + if (!fp) { + return 1; + } fwrite(db->dic_buffer, 1, db->dic_size, fp); fclose(fp); Modified: trunk/pmplib/lib/pmp_iriverplus3/ip3db.h =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/ip3db.h 2006-12-27 11:40:38 UTC (rev 203) +++ trunk/pmplib/lib/pmp_iriverplus3/ip3db.h 2006-12-27 14:23:47 UTC (rev 204) @@ -171,6 +171,7 @@ void ip3db_init(ip3db_t* db); void ip3db_finish(ip3db_t* db); result_t ip3db_read(ip3db_t* db, const ucs2char_t* datfn, const ucs2char_t* dicfn, const ucs2char_t* idxfn); +result_t ip3db_write(ip3db_t* db, const ucs2char_t* datfn, const ucs2char_t* dicfn, const ucs2char_t* idxfn); result_t ip3db_dump(ip3db_t* db, FILE *fpo); void ip3db_record_init(ip3db_t* db, ip3db_music_record_t* record); Modified: trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c =================================================================== --- trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c 2006-12-27 11:40:38 UTC (rev 203) +++ trunk/pmplib/lib/pmp_iriverplus3/pmp_iriverplus3.c 2006-12-27 14:23:47 UTC (rev 204) @@ -505,6 +505,16 @@ ); } +static ucs2char_t* _filepath_removeslash(ucs2char_t* path) +{ + size_t length = ucs2len(path)-1; + while (length >= 0 && path[length] == PATHCHAR) { + path[length] = 0; + length--; + } + return (path + length); +} + static result_t pmpdb_set(pmpdb_t* pmpdb, const pmp_record_t* records, uint32_t num_records) { int i; @@ -515,7 +525,7 @@ ip3db_music_record_t* array = (ip3db_music_record_t*)malloc(sizeof(ip3db_music_record_t) * num_records); ucs2cpy(path_to_root, pmpi->env.path_to_root); - filepath_removeslash(path_to_root); + _filepath_removeslash(path_to_root); for (i = 0;i < num_records;++i) { const pmp_record_t* src = &records[i]; @@ -527,6 +537,16 @@ filepath_addslash(dst[IP3DBF_MUSIC_FILEPATH].value.str); filepath_encode(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); + ip3db_variant_set_word(&dst[IP3DBF_MUSIC_FILEFORMAT], 3); + 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_UID], (uint32_t)i+1); } ip3db_set(&pmpdbi->ip3db, array, num_records); free(array); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |