diff --git a/inotify.c b/inotify.c index fb1b7e5..72fec04 100644 --- a/inotify.c +++ b/inotify.c @@ -20,6 +20,7 @@ #endif #include "upnpglobalvars.h" +#include "inotify.h" #include "utils.h" #include "sql.h" #include "scanner.h" @@ -275,6 +276,7 @@ inotify_insert_file(char * name, const char * path) int depth = 1; enum media_types type = ALL_MEDIA; struct media_dir_s * media_path = media_dirs; + struct stat st; /* Is it cover art for another file? */ if( is_image(path) ) @@ -317,19 +319,29 @@ inotify_insert_file(char * name, const char * path) break; } - /* If it's already in the database, just skip it for now. - * TODO: compare modify timestamps */ - sql = sqlite3_mprintf("SELECT ID from DETAILS where PATH = '%q'", path); + /* If it's already in the database and hasn't been modified, skip it. */ + if( stat(path, &st) != 0 ) + return -1; + + sql = sqlite3_mprintf("SELECT TIMESTAMP from DETAILS where PATH = '%q'", path); if( sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK ) { if( rows ) { - free(last_dir); - free(path_buf); - free(base_name); - sqlite3_free(sql); - sqlite3_free_table(result); - return -1; + if( atoi(result[1]) < st.st_mtime ) + { + DPRINTF(E_DEBUG, L_INOTIFY, "%s is newer than the last db entry.\n", path); + inotify_remove_file(path_buf); + } + else + { + free(last_dir); + free(path_buf); + free(base_name); + sqlite3_free(sql); + sqlite3_free_table(result); + return -1; + } } sqlite3_free_table(result); } @@ -518,22 +530,27 @@ inotify_remove_file(const char * path) if( sql_get_table(db, sql, &result2, NULL, NULL) == SQLITE_OK ) { children = atoi(result2[1]); - if( children < 2 ) - { - free(sql); - asprintf(&sql, "DELETE from OBJECTS where OBJECT_ID = '%s'", result[i]); - sql_exec(db, sql); - } sqlite3_free_table(result2); if( children < 2 ) { - *rindex(result[i], '$') = '\0'; free(sql); + asprintf(&sql, "DELETE from DETAILS where ID =" + " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", result[i]); + sql_exec(db, sql); + free(sql); + asprintf(&sql, "DELETE from OBJECTS where OBJECT_ID = '%s'", result[i]); + sql_exec(db, sql); + free(sql); + *rindex(result[i], '$') = '\0'; asprintf(&sql, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", result[i]); if( sql_get_table(db, sql, &result2, NULL, NULL) == SQLITE_OK ) { if( atoi(result2[1]) == 0 ) { + free(sql); + asprintf(&sql, "DELETE from DETAILS where ID =" + " (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", result[i]); + sql_exec(db, sql); free(sql); asprintf(&sql, "DELETE from OBJECTS where OBJECT_ID = '%s'", result[i]); sql_exec(db, sql); diff --git a/inotify.h b/inotify.h index c739439..91db6f6 100644 --- a/inotify.h +++ b/inotify.h @@ -1,3 +1,6 @@ +int +inotify_remove_file(const char * path); + void * start_inotify(); diff --git a/metadata.c b/metadata.c index d42a774..8360171 100644 --- a/metadata.c +++ b/metadata.c @@ -357,11 +357,11 @@ GetAudioMetadata(const char * path, char * name) album_art = find_album_art(path, song.image, song.image_size); sql = sqlite3_mprintf( "INSERT into DETAILS" - " (PATH, SIZE, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE," + " (PATH, SIZE, TIMESTAMP, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE," " TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, DISC, TRACK, DLNA_PN, MIME, ALBUM_ART) " "VALUES" - " (%Q, %d, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);", - path, song.file_size, duration, song.channels, song.bitrate, song.samplerate, date, + " (%Q, %lld, %ld, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, %d, %Q, '%s', %lld);", + path, file.st_size, file.st_mtime, duration, song.channels, song.bitrate, song.samplerate, date, title, band, artist, album, genre, comment, song.disc, song.track, dlna_pn, song.mime?song.mime:mime, album_art); freetags(&song); @@ -418,7 +418,6 @@ GetImageMetadata(const char * path, char * name) struct jpeg_error_mgr jerr; FILE *infile; int width=0, height=0, thumb=0; - off_t size; char *date = NULL, *cam = NULL; char make[32], model[64] = {'\0'}; char b[1024]; @@ -430,12 +429,10 @@ GetImageMetadata(const char * path, char * name) memset(&m, '\0', sizeof(metadata_t)); //DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path); - if ( stat(path, &file) == 0 ) - size = file.st_size; - else + if ( stat(path, &file) != 0 ) return 0; strip_ext(name); - //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", size); + //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size); /* MIME hard-coded to JPEG for now, until we add PNG support */ asprintf(&m.mime, "image/jpeg"); @@ -541,10 +538,10 @@ no_exifdata: asprintf(&m.resolution, "%dx%d", width, height); sql = sqlite3_mprintf( "INSERT into DETAILS" - " (PATH, TITLE, SIZE, DATE, RESOLUTION, THUMBNAIL, CREATOR, DLNA_PN, MIME) " + " (PATH, TITLE, SIZE, TIMESTAMP, DATE, RESOLUTION, THUMBNAIL, CREATOR, DLNA_PN, MIME) " "VALUES" - " (%Q, '%q', %lld, %Q, %Q, %d, %Q, %Q, %Q);", - path, name, size, date, m.resolution, thumb, cam, m.dlna_pn, m.mime); + " (%Q, '%q', %lld, %ld, %Q, %Q, %d, %Q, %Q, %Q);", + path, name, file.st_size, file.st_mtime, date, m.resolution, thumb, cam, m.dlna_pn, m.mime); //DEBUG DPRINTF(E_DEBUG, L_METADATA, "SQL: %s\n", sql); if( sql_exec(db, sql) != SQLITE_OK ) { @@ -572,7 +569,6 @@ no_exifdata: sqlite_int64 GetVideoMetadata(const char * path, char * name) { - off_t size = 0; struct stat file; char *sql; int ret, i; @@ -590,14 +586,13 @@ GetVideoMetadata(const char * path, char * name) date[0] = '\0'; DPRINTF(E_DEBUG, L_METADATA, "Parsing video %s...\n", name); - if ( stat(path, &file) == 0 ) - { - modtime = localtime(&file.st_mtime); - strftime(date, sizeof(date), "%FT%T", modtime); - size = file.st_size; - } + if ( stat(path, &file) != 0 ) + return 0; strip_ext(name); - //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", size); + //DEBUG DPRINTF(E_DEBUG, L_METADATA, " * size: %jd\n", file.st_size); + + modtime = localtime(&file.st_mtime); + strftime(date, sizeof(date), "%FT%T", modtime); av_register_all(); if( av_open_input_file(&ctx, path, NULL, 0, NULL) != 0 ) @@ -997,11 +992,11 @@ GetVideoMetadata(const char * path, char * name) album_art = find_album_art(path, NULL, 0); sql = sqlite3_mprintf( "INSERT into DETAILS" - " (PATH, SIZE, DURATION, DATE, CHANNELS, BITRATE, SAMPLERATE, RESOLUTION," + " (PATH, SIZE, TIMESTAMP, DURATION, DATE, CHANNELS, BITRATE, SAMPLERATE, RESOLUTION," " CREATOR, TITLE, DLNA_PN, MIME, ALBUM_ART) " "VALUES" - " (%Q, %lld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, '%q', %Q, '%q', %lld);", - path, size, m.duration, + " (%Q, %lld, %ld, %Q, %Q, %Q, %Q, %Q, %Q, %Q, '%q', %Q, '%q', %lld);", + path, file.st_size, file.st_mtime, m.duration, strlen(date) ? date : NULL, m.channels, m.bitrate, m.frequency, m.resolution, m.artist, name, m.dlna_pn, m.mime, diff --git a/scanner.c b/scanner.c index 24e2893..88f92ee 100644 --- a/scanner.c +++ b/scanner.c @@ -628,7 +628,8 @@ CreateDatabase(void) "DLNA_PN TEXT, " "MIME TEXT, " "ALBUM_ART INTEGER DEFAULT 0, " - "DISC INTEGER" + "DISC INTEGER, " + "TIMESTAMP INTEGER" ")"); if( ret != SQLITE_OK ) goto sql_failed;