mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-24 22:25:56 -05:00
Add support for .pls playlists
This commit is contained in:
parent
1b51fcf07c
commit
ae3b5077ec
11
README
11
README
@ -237,11 +237,14 @@ them. Watch out for that.
|
||||
Playlists and internet radio
|
||||
----------------------------
|
||||
|
||||
forked-daapd supports M3U playlists. Just drop your playlist somewhere in
|
||||
your library with an .m3u extension and it will pick it up.
|
||||
forked-daapd supports M3U and PLS playlists. Just drop your playlist somewhere
|
||||
in your library with an .m3u or .pls extension and it will pick it up.
|
||||
|
||||
If the m3u contains an http URL it will be added as an internet radio station,
|
||||
and the URL will be probed for Shoutcast (ICY) metadata.
|
||||
If the playlist contains an http URL it will be added as an internet radio
|
||||
station, and the URL will be probed for Shoutcast (ICY) metadata.
|
||||
|
||||
forked-daapd does not support playlists in playlists (so for instance a .m3u
|
||||
where one of the items is another .m3u or .pls).
|
||||
|
||||
Support for iTunes Music Library XML format is available as a compile-time
|
||||
option. By default, metadata from our parsers is preferred over what's in
|
||||
|
@ -460,9 +460,9 @@ filescanner_process_media(char *path, time_t mtime, off_t size, int type, struct
|
||||
ext = strrchr(path, '.');
|
||||
if (ext)
|
||||
{
|
||||
if ((strcasecmp(ext, ".pls") == 0) || (strcasecmp(ext, ".url") == 0))
|
||||
if (strcasecmp(ext, ".url") == 0)
|
||||
{
|
||||
DPRINTF(E_INFO, L_SCAN, "No support for .url and .pls in this version, use .m3u\n");
|
||||
DPRINTF(E_INFO, L_SCAN, "No support for .url in this version, use .m3u or .pls\n");
|
||||
|
||||
return;
|
||||
}
|
||||
@ -599,7 +599,9 @@ process_playlist(char *file, time_t mtime)
|
||||
if (ext)
|
||||
{
|
||||
if (strcasecmp(ext, ".m3u") == 0)
|
||||
scan_m3u_playlist(file, mtime);
|
||||
scan_playlist(file, mtime);
|
||||
else if (strcasecmp(ext, ".pls") == 0)
|
||||
scan_playlist(file, mtime);
|
||||
#ifdef ITUNES
|
||||
else if (strcasecmp(ext, ".xml") == 0)
|
||||
scan_itunes_itml(file);
|
||||
@ -672,6 +674,7 @@ process_file(char *file, time_t mtime, off_t size, int type, int flags)
|
||||
if (ext)
|
||||
{
|
||||
if ((strcasecmp(ext, ".m3u") == 0)
|
||||
|| (strcasecmp(ext, ".pls") == 0)
|
||||
#ifdef ITUNES
|
||||
|| (strcasecmp(ext, ".xml") == 0)
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@ int
|
||||
scan_metadata_icy(char *url, struct media_file_info *mfi);
|
||||
|
||||
void
|
||||
scan_m3u_playlist(char *file, time_t mtime);
|
||||
scan_playlist(char *file, time_t mtime);
|
||||
|
||||
#ifdef ITUNES
|
||||
void
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include "filescanner.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* Formats we can read so far */
|
||||
#define PLAYLIST_PLS 1
|
||||
#define PLAYLIST_M3U 2
|
||||
|
||||
/* Get metadata from the EXTINF tag */
|
||||
static int
|
||||
@ -71,19 +74,21 @@ extinf_get(char *string, struct media_file_info *mfi, int *extinf)
|
||||
}
|
||||
|
||||
void
|
||||
scan_m3u_playlist(char *file, time_t mtime)
|
||||
scan_playlist(char *file, time_t mtime)
|
||||
{
|
||||
FILE *fp;
|
||||
struct media_file_info mfi;
|
||||
struct playlist_info *pli;
|
||||
struct stat sb;
|
||||
char buf[PATH_MAX];
|
||||
char *path;
|
||||
char *entry;
|
||||
char *filename;
|
||||
char *ptr;
|
||||
size_t len;
|
||||
int extinf;
|
||||
int pl_id;
|
||||
int pl_format;
|
||||
int mfi_id;
|
||||
int ret;
|
||||
int i;
|
||||
@ -98,6 +103,17 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = strrchr(file, '.');
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
if (strcasecmp(ptr, ".m3u") == 0)
|
||||
pl_format = PLAYLIST_M3U;
|
||||
else if (strcasecmp(ptr, ".pls") == 0)
|
||||
pl_format = PLAYLIST_PLS;
|
||||
else
|
||||
return;
|
||||
|
||||
filename = strrchr(file, '/');
|
||||
if (!filename)
|
||||
filename = file;
|
||||
@ -145,7 +161,7 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
ret = db_pl_add(buf, file, &pl_id);
|
||||
if (ret < 0)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SCAN, "Error adding m3u playlist '%s'\n", file);
|
||||
DPRINTF(E_LOG, L_SCAN, "Error adding playlist '%s'\n", file);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -159,12 +175,6 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL)
|
||||
{
|
||||
len = strlen(buf);
|
||||
if (len >= (sizeof(buf) - 1))
|
||||
{
|
||||
DPRINTF(E_LOG, L_SCAN, "Playlist entry exceeds PATH_MAX, discarding\n");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* rtrim and check that length is sane (ignore blank lines) */
|
||||
while ((len > 0) && isspace(buf[len - 1]))
|
||||
@ -176,19 +186,29 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
continue;
|
||||
|
||||
/* Saves metadata in mfi if EXTINF metadata line */
|
||||
if (extinf_get(buf, &mfi, &extinf))
|
||||
if ((pl_format == PLAYLIST_M3U) && extinf_get(buf, &mfi, &extinf))
|
||||
continue;
|
||||
|
||||
/* For pls files we are only interested in the part after the FileX= entry */
|
||||
path = NULL;
|
||||
if ((pl_format == PLAYLIST_PLS) && (strncasecmp(buf, "file", strlen("file")) == 0))
|
||||
path = strchr(buf, '=') + 1;
|
||||
else if (pl_format == PLAYLIST_M3U)
|
||||
path = buf;
|
||||
|
||||
if (!path)
|
||||
continue;
|
||||
|
||||
/* Check that first char is sane for a path */
|
||||
if ((!isalnum(buf[0])) && (buf[0] != '/') && (buf[0] != '.'))
|
||||
if ((!isalnum(path[0])) && (path[0] != '/') && (path[0] != '.'))
|
||||
continue;
|
||||
|
||||
/* Check if line is an URL, will be added to library */
|
||||
if (strcmp(buf, "http://") > 0)
|
||||
if (strncasecmp(path, "http://", strlen("http://")) == 0)
|
||||
{
|
||||
DPRINTF(E_DBG, L_SCAN, "Playlist contains URL entry\n");
|
||||
|
||||
filename = strdup(buf);
|
||||
filename = strdup(path);
|
||||
if (!filename)
|
||||
{
|
||||
DPRINTF(E_LOG, L_SCAN, "Out of memory for playlist filename\n");
|
||||
@ -204,11 +224,11 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
/* Regular file, should already be in library */
|
||||
else
|
||||
{
|
||||
/* m3u might be from Windows so we change backslash to forward slash */
|
||||
for (i = 0; i < strlen(buf); i++)
|
||||
/* Playlist might be from Windows so we change backslash to forward slash */
|
||||
for (i = 0; i < strlen(path); i++)
|
||||
{
|
||||
if (buf[i] == '\\')
|
||||
buf[i] = '/';
|
||||
if (path[i] == '\\')
|
||||
path[i] = '/';
|
||||
}
|
||||
|
||||
/* Now search for the library item where the path has closest match to playlist item */
|
||||
@ -217,7 +237,7 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
entry = NULL;
|
||||
do
|
||||
{
|
||||
ptr = strrchr(buf, '/');
|
||||
ptr = strrchr(path, '/');
|
||||
if (entry)
|
||||
*(entry - 1) = '/';
|
||||
if (ptr)
|
||||
@ -226,7 +246,7 @@ scan_m3u_playlist(char *file, time_t mtime)
|
||||
entry = ptr + 1;
|
||||
}
|
||||
else
|
||||
entry = buf;
|
||||
entry = path;
|
||||
|
||||
DPRINTF(E_SPAM, L_SCAN, "Playlist entry is now %s\n", entry);
|
||||
ret = db_files_get_count_bymatch(entry);
|
||||
|
Loading…
Reference in New Issue
Block a user