From 765cd6d5e74426df6a087cb8ff9ef8872ea7dadd Mon Sep 17 00:00:00 2001 From: Michiel Van Der Kolk Date: Sun, 3 Jul 2005 21:08:16 +0000 Subject: (in theory) more efficient (battery wise) runtime database code. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6999 a1c6a512-1295-4272-9138-f99709370657 --- apps/database.c | 239 ++++++++++++++++++++++++++++++-------------------- apps/database.h | 22 +---- apps/playback.h | 2 +- firmware/export/id3.h | 13 +++ 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 @@ /* internal functions */ void writetagdbheader(void); -void writefentry(void); -void getfentrybyoffset(int offset); +void writefentry(struct mp3entry *id); +void getfentrybyoffset(struct mp3entry *id,int offset); void update_fentryoffsets(int start, int end); void writerundbheader(void); -void getrundbentrybyoffset(int offset); -void writerundbentry(void); -int getfentrybyfilename(char *fname); +void getrundbentrybyoffset(struct mp3entry *id,int offset); +void writerundbentry(struct mp3entry *id); +int getfentrybyfilename(struct mp3entry *id); +void clearfileentryinfo(struct mp3entry *id); +void clearruntimeinfo(struct mp3entry *id); +int findrundbentry(struct mp3entry *id); + int getfentrybyhash(int hash); int deletefentry(char *fname); int tagdb_shiftdown(int targetoffset, int startingoffset, int bytes); int tagdb_shiftup(int targetoffset, int startingoffset, int bytes); -static char sbuf[1024]; -static struct file_entry fe; -static long currentfeoffset, currentferecord; +static char sbuf[MAX_PATH]; int tagdb_fd = -1; int tagdb_initialized = 0; @@ -133,36 +135,42 @@ void writetagdbheader(void) fsync(tagdb_fd); } -void writefentry(void) -{ - lseek(tagdb_fd,currentfeoffset,SEEK_SET); - write(tagdb_fd,sbuf,tagdbheader.filelen); - write(tagdb_fd,&fe.hash,12); - fsync(tagdb_fd); +void writefentry(struct mp3entry *id) +{ long temp; + if(!id->fileentryoffset) + return; + lseek(tagdb_fd,id->fileentryoffset,SEEK_SET); + write(tagdb_fd,id->path,tagdbheader.filelen); + temp=id->filehash; + write(tagdb_fd,&temp,4); + temp=id->songentryoffset; + write(tagdb_fd,&temp,4); + temp=id->rundbentryoffset; + write(tagdb_fd,&temp,4); } -void getfentrybyoffset(int offset) -{ - memset(&fe,0,sizeof(struct file_entry)); +void getfentrybyoffset(struct mp3entry *id,int offset) +{ + clearfileentryinfo(id); lseek(tagdb_fd,offset,SEEK_SET); read(tagdb_fd,sbuf,tagdbheader.filelen); - read(tagdb_fd,&fe.hash,12); - fe.name=sbuf; - currentfeoffset=offset; - currentferecord=(offset-tagdbheader.filestart)/FILEENTRY_SIZE; + id->fileentryoffset=offset; + read(tagdb_fd,&id->filehash,4); + read(tagdb_fd,&id->songentryoffset,4); + read(tagdb_fd,&id->rundbentryoffset,4); } -#define getfentrybyrecord(_x_) getfentrybyoffset(FILERECORD2OFFSET(_x_)) +#define getfentrybyrecord(_y_,_x_) getfentrybyoffset(_y_,FILERECORD2OFFSET(_x_)) -int getfentrybyfilename(char *fname) +int getfentrybyfilename(struct mp3entry *id) { int min=0; int max=tagdbheader.filecount; while(minpath,sbuf); if(compare==0) return 1; else if(compare<0) @@ -170,8 +178,10 @@ int getfentrybyfilename(char *fname) else min=mid+1; } + clearfileentryinfo(id); return 0; } + #if 0 int getfentrybyhash(int hash) { @@ -292,16 +302,28 @@ int rundb_fd = -1; int rundb_initialized = 0; struct rundb_header rundbheader; -static long valid_file, currentreoffset,rundbsize; -static struct rundb_entry rundbentry; +static long rundbsize; /*** RuntimeDatabase code ***/ -void rundb_track_changed(struct track_info *ti) -{ - increaseplaycount(); - logf("rundb new track: %s", ti->id3.path); - loadruntimeinfo(ti->id3.path); +void rundb_unbuffer_track(struct mp3entry *id, bool last_track) { + writeruntimeinfo(id); + if(last_track) { + fsync(rundb_fd); + fsync(tagdb_fd); + } +} + +void rundb_track_change(struct track_info *ti) { + ti->id3.playcount++; +} + +void rundb_buffer_track(struct mp3entry *id, bool last_track) { + loadruntimeinfo(id); + if(last_track) { + fsync(rundb_fd); + fsync(tagdb_fd); + } } int rundb_init(void) @@ -354,8 +376,9 @@ int rundb_init(void) } rundb_initialized = 1; - audio_set_track_changed_event(&rundb_track_changed); - memset(&rundbentry,0,sizeof(struct rundb_entry)); + audio_set_track_buffer_event(&rundb_buffer_track); + audio_set_track_changed_event(&rundb_track_change); + audio_set_track_unbuffer_event(&rundb_unbuffer_track); rundbsize=lseek(rundb_fd,0,SEEK_END); return 0; #endif @@ -366,106 +389,128 @@ void rundb_shutdown(void) if (rundb_fd >= 0) close(rundb_fd); rundb_initialized = 0; + audio_set_track_buffer_event(NULL); + audio_set_track_unbuffer_event(NULL); } void writerundbheader(void) { lseek(rundb_fd,0,SEEK_SET); write(rundb_fd, &rundbheader, 8); - fsync(rundb_fd); } -#define getrundbentrybyrecord(_x_) getrundbentrybyoffset(8+_x_*20) +#define getrundbentrybyrecord(_y_,_x_) getrundbentrybyoffset(_y_,8+_x_*20) -void getrundbentrybyoffset(int offset) { - lseek(rundb_fd,offset,SEEK_SET); - read(rundb_fd,&rundbentry,20); - currentreoffset=offset; +void getrundbentrybyoffset(struct mp3entry *id,int offset) { + lseek(rundb_fd,offset+4,SEEK_SET); // skip fileentry offset + id->rundbentryoffset=offset; + read(rundb_fd,&id->rundbhash,4); + read(rundb_fd,&id->rating,2); + read(rundb_fd,&id->voladjust,2); + read(rundb_fd,&id->playcount,4); + read(rundb_fd,&id->lastplayed,4); #ifdef ROCKBOX_LITTLE_ENDIAN - rundbentry.fileentry=BE32(rundbentry.fileentry); - rundbentry.hash=BE32(rundbentry.hash); - rundbentry.rating=BE16(rundbentry.rating); - rundbentry.voladjust=BE16(rundbentry.voladjust); - rundbentry.playcount=BE32(rundbentry.playcount); - rundbentry.lastplayed=BE32(rundbentry.lastplayed); + id->rundbhash=BE32(id->rundbhash); + id->rating=BE16(id->rating); + id->voladjust=BE16(id->voladjust); + id->playcount=BE32(id->playcount); + id->lastplayed=BE32(id->lastplayed); #endif } -int getrundbentrybyhash(int hash) +int getrundbentrybyhash(struct mp3entry *id) { int min=0; for(min=0;minfilehash==id->rundbhash) return 1; } - memset(&rundbentry,0,sizeof(struct rundb_entry)); + clearruntimeinfo(id); return 0; } -void writerundbentry(void) +void writerundbentry(struct mp3entry *id) { - if(rundbentry.hash==0) /* 0 = invalid rundb info. */ + if(id->rundbhash==0) /* 0 = invalid rundb info. */ return; - lseek(rundb_fd,currentreoffset,SEEK_SET); - write(rundb_fd,&rundbentry,20); - fsync(rundb_fd); + lseek(rundb_fd,id->rundbentryoffset,SEEK_SET); + write(rundb_fd,&id->fileentryoffset,4); + write(rundb_fd,&id->rundbhash,4); + write(rundb_fd,&id->rating,2); + write(rundb_fd,&id->voladjust,2); + write(rundb_fd,&id->playcount,4); + write(rundb_fd,&id->lastplayed,4); +} + +void writeruntimeinfo(struct mp3entry *id) { + if(!id->rundbhash) + addrundbentry(id); + else + writerundbentry(id); +} + +void clearfileentryinfo(struct mp3entry *id) { + id->fileentryoffset=0; + id->filehash=0; + id->songentryoffset=0; + id->rundbentryoffset=0; +} + +void clearruntimeinfo(struct mp3entry *id) { + id->rundbhash=0; + id->rating=0; + id->voladjust=0; + id->playcount=0; + id->lastplayed=0; } -void loadruntimeinfo(char *filename) +void loadruntimeinfo(struct mp3entry *id) { - memset(&rundbentry,0,sizeof(struct rundb_entry)); - valid_file=0; - if(!getfentrybyfilename(filename)) + clearruntimeinfo(id); + clearfileentryinfo(id); + if(!getfentrybyfilename(id)) { + logf("tagdb fail: %s",id->path); return; /* file is not in tagdatabase, could not load. */ - valid_file=1; - if(fe.rundbentry!=-1&&fe.rundbentryrundbentryoffset!=-1&&id->rundbentryoffsetrundbentryoffset); + getrundbentrybyoffset(id,id->rundbentryoffset); + if(id->filehash!=id->rundbhash) { logf("Rundb: Hash mismatch. trying to repair entry.", - fe.hash,rundbentry.hash); - addrundbentry(); + id->filehash,id->rundbhash); + findrundbentry(id); } } - else /* add new rundb entry. */ - addrundbentry(); + else { + if(!findrundbentry(id)) + logf("rundb:no entry and not found."); + } } -void addrundbentry() +int findrundbentry(struct mp3entry *id) { + if(getrundbentrybyhash(id)) { + logf("Found existing rundb entry: 0x%x",id->rundbentryoffset); + writefentry(id); + return 1; + } + clearruntimeinfo(id); + return 0; +} + +void addrundbentry(struct mp3entry *id) { /* first search for an entry with an equal hash. */ - if(getrundbentrybyhash(fe.hash)) { - logf("Found existing rundb entry: 0x%x",currentreoffset); - fe.rundbentry=currentreoffset; - writefentry(); - return; - } +/* if(findrundbentry(id)) + return; disabled cause this SHOULD have been checked at the buffer event.. */ rundbheader.entrycount++; writerundbheader(); - fe.rundbentry=currentreoffset=lseek(rundb_fd,0,SEEK_END); - logf("Add rundb entry: 0x%x hash: 0x%x",fe.rundbentry,fe.hash); - rundbentry.hash=fe.hash; - rundbentry.fileentry=currentfeoffset; - writefentry(); - writerundbentry(); + id->rundbentryoffset=lseek(rundb_fd,0,SEEK_END); + logf("Add rundb entry: 0x%x hash: 0x%x",id->rundbentryoffset,id->filehash); + id->rundbhash=id->filehash; + writefentry(id); + writerundbentry(id); rundbsize=lseek(rundb_fd,0,SEEK_END); } -void increaseplaycount(void) -{ - if(rundbentry.hash==0) /* 0 = invalid rundb info. */ - return; - rundbentry.playcount++; - writerundbentry(); -} - -void setrating(int rating) -{ - if(rundbentry.hash==0) /* 0 = invalid rundb info. */ - return; - rundbentry.rating=rating; - writerundbentry(); -} - /*** 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 { int rundbdirty; }; -struct file_entry { - char *name; - int hash; - int songentry; - int rundbentry; -}; - extern struct tagdb_header tagdbheader; extern int tagdb_fd; @@ -82,24 +75,15 @@ struct rundb_header { int entrycount; }; -struct rundb_entry { - int fileentry; - int hash; - short rating; - short voladjust; - int playcount; - int lastplayed; -}; extern struct rundb_header rundbheader; #define RUNDB_VERSION 1 void tagdb_shutdown(void); -void addrundbentry(void); -void loadruntimeinfo(char *filename); -void increaseplaycount(void); -void setrating(int rating); +void addrundbentry(struct mp3entry *id); +void loadruntimeinfo(struct mp3entry *id); +void writeruntimeinfo(struct mp3entry *id); int rundb_init(void); void rundb_shutdown(void); #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 { void audio_set_track_changed_event(void (*handler)(struct track_info *ti)); void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3, bool last_track)); -void audio_set_track_unbufer_event(void (*handler)(struct mp3entry *id3, +void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3, bool last_track)); void audio_invalidate_tracks(void); 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 { /* resume related */ int offset; /* bytes played */ int index; /* playlist index */ + + /* FileEntry fields */ + long fileentryoffset; + long filehash; + long songentryoffset; + long rundbentryoffset; + + /* runtime database fields */ + long rundbhash; + short rating; + short voladjust; + long playcount; + long lastplayed; }; enum { -- cgit v1.2.3