00001
00002 #include <qregexp.h>
00003 #include <qdir.h>
00004 #include <qfile.h>
00005
00006
00007 #include <iostream>
00008 #include <cstdlib>
00009
00010
00011 #include "mythcontext.h"
00012 #include "mythdbcon.h"
00013
00014
00015 #include "channelutil.h"
00016 #include "frequencytables.h"
00017 #include "cardutil.h"
00018 #include "sourceutil.h"
00019
00020
00021 #include "channeldata.h"
00022 #include "fillutil.h"
00023
00024 void get_atsc_stuff(QString channum, int sourceid, int freqid,
00025 int &major, int &minor, long long &freq)
00026 {
00027 major = freqid;
00028 minor = 0;
00029
00030 int chansep = channum.find(QRegExp("\\D"));
00031 if (chansep < 0)
00032 return;
00033
00034 major = channum.left(chansep).toInt();
00035 minor = channum.right(channum.length() - (chansep + 1)).toInt();
00036
00037 freq = get_center_frequency("atsc", "vsb8", "us", freqid);
00038
00039
00040 MSqlQuery query(MSqlQuery::DDCon());
00041 query.prepare(
00042 "SELECT cardtype "
00043 "FROM capturecard, cardinput "
00044 "WHERE cardinput.cardid = capturecard.cardid AND "
00045 " sourceid = :SOURCEID");
00046 query.bindValue(":SOURCEID", sourceid);
00047
00048 if (query.exec() && query.isActive() && query.next() &&
00049 query.value(0).toString() == "HDTV")
00050 {
00051 freq -= 1750000;
00052 }
00053 }
00054
00055 bool ChannelData::insert_chan(uint sourceid)
00056 {
00057 bool insert_channels = channel_updates;
00058 if (!insert_channels)
00059 {
00060 bool isEncoder, isUnscanable;
00061 if (cardtype.isEmpty())
00062 {
00063 isEncoder = SourceUtil::IsEncoder(sourceid);
00064 isUnscanable = SourceUtil::IsUnscanable(sourceid);
00065 }
00066 else
00067 {
00068 isEncoder = CardUtil::IsEncoder(cardtype);
00069 isUnscanable = CardUtil::IsUnscanable(cardtype);
00070 }
00071 insert_channels = (isEncoder || isUnscanable) && !remove_new_channels;
00072 }
00073
00074 return insert_channels;
00075 }
00076
00077
00078 QString getResponse(const QString &query, const QString &def)
00079 {
00080 cout << query;
00081
00082 if (def != "")
00083 {
00084 cout << " [" << (const char *)def.local8Bit() << "] ";
00085 }
00086
00087 char response[80];
00088 cin.getline(response, 80);
00089
00090 QString qresponse = QString::fromLocal8Bit(response);
00091
00092 if (qresponse == "")
00093 qresponse = def;
00094
00095 return qresponse;
00096 }
00097
00098 unsigned int ChannelData::promptForChannelUpdates(
00099 QValueList<ChanInfo>::iterator chaninfo, unsigned int chanid)
00100 {
00101 if (chanid == 0)
00102 {
00103
00104
00105
00106 chanid = atoi(getResponse("Choose a channel ID (positive integer) ",
00107 "0"));
00108
00109
00110 if (chanid == 0)
00111 return(0);
00112 }
00113
00114 (*chaninfo).name = getResponse("Choose a channel name (any string, "
00115 "long version) ",(*chaninfo).name);
00116 (*chaninfo).callsign = getResponse("Choose a channel callsign (any string, "
00117 "short version) ",(*chaninfo).callsign);
00118
00119 if (channel_preset)
00120 {
00121 (*chaninfo).chanstr = getResponse("Choose a channel preset (0..999) ",
00122 (*chaninfo).chanstr);
00123 (*chaninfo).freqid = getResponse("Choose a frequency id (just like "
00124 "xawtv) ",(*chaninfo).freqid);
00125 }
00126 else
00127 {
00128 (*chaninfo).chanstr = getResponse("Choose a channel number (just like "
00129 "xawtv) ",(*chaninfo).chanstr);
00130 (*chaninfo).freqid = (*chaninfo).chanstr;
00131 }
00132
00133 (*chaninfo).finetune = getResponse("Choose a channel fine tune offset (just"
00134 " like xawtv) ",(*chaninfo).finetune);
00135
00136 (*chaninfo).tvformat = getResponse("Choose a TV format "
00137 "(PAL/SECAM/NTSC/ATSC/Default) ",
00138 (*chaninfo).tvformat);
00139
00140 (*chaninfo).iconpath = getResponse("Choose a channel icon image (any path "
00141 "name) ",(*chaninfo).iconpath);
00142
00143 return(chanid);
00144 }
00145
00146 void ChannelData::handleChannels(int id, QValueList<ChanInfo> *chanlist)
00147 {
00148 QString fileprefix = SetupIconCacheDirectory();
00149
00150 QDir::setCurrent(fileprefix);
00151
00152 fileprefix += "/";
00153
00154 QValueList<ChanInfo>::iterator i = chanlist->begin();
00155 for (; i != chanlist->end(); i++)
00156 {
00157 QString localfile = "";
00158
00159 if ((*i).iconpath != "")
00160 {
00161 QDir remotefile = QDir((*i).iconpath);
00162 QString filename = remotefile.dirName();
00163
00164 localfile = fileprefix + filename;
00165 QFile actualfile(localfile);
00166 if (!actualfile.exists())
00167 {
00168 QString command = QString("wget ") + (*i).iconpath;
00169 system(command);
00170 }
00171 }
00172
00173 MSqlQuery query(MSqlQuery::InitCon());
00174
00175 QString querystr;
00176
00177 if ((*i).old_xmltvid != "")
00178 {
00179 querystr.sprintf("SELECT xmltvid FROM channel WHERE xmltvid = '%s'",
00180 (*i).old_xmltvid.ascii());
00181 query.exec(querystr);
00182
00183 if (query.isActive() && query.size() > 0)
00184 {
00185 VERBOSE(VB_GENERAL, QString("Converting old xmltvid (%1) to "
00186 "new (%2)")
00187 .arg((*i).old_xmltvid)
00188 .arg((*i).xmltvid));
00189
00190 query.exec(QString("UPDATE channel SET xmltvid = '%1' WHERE xmltvid = '%2';")
00191 .arg((*i).xmltvid)
00192 .arg((*i).old_xmltvid));
00193
00194 if (!query.numRowsAffected())
00195 MythContext::DBError("xmltvid conversion",query);
00196 }
00197 }
00198
00199 querystr.sprintf("SELECT chanid,name,callsign,channum,finetune,"
00200 "icon,freqid,tvformat FROM channel WHERE "
00201 "xmltvid = '%s' AND sourceid = %d;",
00202 (*i).xmltvid.ascii(), id);
00203
00204 query.exec(querystr);
00205 if (query.isActive() && query.size() > 0)
00206 {
00207 query.next();
00208
00209 QString chanid = query.value(0).toString();
00210 if (interactive)
00211 {
00212 QString name = QString::fromUtf8(query.value(1).toString());
00213 QString callsign = QString::fromUtf8(query.value(2).toString());
00214 QString chanstr = QString::fromUtf8(query.value(3).toString());
00215 QString finetune = QString::fromUtf8(query.value(4).toString());
00216 QString icon = QString::fromUtf8(query.value(5).toString());
00217 QString freqid = QString::fromUtf8(query.value(6).toString());
00218 QString tvformat = QString::fromUtf8(query.value(7).toString());
00219
00220 cout << "### " << endl;
00221 cout << "### Existing channel found" << endl;
00222 cout << "### " << endl;
00223 cout << "### xmltvid = " << (*i).xmltvid.local8Bit() << endl;
00224 cout << "### chanid = " << chanid.local8Bit() << endl;
00225 cout << "### name = " << name.local8Bit() << endl;
00226 cout << "### callsign = " << callsign.local8Bit() << endl;
00227 cout << "### channum = " << chanstr.local8Bit() << endl;
00228 if (channel_preset)
00229 cout << "### freqid = " << freqid.local8Bit() << endl;
00230 cout << "### finetune = " << finetune.local8Bit() << endl;
00231 cout << "### tvformat = " << tvformat.local8Bit() << endl;
00232 cout << "### icon = " << icon.local8Bit() << endl;
00233 cout << "### " << endl;
00234
00235 (*i).name = name;
00236 (*i).callsign = callsign;
00237 (*i).chanstr = chanstr;
00238 (*i).finetune = finetune;
00239 (*i).freqid = freqid;
00240 (*i).tvformat = tvformat;
00241
00242 promptForChannelUpdates(i, atoi(chanid.ascii()));
00243
00244 if ((*i).callsign == "")
00245 (*i).callsign = chanid;
00246
00247 if (name != (*i).name ||
00248 callsign != (*i).callsign ||
00249 chanstr != (*i).chanstr ||
00250 finetune != (*i).finetune ||
00251 freqid != (*i).freqid ||
00252 icon != localfile ||
00253 tvformat != (*i).tvformat)
00254 {
00255 MSqlQuery subquery(MSqlQuery::InitCon());
00256 subquery.prepare("UPDATE channel SET chanid = :CHANID, "
00257 "name = :NAME, callsign = :CALLSIGN, "
00258 "channum = :CHANNUM, finetune = :FINE, "
00259 "icon = :ICON, freqid = :FREQID, "
00260 "tvformat = :TVFORMAT "
00261 " WHERE xmltvid = :XMLTVID "
00262 "AND sourceid = :SOURCEID;");
00263 subquery.bindValue(":CHANID", chanid);
00264 subquery.bindValue(":NAME", (*i).name.utf8());
00265 subquery.bindValue(":CALLSIGN", (*i).callsign.utf8());
00266 subquery.bindValue(":CHANNUM", (*i).chanstr);
00267 subquery.bindValue(":FINE", (*i).finetune.toInt());
00268 subquery.bindValue(":ICON", localfile);
00269 subquery.bindValue(":FREQID", (*i).freqid);
00270 subquery.bindValue(":TVFORMAT", (*i).tvformat);
00271 subquery.bindValue(":XMLTVID", (*i).xmltvid);
00272 subquery.bindValue(":SOURCEID", id);
00273
00274 if (!subquery.exec())
00275 {
00276 VERBOSE(VB_IMPORTANT, QString("DB Error: Channel "
00277 "update failed, SQL query was: %1")
00278 .arg(querystr));
00279 }
00280 else
00281 {
00282 cout << "### " << endl;
00283 cout << "### Change performed" << endl;
00284 cout << "### " << endl;
00285 }
00286 }
00287 else
00288 {
00289 cout << "### " << endl;
00290 cout << "### Nothing changed" << endl;
00291 cout << "### " << endl;
00292 }
00293 }
00294 else
00295 {
00296 if (!non_us_updating && localfile != "")
00297 {
00298 MSqlQuery subquery(MSqlQuery::InitCon());
00299 subquery.prepare("UPDATE channel SET icon = :ICON WHERE "
00300 "chanid = :CHANID;");
00301 subquery.bindValue(":ICON", localfile);
00302 subquery.bindValue(":CHANID", chanid);
00303
00304 if (!subquery.exec())
00305 MythContext::DBError("Channel icon change", subquery);
00306 }
00307 }
00308 }
00309 else
00310 {
00311 int major, minor;
00312 long long freq;
00313 get_atsc_stuff((*i).chanstr, id, (*i).freqid.toInt(), major, minor, freq);
00314
00315 if (interactive && ((minor == 0) || (freq > 0)))
00316 {
00317 cout << "### " << endl;
00318 cout << "### New channel found" << endl;
00319 cout << "### " << endl;
00320 cout << "### name = " << (*i).name.local8Bit() << endl;
00321 cout << "### callsign = " << (*i).callsign.local8Bit() << endl;
00322 cout << "### channum = " << (*i).chanstr.local8Bit() << endl;
00323 if (channel_preset)
00324 cout << "### freqid = " << (*i).freqid.local8Bit() << endl;
00325 cout << "### finetune = " << (*i).finetune.local8Bit() << endl;
00326 cout << "### tvformat = " << (*i).tvformat.local8Bit() << endl;
00327 cout << "### icon = " << localfile.local8Bit() << endl;
00328 cout << "### " << endl;
00329
00330 uint chanid = promptForChannelUpdates(i,0);
00331
00332 if ((*i).callsign == "")
00333 (*i).callsign = QString::number(chanid);
00334
00335 int mplexid = 0;
00336 if ((chanid > 0) && (minor > 0))
00337 mplexid = ChannelUtil::CreateMultiplex(id, "atsc",
00338 freq, "8vsb");
00339
00340 if (((mplexid > 0) || ((minor == 0) && (chanid > 0))) &&
00341 ChannelUtil::CreateChannel(
00342 mplexid, id, chanid,
00343 (*i).callsign, (*i).name, (*i).chanstr,
00344 0 , major, minor,
00345 false , false ,
00346 false ,
00347 (*i).freqid, localfile, (*i).tvformat,
00348 (*i).xmltvid))
00349 {
00350 cout << "### " << endl;
00351 cout << "### Channel inserted" << endl;
00352 cout << "### " << endl;
00353 }
00354 else
00355 {
00356 cout << "### " << endl;
00357 cout << "### Channel skipped" << endl;
00358 cout << "### " << endl;
00359 }
00360 }
00361 else if (!non_us_updating && ((minor == 0) || (freq > 0)))
00362 {
00363
00364
00365 int mplexid = 0, chanid = 0;
00366 if (minor > 0)
00367 {
00368 mplexid = ChannelUtil::CreateMultiplex(
00369 id, "atsc", freq, "8vsb");
00370 }
00371
00372 if ((mplexid > 0) || (minor == 0))
00373 chanid = ChannelUtil::CreateChanID(id, (*i).chanstr);
00374
00375 if ((*i).callsign.isEmpty())
00376 {
00377 QStringList words = QStringList::split(" ",(*i).name.simplifyWhiteSpace().upper());
00378 QString callsign = "";
00379 QString w1 = words.size() > 0 ? words[0] : QString();
00380 QString w2 = words.size() > 1 ? words[1] : QString();
00381 if (w1.isEmpty())
00382 callsign = QString::number(chanid);
00383 else if (w2.isEmpty())
00384 callsign = words[0].left(5);
00385 else
00386 {
00387 callsign = w1.left(w2.length() == 1 ? 4:3);
00388 callsign += w2.left(5 - callsign.length());
00389 }
00390 (*i).callsign = callsign;
00391 }
00392
00393 if (chanid > 0)
00394 {
00395 QString cstr = QString((*i).chanstr);
00396 if(channel_preset && cstr.isEmpty())
00397 cstr = QString::number(chanid % 1000);
00398
00399 ChannelUtil::CreateChannel(
00400 mplexid, id, chanid,
00401 (*i).callsign, (*i).name, cstr,
00402 0 , major, minor,
00403 false , false ,
00404 false ,
00405 (*i).freqid, localfile, (*i).tvformat,
00406 (*i).xmltvid);
00407 }
00408 }
00409 }
00410 }
00411 }