diff --git a/inotify.c b/inotify.c
index 0d22a2f..c546830 100644
--- a/inotify.c
+++ b/inotify.c
@@ -425,7 +425,9 @@ inotify_insert_directory(int fd, char *name, const char * path)
if( strcmp(e->d_name, ".") == 0 ||
strcmp(e->d_name, "..") == 0 )
continue;
- esc_name = modifyString(strdup(e->d_name), "&", "&", 0);
+ esc_name = escape_tag(e->d_name);
+ if( !esc_name )
+ esc_name = strdup(e->d_name);
asprintf(&path_buf, "%s/%s", path, e->d_name);
if( e->d_type == DT_DIR )
{
diff --git a/metadata.c b/metadata.c
index f3e1d47..5130dc1 100644
--- a/metadata.c
+++ b/metadata.c
@@ -92,6 +92,23 @@ dlna_timestamp_is_present(const char * filename)
return 0;
}
+#ifdef TIVO_SUPPORT
+int
+is_tivo_file(const char * path)
+{
+ unsigned char buf[5];
+ unsigned char hdr[5] = { 'T','i','V','o','\0' };
+ int fd;
+
+ /* read file header */
+ fd = open(path, O_RDONLY);
+ read(fd, buf, 5);
+ close(fd);
+
+ return( !memcmp(buf, hdr, 5) );
+}
+#endif
+
/* This function taken from libavutil (ffmpeg), because it's not included with all versions of libavutil. */
int
get_fourcc(const char *s)
@@ -99,44 +116,23 @@ get_fourcc(const char *s)
return (s[0]) + (s[1]<<8) + (s[2]<<16) + (s[3]<<24);
}
-char *
-escape_tag(const char *tag)
-{
- char *esc_tag = NULL;
-
- if( index(tag, '&') || index(tag, '<') || index(tag, '>') )
- {
- esc_tag = strdup(tag);
- esc_tag = modifyString(esc_tag, "&", "&", 0);
- esc_tag = modifyString(esc_tag, "<", "<", 0);
- esc_tag = modifyString(esc_tag, ">", ">", 0);
- }
-
- return esc_tag;
-}
-
sqlite_int64
GetFolderMetadata(const char * name, const char * path, const char * artist, const char * genre, const char * album_art, const char * art_dlna_pn)
{
char * sql;
- char * esc_name = NULL;
int ret;
- esc_name = escape_tag(name);
sql = sqlite3_mprintf( "INSERT into DETAILS"
" (TITLE, PATH, CREATOR, ARTIST, GENRE, ALBUM_ART, ART_DLNA_PN) "
"VALUES"
" ('%q', %Q, %Q, %Q, %Q, %lld, %Q);",
- esc_name ? esc_name : name,
- path, artist, artist, genre,
+ name, path, artist, artist, genre,
album_art ? strtoll(album_art, NULL, 10) : 0,
art_dlna_pn);
if( sql_exec(db, sql) != SQLITE_OK )
ret = 0;
else
ret = sqlite3_last_insert_rowid(db);
- if( esc_name )
- free(esc_name);
sqlite3_free(sql);
return ret;
@@ -328,7 +324,8 @@ GetImageMetadata(const char * path, char * name)
FILE *infile;
int width=0, height=0, thumb=0;
off_t size;
- char date[64], make[32], model[64];
+ char *date = NULL, *cam = NULL;
+ char make[32], model[64] = {'\0'};
char b[1024];
char *esc_name = NULL;
struct stat file;
@@ -337,9 +334,6 @@ GetImageMetadata(const char * path, char * name)
metadata_t m;
memset(&m, '\0', sizeof(metadata_t));
- date[0] = '\0';
- model[0] = '\0';
-
//DEBUG DPRINTF(E_DEBUG, L_METADATA, "Parsing %s...\n", path);
if ( stat(path, &file) == 0 )
size = file.st_size;
@@ -371,7 +365,7 @@ GetImageMetadata(const char * path, char * name)
tag = EXIF_TAG_DATE_TIME_ORIGINAL;
e = exif_content_get_entry (ed->ifd[EXIF_IFD_EXIF], tag);
if( e || (e = exif_content_get_entry(ed->ifd[EXIF_IFD_0], EXIF_TAG_DATE_TIME)) ) {
- strncpy(date, exif_entry_get_value(e, b, sizeof(b)), sizeof(date));
+ date = strdup(exif_entry_get_value(e, b, sizeof(b)));
if( strlen(date) > 10 )
{
date[4] = '-';
@@ -379,15 +373,12 @@ GetImageMetadata(const char * path, char * name)
date[10] = 'T';
}
else {
- strcpy(date, "0000-00-00");
+ free(date);
+ date = NULL;
}
}
- else {
- strcpy(date, "0000-00-00");
- }
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * date: %s\n", date);
- model[0] = '\0';
tag = EXIF_TAG_MAKE;
e = exif_content_get_entry (ed->ifd[EXIF_IFD_0], tag);
if( e )
@@ -400,10 +391,9 @@ GetImageMetadata(const char * path, char * name)
strncpy(model, exif_entry_get_value(e, b, sizeof(b)), sizeof(model));
if( !strcasestr(model, make) )
snprintf(model, sizeof(model), "%s %s", make, exif_entry_get_value(e, b, sizeof(b)));
+ cam = strdup(model);
}
}
- if( !strlen(model) )
- strcpy(model, "Unknown");
//DEBUG DPRINTF(E_DEBUG, L_METADATA, " * model: %s\n", model);
if( ed->size )
@@ -452,8 +442,8 @@ GetImageMetadata(const char * path, char * name)
sql = sqlite3_mprintf( "INSERT into DETAILS"
" (PATH, TITLE, SIZE, DATE, RESOLUTION, THUMBNAIL, CREATOR, DLNA_PN, MIME) "
"VALUES"
- " (%Q, '%q', %llu, '%s', %Q, %d, '%q', %Q, %Q);",
- path, esc_name?esc_name:name, size, date, m.resolution, thumb, model, m.dlna_pn, m.mime);
+ " (%Q, '%q', %llu, %Q, %Q, %d, %Q, %Q, %Q);",
+ path, esc_name?esc_name:name, size, 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 )
{
@@ -473,6 +463,10 @@ GetImageMetadata(const char * path, char * name)
free(m.mime);
if( esc_name )
free(esc_name);
+ if( date )
+ free(date);
+ if( cam )
+ free(cam);
return ret;
}
@@ -870,7 +864,13 @@ GetVideoMetadata(const char * path, char * name)
DPRINTF(E_WARN, L_METADATA, "Unhandled format: %s\n", ctx->iformat->name);
}
av_close_input_file(ctx);
-
+#ifdef TIVO_SUPPORT
+ if( ends_with(path, ".TiVo") && is_tivo_file(path) )
+ {
+ free(m.mime);
+ asprintf(&m.mime, "video/x-tivo-mpeg");
+ }
+#endif
sql = sqlite3_mprintf( "INSERT into DETAILS"
" (PATH, SIZE, DURATION, DATE, CHANNELS, BITRATE, SAMPLERATE, RESOLUTION,"
" TITLE, DLNA_PN, MIME) "
diff --git a/scanner.c b/scanner.c
index 77ce139..45c0ad3 100644
--- a/scanner.c
+++ b/scanner.c
@@ -52,6 +52,9 @@ is_video(const char * file)
ends_with(file, ".mts") || ends_with(file, ".m2ts") ||
ends_with(file, ".m2t") || ends_with(file, ".mkv") ||
ends_with(file, ".vob") || ends_with(file, ".ts") ||
+ #ifdef TIVO_SUPPORT
+ ends_with(file, ".TiVo") ||
+ #endif
ends_with(file, ".flv") || ends_with(file, ".xvid"));
}
@@ -147,88 +150,96 @@ insert_container(const char * item, const char * rootParent, const char * refID,
void
insert_containers(const char * name, const char *path, const char * refID, const char * class, long unsigned int detailID)
{
- char sql_buf[128];
char *sql;
char **result;
int ret;
int cols, row;
- long long int container;
-
- sprintf(sql_buf, "SELECT * from DETAILS where ID = %lu", detailID);
- ret = sql_get_table(db, sql_buf, &result, &row, &cols);
+ sqlite_int64 container;
if( strstr(class, "imageItem") )
{
- char *date = result[13+cols], *cam = result[16+cols];
- char date_taken[11];
+ char *date = NULL, *cam = NULL;
+ char date_taken[13], camera[64];
static struct virtual_item last_date;
static struct virtual_item last_cam;
static struct virtual_item last_camdate;
static sqlite_int64 last_all_objectID = 0;
+ asprintf(&sql, "SELECT DATE, CREATOR from DETAILS where ID = %lu", detailID);
+ ret = sql_get_table(db, sql, &result, &row, &cols);
+ free(sql);
+ if( ret == SQLITE_OK )
+ {
+ date = result[2];
+ cam = result[3];
+ }
+
if( date )
{
- if( *date == '0' )
- {
- strcpy(date_taken, "Unknown");
- }
- else
- {
- strncpy(date_taken, date, 10);
- date_taken[10] = '\0';
- }
- if( strcmp(last_date.name, date_taken) == 0 )
- {
- last_date.objectID++;
- //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Using last date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
- }
- else
- {
- container = insert_container(date_taken, "3$12", NULL, "album.photoAlbum", NULL, NULL, NULL, NULL);
- sprintf(last_date.parentID, "3$12$%llX", container>>32);
- last_date.objectID = (int)container;
- strcpy(last_date.name, date_taken);
- //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Creating cached date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
- }
- sql = sqlite3_mprintf( "INSERT into OBJECTS"
- " (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
- "VALUES"
- " ('%s$%X', '%s', '%s', '%s', %lu, %Q)",
- last_date.parentID, last_date.objectID, last_date.parentID, refID, class, detailID, name);
- sql_exec(db, sql);
- sqlite3_free(sql);
-
- if( cam )
- {
- if( strcmp(cam, last_cam.name) != 0 )
- {
- container = insert_container(cam, "3$13", NULL, "storageFolder", NULL, NULL, NULL, NULL);
- sprintf(last_cam.parentID, "3$13$%llX", container>>32);
- strncpy(last_cam.name, cam, 255);
- last_camdate.name[0] = '\0';
- }
- if( strcmp(last_camdate.name, date_taken) == 0 )
- {
- last_camdate.objectID++;
- //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Using last camdate item: %s/%s/%s/%X\n", cam, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
- }
- else
- {
- container = insert_container(date_taken, last_cam.parentID, NULL, "album.photoAlbum", NULL, NULL, NULL, NULL);
- sprintf(last_camdate.parentID, "%s$%llX", last_cam.parentID, container>>32);
- last_camdate.objectID = (int)container;
- strcpy(last_camdate.name, date_taken);
- //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Creating cached camdate item: %s/%s/%s/%X\n", cam, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
- }
- sql = sqlite3_mprintf( "INSERT into OBJECTS"
- " (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
- "VALUES"
- " ('%s$%X', '%s', '%s', '%s', %lu, %Q)",
- last_camdate.parentID, last_camdate.objectID, last_camdate.parentID, refID, class, detailID, name);
- sql_exec(db, sql);
- sqlite3_free(sql);
- }
+ strncpy(date_taken, date, 10);
+ date_taken[10] = '\0';
}
+ else
+ {
+ strcpy(date_taken, "Unknown Date");
+ }
+ if( strcmp(last_date.name, date_taken) == 0 )
+ {
+ last_date.objectID++;
+ //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Using last date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
+ }
+ else
+ {
+ container = insert_container(date_taken, "3$12", NULL, "album.photoAlbum", NULL, NULL, NULL, NULL);
+ sprintf(last_date.parentID, "3$12$%llX", container>>32);
+ last_date.objectID = (int)container;
+ strcpy(last_date.name, date_taken);
+ //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Creating cached date item: %s/%s/%X\n", last_date.name, last_date.parentID, last_date.objectID);
+ }
+ sql = sqlite3_mprintf( "INSERT into OBJECTS"
+ " (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
+ "VALUES"
+ " ('%s$%X', '%s', '%s', '%s', %lu, %Q)",
+ last_date.parentID, last_date.objectID, last_date.parentID, refID, class, detailID, name);
+ sql_exec(db, sql);
+ sqlite3_free(sql);
+
+ if( cam )
+ {
+ strncpy(camera, cam, 63);
+ camera[63] = '\0';
+ }
+ else
+ {
+ strcpy(camera, "Unknown Camera");
+ }
+ if( strcmp(camera, last_cam.name) != 0 )
+ {
+ container = insert_container(camera, "3$13", NULL, "storageFolder", NULL, NULL, NULL, NULL);
+ sprintf(last_cam.parentID, "3$13$%llX", container>>32);
+ strncpy(last_cam.name, camera, 255);
+ last_camdate.name[0] = '\0';
+ }
+ if( strcmp(last_camdate.name, date_taken) == 0 )
+ {
+ last_camdate.objectID++;
+ //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Using last camdate item: %s/%s/%s/%X\n", camera, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
+ }
+ else
+ {
+ container = insert_container(date_taken, last_cam.parentID, NULL, "album.photoAlbum", NULL, NULL, NULL, NULL);
+ sprintf(last_camdate.parentID, "%s$%llX", last_cam.parentID, container>>32);
+ last_camdate.objectID = (int)container;
+ strcpy(last_camdate.name, date_taken);
+ //DEBUG DPRINTF(E_DEBUG, L_SCANNER, "Creating cached camdate item: %s/%s/%s/%X\n", camera, last_camdate.name, last_camdate.parentID, last_camdate.objectID);
+ }
+ sql = sqlite3_mprintf( "INSERT into OBJECTS"
+ " (OBJECT_ID, PARENT_ID, REF_ID, CLASS, DETAIL_ID, NAME) "
+ "VALUES"
+ " ('%s$%X', '%s', '%s', '%s', %lu, %Q)",
+ last_camdate.parentID, last_camdate.objectID, last_camdate.parentID, refID, class, detailID, name);
+ sql_exec(db, sql);
+ sqlite3_free(sql);
/* All Images */
if( !last_all_objectID )
{
@@ -244,8 +255,18 @@ insert_containers(const char * name, const char *path, const char * refID, const
}
else if( strstr(class, "audioItem") )
{
- char *artist = cols ? result[7+cols]:NULL, *album = cols ? result[8+cols]:NULL, *genre = cols ? result[9+cols]:NULL;
- char *album_art = cols ? result[19+cols]:NULL, *art_dlna_pn = cols ? result[20+cols]:NULL;
+ asprintf(&sql, "SELECT ARTIST, ALBUM, GENRE, ALBUM_ART, ART_DLNA_PN from DETAILS where ID = %lu", detailID);
+ ret = sql_get_table(db, sql, &result, &row, &cols);
+ free(sql);
+ if( ret != SQLITE_OK )
+ return;
+ if( !row )
+ {
+ sqlite3_free_table(result);
+ return;
+ }
+ char *artist = result[5], *album = result[6], *genre = result[7];
+ char *album_art = result[8], *art_dlna_pn = result[9];
static struct virtual_item last_album;
static struct virtual_item last_artist;
static struct virtual_item last_artistAlbum;
@@ -287,7 +308,7 @@ insert_containers(const char * name, const char *path, const char * refID, const
strcpy(last_artist.name, artist);
last_artistAlbum.name[0] = '\0';
/* Add this file to the "- All Albums -" container as well */
- container = insert_container("- All Albums -", last_artist.parentID, NULL, "storageFolder", NULL, genre, NULL, NULL);
+ container = insert_container("- All Albums -", last_artist.parentID, NULL, "storageFolder", artist, genre, NULL, NULL);
sprintf(last_artistAlbumAll.parentID, "%s$%llX", last_artist.parentID, container>>32);
last_artistAlbumAll.objectID = (int)container;
}
@@ -396,6 +417,11 @@ insert_containers(const char * name, const char *path, const char * refID, const
last_all_objectID++, refID, class, detailID, name);
sql_exec(db, sql);
sqlite3_free(sql);
+ return;
+ }
+ else
+ {
+ return;
}
sqlite3_free_table(result);
}
@@ -637,7 +663,7 @@ CreateDatabase(void)
if( ret != SQLITE_OK )
goto sql_failed;
ret = sql_exec(db, "CREATE TABLE SETTINGS ("
- "UPDATE_ID INTEGER PRIMARY KEY"
+ "UPDATE_ID INTEGER PRIMARY KEY DEFAULT 0"
")");
if( ret != SQLITE_OK )
goto sql_failed;
@@ -762,10 +788,7 @@ ScanDirectory(const char * dir, const char * parent, enum media_types type)
for (i=0; i < n; i++) {
sprintf(full_path, "%s/%s", dir, namelist[i]->d_name);
- if( index(namelist[i]->d_name, '&') )
- {
- name = modifyString(strdup(namelist[i]->d_name), "&", "&", 0);
- }
+ name = escape_tag(namelist[i]->d_name);
if( namelist[i]->d_type == DT_DIR )
{
insert_directory(name?name:namelist[i]->d_name, full_path, BROWSEDIR_ID, (parent ? parent:""), i+startID);
@@ -778,10 +801,7 @@ ScanDirectory(const char * dir, const char * parent, enum media_types type)
fileno++;
}
if( name )
- {
free(name);
- name = NULL;
- }
free(namelist[i]);
}
free(namelist);
diff --git a/tagutils/tagutils-mp3.c b/tagutils/tagutils-mp3.c
index f9c7f04..46d0ca6 100644
--- a/tagutils/tagutils-mp3.c
+++ b/tagutils/tagutils-mp3.c
@@ -696,7 +696,7 @@ _get_mp3fileinfo(char *file, struct song_metadata *psong)
index++;
if(first_check)
{
- DPRINTF(E_WARN, L_SCANNER, "Bad header... dropping back for full frame search\n");
+ DPRINTF(E_INFO, L_SCANNER, "Bad header... dropping back for full frame search [%s]\n", psong->path);
first_check = 0;
fp_size = 0;
break;
diff --git a/tivo_commands.c b/tivo_commands.c
index 1e6390f..b5baef9 100644
--- a/tivo_commands.c
+++ b/tivo_commands.c
@@ -42,7 +42,7 @@ SendRootContainer(struct upnphttp * h)
"