diff --git a/albumart.c b/albumart.c index 3ab6f54..8e3c938 100644 --- a/albumart.c +++ b/albumart.c @@ -28,6 +28,7 @@ #include #include "upnpglobalvars.h" +#include "albumart.h" #include "sql.h" #include "utils.h" #include "image_utils.h" @@ -102,6 +103,80 @@ unsigned int DJBHash(const char * str, int len) } /* And our main album art functions */ +void +update_if_album_art(const char * path) +{ + char * dir; + char * match = NULL; + char * file = NULL; + char * sql; + int ncmp = 0; + struct album_art_name_s * album_art_name; + DIR * dh; + struct dirent *dp; + enum file_types type = TYPE_UNKNOWN; + sqlite_int64 art_id = 0; + + match = strdup(basename((char *)path)); + /* Check if this file name matches a specific audio or video file */ + if( ends_with(match, ".cover.jpg") ) + { + ncmp = strlen(match)-10; + } + else + { + ncmp = strrchr(match, '.')-match; + } + /* Check if this file name matches one of the default album art names */ + for( album_art_name = album_art_names; album_art_name; album_art_name = album_art_name->next ) + { + if( strcmp(album_art_name->name, match) == 0 ) + break; + } + + dir = dirname(strdup(path)); + dh = opendir(dir); + if( !dh ) + return; + while ((dp = readdir(dh)) != NULL) + { + switch( dp->d_type ) + { + case DT_REG: + type = TYPE_FILE; + break; + case DT_LNK: + case DT_UNKNOWN: + asprintf(&file, "%s/%s", dir, dp->d_name); + type = resolve_unknown_type(file, ALL_MEDIA); + free(file); + break; + default: + type = TYPE_UNKNOWN; + break; + } + if( type != TYPE_FILE ) + continue; + if( (*(dp->d_name) != '.') && + (is_video(dp->d_name) || is_audio(dp->d_name)) && + (album_art_name || strncmp(dp->d_name, match, ncmp) == 0) ) + { + DPRINTF(E_DEBUG, L_METADATA, "New file %s looks like cover art for %s\n", path, dp->d_name); + asprintf(&file, "%s/%s", dir, dp->d_name); + art_id = find_album_art(file, NULL, NULL, 0); + sql = sqlite3_mprintf("UPDATE DETAILS set ALBUM_ART = %lld where PATH = '%q'", art_id, file); + if( sql_exec(db, sql) != SQLITE_OK ) + DPRINTF(E_WARN, L_METADATA, "Error setting %s as cover art for %s\n", match, dp->d_name); + sqlite3_free(sql); + free(file); + } + } + closedir(dh); + + free(dir); + free(match); +} + char * check_embedded_art(const char * path, const char * image_data, int image_size) { @@ -268,7 +343,8 @@ find_album_art(const char * path, char * dlna_pn, const char * image_data, int i if( (image_size && (album_art = check_embedded_art(path, image_data, image_size))) || (album_art = check_for_album_file(dirname(mypath), path)) ) { - strcpy(dlna_pn, "JPEG_TN"); + if( dlna_pn ) + strcpy(dlna_pn, "JPEG_TN"); sql = sqlite3_mprintf("SELECT ID from ALBUM_ART where PATH = '%q'", album_art ? album_art : path); if( (sql_get_table(db, sql, &result, &rows, &cols) == SQLITE_OK) && rows ) { diff --git a/albumart.h b/albumart.h index 1ae5cac..42169ea 100644 --- a/albumart.h +++ b/albumart.h @@ -10,6 +10,9 @@ #ifndef __ALBUMART_H__ #define __ALBUMART_H__ +void +update_if_album_art(const char * path); + sqlite_int64 find_album_art(const char * path, char * dlna_pn, const char * image_data, int image_size); diff --git a/inotify.c b/inotify.c index 9cd7ab0..2424005 100644 --- a/inotify.c +++ b/inotify.c @@ -22,6 +22,7 @@ #include "utils.h" #include "sql.h" #include "scanner.h" +#include "albumart.h" #include "log.h" #define EVENT_SIZE ( sizeof (struct inotify_event) ) @@ -268,6 +269,10 @@ inotify_insert_file(char * name, const char * path) enum media_types type = ALL_MEDIA; struct media_dir_s * media_path = media_dirs; + /* Is it cover art for another file? */ + if( is_image(path) ) + update_if_album_art(path); + /* Check if we're supposed to be scanning for this file type in this directory */ while( media_path ) { diff --git a/upnpglobalvars.h b/upnpglobalvars.h index 7d06e93..0f4980f 100644 --- a/upnpglobalvars.h +++ b/upnpglobalvars.h @@ -15,7 +15,7 @@ #include -#define MINIDLNA_VERSION "1.0.14" +#define MINIDLNA_VERSION "1.0.15" #define CLIENT_CACHE_SLOTS 20 #define USE_FORK 1 diff --git a/utils.c b/utils.c index 37b7324..8783e81 100644 --- a/utils.c +++ b/utils.c @@ -31,8 +31,15 @@ int ends_with(const char * haystack, const char * needle) { - const char * end = strrchr(haystack, *needle); - return (strcasecmp(end?end:"", needle) ? 0 : 1); + const char * end; + int nlen = strlen(needle); + int hlen = strlen(haystack); + + if( nlen > hlen ) + return 0; + end = haystack + hlen - nlen; + + return (strcasecmp(end, needle) ? 0 : 1); } char *