1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 ////////////////////////////////////////////////////////////////////////////////
18 // augment UTHASH with two more macrodefs
19 #define HASH_FIND_PTR_EX(hh,head,findptr,out) HASH_FIND(hh,head,findptr,sizeof(void *),out)
20 #define HASH_ADD_PTR_EX(hh,head,ptrfield,add) HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
22 #define HASH_FIND_STR_EX(hh,head,findstr,out) HASH_FIND(hh,head,findstr,strlen(findstr),out)
23 #define HASH_ADD_STR_EX(hh,head,strfield,add) HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
25 #define HASH_FIND_UINT32(head,findint,out) HASH_FIND(hh,head,findint,sizeof(uint32_t),out)
26 #define HASH_ADD_UINT32(head,intfield,add) HASH_ADD(hh,head,intfield,sizeof(uint32_t),add)
27 #define HASH_REPLACE_UINT32(head,intfield,add,replaced) HASH_REPLACE(hh,head,intfield,sizeof(uint32_t),add,replaced)
30 ////////////////////////////////////////////////////////////////////////////////
47 typedef struct __attribute__((packed
,gcc_struct
)) {
52 typedef struct __attribute__((packed
,gcc_struct
)) {
54 fl_tfl_t tfl
[TFL_MAX
];
58 typedef struct __attribute__((packed
,gcc_struct
)) {
61 #ifdef USE_DEVID_INODE
72 uint32_t artist_o
, artist_t
;
73 uint32_t album_o
, album_t
;
74 uint32_t title_o
, title_t
;
75 uint32_t genre_o
, genre_t
;
76 uint32_t yral_o
, yral_t
;
78 uint32_t tags
[TFL_MAX
];
83 ////////////////////////////////////////////////////////////////////////////////
84 static uint32_t file_count
= 0, tag_count
= 0, string_bytes
= 0, o_tag_count
= 0, t_tag_count
= 0, tfl_bytes
= 0;
85 static uint8_t *string_data
= NULL
;
86 static fl_fileinfo_t
*fileinfo_data
= NULL
;
87 static fl_tagvalue_t
*tagvalue_data
= NULL
;
88 static uint32_t *taglisto_data
= NULL
;
89 static uint32_t *taglistt_data
= NULL
;
90 static uint32_t *tfl_data
= NULL
;
92 static inline fl_tagvalue_t
*get_tv (uint32_t idx
) { return (idx
< tag_count
? &tagvalue_data
[idx
] : NULL
); }
93 static inline fl_fileinfo_t
*get_fi (uint32_t idx
) { return (idx
< file_count
? &fileinfo_data
[idx
] : NULL
); }
95 static inline uint32_t tv2idx (const fl_tagvalue_t
*tv
) { return (tv
!= NULL
? (uintptr_t)((const uint8_t *)tv
-(const uint8_t *)tagvalue_data
)/sizeof(*tv
) : 0); }
96 static inline uint32_t fi2idx (const fl_fileinfo_t
*fi
) { return (fi
!= NULL
? (uintptr_t)((const uint8_t *)fi
-(const uint8_t *)fileinfo_data
)/sizeof(*fi
) : 0); }
98 static inline char *get_str (uint32_t ofs
) { return (ofs
>= 2 && ofs
< string_bytes
? (char *)(string_data
+ofs
) : NULL
); }
99 static inline int get_strlen (uint32_t ofs
) { return (ofs
< string_bytes
? *((const uint16_t *)(string_data
+ofs
-2)) : 0); }
102 ////////////////////////////////////////////////////////////////////////////////
103 static void tagdb_unload (void) {
104 file_count
= tag_count
= string_bytes
= o_tag_count
= t_tag_count
= tfl_bytes
= 0;
105 if (string_data
!= NULL
) free(string_data
);
106 if (fileinfo_data
!= NULL
) free(fileinfo_data
);
107 if (tagvalue_data
!= NULL
) free(tagvalue_data
);
108 if (taglisto_data
!= NULL
) free(taglisto_data
);
109 if (taglistt_data
!= NULL
) free(taglistt_data
);
110 if (tfl_data
!= NULL
) free(tfl_data
);
113 fileinfo_data
= NULL
;
114 tagvalue_data
= NULL
;
115 taglisto_data
= NULL
;
116 taglistt_data
= NULL
;
121 ////////////////////////////////////////////////////////////////////////////////
122 static int tagdb_load (const char *fname
) {
126 #if defined(NDEBUG) && NDEBUG
127 # define showofs() ((void)0)
129 void showofs (void) {
130 dlogf("OFS: 0x%08x\n", (unsigned)ftell(fl
));
135 fl
= fopen(fname
, "r");
136 if (fl
== NULL
) return -1; // no tags
138 if (fread(sign
, 4, 1, fl
) != 1) goto error
;
139 #ifdef USE_DEVID_INODE
140 if (memcmp(sign
, "MTD0", 4) != 0) goto error
;
142 if (memcmp(sign
, "MTD2", 4) != 0) goto error
;
144 if (fread(&file_count
, 4, 1, fl
) != 1) goto error
;
145 if (fread(&tag_count
, 4, 1, fl
) != 1) goto error
;
146 if (fread(&string_bytes
, 4, 1, fl
) != 1) goto error
;
147 if (fread(&tfl_bytes
, 4, 1, fl
) != 1) goto error
;
148 if (fread(&o_tag_count
, 4, 1, fl
) != 1) goto error
;
149 if (fread(&t_tag_count
, 4, 1, fl
) != 1) goto error
;
151 //dlogf("%u\n", sizeof(fl_tagvalue_t));
152 dlogf("file_count=%u\n", file_count
);
153 dlogf("tag_count=%u\n", tag_count
);
154 dlogf("string_bytes=%u\n", string_bytes
);
155 dlogf("tfl_bytes=%u\n", tfl_bytes
);
156 dlogf("o_tag_count=%u\n", o_tag_count
);
157 dlogf("t_tag_count=%u\n", t_tag_count
);
159 if (file_count
< 1 || tag_count
< 1 || string_bytes
< 3 || tfl_bytes
< 1 || o_tag_count
< 1 || t_tag_count
< 1) goto error
; // invalid or empty file
161 printf("loading %u files...\n", (unsigned int)file_count
);
162 dlogf("loading strings...\n");
164 if ((string_data
= malloc(string_bytes
)) == NULL
) goto error
;
165 if (fread(string_data
, string_bytes
, 1, fl
) != 1) goto error
;
167 dlogf("loading taglisto...\n");
169 if ((taglisto_data
= malloc(o_tag_count
*sizeof(uint32_t))) == NULL
) goto error
;
170 if (fread(taglisto_data
, o_tag_count
*sizeof(uint32_t), 1, fl
) != 1) goto error
;
172 dlogf("loading taglistt...\n");
174 if ((taglistt_data
= malloc(t_tag_count
*sizeof(uint32_t))) == NULL
) goto error
;
175 if (fread(taglistt_data
, t_tag_count
*sizeof(uint32_t), 1, fl
) != 1) goto error
;
177 dlogf("loading fileinfo...\n");
179 if ((fileinfo_data
= malloc(file_count
*sizeof(fl_fileinfo_t
))) == NULL
) goto error
;
180 if (fread(fileinfo_data
, file_count
*sizeof(fl_fileinfo_t
), 1, fl
) != 1) goto error
;
182 dlogf("loading taginfo...\n");
184 if ((tagvalue_data
= malloc(tag_count
*sizeof(fl_tagvalue_t
))) == NULL
) goto error
;
185 if (fread(tagvalue_data
, tag_count
*sizeof(fl_tagvalue_t
), 1, fl
) != 1) goto error
;
187 dlogf("loading tfl...\n");
189 if ((tfl_data
= malloc(tfl_bytes
)) == NULL
) goto error
;
190 if (fread(tfl_data
, tfl_bytes
, 1, fl
) != 1) goto error
;