|
MythTV
0.26-pre
|
00001 /* 00002 playlistfile (.pls) parser 00003 Eskil Heyn Olsen, 2005, distributed under the GPL as part of mythtv. 00004 00005 Update July 2010 updated for Qt4 (Paul Harrison) 00006 00007 */ 00008 00009 // c 00010 //#include "iostream" 00011 #include <string> 00012 00013 // qt 00014 #include <QPair> 00015 #include <QList> 00016 #include <QMap> 00017 #include <QStringList> 00018 00019 // mythtv 00020 #include <mythlogging.h> 00021 00022 // mythmusic 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 // Some pls files have "numberofentries", some has "NumberOfEntries". 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 // ignore empty lines 00259 if (it->isEmpty()) 00260 continue; 00261 00262 // ignore the M3U header 00263 if (it->startsWith(M3U_HEADER)) 00264 continue; 00265 00266 // for now ignore M3U info lines 00267 if (it->startsWith(M3U_INFO)) 00268 continue; 00269 00270 // add to the playlist 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 }
1.7.6.1