mirror of
https://github.com/owntone/owntone-server.git
synced 2025-03-31 09:43:45 -04:00
Merge branch 'm3u_extinf'
This commit is contained in:
commit
cc6d5670d7
@ -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,21 @@ 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)
|
mfi.data_kind = 0; /* real file */
|
||||||
|| (strcmp(ext, ".url") == 0))
|
ret = scan_metadata_ffmpeg(file, &mfi);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* General case */
|
|
||||||
if (ret < 0)
|
|
||||||
{
|
{
|
||||||
if (url == 0)
|
mfi.data_kind = 1; /* url/stream */
|
||||||
{
|
if (extinf && extinf->found)
|
||||||
mfi.data_kind = 0; /* real file */
|
{
|
||||||
ret = scan_metadata_ffmpeg(file, &mfi);
|
mfi.artist = strdup(extinf->artist);
|
||||||
|
mfi.title = strdup(extinf->artist);
|
||||||
|
mfi.album = strdup(extinf->title);
|
||||||
}
|
}
|
||||||
else if (url == 1)
|
ret = scan_metadata_icy(file, &mfi);
|
||||||
{
|
|
||||||
mfi.data_kind = 1; /* url/stream */
|
|
||||||
ret = scan_metadata_icy(file, &mfi);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@ -526,7 +520,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -664,7 +664,7 @@ scan_metadata_ffmpeg(char *file, struct media_file_info *mfi)
|
|||||||
}
|
}
|
||||||
#endif /* MUSEPACK */
|
#endif /* MUSEPACK */
|
||||||
else
|
else
|
||||||
DPRINTF(E_WARN, L_SCAN, "Could not extract any metadata\n");
|
DPRINTF(E_WARN, L_SCAN, "ffmpeg/libav could not extract any metadata\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just in case there's no title set ... */
|
/* Just in case there's no title set ... */
|
||||||
|
@ -231,6 +231,13 @@ scan_metadata_icy(char *url, struct media_file_info *mfi)
|
|||||||
*/
|
*/
|
||||||
no_icy:
|
no_icy:
|
||||||
ret = scan_metadata_ffmpeg(url, mfi);
|
ret = scan_metadata_ffmpeg(url, mfi);
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_SCAN, "Playlist URL is unavailable for probe/metadata, assuming MP3 encoding\n");
|
||||||
|
mfi->type = strdup("mp3");
|
||||||
|
mfi->codectype = strdup("mpeg");
|
||||||
|
mfi->description = strdup("MPEG audio file");
|
||||||
|
}
|
||||||
|
|
||||||
/* Wait till ICY request completes or we reach timeout */
|
/* Wait till ICY request completes or we reach timeout */
|
||||||
for (i = 0; (status == ICY_WAITING) && (i <= ICY_TIMEOUT); i++)
|
for (i = 0; (status == ICY_WAITING) && (i <= ICY_TIMEOUT); i++)
|
||||||
@ -240,5 +247,5 @@ scan_metadata_icy(char *url, struct media_file_info *mfi)
|
|||||||
|
|
||||||
DPRINTF(E_DBG, L_SCAN, "scan_metadata_icy exiting with status %d after waiting %d sec\n", status, i);
|
DPRINTF(E_DBG, L_SCAN, "scan_metadata_icy exiting with status %d after waiting %d sec\n", status, i);
|
||||||
|
|
||||||
return ret;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -40,12 +40,58 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Get metadata from the EXTINF tag */
|
||||||
|
static int
|
||||||
|
extinf_get(char *string, struct extinf_ctx *extinf)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
|
||||||
|
if (strcmp(string, "#EXTINF:") <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ptr = strchr(string, ',');
|
||||||
|
if (!ptr || strlen(ptr) < 2)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* New extinf found, so clear old data */
|
||||||
|
if (extinf->found)
|
||||||
|
{
|
||||||
|
free(extinf->artist);
|
||||||
|
free(extinf->title);
|
||||||
|
}
|
||||||
|
|
||||||
|
extinf->found = 1;
|
||||||
|
extinf->artist = strdup(ptr + 1);
|
||||||
|
|
||||||
|
ptr = strstr(extinf->artist, " -");
|
||||||
|
if (ptr && strlen(ptr) > 3)
|
||||||
|
extinf->title = strdup(ptr + 3);
|
||||||
|
else
|
||||||
|
extinf->title = strdup("");
|
||||||
|
if (ptr)
|
||||||
|
*ptr = '\0';
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
extinf_reset(struct extinf_ctx *extinf)
|
||||||
|
{
|
||||||
|
if (extinf->found)
|
||||||
|
{
|
||||||
|
free(extinf->artist);
|
||||||
|
free(extinf->title);
|
||||||
|
}
|
||||||
|
extinf->found = 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 +167,34 @@ 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 (extinf_get(buf, &extinf))
|
||||||
|
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)
|
||||||
@ -154,18 +204,21 @@ scan_m3u_playlist(char *file, time_t mtime)
|
|||||||
filename = strdup(buf);
|
filename = strdup(buf);
|
||||||
if (!filename)
|
if (!filename)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_SCAN, "Out of memory for playlist filename.\n");
|
DPRINTF(E_LOG, L_SCAN, "Out of memory for playlist filename\n");
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_media_file(filename, mtime, 0, 0, 1);
|
if (extinf.found)
|
||||||
|
DPRINTF(E_INFO, L_SCAN, "Playlist has EXTINF metadata, artist is '%s', title is '%s'\n", extinf.artist, extinf.title);
|
||||||
|
|
||||||
|
process_media_file(filename, mtime, 0, 0, 1, &extinf);
|
||||||
}
|
}
|
||||||
/* Regular file */
|
/* Regular file */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* m3u might be from Windows so we change backslash to forward slash */
|
/* m3u might be from Windows so we change backslash to forward slash */
|
||||||
for (i = 0; i < strlen(buf); i++)
|
for (i = 0; i < strlen(buf); i++)
|
||||||
{
|
{
|
||||||
if (buf[i] == '\\')
|
if (buf[i] == '\\')
|
||||||
buf[i] = '/';
|
buf[i] = '/';
|
||||||
@ -218,6 +271,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_reset(&extinf);
|
||||||
free(filename);
|
free(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user