Add support for M3U metadata (extinf)

This commit is contained in:
ejurgensen 2013-10-15 13:36:11 +02:00
parent 6fb718b55e
commit d710e6ee95
3 changed files with 155 additions and 70 deletions

View File

@ -296,7 +296,7 @@ fixup_tags(struct media_file_info *mfi)
void void
process_media_file(char *file, time_t mtime, off_t size, int compilation, int url) process_media_file(char *file, time_t mtime, off_t size, int compilation, int url, struct extinf_ctx *extinf)
{ {
struct media_file_info mfi; struct media_file_info mfi;
char *filename; char *filename;
@ -305,6 +305,41 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation, int ur
int id; int id;
int ret; int ret;
filename = strrchr(file, '/');
if (!filename)
{
DPRINTF(E_LOG, L_SCAN, "Could not determine filename for %s\n", file);
return;
}
/* File types which should never be processed */
ext = strrchr(file, '.');
if (ext)
{
if ((strcmp(ext, ".pls") == 0) || (strcmp(ext, ".url") == 0))
{
DPRINTF(E_INFO, L_SCAN, "No support for .url and .pls in this version, use .m3u\n");
return;
}
else if ((strcmp(ext, ".png") == 0) || (strcmp(ext, ".jpg") == 0))
{
/* Artwork files - don't scan */
return;
}
else if ((strcmp(ext, ".db") == 0) || (strcmp(ext, ".ini") == 0))
{
/* System files - don't scan */
return;
}
else if ((strlen(filename) > 1) && ((filename[1] == '_') || (filename[1] == '.')))
{
/* Hidden files - don't scan */
return;
}
}
db_file_stamp_bypath(file, &stamp, &id); db_file_stamp_bypath(file, &stamp, &id);
if (stamp >= mtime) if (stamp >= mtime)
@ -318,14 +353,6 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation, int ur
if (stamp) if (stamp)
mfi.id = db_file_id_bypath(file); mfi.id = db_file_id_bypath(file);
filename = strrchr(file, '/');
if (!filename)
{
DPRINTF(E_LOG, L_SCAN, "Could not determine filename for %s\n", file);
return;
}
mfi.fname = strdup(filename + 1); mfi.fname = strdup(filename + 1);
if (!mfi.fname) if (!mfi.fname)
{ {
@ -346,54 +373,20 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation, int ur
mfi.time_modified = mtime; mfi.time_modified = mtime;
mfi.file_size = size; mfi.file_size = size;
ret = -1; if (!url)
/* Special cases */
ext = strrchr(file, '.');
if (ext)
{
if ((strcmp(ext, ".pls") == 0)
|| (strcmp(ext, ".url") == 0))
{
DPRINTF(E_INFO, L_SCAN, "No support for .url and .pls in this version, use .m3u\n");
goto out;
}
else if ((strcmp(ext, ".png") == 0)
|| (strcmp(ext, ".jpg") == 0))
{
/* Artwork - don't scan */
goto out;
}
else if ((strcmp(ext, ".db") == 0)
|| (strcmp(ext, ".ini") == 0))
{
/* System files - don't scan */
goto out;
}
else if ((filename[1] == '_')
|| (filename[1] == '.'))
{
/* Hidden files - don't scan */
goto out;
}
}
/* General case */
if (ret < 0)
{
if (url == 0)
{ {
mfi.data_kind = 0; /* real file */ mfi.data_kind = 0; /* real file */
ret = scan_metadata_ffmpeg(file, &mfi); ret = scan_metadata_ffmpeg(file, &mfi);
} }
else if (url == 1) else
{ {
mfi.data_kind = 1; /* url/stream */ mfi.data_kind = 1; /* url/stream */
ret = scan_metadata_icy(file, &mfi); if (extinf && extinf->found)
{
mfi.artist = strdup(extinf->artist);
mfi.title = strdup(extinf->title);
} }
else ret = scan_metadata_icy(file, &mfi);
ret = -1;
} }
if (ret < 0) if (ret < 0)
@ -526,7 +519,7 @@ process_file(char *file, time_t mtime, off_t size, int compilation, int flags)
} }
/* Not any kind of special file, so let's see if it's a media file */ /* Not any kind of special file, so let's see if it's a media file */
process_media_file(file, mtime, size, compilation, 0); process_media_file(file, mtime, size, compilation, 0, NULL);
} }

View File

@ -10,8 +10,15 @@ filescanner_init(void);
void void
filescanner_deinit(void); filescanner_deinit(void);
struct extinf_ctx
{
char *artist;
char *title;
int found;
};
void void
process_media_file(char *file, time_t mtime, off_t size, int compilation, int url); process_media_file(char *file, time_t mtime, off_t size, int compilation, int url, struct extinf_ctx *extinf);
/* Actual scanners */ /* Actual scanners */
int int

View File

