00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <string>
00012
00013
00014 #include <QPair>
00015 #include <QList>
00016 #include <QMap>
00017 #include <QStringList>
00018
00019
00020 #include <mythlogging.h>
00021
00022
00023 #include "pls.h"
00024
00025
00026 using namespace std;
00027
00028 class CfgReader
00029 {
00030 public:
00031 CfgReader()
00032 {
00033 }
00034 ~CfgReader()
00035 {
00036 }
00037
00038 typedef QPair<QString,QString> KeyValue;
00039 typedef QList<KeyValue> KeyValueList;
00040 typedef QMap<QString, KeyValueList> ConfigMap;
00041
00042 void parse(const char *d, int l)
00043 {
00044 const char *ptr = d;
00045 int line = 1;
00046 bool done = l <= 0;
00047
00048 QString current_section = "";
00049 KeyValueList keyvals;
00050
00051 while(!done)
00052 {
00053 switch(*ptr)
00054 {
00055 case '\0':
00056 done = true;
00057 break;
00058 case '#':
00059 {
00060 const char *end = strchr(ptr, '\n');
00061 if (!end) done = true;
00062 ptr = end;
00063 break;
00064 }
00065 case '\n':
00066 ptr ++;
00067 line ++;
00068 break;
00069 case '[':
00070 {
00071 ptr ++;
00072 const char *nl = strchr(ptr, '\n');
00073 const char *end = strchr(ptr, ']');
00074
00075 if (!nl) nl = d + l;
00076
00077 if (!end || nl < end)
00078 {
00079 LOG(VB_GENERAL, LOG_ERR,
00080 QString("CfgReader:: Badly formatted section, "
00081 "line %1").arg(line));
00082 done = true;
00083 }
00084
00085 if (current_section.length() > 0)
00086 {
00087 cfg[current_section] = keyvals;
00088 keyvals = KeyValueList();
00089 }
00090
00091 current_section = std::string(ptr, end - ptr).c_str();
00092 if (current_section.length() == 0)
00093 {
00094 LOG(VB_GENERAL, LOG_ERR,
00095 QString("CfgReader:: Badly formatted section, "
00096 "line %1").arg(line));
00097 done = true;
00098 }
00099 ptr = end + 1;
00100 break;
00101 }
00102 default:
00103 {
00104 if (current_section.length() > 0)
00105 {
00106 const char *eq = strchr(ptr, '=');
00107 const char *nl = strchr(ptr, '\n');
00108
00109 if (!nl) nl = d + l;
00110
00111 if (!eq || nl < eq)
00112 {
00113 LOG(VB_GENERAL, LOG_ERR,
00114 QString("CfgReader:: Badly formatted line %1")
00115 .arg(line));
00116 done = true;
00117 }
00118 else
00119 {
00120 QString key = string(ptr, eq - ptr).c_str();
00121 QString val = string(eq + 1, nl - eq - 1).c_str();
00122 keyvals.push_back(KeyValue(key, val));
00123 ptr = nl;
00124 }
00125 }
00126 else
00127 {
00128 LOG(VB_GENERAL, LOG_ERR,
00129 QString("CfgReader:: Badly formatted line %1")
00130 .arg(line));
00131 done = true;
00132 }
00133 break;
00134 }
00135 }
00136
00137 if (ptr - d == l)
00138 done = true;
00139 }
00140
00141 if (current_section.length() > 0)
00142 cfg[current_section] = keyvals;
00143 }
00144
00145 QList<QString> getSections(void)
00146 {
00147 QList<QString> res;
00148 for (ConfigMap::iterator it = cfg.begin(); it != cfg.end(); ++it)
00149 res.push_back(it.key());
00150 return res;
00151 }
00152
00153 QList<QString> getKeys(const QString §ion)
00154 {
00155 KeyValueList keylist = cfg[section];
00156 QList<QString> res;
00157 for (KeyValueList::iterator it = keylist.begin();
00158 it != keylist.end(); ++it)
00159 {
00160 res.push_back((*it).first);
00161 }
00162 return res;
00163 }
00164
00165 QString getStrVal(const QString §ion, const QString &key,
00166 const QString &def = "")
00167 {
00168 KeyValueList keylist = cfg[section];
00169 QString res = def;
00170 for (KeyValueList::iterator it = keylist.begin();
00171 it != keylist.end(); ++it)
00172 {
00173 if ((*it).first == key)
00174 {
00175 res =(*it).second;
00176 break;
00177 }
00178 }
00179 return res;
00180 }
00181
00182 int getIntVal(const QString §ion, const QString &key, int def=0)
00183 {
00184 QString def_str;
00185 def_str.setNum (def);
00186 return getStrVal(section, key, def_str).toInt();
00187 }
00188
00189 private:
00190 ConfigMap cfg;
00191 };
00192
00193
00194
00195 PlayListFile::PlayListFile(void) : m_version(0)
00196 {
00197 }
00198
00199 PlayListFile::~PlayListFile(void)
00200 {
00201 clear();
00202 }
00203
00204 int PlayListFile::parse(PlayListFile *pls, QTextStream *stream, const QString &extension)
00205 {
00206 int result = 0;
00207
00208 if (extension == "pls")
00209 result = PlayListFile::parsePLS(pls, stream);
00210 else if (extension == "m3u")
00211 result = PlayListFile::parseM3U(pls, stream);
00212
00213 return result;
00214 }
00215
00216 int PlayListFile::parsePLS(PlayListFile *pls, QTextStream *stream)
00217 {
00218 int parsed = 0;
00219 QString d = stream->readAll();
00220 CfgReader cfg;
00221 cfg.parse(d.toAscii(), d.length());
00222
00223 int num_entries = cfg.getIntVal("playlist", "numberofentries", -1);
00224
00225
00226 if (num_entries == -1)
00227 num_entries = cfg.getIntVal("playlist", "NumberOfEntries", -1);
00228
00229 for (int n = 1; n <= num_entries; n++)
00230 {
00231 PlayListFileEntry *e = new PlayListFileEntry();
00232 QString t_key = QString("Title%1").arg(n);
00233 QString f_key = QString("File%1").arg(n);
00234 QString l_key = QString("Length%1").arg(n);
00235
00236 e->setFile(cfg.getStrVal("playlist", f_key));
00237 e->setTitle(cfg.getStrVal("playlist", t_key));
00238 e->setLength(cfg.getIntVal("playlist", l_key));
00239
00240 pls->add(e);
00241 parsed++;
00242 }
00243
00244 return parsed;
00245 }
00246
00247 #define M3U_HEADER "#EXTM3U"
00248 #define M3U_INFO "#EXTINF"
00249
00250 int PlayListFile::parseM3U(PlayListFile *pls, QTextStream *stream)
00251 {
00252 QString data = stream->readAll();
00253 QStringList lines = data.split("\r\n");
00254
00255 QStringList::iterator it;
00256 for (it = lines.begin(); it != lines.end(); ++it)
00257 {
00258
00259 if (it->isEmpty())
00260 continue;
00261
00262
00263 if (it->startsWith(M3U_HEADER))
00264 continue;
00265
00266
00267 if (it->startsWith(M3U_INFO))
00268 continue;
00269
00270
00271 PlayListFileEntry *e = new PlayListFileEntry();
00272 e->setFile(*it);
00273 e->setTitle(*it);
00274 e->setLength(-1);
00275
00276 pls->add(e);
00277 }
00278
00279 return pls->size();
00280 }