MythTV master
pls.cpp
Go to the documentation of this file.
1/*
2 playlistfile (.pls) parser
3 Eskil Heyn Olsen, 2005, distributed under the GPL as part of mythtv.
4
5 Update July 2010 updated for Qt4 (Paul Harrison)
6 Update December 2012 updated to use QSettings for the pls parser
7 Update September 2014 add simple asx parser
8*/
9
10// c++
11#include <string>
12
13// qt
14#include <QDomDocument>
15#include <QFileInfo>
16#include <QList>
17#include <QMap>
18#include <QPair>
19#include <QRegularExpression>
20#include <QSettings>
21#include <QStringList>
22
23// MythTV
25
26// mythmusic
27#include "pls.h"
28
30{
31 clear();
32}
33
34int PlayListFile::parse(PlayListFile *pls, const QString &filename)
35{
36 int result = 0;
37 QString extension = QFileInfo(filename).suffix().toLower();
38
39 if (extension == "pls")
40 result = PlayListFile::parsePLS(pls, filename);
41 else if (extension == "m3u")
42 result = PlayListFile::parseM3U(pls, filename);
43 else if (extension == "asx")
44 result = PlayListFile::parseASX(pls, filename);
45
46 return result;
47}
48
50{
51 LOG(VB_FILE, LOG_DEBUG, QString("DecoderHandler: parsePLS - '%1'").arg(filename));
52
53 QSettings settings(filename, QSettings::IniFormat);
54
55 // we allow both 'playlist' and 'Playlist' for the group name
56 QStringList groups = settings.childGroups();
57
58 if (groups.contains("playlist"))
59 settings.beginGroup("playlist");
60 else if (groups.contains("Playlist"))
61 settings.beginGroup("Playlist");
62 else
63 {
64 LOG(VB_GENERAL, LOG_ERR, QString("DecoderHandler: parsePLS - playlist group not found"));
65 return 0;
66 }
67
68 int num_entries = -1;
69
70 // Some pls files have "numberofentries", some have "NumberOfEntries".
71 QStringList keys = settings.childKeys();
72
73 if (keys.contains("numberofentries"))
74 num_entries = settings.value("numberofentries", -1).toInt();
75 else if (keys.contains("NumberOfEntries"))
76 num_entries = settings.value("NumberOfEntries", -1).toInt();
77 else
78 {
79 LOG(VB_GENERAL, LOG_ERR, QString("DecoderHandler: parsePLS - NumberOfEntries key not found"));
80 return 0;
81 }
82
83 for (int n = 1; n <= num_entries; n++)
84 {
85 auto *e = new PlayListFileEntry();
86 QString t_key = QString("Title%1").arg(n);
87 QString f_key = QString("File%1").arg(n);
88 QString l_key = QString("Length%1").arg(n);
89
90 e->setFile(settings.value(f_key).toString());
91 e->setTitle(settings.value(t_key).toString());
92 e->setLength(settings.value(l_key).toInt());
93
94 pls->add(e);
95 }
96
97 return pls->size();
98}
99
100static constexpr const char* M3U_HEADER { "#EXTM3U" };
101static constexpr const char* M3U_INFO { "#EXTINF" };
102
104{
105 QFile f(filename);
106 if (!f.open(QIODevice::ReadOnly))
107 return 0;
108
109 QTextStream stream(&f);
110 QString data = stream.readAll();
111 static const QRegularExpression kNewlineRE { "\\R" }; // Any unicode newline
112 QStringList lines = data.split(kNewlineRE);
113
114 QStringList::iterator it;
115 for (it = lines.begin(); it != lines.end(); ++it)
116 {
117 // ignore empty lines
118 if (it->isEmpty())
119 continue;
120
121 // ignore the M3U header
122 if (it->startsWith(M3U_HEADER))
123 continue;
124
125 // for now ignore M3U info lines
126 if (it->startsWith(M3U_INFO))
127 continue;
128
129 // add to the playlist
130 auto *e = new PlayListFileEntry();
131 e->setFile(*it);
132 e->setTitle(*it);
133 e->setLength(-1);
134
135 pls->add(e);
136 }
137
138 return pls->size();
139}
140
142{
143 QDomDocument doc("mydocument");
144 QFile file(filename);
145 if (!file.open(QIODevice::ReadOnly))
146 return 0;
147
148 if (!doc.setContent(&file))
149 {
150 file.close();
151 return 0;
152 }
153 file.close();
154
155 //QDomElement docElem = doc.documentElement();
156 QDomNodeList entryList = doc.elementsByTagName("Entry");
157 QString url;
158
159 for (int x = 0; x < entryList.count(); x++)
160 {
161 QDomNode n = entryList.item(x);
162 QDomElement elem = n.toElement();
163 QDomNodeList refList = elem.elementsByTagName("ref");
164 for (int y = 0; y < refList.count(); y++)
165 {
166 QDomNode n2 = refList.item(y);
167 QDomElement elem2 = n2.toElement();
168 if (!elem2.isNull())
169 {
170 url = elem2.attribute("href");
171
172 // add to the playlist
173 auto *e = new PlayListFileEntry();
174 e->setFile(url.replace("mms://", "mmsh://"));
175 e->setTitle(url.replace("mms://", "mmsh://"));
176 e->setLength(-1);
177
178 pls->add(e);
179 }
180 }
181 }
182
183 return pls->size();
184}
Class for representing entries in a pls file.
Definition: pls.h:20
Class for containing the info of a pls or m3u file.
Definition: pls.h:42
static int parsePLS(PlayListFile *pls, const QString &filename)
Parse a pls file.
Definition: pls.cpp:49
void add(PlayListFileEntry *e)
Add a entry to the playlist.
Definition: pls.h:80
static int parseASX(PlayListFile *pls, const QString &filename)
Parse a asx file.
Definition: pls.cpp:141
static int parseM3U(PlayListFile *pls, const QString &filename)
Parse a m3u file.
Definition: pls.cpp:103
void clear(void)
Clear out all the entries.
Definition: pls.h:83
static int parse(PlayListFile *pls, const QString &filename)
Parse a pls, m3u or asx playlist file.
Definition: pls.cpp:34
int size(void) const
Get the number of entries in the pls file.
Definition: pls.h:54
~PlayListFile(void)
Definition: pls.cpp:29
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static constexpr const char * M3U_INFO
Definition: pls.cpp:101
static constexpr const char * M3U_HEADER
Definition: pls.cpp:100