@ -34,18 +34,92 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <regex.h>
#include "logger.h" #include "logger.h"
#include "db.h" #include "db.h"
#include "filescanner.h" #include "filescanner.h"
#include "misc.h" #include "misc.h"
static int
get_extinf(char *string, struct extinf_ctx *extinf)
{
regex_t *regex;
regmatch_t *regmatch;
size_t matchlen;
if (strcmp(string, "#EXTINF:") <= 0)
{
DPRINTF(E_DBG, L_SCAN, "Playlist line has no EXTINF data\n");
return 0;
}
regex = (regex_t*)malloc(sizeof(regex_t));
if (!regex)
{
DPRINTF(E_LOG, L_SCAN, "Out of memory for playlist regex.\n");
return 0;
}
regcomp(regex, "^#EXTINF:.*,(.*?)-(.*)",REG_EXTENDED|REG_NEWLINE);
regmatch = (regmatch_t*)malloc(sizeof(regmatch_t) * (1 + regex->re_nsub));
if (!regmatch)
{
DPRINTF(E_LOG, L_SCAN, "Out of memory for playlist regmatch.\n");
goto regexfail;
}
if (regexec(regex, string, 1 + regex->re_nsub, regmatch, 0))
{
DPRINTF(E_DBG, L_SCAN, "Playlist line has no EXTINF data\n");
goto regmatchfail;
}
/* Found extinf */
if (regmatch[0].rm_so != -1)
{
DPRINTF(E_DBG, L_SCAN, "Playlist line has EXTINF data\n");
/* Artist */
if (extinf->artist)
free(extinf->artist);
matchlen = regmatch[1].rm_eo - regmatch[1].rm_so;
extinf->artist = (char*)malloc(matchlen + 1);
strncpy(extinf->artist, string + regmatch[1].rm_so, matchlen + 1);
extinf->artist[matchlen]='\0';
/* Title */
if (extinf->title)
free(extinf->title);
matchlen = regmatch[1].rm_eo - regmatch[1].rm_so;
extinf->title = (char*)malloc(matchlen + 1);
strncpy(extinf->title, string + regmatch[1].rm_so, matchlen + 1);
extinf->title[matchlen]='\0';
free(regmatch);
regfree(regex);
return 1;
}
regmatchfail:
free(regmatch);
regexfail:
regfree(regex);
return 0;
}
void void
scan_m3u_playlist(char *file, time_t mtime) scan_m3u_playlist(char *file, time_t mtime)
{ {
FILE *fp; FILE *fp;
struct playlist_info *pli; struct playlist_info *pli;
struct stat sb; struct stat sb;
struct extinf_ctx extinf;
char buf[PATH_MAX]; char buf[PATH_MAX];
char *entry; char *entry;
char *filename; char *filename;
@ -121,30 +195,36 @@ scan_m3u_playlist(char *file, time_t mtime)
DPRINTF(E_INFO, L_SCAN, "Added playlist as id %d\n", pl_id); DPRINTF(E_INFO, L_SCAN, "Added playlist as id %d\n", pl_id);
} }
extinf.found = 0;
while (fgets(buf, sizeof(buf), fp) != NULL) while (fgets(buf, sizeof(buf), fp) != NULL)
{ {
len = strlen(buf); len = strlen(buf);
if (buf[len - 1] != '\n') if (len >= (sizeof(buf) - 1))
{ {
DPRINTF(E_WARN, L_SCAN, "Entry exceeds PATH_MAX, discarding\n"); DPRINTF(E_LOG, L_SCAN, "Playlist entry exceeds PATH_MAX, discarding\n");
while (fgets(buf, sizeof(buf), fp) != NULL)
{
if (buf[strlen(buf) - 1] == '\n')
break;
}
continue; continue;
} }
if ((!isalnum(buf[0])) && (buf[0] != '/')) /* rtrim and check that length is sane (ignore blank lines) */
continue; while ((len > 0) && isspace(buf[len - 1]))
while (isspace(buf[len - 1]))
{ {
len--; len--;
buf[len] = '\0'; buf[len] = '\0';
} }
if (len < 1)
continue;
/* Saves metadata in extinf if EXTINF metadata line */
if (get_extinf(buf, &extinf))
{
extinf.found = 1;
continue;
}
/* Check that first char is sane for a path */
if ((!isalnum(buf[0])) && (buf[0] != '/') && (buf[0] != '.'))
continue;
/* Check if line is an URL */ /* Check if line is an URL */
if (strcmp(buf, "http://") > 0) if (strcmp(buf, "http://") > 0)
@ -159,7 +239,7 @@ scan_m3u_playlist(char *file, time_t mtime)
continue; continue;
} }
process_media_file(filename, mtime, 0, 0, 1); process_media_file(filename, mtime, 0, 0, 1, &extinf);
} }
/* Regular file */ /* Regular file */
else else
@ -218,6 +298,7 @@ scan_m3u_playlist(char *file, time_t mtime)
if (ret < 0) if (ret < 0)
DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename); DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename);
extinf.found = 0;
free(filename); free(filename);
} }
@ -230,6 +311,10 @@ scan_m3u_playlist(char *file, time_t mtime)
} }
fclose(fp); fclose(fp);
if (extinf.artist)
free(extinf.artist);
if (extinf.title)
free(extinf.title);
DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n"); DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n");
} }