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
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;
char *filename;
@ -305,6 +305,41 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation, int ur
int id;
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);
if (stamp >= mtime)
@ -318,14 +353,6 @@ process_media_file(char *file, time_t mtime, off_t size, int compilation, int ur
if (stamp)
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);
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.file_size = size;
ret = -1;
/* Special cases */
ext = strrchr(file, '.');
if (ext)
if (!url)
{
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;
}
mfi.data_kind = 0; /* real file */
ret = scan_metadata_ffmpeg(file, &mfi);
}
/* General case */
if (ret < 0)
else
{
if (url == 0)
{
mfi.data_kind = 0; /* real file */
ret = scan_metadata_ffmpeg(file, &mfi);
mfi.data_kind = 1; /* url/stream */
if (extinf && extinf->found)
{
mfi.artist = strdup(extinf->artist);
mfi.title = strdup(extinf->title);
}
else if (url == 1)
{
mfi.data_kind = 1; /* url/stream */
ret = scan_metadata_icy(file, &mfi);
}
else
ret = -1;
ret = scan_metadata_icy(file, &mfi);
}
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 */
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
filescanner_deinit(void);
struct extinf_ctx
{
char *artist;
char *title;
int found;
};
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 */
int

View File

@ -34,18 +34,92 @@
#include <sys/stat.h>
#include <errno.h>
#include <regex.h>
#include "logger.h"
#include "db.h"
#include "filescanner.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
scan_m3u_playlist(char *file, time_t mtime)
{
FILE *fp;
struct playlist_info *pli;
struct stat sb;
struct extinf_ctx extinf;
char buf[PATH_MAX];
char *entry;
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);
}
extinf.found = 0;
while (fgets(buf, sizeof(buf), fp) != NULL)
{
len = strlen(buf);
if (buf[len - 1] != '\n')
if (len >= (sizeof(buf) - 1))
{
DPRINTF(E_WARN, L_SCAN, "Entry exceeds PATH_MAX, discarding\n");
while (fgets(buf, sizeof(buf), fp) != NULL)
{
if (buf[strlen(buf) - 1] == '\n')
break;
}
DPRINTF(E_LOG, L_SCAN, "Playlist entry exceeds PATH_MAX, discarding\n");
continue;
}
if ((!isalnum(buf[0])) && (buf[0] != '/'))
continue;
while (isspace(buf[len - 1]))
/* rtrim and check that length is sane (ignore blank lines) */
while ((len > 0) && isspace(buf[len - 1]))
{
len--;
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 */
if (strcmp(buf, "http://") > 0)
@ -159,13 +239,13 @@ scan_m3u_playlist(char *file, time_t mtime)
continue;
}
process_media_file(filename, mtime, 0, 0, 1);
process_media_file(filename, mtime, 0, 0, 1, &extinf);
}
/* Regular file */
else
{
/* m3u might be from Windows so we change backslash to forward slash */
for (i = 0; i < strlen(buf); i++)
/* m3u might be from Windows so we change backslash to forward slash */
for (i = 0; i < strlen(buf); i++)
{
if (buf[i] == '\\')
buf[i] = '/';
@ -218,6 +298,7 @@ scan_m3u_playlist(char *file, time_t mtime)
if (ret < 0)
DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename);
extinf.found = 0;
free(filename);
}
@ -230,6 +311,10 @@ scan_m3u_playlist(char *file, time_t mtime)
}
fclose(fp);
if (extinf.artist)
free(extinf.artist);
if (extinf.title)
free(extinf.title);
DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n");
}