00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <qstringlist.h>
00035 #include <qdeepcopy.h>
00036 #include <qfile.h>
00037
00038
00039 #include "mythcontext.h"
00040 #include "mythdbcon.h"
00041 #include "dvbconfparser.h"
00042 #include "channelutil.h"
00043
00044 #define PARSE_SKIP(VAR) do { \
00045 if (it == tokens.end()) return false; else it++; } while(0)
00046
00047 #define PARSE_CONF(VAR) do { \
00048 if (it == tokens.end() || !VAR.ParseConf(*it++)) \
00049 return false; } while(0)
00050
00051 #define PARSE_STR(VAR) do { \
00052 if (it != tokens.end()) VAR = *it++; else return false; } while(0)
00053
00054 #define PARSE_UINT(VAR) do { \
00055 if (it != tokens.end()) \
00056 VAR = (*it++).toUInt(); else return false; } while(0)
00057
00058 #define PARSE_UINT_1000(VAR) do { \
00059 if (it != tokens.end()) \
00060 VAR = (*it++).toUInt() * 1000ULL; else return false; } while(0)
00061
00062
00063 QString DTVChannelInfo::toString() const
00064 {
00065 return QString("%1 %2 %3 ").arg(name).arg(serviceid).arg(lcn);
00066 }
00067
00068 DTVConfParser::DTVConfParser(enum cardtype_t _type, uint _sourceid,
00069 const QString &_file)
00070 : type(_type), sourceid(_sourceid), filename(QDeepCopy<QString>(_file))
00071 {
00072 }
00073
00074 DTVConfParser::return_t DTVConfParser::Parse(void)
00075 {
00076 channels.clear();
00077
00078 QFile file(filename);
00079 if (!file.open(IO_ReadOnly))
00080 return ERROR_OPEN;
00081
00082 bool ok = true;
00083 QTextStream stream(&file);
00084 QString line;
00085 while (!stream.atEnd())
00086 {
00087 line = stream.readLine();
00088 line.stripWhiteSpace();
00089 if (line.startsWith("#"))
00090 continue;
00091
00092 QStringList list = QStringList::split(":", line);
00093 QString str = *list.at(0);
00094 int channelNo = -1;
00095
00096 if (str.at(0) == '@')
00097 {
00098 channelNo = str.mid(1).toInt();
00099 line = stream.readLine();
00100 list = QStringList::split(":", line);
00101 }
00102
00103 str = *list.at(3);
00104
00105 if ((str == "T") || (str == "C") || (str == "S"))
00106 {
00107 if ((type == OFDM) && (str == "T"))
00108 ok &= ParseVDR(list, channelNo);
00109 else if ((type == QPSK) && (str == "S"))
00110 ok &= ParseVDR(list, channelNo);
00111 else if ((type == QAM) && (str == "C"))
00112 ok &= ParseVDR(list, channelNo);
00113 }
00114 else if (type == OFDM)
00115 ok &= ParseConfOFDM(list);
00116 else if (type == ATSC)
00117 ok &= ParseConfATSC(list);
00118 else if (type == QPSK)
00119 ok &= ParseConfQPSK(list);
00120 else if (type == QAM)
00121 ok &= ParseConfQAM(list);
00122 }
00123 file.close();
00124
00125 return (ok) ? OK : ERROR_PARSE;
00126 }
00127
00128 bool DTVConfParser::ParseConfOFDM(const QStringList &tokens)
00129 {
00130 DTVChannelInfo chan;
00131 DTVMultiplex mux;
00132
00133 QStringList::const_iterator it = tokens.begin();
00134
00135 PARSE_SKIP(unknown);
00136 PARSE_UINT(mux.frequency);
00137 PARSE_CONF(mux.inversion);
00138 PARSE_CONF(mux.bandwidth);
00139 PARSE_CONF(mux.hp_code_rate);
00140 PARSE_CONF(mux.lp_code_rate);
00141 PARSE_CONF(mux.modulation);
00142 PARSE_CONF(mux.trans_mode);
00143 PARSE_CONF(mux.guard_interval);
00144 PARSE_CONF(mux.hierarchy);
00145 PARSE_SKIP(unknown);
00146 PARSE_SKIP(unknown);
00147 PARSE_UINT(chan.serviceid);
00148
00149 AddChannel(mux, chan);
00150
00151 return true;
00152 }
00153
00154 bool DTVConfParser::ParseConfATSC(const QStringList &tokens)
00155 {
00156 DTVChannelInfo chan;
00157 DTVMultiplex mux;
00158
00159 QStringList::const_iterator it = tokens.begin();
00160
00161 PARSE_STR(chan.name);
00162 PARSE_UINT(mux.frequency);
00163 PARSE_CONF(mux.modulation);
00164 PARSE_SKIP(Ignore_Video_PID);
00165 PARSE_SKIP(Ignore_Audio_PID);
00166 PARSE_UINT(chan.serviceid);
00167
00168 AddChannel(mux, chan);
00169
00170 return true;
00171 }
00172
00173 bool DTVConfParser::ParseConfQAM(const QStringList &tokens)
00174 {
00175 DTVChannelInfo chan;
00176 DTVMultiplex mux;
00177
00178 QStringList::const_iterator it = tokens.begin();
00179
00180 PARSE_SKIP(unknown);
00181 PARSE_UINT(mux.frequency);
00182 PARSE_CONF(mux.inversion);
00183 PARSE_UINT(mux.symbolrate);
00184 PARSE_CONF(mux.fec);
00185 PARSE_CONF(mux.modulation);
00186 PARSE_SKIP(unknown);
00187 PARSE_SKIP(unknown);
00188 PARSE_UINT(chan.serviceid);
00189
00190 AddChannel(mux, chan);
00191
00192 return true;
00193 }
00194
00195 bool DTVConfParser::ParseConfQPSK(const QStringList &tokens)
00196 {
00197 DTVChannelInfo chan;
00198 DTVMultiplex mux;
00199
00200 QStringList::const_iterator it = tokens.begin();
00201
00202 PARSE_STR(chan.name);
00203 PARSE_UINT_1000(mux.frequency);
00204 PARSE_CONF(mux.polarity);
00205 PARSE_SKIP(Satelite_Number);
00206 PARSE_UINT_1000(mux.symbolrate);
00207 PARSE_SKIP(unknown);
00208 PARSE_SKIP(unknown);
00209 PARSE_UINT(chan.serviceid);
00210
00211 AddChannel(mux, chan);
00212
00213 return true;
00214 }
00215
00216 bool DTVConfParser::ParseVDR(const QStringList &tokens, int channelNo)
00217 {
00218 DTVChannelInfo chan;
00219 DTVMultiplex mux;
00220
00221 QStringList::const_iterator it = tokens.begin();
00222
00223 chan.lcn = channelNo;
00224
00225
00226
00227 PARSE_SKIP(unknown);
00228
00229 PARSE_UINT_1000(mux.frequency);
00230
00231 if (it == tokens.end())
00232 return false;
00233
00234 QString params = (*it++);
00235 while (!params.isEmpty())
00236 {
00237 QString ori = params;
00238 int s = *((const char*)params);
00239 params = params.mid(1);
00240 switch (s)
00241 {
00242 case 'I':
00243 mux.inversion.ParseVDR(params);
00244 break;
00245 case 'B':
00246 mux.bandwidth.ParseVDR(params);
00247 break;
00248 case 'C':
00249 mux.hp_code_rate.ParseVDR(params);
00250 break;
00251 case 'D':
00252 mux.lp_code_rate.ParseVDR(params);
00253 break;
00254 case 'M':
00255 mux.modulation.ParseVDR(params);
00256 break;
00257 case 'T':
00258 mux.trans_mode.ParseVDR(params);
00259 break;
00260 case 'G':
00261 mux.guard_interval.ParseVDR(params);
00262 break;
00263 case 'Y':
00264 mux.hierarchy.ParseVDR(params);
00265 break;
00266 case 'V':
00267 case 'H':
00268 case 'R':
00269 case 'L':
00270 mux.polarity.ParseVDR(ori);
00271 break;
00272 default:
00273 return false;
00274 }
00275 }
00276
00277 for (uint i = 0; i < 6; i++)
00278 PARSE_SKIP(unknown);
00279
00280 PARSE_UINT(chan.serviceid);
00281
00282 AddChannel(mux, chan);
00283
00284 return true;
00285 }
00286
00287 void DTVConfParser::AddChannel(const DTVMultiplex &mux, DTVChannelInfo &chan)
00288 {
00289 for (uint i = 0; i < channels.size(); i++)
00290 {
00291 if (channels[i] == mux)
00292 {
00293 channels[i].channels.push_back(chan);
00294
00295 VERBOSE(VB_IMPORTANT, "Imported channel: "<<chan.toString()
00296 <<" on "<<mux.toString());
00297 return;
00298 }
00299 }
00300
00301 channels.push_back(mux);
00302 channels.back().channels.push_back(chan);
00303
00304 VERBOSE(VB_IMPORTANT, "Imported channel: "<<chan.toString()
00305 <<" on "<<mux.toString());
00306 }