summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-07-03 21:08:16 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-07-03 21:08:16 +0000
commit765cd6d5e74426df6a087cb8ff9ef8872ea7dadd (patch)
tree785587817df258a024933b01092da98aec5e6127
parent0a9dec60b58cd63aaa7048d0d348b93187f5aa51 (diff)
downloadrockbox-765cd6d5e74426df6a087cb8ff9ef8872ea7dadd.tar.gz
rockbox-765cd6d5e74426df6a087cb8ff9ef8872ea7dadd.zip
(in theory) more efficient (battery wise) runtime database code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6999 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/database.c239
-rw-r--r--apps/database.h22
-rw-r--r--apps/playback.h2
-rw-r--r--firmware/export/id3.h13
4 files changed, 159 insertions, 117 deletions
diff --git a/apps/database.c b/apps/database.c
index ad97b55ee7..50f8b80ac9 100644
--- a/apps/database.c
+++ b/apps/database.c
@@ -48,21 +48,23 @@
48 48
49/* internal functions */ 49/* internal functions */
50void writetagdbheader(void); 50void writetagdbheader(void);
51void writefentry(void); 51void writefentry(struct mp3entry *id);
52void getfentrybyoffset(int offset); 52void getfentrybyoffset(struct mp3entry *id,int offset);
53void update_fentryoffsets(int start, int end); 53void update_fentryoffsets(int start, int end);
54void writerundbheader(void); 54void writerundbheader(void);
55void getrundbentrybyoffset(int offset); 55void getrundbentrybyoffset(struct mp3entry *id,int offset);
56void writerundbentry(void); 56void writerundbentry(struct mp3entry *id);
57int getfentrybyfilename(char *fname); 57int getfentrybyfilename(struct mp3entry *id);
58void clearfileentryinfo(struct mp3entry *id);
59void clearruntimeinfo(struct mp3entry *id);
60int findrundbentry(struct mp3entry *id);
61
58int getfentrybyhash(int hash); 62int getfentrybyhash(int hash);
59int deletefentry(char *fname); 63int deletefentry(char *fname);
60int tagdb_shiftdown(int targetoffset, int startingoffset, int bytes); 64int tagdb_shiftdown(int targetoffset, int startingoffset, int bytes);
61int tagdb_shiftup(int targetoffset, int startingoffset, int bytes); 65int tagdb_shiftup(int targetoffset, int startingoffset, int bytes);
62 66
63static char sbuf[1024]; 67static char sbuf[MAX_PATH];
64static struct file_entry fe;
65static long currentfeoffset, currentferecord;
66 68
67int tagdb_fd = -1; 69int tagdb_fd = -1;
68int tagdb_initialized = 0; 70int tagdb_initialized = 0;
@@ -133,36 +135,42 @@ void writetagdbheader(void)
133 fsync(tagdb_fd); 135 fsync(tagdb_fd);
134} 136}
135 137
136void writefentry(void) 138void writefentry(struct mp3entry *id)
137{ 139{ long temp;
138 lseek(tagdb_fd,currentfeoffset,SEEK_SET); 140 if(!id->fileentryoffset)
139 write(tagdb_fd,sbuf,tagdbheader.filelen); 141 return;
140 write(tagdb_fd,&fe.hash,12); 142 lseek(tagdb_fd,id->fileentryoffset,SEEK_SET);
141 fsync(tagdb_fd); 143 write(tagdb_fd,id->path,tagdbheader.filelen);
144 temp=id->filehash;
145 write(tagdb_fd,&temp,4);
146 temp=id->songentryoffset;
147 write(tagdb_fd,&temp,4);
148 temp=id->rundbentryoffset;
149 write(tagdb_fd,&temp,4);
142} 150}
143 151
144void getfentrybyoffset(int offset) 152void getfentrybyoffset(struct mp3entry *id,int offset)
145{ 153{
146 memset(&fe,0,sizeof(struct file_entry)); 154 clearfileentryinfo(id);
147 lseek(tagdb_fd,offset,SEEK_SET); 155 lseek(tagdb_fd,offset,SEEK_SET);
148 read(tagdb_fd,sbuf,tagdbheader.filelen); 156 read(tagdb_fd,sbuf,tagdbheader.filelen);
149 read(tagdb_fd,&fe.hash,12); 157 id->fileentryoffset=offset;
150 fe.name=sbuf; 158 read(tagdb_fd,&id->filehash,4);
151 currentfeoffset=offset; 159 read(tagdb_fd,&id->songentryoffset,4);
152 currentferecord=(offset-tagdbheader.filestart)/FILEENTRY_SIZE; 160 read(tagdb_fd,&id->rundbentryoffset,4);
153} 161}
154 162
155#define getfentrybyrecord(_x_) getfentrybyoffset(FILERECORD2OFFSET(_x_)) 163#define getfentrybyrecord(_y_,_x_) getfentrybyoffset(_y_,FILERECORD2OFFSET(_x_))
156 164
157int getfentrybyfilename(char *fname) 165int getfentrybyfilename(struct mp3entry *id)
158{ 166{
159 int min=0; 167 int min=0;
160 int max=tagdbheader.filecount; 168 int max=tagdbheader.filecount;
161 while(min<max) { 169 while(min<max) {
162 int mid=(min+max)/2; 170 int mid=(min+max)/2;
163 int compare; 171 int compare;
164 getfentrybyrecord(mid); 172 getfentrybyrecord(id,mid);
165 compare=strcasecmp(fname,fe.name); 173 compare=strcasecmp(id->path,sbuf);
166 if(compare==0) 174 if(compare==0)
167 return 1; 175 return 1;
168 else if(compare<0) 176 else if(compare<0)
@@ -170,8 +178,10 @@ int getfentrybyfilename(char *fname)
170 else 178 else
171 min=mid+1; 179 min=mid+1;
172 } 180 }
181 clearfileentryinfo(id);
173 return 0; 182 return 0;
174} 183}
184
175#if 0 185#if 0
176int getfentrybyhash(int hash) 186int getfentrybyhash(int hash)
177{ 187{
@@ -292,16 +302,28 @@ int rundb_fd = -1;
292int rundb_initialized = 0; 302int rundb_initialized = 0;
293struct rundb_header rundbheader; 303struct rundb_header rundbheader;
294 304
295static long valid_file, currentreoffset,rundbsize; 305static long rundbsize;
296static struct rundb_entry rundbentry;
297 306
298/*** RuntimeDatabase code ***/ 307/*** RuntimeDatabase code ***/
299 308
300void rundb_track_changed(struct track_info *ti) 309void rundb_unbuffer_track(struct mp3entry *id, bool last_track) {
301{ 310 writeruntimeinfo(id);
302 increaseplaycount(); 311 if(last_track) {
303 logf("rundb new track: %s", ti->id3.path); 312 fsync(rundb_fd);
304 loadruntimeinfo(ti->id3.path); 313 fsync(tagdb_fd);
314 }
315}
316
317void rundb_track_change(struct track_info *ti) {
318 ti->id3.playcount++;
319}
320
321void rundb_buffer_track(struct mp3entry *id, bool last_track) {
322 loadruntimeinfo(id);
323 if(last_track) {
324 fsync(rundb_fd);
325 fsync(tagdb_fd);
326 }
305} 327}
306 328
307int rundb_init(void) 329int rundb_init(void)
@@ -354,8 +376,9 @@ int rundb_init(void)
354 } 376 }
355 377
356 rundb_initialized = 1; 378 rundb_initialized = 1;
357 audio_set_track_changed_event(&rundb_track_changed); 379 audio_set_track_buffer_event(&rundb_buffer_track);
358 memset(&rundbentry,0,sizeof(struct rundb_entry)); 380 audio_set_track_changed_event(&rundb_track_change);
381 audio_set_track_unbuffer_event(&rundb_unbuffer_track);
359 rundbsize=lseek(rundb_fd,0,SEEK_END); 382 rundbsize=lseek(rundb_fd,0,SEEK_END);
360 return 0; 383 return 0;
361#endif 384#endif
@@ -366,106 +389,128 @@ void rundb_shutdown(void)
366 if (rundb_fd >= 0) 389 if (rundb_fd >= 0)
367 close(rundb_fd); 390 close(rundb_fd);
368 rundb_initialized = 0; 391 rundb_initialized = 0;
392 audio_set_track_buffer_event(NULL);
393 audio_set_track_unbuffer_event(NULL);
369} 394}
370 395
371void writerundbheader(void) 396void writerundbheader(void)
372{ 397{
373 lseek(rundb_fd,0,SEEK_SET); 398 lseek(rundb_fd,0,SEEK_SET);
374 write(rundb_fd, &rundbheader, 8); 399 write(rundb_fd, &rundbheader, 8);
375 fsync(rundb_fd);
376} 400}
377 401
378#define getrundbentrybyrecord(_x_) getrundbentrybyoffset(8+_x_*20) 402#define getrundbentrybyrecord(_y_,_x_) getrundbentrybyoffset(_y_,8+_x_*20)
379 403
380void getrundbentrybyoffset(int offset) { 404void getrundbentrybyoffset(struct mp3entry *id,int offset) {
381 lseek(rundb_fd,offset,SEEK_SET); 405 lseek(rundb_fd,offset+4,SEEK_SET); // skip fileentry offset
382 read(rundb_fd,&rundbentry,20); 406 id->rundbentryoffset=offset;
383 currentreoffset=offset; 407 read(rundb_fd,&id->rundbhash,4);
408 read(rundb_fd,&id->rating,2);
409 read(rundb_fd,&id->voladjust,2);
410 read(rundb_fd,&id->playcount,4);
411 read(rundb_fd,&id->lastplayed,4);
384#ifdef ROCKBOX_LITTLE_ENDIAN 412#ifdef ROCKBOX_LITTLE_ENDIAN
385 rundbentry.fileentry=BE32(rundbentry.fileentry); 413 id->rundbhash=BE32(id->rundbhash);
386 rundbentry.hash=BE32(rundbentry.hash); 414 id->rating=BE16(id->rating);
387 rundbentry.rating=BE16(rundbentry.rating); 415 id->voladjust=BE16(id->voladjust);
388 rundbentry.voladjust=BE16(rundbentry.voladjust); 416 id->playcount=BE32(id->playcount);
389 rundbentry.playcount=BE32(rundbentry.playcount); 417 id->lastplayed=BE32(id->lastplayed);
390 rundbentry.lastplayed=BE32(rundbentry.lastplayed);
391#endif 418#endif
392} 419}
393 420
394int getrundbentrybyhash(int hash) 421int getrundbentrybyhash(struct mp3entry *id)
395{ 422{
396 int min=0; 423 int min=0;
397 for(min=0;min<rundbheader.entrycount;min++) { 424 for(min=0;min<rundbheader.entrycount;min++) {
398 getrundbentrybyrecord(min); 425 getrundbentrybyrecord(id,min);
399 if(hash==rundbentry.hash) 426 if(id->filehash==id->rundbhash)
400 return 1; 427 return 1;
401 } 428 }
402 memset(&rundbentry,0,sizeof(struct rundb_entry)); 429 clearruntimeinfo(id);
403 return 0; 430 return 0;
404} 431}
405 432
406void writerundbentry(void) 433void writerundbentry(struct mp3entry *id)
407{ 434{
408 if(rundbentry.hash==0) /* 0 = invalid rundb info. */ 435 if(id->rundbhash==0) /* 0 = invalid rundb info. */
409 return; 436 return;
410 lseek(rundb_fd,currentreoffset,SEEK_SET); 437 lseek(rundb_fd,id->rundbentryoffset,SEEK_SET);
411 write(rundb_fd,&rundbentry,20); 438 write(rundb_fd,&id->fileentryoffset,4);
412 fsync(rundb_fd); 439 write(rundb_fd,&id->rundbhash,4);
440 write(rundb_fd,&id->rating,2);
441 write(rundb_fd,&id->voladjust,2);
442 write(rundb_fd,&id->playcount,4);
443 write(rundb_fd,&id->lastplayed,4);
444}
445
446void writeruntimeinfo(struct mp3entry *id) {
447 if(!id->rundbhash)
448 addrundbentry(id);
449 else
450 writerundbentry(id);
451}
452
453void clearfileentryinfo(struct mp3entry *id) {
454 id->fileentryoffset=0;
455 id->filehash=0;
456 id->songentryoffset=0;
457 id->rundbentryoffset=0;
458}
459
460void clearruntimeinfo(struct mp3entry *id) {
461 id->rundbhash=0;
462 id->rating=0;
463 id->voladjust=0;
464 id->playcount=0;
465 id->lastplayed=0;
413} 466}
414 467
415void loadruntimeinfo(char *filename) 468void loadruntimeinfo(struct mp3entry *id)
416{ 469{
417 memset(&rundbentry,0,sizeof(struct rundb_entry)); 470 clearruntimeinfo(id);
418 valid_file=0; 471 clearfileentryinfo(id);
419 if(!getfentrybyfilename(filename)) 472 if(!getfentrybyfilename(id)) {
473 logf("tagdb fail: %s",id->path);
420 return; /* file is not in tagdatabase, could not load. */ 474 return; /* file is not in tagdatabase, could not load. */
421 valid_file=1; 475 }
422 if(fe.rundbentry!=-1&&fe.rundbentry<rundbsize) { 476 if(id->rundbentryoffset!=-1&&id->rundbentryoffset<rundbsize) {
423 logf("load rundbentry: 0x%x",fe.rundbentry); 477 logf("load rundbentry: 0x%x",id->rundbentryoffset);
424 getrundbentrybyoffset(fe.rundbentry); 478 getrundbentrybyoffset(id,id->rundbentryoffset);
425 if(fe.hash!=rundbentry.hash) { 479 if(id->filehash!=id->rundbhash) {
426 logf("Rundb: Hash mismatch. trying to repair entry.", 480 logf("Rundb: Hash mismatch. trying to repair entry.",
427 fe.hash,rundbentry.hash); 481 id->filehash,id->rundbhash);
428 addrundbentry(); 482 findrundbentry(id);
429 } 483 }
430 } 484 }
431 else /* add new rundb entry. */ 485 else {
432 addrundbentry(); 486 if(!findrundbentry(id))
487 logf("rundb:no entry and not found.");
488 }
433} 489}
434 490
435void addrundbentry() 491int findrundbentry(struct mp3entry *id) {
492 if(getrundbentrybyhash(id)) {
493 logf("Found existing rundb entry: 0x%x",id->rundbentryoffset);
494 writefentry(id);
495 return 1;
496 }
497 clearruntimeinfo(id);
498 return 0;
499}
500
501void addrundbentry(struct mp3entry *id)
436{ 502{
437 /* first search for an entry with an equal hash. */ 503 /* first search for an entry with an equal hash. */
438 if(getrundbentrybyhash(fe.hash)) { 504/* if(findrundbentry(id))
439 logf("Found existing rundb entry: 0x%x",currentreoffset); 505 return; disabled cause this SHOULD have been checked at the buffer event.. */
440 fe.rundbentry=currentreoffset;
441 writefentry();
442 return;
443 }
444 rundbheader.entrycount++; 506 rundbheader.entrycount++;
445 writerundbheader(); 507 writerundbheader();
446 fe.rundbentry=currentreoffset=lseek(rundb_fd,0,SEEK_END); 508 id->rundbentryoffset=lseek(rundb_fd,0,SEEK_END);
447 logf("Add rundb entry: 0x%x hash: 0x%x",fe.rundbentry,fe.hash); 509 logf("Add rundb entry: 0x%x hash: 0x%x",id->rundbentryoffset,id->filehash);
448 rundbentry.hash=fe.hash; 510 id->rundbhash=id->filehash;
449 rundbentry.fileentry=currentfeoffset; 511 writefentry(id);
450 writefentry(); 512 writerundbentry(id);
451 writerundbentry();
452 rundbsize=lseek(rundb_fd,0,SEEK_END); 513 rundbsize=lseek(rundb_fd,0,SEEK_END);
453} 514}
454 515
455void increaseplaycount(void)
456{
457 if(rundbentry.hash==0) /* 0 = invalid rundb info. */
458 return;
459 rundbentry.playcount++;
460 writerundbentry();
461}
462
463void setrating(int rating)
464{
465 if(rundbentry.hash==0) /* 0 = invalid rundb info. */
466 return;
467 rundbentry.rating=rating;
468 writerundbentry();
469}
470
471/*** end RuntimeDatabase code ***/ 516/*** end RuntimeDatabase code ***/
diff --git a/apps/database.h b/apps/database.h
index a0e029072c..3c9bef516c 100644
--- a/apps/database.h
+++ b/apps/database.h
@@ -59,13 +59,6 @@ struct tagdb_header {
59 int rundbdirty; 59 int rundbdirty;
60}; 60};
61 61
62struct file_entry {
63 char *name;
64 int hash;
65 int songentry;
66 int rundbentry;
67};
68
69extern struct tagdb_header tagdbheader; 62extern struct tagdb_header tagdbheader;
70extern int tagdb_fd; 63extern int tagdb_fd;
71 64
@@ -82,24 +75,15 @@ struct rundb_header {
82 int entrycount; 75 int entrycount;
83}; 76};
84 77
85struct rundb_entry {
86 int fileentry;
87 int hash;
88 short rating;
89 short voladjust;
90 int playcount;
91 int lastplayed;
92};
93 78
94extern struct rundb_header rundbheader; 79extern struct rundb_header rundbheader;
95 80
96#define RUNDB_VERSION 1 81#define RUNDB_VERSION 1
97 82
98void tagdb_shutdown(void); 83void tagdb_shutdown(void);
99void addrundbentry(void); 84void addrundbentry(struct mp3entry *id);
100void loadruntimeinfo(char *filename); 85void loadruntimeinfo(struct mp3entry *id);
101void increaseplaycount(void); 86void writeruntimeinfo(struct mp3entry *id);
102void setrating(int rating);
103int rundb_init(void); 87int rundb_init(void);
104void rundb_shutdown(void); 88void rundb_shutdown(void);
105#endif 89#endif
diff --git a/apps/playback.h b/apps/playback.h
index b00d5c3e0e..48d533f138 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -65,7 +65,7 @@ struct track_info {
65void audio_set_track_changed_event(void (*handler)(struct track_info *ti)); 65void audio_set_track_changed_event(void (*handler)(struct track_info *ti));
66void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3, 66void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
67 bool last_track)); 67 bool last_track));
68void audio_set_track_unbufer_event(void (*handler)(struct mp3entry *id3, 68void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
69 bool last_track)); 69 bool last_track));
70void audio_invalidate_tracks(void); 70void audio_invalidate_tracks(void);
71 71
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 99999817c2..a1fff903f0 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -94,6 +94,19 @@ struct mp3entry {
94 /* resume related */ 94 /* resume related */
95 int offset; /* bytes played */ 95 int offset; /* bytes played */
96 int index; /* playlist index */ 96 int index; /* playlist index */
97
98 /* FileEntry fields */
99 long fileentryoffset;
100 long filehash;
101 long songentryoffset;
102 long rundbentryoffset;
103
104 /* runtime database fields */
105 long rundbhash;
106 short rating;
107 short voladjust;
108 long playcount;
109 long lastplayed;
97}; 110};
98 111
99enum { 112enum {