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