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
) {
127 fl
= fopen(fname
, "r");
128 if (fl
== NULL
) return -1; // no tags
130 if (fread(sign
, 4, 1, fl
) != 1) goto error
;
131 #ifdef USE_DEVID_INODE
132 if (memcmp(sign
, "MTD0", 4) != 0) goto error
;
134 if (memcmp(sign
, "MTD2", 4) != 0) goto error
;
136 if (fread(&file_count
, 4, 1, fl
) != 1) goto error
;
137 if (fread(&tag_count
, 4, 1, fl
) != 1) goto error
;
138 if (fread(&string_bytes
, 4, 1, fl
) != 1) goto error
;
139 if (fread(&tfl_bytes
, 4, 1, fl
) != 1) goto error
;
140 if (fread(&o_tag_count
, 4, 1, fl
) != 1) goto error
;
141 if (fread(&t_tag_count
, 4, 1, fl
) != 1) goto error
;
143 //dlogf("%u\n", sizeof(fl_tagvalue_t));
144 dlogf("file_count=%u\n", file_count
);
145 dlogf("tag_count=%u\n", tag_count
);
146 dlogf("string_bytes=%u\n", string_bytes
);
147 dlogf("tfl_bytes=%u\n", tfl_bytes
);
148 dlogf("o_tag_count=%u\n", o_tag_count
);
149 dlogf("t_tag_count=%u\n", t_tag_count
);
151 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
153 printf("loading %u files...\n", (unsigned int)file_count
);
154 dlogf("loading strings...\n");
155 if ((string_data
= malloc(string_bytes
)) == NULL
) goto error
;
156 if (fread(string_data
, string_bytes
, 1, fl
) != 1) goto error
;
158 dlogf("loading taglisto...\n");
159 if ((taglisto_data
= malloc(o_tag_count
*sizeof(uint32_t))) == NULL
) goto error
;
160 if (fread(taglisto_data
, o_tag_count
*sizeof(uint32_t), 1, fl
) != 1) goto error
;
162 dlogf("loading taglistt...\n");
163 if ((taglistt_data
= malloc(t_tag_count
*sizeof(uint32_t))) == NULL
) goto error
;
164 if (fread(taglistt_data
, t_tag_count
*sizeof(uint32_t), 1, fl
) != 1) goto error
;
166 dlogf("loading fileinfo...\n");
167 if ((fileinfo_data
= malloc(file_count
*sizeof(fl_fileinfo_t
))) == NULL
) goto error
;
168 if (fread(fileinfo_data
, file_count
*sizeof(fl_fileinfo_t
), 1, fl
) != 1) goto error
;
170 dlogf("loading taginfo...\n");
171 if ((tagvalue_data
= malloc(tag_count
*sizeof(fl_tagvalue_t
))) == NULL
) goto error
;
172 if (fread(tagvalue_data
, tag_count
*sizeof(fl_tagvalue_t
), 1, fl
) != 1) goto error
;
174 dlogf("loading tfl...\n");
175 if ((tfl_data
= malloc(tfl_bytes
)) == NULL
) goto error
;
176 if (fread(tfl_data
, tfl_bytes
, 1, fl
) != 1) goto error
;