Added note about 2.5 being Archos only
[kugel-rb.git] / apps / tagdb / song.c
blob16ae385edac27d3c65284453fd090decd7dce9e9
1 #include "malloc.h" // realloc() and free()
2 #include <string.h> // strncasecmp()
4 #include "song.h"
6 // how is our flag organized?
7 #define FLAG ( 0xCF )
8 #define FLAG_VALID(flag) (flag == 0xCF)
10 static int do_resize(struct song_entry *e, const uint32_t name_len, const uint32_t genre_len, const int zero_fill);
12 struct song_entry* new_song_entry(const uint32_t name_len, const uint32_t genre_len) {
13 // Start my allocating memory
14 struct song_entry *e = (struct song_entry*)malloc(sizeof(struct song_entry));
15 if( e == NULL ) {
16 DEBUGF("new_song_entry: could not allocate memory\n");
17 return NULL;
20 // We begin empty
21 e->name = NULL;
22 e->size.name_len = 0;
24 e->artist = 0;
25 e->album = 0;
26 e->file = 0;
28 e->genre = NULL;
29 e->size.genre_len = 0;
31 e->bitrate = 0;
32 e->year = 0;
33 e->playtime = 0;
34 e->track = 0;
35 e->samplerate = 0;
37 e->flag = FLAG;
39 // and resize to the requested size
40 if( do_resize(e, name_len, genre_len, 1) ) {
41 free(e);
42 return NULL;
44 return e;
47 int song_entry_destruct(struct song_entry *e) {
48 assert(e != NULL);
49 assert(FLAG_VALID(e->flag));
51 free(e->name);
52 free(e->genre);
54 free(e);
56 return ERR_NONE;
59 static int do_resize(struct song_entry *e, const uint32_t name_len, const uint32_t genre_len, const int zero_fill) {
60 void* temp;
62 assert(e != NULL);
63 assert(FLAG_VALID(e->flag));
65 // begin with name
66 if( name_len != e->size.name_len ) {
67 temp = realloc(e->name, name_len);
68 if(temp == NULL && name_len > 0) { // if realloc(,0) don't complain about NULL-pointer
69 DEBUGF("song_entry_resize: out of memory to resize name\n");
70 return ERR_MALLOC;
72 e->name = (char*)temp;
74 // if asked, fill it with zero's
75 if( zero_fill ) {
76 uint32_t i;
77 for(i=e->size.name_len; i<name_len; i++)
78 e->name[i] = (char)0x00;
81 e->size.name_len = name_len;
84 // now the genre
85 if( genre_len != e->size.genre_len ) {
86 temp = realloc(e->genre, genre_len);
87 if(temp == NULL && genre_len > 0) { // if realloc(,0) don't complain about NULL-pointer
88 DEBUGF("song_entry_resize: out of memory to resize genre\n");
89 return ERR_MALLOC;
91 e->genre = (char*)temp;
93 // if asked, fill it with zero's
94 if( zero_fill ) {
95 uint32_t i;
96 for(i=e->size.genre_len; i<genre_len; i++)
97 e->genre[i] = (char)0x00;
100 e->size.genre_len = genre_len;
103 return ERR_NONE;
106 inline int song_entry_resize(struct song_entry *e, const uint32_t name_len, const uint32_t genre_len) {
107 return do_resize(e, name_len, genre_len, 1);
110 int song_entry_serialize(FILE *fd, const struct song_entry *e) {
111 assert(fd != NULL);
112 assert(e != NULL);
113 assert(FLAG_VALID(e->flag));
115 // First byte we write is a flag-byte to indicate this is a valid record
116 if( fwrite(&e->flag, 1, 1, fd) != 1 ) {
117 DEBUGF("song_entry_serialize: failed to write flag-byte\n");
118 return ERR_FILE;
121 // Write the length of the name field
122 if( fwrite(&e->size.name_len, sizeof(e->size.name_len), 1, fd) != 1 ) {
123 DEBUGF("song_entry_serialize: failed to write name_len\n");
124 return ERR_FILE;
127 // now the name field itself
128 if( fwrite(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
129 DEBUGF("song_entry_serialize: failed to write name\n");
130 return ERR_FILE;
133 // Artist field
134 if( fwrite(&e->artist, sizeof(e->artist), 1, fd) != 1 ) {
135 DEBUGF("song_entry_serialize: failed to write artist\n");
136 return ERR_FILE;
139 // Album field
140 if( fwrite(&e->album, sizeof(e->album), 1, fd) != 1 ) {
141 DEBUGF("song_entry_serialize: failed to write album\n");
142 return ERR_FILE;
145 // File field
146 if( fwrite(&e->file, sizeof(e->file), 1, fd) != 1 ) {
147 DEBUGF("song_entry_serialize: failed to write file\n");
148 return ERR_FILE;
151 // length of genre field
152 if( fwrite(&e->size.genre_len, sizeof(e->size.genre_len), 1, fd) != 1 ) {
153 DEBUGF("song_entry_serialize: failed to write genre_len\n");
154 return ERR_FILE;
157 // genre itself
158 if( fwrite(e->genre, 1, e->size.genre_len, fd) != e->size.genre_len ) {
159 DEBUGF("song_entry_serialize: failed to write genre\n");
160 return ERR_FILE;
163 // Bitrate field
164 if( fwrite(&e->bitrate, sizeof(e->bitrate), 1, fd) != 1 ) {
165 DEBUGF("song_entry_serialize: failed to write bitrate\n");
166 return ERR_FILE;
169 // Year field
170 if( fwrite(&e->year, sizeof(e->year), 1, fd) != 1 ) {
171 DEBUGF("song_entry_serialize: failed to write year\n");
172 return ERR_FILE;
175 // Playtime field
176 if( fwrite(&e->playtime, sizeof(e->playtime), 1, fd) != 1 ) {
177 DEBUGF("song_entry_serialize: failed to write playtime\n");
178 return ERR_FILE;
181 // Track field
182 if( fwrite(&e->track, sizeof(e->track), 1, fd) != 1 ) {
183 DEBUGF("song_entry_serialize: failed to write track\n");
184 return ERR_FILE;
187 // Samplerate field
188 if( fwrite(&e->samplerate, sizeof(e->samplerate), 1, fd) != 1 ) {
189 DEBUGF("song_entry_serialize: failed to write samplerate\n");
190 return ERR_FILE;
193 return ERR_NONE;
196 int song_entry_unserialize(struct song_entry **dest, FILE *fd) {
197 uint32_t length;
198 struct song_entry* e;
200 assert(dest != NULL);
201 assert(fd != NULL);
203 // Allocate memory
204 e = new_song_entry(0, 0);
205 if( e == NULL ) {
206 DEBUGF("song_entry_unserialize: could not create new song_entry\n");
207 return ERR_MALLOC;
210 // First we read the length of the name field
211 if( fread(&length, sizeof(length), 1, fd) != 1 ) {
212 DEBUGF("song_entry_unserialize: failed to read name_len\n");
213 song_entry_destruct(e);
214 return ERR_FILE;
217 // allocate memory for the upcomming name-field
218 if( do_resize(e, length, 0, 0) ) {
219 DEBUGF("song_entry_unserialize: failed to allocate memory for name\n");
220 song_entry_destruct(e);
221 return ERR_MALLOC;
224 // read it in
225 if( fread(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
226 DEBUGF("song_entry_unserialize: failed to read name\n");
227 song_entry_destruct(e);
228 return ERR_FILE;
231 // Artist field
232 if( fread(&e->artist, sizeof(e->artist), 1, fd) != 1 ) {
233 DEBUGF("song_entry_unserialize: failed to read artist\n");
234 song_entry_destruct(e);
235 return ERR_FILE;
238 // Album field
239 if( fread(&e->album, sizeof(e->album), 1, fd) != 1 ) {
240 DEBUGF("song_entry_unserialize: failed to read album\n");
241 song_entry_destruct(e);
242 return ERR_FILE;
245 // File field
246 if( fread(&e->file, sizeof(e->file), 1, fd) != 1 ) {
247 DEBUGF("song_entry_unserialize: failed to read file\n");
248 song_entry_destruct(e);
249 return ERR_FILE;
252 // Next the length of genre
253 if( fread(&length, sizeof(length), 1, fd) != 1 ) {
254 DEBUGF("song_entry_unserialize: failed to read genre_len\n");
255 song_entry_destruct(e);
256 return ERR_FILE;
259 // allocate memory for the upcomming name-field
260 if( do_resize(e, e->size.name_len, length, 0) ) {
261 DEBUGF("song_entry_unserialize: failed to allocate memory for song\n");
262 song_entry_destruct(e);
263 return ERR_MALLOC;
266 // read it in
267 if( fread(e->genre, 1, e->size.genre_len, fd) != e->size.genre_len ) {
268 DEBUGF("song_entry_unserialize: failed to read genre\n");
269 song_entry_destruct(e);
270 return ERR_FILE;
273 // Bitrate field
274 if( fread(&e->bitrate, sizeof(e->bitrate), 1, fd) != 1 ) {
275 DEBUGF("song_entry_unserialize: failed to read bitrate\n");
276 song_entry_destruct(e);
277 return ERR_FILE;
280 // Year field
281 if( fread(&e->year, sizeof(e->year), 1, fd) != 1 ) {
282 DEBUGF("song_entry_unserialize: failed to read year\n");
283 song_entry_destruct(e);
284 return ERR_FILE;
287 // Playtime field
288 if( fread(&e->playtime, sizeof(e->playtime), 1, fd) != 1 ) {
289 DEBUGF("song_entry_unserialize: failed to read playtime\n");
290 song_entry_destruct(e);
291 return ERR_FILE;
294 // Track field
295 if( fread(&e->track, sizeof(e->track), 1, fd) != 1 ) {
296 DEBUGF("song_entry_unserialize: failed to read track\n");
297 song_entry_destruct(e);
298 return ERR_FILE;
301 // Samplerate field
302 if( fread(&e->samplerate, sizeof(e->samplerate), 1, fd) != 1 ) {
303 DEBUGF("song_entry_unserialize: failed to read samplerate\n");
304 song_entry_destruct(e);
305 return ERR_FILE;
308 *dest = e;
309 return ERR_NONE;
312 int song_entry_write(FILE *fd, struct song_entry *e, struct song_size *s) {
313 uint32_t be32;
314 uint16_t be16;
315 char pad = 0x00;
317 assert(fd != NULL);
318 assert(e != NULL);
319 assert(FLAG_VALID(e->flag));
321 // song name
322 if( fwrite(e->name, 1, e->size.name_len, fd) != e->size.name_len ) {
323 DEBUGF("song_entry_write: failed to write name\n");
324 return ERR_FILE;
326 // pad the rest (abuse be32 for counter)
327 be32 = e->size.name_len;
328 while( s != NULL && s->name_len > be32) {
329 if( fwrite(&pad, 1, 1, fd) == 1 ) {
330 be32++;
331 } else {
332 DEBUGF("genre_entry_write: failed to pad name\n");
333 return ERR_FILE;
337 // artist
338 be32 = BE32(e->artist);
339 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
340 DEBUGF("song_entry_write: failed to write artist\n");
341 return ERR_FILE;
344 // album
345 be32 = BE32(e->album);
346 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
347 DEBUGF("song_entry_write: failed to write album\n");
348 return ERR_FILE;
351 // file
352 be32 = BE32(e->file);
353 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
354 DEBUGF("song_entry_write: failed to write file\n");
355 return ERR_FILE;
358 // genre
359 if( fwrite(e->genre, 1, e->size.genre_len, fd) != e->size.genre_len ) {
360 DEBUGF("song_entry_write: failed to write genre\n");
361 return ERR_FILE;
363 // pad the rest (abuse be32 for counter)
364 be32 = e->size.genre_len;
365 while( s != NULL && s->genre_len > be32) {
366 if( fwrite(&pad, 1, 1, fd) == 1 ) {
367 be32++;
368 } else {
369 DEBUGF("genre_entry_write: failed to pad genre\n");
370 return ERR_FILE;
374 // bitrate
375 be16 = BE16(e->bitrate);
376 if( fwrite(&be16, sizeof(be16), 1, fd) != 1 ) {
377 DEBUGF("song_entry_write: failed to write bitrate\n");
378 return ERR_FILE;
381 // year
382 be16 = BE16(e->year);
383 if( fwrite(&be16, sizeof(be16), 1, fd) != 1 ) {
384 DEBUGF("song_entry_write: failed to write year\n");
385 return ERR_FILE;
388 // playtime
389 be32 = BE32(e->playtime);
390 if( fwrite(&be32, sizeof(be32), 1, fd) != 1 ) {
391 DEBUGF("song_entry_write: failed to write playtime\n");
392 return ERR_FILE;
395 // track
396 be16 = BE16(e->track);
397 if( fwrite(&be16, sizeof(be16), 1, fd) != 1 ) {
398 DEBUGF("song_entry_write: failed to write track\n");
399 return ERR_FILE;
402 // samplerate
403 be16 = BE16(e->samplerate);
404 if( fwrite(&be16, sizeof(be16), 1, fd) != 1 ) {
405 DEBUGF("song_entry_write: failed to write samplerate\n");
406 return ERR_FILE;
409 return ERR_NONE;
412 inline int song_entry_compare(const struct song_entry *a, const struct song_entry *b) {
413 assert(a != NULL);
414 assert(b != NULL);
415 return strncasecmp(a->name, b->name, (a->size.name_len <= b->size.name_len ? a->size.name_len : b->size.name_len) );
418 struct song_size* new_song_size() {
419 struct song_size *s;
420 s = (struct song_size*)malloc(sizeof(struct song_size));
421 if( s == NULL ) {
422 DEBUGF("new_song_size: failed to allocate memory\n");
423 return NULL;
425 s->name_len = 0;
426 s->genre_len = 0;
428 return s;
431 inline uint32_t song_size_get_length(const struct song_size *size) {
432 assert(size != NULL);
433 return size->name_len + size->genre_len + 6*4;
436 inline int song_size_max(struct song_size *s, const struct song_entry *e) {
437 assert(s != NULL);
438 assert(e != NULL);
439 assert(FLAG_VALID(e->flag));
440 s->name_len = ( s->name_len >= e->size.name_len ? s->name_len : e->size.name_len );
441 s->genre_len = ( s->genre_len >= e->size.genre_len ? s->genre_len : e->size.genre_len );
442 return ERR_NONE;
445 int song_size_destruct(struct song_size *s) {
446 assert(s != NULL);
447 // nothing to do...
448 free(s);
449 return ERR_NONE;