00001 #include <QWidget>
00002 #include <QFile>
00003
00004 #include "channelsettings.h"
00005 #include "channelutil.h"
00006 #include "programinfo.h"
00007 #include "mpegtables.h"
00008 #include "mythdirs.h"
00009 #include "cardutil.h"
00010
00011 QString ChannelDBStorage::GetWhereClause(MSqlBindings &bindings) const
00012 {
00013 QString fieldTag = (":WHERE" + id.getField().toUpper());
00014 QString query(id.getField() + " = " + fieldTag);
00015
00016 bindings.insert(fieldTag, id.getValue());
00017
00018 return query;
00019 }
00020
00021 QString ChannelDBStorage::GetSetClause(MSqlBindings &bindings) const
00022 {
00023 QString fieldTag = (":SET" + id.getField().toUpper());
00024 QString nameTag = (":SET" + GetColumnName().toUpper());
00025
00026 QString query(id.getField() + " = " + fieldTag + ", " +
00027 GetColumnName() + " = " + nameTag);
00028
00029 bindings.insert(fieldTag, id.getValue());
00030 bindings.insert(nameTag, user->GetDBValue());
00031
00032 return query;
00033 }
00034
00035
00036
00037
00038
00039 class Name : public LineEditSetting, public ChannelDBStorage
00040 {
00041 public:
00042 Name(const ChannelID &id) :
00043 LineEditSetting(this), ChannelDBStorage(this, id, "name")
00044 {
00045 setLabel(QObject::tr("Channel Name"));
00046 }
00047 };
00048
00049 class Channum : public LineEditSetting, public ChannelDBStorage
00050 {
00051 public:
00052 Channum(const ChannelID &id) :
00053 LineEditSetting(this), ChannelDBStorage(this, id, "channum")
00054 {
00055 setLabel(QObject::tr("Channel Number"));
00056 }
00057 };
00058
00059 class Source : public ComboBoxSetting, public ChannelDBStorage
00060 {
00061 public:
00062 Source(const ChannelID &id, uint _default_sourceid) :
00063 ComboBoxSetting(this), ChannelDBStorage(this, id, "sourceid"),
00064 default_sourceid(_default_sourceid)
00065 {
00066 setLabel(QObject::tr("Video Source"));
00067 }
00068
00069 void Load(void)
00070 {
00071 fillSelections();
00072 ChannelDBStorage::Load();
00073
00074 if (default_sourceid && !getValue().toUInt())
00075 {
00076 uint which = sourceid_to_index[default_sourceid];
00077 if (which)
00078 setValue(which);
00079 }
00080 }
00081
00082 void fillSelections(void)
00083 {
00084 addSelection(QObject::tr("[Not Selected]"), "0");
00085
00086 MSqlQuery query(MSqlQuery::InitCon());
00087 query.prepare("SELECT name, sourceid "
00088 "FROM videosource "
00089 "ORDER BY sourceid");
00090
00091 if (!query.exec() || !query.isActive())
00092 {
00093 MythDB::DBError("Source::fillSelections", query);
00094 }
00095 else
00096 {
00097 for (uint i = 1; query.next(); i++)
00098 {
00099 sourceid_to_index[query.value(1).toUInt()] = i;
00100 addSelection(query.value(0).toString(),
00101 query.value(1).toString());
00102 }
00103 }
00104
00105 sourceid_to_index[0] = 0;
00106 }
00107
00108 private:
00109 uint default_sourceid;
00110 QMap<uint,uint> sourceid_to_index;
00111 };
00112
00113 class Callsign : public LineEditSetting, public ChannelDBStorage
00114 {
00115 public:
00116 Callsign(const ChannelID &id) :
00117 LineEditSetting(this), ChannelDBStorage(this, id, "callsign")
00118 {
00119 setLabel(QObject::tr("Callsign"));
00120 }
00121 };
00122
00123 ChannelTVFormat::ChannelTVFormat(const ChannelID &id) :
00124 ComboBoxSetting(this), ChannelDBStorage(this, id, "tvformat")
00125 {
00126 setLabel(QObject::tr("TV Format"));
00127 setHelpText(
00128 QObject::tr(
00129 "If this channel uses a format other than TV "
00130 "Format in the General Backend Setup screen, set it here."));
00131
00132 addSelection(QObject::tr("Default"), "Default");
00133
00134 QStringList list = GetFormats();
00135 for (int i = 0; i < list.size(); i++)
00136 addSelection(list[i]);
00137 }
00138
00139 QStringList ChannelTVFormat::GetFormats(void)
00140 {
00141 QStringList list;
00142
00143 list.push_back("NTSC");
00144 list.push_back("NTSC-JP");
00145 list.push_back("PAL");
00146 list.push_back("PAL-60");
00147 list.push_back("PAL-BG");
00148 list.push_back("PAL-DK");
00149 list.push_back("PAL-D");
00150 list.push_back("PAL-I");
00151 list.push_back("PAL-M");
00152 list.push_back("PAL-N");
00153 list.push_back("PAL-NC");
00154 list.push_back("SECAM");
00155 list.push_back("SECAM-D");
00156 list.push_back("SECAM-DK");
00157
00158 return list;
00159 }
00160
00161 class TimeOffset : public SpinBoxSetting, public ChannelDBStorage
00162 {
00163 public:
00164 TimeOffset(const ChannelID &id) :
00165 SpinBoxSetting(this, -1440, 1440, 1),
00166 ChannelDBStorage(this, id, "tmoffset")
00167 {
00168 setLabel(QObject::tr("DataDirect") + " " + QObject::tr("Time Offset"));
00169 setHelpText(QObject::tr("Offset (in minutes) to apply to the program "
00170 "guide data during import. This can be used when the "
00171 "listings for a particular channel are in a different "
00172 "time zone.") + " " +
00173 QObject::tr("(Works for DataDirect listings only.)"));
00174 }
00175 };
00176
00177 class Priority : public SpinBoxSetting, public ChannelDBStorage
00178 {
00179 public:
00180 Priority(const ChannelID &id) :
00181 SpinBoxSetting(this, -99, 99, 1),
00182 ChannelDBStorage(this, id, "recpriority")
00183 {
00184 setLabel(QObject::tr("Priority"));
00185 setHelpText(
00186 QObject::tr("Number of priority points to be added to any "
00187 "recording on this channel during scheduling.")+" "+
00188 QObject::tr("Use a positive number as the priority if you "
00189 "want this to be a preferred channel, a "
00190 "negative one to deprecate this channel."));
00191 }
00192 };
00193
00194 class Icon : public LineEditSetting, public ChannelDBStorage
00195 {
00196 public:
00197 Icon(const ChannelID &id) :
00198 LineEditSetting(this), ChannelDBStorage(this, id, "icon")
00199 {
00200 setLabel(QObject::tr("Icon"));
00201 setHelpText(QObject::tr("Image file to use as the icon for this "
00202 "channel on various MythTV displays."));
00203 }
00204 };
00205
00206 class VideoFilters : public LineEditSetting, public ChannelDBStorage
00207 {
00208 public:
00209 VideoFilters(const ChannelID &id) :
00210 LineEditSetting(this), ChannelDBStorage(this, id, "videofilters")
00211 {
00212 setLabel(QObject::tr("Video filters"));
00213 setHelpText(QObject::tr("Filters to be used when recording "
00214 "from this channel. Not used with "
00215 "hardware encoding cards."));
00216
00217 }
00218 };
00219
00220
00221 class OutputFilters : public LineEditSetting, public ChannelDBStorage
00222 {
00223 public:
00224 OutputFilters(const ChannelID &id) :
00225 LineEditSetting(this), ChannelDBStorage(this, id, "outputfilters")
00226 {
00227 setLabel(QObject::tr("Playback filters"));
00228 setHelpText(QObject::tr("Filters to be used when recordings "
00229 "from this channel are viewed. "
00230 "Start with a plus to append to the "
00231 "global playback filters."));
00232 }
00233 };
00234
00235 class XmltvID : public ComboBoxSetting, public ChannelDBStorage
00236 {
00237 public:
00238 XmltvID(const ChannelID &id, const QString &_sourceName) :
00239 ComboBoxSetting(this, true), ChannelDBStorage(this, id, "xmltvid"),
00240 sourceName(_sourceName)
00241 {
00242 setLabel(QObject::tr("XMLTV ID"));
00243 setHelpText(QObject::tr(
00244 "ID used by listing services to get an exact "
00245 "correspondance between a channel in your line-up "
00246 "and a channel in their database. Normally this is "
00247 "set automatically when 'mythfilldatabase' is run."));
00248 }
00249
00250 void Load(void)
00251 {
00252 fillSelections();
00253 ChannelDBStorage::Load();
00254 }
00255
00256 void fillSelections(void)
00257 {
00258 clearSelections();
00259
00260 QString xmltvFile = GetConfDir() + '/' + sourceName + ".xmltv";
00261
00262 if (QFile::exists(xmltvFile))
00263 {
00264 QFile file(xmltvFile);
00265 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
00266 return;
00267
00268 QStringList idList;
00269
00270 while (!file.atEnd())
00271 {
00272 QByteArray line = file.readLine();
00273
00274 if (line.startsWith("channel="))
00275 {
00276 QString id = line.mid(8, -1).trimmed();
00277 idList.append(id);
00278 }
00279 }
00280
00281 idList.sort();
00282
00283 for (int x = 0; x < idList.size(); x++)
00284 addSelection(idList.at(x), idList.at(x));
00285 }
00286 }
00287
00288 private:
00289 QString sourceName;
00290 };
00291
00292 class CommMethod : public ComboBoxSetting, public ChannelDBStorage
00293 {
00294 public:
00295 CommMethod(const ChannelID &id) :
00296 ComboBoxSetting(this), ChannelDBStorage(this, id, "commmethod")
00297 {
00298 setLabel(QObject::tr("Commercial Detection Method"));
00299 setHelpText(QObject::tr("Changes the method of "
00300 "commercial detection used for recordings on this channel or "
00301 "skips detection by marking the channel as Commercial Free."));
00302
00303 deque<int> tmp = GetPreferredSkipTypeCombinations();
00304 tmp.push_front(COMM_DETECT_UNINIT);
00305 tmp.push_back(COMM_DETECT_COMMFREE);
00306
00307 for (uint i = 0; i < tmp.size(); i++)
00308 addSelection(SkipTypeToString(tmp[i]), QString::number(tmp[i]));
00309 }
00310 };
00311
00312 class Visible : public CheckBoxSetting, public ChannelDBStorage
00313 {
00314 public:
00315 Visible(const ChannelID &id) :
00316 CheckBoxSetting(this), ChannelDBStorage(this, id, "visible")
00317 {
00318 setValue(true);
00319 setLabel(QObject::tr("Visible"));
00320 setHelpText(QObject::tr("If enabled, the channel will be visible in the "
00321 "EPG."));
00322 }
00323 };
00324
00325 class OnAirGuide : public CheckBoxSetting, public ChannelDBStorage
00326 {
00327 public:
00328 OnAirGuide(const ChannelID &id) :
00329 CheckBoxSetting(this), ChannelDBStorage(this, id, "useonairguide")
00330 {
00331 setLabel(QObject::tr("Use on air guide"));
00332 setHelpText(QObject::tr("If enabled, guide information for this "
00333 "channel will be updated using 'Over-the-Air' "
00334 "program listings."));
00335 }
00336 };
00337
00338
00339
00340
00341
00342 class Freqid : public LineEditSetting, public ChannelDBStorage
00343 {
00344 public:
00345 Freqid(const ChannelID &id) :
00346 LineEditSetting(this), ChannelDBStorage(this, id, "freqid")
00347 {
00348 setLabel(QObject::tr("Frequency")+" "+QObject::tr("or")+" "+
00349 QObject::tr("Channel"));
00350 setHelpText(QObject::tr(
00351 "Specify either the exact frequency (in kHz) or "
00352 "a valid channel for your 'TV Format'."));
00353 }
00354 };
00355
00356 class Finetune : public SliderSetting, public ChannelDBStorage
00357 {
00358 public:
00359 Finetune(const ChannelID& id)
00360 : SliderSetting(this, -300, 300, 1),
00361 ChannelDBStorage(this, id, "finetune")
00362 {
00363 setLabel(QObject::tr("Finetune")+" (kHz)");
00364 setHelpText(QObject::tr("Value to be added to your desired frequency "
00365 "(in kHz) for 'fine tuning'."));
00366 }
00367 };
00368
00369 class Contrast : public SliderSetting, public ChannelDBStorage
00370 {
00371 public:
00372 Contrast(const ChannelID &id) :
00373 SliderSetting(this, 0, 65535, 655),
00374 ChannelDBStorage(this, id, "contrast")
00375 {
00376 setLabel(QObject::tr("Contrast"));
00377 }
00378 };
00379
00380 class Brightness : public SliderSetting, public ChannelDBStorage
00381 {
00382 public:
00383 Brightness(const ChannelID &id) :
00384 SliderSetting(this, 0, 65535, 655),
00385 ChannelDBStorage(this, id, "brightness")
00386 {
00387 setLabel(QObject::tr("Brightness"));
00388 }
00389 };
00390
00391 class Colour : public SliderSetting, public ChannelDBStorage
00392 {
00393 public:
00394 Colour(const ChannelID &id) :
00395 SliderSetting(this, 0, 65535, 655),
00396 ChannelDBStorage(this, id, "colour")
00397 {
00398 setLabel(QObject::tr("Color"));
00399 }
00400 };
00401
00402 class Hue : public SliderSetting, public ChannelDBStorage
00403 {
00404 public:
00405 Hue(const ChannelID &id) :
00406 SliderSetting(this, 0, 65535, 655), ChannelDBStorage(this, id, "hue")
00407 {
00408 setLabel(QObject::tr("Hue"));
00409 }
00410 };
00411
00412 ChannelOptionsCommon::ChannelOptionsCommon(const ChannelID &id,
00413 uint default_sourceid) :
00414 VerticalConfigurationGroup(false, true, false, false)
00415 {
00416 setLabel(QObject::tr("Channel Options - Common"));
00417 setUseLabel(false);
00418
00419 addChild(new Name(id));
00420
00421 Source *source = new Source(id, default_sourceid);
00422 source->Load();
00423
00424 HorizontalConfigurationGroup *group1 =
00425 new HorizontalConfigurationGroup(false,false,true,true);
00426 VerticalConfigurationGroup *bottomhoz =
00427 new VerticalConfigurationGroup(false, true);
00428 VerticalConfigurationGroup *left =
00429 new VerticalConfigurationGroup(false, true);
00430 VerticalConfigurationGroup *right =
00431 new VerticalConfigurationGroup(false, true);
00432
00433
00434 left->addChild(new Channum(id));
00435 left->addChild(new Callsign(id));
00436 left->addChild(new Visible(id));
00437
00438 right->addChild(source);
00439 right->addChild(new ChannelTVFormat(id));
00440 right->addChild(new Priority(id));
00441
00442 group1->addChild(left);
00443 group1->addChild(right);
00444
00445 bottomhoz->addChild(onairguide = new OnAirGuide(id));
00446 bottomhoz->addChild(xmltvID = new XmltvID(id, source->getSelectionLabel()));
00447 bottomhoz->addChild(new TimeOffset(id));
00448
00449 addChild(group1);
00450 addChild(new CommMethod(id));
00451 addChild(new Icon(id));
00452 addChild(bottomhoz);
00453
00454 connect(onairguide, SIGNAL(valueChanged( bool)),
00455 this, SLOT( onAirGuideChanged(bool)));
00456 connect(source, SIGNAL(valueChanged( const QString&)),
00457 this, SLOT( sourceChanged(const QString&)));
00458 };
00459
00460 void ChannelOptionsCommon::Load(void)
00461 {
00462 VerticalConfigurationGroup::Load();
00463 }
00464
00465 void ChannelOptionsCommon::onAirGuideChanged(bool fValue)
00466 {
00467 (void)fValue;
00468 }
00469
00470 void ChannelOptionsCommon::sourceChanged(const QString& sourceid)
00471 {
00472 bool supports_eit = true;
00473 bool uses_eit_only = false;
00474
00475 MSqlQuery query(MSqlQuery::InitCon());
00476 query.prepare("SELECT cardtype "
00477 "FROM capturecard, videosource, cardinput "
00478 "WHERE cardinput.sourceid = videosource.sourceid AND "
00479 " cardinput.cardid = capturecard.cardid AND "
00480 " videosource.sourceid = :SOURCEID");
00481 query.bindValue(":SOURCEID", sourceid);
00482
00483 if (!query.exec() || !query.isActive())
00484 MythDB::DBError("sourceChanged -- supports eit", query);
00485 else
00486 {
00487 supports_eit = (query.size()) ? false : true;
00488 while (query.next())
00489 {
00490 supports_eit |= CardUtil::IsEITCapable(
00491 query.value(0).toString().toUpper());
00492 }
00493
00494 query.prepare("SELECT xmltvgrabber "
00495 "FROM videosource "
00496 "WHERE sourceid = :SOURCEID");
00497 query.bindValue(":SOURCEID", sourceid);
00498
00499 if (!query.exec() || !query.isActive())
00500 MythDB::DBError("sourceChanged -- eit only", query);
00501 else
00502 {
00503 uses_eit_only = (query.size()) ? true : false;
00504 while (query.next())
00505 {
00506 uses_eit_only &= (query.value(0).toString() == "eitonly");
00507 }
00508 }
00509 }
00510
00511 onairguide->setEnabled(supports_eit);
00512 xmltvID->setEnabled(!uses_eit_only);
00513 xmltvID->Load();
00514 }
00515
00516 ChannelOptionsFilters::ChannelOptionsFilters(const ChannelID& id) :
00517 VerticalConfigurationGroup(false, true, false, false)
00518 {
00519 setLabel(QObject::tr("Channel Options - Filters"));
00520 setUseLabel(false);
00521
00522 addChild(new VideoFilters(id));
00523 addChild(new OutputFilters(id));
00524 }
00525
00526 ChannelOptionsV4L::ChannelOptionsV4L(const ChannelID& id) :
00527 VerticalConfigurationGroup(false, true, false, false)
00528 {
00529 setLabel(QObject::tr("Channel Options - Video4Linux"));
00530 setUseLabel(false);
00531
00532 addChild(new Freqid(id));
00533 addChild(new Finetune(id));
00534 addChild(new Contrast(id));
00535 addChild(new Brightness(id));
00536 addChild(new Colour(id));
00537 addChild(new Hue(id));
00538 };
00539
00540
00541
00542
00543
00544 ChannelOptionsRawTS::ChannelOptionsRawTS(const ChannelID &id) :
00545 VerticalConfigurationGroup(false, true, false, false), cid(id)
00546 {
00547 setLabel(QObject::tr("Channel Options - Raw Transport Stream"));
00548 setUseLabel(false);
00549
00550 const uint mx = kMaxPIDs;
00551 pids.resize(mx);
00552 sids.resize(mx);
00553 pcrs.resize(mx);
00554
00555 for (uint i = 0; i < mx; i++)
00556 {
00557 HorizontalConfigurationGroup *row =
00558 new HorizontalConfigurationGroup(false, false, true, true);
00559 TransLabelSetting *label0 = new TransLabelSetting();
00560 label0->setLabel(" PID");
00561 TransLabelSetting *label1 = new TransLabelSetting();
00562 label1->setLabel(" StreamID");
00563 TransLabelSetting *label2 = new TransLabelSetting();
00564 label2->setLabel(" Is PCR");
00565 row->addChild(label0);
00566 row->addChild((pids[i] = new TransLineEditSetting()));
00567 row->addChild(label1);
00568 row->addChild((sids[i] = new TransComboBoxSetting()));
00569 for (uint j = 0x101; j <= 0x1ff; j++)
00570 {
00571 QString desc = StreamID::GetDescription(j&0xff);
00572 if (!desc.isEmpty())
00573 sids[i]->addSelection(
00574 QString("%1 (0x%2)")
00575 .arg(desc).arg(j&0xff,2,16,QLatin1Char('0')),
00576 QString::number(j), false);
00577 }
00578 for (uint j = 0x101; j <= 0x1ff; j++)
00579 {
00580 QString desc = StreamID::GetDescription(j&0xff);
00581 if (desc.isEmpty())
00582 sids[i]->addSelection(
00583 QString("0x%1").arg(j&0xff,2,16,QLatin1Char('0')),
00584 QString::number(j), false);
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 row->addChild(label2);
00600 row->addChild((pcrs[i] = new TransCheckBoxSetting()));
00601 addChild(row);
00602 }
00603 };
00604
00605 void ChannelOptionsRawTS::Load(void)
00606 {
00607 uint chanid = cid.getValue().toUInt();
00608
00609 pid_cache_t pid_cache;
00610 if (!ChannelUtil::GetCachedPids(chanid, pid_cache))
00611 return;
00612
00613 pid_cache_t::const_iterator it = pid_cache.begin();
00614 for (uint i = 0; i < kMaxPIDs && it != pid_cache.end(); )
00615 {
00616 if (!(it->IsPermanent()))
00617 {
00618 ++it;
00619 continue;
00620 }
00621
00622 pids[i]->setValue(QString("0x%1")
00623 .arg(it->GetPID(),2,16,QLatin1Char('0')));
00624 sids[i]->setValue(QString::number(it->GetComposite()&0x1ff));
00625 pcrs[i]->setValue(it->IsPCRPID());
00626
00627 ++it;
00628 ++i;
00629 }
00630 }
00631
00632 void ChannelOptionsRawTS::Save(void)
00633 {
00634 uint chanid = cid.getValue().toUInt();
00635
00636 pid_cache_t pid_cache;
00637 for (uint i = 0; i < kMaxPIDs; i++)
00638 {
00639 bool ok;
00640 uint pid = pids[i]->getValue().toUInt(&ok, 0);
00641 if (!ok || !sids[i]->getValue().toUInt())
00642 continue;
00643
00644 pid_cache.push_back(
00645 pid_cache_item_t(
00646 pid, sids[i]->getValue().toUInt() | 0x10000 |
00647 (pcrs[i]->getValue().toUInt() ? 0x200 : 0x0)));
00648 }
00649
00650 ChannelUtil::SaveCachedPids(chanid, pid_cache, true );
00651 }
00652
00653