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 {
60 settings.beginGroup("playlist");
61 }
62 else if (groups.contains("Playlist"))
63 {
64 settings.beginGroup("Playlist");
65 }
66 else
67 {
68 LOG(VB_GENERAL, LOG_ERR, QString("DecoderHandler: parsePLS - playlist group not found"));
69 return 0;
70 }
71
72 int num_entries = -1;
73
74 // Some pls files have "numberofentries", some have "NumberOfEntries".
75 QStringList keys = settings.childKeys();
76
77 if (keys.contains("numberofentries"))
78 {
79 num_entries = settings.value("numberofentries", -1).toInt();
80 }
81 else if (keys.contains("NumberOfEntries"))
82 {
83 num_entries = settings.value("NumberOfEntries", -1).toInt();
84 }
85 else
86 {
87 LOG(VB_GENERAL, LOG_ERR, QString("DecoderHandler: parsePLS - NumberOfEntries key not found"));
88 return 0;
89 }
90
91 for (int n = 1; n <= num_entries; n++)
92 {
93 auto *e = new PlayListFileEntry();
94 QString t_key = QString("Title%1").arg(n);
95 QString f_key = QString("File%1").arg(n);
96 QString l_key = QString("Length%1").arg(n);
97
98 e->setFile(settings.value(f_key).toString());
99 e->setTitle(settings.value(t_key).toString());
100 e->setLength(settings.value(l_key).toInt());
101
102 pls->add(e);
103 }
104
105 return pls->size();
106}
107
108static constexpr const char* M3U_HEADER { "#EXTM3U" };
109static constexpr const char* M3U_INFO { "#EXTINF" };
110
112{
113 QFile f(filename);
114 if (!f.open(QIODevice::ReadOnly))
115 return 0;
116
117 QTextStream stream(&f);
118 QString data = stream.readAll();
119 static const QRegularExpression kNewlineRE { "\\R" }; // Any unicode newline
120 QStringList lines = data.split(kNewlineRE);
121
122 QStringList::iterator it;
123 for (it = lines.begin(); it != lines.end(); ++it)
124 {
125 // ignore empty lines
126 if (it->isEmpty())
127 continue;
128
129 // ignore the M3U header
130 if (it->startsWith(M3U_HEADER))
131 continue;
132
133 // for now ignore M3U info lines
134 if (it->startsWith(M3U_INFO))
135 continue;
136
137 // add to the playlist
138 auto *e = new PlayListFileEntry();
139 e->setFile(*it);
140 e->setTitle(*it);
141 e->setLength(-1);
142
143 pls->add(e);
144 }
145
146 return pls->size();
147}
148
150{
151 QDomDocument doc("mydocument");
152 QFile file(filename);
153 if (!file.open(QIODevice::ReadOnly))
154 return 0;
155
156 if (!doc.setContent(&file))
157 {
158 file.close();
159 return 0;
160 }
161 file.close();
162
163 //QDomElement docElem = doc.documentElement();
164 QDomNodeList entryList = doc.elementsByTagName("Entry");
165 QString url;
166
167 for (int x = 0; x < entryList.count(); x++)
168 {
169 QDomNode n = entryList.item(x);
170 QDomElement elem = n.toElement();
171 QDomNodeList refList = elem.elementsByTagName("ref");
172 for (int y = 0; y < refList.count(); y++)
173 {
174 QDomNode n2 = refList.item(y);
175 QDomElement elem2 = n2.toElement();
176 if (!elem2.isNull())
177 {
178 url = elem2.attribute("href");
179
180 // add to the playlist
181 auto *e = new PlayListFileEntry();
182 e->setFile(url.replace("mms://", "mmsh://"));
183 e->setTitle(url.replace("mms://", "mmsh://"));
184 e->setLength(-1);
185
186 pls->add(e);
187 }
188 }
189 }
190
191 return pls->size();
192}
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:149
static int parseM3U(PlayListFile *pls, const QString &filename)
Parse a m3u file.
Definition: pls.cpp:111
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:109
static constexpr const char * M3U_HEADER
Definition: pls.cpp:108