summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphintuka <phintuka>2007-01-03 10:03:38 +0000
committerphintuka <phintuka>2007-01-03 10:03:38 +0000
commit88a32bbaeb827e19cc9226dd6c1fe339b949a732 (patch)
tree56d267aac8b3162b05772bacceaf9a0693d458bf
parentda45a128dbe244cd929437d29e3248c02bc00b2b (diff)
downloadxineliboutput-88a32bbaeb827e19cc9226dd6c1fe339b949a732.tar.gz
xineliboutput-88a32bbaeb827e19cc9226dd6c1fe339b949a732.tar.bz2
Fixed sorting
Fixed metainfo cache reading Fixed metainfo cache generating with empty meta info strings Reduced logging Enabled recursive directory scanning Extended playlist name with directory name
-rw-r--r--tools/playlist.c199
1 files changed, 121 insertions, 78 deletions
diff --git a/tools/playlist.c b/tools/playlist.c
index 6a28c413..373c9da3 100644
--- a/tools/playlist.c
+++ b/tools/playlist.c
@@ -4,7 +4,7 @@
* See the main source file 'xineliboutput.c' for copyright information and
* how to reach the author.
*
- * $Id: playlist.c,v 1.1 2006-12-24 16:01:28 phintuka Exp $
+ * $Id: playlist.c,v 1.2 2007-01-03 10:03:38 phintuka Exp $
*
*/
@@ -25,7 +25,7 @@
# define PLAYLIST_CACHE ".xineliboutput-playlist.pls"
#endif
-#define MAX_PLAYLIST_FILES 256
+#define MAX_PLAYLIST_FILES 1024
//
@@ -74,16 +74,22 @@ int cPlaylistItem::Compare(const cListObject &ListObject) const
const cPlaylistItem *o = (cPlaylistItem *)&ListObject;
// Use Position (if defined in playlist file)
- if(Position != o->Position) {
- if(Position == -1)
- return -1;
- if(o->Position == -1)
- return 1;
+ if(Position != o->Position)
return Position > o->Position ? 1 : -1;
- }
- /* same position or no positions definend -> alphabetical order */
+ // same position (or no positions definend) -> alphabetical order
+#if 0
return strcmp(Track, o->Track);
+#else
+ // use filename, because:
+ // - implicit playlist has no track names available when sorting
+ // (track names are read during playback), so track name is
+ // just file name without path.
+ // using full path allows sorting of each album and tracks inside albums...
+ // - "normal" playlist is ordered using Position,
+ // so track names are never compared anyway ...
+ return strcmp(Filename, o->Filename);
+#endif
}
@@ -106,7 +112,7 @@ class cID3Scanner : public cThread
{
cPlaylistItem *Item = NULL;
- nice(10);
+ (void)nice(10);
cCondWait::SleepMs(5000);
LOGDBG("ID3Scanner Started");
@@ -127,17 +133,17 @@ class cID3Scanner : public cThread
cReadLine r;
char *pt;
while(NULL != (pt = r.Read(p))) {
- if(!strncmp(pt, "Artist: ", 8))
+ if(!strncmp(pt, "Artist: ", 8) && strlen(pt) > 9)
Item->Artist = (pt+8);
- if(!strncmp(pt, "Album: ", 7))
+ if(!strncmp(pt, "Album: ", 7) && strlen(pt) > 8)
Item->Album = (pt+7);
- if(!strncmp(pt, "Track: ", 7))
+ if(!strncmp(pt, "Track: ", 7) && strlen(pt) > 8)
Item->Track = (pt+7);
}
}
}
}
- LOGDBG("ID3Scanner: Done.");
+ LOGDBG("ID3Scanner Done.");
m_List.PlaylistChanged(Item);
m_Done = true;
@@ -210,12 +216,12 @@ class cPlsReader : public cPlaylistReader
1 == sscanf(line + 4, "%d=", &n)) {
m_Current = n;
m_Position = n;
- if(t && *(t+1))
+ if(*(t+1))
return t+1;
}
else if(!strncasecmp(line, "title", 5) &&
1 == sscanf(line + 5, "%d=", &n)) {
- if(t++) {
+ if(*(t+1)) {
if(n == m_Current)
Prev()->Track = t;
else
@@ -391,10 +397,11 @@ bool cPlaylist::StoreCache(void)
}
entries++;
fprintf(f, "File%d=%s\r\n", entries, *Filename);
- fprintf(f, "Title%d=%s\r\n", entries, *i->Track);
- if(*i->Artist)
+ if(*i->Track && (*i->Track)[0])
+ fprintf(f, "Title%d=%s\r\n", entries, *i->Track);
+ if(*i->Artist && (*i->Artist)[0])
fprintf(f, "Artist%d=%s\r\n", entries, *i->Artist);
- if(*i->Album)
+ if(*i->Album && (*i->Album)[0])
fprintf(f, "Album%d=%s\r\n", entries, *i->Album);
}
}
@@ -409,6 +416,11 @@ bool cPlaylist::StoreCache(void)
return false;
}
+static const char *strchrnext(const char *s, char c)
+{
+ return (s = strchr(s, c)) ? ((*(s+1))?(s+1):NULL) : NULL;
+}
+
bool cPlaylist::ReadCache(void)
{
if(m_Origin == eImplicit && *m_Folder) {
@@ -423,24 +435,23 @@ bool cPlaylist::ReadCache(void)
while(NULL != (pt = r.Read(f))) {
if(!strncmp(pt, "File", 4)) {
it = NULL;
- cString Filename = strchr(pt, '=');
- for(cPlaylistItem *i = First(); i; i=Next(i)) {
- if(!strncmp(i->Filename, m_Folder, len)) {
- if(!strcmp(*i->Filename + len, Filename)) {
- it = i;
- break;
+ const char *Filename = strchrnext(pt+4, '=');
+ if(Filename && *Filename) {
+ for(cPlaylistItem *i = First(); i; i=Next(i)) {
+ if(!strncmp(i->Filename, m_Folder, len)) {
+ if(!strcmp(*i->Filename + len, Filename)) {
+ it = i;
+ break;
+ }
}
}
}
} else if(it && !strncmp(pt, "Title", 5)) {
- it->Track = strchr(pt, '=');
-LOGMSG("ReadCache: Track -> %s", *it->Track);
+ it->Track = strchrnext(pt, '=');
} else if(it && !strncmp(pt, "Artist", 6)) {
- it->Artist = strchr(pt, '=');
-LOGMSG("ReadCache: Artist -> %s", *it->Artist);
+ it->Artist = strchrnext(pt, '=');
} else if(it && !strncmp(pt, "Album", 5)) {
- it->Album = strchr(pt, '=');
-LOGMSG("ReadCache: Album -> %s", *it->Album);
+ it->Album = strchrnext(pt, '=');
} else {
/*it = NULL;*/
}
@@ -520,6 +531,7 @@ int cPlaylist::ScanFolder(const char *FolderName,
{
cMutexLock ml(&m_Lock);
static int depth = 0;
+
DIR *d = opendir(FolderName);
if (d) {
@@ -536,10 +548,16 @@ int cPlaylist::ScanFolder(const char *FolderName,
LOGMSG("ScanFolder: Too deep directory tree");
} else if(e->d_name[0]=='.') {
} else {
- depth++; /* limit depth */
- Buffer = cString::sprintf("%s/", *Buffer);
- n += ScanFolder(Buffer);
- depth--;
+ if(n<MAX_PLAYLIST_FILES) {
+ depth++; /* limit depth */
+ Buffer = cString::sprintf("%s/", *Buffer);
+ n += ScanFolder(Buffer, Recursive, Filter);
+ depth--;
+ } else {
+ if(!++warn)
+ LOGMSG("ScanFolder: Found over %d matching files, list truncated!", n);
+ break;
+ }
}
}
} else /* == if(!S_ISDIR(st.st_mode))*/ {
@@ -552,11 +570,12 @@ int cPlaylist::ScanFolder(const char *FolderName,
continue;
}
if((xc.*Filter)(Buffer)) {
+ /* TODO: Should ScanDir add contents of playlist files ... ? */
if(Filter == &config_t::IsPlaylistFile || !xc.IsPlaylistFile(Buffer)) {
n++;
if(n<MAX_PLAYLIST_FILES) {
Add(new cPlaylistItem(e->d_name, FolderName));
- LOGDBG("ScanFolder: %s", e->d_name);
+ //LOGDBG("ScanFolder: %s", e->d_name);
} else {
if(!++warn)
LOGMSG("ScanFolder: Found over %d matching files, list truncated!", n);
@@ -567,7 +586,7 @@ int cPlaylist::ScanFolder(const char *FolderName,
}
}
}
- LOGDBG("ScanFolder: Found %d matching files", n);
+ LOGDBG("ScanFolder: Found %d matching files from %s", n, FolderName);
closedir(d);
return n;
@@ -593,24 +612,24 @@ void cPlaylist::StartScanner(void)
struct stat stf, stc;
if(!stat(m_Folder, &stf)) {
if(!stat(CacheName, &stc)) {
- LOGMSG("Cache modified: %d, folder modified: %d, diff %d",
- (unsigned int)stc.st_mtime, (unsigned int)stf.st_mtime,
- (unsigned int)(stc.st_mtime - stf.st_mtime));
- if(stc.st_mtime < stf.st_mtime) {
- LOGMSG(" -> using up-to-date cache");
+ //LOGDBG("ID3 Cache modified %d, folder modified %d, diff %d",
+ // (unsigned int)stc.st_mtime, (unsigned int)stf.st_mtime,
+ // (unsigned int)(stc.st_mtime - stf.st_mtime));
+ if(stc.st_mtime >= stf.st_mtime) {
if(ReadCache()) {
- LOGMSG(" Cache read OK.");
+ LOGDBG("cPlaylist: using up-to-date ID3 cache");
+ //LOGMSG(" Cache read OK.");
return;
}
- LOGMSG(" Cache read FAILED");
+ LOGMSG("cPlaylist: ID3 cache read FAILED");
} else {
- LOGMSG(" -> using cache and scanning for changes");
+ LOGDBG("cPlaylist: ID3 cache not up-to-date, using old cache and scanning for changes");
ReadCache();
}
- } else
- LOGERR("stat(Cache) failed");
- } else
- LOGERR("stat(Folder) failed");
+ }
+ //else LOGERR("cPlaylist: stat(%s) failed");
+ }
+ //else LOGERR("cPlaylist: stat(%s) failed");
if(xc.enable_id3_scanner) {
m_Scanner = new cID3Scanner(*this);
@@ -629,9 +648,10 @@ int cPlaylist::ReadPlaylist(const char *file)
f = fopen(file, "r");
} else {
// fetch playlist from server using curl
+ LOGDBG("cPlaylist: fetching remote playlist from %s", file);
cString Cmd = cString::sprintf("curl %s", file);
if(!p.Open(Cmd, "r")) {
- LOGERR("CURL command (%s) failed", *Cmd);
+ LOGERR("cPlaylist: CURL command (%s) failed", *Cmd);
return false;
}
// process as normal file
@@ -639,7 +659,7 @@ int cPlaylist::ReadPlaylist(const char *file)
}
if(f) {
- LOGDBG("parse_playlist(%s)", file);
+ LOGDBG("cPlaylist: parsing %s", file);
char *pt = strrchr(file, '.');
if(!strcasecmp(pt, ".pls"))
parser = new cPlsReader(*this);
@@ -659,9 +679,9 @@ int cPlaylist::ReadPlaylist(const char *file)
if(xc.IsPlaylistFile(pt)) {
parser->ResetCache();
- LOGMSG("playlist inside playlist");
+ LOGDBG("cPlaylist: found playlist inside playlist");
if(depth > 4)
- LOGMSG("recursion too deep, skipped %s", pt);
+ LOGMSG("cPlaylist: recursion too deep, skipped %s", pt);
else {
depth++;
n += ReadPlaylist(pt);
@@ -682,7 +702,7 @@ int cPlaylist::ReadPlaylist(const char *file)
}
Last()->Position = parser->Position();
parser->ResetCache();
- LOGDBG("read_playlist: %s", pt);
+ //LOGDBG("read_playlist: %s", pt);
n++;
}
}
@@ -692,57 +712,80 @@ int cPlaylist::ReadPlaylist(const char *file)
fclose(f);
if(n >= MAX_PLAYLIST_FILES)
- LOGMSG("read_playlist: Found over %d matching files, list truncated!", n);
- LOGDBG("read_playlist: Found %d matching files", n);
+ LOGMSG("cPlaylist: Found over %d matching files, list truncated!", n);
+ LOGDBG("cPlaylist: Found %d matching files", n);
return n;
}
- LOGERR("read_playlist: Error opening %s", file);
+ LOGERR("cPlaylist: Error opening %s", file);
return 0;
}
+static cString LastDir(cString& path)
+{
+ cString tmp = strdup(path);
+ char *pt = strrchr(tmp, '/');
+ if(pt && pt > *tmp) {
+ *pt = 0;
+ pt = strrchr(tmp, '/');
+ if(pt)
+ return cString(pt+1);
+ }
+ return cString(NULL);
+}
+
bool cPlaylist::Read(const char *PlaylistFile, bool Recursive)
{
cMutexLock ml(&m_Lock);
bool Result = true;
+ // extract playlist root folder
m_Folder = PlaylistFile;
+ if(strrchr(m_Folder, '/'))
+ *(strrchr(m_Folder, '/') + 1) = 0;
- if(xc.IsPlaylistFile(PlaylistFile)) {
- // Playlist file
- char *pt = strrchr(PlaylistFile, '/');
- m_Name = pt ? pt+1 : "";
- *(strrchr(m_Name, '.')) = 0;
- if(strrchr(m_Folder, '/'))
- *(strrchr(m_Folder, '/') + 1) = 0;
+ if(xc.IsPlaylistFile(PlaylistFile)) {
+ // Read playlist file
Result = ReadPlaylist(PlaylistFile);
m_Origin = ePlaylist;
} else if(PlaylistFile[strlen(PlaylistFile)-1] == '/') {
- // Whole folder
- m_Name = PlaylistFile;
- if(strrchr(m_Name, '/'))
- *(strrchr(m_Name, '/')) = 0;
- if(strrchr(m_Name, '/'))
- m_Name = strrchr(m_Name, '/')+1;
-
+ // Scan folder
Result = ScanFolder(PlaylistFile, Recursive) > 0;
m_Origin = eImplicit;
-
Sort();
+ if(!*m_Name) {
+ m_Name = PlaylistFile;
+ *(strrchr(m_Name, '/')) = 0;
+ if(strrchr(m_Name, '/')) {
+ cString dir = LastDir(m_Name);
+ if(*dir)
+ m_Name = cString::sprintf("%s - %s", *dir, strrchr(m_Name, '/')+1);
+ else
+ m_Name = strrchr(m_Name, '/')+1;
+ }
+ }
+
} else {
// Single file
+ Add(new cPlaylistItem(PlaylistFile));
+ m_Origin = eImplicit;
+ }
+
+ if(!*m_Name) {
char *pt = strrchr(PlaylistFile, '/');
- m_Name = pt;
+ pt = pt ? pt+1 : NULL;
+
+ cString dir = LastDir(m_Folder);
+ if(*dir && pt)
+ m_Name = cString::sprintf("%s - %s", *dir, pt ?: "");
+ else
+ m_Name = pt ?: "";
+
if(strrchr(m_Name, '.'))
*(strrchr(m_Name, '.')) = 0;
- if(strrchr(m_Folder, '/'))
- *(strrchr(m_Folder, '/') + 1) = 0;
-
- Add(new cPlaylistItem(PlaylistFile));
- m_Origin = eImplicit;
}
if(Count() < 1) {