diff --git a/src/Makefile.am b/src/Makefile.am index e8a2c8c5..8566452e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,7 +13,7 @@ DBFILE=db-memory.c endif if COND_NEED_STRCASESTR -STRCASESTR=strcasestr.c +STRCASESTR=strcasestr.c strcasestr.h endif if COND_NEED_STRSEP @@ -41,7 +41,7 @@ mt_daapd_SOURCES = main.c daapd.h rend.h uici.c uici.h webserver.c \ EXTRA_DIST = mdns/mDNS.c mdns/mDNSClientAPI.h mdns/mDNSDebug.h mdns/mDNSPosix.c \ mdns/mDNSUNP.c mdns/mDNSPlatformFunctions.h mdns/mDNSPosix.h mdns/mDNSUNP.h \ rend-howl.c rend-posix.c rend-osx.c strcasestr.c strsep.c db-memory.c \ - db-gdbm.c + db-gdbm.c strcasestr.h diff --git a/src/db-gdbm.c b/src/db-gdbm.c index 73a33831..ea2156c3 100644 --- a/src/db-gdbm.c +++ b/src/db-gdbm.c @@ -171,7 +171,7 @@ int db_init(char *parameters) { db_version_no=1; db_song_count=0; - /* count the actual songs... */ + /* count the actual songs and build the playlists */ tmp_data=gdbm_firstkey(db_songs); MEMNOTIFY(tmp_data.dptr); @@ -560,7 +560,7 @@ int db_add(MP3FILE *pmp3) { ppacked->time_modified=ppacked->time_added; ppacked->time_played=0; - if(gdbm_store(db_songs,dkey,*pnew,GDBM_INSERT)) { + if(gdbm_store(db_songs,dkey,*pnew,GDBM_REPLACE)) { log_err(0,"Error inserting file %s in database\n",pmp3->fname); } @@ -789,6 +789,7 @@ int db_playlist_items_enum_end(void) { return pthread_rwlock_unlock(&db_rwlock); } + /* * db_find * @@ -901,3 +902,33 @@ char *db_get_playlist_name(int playlistid) { return name; } + +/* + * db_exists + * + * Check if a particular ID exists or not + */ +int db_exists(int id) { + /* this is wrong and expensive */ + MP3FILE *pmp3; + + pmp3=db_find(id); + return pmp3 ? 1 : 0; +} + + +/* + * db_last_modified + * + * See when the file was last updated in the database + */ +int db_last_modified(int id) { + MP3FILE *pmp3; + + pmp3=db_find(id); + if(!pmp3) + return 0; + + + return pmp3->time_modified; +} diff --git a/src/db-memory.c b/src/db-memory.c index 9154de38..1b9be8ae 100644 --- a/src/db-memory.c +++ b/src/db-memory.c @@ -629,3 +629,29 @@ char *db_get_playlist_name(int playlistid) { pthread_rwlock_unlock(&db_rwlock); return name; } + + +/* + * db_exists + * + * Check if a particular id is in the database + */ +int db_exists(int id) { + MP3FILE *pmp3; + + pmp3=db_find(id); + + return pmp3 ? 1 : 0; +} + +/* + * db_last_modified + * + * See when the file was modified (according to the database) + * + * This is merely a stub for the in-memory db + */ +int db_last_modified(int id) { + return 0; +} + diff --git a/src/db-memory.h b/src/db-memory.h index 4aca5b65..f3db932f 100644 --- a/src/db-memory.h +++ b/src/db-memory.h @@ -55,4 +55,8 @@ extern int db_playlist_items_enum_end(void); extern char *db_get_playlist_name(int playlistid); +/* For persistant databases only */ +extern int db_exists(int id); +extern int db_last_modified(int id); + #endif /* _DB_MEMORY_H_ */ diff --git a/src/mp3-scanner.c b/src/mp3-scanner.c index 6422419b..46acac0c 100644 --- a/src/mp3-scanner.c +++ b/src/mp3-scanner.c @@ -38,6 +38,7 @@ #include #include +#include /* htons and friends */ #include #include @@ -46,6 +47,7 @@ #include "err.h" #include "mp3-scanner.h" #include "playlist.h" +#include "strcasestr.h" /* * Typedefs @@ -68,6 +70,8 @@ int scan_br_table[] = { 0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0 }; +int scan_mode_foreground=1; + char *scan_winamp_genre[] = { "Blues", // 0 "Classic Rock", @@ -226,7 +230,7 @@ char *scan_winamp_genre[] = { /* * Forwards */ -int scan_foreground(char *path); +int scan_path(char *path); int scan_gettags(char *file, MP3FILE *pmp3); int scan_get_mp3tags(char *file, MP3FILE *pmp3); int scan_get_aactags(char *file, MP3FILE *pmp3); @@ -250,37 +254,42 @@ void scan_music_file(char *path, struct dirent *pde, struct stat *psb); int scan_init(char *path) { int err; + + scan_mode_foreground=0; if(db_is_empty()) { + scan_mode_foreground=1; if(db_start_initial_update()) return -1; + } + DPRINTF(ERR_DEBUG,"%s scanning for MP3s in %s\n", + scan_mode_foreground ? "Foreground" : "Background", + path); - DPRINTF(ERR_DEBUG,"Scanning for MP3s in %s\n",path); - - err=scan_foreground(path); + err=scan_path(path); + if(scan_mode_foreground) if(db_end_initial_update()) return -1; - } else { - /* do deferred updating */ - return ENOTSUP; - } + + scan_mode_foreground=0; return err; } /* - * scan_foreground + * scan_path * * Do a brute force scan of a path, finding all the MP3 files there */ -int scan_foreground(char *path) { +int scan_path(char *path) { DIR *current_dir; char de[sizeof(struct dirent) + MAXNAMLEN + 1]; /* overcommit for solaris */ struct dirent *pde; int err; char mp3_path[PATH_MAX]; struct stat sb; + int modified_time; if((current_dir=opendir(path)) == NULL) { return -1; @@ -312,7 +321,7 @@ int scan_foreground(char *path) { if(sb.st_mode & S_IFDIR) { /* dir -- recurse */ DPRINTF(ERR_DEBUG,"Found dir %s... recursing\n",pde->d_name); - scan_foreground(mp3_path); + scan_path(mp3_path); } else { DPRINTF(ERR_DEBUG,"Processing file\n"); /* process the file */ @@ -322,7 +331,16 @@ int scan_foreground(char *path) { scan_static_playlist(path, pde, &sb); } else if (strcasestr(config.extensions, (char*)&pde->d_name[strlen(pde->d_name) - 4])) { - scan_music_file(path,pde,&sb); + + /* only scan if it's been changed, or empty db */ + modified_time=sb.st_mtime; + if((scan_mode_foreground) || + !db_exists(sb.st_ino) || + db_last_modified(sb.st_ino) < modified_time) { + scan_music_file(path,pde,&sb); + } else { + DPRINTF(ERR_DEBUG,"Skipping file... not modified\n"); + } } } } @@ -471,6 +489,7 @@ int scan_get_aactags(char *file, MP3FILE *pmp3) { char current_atom[4]; char *current_data; unsigned short us_data; + int len; if(!(fin=fopen(file,"rb"))) { DPRINTF(ERR_INFO,"Cannot open file %s for reading\n",file); @@ -504,8 +523,12 @@ int scan_get_aactags(char *file, MP3FILE *pmp3) { if(fread(current_atom,1,4,fin) != 4) break; - current_data=(char*)malloc(current_size - 7); /* extra byte */ - memset(current_data,0x00,current_size - 7); + len=current_size-7; /* for ill-formed too-short tags */ + if(len < 22) + len=22; + + current_data=(char*)malloc(len); /* extra byte */ + memset(current_data,0x00,len); if(fread(current_data,1,current_size-8,fin) != current_size-8) break; @@ -812,7 +835,7 @@ int scan_getfileinfo(char *file, MP3FILE *pmp3) { if(!pmp3->song_length) /* could have gotten it from the tag */ pmp3->song_length=time_seconds; } else { - /* should really scan forward to next sync frame */ + /* FIXME: should really scan forward to next sync frame */ fclose(infile); DPRINTF(ERR_DEBUG,"Could not find sync frame\n"); return -1; diff --git a/src/rend-posix.c b/src/rend-posix.c index e8aeeb6a..e5f6fddd 100644 --- a/src/rend-posix.c +++ b/src/rend-posix.c @@ -89,6 +89,9 @@ Change History (most recent first): $Log$ + Revision 1.16 2004/03/08 19:21:03 rpedde + start of background scanning + Revision 1.15 2004/03/02 01:35:31 rpedde fix domain @@ -240,15 +243,13 @@ static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegi switch (status) { case mStatus_NoError: - DPRINTF(ERR_DEBUG,"Callback: %##s Name Registered\n", - thisRegistration->RR_SRV.resrec.name.c); + DPRINTF(ERR_DEBUG,"Callback: Name Registered\n"); // Do nothing; our name was successfully registered. We may // get more call backs in the future. break; case mStatus_NameConflict: - DPRINTF(ERR_WARN,"Callback: %##s Name Conflict\n", - thisRegistration->RR_SRV.resrec.name.c); + DPRINTF(ERR_WARN,"Callback: Name Conflict\n"); // In the event of a conflict, this sample RegistrationCallback // just calls mDNS_RenameAndReregisterService to automatically @@ -266,8 +267,7 @@ static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegi break; case mStatus_MemFree: - DPRINTF(ERR_WARN,"Callback: %##s Memory Free\n", - thisRegistration->RR_SRV.resrec.name.c); + DPRINTF(ERR_WARN,"Callback: Memory Free\n"); // When debugging is enabled, make sure that thisRegistration // is not on our gServiceList. @@ -287,8 +287,7 @@ static void RegistrationCallback(mDNS *const m, ServiceRecordSet *const thisRegi break; default: - DPRINTF(ERR_WARN,"Callback: %##s Unknown Status %d\n", - thisRegistration->RR_SRV.resrec.name.c, status); + DPRINTF(ERR_WARN,"Callback: Unknown Status %d\n",status); break; } } diff --git a/src/strcasestr.h b/src/strcasestr.h new file mode 100644 index 00000000..8ac05bad --- /dev/null +++ b/src/strcasestr.h @@ -0,0 +1,6 @@ +#ifndef _STRCASESTR_H_ +#define _STRCASESTR_H_ + +extern char * strcasestr(char* haystack, char* needle); + +#endif