* Be more flexible when it comes to album art resolutions. This is really just a recommendation and not an absolute requirement for DLNA compliance.

This commit is contained in:
Justin Maggard 2009-02-04 02:25:24 +00:00
parent 48a742181d
commit a1d385241d
6 changed files with 77 additions and 43 deletions

View File

@ -38,6 +38,24 @@ static void libjpeg_error_handler(j_common_ptr cinfo)
return; return;
} }
int
check_res(int width, int height, char * dlna_pn)
{
if( (width <= 0) || (height <= 0) )
return 0;
if( width <= 160 && height <= 160 )
strcpy(dlna_pn, "JPEG_TN");
else if( width <= 640 && height <= 480 )
strcpy(dlna_pn, "JPEG_SM");
else if( width <= 1024 && height <= 768 )
strcpy(dlna_pn, "JPEG_MED");
else if( width <= 4096 && height <= 4096 )
strcpy(dlna_pn, "JPEG_LRG");
else
return 0;
return 1;
}
#ifdef HAVE_LIBID3TAG #ifdef HAVE_LIBID3TAG
#include <id3tag.h> #include <id3tag.h>
@ -101,9 +119,9 @@ jpeg_memory_src(j_decompress_ptr cinfo, unsigned char const *buffer, size_t bufs
src->pub.bytes_in_buffer = bufsize; src->pub.bytes_in_buffer = bufsize;
} }
/* And our main album art function */ /* And our main album art functions */
int int
check_embedded_art(const char * path) check_embedded_art(const char * path, char * dlna_pn)
{ {
struct id3_file *file; struct id3_file *file;
struct id3_tag *pid3tag; struct id3_tag *pid3tag;
@ -148,21 +166,22 @@ check_embedded_art(const char * path)
} }
id3_file_close(file); id3_file_close(file);
/* It's not a valid DLNA_PN JPEG_TN unless it's JPEG <= 160x160 */ return( check_res(width, height, dlna_pn) );
return( (width > 0 && width <= 160) && (height > 0 && height <= 160) );
} }
#endif // HAVE_LIBID3TAG #endif // HAVE_LIBID3TAG
char * char *
check_for_album_file(char * dir) check_for_album_file(char * dir, char * dlna_pn)
{ {
char * file = malloc(PATH_MAX); char * file = malloc(PATH_MAX);
char * album_art_names[] = char * album_art_names[] =
{ {
"Cover.jpg", "cover.jpg", "AlbumArtSmall.jpg", "albumartsmall.jpg",
"Album.jpg", "album.jpg", "Cover.jpg", "cover.jpg",
"Folder.jpg", "folder.jpg", "AlbumArt.jpg", "albumart.jpg",
"Thumb.jpg", "thumb.jpg", "Album.jpg", "album.jpg",
"Folder.jpg", "folder.jpg",
"Thumb.jpg", "thumb.jpg",
0 0
}; };
struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo;
@ -191,8 +210,10 @@ check_for_album_file(char * dir)
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(infile); fclose(infile);
if( (width > 0 && width <= 160) && (height > 0 && height <= 160) ) if( check_res(width, height, dlna_pn) )
return(file); return(file);
else
return(NULL);
} }
} }
free(file); free(file);
@ -200,7 +221,7 @@ check_for_album_file(char * dir)
} }
sqlite_int64 sqlite_int64
find_album_art(const char * path) find_album_art(const char * path, char * dlna_pn)
{ {
char * album_art = NULL; char * album_art = NULL;
char * sql; char * sql;
@ -210,9 +231,9 @@ find_album_art(const char * path)
char * mypath = strdup(path); char * mypath = strdup(path);
#ifdef HAVE_LIBID3TAG #ifdef HAVE_LIBID3TAG
if( check_embedded_art(path) || (album_art = check_for_album_file(dirname(mypath))) ) if( check_embedded_art(path, dlna_pn) || (album_art = check_for_album_file(dirname(mypath), dlna_pn)) )
#else #else
if( (album_art = check_for_album_file(dirname(mypath))) ) if( (album_art = check_for_album_file(dirname(mypath), dlna_pn)) )
#endif #endif
{ {
sql = sqlite3_mprintf("SELECT ID from ALBUM_ART where PATH = '%q'", album_art ? album_art : path); sql = sqlite3_mprintf("SELECT ID from ALBUM_ART where PATH = '%q'", album_art ? album_art : path);

View File

@ -11,6 +11,6 @@
#define __ALBUMART_H__ #define __ALBUMART_H__
sqlite_int64 sqlite_int64
find_album_art(const char * path); find_album_art(const char * path, char * dlna_pn);
#endif #endif

View File

@ -100,17 +100,18 @@ get_fourcc(const char *s)
} }
sqlite_int64 sqlite_int64
GetFolderMetadata(const char * name, const char * artist, const char * genre, const char * album_art) GetFolderMetadata(const char * name, const char * artist, const char * genre, const char * album_art, const char * art_dlna_pn)
{ {
char * sql; char * sql;
int ret; int ret;
sql = sqlite3_mprintf( "INSERT into DETAILS" sql = sqlite3_mprintf( "INSERT into DETAILS"
" (TITLE, CREATOR, ARTIST, GENRE, ALBUM_ART) " " (TITLE, CREATOR, ARTIST, GENRE, ALBUM_ART, ART_DLNA_PN) "
"VALUES" "VALUES"
" ('%q', %Q, %Q, %Q, %lld);", " ('%q', %Q, %Q, %Q, %lld, %Q);",
name, artist, artist, genre, name, artist, artist, genre,
album_art ? strtoll(album_art, NULL, 10) : 0); album_art ? strtoll(album_art, NULL, 10) : 0,
art_dlna_pn);
if( sql_exec(db, sql) != SQLITE_OK ) if( sql_exec(db, sql) != SQLITE_OK )
ret = 0; ret = 0;
@ -136,6 +137,8 @@ GetAudioMetadata(const char * path, char * name)
char *zErrMsg = NULL; char *zErrMsg = NULL;
char *title, *artist, *album, *genre, *comment; char *title, *artist, *album, *genre, *comment;
int free_flags = 0; int free_flags = 0;
sqlite_int64 album_art;
char art_dlna_pn[9];
if ( stat(path, &file) == 0 ) if ( stat(path, &file) == 0 )
size = file.st_size; size = file.st_size;
@ -248,11 +251,13 @@ GetAudioMetadata(const char * path, char * name)
strcpy(mime, "audio/mp4"); strcpy(mime, "audio/mp4");
} }
album_art = find_album_art(path, art_dlna_pn);
sql = sqlite3_mprintf( "INSERT into DETAILS" sql = sqlite3_mprintf( "INSERT into DETAILS"
" (PATH, SIZE, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE," " (PATH, SIZE, DURATION, CHANNELS, BITRATE, SAMPLERATE, DATE,"
" TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, TRACK, DLNA_PN, MIME, ALBUM_ART) " " TITLE, CREATOR, ARTIST, ALBUM, GENRE, COMMENT, TRACK, DLNA_PN, MIME, ALBUM_ART, ART_DLNA_PN) "
"VALUES" "VALUES"
" (%Q, %llu, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, '%s', '%s', %lld);", " (%Q, %llu, '%s', %d, %d, %d, %Q, %Q, %Q, %Q, %Q, %Q, %Q, %d, '%s', '%s', %lld, %Q);",
path, size, duration, taglib_audioproperties_channels(properties), path, size, duration, taglib_audioproperties_channels(properties),
taglib_audioproperties_bitrate(properties)*1024, taglib_audioproperties_bitrate(properties)*1024,
taglib_audioproperties_samplerate(properties), taglib_audioproperties_samplerate(properties),
@ -264,7 +269,7 @@ GetAudioMetadata(const char * path, char * name)
comment, comment,
taglib_tag_track(tag), taglib_tag_track(tag),
dlna_pn, mime, dlna_pn, mime,
find_album_art(path) ); album_art, album_art?art_dlna_pn:NULL );
taglib_tag_free_strings(); taglib_tag_free_strings();
taglib_file_free(audio_file); taglib_file_free(audio_file);

View File

@ -44,7 +44,7 @@ char *
modifyString(char * string, const char * before, const char * after, short like); modifyString(char * string, const char * before, const char * after, short like);
sqlite_int64 sqlite_int64
GetFolderMetadata(const char * name, const char * artist, const char * genre, const char * album_art); GetFolderMetadata(const char * name, const char * artist, const char * genre, const char * album_art, const char * art_dlna_pn);
sqlite_int64 sqlite_int64
GetAudioMetadata(const char * path, char * name); GetAudioMetadata(const char * path, char * name);

View File

@ -79,7 +79,7 @@ get_next_available_id(const char * table, const char * parentID)
long long int long long int
insert_container(const char * tmpTable, const char * item, const char * rootParent, const char *subParent, insert_container(const char * tmpTable, const char * item, const char * rootParent, const char *subParent,
const char *class, const char *artist, const char *genre, const char *album_art) const char *class, const char *artist, const char *genre, const char *album_art, const char *art_dlna_pn)
{ {
char **result; char **result;
char *sql; char *sql;
@ -100,7 +100,7 @@ insert_container(const char * tmpTable, const char * item, const char * rootPare
else else
{ {
parentID = get_next_available_id("OBJECTS", rootParent); parentID = get_next_available_id("OBJECTS", rootParent);
detailID = GetFolderMetadata(item, artist, genre, album_art); detailID = GetFolderMetadata(item, artist, genre, album_art, art_dlna_pn);
sql = sqlite3_mprintf( "INSERT into OBJECTS" sql = sqlite3_mprintf( "INSERT into OBJECTS"
" (OBJECT_ID, PARENT_ID, DETAIL_ID, CLASS, NAME) " " (OBJECT_ID, PARENT_ID, DETAIL_ID, CLASS, NAME) "
"VALUES" "VALUES"
@ -147,7 +147,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
{ {
strncpy(date_taken, date, 10); strncpy(date_taken, date, 10);
} }
container = insert_container("DATES", date_taken, "3$12", NULL, "album.photoAlbum", NULL, NULL, NULL); container = insert_container("DATES", date_taken, "3$12", NULL, "album.photoAlbum", NULL, NULL, NULL, NULL);
parentID = container>>32; parentID = container>>32;
objectID = container; objectID = container;
sql = sqlite3_mprintf( "INSERT into OBJECTS" sql = sqlite3_mprintf( "INSERT into OBJECTS"
@ -160,12 +160,12 @@ insert_containers(const char * name, const char *path, const char * refID, const
} }
if( cam && date ) if( cam && date )
{ {
container = insert_container("CAMS", cam, "3$13", NULL, "storageFolder", NULL, NULL, NULL); container = insert_container("CAMS", cam, "3$13", NULL, "storageFolder", NULL, NULL, NULL, NULL);
parentID = container>>32; parentID = container>>32;
//objectID = container; //objectID = container;
char parent[64]; char parent[64];
sprintf(parent, "3$13$%X", parentID); sprintf(parent, "3$13$%X", parentID);
long long int subcontainer = insert_container("CAMDATE", date_taken, parent, cam, "storageFolder", NULL, NULL, NULL); long long int subcontainer = insert_container("CAMDATE", date_taken, parent, cam, "storageFolder", NULL, NULL, NULL, NULL);
int subParentID = subcontainer>>32; int subParentID = subcontainer>>32;
int subObjectID = subcontainer; int subObjectID = subcontainer;
sql = sqlite3_mprintf( "INSERT into OBJECTS" sql = sqlite3_mprintf( "INSERT into OBJECTS"
@ -187,8 +187,8 @@ insert_containers(const char * name, const char *path, const char * refID, const
} }
else if( strstr(class, "audioItem") ) else if( strstr(class, "audioItem") )
{ {
char *artist = cols ? result[7+cols]:NULL, *album = cols ? result[8+cols]:NULL; char *artist = cols ? result[7+cols]:NULL, *album = cols ? result[8+cols]:NULL, *genre = cols ? result[9+cols]:NULL;
char *genre = cols ? result[9+cols]:NULL, *album_art = cols ? result[19+cols]:NULL; char *album_art = cols ? result[19+cols]:NULL, *art_dlna_pn = cols ? result[20+cols]:NULL;
static char last_artist[1024] = "0"; static char last_artist[1024] = "0";
static int last_artist_parentID, last_artist_objectID; static int last_artist_parentID, last_artist_objectID;
static char last_album[1024]; static char last_album[1024];
@ -207,7 +207,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
else else
{ {
strcpy(last_artist, artist); strcpy(last_artist, artist);
container = insert_container("ARTISTS", artist, "1$6", NULL, "person.musicArtist", NULL, genre, NULL); container = insert_container("ARTISTS", artist, "1$6", NULL, "person.musicArtist", NULL, genre, NULL, NULL);
parentID = container>>32; parentID = container>>32;
objectID = container; objectID = container;
last_artist_objectID = objectID; last_artist_objectID = objectID;
@ -231,7 +231,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
else else
{ {
strcpy(last_album, album); strcpy(last_album, album);
container = insert_container("ALBUMS", album, "1$7", NULL, "album.musicAlbum", artist, genre, album_art); container = insert_container("ALBUMS", album, "1$7", NULL, "album.musicAlbum", artist, genre, album_art, art_dlna_pn);
parentID = container>>32; parentID = container>>32;
objectID = container; objectID = container;
last_album_objectID = objectID; last_album_objectID = objectID;
@ -255,7 +255,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
else else
{ {
strcpy(last_genre, genre); strcpy(last_genre, genre);
container = insert_container("GENRES", genre, "1$5", NULL, "genre.musicGenre", NULL, NULL, NULL); container = insert_container("GENRES", genre, "1$5", NULL, "genre.musicGenre", NULL, NULL, NULL, NULL);
parentID = container>>32; parentID = container>>32;
objectID = container; objectID = container;
last_genre_objectID = objectID; last_genre_objectID = objectID;
@ -361,7 +361,7 @@ insert_directory(const char * name, const char * path, const char * base, const
return 1; return 1;
} }
detailID = GetFolderMetadata(name, NULL, NULL, NULL); detailID = GetFolderMetadata(name, NULL, NULL, NULL, NULL);
sql = sqlite3_mprintf( "INSERT into OBJECTS" sql = sqlite3_mprintf( "INSERT into OBJECTS"
" (OBJECT_ID, PARENT_ID, REF_ID, DETAIL_ID, CLASS, NAME) " " (OBJECT_ID, PARENT_ID, REF_ID, DETAIL_ID, CLASS, NAME) "
"VALUES" "VALUES"
@ -513,7 +513,8 @@ CreateDatabase(void)
"CREATOR TEXT, " "CREATOR TEXT, "
"DLNA_PN TEXT, " "DLNA_PN TEXT, "
"MIME TEXT, " "MIME TEXT, "
"ALBUM_ART INTEGER DEFAULT 0" "ALBUM_ART INTEGER DEFAULT 0, "
"ART_DLNA_PN TEXT DEFAULT NULL"
");"); ");");
if( ret != SQLITE_OK ) if( ret != SQLITE_OK )
goto sql_failed; goto sql_failed;
@ -529,7 +530,7 @@ CreateDatabase(void)
sprintf(sql_buf, "INSERT into OBJECTS (OBJECT_ID, PARENT_ID, DETAIL_ID, CLASS, NAME)" sprintf(sql_buf, "INSERT into OBJECTS (OBJECT_ID, PARENT_ID, DETAIL_ID, CLASS, NAME)"
" values " " values "
"('%s', '%s', %lld, 'container.storageFolder', '%s')", "('%s', '%s', %lld, 'container.storageFolder', '%s')",
containers[i], containers[i+1], GetFolderMetadata(containers[i+2], NULL, NULL, NULL), containers[i+2]); containers[i], containers[i+1], GetFolderMetadata(containers[i+2], NULL, NULL, NULL, NULL), containers[i+2]);
ret = sql_exec(db, sql_buf); ret = sql_exec(db, sql_buf);
if( ret != SQLITE_OK ) if( ret != SQLITE_OK )
goto sql_failed; goto sql_failed;

View File

@ -209,8 +209,8 @@ static int callback(void *args, int argc, char **argv, char **azColName)
struct Response { char *resp; int returned; int requested; int total; char *filter; } *passed_args = (struct Response *)args; struct Response { char *resp; int returned; int requested; int total; char *filter; } *passed_args = (struct Response *)args;
char *id = argv[1], *parent = argv[2], *refID = argv[3], *class = argv[4], *detailID = argv[5], *size = argv[9], *title = argv[10], char *id = argv[1], *parent = argv[2], *refID = argv[3], *class = argv[4], *detailID = argv[5], *size = argv[9], *title = argv[10],
*duration = argv[11], *bitrate = argv[12], *sampleFrequency = argv[13], *artist = argv[14], *album = argv[15], *duration = argv[11], *bitrate = argv[12], *sampleFrequency = argv[13], *artist = argv[14], *album = argv[15],
*genre = argv[16], *comment = argv[17], *nrAudioChannels = argv[18], *track = argv[19], *date = argv[20], *genre = argv[16], *comment = argv[17], *nrAudioChannels = argv[18], *track = argv[19], *date = argv[20], *resolution = argv[21],
*resolution = argv[21], *tn = argv[22], *creator = argv[23], *dlna_pn = argv[24], *mime = argv[25], *album_art = argv[26]; *tn = argv[22], *creator = argv[23], *dlna_pn = argv[24], *mime = argv[25], *album_art = argv[26], *art_dlna_pn = argv[27];
char dlna_buf[64]; char dlna_buf[64];
char str_buf[4096]; char str_buf[4096];
char **result; char **result;
@ -269,10 +269,12 @@ static int callback(void *args, int argc, char **argv, char **azColName)
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) { if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) {
sprintf(str_buf, "&lt;upnp:albumArtURI %s" strcat(passed_args->resp, "&lt;upnp:albumArtURI ");
"&gt;http://%s:%d/AlbumArt/%s.jpg&lt;/upnp:albumArtURI&gt;", if( !passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI@dlna:profileID") ) {
(!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI@dlna:profileID")) ? sprintf(str_buf, "dlna:profileID=\"%s\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\"", art_dlna_pn);
"dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\"" : "", strcat(passed_args->resp, str_buf);
}
sprintf(str_buf, "&gt;http://%s:%d/AlbumArt/%s.jpg&lt;/upnp:albumArtURI&gt;",
lan_addr[0].str, runtime_vars.port, album_art); lan_addr[0].str, runtime_vars.port, album_art);
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
@ -368,8 +370,13 @@ static int callback(void *args, int argc, char **argv, char **azColName)
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) { if( album_art && atoi(album_art) && (!passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI")) ) {
sprintf(str_buf, "&lt;upnp:albumArtURI dlna:profileID=\"JPEG_TN\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\"" strcat(passed_args->resp, "&lt;upnp:albumArtURI ");
"&gt;http://%s:%d/AlbumArt/%s.jpg&lt;/upnp:albumArtURI&gt;", lan_addr[0].str, runtime_vars.port, album_art); if( !passed_args->filter || strstr(passed_args->filter, "upnp:albumArtURI@dlna:profileID") ) {
sprintf(str_buf, "dlna:profileID=\"%s\" xmlns:dlna=\"urn:schemas-dlnaorg:metadata-1-0/\"", art_dlna_pn);
strcat(passed_args->resp, str_buf);
}
sprintf(str_buf, "&gt;http://%s:%d/AlbumArt/%s.jpg&lt;/upnp:albumArtURI&gt;",
lan_addr[0].str, runtime_vars.port, album_art);
strcat(passed_args->resp, str_buf); strcat(passed_args->resp, str_buf);
} }
sprintf(str_buf, "&lt;/container&gt;"); sprintf(str_buf, "&lt;/container&gt;");