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