MythTV  0.28pre
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Modules Pages
videosource.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 
3 // Standard UNIX C headers
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 
9 // C++ headers
10 #include <algorithm>
11 using namespace std;
12 
13 // Qt headers
14 #include <QCoreApplication>
15 #include <QTextStream>
16 #include <QStringList>
17 #include <QCursor>
18 #include <QLayout>
19 #include <QFile>
20 #include <QMap>
21 #include <QDir>
22 #include <QDateTime>
23 
24 // MythTV headers
25 #include "mythconfig.h"
26 #include "mythwidgets.h"
27 #include "mythdialogs.h"
28 #include "mythcorecontext.h"
29 #include "videosource.h"
30 #include "datadirect.h"
31 #include "scanwizard.h"
32 #include "cardutil.h"
33 #include "sourceutil.h"
34 #include "channelinfo.h"
35 #include "channelutil.h"
36 #include "frequencies.h"
37 #include "diseqcsettings.h"
38 #include "firewiredevice.h"
39 #include "compat.h"
40 #include "mythdb.h"
41 #include "mythdirs.h"
42 #include "mythlogging.h"
43 #include "libmythupnp/httprequest.h" // for TestMimeType()
44 #include "mythsystemlegacy.h"
45 #include "exitcodes.h"
46 
47 #ifdef USING_DVB
48 #include "dvbtypes.h"
49 #endif
50 
51 #ifdef USING_V4L2
52 #include <linux/videodev2.h>
53 #endif
54 
55 #ifdef USING_HDHOMERUN
56 #include "hdhomerun.h"
57 #endif
58 
59 static const uint kDefaultMultirecCount = 2;
60 
62  const QString &_card_types,
63  bool _must_have_mplexid) :
64  ComboBoxSetting(this),
65  initial_sourceid(_initial_sourceid),
66  card_types(_card_types),
67  must_have_mplexid(_must_have_mplexid)
68 {
69  card_types.detach();
70  setLabel(tr("Video Source"));
71 }
72 
74 {
76 
77  QString querystr =
78  "SELECT DISTINCT videosource.name, videosource.sourceid "
79  "FROM capturecard, videosource";
80 
81  querystr += (must_have_mplexid) ? ", channel " : " ";
82 
83  querystr +=
84  "WHERE capturecard.sourceid = videosource.sourceid AND "
85  " capturecard.hostname = :HOSTNAME ";
86 
87  if (!card_types.isEmpty())
88  {
89  querystr += QString(" AND capturecard.cardtype in %1 ")
90  .arg(card_types);
91  }
92 
94  {
95  querystr +=
96  " AND channel.sourceid = videosource.sourceid "
97  " AND channel.mplexid != 32767 "
98  " AND channel.mplexid != 0 ";
99  }
100 
101  query.prepare(querystr);
102  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
103 
104  if (!query.exec() || !query.isActive() || query.size() <= 0)
105  return;
106 
107  uint sel = 0, cnt = 0;
108  for (; query.next(); cnt++)
109  {
110  addSelection(query.value(0).toString(),
111  query.value(1).toString());
112 
113  sel = (query.value(1).toUInt() == initial_sourceid) ? cnt : sel;
114  }
115 
116  if (initial_sourceid)
117  {
118  if (cnt)
119  setValue(sel);
120  setEnabled(false);
121  }
122 }
123 
125 {
126  public:
128  {
129  setLabel(QObject::tr("Max recordings"));
130  setHelpText(
131  QObject::tr(
132  "Maximum number of simultaneous recordings this device "
133  "should make. Some digital transmitters transmit multiple "
134  "programs on a multiplex, if this is set to a value greater "
135  "than one MythTV can sometimes take advantage of this."));
136  uint cnt = parent.GetInstanceCount();
137  cnt = (!cnt) ? kDefaultMultirecCount : cnt;
138  setValue(cnt);
139  };
140 };
141 
143 {
144  QString sourceidTag(":WHERESOURCEID");
145 
146  QString query("sourceid = " + sourceidTag);
147 
148  bindings.insert(sourceidTag, m_parent.getSourceID());
149 
150  return query;
151 }
152 
154 {
155  QString sourceidTag(":SETSOURCEID");
156  QString colTag(":SET" + GetColumnName().toUpper());
157 
158  QString query("sourceid = " + sourceidTag + ", " +
159  GetColumnName() + " = " + colTag);
160 
161  bindings.insert(sourceidTag, m_parent.getSourceID());
162  bindings.insert(colTag, user->GetDBValue());
163 
164  return query;
165 }
166 
168 {
169  QString cardidTag(":WHERECARDID");
170 
171  QString query("cardid = " + cardidTag);
172 
173  bindings.insert(cardidTag, m_parent.getCardID());
174 
175  return query;
176 }
177 
179 {
180  QString cardidTag(":SETCARDID");
181  QString colTag(":SET" + GetColumnName().toUpper());
182 
183  QString query("cardid = " + cardidTag + ", " +
184  GetColumnName() + " = " + colTag);
185 
186  bindings.insert(cardidTag, m_parent.getCardID());
187  bindings.insert(colTag, user->GetDBValue());
188 
189  return query;
190 }
191 
193 {
194  public:
196  ComboBoxSetting(this),
197  VideoSourceDBStorage(this, parent, "xmltvgrabber")
198  {
199  setLabel(QObject::tr("Listings grabber"));
200  };
201 };
202 
204 {
205  public:
206  DVBNetID(const VideoSource &parent, signed int value, signed int min_val) :
207  SpinBoxSetting(this, min_val, 0xffff, 1),
208  VideoSourceDBStorage(this, parent, "dvb_nit_id")
209  {
210  setLabel(QObject::tr("Network ID"));
211  //: Network_ID is the name of an identifier in the DVB's Service
212  //: Information standard specification.
213  setHelpText(QObject::tr("If your provider has asked you to configure a "
214  "specific network identifier (Network_ID), "
215  "enter it here. Leave it at -1 otherwise."));
216  setValue(value);
217  };
218 };
219 
221  ComboBoxSetting(this), VideoSourceDBStorage(this, parent, "freqtable")
222 {
223  setLabel(QObject::tr("Channel frequency table"));
224  addSelection("default");
225 
226  for (uint i = 0; chanlists[i].name; i++)
228 
229  setHelpText(QObject::tr("Use default unless this source uses a "
230  "different frequency table than the system wide table "
231  "defined in the General settings."));
232 }
233 
235  ComboBoxSetting(this), sourceid(_sourceid),
236  loaded_freq_table(QString::null)
237 {
238  setLabel(QObject::tr("Channel frequency table"));
239 
240  for (uint i = 0; chanlists[i].name; i++)
242 }
243 
245 {
246  int idx = getValueIndex(gCoreContext->GetSetting("FreqTable"));
247  if (idx >= 0)
248  setValue(idx);
249 
250  if (!sourceid)
251  return;
252 
253  MSqlQuery query(MSqlQuery::InitCon());
254  query.prepare(
255  "SELECT freqtable "
256  "FROM videosource "
257  "WHERE sourceid = :SOURCEID");
258  query.bindValue(":SOURCEID", sourceid);
259 
260  if (!query.exec() || !query.isActive())
261  {
262  MythDB::DBError("TransFreqTableSelector::load", query);
263  return;
264  }
265 
266  loaded_freq_table = QString::null;
267 
268  if (query.next())
269  {
270  loaded_freq_table = query.value(0).toString();
271  if (!loaded_freq_table.isEmpty() &&
272  (loaded_freq_table.toLower() != "default"))
273  {
274  int idx = getValueIndex(loaded_freq_table);
275  if (idx >= 0)
276  setValue(idx);
277  }
278  }
279 }
280 
282 {
283  LOG(VB_GENERAL, LOG_INFO, "TransFreqTableSelector::Save(void)");
284 
285  if ((loaded_freq_table == getValue()) ||
286  ((loaded_freq_table.toLower() == "default") &&
287  (getValue() == gCoreContext->GetSetting("FreqTable"))))
288  {
289  return;
290  }
291 
292  MSqlQuery query(MSqlQuery::InitCon());
293  query.prepare(
294  "UPDATE videosource "
295  "SET freqtable = :FREQTABLE "
296  "WHERE sourceid = :SOURCEID");
297 
298  query.bindValue(":FREQTABLE", getValue());
299  query.bindValue(":SOURCEID", sourceid);
300 
301  if (!query.exec() || !query.isActive())
302  {
303  MythDB::DBError("TransFreqTableSelector::load", query);
304  return;
305  }
306 }
307 
309 {
310  sourceid = _sourceid;
311  Load();
312 }
313 
315 {
316  public:
318  CheckBoxSetting(this), VideoSourceDBStorage(this, parent, "useeit")
319  {
320  setLabel(QObject::tr("Perform EIT scan"));
321  setHelpText(QObject::tr(
322  "If enabled, program guide data for channels on this "
323  "source will be updated with data provided by the "
324  "channels themselves 'Over-the-Air'."));
325  }
326 };
327 
329 {
330  public:
332  LineEditSetting(this), VideoSourceDBStorage(this, parent, "userid")
333  {
334  setLabel(QObject::tr("User ID"));
335  }
336 };
337 
339 {
340  public:
342  LineEditSetting(this, true),
343  VideoSourceDBStorage(this, parent, "password")
344  {
345  SetPasswordEcho(true);
346  setLabel(QObject::tr("Password"));
347  }
348 };
349 
351  const QString &pwd,
352  int _source)
353 {
354  (void) uid;
355  (void) pwd;
356 #ifdef USING_BACKEND
357  if (uid.isEmpty() || pwd.isEmpty())
358  return;
359 
360  qApp->processEvents();
361 
362  DataDirectProcessor ddp(_source, uid, pwd);
363  QString waitMsg = tr("Fetching lineups from %1...")
364  .arg(ddp.GetListingsProviderName());
365 
366  LOG(VB_GENERAL, LOG_INFO, waitMsg);
367  MythProgressDialog *pdlg = new MythProgressDialog(waitMsg, 2);
368 
369  clearSelections();
370 
371  pdlg->setProgress(1);
372 
373  if (!ddp.GrabLineupsOnly())
374  {
375  LOG(VB_GENERAL, LOG_ERR,
376  "DDLS: fillSelections did not successfully load selections");
377  pdlg->deleteLater();
378  return;
379  }
380  const DDLineupList lineups = ddp.GetLineups();
381 
382  DDLineupList::const_iterator it;
383  for (it = lineups.begin(); it != lineups.end(); ++it)
384  addSelection((*it).displayname, (*it).lineupid);
385 
386  pdlg->setProgress(2);
387  pdlg->Close();
388  pdlg->deleteLater();
389 #else // USING_BACKEND
390  LOG(VB_GENERAL, LOG_ERR,
391  "You must compile the backend to set up a DataDirect line-up");
392 #endif // USING_BACKEND
393 }
394 
396 {
398  bool is_sd_userid = userid->getValue().contains('@') > 0;
399  bool match = ((is_sd_userid && (source == DD_SCHEDULES_DIRECT)) ||
400  (!is_sd_userid && (source == DD_ZAP2IT)));
401  if (((userid->getValue() != lastloadeduserid) ||
402  (password->getValue() != lastloadedpassword)) && match)
403  {
405  password->getValue(),
406  source);
409  }
410 }
411 
412 DataDirect_config::DataDirect_config(const VideoSource& _parent, int _source) :
414  parent(_parent)
415 {
416  source = _source;
417 
419  new HorizontalConfigurationGroup(false, false, true, true);
420 
422  addChild(up);
423 
425  new HorizontalConfigurationGroup(false, false, true, true);
426 
428  lp->addChild(button = new DataDirectButton());
429  addChild(lp);
430 
432  addChild(new UseEIT(parent));
433 
434  connect(button, SIGNAL(pressed()),
435  this, SLOT(fillDataDirectLineupSelector()));
436 }
437 
439 {
442 }
443 
445  QString _grabber) :
447  parent(_parent), grabber(_grabber)
448 {
449  QString filename = QString("%1/%2.xmltv")
450  .arg(GetConfDir()).arg(parent.getSourceName());
451 
452  grabberArgs.push_back("--config-file");
453  grabberArgs.push_back(filename);
454  grabberArgs.push_back("--configure");
455 
456  addChild(new UseEIT(parent));
457 
458  TransButtonSetting *config = new TransButtonSetting();
459  config->setLabel(tr("Configure"));
460  config->setHelpText(tr("Run XMLTV configure command."));
461 
462  addChild(config);
463 
464  connect(config, SIGNAL(pressed()), SLOT(RunConfig()));
465 }
466 
468 {
470 #if 0
471  QString err_msg = QObject::tr(
472  "You MUST run 'mythfilldatabase --manual' the first time,\n"
473  "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
474  "channel numbers, so you have to set them manually.");
475 
477  {
478  LOG(VB_GENERAL, LOG_ERR, err_msg);
480  GetMythMainWindow(), QObject::tr("Warning."), err_msg);
481  }
482 #endif
483 }
484 
486 {
488  tw->exec(false, true);
489  delete tw;
490 }
491 
494 {
495  useeit = new UseEIT(_parent);
496  useeit->setValue(true);
497  useeit->setVisible(false);
498  addChild(useeit);
499 
501  label=new TransLabelSetting();
502  label->setValue(QObject::tr("Use only the transmitted guide data."));
503  addChild(label);
504  label=new TransLabelSetting();
505  label->setValue(
506  QObject::tr("This will usually only work with ATSC or DVB channels,"));
507  addChild(label);
508  label=new TransLabelSetting();
509  label->setValue(
510  QObject::tr("and generally provides data only for the next few days."));
511  addChild(label);
512 }
513 
515 {
516  // Force this value on
517  useeit->setValue(true);
518  useeit->Save();
519 }
520 
523 {
524  useeit = new UseEIT(_parent);
525  useeit->setValue(false);
526  useeit->setVisible(false);
527  addChild(useeit);
528 
530  label->setValue(QObject::tr("Do not configure a grabber"));
531  addChild(label);
532 }
533 
535 {
536  useeit->setValue(false);
537  useeit->Save();
538 }
539 
540 
543  parent(aparent), grabber(new XMLTVGrabber(parent))
544 {
545  addChild(grabber);
547 
548  // only save settings for the selected grabber
549  setSaveAll(false);
550 
551 }
552 
554 {
555  addTarget("schedulesdirect1",
557  addTarget("eitonly", new EITOnly_config(parent));
558  addTarget("/bin/true", new NoGrabber_config(parent));
559 
561  QObject::tr("North America (SchedulesDirect.org) (Internal)"),
562  "schedulesdirect1");
563 
565  QObject::tr("Transmitted guide only (EIT)"), "eitonly");
566 
567  grabber->addSelection(QObject::tr("No grabber"), "/bin/true");
568 
569 
570  QString validValues;
571  validValues += "schedulesdirect1";
572  validValues += "eitonly";
573  validValues += "/bin/true";
574 
575  QString gname, d1, d2, d3;
577 
578 #ifdef _MSC_VER
579  #pragma message( "tv_find_grabbers is not supported yet on windows." )
580  //-=>TODO:Screen doesn't show up if the call to MythSysemLegacy is executed
581 #else
582 
583  QString loc = "XMLTVConfig::Load: ";
584  QString loc_err = "XMLTVConfig::Load, Error: ";
585 
586  QStringList name_list;
587  QStringList prog_list;
588 
589  QStringList args;
590  args += "baseline";
591 
592  MythSystemLegacy find_grabber_proc("tv_find_grabbers", args,
594  find_grabber_proc.Run(25);
595  LOG(VB_GENERAL, LOG_INFO,
596  loc + "Running 'tv_find_grabbers " + args.join(" ") + "'.");
597  uint status = find_grabber_proc.Wait();
598 
599  if (status == GENERIC_EXIT_OK)
600  {
601  QTextStream ostream(find_grabber_proc.ReadAll());
602  while (!ostream.atEnd())
603  {
604  QString grabber_list(ostream.readLine());
605  QStringList grabber_split =
606  grabber_list.split("|", QString::SkipEmptyParts);
607  QString grabber_name = grabber_split[1] + " (xmltv)";
608  QFileInfo grabber_file(grabber_split[0]);
609 
610  name_list.push_back(grabber_name);
611  prog_list.push_back(grabber_file.fileName());
612  LOG(VB_GENERAL, LOG_DEBUG, "Found " + grabber_split[0]);
613  }
614  LOG(VB_GENERAL, LOG_INFO, loc + "Finished running tv_find_grabbers");
615  }
616  else
617  LOG(VB_GENERAL, LOG_ERR, loc + "Failed to run tv_find_grabbers");
618 
619  LoadXMLTVGrabbers(name_list, prog_list);
620 #endif
621 
623 
624 }
625 
627  QStringList name_list, QStringList prog_list)
628 {
629  if (name_list.size() != prog_list.size())
630  return;
631 
632  QString selValue = grabber->getValue();
633  int selIndex = grabber->getValueIndex(selValue);
634  grabber->setValue(0);
635 
636  QString validValues;
637  validValues += "schedulesdirect1";
638  validValues += "eitonly";
639  validValues += "/bin/true";
640 
641  for (uint i = 0; i < grabber->size(); i++)
642  {
643  if (!validValues.contains(grabber->GetValue(i)))
644  {
646  i--;
647  }
648  }
649 
650  for (uint i = 0; i < (uint) name_list.size(); i++)
651  {
652  addTarget(prog_list[i],
653  new XMLTV_generic_config(parent, prog_list[i]));
654  grabber->addSelection(name_list[i], prog_list[i]);
655  }
656 
657  if (!selValue.isEmpty())
658  selIndex = grabber->getValueIndex(selValue);
659  if (selIndex >= 0)
660  grabber->setValue(selIndex);
661 
662 }
663 
665 {
667  MSqlQuery query(MSqlQuery::InitCon());
668  query.prepare(
669  "UPDATE videosource "
670  "SET userid=NULL, password=NULL "
671  "WHERE xmltvgrabber NOT IN ( 'datadirect', 'technovera', "
672  " 'schedulesdirect1' )");
673  if (!query.exec())
674  MythDB::DBError("XMLTVConfig::Save", query);
675 }
676 
678 {
679  // must be first
680  addChild(id = new ID());
681 
682  ConfigurationGroup *group = new VerticalConfigurationGroup(false, false);
683  group->setLabel(QObject::tr("Video Source Setup"));
684  group->addChild(name = new Name(*this));
685  group->addChild(xmltv = new XMLTVConfig(*this));
686  group->addChild(new FreqTableSelector(*this));
687  group->addChild(new DVBNetID(*this, -1, -1));
688  addChild(group);
689 }
690 
691 bool VideoSourceEditor::cardTypesInclude(const int &sourceID,
692  const QString &thecardtype)
693 {
694  MSqlQuery query(MSqlQuery::InitCon());
695  query.prepare("SELECT count(cardtype)"
696  " FROM capturecard "
697  " WHERE capturecard.sourceid = :SOURCEID "
698  " AND capturecard.cardtype = :CARDTYPE ;");
699  query.bindValue(":SOURCEID", sourceID);
700  query.bindValue(":CARDTYPE", thecardtype);
701 
702  if (query.exec() && query.next())
703  {
704  int count = query.value(0).toInt();
705 
706  if (count > 0)
707  return true;
708  }
709 
710  return false;
711 }
712 
714 {
715  MSqlQuery result(MSqlQuery::InitCon());
716  result.prepare("SELECT name, sourceid FROM videosource;");
717 
718  if (result.exec() && result.isActive() && result.size() > 0)
719  {
720  while (result.next())
721  {
722  setting->addSelection(result.value(0).toString(),
723  result.value(1).toString());
724  }
725  }
726 }
727 
728 void VideoSource::loadByID(int sourceid)
729 {
730  id->setValue(sourceid);
731 }
732 
734 {
735  public:
737  uint minor_min = 0,
738  uint minor_max = UINT_MAX,
739  QString card = QString::null,
740  QString driver = QString::null) :
741  PathSetting(this, true),
742  CaptureCardDBStorage(this, parent, "videodevice")
743  {
744  setLabel(QObject::tr("Video device"));
745 
746  // /dev/v4l/video*
747  QDir dev("/dev/v4l", "video*", QDir::Name, QDir::System);
748  fillSelectionsFromDir(dev, minor_min, minor_max,
749  card, driver, false);
750 
751  // /dev/video*
752  dev.setPath("/dev");
753  fillSelectionsFromDir(dev, minor_min, minor_max,
754  card, driver, false);
755 
756  // /dev/dtv/video*
757  dev.setPath("/dev/dtv");
758  fillSelectionsFromDir(dev, minor_min, minor_max,
759  card, driver, false);
760 
761  // /dev/dtv*
762  dev.setPath("/dev");
763  dev.setNameFilters(QStringList("dtv*"));
764  fillSelectionsFromDir(dev, minor_min, minor_max,
765  card, driver, false);
766  };
767 
768  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
769  {
770  fillSelectionsFromDir(dir, 0, 255, QString::null, QString::null, false);
771  }
772 
773  uint fillSelectionsFromDir(const QDir& dir,
774  uint minor_min, uint minor_max,
775  QString card, QString driver,
776  bool allow_duplicates)
777  {
778  uint cnt = 0;
779 
780  QFileInfoList il = dir.entryInfoList();
781  QRegExp *driverExp = NULL;
782  if (!driver.isEmpty())
783  driverExp = new QRegExp(driver);
784 
785  for( QFileInfoList::iterator it = il.begin();
786  it != il.end();
787  ++it )
788  {
789  QFileInfo &fi = *it;
790 
791  struct stat st;
792  QString filepath = fi.absoluteFilePath();
793  int err = lstat(filepath.toLocal8Bit().constData(), &st);
794 
795  if (err)
796  {
797  LOG(VB_GENERAL, LOG_ERR,
798  QString("Could not stat file: %1").arg(filepath));
799  continue;
800  }
801 
802  // is this is a character device?
803  if (!S_ISCHR(st.st_mode))
804  continue;
805 
806  // is this device is in our minor range?
807  uint minor_num = minor(st.st_rdev);
808  if (minor_min > minor_num || minor_max < minor_num)
809  continue;
810 
811  // ignore duplicates if allow_duplicates not set
812  if (!allow_duplicates && minor_list[minor_num])
813  continue;
814 
815  // if the driver returns any info add this device to our list
816  QByteArray tmp = filepath.toLatin1();
817  int videofd = open(tmp.constData(), O_RDWR);
818  if (videofd >= 0)
819  {
820  QString cn, dn;
821  if (CardUtil::GetV4LInfo(videofd, cn, dn) &&
822  (!driverExp || (driverExp->exactMatch(dn))) &&
823  (card.isEmpty() || (cn == card)))
824  {
825  addSelection(filepath);
826  cnt++;
827  }
828  close(videofd);
829  }
830 
831  // add to list of minors discovered to avoid duplicates
832  minor_list[minor_num] = 1;
833  }
834  delete driverExp;
835 
836  return cnt;
837  }
838 
839  private:
840  QMap<uint, uint> minor_list;
841 };
842 
844 {
845  public:
847  PathSetting(this, true),
848  CaptureCardDBStorage(this, parent, "vbidevice")
849  {
850  setLabel(QObject::tr("VBI device"));
851  setFilter(QString::null, QString::null);
852  };
853 
854  void setFilter(const QString &card, const QString &driver)
855  {
856  clearSelections();
857  QDir dev("/dev/v4l", "vbi*", QDir::Name, QDir::System);
858  if (!fillSelectionsFromDir(dev, card, driver))
859  {
860  dev.setPath("/dev");
861  if (!fillSelectionsFromDir(dev, card, driver) &&
862  !getValue().isEmpty())
863  {
864  addSelection(getValue(),getValue(),true);
865  }
866  }
867  }
868 
869  void fillSelectionsFromDir(const QDir &dir, bool absPath = true)
870  {
871  fillSelectionsFromDir(dir, QString::null, QString::null);
872  }
873 
874  uint fillSelectionsFromDir(const QDir &dir, const QString &card,
875  const QString &driver)
876  {
877  QStringList devices;
878  QFileInfoList il = dir.entryInfoList();
879  for( QFileInfoList::iterator it = il.begin();
880  it != il.end();
881  ++it )
882  {
883  QFileInfo &fi = *it;
884 
885  QString device = fi.absoluteFilePath();
886  QByteArray adevice = device.toLatin1();
887  int vbifd = open(adevice.constData(), O_RDWR);
888  if (vbifd < 0)
889  continue;
890 
891  QString cn, dn;
892  if (CardUtil::GetV4LInfo(vbifd, cn, dn) &&
893  (driver.isEmpty() || (dn == driver)) &&
894  (card.isEmpty() || (cn == card)))
895  {
896  devices.push_back(device);
897  }
898 
899  close(vbifd);
900  }
901 
902  QString sel = getValue();
903  for (uint i = 0; i < (uint) devices.size(); i++)
904  addSelection(devices[i], devices[i], devices[i] == sel);
905 
906  return (uint) devices.size();
907  }
908 };
909 
911 {
912  public:
914  LineEditSetting(this, true),
915  CaptureCardDBStorage(this, parent, "audiodevice") // change to arguments
916  {
917  setLabel(QObject::tr("Arguments"));
918  }
919 };
920 
922 {
923  public:
925  PathSetting(this, false),
926  CaptureCardDBStorage(this, parent, "videodevice")
927  {
928  setLabel(QObject::tr("File path"));
929  };
930 };
931 
933 {
934  public:
936  PathSetting(this, false),
937  CaptureCardDBStorage(this, parent, "audiodevice")
938  {
939  setLabel(QObject::tr("Audio device"));
940 #if USING_OSS
941  QDir dev("/dev", "dsp*", QDir::Name, QDir::System);
943  dev.setPath("/dev/sound");
945 #endif
946 #if USING_ALSA
947  addSelection("ALSA:default", "ALSA:default");
948 #endif
949  addSelection(QObject::tr("(None)"), "NULL");
950  };
951 };
952 
954 {
955  public:
956  SignalTimeout(const CaptureCard &parent, uint value, uint min_val) :
957  SpinBoxSetting(this, min_val, 60000, 250),
958  CaptureCardDBStorage(this, parent, "signal_timeout")
959  {
960  setLabel(QObject::tr("Signal timeout (ms)"));
961  setValue(value);
962  setHelpText(QObject::tr(
963  "Maximum time (in milliseconds) MythTV waits for "
964  "a signal when scanning for channels."));
965  };
966 };
967 
969 {
970  public:
971  ChannelTimeout(const CaptureCard &parent, uint value, uint min_val) :
972  SpinBoxSetting(this, min_val, 65000, 250),
973  CaptureCardDBStorage(this, parent, "channel_timeout")
974  {
975  setLabel(QObject::tr("Tuning timeout (ms)"));
976  setValue(value);
977  setHelpText(QObject::tr(
978  "Maximum time (in milliseconds) MythTV waits for "
979  "a channel lock. For recordings, if this time is "
980  "exceeded, the recording will be marked as failed."));
981  };
982 };
983 
985 {
986  public:
988  ComboBoxSetting(this),
989  CaptureCardDBStorage(this, parent, "audioratelimit")
990  {
991  setLabel(QObject::tr("Force audio sampling rate"));
992  setHelpText(
993  QObject::tr("If non-zero, override the audio sampling "
994  "rate in the recording profile when this card is "
995  "used. Use this if your capture card does not "
996  "support all of the standard rates."));
997  addSelection(QObject::tr("(None)"), "0");
998  addSelection("32000");
999  addSelection("44100");
1000  addSelection("48000");
1001  };
1002 };
1003 
1005 {
1006  public:
1008  CheckBoxSetting(this),
1009  CaptureCardDBStorage(this, parent, "skipbtaudio")
1010  {
1011  setLabel(QObject::tr("Do not adjust volume"));
1012  setHelpText(
1013  QObject::tr("Enable this option for budget BT878 based "
1014  "DVB-T cards such as the AverTV DVB-T which "
1015  "require the audio volume to be left alone."));
1016  };
1017 };
1018 
1020 {
1021  public:
1023  PathSetting(this, true),
1024  CaptureCardDBStorage(this, parent, "videodevice")
1025  {
1026  setLabel(QObject::tr("DVB device"));
1027  setHelpText(
1028  QObject::tr("When you change this setting, the text below "
1029  "should change to the name and type of your card. "
1030  "If the card cannot be opened, an error message "
1031  "will be displayed."));
1032  fillSelections(QString::null);
1033  };
1034 
1038  void fillSelections(const QString &current)
1039  {
1040  clearSelections();
1041 
1042  // Get devices from filesystem
1043  QStringList sdevs = CardUtil::ProbeVideoDevices("DVB");
1044 
1045  // Add current if needed
1046  if (!current.isEmpty() &&
1047  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1048  {
1049  stable_sort(sdevs.begin(), sdevs.end());
1050  }
1051 
1052  QStringList db = CardUtil::GetVideoDevices("DVB");
1053 
1054  QMap<QString,bool> in_use;
1055  QString sel = current;
1056  for (uint i = 0; i < (uint)sdevs.size(); i++)
1057  {
1058  const QString dev = sdevs[i];
1059  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1060  if (sel.isEmpty() && !in_use[sdevs[i]])
1061  sel = dev;
1062  }
1063 
1064  if (sel.isEmpty() && sdevs.size())
1065  sel = sdevs[0];
1066 
1067  QString usestr = QString(" -- ");
1068  usestr += QObject::tr("Warning: already in use");
1069 
1070  for (uint i = 0; i < (uint)sdevs.size(); i++)
1071  {
1072  const QString dev = sdevs[i];
1073  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1074  desc = (current == sdevs[i]) ? dev : desc;
1075  addSelection(desc, dev, dev == sel);
1076  }
1077  }
1078 
1079  virtual void Load(void)
1080  {
1081  clearSelections();
1082  addSelection(QString::null);
1083 
1085 
1087  fillSelections(dev);
1088  }
1089 };
1090 
1092 {
1093  public:
1095  {
1096  setLabel(QObject::tr("Subtype"));
1097  };
1098 };
1099 
1101 {
1102  public:
1104  {
1105  setLabel(QObject::tr("Frontend ID"));
1106  };
1107 };
1108 
1110 {
1111  public:
1113  CheckBoxSetting(this),
1114  CaptureCardDBStorage(this, parent, "dvb_wait_for_seqstart")
1115  {
1116  setLabel(QObject::tr("Wait for SEQ start header."));
1117  setValue(true);
1118  setHelpText(
1119  QObject::tr("If enabled, drop packets from the start of a DVB "
1120  "recording until a sequence start header is seen."));
1121  };
1122 };
1123 
1125 {
1126  public:
1128  CheckBoxSetting(this),
1129  CaptureCardDBStorage(this, parent, "dvb_on_demand")
1130  {
1131  setLabel(QObject::tr("Open DVB card on demand"));
1132  setValue(true);
1133  setHelpText(
1134  QObject::tr("If enabled, only open the DVB card when required, "
1135  "leaving it free for other programs at other times."));
1136  };
1137 };
1138 
1140 {
1141  public:
1143  CheckBoxSetting(this),
1144  CaptureCardDBStorage(this, parent, "dvb_eitscan")
1145  {
1146  setLabel(QObject::tr("Use DVB card for active EIT scan"));
1147  setValue(true);
1148  setHelpText(
1149  QObject::tr("If enabled, activate active scanning for "
1150  "program data (EIT). When this option is enabled "
1151  "the DVB card is constantly in-use."));
1152  };
1153 };
1154 
1156 {
1157  public:
1159  SpinBoxSetting(this, 0, 2000, 25),
1160  CaptureCardDBStorage(this, parent, "dvb_tuning_delay")
1161  {
1162  setLabel(QObject::tr("DVB tuning delay (ms)"));
1163  setValue(true);
1164  setHelpText(
1165  QObject::tr("Some Linux DVB drivers, in particular for the "
1166  "Hauppauge Nova-T, require that we slow down "
1167  "the tuning process by specifying a delay "
1168  "(in milliseconds)."));
1169  };
1170 };
1171 
1173 {
1174  public:
1176  ComboBoxSetting(this),
1177  CaptureCardDBStorage(this, parent, "videodevice")
1178  {
1179  setLabel(QObject::tr("GUID"));
1180 #ifdef USING_FIREWIRE
1181  vector<AVCInfo> list = FirewireDevice::GetSTBList();
1182  for (uint i = 0; i < list.size(); i++)
1183  {
1184  QString guid = list[i].GetGUIDString();
1185  guid_to_avcinfo[guid] = list[i];
1186  addSelection(guid);
1187  }
1188 #endif // USING_FIREWIRE
1189  }
1190 
1191  AVCInfo GetAVCInfo(const QString &guid) const
1192  { return guid_to_avcinfo[guid]; }
1193 
1194  private:
1195  QMap<QString,AVCInfo> guid_to_avcinfo;
1196 };
1197 
1199  const FirewireGUID *_guid) :
1200  ComboBoxSetting(this),
1201  CaptureCardDBStorage(this, parent, "firewire_model"),
1202  guid(_guid)
1203 {
1204  setLabel(QObject::tr("Cable box model"));
1205  addSelection(QObject::tr("Motorola Generic"), "MOTO GENERIC");
1206  addSelection(QObject::tr("SA/Cisco Generic"), "SA GENERIC");
1207  addSelection("DCH-3200");
1208  addSelection("DCX-3200");
1209  addSelection("DCT-3412");
1210  addSelection("DCT-3416");
1211  addSelection("DCT-6200");
1212  addSelection("DCT-6212");
1213  addSelection("DCT-6216");
1214  addSelection("QIP-6200");
1215  addSelection("QIP-7100");
1216  addSelection("PACE-550");
1217  addSelection("PACE-779");
1218  addSelection("SA3250HD");
1219  addSelection("SA4200HD");
1220  addSelection("SA4250HDC");
1221  addSelection("SA8300HD");
1222  QString help = QObject::tr(
1223  "Choose the model that most closely resembles your set top box. "
1224  "Depending on firmware revision SA4200HD may work better for a "
1225  "SA3250HD box.");
1226  setHelpText(help);
1227 }
1228 
1229 void FirewireModel::SetGUID(const QString &_guid)
1230 {
1231  (void) _guid;
1232 
1233 #ifdef USING_FIREWIRE
1234  AVCInfo info = guid->GetAVCInfo(_guid);
1235  QString model = FirewireDevice::GetModelName(info.vendorid, info.modelid);
1236  setValue(max(getValueIndex(model), 0));
1237 #endif // USING_FIREWIRE
1238 }
1239 
1240 void FirewireDesc::SetGUID(const QString &_guid)
1241 {
1242  (void) _guid;
1243 
1244  setLabel(tr("Description"));
1245 
1246 #ifdef USING_FIREWIRE
1247  QString name = guid->GetAVCInfo(_guid).product_name;
1248  name.replace("Scientific-Atlanta", "SA");
1249  name.replace(", Inc.", "");
1250  name.replace("Explorer(R)", "");
1251  name = name.simplified();
1252  setValue((name.isEmpty()) ? "" : name);
1253 #endif // USING_FIREWIRE
1254 }
1255 
1257 {
1258  public:
1260  ComboBoxSetting(this),
1261  CaptureCardDBStorage(this, parent, "firewire_connection")
1262  {
1263  setLabel(QObject::tr("Connection Type"));
1264  addSelection(QObject::tr("Point to Point"),"0");
1265  addSelection(QObject::tr("Broadcast"),"1");
1266  }
1267 };
1268 
1270 {
1271  public:
1273  ComboBoxSetting(this),
1274  CaptureCardDBStorage(this, parent, "firewire_speed")
1275  {
1276  setLabel(QObject::tr("Speed"));
1277  addSelection(QObject::tr("100Mbps"),"0");
1278  addSelection(QObject::tr("200Mbps"),"1");
1279  addSelection(QObject::tr("400Mbps"),"2");
1280  addSelection(QObject::tr("800Mbps"),"3");
1281  }
1282 };
1283 
1285 {
1286  public:
1289  parent(a_parent),
1290  dev(new FirewireGUID(parent)),
1291  desc(new FirewireDesc(dev)),
1292  model(new FirewireModel(parent, dev))
1293  {
1294  addChild(dev);
1297  addChild(desc);
1298  addChild(model);
1299 
1300 #ifdef USING_LINUX_FIREWIRE
1303 #endif // USING_LINUX_FIREWIRE
1304 
1305  addChild(new SignalTimeout(parent, 2000, 1000));
1306  addChild(new ChannelTimeout(parent, 9000, 1750));
1307 
1308  model->SetGUID(dev->getValue());
1309  desc->SetGUID(dev->getValue());
1310  connect(dev, SIGNAL(valueChanged(const QString&)),
1311  model, SLOT( SetGUID( const QString&)));
1312  connect(dev, SIGNAL(valueChanged(const QString&)),
1313  desc, SLOT( SetGUID( const QString&)));
1314  };
1315 
1316  private:
1321 };
1322 
1323 // -----------------------
1324 // HDHomeRun Configuration
1325 // -----------------------
1326 
1328 {
1329  setLabel(QObject::tr("IP Address"));
1330  setEnabled(false);
1331  connect(this, SIGNAL(valueChanged( const QString&)),
1332  this, SLOT( UpdateDevices(const QString&)));
1333  _oldValue="";
1334 };
1335 
1337 {
1339  if (e)
1340  {
1341  if (!_oldValue.isEmpty())
1343  emit NewIP(getValue());
1344  }
1345  else
1346  {
1347  _oldValue = getValue();
1348  _oldValue.detach();
1349  }
1350 }
1351 
1352 void HDHomeRunIP::UpdateDevices(const QString &v)
1353 {
1354  if (isEnabled())
1355  {
1356 #if 0
1357  LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewIP(%1)").arg(v));
1358 #endif
1359  emit NewIP(v);
1360  }
1361 }
1362 
1364 {
1365  setLabel(QObject::tr("Tuner"));
1366  setEnabled(false);
1367  connect(this, SIGNAL(valueChanged( const QString&)),
1368  this, SLOT( UpdateDevices(const QString&)));
1369  _oldValue = "";
1370 };
1371 
1373 {
1375  if (e) {
1376  if (!_oldValue.isEmpty())
1378  emit NewTuner(getValue());
1379  }
1380  else
1381  {
1382  _oldValue = getValue();
1383  }
1384 }
1385 
1387 {
1388  if (isEnabled())
1389  {
1390 #if 0
1391  LOG(VB_GENERAL, LOG_DEBUG, QString("Emitting NewTuner(%1)").arg(v));
1392 #endif
1393  emit NewTuner(v);
1394  }
1395 }
1396 
1398  LabelSetting(this),
1399  CaptureCardDBStorage(this, parent, "videodevice"),
1400  _ip(QString::null),
1401  _tuner(QString::null),
1402  _overridedeviceid(QString::null)
1403 {
1404  setLabel(tr("Device ID"));
1405  setHelpText(tr("Device ID of HDHomeRun device"));
1406 }
1407 
1408 void HDHomeRunDeviceID::SetIP(const QString &ip)
1409 {
1410 #if 0
1411  LOG(VB_GENERAL, LOG_DEBUG, QString("Setting IP to %1").arg(ip));
1412 #endif
1413  _ip = ip;
1414  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1415 #if 0
1416  LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting IP to %1").arg(ip));
1417 #endif
1418 }
1419 
1420 void HDHomeRunDeviceID::SetTuner(const QString &tuner)
1421 {
1422 #if 0
1423  LOG(VB_GENERAL, LOG_DEBUG, QString("Setting Tuner to %1").arg(tuner));
1424 #endif
1425  _tuner = tuner;
1426  setValue(QString("%1-%2").arg(_ip).arg(_tuner));
1427 #if 0
1428  LOG(VB_GENERAL, LOG_DEBUG, QString("Done Setting Tuner to %1").arg(tuner));
1429 #endif
1430 }
1431 
1432 void HDHomeRunDeviceID::SetOverrideDeviceID(const QString &deviceid)
1433 {
1434  _overridedeviceid = deviceid;
1435  setValue(deviceid);
1436 }
1437 
1439 {
1441  if (!_overridedeviceid.isEmpty())
1442  {
1444  _overridedeviceid = QString::null;
1445  }
1446 }
1447 
1449  HDHomeRunDeviceID *deviceid,
1450  TransLabelSetting *desc,
1451  HDHomeRunIP *cardip,
1452  HDHomeRunTunerIndex *cardtuner,
1453  HDHomeRunDeviceList *devicelist) :
1454  _deviceid(deviceid),
1455  _desc(desc),
1456  _cardip(cardip),
1457  _cardtuner(cardtuner),
1458  _devicelist(devicelist)
1459 {
1460  setLabel(QObject::tr("Available devices"));
1461  setHelpText(
1462  QObject::tr(
1463  "Device ID and Tuner Number of available HDHomeRun devices."));
1464 
1465  connect(this, SIGNAL(valueChanged( const QString&)),
1466  this, SLOT( UpdateDevices(const QString&)));
1467 
1468  _oldValue = "";
1469 };
1470 
1475 {
1476  clearSelections();
1477 
1478  vector<QString> devs;
1479  QMap<QString, bool> in_use;
1480 
1481  QString current = cur;
1482 
1483 #if 0
1484  LOG(VB_GENERAL, LOG_DEBUG, QString("Filling List, current = '%1'")
1485  .arg(current));
1486 #endif
1487 
1488  HDHomeRunDeviceList::iterator it = _devicelist->begin();
1489  for (; it != _devicelist->end(); ++it)
1490  {
1491  if ((*it).discovered)
1492  {
1493  devs.push_back(it.key());
1494  in_use[it.key()] = (*it).inuse;
1495  }
1496  }
1497 
1498  QString man_addr = HDHomeRunDeviceIDList::tr("Manually Enter IP Address");
1499  QString sel = man_addr;
1500  devs.push_back(sel);
1501 
1502  if (3 == devs.size() && current.startsWith("FFFFFFFF", Qt::CaseInsensitive))
1503  {
1504  current = sel = (current.endsWith("0")) ?
1505  *(devs.begin()) : *(++devs.begin());
1506  }
1507  else
1508  {
1509  vector<QString>::const_iterator it = devs.begin();
1510  for (; it != devs.end(); ++it)
1511  sel = (current == *it) ? *it : sel;
1512  }
1513 
1514  QString usestr = QString(" -- ");
1515  usestr += QObject::tr("Warning: already in use");
1516 
1517  for (uint i = 0; i < devs.size(); i++)
1518  {
1519  const QString dev = devs[i];
1520  QString desc = dev + (in_use[devs[i]] ? usestr : "");
1521  desc = (current == devs[i]) ? dev : desc;
1522  addSelection(desc, dev, dev == sel);
1523  }
1524 
1525  if (current != cur)
1526  {
1527  _deviceid->SetOverrideDeviceID(current);
1528  }
1529  else if (sel == man_addr && !current.isEmpty())
1530  {
1531  // Populate the proper values for IP address and tuner
1532  QStringList selection = current.split("-");
1533 
1534  _cardip->SetOldValue(selection.first());
1535  _cardtuner->SetOldValue(selection.last());
1536 
1537  _cardip->setValue(selection.first());
1538  _cardtuner->setValue(selection.last());
1539  }
1540 }
1541 
1543 {
1544  clearSelections();
1545 
1547 }
1548 
1550 {
1551 #if 0
1552  LOG(VB_GENERAL, LOG_DEBUG, QString("Got signal with %1").arg(v));
1553 #endif
1554  if (v == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
1555  {
1556  _cardip->setEnabled(true);
1557  _cardtuner->setEnabled(true);
1558 #if 0
1559  LOG(VB_GENERAL, LOG_DEBUG, "Done");
1560 #endif
1561  }
1562  else if (!v.isEmpty())
1563  {
1564  if (_oldValue == HDHomeRunDeviceIDList::tr("Manually Enter IP Address"))
1565  {
1566  _cardip->setEnabled(false);
1567  _cardtuner->setEnabled(false);
1568  }
1569  _deviceid->setValue(v);
1570 
1571  // Update _cardip and cardtuner
1572  _cardip->setValue((*_devicelist)[v].cardip);
1573  _cardtuner->setValue(QString("%1").arg((*_devicelist)[v].cardtuner));
1574  _desc->setValue((*_devicelist)[v].desc);
1575  }
1576  _oldValue = v;
1577 };
1578 
1580 {
1581  public:
1583  LineEditSetting(this),
1584  CaptureCardDBStorage(this, parent, "videodevice")
1585  {
1586  setValue("http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1587  setLabel(QObject::tr("M3U URL"));
1588  setHelpText(
1589  QObject::tr("URL of M3U containing RTSP/RTP/UDP channel URLs."));
1590  }
1591 };
1592 
1594 {
1595  public:
1598  parent(a_parent),
1600  {
1601  setUseLabel(false);
1602  addChild(new IPTVHost(parent));
1603  addChild(new ChannelTimeout(parent, 30000, 1750));
1607 
1608  connect(instances, SIGNAL(valueChanged(int)),
1609  &parent, SLOT( SetInstanceCount(int)));
1610  };
1611 
1612  private:
1615 };
1616 
1618 {
1619  public:
1621  ComboBoxSetting(this, true),
1622  CaptureCardDBStorage(this, parent, "videodevice")
1623  {
1624  setLabel(QObject::tr("ASI device"));
1625  fillSelections(QString::null);
1626  };
1627 
1631  void fillSelections(const QString &current)
1632  {
1633  clearSelections();
1634 
1635  // Get devices from filesystem
1636  QStringList sdevs = CardUtil::ProbeVideoDevices("ASI");
1637 
1638  // Add current if needed
1639  if (!current.isEmpty() &&
1640  (find(sdevs.begin(), sdevs.end(), current) == sdevs.end()))
1641  {
1642  stable_sort(sdevs.begin(), sdevs.end());
1643  }
1644 
1645  // Get devices from DB
1646  QStringList db = CardUtil::GetVideoDevices("ASI");
1647 
1648  // Figure out which physical devices are already in use
1649  // by another card defined in the DB, and select a device
1650  // for new configs (preferring non-conflicing devices).
1651  QMap<QString,bool> in_use;
1652  QString sel = current;
1653  for (uint i = 0; i < (uint)sdevs.size(); i++)
1654  {
1655  const QString dev = sdevs[i];
1656  in_use[sdevs[i]] = find(db.begin(), db.end(), dev) != db.end();
1657  if (sel.isEmpty() && !in_use[sdevs[i]])
1658  sel = dev;
1659  }
1660 
1661  // Unfortunately all devices are conflicted, select first device.
1662  if (sel.isEmpty() && sdevs.size())
1663  sel = sdevs[0];
1664 
1665  QString usestr = QString(" -- ");
1666  usestr += QObject::tr("Warning: already in use");
1667 
1668  // Add the devices to the UI
1669  bool found = false;
1670  for (uint i = 0; i < (uint)sdevs.size(); i++)
1671  {
1672  const QString dev = sdevs[i];
1673  QString desc = dev + (in_use[sdevs[i]] ? usestr : "");
1674  desc = (current == sdevs[i]) ? dev : desc;
1675  addSelection(desc, dev, dev == sel);
1676  found |= (dev == sel);
1677  }
1678 
1679  // If a configured device isn't on the list, add it with warning
1680  if (!found && !current.isEmpty())
1681  {
1682  QString desc = current + " -- " +
1683  QObject::tr("Warning: unable to open");
1684  addSelection(desc, current, true);
1685  }
1686  }
1687 
1688  virtual void Load(void)
1689  {
1690  clearSelections();
1691  addSelection(QString::null);
1694  }
1695 };
1696 
1699  parent(a_parent),
1700  device(new ASIDevice(parent)),
1701  cardinfo(new TransLabelSetting()),
1702  instances(new InstanceCount(parent))
1703 {
1704  addChild(device);
1707  addChild(cardinfo);
1709 
1710  connect(device, SIGNAL(valueChanged(const QString&)),
1711  this, SLOT( probeCard( const QString&)));
1712  connect(instances, SIGNAL(valueChanged(int)),
1713  &parent, SLOT( SetInstanceCount(int)));
1714 
1716 };
1717 
1718 void ASIConfigurationGroup::probeCard(const QString &device)
1719 {
1720 #ifdef USING_ASI
1721  if (device.isEmpty())
1722  {
1723  cardinfo->setValue("");
1724  return;
1725  }
1726 
1727  if (parent.getCardID() && parent.GetRawCardType() != "ASI")
1728  {
1729  cardinfo->setValue("");
1730  return;
1731  }
1732 
1733  QString error;
1734  int device_num = CardUtil::GetASIDeviceNumber(device, &error);
1735  if (device_num < 0)
1736  {
1737  cardinfo->setValue(tr("Not a valid DVEO ASI card"));
1738  LOG(VB_GENERAL, LOG_WARNING,
1739  "ASIConfigurationGroup::probeCard(), Warning: " + error);
1740  return;
1741  }
1742  cardinfo->setValue(tr("Valid DVEO ASI card"));
1743 #else
1744  cardinfo->setValue(QString("Not compiled with ASI support"));
1745 #endif
1746 }
1747 
1750  parent(a_parent),
1751  info(new TransLabelSetting()), size(new TransLabelSetting())
1752 {
1753  FileDevice *device = new FileDevice(parent);
1754  device->setHelpText(tr("A local file used to simulate a recording."
1755  " Leave empty to use MythEvents to trigger an"
1756  " external program to import recording files."));
1757  addChild(device);
1758 
1761 
1762  info->setLabel(tr("File info"));
1763  addChild(info);
1764 
1765  size->setLabel(tr("File size"));
1766  addChild(size);
1767 
1768  connect(device, SIGNAL(valueChanged(const QString&)),
1769  this, SLOT( probeCard( const QString&)));
1770 
1771  probeCard(device->getValue());
1772 };
1773 
1774 void ImportConfigurationGroup::probeCard(const QString &device)
1775 {
1776  QString ci, cs;
1777  QFileInfo fileInfo(device);
1778 
1779  // For convenience, ImportRecorder allows both formats:
1780  if (device.toLower().startsWith("file:"))
1781  fileInfo.setFile(device.mid(5));
1782 
1783  if (fileInfo.exists())
1784  {
1785  if (fileInfo.isReadable() && (fileInfo.isFile()))
1786  {
1787  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
1788  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
1789  }
1790  else
1791  ci = tr("File not readable");
1792  }
1793  else
1794  {
1795  ci = tr("File %1 does not exist").arg(device);
1796  }
1797 
1798  info->setValue(ci);
1799  size->setValue(cs);
1800 }
1801 
1803 {
1804  public:
1807  {
1808  return (uint) count->intValue();
1809  }
1810 
1811  private:
1813 };
1814 
1816  count(new InstanceCount(parent.parent))
1817 {
1819  rec->setLabel(QObject::tr("Recorder Options"));
1820  rec->setUseLabel(false);
1821 
1822  rec->addChild(new SignalTimeout(parent.parent, 1000, 250));
1823  rec->addChild(new ChannelTimeout(parent.parent, 3000, 1750));
1824  rec->addChild(count);
1825 
1826  addChild(rec);
1827 }
1828 
1830  (CaptureCard& a_parent) :
1831  VerticalConfigurationGroup(false, true, false, false),
1832  parent(a_parent)
1833 {
1834  setUseLabel(false);
1835 
1836  // Fill Device list
1837  FillDeviceList();
1838 
1839  deviceid = new HDHomeRunDeviceID(parent);
1840  desc = new TransLabelSetting();
1841  desc->setLabel(tr("Description"));
1842  cardip = new HDHomeRunIP();
1843  cardtuner = new HDHomeRunTunerIndex();
1844  deviceidlist = new HDHomeRunDeviceIDList(
1845  deviceid, desc, cardip, cardtuner, &devicelist);
1846 
1847  addChild(deviceidlist);
1848  addChild(new EmptyAudioDevice(parent));
1849  addChild(new EmptyVBIDevice(parent));
1850  addChild(deviceid);
1851  addChild(desc);
1852  addChild(cardip);
1853  addChild(cardtuner);
1854 
1855  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
1856  buttonRecOpt->setLabel(tr("Recording Options"));
1857  addChild(buttonRecOpt);
1858 
1859  connect(buttonRecOpt, SIGNAL(pressed()),
1860  this, SLOT( HDHomeRunExtraPanel()));
1861 
1862  connect(cardip, SIGNAL(NewIP(const QString&)),
1863  deviceid, SLOT( SetIP(const QString&)));
1864  connect(cardtuner, SIGNAL(NewTuner(const QString&)),
1865  deviceid, SLOT( SetTuner(const QString&)));
1866 };
1867 
1869 {
1870  devicelist.clear();
1871 
1872  // Find physical devices first
1873  // ProbeVideoDevices returns "deviceid ip" pairs
1874  QStringList devs = CardUtil::ProbeVideoDevices("HDHOMERUN");
1875 
1876  QStringList::const_iterator it;
1877 
1878  for (it = devs.begin(); it != devs.end(); ++it)
1879  {
1880  QString dev = *it;
1881  QStringList devinfo = dev.split(" ");
1882  QString devid = devinfo.at(0);
1883  QString devip = devinfo.at(1);
1884  QString devtuner = devinfo.at(2);
1885 
1886  HDHomeRunDevice tmpdevice;
1887  tmpdevice.deviceid = devid;
1888  tmpdevice.desc = CardUtil::GetHDHRdesc(devid);
1889  tmpdevice.cardip = devip;
1890  tmpdevice.inuse = false;
1891  tmpdevice.discovered = true;
1892  tmpdevice.cardtuner = devtuner;
1893  tmpdevice.mythdeviceid =
1894  tmpdevice.deviceid + "-" + tmpdevice.cardtuner;
1895  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
1896  }
1897  uint found_device_count = devicelist.size();
1898 
1899  // Now find configured devices
1900 
1901  // returns "xxxxxxxx-n" or "ip.ip.ip.ip-n" values
1902  QStringList db = CardUtil::GetVideoDevices("HDHOMERUN");
1903 
1904  for (it = db.begin(); it != db.end(); ++it)
1905  {
1906  QMap<QString, HDHomeRunDevice>::iterator dit;
1907 
1908  dit = devicelist.find(*it);
1909 
1910  if (dit == devicelist.end())
1911  {
1912  if ((*it).toUpper() == "FFFFFFFF-0" && 2 == found_device_count)
1913  dit = devicelist.begin();
1914 
1915  if ((*it).toUpper() == "FFFFFFFF-1" && 2 == found_device_count)
1916  {
1917  dit = devicelist.begin();
1918  ++dit;
1919  }
1920  }
1921 
1922  if (dit != devicelist.end())
1923  {
1924  (*dit).inuse = true;
1925  continue;
1926  }
1927 
1928  HDHomeRunDevice tmpdevice;
1929  tmpdevice.mythdeviceid = *it;
1930  tmpdevice.inuse = true;
1931  tmpdevice.discovered = false;
1932 
1933  if (ProbeCard(tmpdevice))
1934  devicelist[tmpdevice.mythdeviceid] = tmpdevice;
1935  }
1936 
1937 #if 0
1938  // Debug dump of cards
1939  QMap<QString, HDHomeRunDevice>::iterator debugit;
1940  for (debugit = devicelist.begin(); debugit != devicelist.end(); ++debugit)
1941  {
1942  LOG(VB_GENERAL, LOG_DEBUG, QString("%1: %2 %3 %4 %5 %6 %7")
1943  .arg(debugit.key())
1944  .arg((*debugit).mythdeviceid)
1945  .arg((*debugit).deviceid)
1946  .arg((*debugit).cardip)
1947  .arg((*debugit).cardtuner)
1948  .arg((*debugit).inuse)
1949  .arg((*debugit).discovered));
1950  }
1951 #endif
1952 }
1953 
1955 {
1956 #ifdef USING_HDHOMERUN
1957  hdhomerun_device_t *thisdevice =
1958  hdhomerun_device_create_from_str(
1959  tmpdevice.mythdeviceid.toLocal8Bit().constData(), NULL);
1960 
1961  if (thisdevice)
1962  {
1963  uint device_id = hdhomerun_device_get_device_id(thisdevice);
1964  uint device_ip = hdhomerun_device_get_device_ip(thisdevice);
1965  uint tuner = hdhomerun_device_get_tuner(thisdevice);
1966  hdhomerun_device_destroy(thisdevice);
1967 
1968  if (device_id == 0)
1969  tmpdevice.deviceid = "NOTFOUND";
1970  else
1971  {
1972  tmpdevice.deviceid = QString("%1").arg(device_id, 8, 16);
1973  tmpdevice.desc = CardUtil::GetHDHRdesc(tmpdevice.deviceid);
1974  }
1975 
1976  tmpdevice.deviceid = tmpdevice.deviceid.toUpper();
1977 
1978  tmpdevice.cardip = QString("%1.%2.%3.%4")
1979  .arg((device_ip>>24) & 0xFF).arg((device_ip>>16) & 0xFF)
1980  .arg((device_ip>> 8) & 0xFF).arg((device_ip>> 0) & 0xFF);
1981 
1982  tmpdevice.cardtuner = QString("%1").arg(tuner);
1983  return true;
1984  }
1985 #endif // USING_HDHOMERUN
1986  return false;
1987 }
1988 
1990 {
1991  parent.reload(); // ensure card id is valid
1992 
1993  HDHomeRunExtra acw(*this);
1994  acw.exec();
1996 }
1997 
1998 // -----------------------
1999 // Ceton Configuration
2000 // -----------------------
2001 
2002 CetonSetting::CetonSetting(const char* label, const char* helptext)
2003 {
2004  setLabel(QObject::tr(label));
2005  setHelpText(tr(helptext));
2006  connect(this, SIGNAL(valueChanged( const QString&)),
2007  this, SLOT( UpdateDevices(const QString&)));
2008 }
2009 
2010 void CetonSetting::UpdateDevices(const QString &v)
2011 {
2012  if (isEnabled())
2013  emit NewValue(v);
2014 }
2015 
2016 void CetonSetting::LoadValue(const QString &value)
2017 {
2018  setValue(value);
2019 }
2020 
2022  LabelSetting(this),
2023  CaptureCardDBStorage(this, parent, "videodevice"),
2024  _ip(), _card(), _tuner(), _parent(parent)
2025 {
2026  setLabel(tr("Device ID"));
2027  setHelpText(tr("Device ID of Ceton device"));
2028 }
2029 
2030 void CetonDeviceID::SetIP(const QString &ip)
2031 {
2032  QString regexp = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$";
2033  if (QRegExp(regexp).exactMatch(ip + "."))
2034  {
2035  _ip = ip;
2036  setValue(QString("%1-RTP.%3").arg(_ip).arg(_tuner));
2037  }
2038 }
2039 
2040 void CetonDeviceID::SetTuner(const QString &tuner)
2041 {
2042  if (QRegExp("^\\d$").exactMatch(tuner))
2043  {
2044  _tuner = tuner;
2045  setValue(QString("%1-RTP.%2").arg(_ip).arg(_tuner));
2046  }
2047 }
2048 
2050 {
2052  UpdateValues();
2053 }
2054 
2056 {
2057  QRegExp newstyle("^([0-9.]+)-(\\d|RTP)\\.(\\d)$");
2058  if (newstyle.exactMatch(getValue()))
2059  {
2060  emit LoadedIP(newstyle.cap(1));
2061  emit LoadedTuner(newstyle.cap(3));
2062  }
2063  if (_parent.getCardID())
2065 }
2066 
2069  parent(a_parent), instances(new InstanceCount(parent))
2070 {
2071  setUseLabel(false);
2072 
2073  deviceid = new CetonDeviceID(parent);
2074  desc = new TransLabelSetting();
2075  desc->setLabel(tr("Description"));
2076  ip = new CetonSetting(
2077  "IP Address",
2078  "IP Address of the Ceton device (192.168.200.1 by default)");
2079  tuner = new CetonSetting(
2080  "Tuner",
2081  "Number of the tuner on the Ceton device (first tuner is number 0)");
2082 
2083  addChild(ip);
2084  addChild(tuner);
2085  addChild(deviceid);
2086  addChild(desc);
2088 
2089  connect(ip, SIGNAL(NewValue(const QString&)),
2090  deviceid, SLOT( SetIP(const QString&)));
2091  connect(tuner, SIGNAL(NewValue(const QString&)),
2092  deviceid, SLOT( SetTuner(const QString&)));
2093 
2094  connect(deviceid, SIGNAL(LoadedIP(const QString&)),
2095  ip, SLOT( LoadValue(const QString&)));
2096  connect(deviceid, SIGNAL(LoadedTuner(const QString&)),
2097  tuner, SLOT( LoadValue(const QString&)));
2098  connect(deviceid, SIGNAL(LoadedInstances(int)),
2099  instances, SLOT( setValue(int)));
2100  connect(instances, SIGNAL(valueChanged(int)),
2101  &parent, SLOT( SetInstanceCount(int)));
2102 
2103 };
2104 
2107  parent(a_parent),
2108  cardinfo(new TransLabelSetting()), vbidev(new VBIDevice(parent))
2109 {
2110  QString drv = "(?!ivtv|hdpvr|(saa7164(.*)))";
2111  VideoDevice *device = new VideoDevice(parent, 0, 15, QString::null, drv);
2113  new HorizontalConfigurationGroup(false, false, true, true);
2114 
2115  cardinfo->setLabel(tr("Probed info"));
2116  audgrp->addChild(new AudioRateLimit(parent));
2117  audgrp->addChild(new SkipBtAudio(parent));
2118 
2119  addChild(device);
2120  addChild(cardinfo);
2121  addChild(vbidev);
2122  addChild(new AudioDevice(parent));
2123  addChild(audgrp);
2124 
2125  connect(device, SIGNAL(valueChanged(const QString&)),
2126  this, SLOT( probeCard( const QString&)));
2127 
2128  probeCard(device->getValue());
2129 };
2130 
2131 void V4LConfigurationGroup::probeCard(const QString &device)
2132 {
2133  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2134 
2135  QByteArray adevice = device.toLatin1();
2136  int videofd = open(adevice.constData(), O_RDWR);
2137  if (videofd >= 0)
2138  {
2139  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2140  ci = cn = tr("Failed to probe");
2141  else if (!dn.isEmpty())
2142  ci = cn + " [" + dn + "]";
2143  close(videofd);
2144  }
2145 
2146  cardinfo->setValue(ci);
2147  vbidev->setFilter(cn, dn);
2148 }
2149 
2150 
2153  parent(a_parent),
2154  device(NULL), vbidevice(NULL),
2155  cardinfo(new TransLabelSetting())
2156 {
2157  QString drv = "ivtv|(saa7164(.*))";
2158  device = new VideoDevice(parent, 0, 15, QString::null, drv);
2159  vbidevice = new VBIDevice(parent);
2160  vbidevice->setVisible(false);
2161 
2162  cardinfo->setLabel(tr("Probed info"));
2163 
2164  addChild(device);
2166  addChild(cardinfo);
2167  addChild(new ChannelTimeout(parent, 12000, 2000));
2168 
2169  connect(device, SIGNAL(valueChanged(const QString&)),
2170  this, SLOT( probeCard( const QString&)));
2171 
2173 }
2174 
2175 void MPEGConfigurationGroup::probeCard(const QString &device)
2176 {
2177  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2178 
2179  QByteArray adevice = device.toLatin1();
2180  int videofd = open(adevice.constData(), O_RDWR);
2181  if (videofd >= 0)
2182  {
2183  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2184  ci = cn = tr("Failed to probe");
2185  else if (!dn.isEmpty())
2186  ci = cn + " [" + dn + "]";
2187  close(videofd);
2188  }
2189 
2190  cardinfo->setValue(ci);
2191  vbidevice->setVisible(dn!="ivtv");
2192  vbidevice->setFilter(cn, dn);
2193 }
2194 
2197  parent(a_parent),
2198  info(new TransLabelSetting()), size(new TransLabelSetting())
2199 {
2200  FileDevice *device = new FileDevice(parent);
2201  device->setHelpText(tr("A local MPEG file used to simulate a recording."
2202  " Must be entered as file:/path/movie.mpg"));
2203  device->addSelection("file:/");
2204  addChild(device);
2205 
2208 
2209  info->setLabel(tr("File info"));
2210  addChild(info);
2211 
2212  size->setLabel(tr("File size"));
2213  addChild(size);
2214 
2215  connect(device, SIGNAL(valueChanged(const QString&)),
2216  this, SLOT( probeCard( const QString&)));
2217 
2218  probeCard(device->getValue());
2219 }
2220 
2221 void DemoConfigurationGroup::probeCard(const QString &device)
2222 {
2223  if (!device.startsWith("file:", Qt::CaseInsensitive))
2224  {
2225  info->setValue("");
2226  size->setValue("");
2227  return;
2228  }
2229 
2230 
2231  QString ci, cs;
2232  QFileInfo fileInfo(device.mid(5));
2233  if (fileInfo.exists())
2234  {
2235  if (fileInfo.isReadable() && (fileInfo.isFile()))
2236  {
2237  ci = HTTPRequest::TestMimeType(fileInfo.absoluteFilePath());
2238  cs = tr("%1 MB").arg(fileInfo.size() / 1024 / 1024);
2239  }
2240  else
2241  ci = tr("File not readable");
2242  }
2243  else
2244  {
2245  ci = tr("File does not exist");
2246  }
2247 
2248  info->setValue(ci);
2249  size->setValue(cs);
2250 }
2251 
2252 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2255  parent(a_parent),
2256  info(new TransLabelSetting()),
2257  instances(new InstanceCount(parent))
2258 {
2259  FileDevice *device = new FileDevice(parent);
2260  device->setHelpText(tr("A 'black box' application controlled via "
2261  "stdin, status on stderr and TransportStream "
2262  "read from stdout"));
2263  addChild(device);
2264 
2265  info->setLabel(tr("File info"));
2266  addChild(info);
2268 
2269  connect(device, SIGNAL(valueChanged(const QString&)),
2270  this, SLOT( probeApp( const QString&)));
2271  connect(instances, SIGNAL(valueChanged(int)),
2272  &parent, SLOT( SetInstanceCount(int)));
2273 
2274  probeApp(device->getValue());
2275 }
2276 
2277 void ExternalConfigurationGroup::probeApp(const QString & path)
2278 {
2279  int idx1 = path.toLower().startsWith("file:") ? 5 : 0;
2280  int idx2 = path.indexOf(' ', idx1);
2281 
2282  QString ci, cs;
2283  QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2284 
2285  if (fileInfo.exists())
2286  {
2287  if (!fileInfo.isReadable() || !fileInfo.isFile())
2288  ci = tr("File not readable: ");
2289  if (!fileInfo.isExecutable())
2290  ci = tr("File is not exacutable: ");
2291  }
2292  else
2293  {
2294  ci = tr("File does not exist: ");
2295  }
2296  ci += QString("'%1'").arg(fileInfo.absoluteFilePath());
2297 
2298  info->setValue(ci);
2299 }
2300 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2301 
2304  parent(a_parent), cardinfo(new TransLabelSetting()),
2305  audioinput(new TunerCardAudioInput(parent, QString::null, "HDPVR"))
2306 {
2307  VideoDevice *device =
2308  new VideoDevice(parent, 0, 15, QString::null, "hdpvr");
2309 
2310  cardinfo->setLabel(tr("Probed info"));
2311 
2312  addChild(device);
2315  addChild(cardinfo);
2317  addChild(new ChannelTimeout(parent, 15000, 2000));
2318 
2319  connect(device, SIGNAL(valueChanged(const QString&)),
2320  this, SLOT( probeCard( const QString&)));
2321 
2322  probeCard(device->getValue());
2323 }
2324 
2325 void HDPVRConfigurationGroup::probeCard(const QString &device)
2326 {
2327  QString cn = tr("Failed to open"), ci = cn, dn = QString::null;
2328 
2329  int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2330  if (videofd >= 0)
2331  {
2332  if (!CardUtil::GetV4LInfo(videofd, cn, dn))
2333  ci = cn = tr("Failed to probe");
2334  else if (!dn.isEmpty())
2335  ci = cn + " [" + dn + "]";
2336  close(videofd);
2337  }
2338 
2339  cardinfo->setValue(ci);
2340  audioinput->fillSelections(device);
2341 }
2342 
2345 {
2346  setLabel(QObject::tr("Capture Card Setup"));
2347 
2348  CardType* cardtype = new CardType(parent);
2349  addChild(cardtype);
2350 
2351  setTrigger(cardtype);
2352  setSaveAll(false);
2353 
2354 #ifdef USING_DVB
2355  addTarget("DVB", new DVBConfigurationGroup(parent));
2356 #endif // USING_DVB
2357 
2358 #ifdef USING_V4L2
2359 # ifdef USING_HDPVR
2360  addTarget("HDPVR", new HDPVRConfigurationGroup(parent));
2361 # endif // USING_HDPVR
2362 #endif // USING_V4L2
2363 
2364 #ifdef USING_HDHOMERUN
2365  addTarget("HDHOMERUN", new HDHomeRunConfigurationGroup(parent));
2366 #endif // USING_HDHOMERUN
2367 
2368 #ifdef USING_FIREWIRE
2369  addTarget("FIREWIRE", new FirewireConfigurationGroup(parent));
2370 #endif // USING_FIREWIRE
2371 
2372 #ifdef USING_CETON
2373  addTarget("CETON", new CetonConfigurationGroup(parent));
2374 #endif // USING_CETON
2375 
2376 #ifdef USING_IPTV
2377  addTarget("FREEBOX", new IPTVConfigurationGroup(parent));
2378 #endif // USING_IPTV
2379 
2380 #ifdef USING_V4L2
2381  addTarget("V4L", new V4LConfigurationGroup(parent));
2382 # ifdef USING_IVTV
2383  addTarget("MPEG", new MPEGConfigurationGroup(parent));
2384 # endif // USING_IVTV
2385 #endif // USING_V4L2
2386 
2387 #ifdef USING_ASI
2388  addTarget("ASI", new ASIConfigurationGroup(parent));
2389 #endif // USING_ASI
2390 
2391  // for testing without any actual tuner hardware:
2392  addTarget("IMPORT", new ImportConfigurationGroup(parent));
2393  addTarget("DEMO", new DemoConfigurationGroup(parent));
2394 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2395  addTarget("EXTERNAL", new ExternalConfigurationGroup(parent));
2396 #endif
2397 }
2398 
2399 void CaptureCardGroup::triggerChanged(const QString& value)
2400 {
2401  QString own = (value == "MJPEG" || value == "GO7007") ? "V4L" : value;
2403 }
2404 
2405 CaptureCard::CaptureCard(bool use_card_group)
2406  : id(new ID), instance_count(0)
2407 {
2408  addChild(id);
2409  if (use_card_group)
2410  addChild(new CaptureCardGroup(*this));
2411  addChild(new Hostname(*this));
2412 }
2413 
2414 QString CaptureCard::GetRawCardType(void) const
2415 {
2416  int cardid = getCardID();
2417  if (cardid <= 0)
2418  return QString::null;
2419  return CardUtil::GetRawCardType(cardid);
2420 }
2421 
2423 {
2424  MSqlQuery query(MSqlQuery::InitCon());
2425  QString qstr =
2426  "SELECT cardid, videodevice, cardtype "
2427  "FROM capturecard "
2428  "WHERE hostname = :HOSTNAME AND parentid = 0 "
2429  "ORDER BY cardid";
2430 
2431  query.prepare(qstr);
2432  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2433 
2434  if (!query.exec())
2435  {
2436  MythDB::DBError("CaptureCard::fillSelections", query);
2437  return;
2438  }
2439 
2440  while (query.next())
2441  {
2442  uint cardid = query.value(0).toUInt();
2443  QString videodevice = query.value(1).toString();
2444  QString cardtype = query.value(2).toString();
2445  QString label = CardUtil::GetDeviceLabel(cardtype, videodevice);
2446  setting->addSelection(label, QString::number(cardid));
2447  }
2448 }
2449 
2450 void CaptureCard::loadByID(int cardid)
2451 {
2452  id->setValue(cardid);
2453  Load();
2454 
2455  // Update instance count for cloned cards.
2456  if (cardid)
2458 }
2459 
2461 {
2462  uint init_cardid = getCardID();
2463  QString init_type = CardUtil::GetRawCardType(init_cardid);
2464  QString init_dev = CardUtil::GetVideoDevice(init_cardid);
2465  QString init_input = CardUtil::GetInputName(init_cardid);
2466  vector<uint> cardids = CardUtil::GetChildCardIDs(init_cardid);
2467 
2469 
2471 
2473 
2474  uint cardid = getCardID();
2475  QString type = CardUtil::GetRawCardType(cardid);
2476  QString dev = CardUtil::GetVideoDevice(cardid);
2477 
2478  if (dev != init_dev)
2479  {
2480  if (!init_dev.isEmpty())
2481  {
2482  uint init_groupid = CardUtil::GetDeviceInputGroup(init_cardid);
2483  CardUtil::UnlinkInputGroup(init_cardid, init_groupid);
2484  }
2485  if (!dev.isEmpty())
2486  {
2487  uint groupid =
2489  dev);
2490  CardUtil::LinkInputGroup(cardid, groupid);
2491  CardUtil::UnlinkInputGroup(0, groupid);
2492  }
2493  }
2494 
2496  return;
2497 
2498  if (!instance_count)
2499  {
2500  instance_count = (init_cardid) ?
2501  max((size_t)1, cardids.size() + 1) : kDefaultMultirecCount;
2502  }
2503 
2504  // Delete old clone cards as required.
2505  for (uint i = cardids.size() + 1;
2506  (i > instance_count) && !cardids.empty(); --i)
2507  {
2508  CardUtil::DeleteCard(cardids.back());
2509  cardids.pop_back();
2510  }
2511 
2512  // Clone this config to existing clone cards.
2513  for (uint i = 0; i < cardids.size(); ++i)
2514  {
2515  CardUtil::CloneCard(cardid, cardids[i]);
2516  }
2517 
2518  // Create new clone cards as required.
2519  for (uint i = cardids.size() + 1; i < instance_count; i++)
2520  {
2521  CardUtil::CloneCard(cardid, 0);
2522  }
2523 }
2524 
2526 {
2527  if (getCardID() == 0)
2528  {
2529  Save();
2530  Load();
2531  }
2532 }
2533 
2535  ComboBoxSetting(this),
2536  CaptureCardDBStorage(this, parent, "cardtype")
2537 {
2538  setLabel(QObject::tr("Card type"));
2539  setHelpText(QObject::tr("Change the cardtype to the appropriate type for "
2540  "the capture card you are configuring."));
2541  fillSelections(this);
2542 }
2543 
2545 {
2546 #ifdef USING_DVB
2547  setting->addSelection(
2548  QObject::tr("DVB-T/S/C, ATSC or ISDB-T tuner card"), "DVB");
2549 #endif // USING_DVB
2550 
2551 #ifdef USING_V4L2
2552 # ifdef USING_HDPVR
2553  setting->addSelection(
2554  QObject::tr("HD-PVR H.264 encoder"), "HDPVR");
2555 # endif // USING_HDPVR
2556 #endif // USING_V4L2
2557 
2558 #ifdef USING_HDHOMERUN
2559  setting->addSelection(
2560  QObject::tr("HDHomeRun networked tuner"), "HDHOMERUN");
2561 #endif // USING_HDHOMERUN
2562 
2563 #ifdef USING_FIREWIRE
2564  setting->addSelection(
2565  QObject::tr("FireWire cable box"), "FIREWIRE");
2566 #endif // USING_FIREWIRE
2567 
2568 #ifdef USING_CETON
2569  setting->addSelection(
2570  QObject::tr("Ceton Cablecard tuner"), "CETON");
2571 #endif // USING_CETON
2572 
2573 #ifdef USING_IPTV
2574  setting->addSelection(QObject::tr("IPTV recorder"), "FREEBOX");
2575 #endif // USING_IPTV
2576 
2577 #ifdef USING_V4L2
2578 # ifdef USING_IVTV
2579  setting->addSelection(
2580  QObject::tr("Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"), "MPEG");
2581 # endif // USING_IVTV
2582  setting->addSelection(
2583  QObject::tr("Analog to MJPEG encoder card (Matrox G200, DC10, etc)"), "MJPEG");
2584  setting->addSelection(
2585  QObject::tr("Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2586  "GO7007");
2587  setting->addSelection(
2588  QObject::tr("Analog capture card"), "V4L");
2589 #endif // USING_V4L2
2590 
2591 #ifdef USING_ASI
2592  setting->addSelection(QObject::tr("DVEO ASI recorder"), "ASI");
2593 #endif
2594 
2595  setting->addSelection(QObject::tr("Import test recorder"), "IMPORT");
2596  setting->addSelection(QObject::tr("Demo test recorder"), "DEMO");
2597 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2598  setting->addSelection(QObject::tr("External (black box) recorder"),
2599  "EXTERNAL");
2600 #endif
2601 }
2602 
2604 {
2605  public:
2607  ComboBoxSetting(this), CardInputDBStorage(this, parent, "inputname")
2608  {
2609  setLabel(QObject::tr("Input name"));
2610  addSelection(QObject::tr("(None)"), "None");
2611  };
2612 
2613  virtual void Load(void)
2614  {
2615  fillSelections();
2617  };
2618 
2620  clearSelections();
2621  addSelection(QObject::tr("(None)"), "None");
2622  uint cardid = getInputID();
2623  QString type = CardUtil::GetRawCardType(cardid);
2624  QString device = CardUtil::GetVideoDevice(cardid);
2625  QStringList inputs;
2626  CardUtil::GetCardInputs(cardid, device, type, inputs);
2627  while (!inputs.isEmpty())
2628  {
2629  addSelection(inputs.front());
2630  inputs.pop_front();
2631  }
2632  };
2633 };
2634 
2636 {
2637  public:
2639  LineEditSetting(this),
2640  CardInputDBStorage(this, parent, "displayname")
2641  {
2642  setLabel(QObject::tr("Display name (optional)"));
2643  setHelpText(QObject::tr(
2644  "This name is displayed on screen when Live TV begins "
2645  "and when changing the selected input or card. If you "
2646  "use this, make sure the information is unique for "
2647  "each input."));
2648  };
2649 };
2650 
2652 {
2653  public:
2655  ComboBoxSetting(this), CardInputDBStorage(this, parent, "sourceid")
2656  {
2657  setLabel(QObject::tr("Video source"));
2658  addSelection(QObject::tr("(None)"), "0");
2659  };
2660 
2661  virtual void Load(void)
2662  {
2663  fillSelections();
2665  };
2666 
2668  clearSelections();
2669  addSelection(QObject::tr("(None)"), "0");
2671  };
2672 };
2673 
2675 {
2676  public:
2677  InputGroup(const CardInput &parent, uint group_num) :
2679  groupnum(group_num), groupid(0)
2680  {
2681  setLabel(QObject::tr("Input group") +
2682  QString(" %1").arg(groupnum + 1));
2683  setHelpText(QObject::tr(
2684  "Leave as 'Generic' unless this input is shared with "
2685  "another device. Only one of the inputs in an input "
2686  "group will be allowed to record at any given time."));
2687  }
2688 
2689  virtual void Load(void);
2690 
2691  virtual void Save(void)
2692  {
2693  uint inputid = cardinput.getInputID();
2694  uint new_groupid = getValue().toUInt();
2695 
2696  if (groupid)
2698 
2699  if (new_groupid)
2700  {
2701  if (CardUtil::UnlinkInputGroup(inputid, new_groupid))
2702  CardUtil::LinkInputGroup(inputid, new_groupid);
2703  }
2704  }
2705 
2706  virtual void Save(QString /*destination*/) { Save(); }
2707 
2708  private:
2712 };
2713 
2715 {
2716 #if 0
2717  LOG(VB_GENERAL, LOG_DEBUG, QString("InputGroup::Load() %1 %2")
2718  .arg(groupnum).arg(cardinput.getInputID()));
2719 #endif
2720 
2721  uint inputid = cardinput.getInputID();
2722  QMap<uint, uint> grpcnt;
2723  vector<QString> names;
2724  vector<uint> grpid;
2725  vector<uint> selected_groupids;
2726 
2727  names.push_back(QObject::tr("Generic"));
2728  grpid.push_back(0);
2729  grpcnt[0]++;
2730 
2731  MSqlQuery query(MSqlQuery::InitCon());
2732  query.prepare(
2733  "SELECT cardinputid, inputgroupid, inputgroupname "
2734  "FROM inputgroup "
2735  "WHERE inputgroupname LIKE 'user:%' "
2736  "ORDER BY inputgroupid, cardinputid, inputgroupname");
2737 
2738  if (!query.exec())
2739  {
2740  MythDB::DBError("InputGroup::Load()", query);
2741  }
2742  else
2743  {
2744  while (query.next())
2745  {
2746  uint groupid = query.value(1).toUInt();
2747  if (inputid && (query.value(0).toUInt() == inputid))
2748  selected_groupids.push_back(groupid);
2749 
2750  grpcnt[groupid]++;
2751 
2752  if (grpcnt[groupid] == 1)
2753  {
2754  names.push_back(query.value(2).toString().mid(5, -1));
2755  grpid.push_back(groupid);
2756  }
2757  }
2758  }
2759 
2760  // makes sure we select something
2761  groupid = 0;
2762  if (groupnum < selected_groupids.size())
2763  groupid = selected_groupids[groupnum];
2764 
2765 #if 0
2766  LOG(VB_GENERAL, LOG_DEBUG, QString("Group num: %1 id: %2")
2767  .arg(groupnum).arg(groupid));
2768  {
2769  QString msg;
2770  for (uint i = 0; i < selected_groupids.size(); i++)
2771  msg += QString("%1 ").arg(selected_groupids[i]);
2772  LOG(VB_GENERAL, LOG_DEBUG, msg);
2773  }
2774 #endif
2775 
2776  // add selections to combobox
2777  clearSelections();
2778  uint index = 0;
2779  for (uint i = 0; i < names.size(); i++)
2780  {
2781  bool sel = (groupid == grpid[i]);
2782  index = (sel) ? i : index;
2783 
2784 #if 0
2785  LOG(VB_GENERAL, LOG_DEBUG, QString("grpid %1, name '%2', i %3, s %4")
2786  .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ? "T" : "F"));
2787 #endif
2788 
2789  addSelection(names[i], QString::number(grpid[i]), sel);
2790  }
2791 
2792 #if 0
2793  LOG(VB_GENERAL, LOG_DEBUG, QString("Group index: %1").arg(index));
2794 #endif
2795 
2796  if (!names.empty())
2797  setValue(index);
2798 }
2799 
2801 {
2802  public:
2804  ComboBoxSetting(this), CardInputDBStorage(this, parent, "quicktune")
2805  {
2806  setLabel(QObject::tr("Use quick tuning"));
2807  addSelection(QObject::tr("Never"), "0", true);
2808  addSelection(QObject::tr("Live TV only"), "1", false);
2809  addSelection(QObject::tr("Always"), "2", false);
2810  setHelpText(QObject::tr(
2811  "If enabled, MythTV will tune using only the "
2812  "MPEG program number. The program numbers "
2813  "change more often than DVB or ATSC tuning "
2814  "parameters, so this is slightly less reliable. "
2815  "This will also inhibit EIT gathering during "
2816  "Live TV and recording."));
2817  };
2818 };
2819 
2821  public LineEditSetting, public CardInputDBStorage
2822 {
2823  public:
2825  LineEditSetting(this),
2826  CardInputDBStorage(this, parent, "externalcommand")
2827  {
2828  setLabel(QObject::tr("External channel change command"));
2829  setValue("");
2830  setHelpText(QObject::tr("If specified, this command will be run to "
2831  "change the channel for inputs which have an external "
2832  "tuner device such as a cable box. The first argument "
2833  "will be the channel number."));
2834  };
2835 };
2836 
2838 {
2839  public:
2841  LineEditSetting(this),
2842  CardInputDBStorage(this, parent, "tunechan")
2843  {
2844  setLabel(QObject::tr("Preset tuner to channel"));
2845  setValue("");
2846  setHelpText(QObject::tr("Leave this blank unless you have an external "
2847  "tuner that is connected to the tuner input of your card. "
2848  "If so, you will need to specify the preset channel for "
2849  "the signal (normally 3 or 4)."));
2850  };
2851 };
2852 
2853 void StartingChannel::SetSourceID(const QString &sourceid)
2854 {
2855  clearSelections();
2856  if (sourceid.isEmpty() || !sourceid.toUInt())
2857  return;
2858 
2859  // Get the existing starting channel
2860  QString startChan = CardUtil::GetStartingChannel(getInputID());
2861 
2862  ChannelInfoList channels = ChannelUtil::GetAllChannels(sourceid.toUInt());
2863 
2864  if (channels.empty())
2865  {
2866  addSelection(tr("Please add channels to this source"),
2867  startChan.isEmpty() ? "0" : startChan);
2868  return;
2869  }
2870 
2871  // If there are channels sort them, then add theme
2872  // (selecting the old start channel if it is there).
2873  QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
2874  ChannelUtil::SortChannels(channels, order);
2875  bool has_visible = false;
2876  for (uint i = 0; i < channels.size() && !has_visible; i++)
2877  has_visible |= channels[i].visible;
2878 
2879  for (uint i = 0; i < channels.size(); i++)
2880  {
2881  const QString channum = channels[i].channum;
2882  bool sel = channum == startChan;
2883  if (!has_visible || channels[i].visible || sel)
2884  {
2885  addSelection(channum, channum, sel);
2886  }
2887  }
2888 }
2889 
2891 {
2892  public:
2894  SpinBoxSetting(this, -99, 99, 1),
2895  CardInputDBStorage(this, parent, "recpriority")
2896  {
2897  setLabel(QObject::tr("Input priority"));
2898  setValue(0);
2899  setHelpText(QObject::tr("If the input priority is not equal for "
2900  "all inputs, the scheduler may choose to record a show "
2901  "at a later time so that it can record on an input with "
2902  "a higher value."));
2903  };
2904 };
2905 
2907 {
2908  public:
2909  ScheduleOrder(const CardInput &parent, int _value) :
2910  SpinBoxSetting(this, 0, 99, 1),
2911  CardInputDBStorage(this, parent, "schedorder")
2912  {
2913  setLabel(QObject::tr("Schedule order"));
2914  setValue(_value);
2915  setHelpText(QObject::tr("If priorities and other factors are equal "
2916  "the scheduler will choose the available "
2917  "input with the lowest, non-zero value. "
2918  "Setting this value to zero will make the "
2919  "input unavailable to the scheduler."));
2920  };
2921 };
2922 
2924 {
2925  public:
2926  LiveTVOrder(const CardInput &parent, int _value) :
2927  SpinBoxSetting(this, 0, 99, 1),
2928  CardInputDBStorage(this, parent, "livetvorder")
2929  {
2930  setLabel(QObject::tr("Live TV order"));
2931  setValue(_value);
2932  setHelpText(QObject::tr("When entering Live TV, the available, local "
2933  "input with the lowest, non-zero value will "
2934  "be used. If no local inputs are available, "
2935  "the available, remote input with the lowest, "
2936  "non-zero value will be used. "
2937  "Setting this value to zero will make the "
2938  "input unavailable to live TV."));
2939  };
2940 };
2941 
2943 {
2944  public:
2946  CheckBoxSetting(this),
2947  CardInputDBStorage(this, parent, "dishnet_eit")
2948  {
2949  setLabel(QObject::tr("Use DishNet long-term EIT data"));
2950  setValue(false);
2951  setHelpText(
2952  QObject::tr(
2953  "If you point your satellite dish toward DishNet's birds, "
2954  "you may wish to enable this feature. For best results, "
2955  "enable general EIT collection as well."));
2956  };
2957 };
2958 
2959 CardInput::CardInput(const QString & cardtype,
2960  bool isNewInput, int _cardid) :
2961  id(new ID()),
2962  inputname(new InputName(*this)),
2963  sourceid(new SourceID(*this)),
2964  startchan(new StartingChannel(*this)),
2965  scan(new TransButtonSetting()),
2966  srcfetch(new TransButtonSetting()),
2967  externalInputSettings(new DiSEqCDevSettings()),
2968  inputgrp0(new InputGroup(*this, 0)),
2969  inputgrp1(new InputGroup(*this, 1))
2970 {
2971  addChild(id);
2972 
2974  {
2976  _cardid, isNewInput));
2977  }
2978 
2979  ConfigurationGroup *basic =
2980  new VerticalConfigurationGroup(false, false, true, true);
2981 
2982  basic->setLabel(QObject::tr("Connect source to input"));
2983 
2984  basic->addChild(inputname);
2985  basic->addChild(new InputDisplayName(*this));
2986  basic->addChild(sourceid);
2987 
2988  if (CardUtil::IsEncoder(cardtype) || CardUtil::IsUnscanable(cardtype))
2989  {
2990  basic->addChild(new ExternalChannelCommand(*this));
2991  if (CardUtil::IsV4L(cardtype) && cardtype != "HDPVR")
2992  basic->addChild(new PresetTuner(*this));
2993  }
2994  else
2995  {
2996  ConfigurationGroup *chgroup =
2997  new HorizontalConfigurationGroup(false, false, true, true);
2998  chgroup->addChild(new QuickTune(*this));
2999  if ("DVB" == cardtype)
3000  chgroup->addChild(new DishNetEIT(*this));
3001  basic->addChild(chgroup);
3002  }
3003 
3004  scan->setLabel(tr("Scan for channels"));
3005  scan->setHelpText(
3006  tr("Use channel scanner to find channels for this input."));
3007 
3008  srcfetch->setLabel(tr("Fetch channels from listings source"));
3010  tr("This uses the listings data source to "
3011  "provide the channels for this input.") + " " +
3012  tr("This can take a long time to run."));
3013 
3014  ConfigurationGroup *sgrp =
3015  new HorizontalConfigurationGroup(false, false, true, true);
3016  sgrp->addChild(scan);
3017  sgrp->addChild(srcfetch);
3018  basic->addChild(sgrp);
3019 
3020  basic->addChild(startchan);
3021 
3022  addChild(basic);
3023 
3024  ConfigurationGroup *interact =
3025  new VerticalConfigurationGroup(false, false, true, true);
3026 
3027  interact->setLabel(QObject::tr("Interactions between inputs"));
3028  interact->addChild(new InputPriority(*this));
3029  interact->addChild(new ScheduleOrder(*this, _cardid));
3030  interact->addChild(new LiveTVOrder(*this, _cardid));
3031 
3032  TransButtonSetting *ingrpbtn = new TransButtonSetting("newgroup");
3033  ingrpbtn->setLabel(QObject::tr("Create a New Input Group"));
3034  ingrpbtn->setHelpText(
3035  QObject::tr("Input groups are only needed when two or more cards "
3036  "share the same resource such as a FireWire card and "
3037  "an analog card input controlling the same set top box."));
3038  interact->addChild(ingrpbtn);
3039  interact->addChild(inputgrp0);
3040  interact->addChild(inputgrp1);
3041 
3042  addChild(interact);
3043 
3044  setObjectName("CardInput");
3045  SetSourceID("-1");
3046 
3047  connect(scan, SIGNAL(pressed()), SLOT(channelScanner()));
3048  connect(srcfetch, SIGNAL(pressed()), SLOT(sourceFetch()));
3049  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3050  startchan,SLOT( SetSourceID (const QString&)));
3051  connect(sourceid, SIGNAL(valueChanged(const QString&)),
3052  this, SLOT( SetSourceID (const QString&)));
3053  connect(ingrpbtn, SIGNAL(pressed(QString)),
3054  this, SLOT( CreateNewInputGroup()));
3055 }
3056 
3058 {
3060  {
3061  delete externalInputSettings;
3062  externalInputSettings = NULL;
3063  }
3064 }
3065 
3066 void CardInput::SetSourceID(const QString &sourceid)
3067 {
3068  uint cid = id->getValue().toUInt();
3069  QString raw_card_type = CardUtil::GetRawCardType(cid);
3070  bool enable = (sourceid.toInt() > 0);
3071  scan->setEnabled(enable && !raw_card_type.isEmpty() &&
3072  !CardUtil::IsUnscanable(raw_card_type));
3073  srcfetch->setEnabled(enable);
3074 }
3075 
3076 QString CardInput::getSourceName(void) const
3077 {
3078  return sourceid->getSelectionLabel();
3079 }
3080 
3082 {
3083  QString new_name = QString::null;
3084  QString tmp_name = QString::null;
3085 
3086  inputgrp0->Save();
3087  inputgrp1->Save();
3088 
3089  while (true)
3090  {
3091  tmp_name = "";
3093  GetMythMainWindow(), tr("Create Input Group"),
3094  tr("Enter new group name"), tmp_name);
3095 
3096  if (!ok)
3097  return;
3098 
3099  if (tmp_name.isEmpty())
3100  {
3102  GetMythMainWindow(), tr("Error"),
3103  tr("Sorry, this Input Group name cannot be blank."));
3104  continue;
3105  }
3106 
3107  new_name = QString("user:") + tmp_name;
3108 
3109  MSqlQuery query(MSqlQuery::InitCon());
3110  query.prepare(
3111  "SELECT inputgroupname "
3112  "FROM inputgroup "
3113  "WHERE inputgroupname = :GROUPNAME");
3114  query.bindValue(":GROUPNAME", new_name);
3115 
3116  if (!query.exec())
3117  {
3118  MythDB::DBError("CreateNewInputGroup 1", query);
3119  return;
3120  }
3121 
3122  if (query.next())
3123  {
3125  GetMythMainWindow(), tr("Error"),
3126  tr("Sorry, this Input Group name is already in use."));
3127  continue;
3128  }
3129 
3130  break;
3131  }
3132 
3133  uint inputgroupid = CardUtil::CreateInputGroup(new_name);
3134 
3135  inputgrp0->Load();
3136  inputgrp1->Load();
3137 
3138  if (!inputgrp0->getValue().toUInt())
3139  {
3141  inputgrp0->getValueIndex(QString::number(inputgroupid)));
3142  }
3143  else
3144  {
3146  inputgrp1->getValueIndex(QString::number(inputgroupid)));
3147  }
3148 }
3149 
3151 {
3152  uint srcid = sourceid->getValue().toUInt();
3153  uint crdid = id->getValue().toUInt();
3154  QString in = inputname->getValue();
3155 
3156 #ifdef USING_BACKEND
3157  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3158 
3159  Save(); // save info for scanner.
3160 
3161  QString cardtype = CardUtil::GetRawCardType(crdid);
3162  if (CardUtil::IsUnscanable(cardtype))
3163  {
3164  LOG(VB_GENERAL, LOG_ERR,
3165  QString("Sorry, %1 cards do not yet support scanning.")
3166  .arg(cardtype));
3167  return;
3168  }
3169 
3170  ScanWizard *scanwizard = new ScanWizard(srcid, crdid, in);
3171  scanwizard->exec(false, true);
3172  scanwizard->deleteLater();
3173 
3174  if (SourceUtil::GetChannelCount(srcid))
3175  startchan->SetSourceID(QString::number(srcid));
3176  if (num_channels_before)
3177  {
3178  startchan->Load();
3179  startchan->Save();
3180  }
3181 #else
3182  LOG(VB_GENERAL, LOG_ERR, "You must compile the backend "
3183  "to be able to scan for channels");
3184 #endif
3185 }
3186 
3188 {
3189  uint srcid = sourceid->getValue().toUInt();
3190  uint crdid = id->getValue().toUInt();
3191 
3192  uint num_channels_before = SourceUtil::GetChannelCount(srcid);
3193 
3194  if (crdid && srcid)
3195  {
3196  Save(); // save info for fetch..
3197 
3198  QString cardtype = CardUtil::GetRawCardType(crdid);
3199 
3200  if (!CardUtil::IsCableCardPresent(crdid, cardtype) &&
3201  !CardUtil::IsUnscanable(cardtype) &&
3202  !CardUtil::IsEncoder(cardtype) &&
3203  !num_channels_before)
3204  {
3205  LOG(VB_GENERAL, LOG_ERR, "Skipping channel fetch, you need to "
3206  "scan for channels first.");
3207  return;
3208  }
3209 
3210  SourceUtil::UpdateChannelsFromListings(srcid, cardtype);
3211  }
3212 
3213  if (SourceUtil::GetChannelCount(srcid))
3214  startchan->SetSourceID(QString::number(srcid));
3215  if (num_channels_before)
3216  {
3217  startchan->Load();
3218  startchan->Save();
3219  }
3220 }
3221 
3223 {
3224  QString cardinputidTag(":WHERECARDID");
3225 
3226  QString query("cardid = " + cardinputidTag);
3227 
3228  bindings.insert(cardinputidTag, m_parent.getInputID());
3229 
3230  return query;
3231 }
3232 
3234 {
3235  QString cardinputidTag(":SETCARDID");
3236  QString colTag(":SET" + GetColumnName().toUpper());
3237 
3238  QString query("cardid = " + cardinputidTag + ", " +
3239  GetColumnName() + " = " + colTag);
3240 
3241  bindings.insert(cardinputidTag, m_parent.getInputID());
3242  bindings.insert(colTag, user->GetDBValue());
3243 
3244  return query;
3245 }
3246 
3247 void CardInput::loadByID(int inputid)
3248 {
3249  id->setValue(inputid);
3250  externalInputSettings->Load(inputid);
3252 }
3253 
3254 void CardInput::loadByInput(int _cardid, QString _inputname)
3255 {
3256  MSqlQuery query(MSqlQuery::InitCon());
3257  query.prepare("SELECT cardid FROM capturecard "
3258  "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3259  query.bindValue(":CARDID", _cardid);
3260  query.bindValue(":INPUTNAME", _inputname);
3261 
3262  if (query.exec() && query.isActive() && query.next())
3263  {
3264  loadByID(query.value(0).toInt());
3265  }
3266 }
3267 
3269 {
3270  uint src_cardid = id->getValue().toUInt();
3271  QString init_input = CardUtil::GetInputName(src_cardid);
3274 
3275  // Handle any cloning we may need to do
3276  QString type = CardUtil::GetRawCardType(src_cardid);
3278  {
3279  vector<uint> clones = CardUtil::GetChildCardIDs(src_cardid);
3280  for (uint i = 0; i < clones.size(); i++)
3281  CardUtil::CloneCard(src_cardid, clones[i]);
3282  }
3283 
3284  // Delete any orphaned inputs
3286  // Delete any unused input groups
3288 }
3289 
3291 {
3292  return m_parent.getInputID();
3293 }
3294 
3296 {
3297  return m_parent.getCardID();
3298 }
3299 
3301 {
3302  listbox->setLabel(tr("Capture cards"));
3303  addChild(listbox);
3304 }
3305 
3307 {
3309  edit();
3310 
3311  return kDialogCodeRejected;
3312 }
3313 
3315 {
3317  listbox->addSelection(QObject::tr("(New capture card)"), "0");
3318  listbox->addSelection(QObject::tr("(Delete all capture cards on %1)")
3319  .arg(gCoreContext->GetHostName()), "-1");
3320  listbox->addSelection(QObject::tr("(Delete all capture cards)"), "-2");
3322 }
3323 
3325  const char* widgetName)
3326 {
3327  dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
3328  connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(menu()));
3329  connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
3330  connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
3331  return dialog;
3332 }
3333 
3335 {
3336  if (!listbox->getValue().toInt())
3337  {
3338  CaptureCard cc;
3339  cc.exec();
3340  }
3341  else
3342  {
3345  "",
3346  tr("Capture Card Menu"),
3347  tr("Edit..."),
3348  tr("Delete..."),
3350 
3351  if (kDialogCodeButton0 == val)
3352  edit();
3353  else if (kDialogCodeButton1 == val)
3354  del();
3355  }
3356 }
3357 
3359 {
3360  const int cardid = listbox->getValue().toInt();
3361  if (-1 == cardid)
3362  {
3364  GetMythMainWindow(), "",
3365  tr("Are you sure you want to delete "
3366  "ALL capture cards on %1?").arg(gCoreContext->GetHostName()),
3367  tr("Yes, delete capture cards"),
3368  tr("No, don't"), kDialogCodeButton1);
3369 
3370  if (kDialogCodeButton0 == val)
3371  {
3372  MSqlQuery cards(MSqlQuery::InitCon());
3373 
3374  cards.prepare(
3375  "SELECT cardid "
3376  "FROM capturecard "
3377  "WHERE hostname = :HOSTNAME");
3378  cards.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3379 
3380  if (!cards.exec() || !cards.isActive())
3381  {
3384  tr("Error getting list of cards for this host"),
3385  tr("Unable to delete capturecards for %1")
3386  .arg(gCoreContext->GetHostName()));
3387 
3388  MythDB::DBError("Selecting cardids for deletion", cards);
3389  return;
3390  }
3391 
3392  while (cards.next())
3393  CardUtil::DeleteCard(cards.value(0).toUInt());
3394  }
3395  }
3396  else if (-2 == cardid)
3397  {
3399  GetMythMainWindow(), "",
3400  tr("Are you sure you want to delete "
3401  "ALL capture cards?"),
3402  tr("Yes, delete capture cards"),
3403  tr("No, don't"), kDialogCodeButton1);
3404 
3405  if (kDialogCodeButton0 == val)
3406  {
3408  Load();
3409  }
3410  }
3411  else
3412  {
3413  CaptureCard cc;
3414  if (cardid)
3415  cc.loadByID(cardid);
3416  cc.exec();
3417  }
3418 }
3419 
3421 {
3423  GetMythMainWindow(), "",
3424  tr("Are you sure you want to delete this capture card?"),
3425  tr("Yes, delete capture card"),
3426  tr("No, don't"), kDialogCodeButton1);
3427 
3428  if (kDialogCodeButton0 == val)
3429  {
3430  CardUtil::DeleteCard(listbox->getValue().toUInt());
3431  Load();
3432  }
3433 }
3434 
3436 {
3437  listbox->setLabel(tr("Video sources"));
3438  addChild(listbox);
3439 }
3440 
3442  const char* widgetName)
3443 {
3444  dialog = ConfigurationDialog::dialogWidget(parent, widgetName);
3445  connect(dialog, SIGNAL(menuButtonPressed()), this, SLOT(menu()));
3446  connect(dialog, SIGNAL(editButtonPressed()), this, SLOT(edit()));
3447  connect(dialog, SIGNAL(deleteButtonPressed()), this, SLOT(del()));
3448  return dialog;
3449 }
3450 
3452 {
3454  edit();
3455 
3456  return kDialogCodeRejected;
3457 }
3458 
3460 {
3462  listbox->addSelection(QObject::tr("(New video source)"), "0");
3463  listbox->addSelection(QObject::tr("(Delete all video sources)"), "-1");
3465 }
3466 
3468 {
3469  if (!listbox->getValue().toInt())
3470  {
3471  VideoSource vs;
3472  vs.exec();
3473  }
3474  else
3475  {
3478  "",
3479  tr("Video Source Menu"),
3480  tr("Edit..."),
3481  tr("Delete..."),
3483 
3484  if (kDialogCodeButton0 == val)
3485  edit();
3486  else if (kDialogCodeButton1 == val)
3487  del();
3488  }
3489 }
3490 
3492 {
3493  const int sourceid = listbox->getValue().toInt();
3494  if (-1 == sourceid)
3495  {
3497  GetMythMainWindow(), "",
3498  tr("Are you sure you want to delete "
3499  "ALL video sources?"),
3500  tr("Yes, delete video sources"),
3501  tr("No, don't"), kDialogCodeButton1);
3502 
3503  if (kDialogCodeButton0 == val)
3504  {
3506  Load();
3507  }
3508  }
3509  else
3510  {
3511  VideoSource vs;
3512  if (sourceid)
3513  vs.loadByID(sourceid);
3514  vs.exec();
3515  }
3516 }
3517 
3519 {
3521  GetMythMainWindow(), "",
3522  tr("Are you sure you want to delete "
3523  "this video source?"),
3524  tr("Yes, delete video source"),
3525  tr("No, don't"),
3527 
3528  if (kDialogCodeButton0 == val)
3529  {
3531  Load();
3532  }
3533 }
3534 
3536 {
3537  listbox->setLabel(tr("Input connections"));
3538  addChild(listbox);
3539 }
3540 
3542 {
3544  {
3545  if (!listbox)
3546  return kDialogCodeRejected;
3547 
3548  if (cardinputs.empty())
3549  return kDialogCodeRejected;
3550 
3551  int val = listbox->getValue().toInt();
3552 
3553  if (cardinputs[val])
3554  cardinputs[val]->exec();
3555  }
3556 
3557  return kDialogCodeRejected;
3558 }
3559 
3561 {
3562  cardinputs.clear();
3564 
3565  // We do this manually because we want custom labels. If
3566  // SelectSetting provided a facility to edit the labels, we
3567  // could use CaptureCard::fillSelections
3568 
3569  MSqlQuery query(MSqlQuery::InitCon());
3570  query.prepare(
3571  "SELECT cardid, videodevice, cardtype, inputname "
3572  "FROM capturecard "
3573  "WHERE hostname = :HOSTNAME "
3574  " AND parentid = 0 "
3575  "ORDER BY cardid");
3576  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
3577 
3578  if (!query.exec())
3579  {
3580  MythDB::DBError("CardInputEditor::load", query);
3581  return;
3582  }
3583 
3584  uint j = 0;
3585  QMap<QString, uint> device_refs;
3586  while (query.next())
3587  {
3588  uint cardid = query.value(0).toUInt();
3589  QString videodevice = query.value(1).toString();
3590  QString cardtype = query.value(2).toString();
3591  QString inputname = query.value(3).toString();
3592  if (inputname.isEmpty())
3593  inputname = QObject::tr("(None)");
3594 
3595  CardInput *cardinput = new CardInput(cardtype, false, cardid);
3596  cardinput->loadByID(cardid);
3597  QString inputlabel = QString("%1 (%2) -> %3")
3598  .arg(CardUtil::GetDeviceLabel(cardtype, videodevice))
3599  .arg(inputname).arg(cardinput->getSourceName());
3600  cardinputs.push_back(cardinput);
3601  listbox->addSelection(inputlabel, QString::number(j++));
3602  }
3603 }
3604 
3605 #ifdef USING_DVB
3606 static QString remove_chaff(const QString &name)
3607 {
3608  // Trim off some of the chaff.
3609  QString short_name = name;
3610  if (short_name.startsWith("LG Electronics"))
3611  short_name = short_name.right(short_name.length() - 15);
3612  if (short_name.startsWith("Oren"))
3613  short_name = short_name.right(short_name.length() - 5);
3614  if (short_name.startsWith("Nextwave"))
3615  short_name = short_name.right(short_name.length() - 9);
3616  if (short_name.startsWith("frontend", Qt::CaseInsensitive))
3617  short_name = short_name.left(short_name.length() - 9);
3618  if (short_name.endsWith("VSB/QAM"))
3619  short_name = short_name.left(short_name.length() - 8);
3620  if (short_name.endsWith("VSB"))
3621  short_name = short_name.left(short_name.length() - 4);
3622  if (short_name.endsWith("DVB-T"))
3623  short_name = short_name.left(short_name.length() - 6);
3624 
3625  // It would be infinitely better if DVB allowed us to query
3626  // the vendor ID. But instead we have to guess based on the
3627  // demodulator name. This means cards like the Air2PC HD5000
3628  // and DViCO Fusion HDTV cards are not identified correctly.
3629  short_name = short_name.simplified();
3630  if (short_name.startsWith("or51211", Qt::CaseInsensitive))
3631  short_name = "pcHDTV HD-2000";
3632  else if (short_name.startsWith("or51132", Qt::CaseInsensitive))
3633  short_name = "pcHDTV HD-3000";
3634  else if (short_name.startsWith("bcm3510", Qt::CaseInsensitive))
3635  short_name = "Air2PC v1";
3636  else if (short_name.startsWith("nxt2002", Qt::CaseInsensitive))
3637  short_name = "Air2PC v2";
3638  else if (short_name.startsWith("nxt200x", Qt::CaseInsensitive))
3639  short_name = "Air2PC v2";
3640  else if (short_name.startsWith("lgdt3302", Qt::CaseInsensitive))
3641  short_name = "DViCO HDTV3";
3642  else if (short_name.startsWith("lgdt3303", Qt::CaseInsensitive))
3643  short_name = "DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3644 
3645  return short_name;
3646 }
3647 #endif // USING_DVB
3648 
3649 void DVBConfigurationGroup::probeCard(const QString &videodevice)
3650 {
3651  if (videodevice.isEmpty())
3652  {
3653  cardname->setValue("");
3654  cardtype->setValue("");
3655  return;
3656  }
3657 
3658  if (parent.getCardID() && parent.GetRawCardType() != "DVB")
3659  {
3660  cardname->setValue("");
3661  cardtype->setValue("");
3662  return;
3663  }
3664 
3665 #ifdef USING_DVB
3666  QString frontend_name = CardUtil::ProbeDVBFrontendName(videodevice);
3667  QString subtype = CardUtil::ProbeDVBType(videodevice);
3668 
3669  QString err_open = tr("Could not open card %1").arg(videodevice);
3670  QString err_other = tr("Could not get card info for card %1").arg(videodevice);
3671 
3672  switch (CardUtil::toCardType(subtype))
3673  {
3674  case CardUtil::ERROR_OPEN:
3675  cardname->setValue(err_open);
3676  cardtype->setValue(strerror(errno));
3677  break;
3679  cardname->setValue(err_other);
3680  cardtype->setValue("Unknown error");
3681  break;
3682  case CardUtil::ERROR_PROBE:
3683  cardname->setValue(err_other);
3684  cardtype->setValue(strerror(errno));
3685  break;
3686  case CardUtil::QPSK:
3687  cardtype->setValue("DVB-S");
3688  cardname->setValue(frontend_name);
3689  signal_timeout->setValue(7000);
3690  channel_timeout->setValue(10000);
3691  break;
3692  case CardUtil::DVBS2:
3693  cardtype->setValue("DVB-S2");
3694  cardname->setValue(frontend_name);
3695  signal_timeout->setValue(7000);
3696  channel_timeout->setValue(10000);
3697  break;
3698  case CardUtil::QAM:
3699  cardtype->setValue("DVB-C");
3700  cardname->setValue(frontend_name);
3701  signal_timeout->setValue(1000);
3702  channel_timeout->setValue(3000);
3703  break;
3704  case CardUtil::OFDM:
3705  {
3706  cardtype->setValue("DVB-T");
3707  cardname->setValue(frontend_name);
3708  signal_timeout->setValue(1000);
3709  channel_timeout->setValue(3000);
3710  if (frontend_name.toLower().indexOf("usb") >= 0)
3711  {
3712  signal_timeout->setValue(40000);
3713  channel_timeout->setValue(42500);
3714  }
3715 
3716  // slow down tuning for buggy drivers
3717  if ((frontend_name == "DiBcom 3000P/M-C DVB-T") ||
3718  (frontend_name ==
3719  "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
3720  {
3721  tuning_delay->setValue(200);
3722  }
3723 
3724 #if 0 // frontends on hybrid DVB-T/Analog cards
3725  QString short_name = remove_chaff(frontend_name);
3727  short_name.startsWith("zarlink zl10353",
3728  Qt::CaseInsensitive) ||
3729  short_name.startsWith("wintv hvr 900 m/r: 65008/a1c0",
3730  Qt::CaseInsensitive) ||
3731  short_name.startsWith("philips tda10046h",
3732  Qt::CaseInsensitive));
3733 #endif
3734  }
3735  break;
3736  case CardUtil::ATSC:
3737  {
3738  QString short_name = remove_chaff(frontend_name);
3739  cardtype->setValue("ATSC");
3740  cardname->setValue(short_name);
3741  signal_timeout->setValue(500);
3742  channel_timeout->setValue(3000);
3743 
3744  // According to #1779 and #1935 the AverMedia 180 needs
3745  // a 3000 ms signal timeout, at least for QAM tuning.
3746  if (frontend_name == "Nextwave NXT200X VSB/QAM frontend")
3747  {
3748  signal_timeout->setValue(3000);
3749  channel_timeout->setValue(5500);
3750  }
3751 
3752 #if 0 // frontends on hybrid DVB-T/Analog cards
3753  if (frontend_name.toLower().indexOf("usb") < 0)
3754  {
3756  short_name.startsWith("pchdtv", Qt::CaseInsensitive) ||
3757  short_name.startsWith("dvico", Qt::CaseInsensitive) ||
3758  short_name.startsWith("nextwave", Qt::CaseInsensitive));
3759  }
3760 #endif
3761  }
3762  break;
3763  default:
3764  break;
3765  }
3766 #else
3767  cardtype->setValue(QString("Recompile with DVB-Support!"));
3768 #endif
3769 }
3770 
3772  QString dev, QString type) :
3773  ComboBoxSetting(this), CaptureCardDBStorage(this, parent, "audiodevice"),
3774  last_device(dev), last_cardtype(type)
3775 {
3776  setLabel(QObject::tr("Audio input"));
3777  int cardid = parent.getCardID();
3778  if (cardid <= 0)
3779  return;
3780 
3783 }
3784 
3785 void TunerCardAudioInput::fillSelections(const QString &device)
3786 {
3787  clearSelections();
3788 
3789  if (device.isEmpty())
3790  return;
3791 
3792  last_device = device;
3793  QStringList inputs =
3795 
3796  for (uint i = 0; i < (uint)inputs.size(); i++)
3797  {
3798  addSelection(inputs[i], QString::number(i),
3799  last_device == QString::number(i));
3800  }
3801 }
3802 
3804 {
3805  public:
3808  {
3809  return (uint) count->intValue();
3810  }
3811 
3812  private:
3814 };
3815 
3817  : count(new InstanceCount(parent.parent))
3818 {
3820  rec->setLabel(QObject::tr("Recorder Options"));
3821  rec->setUseLabel(false);
3822 
3823  rec->addChild(count);
3824  rec->addChild(new DVBNoSeqStart(parent.parent));
3825  rec->addChild(new DVBOnDemand(parent.parent));
3826  rec->addChild(new DVBEITScan(parent.parent));
3827  rec->addChild(new DVBTuningDelay(parent.parent));
3828 
3829  addChild(rec);
3830 }
3831 
3834  parent(a_parent),
3835  diseqc_tree(new DiSEqCDevTree())
3836 {
3837  cardnum = new DVBCardNum(parent);
3838  cardname = new DVBCardName();
3839  cardtype = new DVBCardType();
3840 
3841  signal_timeout = new SignalTimeout(parent, 500, 250);
3842  channel_timeout = new ChannelTimeout(parent, 3000, 1750);
3843 
3844  addChild(cardnum);
3845 
3847  new HorizontalConfigurationGroup(false, false, true, true);
3848  hg0->addChild(cardname);
3849  hg0->addChild(cardtype);
3850  addChild(hg0);
3851 
3854 
3857 
3858  TransButtonSetting *buttonRecOpt = new TransButtonSetting();
3859  buttonRecOpt->setLabel(tr("Recording Options"));
3860 
3862  new HorizontalConfigurationGroup(false, false, true, true);
3863  advcfg->addChild(buttonRecOpt);
3864  addChild(advcfg);
3865 
3867  diseqc_btn->setLabel(tr("DiSEqC (Switch, LNB, and Rotor Configuration)"));
3868  diseqc_btn->setHelpText(tr("Input and satellite settings."));
3869 
3870  HorizontalConfigurationGroup *diseqc_cfg =
3871  new HorizontalConfigurationGroup(false, false, true, true);
3872  diseqc_cfg->addChild(diseqc_btn);
3873  diseqc_btn->setVisible(false);
3874  addChild(diseqc_cfg);
3875 
3878  tuning_delay->setVisible(false);
3879 
3880  connect(cardnum, SIGNAL(valueChanged(const QString&)),
3881  this, SLOT( probeCard (const QString&)));
3882  connect(diseqc_btn, SIGNAL(pressed()),
3883  this, SLOT( DiSEqCPanel()));
3884  connect(buttonRecOpt, SIGNAL(pressed()),
3885  this, SLOT( DVBExtraPanel()));
3886 }
3887 
3889 {
3890  if (diseqc_tree)
3891  {
3892  delete diseqc_tree;
3893  diseqc_tree = NULL;
3894  }
3895 }
3896 
3898 {
3899  parent.reload(); // ensure card id is valid
3900 
3901  DTVDeviceTreeWizard diseqcWiz(*diseqc_tree);
3902  diseqcWiz.exec();
3903 }
3904 
3906 {
3909  if (cardtype->getValue() == "DVB-S" ||
3910  cardtype->getValue() == "DVB-S2" ||
3912  {
3913  diseqc_btn->setVisible(true);
3914  }
3915 }
3916 
3918 {
3921  DiSEqCDev trees;
3922  trees.InvalidateTrees();
3923 }
3924 
3926 {
3927  parent.reload(); // ensure card id is valid
3928 
3929  DVBExtra acw(*this);
3930  acw.exec();
3932 }
void SetOldValue(const QString &s)
Definition: videosource.h:880
virtual void setValue(const QString &newValue)
Definition: settings.cpp:96
QStringList grabberArgs
Definition: videosource.h:179
static bool UpdateChannelsFromListings(uint sourceid, QString cardtype=QString::null, bool wait=false)
Definition: sourceutil.cpp:362
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:785
TransButtonSetting * scan
Definition: videosource.h:841
HDHomeRunIP * _cardip
Definition: videosource.h:915
DataDirectUserID(const VideoSource &parent)
QuickTune(const CardInput &parent)
void UpdateDevices(const QString &)
void Run(time_t timeout=0)
Runs a command inside the /bin/sh shell. Returns immediately.
static bool IsTunerSharingCapable(const QString &rawtype)
Definition: cardutil.h:155
void LoadedInstances(int)
static QString remove_chaff(const QString &name)
StorageUser * user
Definition: mythstorage.h:46
void SetSourceID(uint _sourceid)
virtual void Load(void)
virtual void clearSelections(void)
Definition: settings.cpp:175
void setVisible(bool b)
Definition: settings.h:65
virtual void setHelpText(const QString &str)
Definition: settings.cpp:561
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:297
virtual void setEnabled(bool e)
TransLabelSetting * cardinfo
Definition: videosource.h:449
virtual void setValue(bool check)
Definition: settings.h:431
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:884
DiSEqCDevSettings * externalInputSettings
Definition: videosource.h:843
vector< CardInput * > cardinputs
Definition: videosource.h:782
Definition: cc.h:13
static ChannelInfoList GetAllChannels(uint sourceid)
Returns channels that are not connected to a capture card and channels that are not marked as visible...
Definition: channelutil.h:243
DVB-S device settings class.
Definition: diseqc.h:37
TransButtonSetting * srcfetch
Definition: videosource.h:842
QString _tuner
Definition: videosource.h:981
const CaptureCard & _parent
Definition: videosource.h:982
static QString GetInputName(uint inputid)
Definition: cardutil.cpp:1109
void fillSelections()
CaptureCard & parent
Definition: videosource.h:427
void valueChanged(const QString &)
virtual DialogCode exec(void)
virtual void Load(void)
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:83
static bool CloneCard(uint src_cardid, uint dst_cardid)
Definition: cardutil.cpp:859
virtual void setLabel(QString str)
Definition: settings.cpp:930
allow access to stdout
Definition: mythsystem.h:39
virtual void Save(void)
static QStringList GetVideoDevices(const QString &rawtype, QString hostname=QString::null)
Returns the videodevices of the matching cards, duplicates removed.
Definition: cardutil.cpp:254
bool Store(uint cardid)
Stores the device tree to the database.
Definition: diseqc.cpp:402
virtual MythDialog * dialogWidget(MythMainWindow *parent, const char *widgetName=0)
VideoDevice(const CaptureCard &parent, uint minor_min=0, uint minor_max=UINT_MAX, QString card=QString::null, QString driver=QString::null)
virtual void Load(void)
virtual void Load(void)
virtual void Save(void)
HDHomeRunDeviceIDList(HDHomeRunDeviceID *deviceid, TransLabelSetting *desc, HDHomeRunIP *cardip, HDHomeRunTunerIndex *cardtuner, HDHomeRunDeviceList *devicelist)
virtual void Save(void)
void setProgress(int curprogress)
virtual QString getSelectionLabel(void) const
Definition: settings.cpp:213
virtual void setEnabled(bool b)
Definition: settings.cpp:688
CardType(const CaptureCard &parent)
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:1342
void probeCard(const QString &device)
bool Load(uint cardid)
Loads the device tree from the database.
Definition: diseqc.cpp:331
virtual void deleteLater(void)
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:400
int getCardID(void) const
static DialogCode Show2ButtonPopup(MythMainWindow *parent, const QString &title, const QString &message, const QString &button1msg, const QString &button2msg, DialogCode default_button)
QString _oldValue
Definition: videosource.h:869
void SetSourceID(const QString &sourceid)
TunerCardAudioInput(const CaptureCard &parent, QString dev=QString::null, QString type=QString::null)
EITOnly_config(const VideoSource &_parent)
ASIDevice(const CaptureCard &parent)
AudioRateLimit(const CaptureCard &parent)
virtual void Load(void)
NoGrabber_config(const VideoSource &_parent)
static uint GetChannelCount(uint sourceid)
Definition: sourceutil.cpp:109
bool visible
Definition: settings.h:91
uint modelid
Definition: avcinfo.h:44
SignalTimeout(const CaptureCard &parent, uint value, uint min_val)
QVariant value(int i) const
Definition: mythdbcon.h:182
static void error(const char *str,...)
Definition: vbi.c:41
static bool DeleteSource(uint sourceid)
Definition: sourceutil.cpp:479
virtual void setHelpText(const QString &str)
Definition: settings.cpp:369
virtual int getValueIndex(QString value)
Returns index of value in SelectSetting, or -1 if not found.
Definition: settings.cpp:224
virtual void setVisible(bool b)
Definition: settings.cpp:695
CetonDeviceID * deviceid
Definition: videosource.h:429
TransButtonSetting * buttonAnalog
Definition: videosource.h:595
GLuint index
TransLabelSetting * desc
Definition: videosource.h:428
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
ScheduleOrder(const CardInput &parent, int _value)
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
static QString ProbeDVBFrontendName(const QString &device)
Returns the card type from the video device.
Definition: cardutil.cpp:446
uint GetInstanceCount(void) const
LiveTVOrder(const CardInput &parent, int _value)
static QString GetRawCardType(uint cardid)
Definition: cardutil.h:258
QString lastloadedpassword
Definition: videosource.h:159
virtual void Load(void)
DVBExtra(DVBConfigurationGroup &parent)
QString _overridedeviceid
Definition: videosource.h:939
QString label
Definition: settings.h:89
static bool IsUnscanable(const QString &rawtype)
Definition: cardutil.h:137
bool cardTypesInclude(const int &SourceID, const QString &thecardtype)
InputGroup(const CardInput &parent, uint group_num)
FirewireModel(const CaptureCard &parent, const FirewireGUID *)
DVBEITScan(const CaptureCard &parent)
virtual void addChild(Configurable *child)
virtual DialogCode exec(void)
InstanceCount * instances
Definition: videosource.h:506
static bool IsInNeedOfExternalInputConf(uint cardid)
Definition: cardutil.cpp:1610
AllMusic * parent
int getInputID(void) const
Definition: videosource.h:811
void CreateNewInputGroup()
static uint GetChildCardCount(uint cardid)
Definition: cardutil.cpp:677
HDHomeRunDeviceList * _devicelist
Definition: videosource.h:917
InputDisplayName(const CardInput &parent)
const FirewireGUID * guid
Definition: videosource.h:629
ChannelTimeout * channel_timeout
Definition: videosource.h:593
const char * filename
Definition: ioapi.h:135
virtual void setValue(const QString &newValue)
Definition: settings.cpp:707
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
TransLabelSetting * cardinfo
Definition: videosource.h:505
GLint GLenum GLsizei GLint GLenum GLenum type
unsigned current
Definition: settings.h:308
SourceID * sourceid
Definition: videosource.h:839
static bool DeleteCard(uint cardid)
Definition: cardutil.cpp:2084
V4LConfigurationGroup(CaptureCard &parent)
QString product_name
Definition: avcinfo.h:46
QString lastloadeduserid
Definition: videosource.h:158
TransLabelSetting * info
Definition: videosource.h:539
DataDirectPassword * password
Definition: videosource.h:155
IPTVHost(const CaptureCard &parent)
XMLTVConfig * xmltv
Definition: videosource.h:275
DDLineupList GetLineups(void) const
Definition: datadirect.h:343
CetonDeviceID(const CaptureCard &parent)
virtual DialogCode exec(void)
int getSourceID(void) const
Definition: videosource.h:230
int size(void) const
Definition: mythdbcon.h:187
HDHomeRunDeviceList devicelist
Definition: videosource.h:412
virtual QString GetDBValue(void) const =0
HDHomeRunDeviceID * _deviceid
Definition: videosource.h:913
void NewTuner(const QString &)
ListBoxSetting * listbox
Definition: videosource.h:783
TransLabelSetting * cardinfo
Definition: videosource.h:470
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
VideoSourceSelector(uint _initial_sourceid, const QString &_card_types, bool _must_have_mplexid)
Definition: videosource.cpp:61
void UpdateDevices(const QString &)
uint GetInstanceCount(void) const
CaptureCard & parent
Definition: videosource.h:448
QString GetRawCardType(void) const
bool ProbeCard(HDHomeRunDevice &)
InputGroup * inputgrp0
Definition: videosource.h:844
void probeApp(const QString &path)
QMap< QString, HDHomeRunDevice > HDHomeRunDeviceList
Definition: videosource.h:383
DVBTuningDelay(const CaptureCard &parent)
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:137
virtual MythDialog * dialogWidget(MythMainWindow *parent, const char *widgetName=0)
InstanceCount * instances
InstanceCount * instances
Definition: videosource.h:432
virtual void Save(void)
virtual void Load(void)
void SetOldValue(const QString &s)
Definition: videosource.h:859
void probeCard(const QString &device)
virtual void Load(void)
Definition: videosource.cpp:73
void fillSelections(const QString &current)
Adds all available cards to list If current is >= 0 it will be considered available even if no device...
virtual void addChild(Configurable *child)
CaptureCard & parent
Definition: videosource.h:587
void LoadedTuner(const QString &)
virtual void setHelpText(const QString &str)
Definition: settings.h:61
virtual void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:843
void NewValue(const QString &)
void SetTuner(const QString &)
const char * name
Definition: frequencies.h:102
static bool IsEncoder(const QString &rawtype)
Definition: cardutil.h:116
DVBConfigurationGroup(CaptureCard &a_parent)
virtual void setLabel(QString)
Definition: settings.cpp:1194
ExternalConfigurationGroup(CaptureCard &parent)
QString deviceid
Definition: videosource.h:375
static uint CreateDeviceInputGroup(const QString &host, const QString &device)
Definition: cardutil.h:327
void fillSelections(const QString &current)
Adds all available cards to list If current is >= 0 it will be considered available even if no device...
virtual void Load(void)
static void fillSelections(SelectSetting *setting)
QString GetConfDir(void)
Definition: mythdirs.cpp:140
void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:1018
const CaptureCard & m_parent
Definition: videosource.h:294
void loadByID(int id)
int getInputID(void) const
QString getSourceName(void) const
void probeCard(const QString &device)
FirewireConfigurationGroup(CaptureCard &a_parent)
void removeTarget(QString triggerValue)
void sourceFetch()
InstanceCount * instances
Definition: videosource.h:557
CaptureCard(bool use_card_group=true)
static vector< uint > GetChildCardIDs(uint cardid)
Definition: cardutil.cpp:701
static bool showGetTextPopup(MythMainWindow *parent, QString title, QString message, QString &text)
virtual void Load(void)
Definition: mythstorage.cpp:7
QString cardtuner
Definition: videosource.h:378
void SetTuner(const QString &)
DataDirectLineupSelector * lineupselector
Definition: videosource.h:157
static vector< AVCInfo > GetSTBList(void)
DataDirect_config(const VideoSource &_parent, int _ddsource)
const FirewireGUID * guid
Definition: videosource.h:614
SourceID(const CardInput &parent)
virtual uint size(void) const
Definition: settings.h:282
struct CHANLISTS chanlists[]
void loadByInput(int cardid, QString input)
virtual void setEnabled(bool b)
Definition: settings.cpp:1187
static QString TestMimeType(const QString &sFileName)
void fillSelections()
DialogCode
Definition: mythdialogs.h:21
virtual void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:115
void probeCard(const QString &device)
int errno
TunerCardAudioInput * audioinput
Definition: videosource.h:486
FileDevice(const CaptureCard &parent)
void LoadedIP(const QString &)
InputName(const CardInput &parent)
static uint GetDeviceInputGroup(uint cardid)
Definition: cardutil.cpp:1384
int getCardID(void) const
Definition: videosource.h:648
virtual void Load(void)
QMap< uint, uint > minor_list
AudioDevice(const CaptureCard &parent)
virtual QString GetSetClause(MSqlBindings &bindings) const
run process through shell
Definition: mythsystem.h:41
bool isEnabled()
Definition: settings.h:69
virtual void setEnabled(bool e)
QString GetSetting(const QString &key, const QString &defaultval="")
CaptureCard & parent
Definition: videosource.h:467
QByteArray & ReadAll()
static QString GetDeviceName(dvb_dev_type_t, const QString &device)
Definition: cardutil.cpp:2208
static QString GetAudioDevice(uint cardid)
Definition: cardutil.h:262
static bool DeleteOrphanInputs(void)
Definition: cardutil.cpp:1337
TransFreqTableSelector(uint _sourceid)
XMLTVGrabber * grabber
Definition: videosource.h:221
void UpdateDevices(const QString &)
TransButtonSetting * diseqc_btn
Definition: videosource.h:599
static void fillSelections(SelectSetting *setting)
uint GetInstanceCount(void) const
Definition: videosource.h:660
DishNetEIT(const CardInput &parent)
virtual void Save(void)
virtual void Load(void)
CetonSetting * tuner
Definition: videosource.h:431
DataDirectButton * button
Definition: videosource.h:156
void SetGUID(const QString &)
TransLabelSetting * cardinfo
Definition: videosource.h:485
ASIConfigurationGroup(CaptureCard &parent)
CaptureCard & parent
Definition: videosource.h:484
virtual void Save(void)
TransLabelSetting * _desc
Definition: videosource.h:914
Name * name
Definition: videosource.h:274
void SetGUID(const QString &)
QString mythdeviceid
Definition: videosource.h:374
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1448
virtual void Load(void)
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:542
static QString GetModelName(uint vendorid, uint modelid)
void LoadValue(const QString &)
CardInput(const QString &cardtype, bool is_new_input, int cardid)
uint vendorid
Definition: avcinfo.h:43
XMLTVConfig(const VideoSource &aparent)
QString GetColumnName(void) const
Definition: mythstorage.h:43
virtual void Load(void)
SignalTimeout * signal_timeout
Definition: videosource.h:592
const char * name
Definition: ParseText.cpp:338
virtual void Save(void)
TransLabelSetting * info
Definition: videosource.h:523
virtual QString GetWhereClause(MSqlBindings &bindings) const
InstanceCount * count
FirewireConnection(const CaptureCard &parent)
CetonConfigurationGroup(CaptureCard &parent)
virtual void setHelpText(const QString &str)
Definition: settings.cpp:947
bool isActive(void) const
Definition: mythdbcon.h:188
virtual DialogCode exec(void)
DVBCardName * cardname
Definition: videosource.h:590
void addSelection(const QString &label, QString value=QString::null, bool select=false)
Definition: settings.cpp:733
int intValue(void) const
Definition: settings.h:179
IPTVConfigurationGroup(CaptureCard &a_parent)
const CardInput & cardinput
static int GetASIDeviceNumber(const QString &device, QString *error=NULL)
Definition: cardutil.cpp:2350
ListBoxSetting * listbox
Definition: videosource.h:735
CetonSetting(const char *label, const char *helptext)
A ConfigurationDialog that uses a ConfigurationGroup with one child per page.
Base dialog for most dialogs in MythTV using the old UI.
Definition: mythdialogs.h:50
virtual void Load(void)
void fillDataDirectLineupSelector(void)
MPEGConfigurationGroup(CaptureCard &parent)
DVBOnDemand(const CaptureCard &parent)
InputPriority(const CardInput &parent)
MythMainWindow * GetMythMainWindow(void)
virtual void Save(void)
Definition: mythstorage.cpp:83
const VideoSource & m_parent
Definition: videosource.h:66
uint Wait(time_t timeout=0)
virtual void setEnabled(bool b)
Definition: settings.cpp:342
void SetIP(const QString &)
virtual void triggerChanged(const QString &value)
QString GetListingsProviderName(void) const
Definition: datadirect.h:351
static bool showOkPopup(MythMainWindow *parent, const QString &title, const QString &message, QString button_msg=QString())
XMLTV_generic_config(const VideoSource &_parent, QString _grabber)
vector< ChannelInfo > ChannelInfoList
Definition: channelinfo.h:121
void SetIP(const QString &)
static const uint kDefaultMultirecCount
Definition: videosource.cpp:59
static QStringList ProbeAudioInputs(QString device, QString cardtype=QString::null)
Definition: cardutil.cpp:1833
void LoadXMLTVGrabbers(QStringList name_list, QStringList prog_list)
ImportConfigurationGroup(CaptureCard &parent)
virtual void Save(void)
virtual void Save(QString)
virtual void Load(void)
DataDirectUserID * userid
Definition: videosource.h:154
InputGroup * inputgrp1
Definition: videosource.h:845
VERBOSE_PREAMBLE Most Errors or other very important messages true
Definition: verbosedefs.h:91
DiSEqCDevTree * diseqc_tree
Definition: videosource.h:598
virtual void clearSelections(void)
Definition: settings.cpp:1011
virtual void Save(void)
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:810
static QString GetVideoDevice(uint cardid)
Definition: cardutil.h:260
uint instance_count
Definition: videosource.h:688
static void fillSelections(SelectSetting *setting)
DataDirectPassword(const VideoSource &parent)
SkipBtAudio(const CaptureCard &parent)
VideoDevice * device
Definition: videosource.h:468
CaptureCard & parent
Definition: videosource.h:538
const VideoSource & parent
Definition: videosource.h:220
HDHomeRunDeviceID(const CaptureCard &parent)
virtual void triggerChanged(const QString &value)
UseEIT(const VideoSource &parent)
virtual QString GetValue(uint i) const
Definition: settings.h:286
CaptureCardGroup(CaptureCard &parent)
void probeCard(const QString &cardNumber)
vector< DataDirectLineup > DDLineupList
Definition: datadirect.h:299
typedef void(APIENTRY *MYTH_GLTEXIMAGE1DPROC)(GLenum target
static bool Exists(int id)
Check if a Diseqc device tree exists.
Definition: diseqc.cpp:374
HDHomeRunExtra(HDHomeRunConfigurationGroup &parent)
QMap< QString, AVCInfo > guid_to_avcinfo
void fillSelections(const QString &device)
virtual DialogCode exec(bool saveOnExec=false, bool doLoad=false)
virtual void setHelpText(const QString &str)
Definition: settings.cpp:793
DVBNetID(const VideoSource &parent, signed int value, signed int min_val)
void probeCard(const QString &device)
static bool DeleteAllSources(void)
Definition: sourceutil.cpp:531
HDPVRConfigurationGroup(CaptureCard &parent)
StartingChannel * startchan
Definition: videosource.h:840
void channelScanner()
virtual void setLabel(QString str)
Definition: settings.h:57
virtual DialogCode exec(bool saveOnExec=true, bool doLoad=true)
ListBoxSetting * listbox
Definition: videosource.h:764
static QString GetDeviceLabel(const QString &cardtype, const QString &videodevice)
Definition: cardutil.cpp:1929
void SetOverrideDeviceID(const QString &)
void SetInstanceCount(uint cnt)
Definition: videosource.h:663
DVBCardNum * cardnum
Definition: videosource.h:589
DVBNoSeqStart(const CaptureCard &parent)
void loadByID(int id)
void UpdateDevices(const QString &)
void InvalidateTrees(void)
Invalidate cached trees.
Definition: diseqc.cpp:256
ChannelTimeout(const CaptureCard &parent, uint value, uint min_val)
XMLTVGrabber(const VideoSource &parent)
void setUseLabel(bool useit)
DVBCardType * cardtype
Definition: videosource.h:591
void probeCard(const QString &device)
DemoConfigurationGroup(CaptureCard &parent)
virtual void Load(void)
VBIDevice(const CaptureCard &parent)
virtual QString GetSetClause(MSqlBindings &bindings) const
virtual QString getValue(void) const
Definition: settings.cpp:91
void reload(void)
virtual QString GetSetClause(MSqlBindings &bindings) const
static void GetCardInputs(uint cardid, const QString &device, const QString &cardtype, QStringList &inputs)
Definition: cardutil.cpp:1952
HDHomeRunTunerIndex * _cardtuner
Definition: videosource.h:916
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:171
virtual void setVisible(bool b)
Definition: settings.cpp:918
void setTrigger(Configurable *_trigger)
void fillSelections(const QString &current)
Adds all available device-tuner combinations to list If current is >= 0 it will be considered availab...
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
bool GrabLineupsOnly(void)
static bool GetV4LInfo(int videofd, QString &card, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:1657
QMap< QString, QVariant > MSqlBindings
typedef for a map of string -> string bindings for generic queries.
Definition: mythdbcon.h:98
ExternalChannelCommand(const CardInput &parent)
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:610
virtual void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
Definition: settings.cpp:158
virtual QString GetWhereClause(MSqlBindings &bindings) const
virtual void setSaveAll(bool b)
static bool GetListingsLoginData(uint sourceid, QString &grabber, QString &userid, QString &passwd, QString &lineupid)
Definition: sourceutil.cpp:144
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1408
FirewireGUID(const CaptureCard &parent)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:181
QString getSourceName(void) const
Definition: videosource.h:237
virtual void Load(void)
FirewireSpeed(const CaptureCard &parent)
uint fillSelectionsFromDir(const QDir &dir, uint minor_min, uint minor_max, QString card, QString driver, bool allow_duplicates)
DVBTuningDelay * tuning_delay
Definition: videosource.h:597
virtual QString GetWhereClause(MSqlBindings &bindings) const
void fillSelectionsFromDir(const QDir &dir, bool absPath=true)
ArgumentString(const CaptureCard &parent)
virtual void setHelpText(const QString &)
Definition: settings.cpp:1201
virtual void Save()
static bool DeleteAllCards(void)
Definition: cardutil.cpp:2155
virtual void SetPasswordEcho(bool b)
Definition: settings.cpp:362
void NewIP(const QString &)
static bool IsCableCardPresent(uint cardid, const QString &cardType)
Definition: cardutil.cpp:103
AVCInfo GetAVCInfo(const QString &guid) const
QString GetHostName(void)
DVBCardNum(const CaptureCard &parent)
const CardInput & m_parent
Definition: videosource.h:709
const VideoSource & parent
Definition: videosource.h:153
DVB-S device tree class.
Definition: diseqc.h:75
uint fillSelectionsFromDir(const QDir &dir, const QString &card, const QString &driver)
InstanceCount(const CaptureCard &parent)
InputName * inputname
Definition: videosource.h:838
void setFilter(const QString &card, const QString &driver)
TransLabelSetting * info
Definition: videosource.h:556
const VideoSource & parent
Definition: videosource.h:177
UseEIT * useeit
Definition: videosource.h:191
static bool IsV4L(const QString &rawtype)
Definition: cardutil.h:125
void SetSourceID(const QString &sourceid)
HDHomeRunConfigurationGroup(CaptureCard &parent)
static enum CARD_TYPES toCardType(const QString &name)
Definition: cardutil.h:73
PresetTuner(const CardInput &parent)
static QString GetHDHRdesc(const QString &device)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2265
CaptureCard & parent
Definition: videosource.h:503
static bool is_grabber_external(const QString &grabber)
Definition: videosource.h:25
virtual void Save(void)
void fillSelections(const QString &uid, const QString &pwd, int source)
static QString GetStartingChannel(uint inputid)
Definition: cardutil.cpp:1116
virtual void setValue(int newValue)
Definition: settings.cpp:521
Main DVB-S device interface.
Definition: diseqc.h:52
MYTH_GLsizeiptr size
virtual MythDialog * dialogWidget(MythMainWindow *parent, const char *widgetName)
FreqTableSelector(const VideoSource &parent)
void addChild(Configurable *child)
InstanceCount * count
void addTarget(QString triggerValue, Configurable *target)
virtual void Load(void)
void loadByID(int id)