MythTV  master
cardutil.cpp
Go to the documentation of this file.
1 // Standard UNIX C headers
2 #include <fcntl.h>
3 #include <unistd.h>
4 
5 #include <algorithm>
6 
7 #if defined(USING_V4L2) || defined(USING_DVB)
8 #include <sys/ioctl.h>
9 #endif
10 
11 // Qt headers
12 #include <QMap>
13 #include <QDir>
14 
15 // MythTV headers
16 #include "mythconfig.h"
17 #include "cardutil.h"
18 #include "videosource.h"
19 #include "dvbchannel.h"
20 #include "diseqcsettings.h"
21 #include "sourceutil.h"
22 #include "mythdb.h"
23 #include "mythlogging.h"
24 #include "inputinfo.h"
25 #include "mythmiscutil.h" // for ping()
26 #include "mythdownloadmanager.h"
27 
28 #ifdef USING_DVB
29 #include "dvbtypes.h"
30 #endif
31 
32 #ifdef USING_V4L1
33 #include <linux/videodev.h>
34 #endif
35 
36 #ifdef USING_V4L2
37 #include "v4l2util.h"
38 #endif
39 
40 #ifdef USING_HDHOMERUN
41 #include HDHOMERUN_HEADERFILE
42 #endif
43 
44 #ifdef USING_VBOX
45 #include "vboxutils.h"
46 #include "mythmiscutil.h"
47 #endif
48 
49 #ifdef USING_SATIP
50 #include "satiputils.h"
51 #endif
52 
53 #ifdef USING_ASI
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <dveo/asi.h>
57 #include <dveo/master.h>
58 #endif
59 
60 #define LOC QString("CardUtil: ")
61 
63 {
64  QStringList inputTypes {};
65 
66 #ifdef USING_DVB
67  inputTypes += "'DVB'";
68 #endif // USING_DVB
69 
70 #ifdef USING_V4L2
71  inputTypes += "'V4L'";
72 # ifdef USING_IVTV
73  inputTypes += "'MPEG'";
74 # endif // USING_IVTV
75 #endif // USING_V4L2
76 
77 #ifdef USING_IPTV
78  inputTypes += "'FREEBOX'";
79 #endif // USING_IPTV
80 
81 #ifdef USING_VBOX
82  inputTypes += "'VBOX'";
83 #endif // USING_VBOX
84 
85 #ifdef USING_HDHOMERUN
86  inputTypes += "'HDHOMERUN'";
87 #endif // USING_HDHOMERUN
88 
89 #ifdef USING_SATIP
90  inputTypes += "'SATIP'";
91 #endif // USING_SATIP
92 
93 #ifdef USING_ASI
94  inputTypes += "'ASI'";
95 #endif
96 
97 #ifdef USING_CETON
98  inputTypes += "'CETON'";
99 #endif // USING_CETON
100 
101 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
102  inputTypes += "'EXTERNAL'";
103 #endif
104 
105  if (inputTypes.isEmpty())
106  return "('DUMMY')";
107 
108  return QString("(%1)").arg(inputTypes.join(','));
109 }
110 
112  const QString &inputType)
113 {
114 #if (!USING_HDHOMERUN && !USING_CETON)
115  Q_UNUSED(inputid);
116 #endif
117 
118  if (inputType == "HDHOMERUN")
119  {
120 #ifdef USING_HDHOMERUN
121  hdhomerun_tuner_status_t status {};
122  QString device = GetVideoDevice(inputid);
123  hdhomerun_device_t *hdhr =
124  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
125  if (!hdhr)
126  return false;
127 
128  int oob = hdhomerun_device_get_oob_status(hdhr, nullptr, &status);
129 
130  // if no OOB tuner, oob will be < 1. If no CC present, OOB
131  // status will be "none."
132  if (oob > 0 && (strncmp(status.channel, "none", 4) != 0))
133  {
134  LOG(VB_GENERAL, LOG_INFO, "Cardutil: HDHomeRun Cablecard Present.");
135  hdhomerun_device_destroy(hdhr);
136  return true;
137  }
138 
139  hdhomerun_device_destroy(hdhr);
140 
141 #endif
142  return false;
143  }
144  if (inputType == "CETON")
145  {
146 #ifdef USING_CETON
147  QString device = GetVideoDevice(inputid);
148 
149  QStringList parts = device.split("-");
150  if (parts.size() != 2)
151  {
152  LOG(VB_GENERAL, LOG_ERR,
153  QString("CardUtil: Ceton invalid device id %1").arg(device));
154  return false;
155  }
156 
157  const QString& ip_address = parts.at(0);
158 
159  QStringList tuner_parts = parts.at(1).split(".");
160  if (tuner_parts.size() != 2)
161  {
162  LOG(VB_GENERAL, LOG_ERR, LOC +
163  QString("CardUtil: Ceton invalid device id %1").arg(device));
164  return false;
165  }
166 
167  uint tuner = tuner_parts.at(1).toUInt();
168 
169  QUrlQuery params;
170  params.addQueryItem("i", QString::number(tuner));
171  params.addQueryItem("s", "cas");
172  params.addQueryItem("v", "CardStatus");
173 
174  QUrl url;
175  url.setScheme("http");
176  url.setHost(ip_address);
177  url.setPath("/get_var.json");
178  url.setQuery(params);
179 
180  auto *request = new QNetworkRequest();
181  request->setAttribute(QNetworkRequest::CacheLoadControlAttribute,
182  QNetworkRequest::AlwaysNetwork);
183  request->setUrl(url);
184 
185  QByteArray data;
187 
188  if (!manager->download(request, &data))
189  {
190  LOG(VB_GENERAL, LOG_ERR,
191  QString("CardUtil: Ceton http request failed %1").arg(device));
192  return false;
193  }
194 
195  QString response = QString(data);
196 
197  QRegExp regex("^\\{ \"?result\"?: \"(.*)\" \\}$");
198  if (regex.indexIn(response) == -1)
199  {
200  LOG(VB_GENERAL, LOG_ERR,
201  QString("CardUtil: Ceton unexpected http response: %1").arg(response));
202  return false;
203  }
204 
205  QString result = regex.cap(1);
206 
207  if (result == "Inserted")
208  {
209  LOG(VB_GENERAL, LOG_DEBUG, "Cardutil: Ceton CableCARD present.");
210  return true;
211  }
212 
213  LOG(VB_GENERAL, LOG_DEBUG, "Cardutil: Ceton CableCARD not present.");
214  return false;
215 #else
216  return false;
217 #endif
218  }
219  return false;
220 }
221 
222 bool CardUtil::HasTuner(const QString &rawtype, const QString & device)
223 {
224  if (rawtype == "DVB" || rawtype == "HDHOMERUN" ||
225  rawtype == "FREEBOX" || rawtype == "CETON" ||
226  rawtype == "VBOX" || rawtype == "SATIP")
227  return true;
228 
229 #ifdef USING_V4L2
230  if (rawtype == "V4L2ENC")
231  {
232  V4L2util v4l2(device);
233  return !v4l2 ? false : v4l2.HasTuner();
234  }
235 #else
236  Q_UNUSED(device);
237 #endif
238 
239  if (rawtype == "EXTERNAL")
240  {
241  // TODO: query EXTERNAL for capability
242  return true;
243  }
244 
245  return false;
246 }
247 
248 bool CardUtil::IsTunerShared(uint inputidA, uint inputidB)
249 {
250  LOG(VB_GENERAL, LOG_DEBUG, QString("IsTunerShared(%1,%2)")
251  .arg(inputidA).arg(inputidB));
252 
254  query.prepare("SELECT videodevice, hostname, cardtype "
255  "FROM capturecard "
256  "WHERE ( (cardid = :INPUTID_A) OR "
257  " (cardid = :INPUTID_B) )");
258  query.bindValue(":INPUTID_A", inputidA);
259  query.bindValue(":INPUTID_B", inputidB);
260 
261  if (!query.exec())
262  {
263  MythDB::DBError("CardUtil::is_tuner_shared()", query);
264  return false;
265  }
266 
267  if (!query.next())
268  return false;
269 
270  const QString vdevice = query.value(0).toString();
271  const QString hostname = query.value(1).toString();
272  const QString inputtype = query.value(2).toString();
273 
274  if (!IsTunerSharingCapable(inputtype.toUpper()))
275  return false;
276 
277  if (!query.next())
278  return false;
279 
280  bool ret = ((vdevice == query.value(0).toString()) &&
281  (hostname == query.value(1).toString()) &&
282  (inputtype == query.value(2).toString()));
283 
284  LOG(VB_RECORD, LOG_DEBUG, QString("IsTunerShared(%1,%2) -> %3")
285  .arg(inputidA).arg(inputidB).arg(ret));
286 
287  return ret;
288 }
289 
295 bool CardUtil::IsInputTypePresent(const QString &rawtype, QString hostname)
296 {
297  if (hostname.isEmpty())
299 
301  QString qstr =
302  "SELECT count(cardtype) "
303  "FROM capturecard "
304  "WHERE capturecard.hostname = :HOSTNAME ";
305 
306  if (!rawtype.isEmpty())
307  qstr += " AND capturecard.cardtype = :INPUTTYPE";
308 
309  query.prepare(qstr);
310 
311  if (!rawtype.isEmpty())
312  query.bindValue(":INPUTTYPE", rawtype.toUpper());
313 
314  query.bindValue(":HOSTNAME", hostname);
315 
316  if (!query.exec())
317  {
318  MythDB::DBError("CardUtil::IsInputTypePresent()", query);
319  return false;
320  }
321 
322  uint count = 0;
323  if (query.next())
324  count = query.value(0).toUInt();
325 
326  return count > 0;
327 }
328 
330 {
331  InputTypes inputtypes;
332 
334  query.prepare("SELECT DISTINCT cardtype, videodevice "
335  "FROM capturecard");
336 
337  if (!query.exec())
338  {
339  MythDB::DBError("CardUtil::GetInputTypes()", query);
340  }
341  else
342  {
343  QString cardtype;
344 
345  while (query.next())
346  {
347  cardtype = query.value(0).toString();
348  if (cardtype != "V4L2ENC")
349  {
350  inputtypes[cardtype] = "";
351  }
352 #ifdef USING_V4L2
353  else
354  {
355  V4L2util v4l2(query.value(1).toString());
356  if (v4l2.IsOpen())
357  {
358  QString driver_name = "V4L2:" + v4l2.DriverName();
359  inputtypes[driver_name] = v4l2.CardName();
360  }
361  }
362 #endif
363  }
364  }
365 
366  return inputtypes;
367 }
368 
376 QStringList CardUtil::GetInputTypeNames(uint sourceid)
377 {
379  query.prepare("SELECT cardtype "
380  "FROM capturecard "
381  "WHERE capturecard.sourceid = :SOURCEID "
382  "GROUP BY cardtype");
383  query.bindValue(":SOURCEID", sourceid);
384 
385  QStringList list;
386  if (!query.exec())
387  {
388  MythDB::DBError("CardUtil::GetInputTypes", query);
389  return list;
390  }
391  while (query.next())
392  list.push_back(query.value(0).toString());
393  return list;
394 }
395 
396 
397 
398 
404 QStringList CardUtil::GetVideoDevices(const QString &rawtype, QString hostname)
405 {
406  QStringList list;
407 
408  if (hostname.isEmpty())
410 
412  QString qstr =
413  "SELECT videodevice "
414  "FROM capturecard "
415  "WHERE hostname = :HOSTNAME";
416 
417  if (!rawtype.isEmpty())
418  qstr += " AND cardtype = :INPUTTYPE";
419 
420  query.prepare(qstr);
421 
422  if (!rawtype.isEmpty())
423  query.bindValue(":INPUTTYPE", rawtype.toUpper());
424 
425  query.bindValue(":HOSTNAME", hostname);
426 
427  if (!query.exec())
428  {
429  MythDB::DBError("CardUtil::GetVideoDevices", query);
430  return list;
431  }
432 
433  QMap<QString,bool> dup;
434  while (query.next())
435  {
436  QString videodevice = query.value(0).toString();
437  if (dup[videodevice])
438  continue;
439 
440  list.push_back(videodevice);
441  dup[videodevice] = true;
442  }
443 
444  return list;
445 }
446 
447 QMap <QString,QStringList> CardUtil::s_videoDeviceCache;
448 
450 {
451  s_videoDeviceCache.clear();
452 }
453 
454 
455 QStringList CardUtil::ProbeVideoDevices(const QString &rawtype)
456 {
457  if (s_videoDeviceCache.contains(rawtype))
458  return s_videoDeviceCache[rawtype];
459 
460  QStringList devs;
461 
462  if (rawtype.toUpper() == "DVB")
463  {
464  QDir dir("/dev/dvb", "adapter*", QDir::Name, QDir::Dirs);
465  QFileInfoList entries = dir.entryInfoList();
466  for (const auto & it : qAsConst(entries))
467  {
468  QDir subdir(it.filePath(), "frontend*", QDir::Name, QDir::Files | QDir::System);
469  const QFileInfoList subil = subdir.entryInfoList();
470  if (subil.isEmpty())
471  continue;
472 
473  for (const auto & subit : qAsConst(subil))
474  devs.push_back(subit.filePath());
475  }
476  }
477  else if (rawtype.toUpper() == "ASI")
478  {
479  QDir dir("/dev/", "asirx*", QDir::Name, QDir::System);
480  QFileInfoList entries = dir.entryInfoList();
481  for (const auto & it : qAsConst(entries))
482  {
483  if (GetASIDeviceNumber(it.filePath()) >= 0)
484  {
485  devs.push_back(it.filePath());
486  continue;
487  }
488  break;
489  }
490  }
491 #ifdef USING_HDHOMERUN
492  else if (rawtype.toUpper() == "HDHOMERUN")
493  {
494  uint32_t target_ip = 0;
495  uint32_t device_type = HDHOMERUN_DEVICE_TYPE_TUNER;
496  uint32_t device_id = HDHOMERUN_DEVICE_ID_WILDCARD;
497  const int max_count = 50;
498  std::array<hdhomerun_discover_device_t,max_count> result_list {};
499 
500 #ifdef HDHOMERUN_V2
501  int result = hdhomerun_discover_find_devices_custom_v2(
502  target_ip, device_type, device_id, result_list.data(), result_list.size());
503 #else
504  int result = hdhomerun_discover_find_devices_custom(
505  target_ip, device_type, device_id, result_list.data(), result_list.size());
506 #endif
507 
508  if (result == -1)
509  {
510  LOG(VB_GENERAL, LOG_ERR, "Error finding HDHomerun devices");
511  }
512 
513  if (result >= max_count)
514  {
515  LOG(VB_GENERAL, LOG_WARNING,
516  "Warning: may be > 50 HDHomerun devices");
517  }
518 
519  // Return "deviceid ipaddress" pairs
520  for (int i = 0; i < result; i++)
521  {
522  QString id = QString("%1").arg(result_list[i].device_id, 0, 16);
523  QString ip = QString("%1.%2.%3.%4")
524  .arg((result_list[i].ip_addr>>24) & 0xFF)
525  .arg((result_list[i].ip_addr>>16) & 0xFF)
526  .arg((result_list[i].ip_addr>> 8) & 0xFF)
527  .arg((result_list[i].ip_addr>> 0) & 0xFF);
528 
529  QString model = "";
530  hdhomerun_device_t *device = hdhomerun_device_create(
531  result_list[i].device_id, 0, 0, nullptr);
532  if (device)
533  {
534  model = hdhomerun_device_get_model_str(device);
535  hdhomerun_device_destroy(device);
536  }
537 
538  QString hdhrdev = id.toUpper() + " " + ip + " " + model;
539  devs.push_back(hdhrdev);
540  }
541  }
542 #endif // USING_HDHOMERUN
543 #ifdef USING_SATIP
544  else if (rawtype.toUpper() == "SATIP")
545  {
546  devs = SatIP::probeDevices();
547  }
548 #endif // USING_SATIP
549 #ifdef USING_VBOX
550  else if (rawtype.toUpper() == "VBOX")
551  {
552  devs = VBox::probeDevices();
553  }
554 #endif // USING_VBOX
555 #ifdef USING_CETON
556  else if (rawtype.toUpper() == "CETON")
557  {
558  // TODO implement CETON probing.
559  LOG(VB_GENERAL, LOG_INFO, "CardUtil::ProbeVideoDevices: "
560  "TODO Probe Ceton devices");
561  }
562 #endif // USING_CETON
563  else
564  {
565  LOG(VB_GENERAL, LOG_ERR, QString("Raw Type: '%1' is not supported")
566  .arg(rawtype));
567  }
568 
569  s_videoDeviceCache.insert(rawtype,devs);
570  return devs;
571 }
572 
573 // Get the list of delivery systems from the card
574 QStringList CardUtil::ProbeDeliverySystems(const QString &device)
575 {
576  QStringList delsyslist;
577 
578 #ifdef USING_DVB
579  int fd_frontend = OpenVideoDevice(device);
580  if (fd_frontend < 0)
581  {
582  return delsyslist;
583  }
584 
585  struct dtv_property prop = {};
586  struct dtv_properties cmd = {};
587 
588  prop.cmd = DTV_API_VERSION;
589  cmd.num = 1;
590  cmd.props = &prop;
591  if (ioctl(fd_frontend, FE_GET_PROPERTY, &cmd) == 0)
592  {
593  LOG(VB_GENERAL, LOG_INFO,
594  QString("CardUtil(%1): ").arg(device) +
595  QString("dvb api version %1.%2").arg((prop.u.data>>8)&0xff).arg((prop.u.data)&0xff));
596  }
597  else
598  {
599  LOG(VB_GENERAL, LOG_ERR,
600  QString("CardUtil(%1) FE_GET_PROPERTY ioctl failed").arg(device) + ENO);
601  close(fd_frontend);
602  return delsyslist;
603  }
604 
605  delsyslist = ProbeDeliverySystems(fd_frontend);
606 
607  QString msg = "Delivery systems:";
608  for (const auto & item : qAsConst(delsyslist))
609  {
610  msg += " ";
611  msg += item;
612  }
613  LOG(VB_GENERAL, LOG_INFO, QString("CardUtil(%1): ").arg(device) + msg);
614 
615  close(fd_frontend);
616 #else
617  Q_UNUSED(device);
618 #endif // USING_DVB
619 
620  return delsyslist;
621 }
622 
623 // Get the list of all supported delivery systems from the card
624 QStringList CardUtil::ProbeDeliverySystems(int fd_frontend)
625 {
626  QStringList delsyslist;
627 
628 #ifdef USING_DVB
629  struct dtv_property prop = {};
630  struct dtv_properties cmd = {};
631 
632  prop.cmd = DTV_ENUM_DELSYS;
633  cmd.num = 1;
634  cmd.props = &prop;
635  if (ioctl(fd_frontend, FE_GET_PROPERTY, &cmd) == 0)
636  {
637  for (unsigned int i = 0; i < prop.u.buffer.len; i++)
638  {
639  delsyslist.push_back(DTVModulationSystem::toString(prop.u.buffer.data[i]));
640  }
641  }
642  else
643  {
644  LOG(VB_GENERAL, LOG_ERR, LOC + "FE_GET_PROPERTY ioctl failed " + ENO);
645  }
646 #else
647  Q_UNUSED(fd_frontend);
648 #endif // USING_DVB
649 
650  return delsyslist;
651 }
652 
653 QString CardUtil::ProbeDefaultDeliverySystem(const QString &device)
654 {
655  DTVModulationSystem delsys;
656 
657 #ifdef USING_DVB
658  int fd = OpenVideoDevice(device);
659  if (fd >= 0)
660  {
661  delsys = ProbeBestDeliverySystem(fd);
662  close(fd);
663  }
664 #else
665  Q_UNUSED(device);
666 #endif // USING_DVB
667 
668  return delsys.toString();
669 }
670 
671 QString CardUtil::ProbeDVBType(const QString &device)
672 {
673  QString ret = "ERROR_UNKNOWN";
674 
675  if (device.isEmpty())
676  return ret;
677 
678 #ifdef USING_DVB
679  DTVTunerType type = ProbeTunerType(device);
680  ret = (type.toString() != "UNKNOWN") ? type.toString().toUpper() : ret;
681 
682  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("(%1) tuner type:%2 %3")
683  .arg(device).arg(type).arg(ret));
684 #endif // USING_DVB
685 
686  return ret;
687 }
688 
692 QString CardUtil::ProbeDVBFrontendName(const QString &device)
693 {
694  QString ret = "ERROR_UNKNOWN";
695 
696 #ifdef USING_DVB
697  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_FRONTEND, device);
698  QByteArray dev = dvbdev.toLatin1();
699  int fd_frontend = open(dev.constData(), O_RDWR | O_NONBLOCK);
700  if (fd_frontend < 0)
701  return "ERROR_OPEN";
702 
703  struct dvb_frontend_info info {};
704  int err = ioctl(fd_frontend, FE_GET_INFO, &info);
705  if (err < 0)
706  {
707  close(fd_frontend);
708  return "ERROR_PROBE";
709  }
710 
711  ret = info.name;
712 
713  close(fd_frontend);
714 #else
715  Q_UNUSED(device);
716 #endif // USING_DVB
717 
718  return ret;
719 }
720 
738 bool CardUtil::HasDVBCRCBug(const QString &device)
739 {
740  QString name = ProbeDVBFrontendName(device);
741  return ((name == "VLSI VES1x93 DVB-S") || // munges PMT
742  (name == "ST STV0299 DVB-S")); // munges PAT
743 }
744 
746 {
747  QString name = ProbeDVBFrontendName(device);
748  if (name.indexOf("DVB-S") >= 0)
749  return 300;
750  if (name == "DiBcom 3000P/M-C DVB-T")
751  return 100;
752  return 25;
753 }
754 
756 {
757  DTVTunerType tunertype;
758 
759  switch (delsys)
760  {
762  tunertype = DTVTunerType::kTunerTypeDVBS1;
763  break;
765  tunertype = DTVTunerType::kTunerTypeDVBS2;
766  break;
769  tunertype = DTVTunerType::kTunerTypeDVBC;
770  break;
772  tunertype = DTVTunerType::kTunerTypeDVBT;
773  break;
775  tunertype = DTVTunerType::kTunerTypeDVBT2;
776  break;
778  tunertype = DTVTunerType::kTunerTypeDVBT;
779  break;
782  tunertype = DTVTunerType::kTunerTypeATSC;
783  break;
786  break;
787  default:
788  LOG(VB_GENERAL, LOG_ERR, LOC +
789  QString("TODO Add to switch case delivery system:%2 %3")
790  .arg(delsys).arg(delsys.toString()));
791  break;
792  }
793 
794  return tunertype;
795 }
796 
797 // Get the currently configured tuner type from the database
799 {
800  DTVModulationSystem delsys = GetDeliverySystem(inputid);
801  DTVTunerType tunertype = ConvertToTunerType(delsys);
802  return tunertype;
803 }
804 
805 // Get the currently configured tuner type from the device
807 {
808  DTVModulationSystem delsys = ProbeCurrentDeliverySystem(fd_frontend);
809  DTVTunerType tunertype = ConvertToTunerType(delsys);
810  return tunertype;
811 }
812 
813 // Get the currently configured tuner type from the device
815 {
817  DTVTunerType tunertype = ConvertToTunerType(delsys);
818  return tunertype;
819 }
820 
821 // Get the tuner type from the multiplex
823 {
824  DTVTunerType tuner_type;
825 
827  query.prepare(
828  "SELECT mod_sys "
829  "FROM dtv_multiplex "
830  "WHERE dtv_multiplex.mplexid = :MPLEXID");
831  query.bindValue(":MPLEXID", mplexid);
832 
833  if (!query.exec())
834  {
835  MythDB::DBError("CardUtil::GetTunerTypeFromMultiplex", query);
836  return tuner_type;
837  }
838 
839  if (!query.next())
840  {
841  LOG(VB_GENERAL, LOG_ERR, LOC +
842  QString("Could not find mod_sys in dtv_multiplex for mplexid %1")
843  .arg(mplexid));
844 
845  return tuner_type;
846  }
847 
848  DTVModulationSystem mod_sys;
849  mod_sys.Parse(query.value(0).toString());
850  tuner_type = CardUtil::ConvertToTunerType(mod_sys);
851 
852  return tuner_type;
853 }
854 
855 // Get the currently configured delivery system from the database
857 {
858  QString ds = GetDeliverySystemFromDB(inputid);
859  DTVModulationSystem delsys;
860  delsys.Parse(ds);
861  return delsys;
862 }
863 
864 // Get the currently configured delivery system from the device
866 {
867  DTVModulationSystem delsys;
868 
869  if (device.isEmpty())
870  {
871  return delsys;
872  }
873 
874 #ifdef USING_DVB
875  int fd_frontend = OpenVideoDevice(device);
876  if (fd_frontend < 0)
877  {
878  LOG(VB_GENERAL, LOG_ERR, LOC +
879  QString("open failed (%1)")
880  .arg(device) + ENO);
881  return delsys;
882  }
883 
884  delsys = ProbeCurrentDeliverySystem(fd_frontend);
885 
886  LOG(VB_GENERAL, LOG_DEBUG, QString("CardUtil(%1): delsys:%2 %3")
887  .arg(device).arg(delsys).arg(delsys.toString()));
888 
889  close(fd_frontend);
890 #else
891  Q_UNUSED(device);
892 #endif
893 
894  return delsys;
895 }
896 
897 // Get the currently configured delivery system from the device
899 {
900  DTVModulationSystem delsys;
901 
902 #ifdef USING_DVB
903  struct dtv_property prop = {};
904  struct dtv_properties cmd = {};
905 
906  prop.cmd = DTV_DELIVERY_SYSTEM;
907  // prop.u.data = delsys;
908  cmd.num = 1;
909  cmd.props = &prop;
910 
911  int ret = ioctl(fd_frontend, FE_GET_PROPERTY, &cmd);
912  if (ret < 0)
913  {
914  LOG(VB_GENERAL, LOG_ERR, LOC +
915  QString("FE_GET_PROPERTY ioctl failed (fd_frontend:%1)")
916  .arg(fd_frontend) + ENO);
917  return delsys;
918  }
919 
920  delsys = prop.u.data;
921 
922 #else
923  Q_UNUSED(fd_frontend);
924 #endif // USING_DVB
925 
926  return delsys;
927 }
928 
929 // Get the delivery system from database table capturecard.
930 // If there is nothing in the database then get the currently
931 // configured delivery system, check for DVB-T/T2 and DVB-S/S2
932 // and update the database.
933 // Configure the tuner.
934 // Return the tuner type corresponding with the modulation system.
936 {
937  QString type = GetRawInputType(inputid);
938  if ("DVB" != type)
939  return type;
940 
941  DTVTunerType tunertype;
942  int fd_frontend = OpenVideoDevice(inputid);
943  if (fd_frontend < 0)
944  return "ERROR_OPEN";
945 
946  DTVModulationSystem delsys = GetDeliverySystem(inputid);
948  {
949  delsys = ProbeBestDeliverySystem(fd_frontend);
951  {
952  // Update database
953  set_on_input("inputname", inputid, delsys.toString()); // Update DB capturecard
954  LOG(VB_GENERAL, LOG_INFO,
955  QString("CardUtil[%1]: ").arg(inputid) +
956  QString("Update capturecard delivery system: %1").arg(delsys.toString()));
957  }
958  else
959  {
960  LOG(VB_GENERAL, LOG_ERR,
961  QString("CardUtil[%1]: Error probing best delivery system").arg(inputid));
962  return "ERROR_UNKNOWN";
963  }
964  }
965  SetDeliverySystem(inputid, delsys, fd_frontend);
966  tunertype = ConvertToTunerType(delsys);
967  close(fd_frontend);
968 
969  QString subtype = "ERROR_UNKNOWN";
970  if (DTVTunerType::kTunerTypeUnknown != tunertype)
971  {
972  subtype = tunertype.toString();
973  }
974 
975  LOG(VB_GENERAL, LOG_DEBUG,
976  QString("CardUtil[%1]: subtype:%2").arg(inputid).arg(subtype));
977 
978  return subtype;
979 }
980 
982 bool CardUtil::IsDVBInputType(const QString &inputType)
983 {
984  QString t = inputType.toUpper();
985  return (t == "DVB") || (t == "QPSK") || (t == "QAM") || (t == "OFDM") ||
986  (t == "ATSC") || (t == "DVB_S2") || (t == "DVB_T2");
987 }
988 
989 // Get the current delivery system from the card
990 // Get all supported delivery systems from the card
991 // If the current delivery system is DVB-T and DVB-T2 is supported then select DVB-T2
992 // If the current delivery system is DVB-S and DVB-S2 is supported then select DVB-S2
993 //
995 {
996  DTVModulationSystem delsys;
997 
998 #ifdef USING_DVB
999  // Get the current delivery system from the card
1000  delsys = ProbeCurrentDeliverySystem(fd);
1001  LOG(VB_GENERAL, LOG_INFO, LOC +
1002  QString("Current delivery system: %1").arg(delsys.toString()));
1003 
1004  // Get all supported delivery systems from the card
1005  QString msg = "Supported delivery systems:";
1006  QStringList delsyslist = ProbeDeliverySystems(fd);
1007  msg.append(delsyslist.join(" "));
1008  LOG(VB_GENERAL, LOG_INFO, LOC + msg);
1009 
1010  // If the current delivery system is DVB-T and DVB-T2 is supported then select DVB-T2
1012  {
1014  if (delsyslist.contains(newdelsys.toString()))
1015  {
1016  LOG(VB_GENERAL, LOG_INFO, LOC +
1017  QString("Changing delivery system from %1 to %2")
1018  .arg(delsys.toString()).arg(newdelsys.toString()));
1019  delsys = newdelsys;
1020  }
1021  }
1022 
1023  // If the current delivery system is DVB-S and DVB-S2 is supported then select DVB-S2
1025  {
1027  if (delsyslist.contains(newdelsys.toString()))
1028  {
1029  LOG(VB_GENERAL, LOG_INFO, LOC +
1030  QString("Changing delivery system from %1 to %2")
1031  .arg(delsys.toString()).arg(newdelsys.toString()));
1032  delsys = newdelsys;
1033  }
1034  }
1035 #else
1036  Q_UNUSED(fd);
1037 #endif
1038 
1039  return delsys;
1040 }
1041 
1042 // Get the delivery system from the database
1043 // If not found then get the best delivery system from the card
1044 //
1046 {
1047  DTVModulationSystem delsys;
1048 #ifdef USING_DVB
1049 
1050  // If there is a valid modulation system in the database
1051  // then we return that and do nothing more.
1052  delsys = GetDeliverySystem(inputid);
1054  {
1055  return delsys;
1056  }
1057 
1058  // Nothing in the database, get default and use that
1059  delsys = ProbeBestDeliverySystem(fd);
1060  LOG(VB_GENERAL, LOG_INFO,
1061  QString("CardUtil[%1]: ").arg(inputid) +
1062  QString("No capturecard delivery system in database, using: %1").arg(delsys.toString()));
1063 
1064 #else
1065  Q_UNUSED(inputid);
1066  Q_UNUSED(fd);
1067 #endif
1068 
1069  return delsys;
1070 }
1071 
1072 // Configure the tuner to use the delivery system from database
1073 // If not found then set to the best delivery system from the card
1074 //
1076 {
1077  int ret = -1;
1078 
1079 #ifdef USING_DVB
1080  DTVModulationSystem delsys = GetOrProbeDeliverySystem(inputid, fd);
1082  {
1083  ret = SetDeliverySystem(inputid, delsys, fd);
1084  }
1085 #else
1086  Q_UNUSED(inputid);
1087  Q_UNUSED(fd);
1088 #endif
1089 
1090  return ret;
1091 }
1092 
1093 // Set delivery system from database
1094 //
1096 {
1097  int ret = -1;
1098 
1099 #ifdef USING_DVB
1100  DTVModulationSystem delsys = GetDeliverySystem(inputid);
1102  {
1103  ret = SetDeliverySystem(inputid, delsys);
1104  }
1105 #else
1106  Q_UNUSED(inputid);
1107 #endif // USING_DVB
1108 
1109  return ret;
1110 }
1111 
1113 {
1114  int ret = -1;
1115 
1116 #ifdef USING_DVB
1117  QString device = GetVideoDevice(inputid);
1118 
1119  if (device.isEmpty())
1120  {
1121  LOG(VB_GENERAL, LOG_DEBUG,
1122  QString("CardUtil[%1]: ").arg(inputid) +
1123  QString("inputid:%1 ").arg(inputid) +
1124  QString("delsys:%1").arg(delsys.toString()));
1125  return ret;
1126  }
1127 
1128  int fd_frontend = OpenVideoDevice(device);
1129  if (fd_frontend < 0)
1130  {
1131  LOG(VB_GENERAL, LOG_ERR,
1132  QString("CardUtil[%1]: ").arg(inputid) +
1133  QString("open failed (%1)").arg(device) + ENO);
1134  return ret;
1135  }
1136  ret = SetDeliverySystem(inputid, delsys, fd_frontend);
1137 
1138  close(fd_frontend);
1139 #else
1140  Q_UNUSED(inputid);
1141  Q_UNUSED(delsys);
1142 #endif // USING_DVB
1143 
1144  return ret;
1145 }
1146 
1147 // Get delivery system from the database and write it to the card
1148 int CardUtil::SetDeliverySystem(uint inputid, int fd)
1149 {
1150  int ret = -1;
1151 
1152 #ifdef USING_DVB
1153  DTVModulationSystem delsys = GetDeliverySystem(inputid);
1155  {
1156  ret = SetDeliverySystem(inputid, delsys, fd);
1157  }
1158 #else
1159  Q_UNUSED(inputid);
1160  Q_UNUSED(fd);
1161 #endif // USING_DVB
1162 
1163  return ret;
1164 }
1165 
1166 // Write the delivery system to the card
1168 {
1169  int ret = -1;
1170 
1171 #ifdef USING_DVB
1172  LOG(VB_GENERAL, LOG_INFO,
1173  QString("CardUtil[%1]: ").arg(inputid) +
1174  QString("Set delivery system: %1").arg(delsys.toString()));
1175 
1176  struct dtv_property prop = {};
1177  struct dtv_properties cmd = {};
1178 
1179  prop.cmd = DTV_DELIVERY_SYSTEM;
1180  prop.u.data = delsys;
1181  cmd.num = 1;
1182  cmd.props = &prop;
1183 
1184  ret = ioctl(fd, FE_SET_PROPERTY, &cmd);
1185  if (ret < 0)
1186  {
1187  LOG(VB_GENERAL, LOG_ERR, LOC +
1188  QString("[%1] FE_SET_PROPERTY ioctl failed")
1189  .arg(inputid) + ENO);
1190  return ret;
1191  }
1192 #else
1193  Q_UNUSED(inputid);
1194  Q_UNUSED(delsys);
1195  Q_UNUSED(fd);
1196 #endif // USING_DVB
1197 
1198  return ret;
1199 }
1200 
1202 {
1203  QString device = GetVideoDevice(inputid);
1204  return OpenVideoDevice(device);
1205 }
1206 
1207 int CardUtil::OpenVideoDevice(const QString &device)
1208 {
1209  if (device.isEmpty())
1210  return -1;
1211 
1212  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_FRONTEND, device);
1213  QByteArray dev = dvbdev.toLatin1();
1214  int fd_frontend = open(dev.constData(), O_RDWR | O_NONBLOCK);
1215  if (fd_frontend < 0)
1216  {
1217  LOG(VB_GENERAL, LOG_ERR, LOC +
1218  QString("Can't open DVB frontend (%1) for %2.")
1219  .arg(dvbdev).arg(device) + ENO);
1220  }
1221  return fd_frontend;
1222 }
1223 
1224 QString get_on_input(const QString &to_get, uint inputid)
1225 {
1227  query.prepare(
1228  QString("SELECT %1 ").arg(to_get) +
1229  "FROM capturecard "
1230  "WHERE capturecard.cardid = :INPUTID");
1231  query.bindValue(":INPUTID", inputid);
1232 
1233  if (!query.exec())
1234  MythDB::DBError("CardUtil::get_on_input", query);
1235  else if (query.next())
1236  return query.value(0).toString();
1237 
1238  return QString();
1239 }
1240 
1241 bool set_on_input(const QString &to_set, uint inputid, const QString &value)
1242 {
1243  QString tmp = get_on_input("capturecard.cardid", inputid);
1244  if (tmp.isEmpty())
1245  return false;
1246 
1248  query.prepare(
1249  QString("UPDATE capturecard SET %1 = :VALUE ").arg(to_set) +
1250  "WHERE cardid = :INPUTID");
1251  query.bindValue(":INPUTID", inputid);
1252  query.bindValue(":VALUE", value);
1253 
1254  if (query.exec())
1255  return true;
1256 
1257  MythDB::DBError("CardUtil::set_on_input", query);
1258  return false;
1259 }
1260 
1271 std::vector<uint> CardUtil::GetInputIDs(const QString& videodevice,
1272  const QString& rawtype,
1273  const QString& inputname,
1274  QString hostname)
1275 {
1276  std::vector<uint> list;
1277 
1278  if (hostname.isEmpty())
1280 
1282  QString qstr =
1283  "SELECT cardid "
1284  "FROM capturecard "
1285  "WHERE hostname = :HOSTNAME ";
1286  if (!videodevice.isEmpty())
1287  qstr += "AND videodevice = :DEVICE ";
1288  if (!inputname.isEmpty())
1289  qstr += "AND inputname = :INPUTNAME ";
1290  if (!rawtype.isEmpty())
1291  qstr += "AND cardtype = :INPUTTYPE ";
1292  qstr += "ORDER BY cardid";
1293 
1294  query.prepare(qstr);
1295 
1296  query.bindValue(":HOSTNAME", hostname);
1297  if (!videodevice.isEmpty())
1298  query.bindValue(":DEVICE", videodevice);
1299  if (!inputname.isEmpty())
1300  query.bindValue(":INPUTNAME", inputname);
1301  if (!rawtype.isEmpty())
1302  query.bindValue(":INPUTTYPE", rawtype.toUpper());
1303 
1304  if (!query.exec())
1305  MythDB::DBError("CardUtil::GetInputIDs(videodevice...)", query);
1306  else
1307  {
1308  while (query.next())
1309  list.push_back(query.value(0).toUInt());
1310  }
1311 
1312  return list;
1313 }
1314 
1316 {
1317  if (!inputid)
1318  return 0;
1319 
1321  QString qstr =
1322  "SELECT COUNT(*) "
1323  "FROM capturecard "
1324  "WHERE parentid = :INPUTID";
1325 
1326  query.prepare(qstr);
1327  query.bindValue(":INPUTID", inputid);
1328 
1329  uint count = 0;
1330 
1331  if (!query.exec())
1332  MythDB::DBError("CardUtil::GetChildInputCount()", query);
1333  else if (query.next())
1334  count = query.value(0).toUInt();
1335 
1336  return count;
1337 }
1338 
1339 std::vector<uint> CardUtil::GetChildInputIDs(uint inputid)
1340 {
1341  std::vector<uint> list;
1342 
1343  if (!inputid)
1344  return list;
1345 
1347  QString qstr =
1348  "SELECT cardid "
1349  "FROM capturecard "
1350  "WHERE parentid = :INPUTID "
1351  "ORDER BY cardid";
1352 
1353  query.prepare(qstr);
1354  query.bindValue(":INPUTID", inputid);
1355 
1356  if (!query.exec())
1357  MythDB::DBError("CardUtil::GetChildInputIDs()", query);
1358  else
1359  {
1360  while (query.next())
1361  list.push_back(query.value(0).toUInt());
1362  }
1363 
1364  return list;
1365 }
1366 
1367 static uint clone_capturecard(uint src_inputid, uint orig_dst_inputid)
1368 {
1369  uint dst_inputid = orig_dst_inputid;
1370 
1372  if (!dst_inputid)
1373  {
1374  query.prepare(
1375  "DELETE FROM capturecard "
1376  "WHERE videodevice = 'temp_dummy'");
1377 
1378  if (!query.exec())
1379  {
1380  MythDB::DBError("clone_capturecard -- delete temp", query);
1381  return 0;
1382  }
1383 
1384  query.prepare(
1385  "INSERT INTO capturecard "
1386  "SET videodevice = 'temp_dummy'");
1387 
1388  if (!query.exec())
1389  {
1390  MythDB::DBError("clone_capturecard -- insert temp", query);
1391  return 0;
1392  }
1393 
1394  query.prepare(
1395  "SELECT cardid "
1396  "FROM capturecard "
1397  "WHERE videodevice = 'temp_dummy'");
1398 
1399  if (!query.exec())
1400  {
1401  MythDB::DBError("clone_capturecard -- get temp id", query);
1402  return 0;
1403  }
1404 
1405  if (!query.next())
1406  {
1407  LOG(VB_GENERAL, LOG_ERR, "clone_capturecard -- get temp id");
1408  return 0;
1409  }
1410 
1411  dst_inputid = query.value(0).toUInt();
1412  }
1413 
1414  query.prepare(
1415  "SELECT videodevice, audiodevice, vbidevice, "
1416  " cardtype, hostname, signal_timeout, "
1417  " channel_timeout, dvb_wait_for_seqstart, dvb_on_demand, "
1418  " dvb_tuning_delay, dvb_diseqc_type, diseqcid, "
1419  " dvb_eitscan, inputname, sourceid, "
1420  " externalcommand, changer_device, changer_model, "
1421  " tunechan, startchan, displayname, "
1422  " dishnet_eit, recpriority, quicktune, "
1423  " livetvorder, reclimit, "
1424  // See below for special handling of the following.
1425  " schedgroup, schedorder "
1426  "FROM capturecard "
1427  "WHERE cardid = :INPUTID");
1428  query.bindValue(":INPUTID", src_inputid);
1429 
1430  if (!query.exec())
1431  {
1432  MythDB::DBError("clone_capturecard -- get data", query);
1433  return 0;
1434  }
1435  if (!query.next())
1436  {
1437  LOG(VB_GENERAL, LOG_ERR, "clone_cardinput -- get data 2");
1438  return 0;
1439  }
1440 
1441  // Handle schedgroup and schedorder specially. If schedgroup is
1442  // set, schedgroup and schedorder should be false and 0,
1443  // respectively, for all children.
1444  bool schedgroup = query.value(26).toBool();
1445  uint schedorder = query.value(27).toUInt();
1446  if (schedgroup)
1447  {
1448  schedgroup = false;
1449  schedorder = 0;
1450  }
1451 
1452  MSqlQuery query2(MSqlQuery::InitCon());
1453  query2.prepare(
1454  "UPDATE capturecard "
1455  "SET videodevice = :V0, "
1456  " audiodevice = :V1, "
1457  " vbidevice = :V2, "
1458  " cardtype = :V3, "
1459  " hostname = :V4, "
1460  " signal_timeout = :V5, "
1461  " channel_timeout = :V6, "
1462  " dvb_wait_for_seqstart = :V7, "
1463  " dvb_on_demand = :V8, "
1464  " dvb_tuning_delay = :V9, "
1465  " dvb_diseqc_type = :V10, "
1466  " diseqcid = :V11,"
1467  " dvb_eitscan = :V12, "
1468  " inputname = :V13, "
1469  " sourceid = :V14, "
1470  " externalcommand = :V15, "
1471  " changer_device = :V16, "
1472  " changer_model = :V17, "
1473  " tunechan = :V18, "
1474  " startchan = :V19, "
1475  " displayname = :V20, "
1476  " dishnet_eit = :V21, "
1477  " recpriority = :V22, "
1478  " quicktune = :V23, "
1479  " livetvorder = :V24, "
1480  " reclimit = :V25, "
1481  " schedgroup = :SCHEDGROUP, "
1482  " schedorder = :SCHEDORDER, "
1483  " parentid = :PARENTID "
1484  "WHERE cardid = :INPUTID");
1485  for (uint i = 0; i < 26; ++i)
1486  query2.bindValue(QString(":V%1").arg(i), query.value(i).toString());
1487  query2.bindValue(":INPUTID", dst_inputid);
1488  query2.bindValue(":PARENTID", src_inputid);
1489  query2.bindValue(":SCHEDGROUP", schedgroup);
1490  query2.bindValue(":SCHEDORDER", schedorder);
1491 
1492  if (!query2.exec())
1493  {
1494  MythDB::DBError("clone_capturecard -- save data", query2);
1495  if (!orig_dst_inputid)
1496  CardUtil::DeleteInput(dst_inputid);
1497  return 0;
1498  }
1499 
1500  // copy input group linkages
1501  std::vector<uint> src_grps = CardUtil::GetInputGroups(src_inputid);
1502  std::vector<uint> dst_grps = CardUtil::GetInputGroups(dst_inputid);
1503  for (uint dst_grp : dst_grps)
1504  CardUtil::UnlinkInputGroup(dst_inputid, dst_grp);
1505  for (uint src_grp : src_grps)
1506  CardUtil::LinkInputGroup(dst_inputid, src_grp);
1507 
1508  // clone diseqc_config (just points to the same diseqc_tree row)
1509  DiSEqCDevSettings diseqc;
1510  if (diseqc.Load(src_inputid))
1511  diseqc.Store(dst_inputid);
1512 
1513  return dst_inputid;
1514 }
1515 
1516 uint CardUtil::CloneCard(uint src_inputid, uint orig_dst_inputid)
1517 {
1518  QString type = CardUtil::GetRawInputType(src_inputid);
1520  return 0;
1521 
1522  uint dst_inputid = clone_capturecard(src_inputid, orig_dst_inputid);
1523  return dst_inputid;
1524 }
1525 
1527 {
1528  uint inputid = CloneCard(parentid, 0);
1529 
1530  // Update the reclimit for the parent and all children so the new
1531  // child doesn't get removed the next time mythtv-setup is run.
1532  if (inputid)
1533  {
1534  LOG(VB_GENERAL, LOG_INFO, LOC +
1535  QString("Added child input %1 to parent %2")
1536  .arg(inputid).arg(parentid));
1538  query.prepare("UPDATE capturecard "
1539  "SET reclimit = reclimit + 1 "
1540  "WHERE cardid = :PARENTID");
1541  query.bindValue(":PARENTID", parentid);
1542  if (!query.exec())
1543  MythDB::DBError("CardUtil::AddChildInput", query);
1544  }
1545  else
1546  {
1547  LOG(VB_GENERAL, LOG_ERR, LOC +
1548  QString("Failed to add child input to parent %1").arg(parentid));
1549  }
1550 
1551  return inputid;
1552 }
1553 
1555 {
1556  QString fwnode;
1557 
1559  query.prepare("SELECT changer_device "
1560  "FROM capturecard WHERE cardid = :INPUTID ");
1561  query.bindValue(":INPUTID", inputid);
1562 
1563  if (query.exec() && query.next())
1564  {
1565  fwnode = query.value(0).toString();
1566  }
1567 
1568  return fwnode;
1569 }
1570 
1572 {
1573  QString fwnode;
1574 
1576  query.prepare("SELECT changer_model "
1577  "FROM capturecard WHERE cardid = :INPUTID ");
1578  query.bindValue(":INPUTID", inputid);
1579 
1580  if (query.exec() && query.next())
1581  {
1582  fwnode = query.value(0).toString();
1583  }
1584 
1585  return fwnode;
1586 }
1587 
1588 std::vector<uint> CardUtil::GetInputIDs(uint sourceid)
1589 {
1591 
1592  query.prepare(
1593  "SELECT DISTINCT cardid "
1594  "FROM capturecard "
1595  "WHERE sourceid = :SOURCEID");
1596  query.bindValue(":SOURCEID", sourceid);
1597 
1598  std::vector<uint> list;
1599 
1600  if (!query.exec())
1601  {
1602  MythDB::DBError("CardUtil::GetInputIDs(sourceid)", query);
1603  return list;
1604  }
1605 
1606  while (query.next())
1607  list.push_back(query.value(0).toUInt());
1608 
1609  return list;
1610 }
1611 
1612 bool CardUtil::SetStartChannel(uint inputid, const QString &channum)
1613 {
1615  query.prepare("UPDATE capturecard "
1616  "SET startchan = :CHANNUM "
1617  "WHERE cardid = :INPUTID");
1618  query.bindValue(":CHANNUM", channum);
1619  query.bindValue(":INPUTID", inputid);
1620 
1621  if (!query.exec())
1622  {
1623  MythDB::DBError("CardUtil::SetStartChannel", query);
1624  return false;
1625  }
1626 
1627  return true;
1628 }
1629 
1630 bool CardUtil::GetInputInfo(InputInfo &input, std::vector<uint> *groupids)
1631 {
1632  if (!input.m_inputId)
1633  return false;
1634 
1636  query.prepare("SELECT "
1637  "inputname, sourceid, livetvorder, "
1638  "schedorder, displayname, recpriority, quicktune "
1639  "FROM capturecard "
1640  "WHERE cardid = :INPUTID");
1641  query.bindValue(":INPUTID", input.m_inputId);
1642 
1643  if (!query.exec())
1644  {
1645  MythDB::DBError("CardUtil::GetInputInfo()", query);
1646  return false;
1647  }
1648 
1649  if (!query.next())
1650  return false;
1651 
1652  input.m_name = query.value(0).toString();
1653  input.m_sourceId = query.value(1).toUInt();
1654  input.m_liveTvOrder = query.value(2).toUInt();
1655  input.m_scheduleOrder = query.value(3).toUInt();
1656  input.m_displayName = query.value(4).toString();
1657  input.m_recPriority = query.value(5).toInt();
1658  input.m_quickTune = query.value(6).toBool();
1659 
1660  if (groupids)
1661  *groupids = GetInputGroups(input.m_inputId);
1662 
1663  return true;
1664 }
1665 
1666 QList<InputInfo> CardUtil::GetAllInputInfo()
1667 {
1668  QList<InputInfo> infoInputList;
1669 
1671  query.prepare("SELECT cardid, "
1672  "inputname, sourceid, livetvorder, "
1673  "schedorder, displayname, recpriority, quicktune "
1674  "FROM capturecard");
1675 
1676  if (!query.exec())
1677  {
1678  MythDB::DBError("CardUtil::GetAllInputInfo()", query);
1679  return infoInputList;
1680  }
1681 
1682  while (query.next())
1683  {
1684  InputInfo input;
1685  input.m_inputId = query.value(0).toUInt();
1686  input.m_name = query.value(1).toString();
1687  input.m_sourceId = query.value(2).toUInt();
1688  input.m_liveTvOrder = query.value(3).toUInt();
1689  input.m_scheduleOrder = query.value(4).toUInt();
1690  input.m_displayName = query.value(5).toString();
1691  input.m_recPriority = query.value(6).toInt();
1692  input.m_quickTune = query.value(7).toBool();
1693 
1694  infoInputList.push_back(input);
1695  }
1696 
1697  return infoInputList;
1698 }
1699 
1701 {
1702  InputInfo info("None", 0, inputid, 0, 0, 0);
1703  GetInputInfo(info);
1704  return info.m_name;
1705 }
1706 
1708 {
1710  query.prepare("SELECT startchan "
1711  "FROM capturecard "
1712  "WHERE cardid = :INPUTID");
1713  query.bindValue(":INPUTID", inputid);
1714 
1715  if (!query.exec())
1716  MythDB::DBError("CardUtil::GetStartingChannel(uint)", query);
1717  else if (query.next())
1718  return query.value(0).toString();
1719 
1720  return QString();
1721 }
1722 
1724 {
1725  if (!inputid)
1726  return QString();
1727 
1729  query.prepare("SELECT displayname "
1730  "FROM capturecard "
1731  "WHERE cardid = :INPUTID");
1732  query.bindValue(":INPUTID", inputid);
1733 
1734  if (!query.exec())
1735  MythDB::DBError("CardUtil::GetDisplayName(uint)", query);
1736  else if (query.next())
1737  {
1738  QString result = query.value(0).toString();
1739  return result;
1740  }
1741 
1742  return QString();
1743 }
1744 
1745 bool CardUtil::IsUniqueDisplayName(const QString &name, uint exclude_inputid)
1746 {
1747  if (name.isEmpty())
1748  return false;
1749 
1751  query.prepare("SELECT cardid "
1752  "FROM capturecard "
1753  "WHERE parentid = 0 "
1754  " AND cardid <> :INPUTID "
1755  " AND right(displayname, 2) = :NAME");
1756  query.bindValue(":NAME", name.right(2));
1757  query.bindValue(":INPUTID", exclude_inputid);
1758 
1759  if (!query.exec())
1760  {
1761  MythDB::DBError("CardUtil::IsUniqueDisplayName()", query);
1762  return false;
1763  }
1764 
1765  // Any result means it's not unique.
1766  return !query.next();
1767 }
1768 
1770 {
1772  query.prepare(
1773  "SELECT sourceid "
1774  "FROM capturecard "
1775  "WHERE cardid = :INPUTID");
1776  query.bindValue(":INPUTID", inputid);
1777  if (!query.exec() || !query.isActive())
1778  MythDB::DBError("CardUtil::GetSourceID()", query);
1779  else if (query.next())
1780  return query.value(0).toUInt();
1781 
1782  return 0;
1783 }
1784 
1785 // Is this intentionally leaving out the hostname when updating the
1786 // capturecard table? The hostname value does get set when inserting
1787 // into the capturecard table. (Code written in 2011.)
1789  const uint sourceid,
1790  const QString &inputname,
1791  const QString &externalcommand,
1792  const QString &changer_device,
1793  const QString &changer_model,
1794  const QString &/*hostname*/,
1795  const QString &tunechan,
1796  const QString &startchan,
1797  const QString &displayname,
1798  bool dishnet_eit,
1799  const uint recpriority,
1800  const uint quicktune,
1801  const uint schedorder,
1802  const uint livetvorder)
1803 {
1805 
1806  query.prepare(
1807  "UPDATE capturecard "
1808  "SET sourceid = :SOURCEID, "
1809  " inputname = :INPUTNAME, "
1810  " externalcommand = :EXTERNALCOMMAND, "
1811  " changer_device = :CHANGERDEVICE, "
1812  " changer_model = :CHANGERMODEL, "
1813  " tunechan = :TUNECHAN, "
1814  " startchan = :STARTCHAN, "
1815  " displayname = :DISPLAYNAME, "
1816  " dishnet_eit = :DISHNETEIT, "
1817  " recpriority = :RECPRIORITY, "
1818  " quicktune = :QUICKTUNE, "
1819  " schedorder = :SCHEDORDER, "
1820  " livetvorder = :LIVETVORDER "
1821  "WHERE cardid = :INPUTID AND "
1822  " inputname = 'None'");
1823 
1824  query.bindValue(":INPUTID", inputid);
1825  query.bindValue(":SOURCEID", sourceid);
1826  query.bindValue(":INPUTNAME", inputname);
1827  query.bindValue(":EXTERNALCOMMAND", externalcommand);
1828  query.bindValue(":CHANGERDEVICE", changer_device);
1829  query.bindValue(":CHANGERMODEL", changer_model);
1830  query.bindValue(":TUNECHAN", tunechan);
1831  query.bindValue(":STARTCHAN", startchan);
1832  query.bindValue(":DISPLAYNAME", displayname.isNull() ? "" : displayname);
1833  query.bindValue(":DISHNETEIT", dishnet_eit);
1834  query.bindValue(":RECPRIORITY", recpriority);
1835  query.bindValue(":QUICKTUNE", quicktune);
1836  query.bindValue(":SCHEDORDER", schedorder);
1837  query.bindValue(":LIVETVORDER", livetvorder);
1838 
1839  if (!query.exec())
1840  {
1841  MythDB::DBError("CardUtil::CreateCardInput()", query);
1842  return -1;
1843  }
1844 
1845  return inputid;
1846 }
1847 
1848 uint CardUtil::CreateInputGroup(const QString &name)
1849 {
1851 
1852  query.prepare("SELECT inputgroupid FROM inputgroup "
1853  "WHERE inputgroupname = :GROUPNAME "
1854  "LIMIT 1");
1855  query.bindValue(":GROUPNAME", name);
1856  if (!query.exec())
1857  {
1858  MythDB::DBError("CardUtil::CreateNewInputGroup 0", query);
1859  return 0;
1860  }
1861 
1862  if (query.next())
1863  return query.value(0).toUInt();
1864 
1865  query.prepare("SELECT MAX(inputgroupid) FROM inputgroup");
1866  if (!query.exec())
1867  {
1868  MythDB::DBError("CardUtil::CreateNewInputGroup 1", query);
1869  return 0;
1870  }
1871 
1872  uint inputgroupid = (query.next()) ? query.value(0).toUInt() + 1 : 1;
1873 
1874  query.prepare(
1875  "INSERT INTO inputgroup "
1876  " (cardinputid, inputgroupid, inputgroupname) "
1877  "VALUES (:INPUTID, :GROUPID, :GROUPNAME ) ");
1878  query.bindValue(":INPUTID", 0);
1879  query.bindValue(":GROUPID", inputgroupid);
1880  query.bindValue(":GROUPNAME", name);
1881  if (!query.exec())
1882  {
1883  MythDB::DBError("CardUtil::CreateNewInputGroup 2", query);
1884  return 0;
1885  }
1886 
1887  return inputgroupid;
1888 }
1889 
1891  const QString &type,
1892  const QString &host,
1893  const QString &device)
1894 {
1895  QString name = host + '|' + device;
1896  if (type == "FREEBOX" || type == "IMPORT" ||
1897  type == "DEMO" || type == "EXTERNAL" ||
1898  type == "HDHOMERUN" || type == "SATIP")
1899  name += QString("|%1").arg(inputid);
1900  return CreateInputGroup(name);
1901 }
1902 
1904 {
1906  query.prepare(
1907  "SELECT inputgroupid "
1908  "FROM inputgroup "
1909  "WHERE cardinputid = :INPUTID "
1910  " AND inputgroupname REGEXP '^[a-z_-]*\\\\|'");
1911  query.bindValue(":INPUTID", inputid);
1912 
1913  if (!query.exec())
1914  {
1915  MythDB::DBError("CardUtil::GetDeviceInputGroup()", query);
1916  return 0;
1917  }
1918 
1919  if (query.next())
1920  {
1921  return query.value(0).toUInt();
1922  }
1923 
1924  return 0;
1925 }
1926 
1927 bool CardUtil::LinkInputGroup(uint inputid, uint inputgroupid)
1928 {
1930 
1931  query.prepare(
1932  "SELECT cardinputid, inputgroupid, inputgroupname "
1933  "FROM inputgroup "
1934  "WHERE inputgroupid = :GROUPID "
1935  "ORDER BY inputgroupid, cardinputid, inputgroupname");
1936  query.bindValue(":GROUPID", inputgroupid);
1937 
1938  if (!query.exec())
1939  {
1940  MythDB::DBError("CardUtil::CreateInputGroup() 1", query);
1941  return false;
1942  }
1943 
1944  if (!query.next())
1945  return false;
1946 
1947  const QString name = query.value(2).toString();
1948 
1949  query.prepare(
1950  "INSERT INTO inputgroup "
1951  " (cardinputid, inputgroupid, inputgroupname) "
1952  "VALUES (:INPUTID, :GROUPID, :GROUPNAME ) ");
1953 
1954  query.bindValue(":INPUTID", inputid);
1955  query.bindValue(":GROUPID", inputgroupid);
1956  query.bindValue(":GROUPNAME", name);
1957 
1958  if (!query.exec())
1959  {
1960  MythDB::DBError("CardUtil::CreateInputGroup() 2", query);
1961  return false;
1962  }
1963 
1964  return true;
1965 }
1966 
1967 bool CardUtil::UnlinkInputGroup(uint inputid, uint inputgroupid)
1968 {
1970 
1971  if (!inputid && !inputgroupid)
1972  {
1973  query.prepare(
1974  "DELETE FROM inputgroup "
1975  "WHERE cardinputid NOT IN "
1976  "( SELECT cardid FROM capturecard )");
1977  }
1978  else
1979  {
1980  query.prepare(
1981  "DELETE FROM inputgroup "
1982  "WHERE cardinputid = :INPUTID AND "
1983  " inputgroupid = :GROUPID ");
1984 
1985  query.bindValue(":INPUTID", inputid);
1986  query.bindValue(":GROUPID", inputgroupid);
1987  }
1988 
1989  if (!query.exec())
1990  {
1991  MythDB::DBError("CardUtil::DeleteInputGroup()", query);
1992  return false;
1993  }
1994 
1995  return true;
1996 }
1997 
1998 std::vector<uint> CardUtil::GetInputGroups(uint inputid)
1999 {
2000  std::vector<uint> list;
2001 
2003 
2004  query.prepare(
2005  "SELECT inputgroupid "
2006  "FROM inputgroup "
2007  "WHERE cardinputid = :INPUTID "
2008  "ORDER BY inputgroupid, cardinputid, inputgroupname");
2009 
2010  query.bindValue(":INPUTID", inputid);
2011 
2012  if (!query.exec())
2013  {
2014  MythDB::DBError("CardUtil::GetInputGroups()", query);
2015  return list;
2016  }
2017 
2018  while (query.next())
2019  list.push_back(query.value(0).toUInt());
2020 
2021  return list;
2022 }
2023 
2024 std::vector<uint> CardUtil::GetGroupInputIDs(uint inputgroupid)
2025 {
2026  std::vector<uint> list;
2027 
2029 
2030  query.prepare(
2031  "SELECT DISTINCT cardid "
2032  "FROM capturecard, inputgroup "
2033  "WHERE inputgroupid = :GROUPID AND "
2034  " capturecard.cardid = inputgroup.cardinputid "
2035  "ORDER BY cardid");
2036 
2037  query.bindValue(":GROUPID", inputgroupid);
2038 
2039  if (!query.exec())
2040  {
2041  MythDB::DBError("CardUtil::GetGroupInputIDs()", query);
2042  return list;
2043  }
2044 
2045  while (query.next())
2046  list.push_back(query.value(0).toUInt());
2047 
2048  return list;
2049 }
2050 
2051 std::vector<uint> CardUtil::GetConflictingInputs(uint inputid)
2052 {
2053  LOG(VB_RECORD, LOG_INFO,
2054  QString("CardUtil[%1]: GetConflictingInputs() input %1").arg(inputid));
2055 
2056  std::vector<uint> inputids;
2057 
2059 
2060  query.prepare(
2061  "SELECT DISTINCT c.cardid "
2062  "FROM ( "
2063  " SELECT inputgroupid "
2064  " FROM inputgroup "
2065  " WHERE cardinputid = :INPUTID1 "
2066  ") g "
2067  "JOIN inputgroup ig ON ig.inputgroupid = g.inputgroupid "
2068  "JOIN capturecard c ON c.cardid = ig.cardinputid "
2069  " AND c.cardid <> :INPUTID2 "
2070  "ORDER BY c.cardid");
2071 
2072  query.bindValue(":INPUTID1", inputid);
2073  query.bindValue(":INPUTID2", inputid);
2074 
2075  if (!query.exec())
2076  {
2077  MythDB::DBError("CardUtil::GetConflictingInputs()", query);
2078  return inputids;
2079  }
2080 
2081  while (query.next())
2082  {
2083  inputids.push_back(query.value(0).toUInt());
2084  LOG(VB_RECORD, LOG_INFO,
2085  QString("CardUtil[%1]: GetConflictingInputs() got input %2")
2086  .arg(inputid).arg(inputids.back()));
2087  }
2088 
2089  return inputids;
2090 }
2091 
2093  uint &signal_timeout, uint &channel_timeout)
2094 {
2096  query.prepare(
2097  "SELECT signal_timeout, channel_timeout "
2098  "FROM capturecard "
2099  "WHERE cardid = :INPUTID");
2100  query.bindValue(":INPUTID", inputid);
2101 
2102  if (!query.exec() || !query.isActive())
2103  MythDB::DBError("CardUtil::GetTimeouts()", query);
2104  else if (query.next())
2105  {
2106  signal_timeout = (uint) std::max(query.value(0).toInt(), 250);
2107  channel_timeout = (uint) std::max(query.value(1).toInt(), 500);
2108  return true;
2109  }
2110 
2111  return false;
2112 }
2113 
2115 {
2116  DiSEqCDevTree *diseqc_tree = DiSEqCDev::FindTree(inputid);
2117 
2118  bool needsConf = false;
2119  if (diseqc_tree)
2120  needsConf = diseqc_tree->IsInNeedOfConf();
2121 
2122  return needsConf;
2123 }
2124 
2125 uint CardUtil::GetQuickTuning(uint inputid, const QString &input_name)
2126 {
2127  uint quicktune = 0;
2128 
2130  query.prepare(
2131  "SELECT quicktune "
2132  "FROM capturecard "
2133  "WHERE cardid = :INPUTID AND "
2134  " inputname = :INPUTNAME");
2135  query.bindValue(":INPUTID", inputid);
2136  query.bindValue(":INPUTNAME", input_name);
2137 
2138  if (!query.exec() || !query.isActive())
2139  MythDB::DBError("CardUtil::GetQuickTuning()", query);
2140  else if (query.next())
2141  quicktune = query.value(0).toUInt();
2142 
2143  return quicktune;
2144 }
2145 
2146 bool CardUtil::hasV4L2(int videofd)
2147 {
2148  (void) videofd;
2149 #ifdef USING_V4L2
2150  struct v4l2_capability vcap {};
2151 
2152  return ((ioctl(videofd, VIDIOC_QUERYCAP, &vcap) >= 0) &&
2153  ((vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE) != 0U));
2154 #else // if !USING_V4L2
2155  return false;
2156 #endif // !USING_V4L2
2157 }
2158 
2160  int videofd, QString &input, QString &driver, uint32_t &version,
2161  uint32_t &capabilities)
2162 {
2163  input.clear();
2164  driver.clear();
2165  version = 0;
2166  capabilities = 0;
2167 
2168  if (videofd < 0)
2169  return false;
2170 
2171 #ifdef USING_V4L2
2172  // First try V4L2 query
2173  struct v4l2_capability capability {};
2174  if (ioctl(videofd, VIDIOC_QUERYCAP, &capability) >= 0)
2175  {
2176  input = QString::fromLatin1((const char*)capability.card);
2177  driver = QString::fromLatin1((const char*)capability.driver);
2178  version = capability.version;
2179  capabilities = capability.capabilities;
2180  }
2181 #ifdef USING_V4L1
2182  else // Fallback to V4L1 query
2183  {
2184  struct video_capability capability2;
2185  if (ioctl(videofd, VIDIOCGCAP, &capability2) >= 0)
2186  input = QString::fromLatin1((const char*)capability2.name);
2187  }
2188 #endif // USING_V4L1
2189 #endif // USING_V4L2
2190 
2191  if (!driver.isEmpty())
2192  driver.remove( QRegularExpression(R"(\[[0-9]\]$)") );
2193 
2194  return !input.isEmpty();
2195 }
2196 
2198 {
2199  (void) videofd;
2200 
2201  InputNames list;
2202  ok = false;
2203 
2204 #ifdef USING_V4L2
2205  bool usingv4l2 = hasV4L2(videofd);
2206 
2207  // V4L v2 query
2208  struct v4l2_input vin {};
2209  while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMINPUT, &vin) >= 0))
2210  {
2211  QString input((char *)vin.name);
2212  list[vin.index] = input;
2213  vin.index++;
2214  }
2215  if (vin.index)
2216  {
2217  ok = true;
2218  return list;
2219  }
2220 
2221 #ifdef USING_V4L1
2222  // V4L v1 query
2223  struct video_capability vidcap;
2224  memset(&vidcap, 0, sizeof(vidcap));
2225  if (ioctl(videofd, VIDIOCGCAP, &vidcap) != 0)
2226  {
2227  QString msg = QObject::tr("Could not query inputs.");
2228  LOG(VB_GENERAL, LOG_ERR, "ProbeV4LVideoInputs(): Error, " + msg + ENO);
2229  list[-1] = msg;
2230  vidcap.channels = 0;
2231  }
2232 
2233  for (int i = 0; i < vidcap.channels; i++)
2234  {
2235  struct video_channel test;
2236  memset(&test, 0, sizeof(test));
2237  test.channel = i;
2238 
2239  if (ioctl(videofd, VIDIOCGCHAN, &test) != 0)
2240  {
2241  LOG(VB_GENERAL, LOG_ERR, "ProbeV4LVideoInputs(): Error, " +
2242  QString("Could determine name of input #%1"
2243  "\n\t\t\tNot adding it to the list.")
2244  .arg(test.channel) + ENO);
2245  continue;
2246  }
2247 
2248  list[i] = test.name;
2249  }
2250 #endif // USING_V4L1
2251 
2252  // Create an input when none are advertised
2253  if (list.isEmpty())
2254  list[0] = "Television";
2255 
2256  ok = true;
2257 #else // if !USING_V4L2
2258  list[-1] += QObject::tr("ERROR, Compile with V4L support to query inputs");
2259 #endif // !USING_V4L2
2260  return list;
2261 }
2262 
2264 {
2265  (void) videofd;
2266 
2267  InputNames list;
2268  ok = false;
2269 
2270 #ifdef USING_V4L2
2271  bool usingv4l2 = hasV4L2(videofd);
2272 
2273  // V4L v2 query
2274  struct v4l2_audio ain {};
2275  while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMAUDIO, &ain) >= 0))
2276  {
2277  QString input((char *)ain.name);
2278  list[ain.index] = input;
2279  ain.index++;
2280  }
2281  if (ain.index)
2282  {
2283  ok = true;
2284  return list;
2285  }
2286 
2287  ok = true;
2288 #else // if !USING_V4L2
2289  list[-1] += QObject::tr(
2290  "ERROR, Compile with V4L support to query audio inputs");
2291 #endif // !USING_V4L2
2292  return list;
2293 }
2294 
2296 {
2297  InputNames list;
2299  query.prepare(
2300  "SELECT cardid, inputname "
2301  "FROM capturecard "
2302  "WHERE hostname = :HOSTNAME "
2303  " AND videodevice = :DEVICE "
2304  " AND parentid = 0 "
2305  " AND inputname <> 'None'");
2306  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
2307  query.bindValue(":DEVICE", device);
2308 
2309  if (!query.exec() || !query.isActive())
2310  MythDB::DBError("CardUtil::GetConfiguredDVBInputs", query);
2311  else
2312  {
2313  while (query.next())
2314  list[query.value(0).toUInt()] = query.value(1).toString();
2315  }
2316  return list;
2317 }
2318 
2319 // Convert DVBv5 frontend capabilities from bitmask to string
2320 //
2321 // Source linuxtv.org v4l-utils/lib/libdvbv5/dvb-v5.c
2322 //
2323 QStringList CardUtil::CapabilitiesToString(uint64_t capabilities)
2324 {
2325  QStringList caps;
2326 #ifdef USING_DVB
2327 
2328  struct fe_caps_name {
2329  unsigned idx;
2330  const char *name;
2331  };
2332 
2333  struct fe_caps_name fe_caps_name[31] = {
2334  { FE_CAN_2G_MODULATION, "CAN_2G_MODULATION" },
2335  { FE_CAN_8VSB, "CAN_8VSB" },
2336  { FE_CAN_16VSB, "CAN_16VSB" },
2337  { FE_CAN_BANDWIDTH_AUTO, "CAN_BANDWIDTH_AUTO" },
2338  { FE_CAN_FEC_1_2, "CAN_FEC_1_2" },
2339  { FE_CAN_FEC_2_3, "CAN_FEC_2_3" },
2340  { FE_CAN_FEC_3_4, "CAN_FEC_3_4" },
2341  { FE_CAN_FEC_4_5, "CAN_FEC_4_5" },
2342  { FE_CAN_FEC_5_6, "CAN_FEC_5_6" },
2343  { FE_CAN_FEC_6_7, "CAN_FEC_6_7" },
2344  { FE_CAN_FEC_7_8, "CAN_FEC_7_8" },
2345  { FE_CAN_FEC_8_9, "CAN_FEC_8_9" },
2346  { FE_CAN_FEC_AUTO, "CAN_FEC_AUTO" },
2347  { FE_CAN_GUARD_INTERVAL_AUTO, "CAN_GUARD_INTERVAL_AUTO" },
2348  { FE_CAN_HIERARCHY_AUTO, "CAN_HIERARCHY_AUTO" },
2349  { FE_CAN_INVERSION_AUTO, "CAN_INVERSION_AUTO" },
2350  { FE_CAN_MULTISTREAM, "CAN_MULTISTREAM" },
2351  { FE_CAN_MUTE_TS, "CAN_MUTE_TS" },
2352  { FE_CAN_QAM_16, "CAN_QAM_16" },
2353  { FE_CAN_QAM_32, "CAN_QAM_32" },
2354  { FE_CAN_QAM_64, "CAN_QAM_64" },
2355  { FE_CAN_QAM_128, "CAN_QAM_128" },
2356  { FE_CAN_QAM_256, "CAN_QAM_256" },
2357  { FE_CAN_QAM_AUTO, "CAN_QAM_AUTO" },
2358  { FE_CAN_QPSK, "CAN_QPSK" },
2359  { FE_CAN_RECOVER, "CAN_RECOVER" },
2360  { FE_CAN_TRANSMISSION_MODE_AUTO, "CAN_TRANSMISSION_MODE_AUTO" },
2361  { FE_CAN_TURBO_FEC, "CAN_TURBO_FEC" },
2362  { FE_HAS_EXTENDED_CAPS, "HAS_EXTENDED_CAPS" },
2363  { FE_IS_STUPID, "IS_STUPID" },
2364  { FE_NEEDS_BENDING, "NEEDS_BENDING" },
2365  };
2366 
2367  for (uint i = 0; i < sizeof(fe_caps_name)/sizeof(fe_caps_name[0]); i++)
2368  {
2369  if (capabilities & fe_caps_name[i].idx)
2370  caps.append(fe_caps_name[i].name);
2371  }
2372 #endif // USING_DVB
2373  return caps;
2374 }
2375 
2376 QStringList CardUtil::ProbeVideoInputs(const QString& device, const QString& inputtype)
2377 {
2378  QStringList ret;
2379 
2380  if (IsSingleInputType(inputtype))
2381  ret += "MPEG2TS";
2382  else if ("DVB" == inputtype)
2383  ret += ProbeDVBInputs(device);
2384  else
2385  ret += ProbeV4LVideoInputs(device);
2386 
2387  return ret;
2388 }
2389 
2390 QStringList CardUtil::ProbeAudioInputs(const QString& device, const QString& inputtype)
2391 {
2392  LOG(VB_GENERAL, LOG_DEBUG, QString("ProbeAudioInputs(%1,%2)")
2393  .arg(device).arg(inputtype));
2394  QStringList ret;
2395 
2396  if ("HDPVR" == inputtype ||
2397  "V4L2" == inputtype)
2398  ret += ProbeV4LAudioInputs(device);
2399 
2400  return ret;
2401 }
2402 
2403 QStringList CardUtil::ProbeV4LVideoInputs(const QString& device)
2404 {
2405  bool ok = false;
2406  QStringList ret;
2407  QByteArray dev = device.toLatin1();
2408  int videofd = open(dev.constData(), O_RDWR);
2409  if (videofd < 0)
2410  {
2411  ret += QObject::tr("Could not open '%1' "
2412  "to probe its inputs.").arg(device);
2413  return ret;
2414  }
2415  InputNames list = CardUtil::ProbeV4LVideoInputs(videofd, ok);
2416  close(videofd);
2417 
2418  if (!ok)
2419  {
2420  ret += list[-1];
2421  return ret;
2422  }
2423 
2424  InputNames::iterator it;
2425  for (it = list.begin(); it != list.end(); ++it)
2426  {
2427  if (it.key() >= 0)
2428  ret += *it;
2429  }
2430 
2431  return ret;
2432 }
2433 
2434 QStringList CardUtil::ProbeV4LAudioInputs(const QString& device)
2435 {
2436  LOG(VB_GENERAL, LOG_DEBUG, QString("ProbeV4LAudioInputs(%1)").arg(device));
2437 
2438  bool ok = false;
2439  QStringList ret;
2440  int videofd = open(device.toLatin1().constData(), O_RDWR);
2441  if (videofd < 0)
2442  {
2443  LOG(VB_GENERAL, LOG_ERR, "ProbeAudioInputs() -> couldn't open device");
2444  ret += QObject::tr("Could not open '%1' to probe its inputs.")
2445  .arg(device);
2446  return ret;
2447  }
2448  InputNames list = CardUtil::ProbeV4LAudioInputs(videofd, ok);
2449  close(videofd);
2450 
2451  if (!ok)
2452  {
2453  ret += list[-1];
2454  return ret;
2455  }
2456 
2457  InputNames::iterator it;
2458  for (it = list.begin(); it != list.end(); ++it)
2459  {
2460  if (it.key() >= 0)
2461  ret += *it;
2462  }
2463 
2464  return ret;
2465 }
2466 
2467 QStringList CardUtil::ProbeDVBInputs(const QString& device)
2468 {
2469  QStringList ret;
2470 
2471 #ifdef USING_DVB
2472  InputNames list = GetConfiguredDVBInputs(device);
2473  InputNames::iterator it;
2474  for (it = list.begin(); it != list.end(); ++it)
2475  {
2476  if (it.key())
2477  ret += *it;
2478  }
2479 #else
2480  (void) device;
2481  ret += QObject::tr("ERROR, Compile with DVB support to query inputs");
2482 #endif
2483 
2484  return ret;
2485 }
2486 
2487 QString CardUtil::GetDeviceLabel(const QString &inputtype,
2488  const QString &videodevice)
2489 {
2490  return QString("[ %1 : %2 ]").arg(inputtype).arg(videodevice);
2491 }
2492 
2494 {
2496  query.prepare("SELECT cardtype, videodevice "
2497  "FROM capturecard WHERE cardid = :INPUTID ");
2498  query.bindValue(":INPUTID", inputid);
2499 
2500  if (query.exec() && query.next())
2501  {
2502  return GetDeviceLabel(query.value(0).toString(),
2503  query.value(1).toString());
2504  }
2505 
2506  return "[ UNKNOWN ]";
2507 }
2508 
2510  const QString &device,
2511  const QString &inputtype,
2512  QStringList &inputs)
2513 {
2514  inputs.clear();
2515  if (IsSingleInputType(inputtype))
2516  inputs += "MPEG2TS";
2517  else if (inputtype == "DVB")
2518  inputs += "DVBInput";
2519  else
2520  inputs += ProbeV4LVideoInputs(device);
2521 }
2522 
2523 int CardUtil::CreateCaptureCard(const QString &videodevice,
2524  const QString &audiodevice,
2525  const QString &vbidevice,
2526  const QString &inputtype,
2527  const uint audioratelimit,
2528  const QString &hostname,
2529  const uint dvb_swfilter,
2530  const uint dvb_sat_type,
2531  bool dvb_wait_for_seqstart,
2532  bool skipbtaudio,
2533  bool dvb_on_demand,
2534  const uint dvb_diseqc_type,
2535  const uint firewire_speed,
2536  const QString &firewire_model,
2537  const uint firewire_connection,
2538  const uint signal_timeout,
2539  const uint channel_timeout,
2540  const uint dvb_tuning_delay,
2541  const uint contrast,
2542  const uint brightness,
2543  const uint colour,
2544  const uint hue,
2545  const uint diseqcid,
2546  bool dvb_eitscan)
2547 {
2549 
2550  query.prepare(
2551  "INSERT INTO capturecard "
2552  "(videodevice, audiodevice, vbidevice, cardtype, "
2553  "audioratelimit, hostname, dvb_swfilter, dvb_sat_type, "
2554  "dvb_wait_for_seqstart, skipbtaudio, dvb_on_demand, dvb_diseqc_type, "
2555  "firewire_speed, firewire_model, firewire_connection, signal_timeout, "
2556  "channel_timeout, dvb_tuning_delay, contrast, brightness, colour, "
2557  "hue, diseqcid, dvb_eitscan) "
2558  "VALUES (:VIDEODEVICE, :AUDIODEVICE, :VBIDEVICE, :INPUTTYPE, "
2559  ":AUDIORATELIMIT, :HOSTNAME, :DVBSWFILTER, :DVBSATTYPE, "
2560  ":DVBWAITFORSEQSTART, :SKIPBTAUDIO, :DVBONDEMAND, :DVBDISEQCTYPE, "
2561  ":FIREWIRESPEED, :FIREWIREMODEL, :FIREWIRECONNECTION, :SIGNALTIMEOUT, "
2562  ":CHANNELTIMEOUT, :DVBTUNINGDELAY, :CONTRAST, :BRIGHTNESS, :COLOUR, "
2563  ":HUE, :DISEQCID, :DVBEITSCAN ) ");
2564 
2565  query.bindValue(":VIDEODEVICE", videodevice);
2566  query.bindValue(":AUDIODEVICE", audiodevice);
2567  query.bindValue(":VBIDEVICE", vbidevice);
2568  query.bindValue(":INPUTTYPE", inputtype);
2569  query.bindValue(":AUDIORATELIMIT", audioratelimit);
2570  query.bindValue(":HOSTNAME", hostname);
2571  query.bindValue(":DVBSWFILTER", dvb_swfilter);
2572  query.bindValue(":DVBSATTYPE", dvb_sat_type);
2573  query.bindValue(":DVBWAITFORSEQSTART", dvb_wait_for_seqstart);
2574  query.bindValue(":SKIPBTAUDIO", skipbtaudio);
2575  query.bindValue(":DVBONDEMAND", dvb_on_demand);
2576  query.bindValue(":DVBDISEQCTYPE", dvb_diseqc_type);
2577  query.bindValue(":FIREWIRESPEED", firewire_speed);
2578  query.bindValue(":FIREWIREMODEL", firewire_model);
2579  query.bindValue(":FIREWIRECONNECTION", firewire_connection);
2580  query.bindValue(":SIGNALTIMEOUT", signal_timeout);
2581  query.bindValue(":CHANNELTIMEOUT", channel_timeout);
2582  query.bindValue(":DVBTUNINGDELAY", dvb_tuning_delay);
2583  query.bindValue(":CONTRAST", contrast);
2584  query.bindValue(":BRIGHTNESS", brightness);
2585  query.bindValue(":COLOUR", colour);
2586  query.bindValue(":HUE", hue);
2587  query.bindValue(":DISEQCID", diseqcid);
2588  query.bindValue(":DVBEITSCAN", dvb_eitscan);
2589 
2590  if (!query.exec())
2591  {
2592  MythDB::DBError("CreateCaptureCard", query);
2593  return -1;
2594  }
2595 
2596  query.prepare("SELECT MAX(cardid) FROM capturecard");
2597 
2598  if (!query.exec())
2599  {
2600  MythDB::DBError("CreateCaptureCard maxinput", query);
2601  return -1;
2602  }
2603 
2604  int inputid = -1; /* must be int not uint because of return type. */
2605 
2606  if (query.next())
2607  {
2608  inputid = query.value(0).toInt();
2609  uint groupid = CardUtil::CreateDeviceInputGroup(inputid, inputtype,
2610  hostname, videodevice);
2611  CardUtil::LinkInputGroup(inputid, groupid);
2612  }
2613 
2614  return inputid;
2615 }
2616 
2618 {
2619  std::vector<uint> childids = GetChildInputIDs(inputid);
2620  for (uint childid : childids)
2621  {
2622  if (!DeleteInput(childid))
2623  {
2624  LOG(VB_GENERAL, LOG_ERR, LOC +
2625  QString("CardUtil: Failed to delete child input %1")
2626  .arg(childid));
2627  return false;
2628  }
2629  }
2630 
2632 
2633  DiSEqCDevTree tree;
2634  tree.Load(inputid);
2635 
2636  // Delete the capturecard row for this input
2637  query.prepare("DELETE FROM capturecard WHERE cardid = :INPUTID");
2638  query.bindValue(":INPUTID", inputid);
2639  if (!query.exec())
2640  {
2641  MythDB::DBError("DeleteCard -- delete capturecard", query);
2642  return false;
2643  }
2644 
2645  // Update the reclimit of the parent input
2646  query.prepare("UPDATE capturecard SET reclimit=reclimit-1 "
2647  "WHERE cardid = :INPUTID");
2648  query.bindValue(":INPUTID", inputid);
2649  if (!query.exec())
2650  {
2651  MythDB::DBError("DeleteCard -- update capturecard", query);
2652  return false;
2653  }
2654 
2655  // Delete the inputgroup rows for this input
2656  query.prepare("DELETE FROM inputgroup WHERE cardinputid = :INPUTID");
2657  query.bindValue(":INPUTID", inputid);
2658  if (!query.exec())
2659  {
2660  MythDB::DBError("DeleteCard -- delete inputgroup", query);
2661  return false;
2662  }
2663 
2664  // Delete the diseqc tree if no more inputs reference it.
2665  if (tree.Root())
2666  {
2667  query.prepare("SELECT cardid FROM capturecard "
2668  "WHERE diseqcid = :DISEQCID LIMIT 1");
2669  query.bindValue(":DISEQCID", tree.Root()->GetDeviceID());
2670  if (!query.exec())
2671  {
2672  MythDB::DBError("DeleteCard -- find diseqc tree", query);
2673  }
2674  else if (!query.next())
2675  {
2676  tree.SetRoot(nullptr);
2677  tree.Store(inputid);
2678  }
2679  }
2680 
2681  // delete any unused input groups
2682  UnlinkInputGroup(0, 0);
2683 
2684  return true;
2685 }
2686 
2688 {
2690  return (query.exec("TRUNCATE TABLE inputgroup") &&
2691  query.exec("TRUNCATE TABLE diseqc_config") &&
2692  query.exec("TRUNCATE TABLE diseqc_tree") &&
2693  query.exec("TRUNCATE TABLE capturecard") &&
2694  query.exec("TRUNCATE TABLE iptv_channel"));
2695 }
2696 
2697 std::vector<uint> CardUtil::GetInputList(void)
2698 {
2699  std::vector<uint> list;
2700 
2702  query.prepare(
2703  "SELECT cardid "
2704  "FROM capturecard "
2705  "ORDER BY cardid");
2706 
2707  if (!query.exec())
2708  MythDB::DBError("CardUtil::GetInputList()", query);
2709  else
2710  {
2711  while (query.next())
2712  list.push_back(query.value(0).toUInt());
2713  }
2714 
2715  return list;
2716 }
2717 
2718 std::vector<uint> CardUtil::GetSchedInputList(void)
2719 {
2720  std::vector<uint> list;
2721 
2723  query.prepare(
2724  "SELECT DISTINCT cardid "
2725  "FROM capturecard "
2726  "WHERE schedorder <> 0 "
2727  "ORDER BY schedorder, cardid");
2728 
2729  if (!query.exec())
2730  MythDB::DBError("CardUtil::GetSchedInputList()", query);
2731  else
2732  {
2733  while (query.next())
2734  list.push_back(query.value(0).toUInt());
2735  }
2736 
2737  return list;
2738 }
2739 
2740 std::vector<uint> CardUtil::GetLiveTVInputList(void)
2741 {
2742  std::vector<uint> list;
2743 
2745  query.prepare(
2746  "SELECT DISTINCT cardid "
2747  "FROM capturecard "
2748  "WHERE livetvorder <> 0 "
2749  "ORDER BY livetvorder, cardid");
2750 
2751  if (!query.exec())
2752  MythDB::DBError("CardUtil::GetLiveTVInputList()", query);
2753  else
2754  {
2755  while (query.next())
2756  list.push_back(query.value(0).toUInt());
2757  }
2758 
2759  return list;
2760 }
2761 
2762 QString CardUtil::GetDeviceName(dvb_dev_type_t type, const QString &device)
2763 {
2764  QString devname = QString(device);
2765 #if 0
2766  LOG(VB_RECORD, LOG_DEBUG, LOC + QString("DVB Device (%1)").arg(devname));
2767 #endif
2768 
2769  if (DVB_DEV_FRONTEND == type)
2770  {
2771  return devname;
2772  }
2773 
2774  if (DVB_DEV_DVR == type)
2775  {
2776  QString tmp = devname;
2777  tmp = tmp.replace(tmp.indexOf("frontend"), 8, "dvr");
2778  if (QFile::exists(tmp))
2779  {
2780  LOG(VB_RECORD, LOG_DEBUG, LOC +
2781  QString("Adapter Frontend dvr number matches (%1)").arg(tmp));
2782  return tmp;
2783  }
2784 
2785  // Use dvr0, allows multi-standard frontends which only have one dvr
2786  tmp = devname;
2787  tmp = tmp.replace(tmp.indexOf("frontend"), 9, "dvr0");
2788  if (QFile::exists(tmp))
2789  {
2790  LOG(VB_RECORD, LOG_DEBUG, LOC +
2791  QString("Adapter Frontend dvr number not matching, using dvr0 instead (%1)").arg(tmp));
2792  return tmp;
2793  }
2794 
2795  LOG(VB_RECORD, LOG_DEBUG, LOC +
2796  QString("Adapter Frontend no dvr device found for (%1)").arg(devname));
2797  return "";
2798  }
2799 
2800  if (DVB_DEV_DEMUX == type)
2801  {
2802  QString tmp = devname;
2803  tmp = tmp.replace(tmp.indexOf("frontend"), 8, "demux");
2804  if (QFile::exists(tmp))
2805  {
2806  LOG(VB_RECORD, LOG_DEBUG, LOC +
2807  QString("Adapter Frontend demux number matches (%1)").arg(tmp));
2808  return tmp;
2809  }
2810 
2811  // Use demux0, allows multi-standard frontends, which only have one demux
2812  tmp = devname;
2813  tmp = tmp.replace(tmp.indexOf("frontend"), 9, "demux0");
2814  if (QFile::exists(tmp))
2815  {
2816  LOG(VB_RECORD, LOG_DEBUG, LOC +
2817  QString("Adapter Frontend demux number not matching, using demux0 instead (%1)").arg(tmp));
2818  return tmp;
2819  }
2820 
2821  LOG(VB_RECORD, LOG_DEBUG, LOC +
2822  QString("Adapter Frontend no demux device found for (%1)").arg(devname));
2823  return "";
2824  }
2825 
2826  if (DVB_DEV_CA == type)
2827  {
2828  QString tmp = devname;
2829  tmp = tmp.replace(tmp.indexOf("frontend"), 8, "ca");
2830  if (QFile::exists(tmp))
2831  {
2832  LOG(VB_RECORD, LOG_DEBUG, LOC +
2833  QString("Adapter Frontend ca number matches (%1)").arg(tmp));
2834  return tmp;
2835  }
2836 
2837  // Use ca0, allows multi-standard frontends, which only have one ca
2838  tmp = devname;
2839  tmp = tmp.replace(tmp.indexOf("frontend"), 9, "ca0");
2840  if (QFile::exists(tmp))
2841  {
2842  LOG(VB_RECORD, LOG_DEBUG, LOC +
2843  QString("Adapter Frontend ca number not matching, using ca0 instead (%1)").arg(tmp));
2844  return tmp;
2845  }
2846 
2847  LOG(VB_RECORD, LOG_DEBUG, LOC +
2848  QString("Adapter Frontend no ca device found for (%1)").arg(devname));
2849  return "";
2850  }
2851 
2852  if (DVB_DEV_AUDIO == type)
2853  {
2854  return devname.replace(devname.indexOf("frontend"), 8, "audio");
2855  }
2856 
2857  if (DVB_DEV_VIDEO == type)
2858  {
2859  return devname.replace(devname.indexOf("frontend"), 8, "video");
2860  }
2861 
2862  return "";
2863 }
2864 
2865 
2875 bool CardUtil::HDHRdoesDVB(const QString &device)
2876 {
2877  (void) device;
2878 
2879 #ifdef USING_HDHOMERUN
2880  hdhomerun_device_t *hdhr =
2881  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
2882  if (!hdhr)
2883  return false;
2884 
2885  const char *model = hdhomerun_device_get_model_str(hdhr);
2886  if (model && strstr(model, "dvb"))
2887  {
2888  hdhomerun_device_destroy(hdhr);
2889  return true;
2890  }
2891 
2892  hdhomerun_device_destroy(hdhr);
2893 
2894 #endif
2895 
2896  return false;
2897 }
2898 
2903 bool CardUtil::HDHRdoesDVBC(const QString &device)
2904 {
2905  (void) device;
2906 
2907 #ifdef USING_HDHOMERUN
2908  hdhomerun_device_t *hdhr =
2909  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
2910  if (!hdhr)
2911  return false;
2912 
2913  const char *model = hdhomerun_device_get_model_str(hdhr);
2914  if (model && strstr(model, "dvbc"))
2915  {
2916  hdhomerun_device_destroy(hdhr);
2917  return true;
2918  }
2919 
2920  hdhomerun_device_destroy(hdhr);
2921 
2922 #endif
2923 
2924  return false;
2925 }
2926 
2931 QString CardUtil::GetHDHRdesc(const QString &device)
2932 {
2933  QString connectErr = QObject::tr("Unable to connect to device.");
2934 
2935 #ifdef USING_HDHOMERUN
2936  bool deviceIsIP = false;
2937 
2938  if (device.contains('.')) // Simplistic check, but also allows DNS names
2939  deviceIsIP = true;
2940  else
2941  {
2942  bool validID = false;
2943 
2944  uint32_t dev = device.toUInt(&validID, 16);
2945  if (!validID || !hdhomerun_discover_validate_device_id(dev))
2946  return QObject::tr("Invalid Device ID");
2947  }
2948  (void) deviceIsIP;
2949 
2950  LOG(VB_GENERAL, LOG_INFO, "CardUtil::GetHDHRdescription(" + device +
2951  ") - trying to locate device");
2952 
2953  hdhomerun_device_t *hdhr =
2954  hdhomerun_device_create_from_str(device.toLatin1(), nullptr);
2955  if (!hdhr)
2956  return QObject::tr("Invalid Device ID or address.");
2957 
2958  const char *model = hdhomerun_device_get_model_str(hdhr);
2959  if (!model)
2960  {
2961  hdhomerun_device_destroy(hdhr);
2962  return connectErr;
2963  }
2964 
2965 
2966  QString description = model;
2967  char *sVersion = nullptr;
2968  uint32_t iVersion = 0;
2969 
2970  if (hdhomerun_device_get_version(hdhr, &sVersion, &iVersion))
2971  description += QObject::tr(", firmware: %2").arg(sVersion);
2972 
2973  hdhomerun_device_destroy(hdhr);
2974 
2975  return description;
2976 #else
2977 
2978  (void) device;
2979  return connectErr;
2980 #endif
2981 }
2982 
2987 QString CardUtil::GetVBoxdesc(const QString &id, const QString &ip,
2988  const QString &tunerNo, const QString &tunerType)
2989 {
2990  QString connectErr = QObject::tr("Unable to connect to device.");
2991 
2992 #ifdef USING_VBOX
2993  VBox *vbox = new VBox(ip);
2994 
2995  if (!vbox->checkConnection())
2996  {
2997  delete vbox;
2998  return connectErr;
2999  }
3000 
3001  QString version;
3002 
3003  if (!vbox->checkVersion(version))
3004  {
3005  QString apiVersionErr = QObject::tr("The VBox software version is too old (%1), we require %2")
3006  .arg(version).arg(VBOX_MIN_API_VERSION);
3007  delete vbox;
3008  return apiVersionErr;
3009 
3010  }
3011 
3012  delete vbox;
3013 
3014  return QString("V@Box TV Gateway - ID: %1, IP: %2, Tuner: %3-%4").arg(id)
3015  .arg(ip).arg(tunerNo).arg(tunerType);
3016 
3017 #else
3018  (void) id;
3019  (void) ip;
3020  (void) tunerNo;
3021  (void) tunerType;
3022 
3023  return connectErr;
3024 #endif
3025 }
3026 
3027 #ifdef USING_ASI
3028 static QString sys_dev(uint device_num, const QString& dev)
3029 {
3030  return QString("/sys/class/asi/asirx%1/%2").arg(device_num).arg(dev);
3031 }
3032 
3033 static QString read_sys(const QString& sys_dev)
3034 {
3035  QFile f(sys_dev);
3036  f.open(QIODevice::ReadOnly);
3037  QByteArray sdba = f.readAll();
3038  f.close();
3039  return sdba;
3040 }
3041 
3042 static bool write_sys(const QString& sys_dev, const QString& str)
3043 {
3044  QFile f(sys_dev);
3045  f.open(QIODevice::WriteOnly);
3046  QByteArray ba = str.toLocal8Bit();
3047  qint64 offset = 0;
3048  for (uint tries = 0; (offset < ba.size()) && tries < 5; tries++)
3049  {
3050  qint64 written = f.write(ba.data()+offset, ba.size()-offset);
3051  if (written < 0)
3052  return false;
3053  offset += written;
3054  }
3055  return true;
3056 }
3057 #endif
3058 
3059 int CardUtil::GetASIDeviceNumber(const QString &device, QString *error)
3060 {
3061 #ifdef USING_ASI
3062  // basic confirmation
3063  struct stat statbuf {};
3064  if (stat(device.toLocal8Bit().constData(), &statbuf) < 0)
3065  {
3066  if (error)
3067  *error = QString("Unable to stat '%1'").arg(device) + ENO;
3068  return -1;
3069  }
3070 
3071  if (!S_ISCHR(statbuf.st_mode))
3072  {
3073  if (error)
3074  *error = QString("'%1' is not a character device").arg(device);
3075  return -1;
3076  }
3077 
3078  if (!(statbuf.st_rdev & 0x0080))
3079  {
3080  if (error)
3081  *error = QString("'%1' not a DVEO ASI receiver").arg(device);
3082  return -1;
3083  }
3084 
3085  int device_num = statbuf.st_rdev & 0x007f;
3086 
3087  // extra confirmation
3088  QString sys_dev_contents = read_sys(sys_dev(device_num, "dev"));
3089  QStringList sys_dev_clist = sys_dev_contents.split(":");
3090  if (2 != sys_dev_clist.size())
3091  {
3092  if (error)
3093  {
3094  *error = QString("Unable to read '%1'")
3095  .arg(sys_dev(device_num, "dev"));
3096  }
3097  return -1;
3098  }
3099  if (sys_dev_clist[0].toUInt() != (statbuf.st_rdev>>8))
3100  {
3101  if (error)
3102  *error = QString("'%1' not a DVEO ASI device").arg(device);
3103  return -1;
3104  }
3105 
3106  return device_num;
3107 #else
3108  (void) device;
3109  if (error)
3110  *error = "Not compiled with ASI support.";
3111  return -1;
3112 #endif
3113 }
3114 
3116 {
3117 #ifdef USING_ASI
3118  // get the buffer size
3119  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "bufsize"));
3120  bool ok = false;
3121  uint buf_size = sys_bufsize_contents.toUInt(&ok);
3122  if (!ok)
3123  {
3124  if (error)
3125  {
3126  *error = QString("Failed to read buffer size from '%1'")
3127  .arg(sys_dev(device_num, "bufsize"));
3128  }
3129  return 0;
3130  }
3131  return buf_size;
3132 #else
3133  (void) device_num;
3134  if (error)
3135  *error = "Not compiled with ASI support.";
3136  return 0;
3137 #endif
3138 }
3139 
3141 {
3142 #ifdef USING_ASI
3143  // get the buffer size
3144  QString sys_numbuffers_contents = read_sys(sys_dev(device_num, "buffers"));
3145  bool ok = false;
3146  uint num_buffers = sys_numbuffers_contents.toUInt(&ok);
3147  if (!ok)
3148  {
3149  if (error)
3150  {
3151  *error = QString("Failed to read num buffers from '%1'")
3152  .arg(sys_dev(device_num, "buffers"));
3153  }
3154  return 0;
3155  }
3156  return num_buffers;
3157 #else
3158  (void) device_num;
3159  if (error)
3160  *error = "Not compiled with ASI support.";
3161  return 0;
3162 #endif
3163 }
3164 
3165 int CardUtil::GetASIMode(uint device_num, QString *error)
3166 {
3167 #ifdef USING_ASI
3168  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "mode"));
3169  bool ok = false;
3170  uint mode = sys_bufsize_contents.toUInt(&ok);
3171  if (!ok)
3172  {
3173  if (error)
3174  {
3175  *error = QString("Failed to read mode from '%1'")
3176  .arg(sys_dev(device_num, "mode"));
3177  }
3178  return -1;
3179  }
3180  return mode;
3181 #else
3182  (void) device_num;
3183  if (error)
3184  *error = "Not compiled with ASI support.";
3185  return -1;
3186 #endif
3187 }
3188 
3189 bool CardUtil::SetASIMode(uint device_num, uint mode, QString *error)
3190 {
3191 #ifdef USING_ASI
3192  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "mode"));
3193  bool ok = false;
3194  uint old_mode = sys_bufsize_contents.toUInt(&ok);
3195  if (ok && old_mode == mode)
3196  return true;
3197  ok = write_sys(sys_dev(device_num, "mode"), QString("%1\n").arg(mode));
3198  if (!ok && error)
3199  {
3200  *error = QString("Failed to set mode to %1 using '%2'")
3201  .arg(mode).arg(sys_dev(device_num, "mode"));
3202  }
3203  return ok;
3204 #else
3205  Q_UNUSED(device_num);
3206  Q_UNUSED(mode);
3207  if (error)
3208  *error = "Not compiled with ASI support.";
3209  return false;
3210 #endif
3211 }
3212 
3218 {
3219  // should only be called if inputtype == VBOX
3220  if (!inputid )
3221  {
3222  LOG(VB_GENERAL, LOG_ERR, QString("VBOX inputid (%1) not valid, redo mythtv-setup")
3223  .arg(inputid));
3224  return false;
3225  }
3226 
3227  // get sourceid and startchan from table capturecard for inputid
3228  uint chanid = 0;
3229  chanid = ChannelUtil::GetChannelValueInt("chanid",GetSourceID(inputid),GetStartingChannel(inputid));
3230  if (!chanid)
3231  {
3232  // no chanid, presume bad setup
3233  LOG(VB_GENERAL, LOG_ERR, QString("VBOX chanid (%1) not found for inputid (%2) , redo mythtv-setup")
3234  .arg(chanid).arg(inputid));
3235  return false;
3236  }
3237 
3238  // get timeouts for inputid
3239  uint signal_timeout = 0;
3240  uint tuning_timeout = 0;
3241  if (!GetTimeouts(inputid,signal_timeout,tuning_timeout))
3242  {
3243  LOG(VB_GENERAL, LOG_ERR, QString("Failed to get timeouts for inputid (%1)")
3244  .arg(inputid));
3245  return false;
3246  }
3247 
3248  signal_timeout = signal_timeout/1000; //convert to seconds
3249 
3250  // now get url from iptv_channel table
3251  QUrl url;
3253  query.prepare("SELECT url "
3254  "FROM iptv_channel "
3255  "WHERE chanid = :CHANID");
3256  query.bindValue(":CHANID", chanid);
3257 
3258  if (!query.exec())
3259  MythDB::DBError("CardUtil::IsVBoxPresent url", query);
3260  else if (query.next())
3261  url = query.value(0).toString();
3262 
3263  //now get just the IP address from the url
3264  QString ip = url.host();
3265  LOG(VB_GENERAL, LOG_INFO, QString("VBOX IP found (%1) for inputid (%2)")
3266  .arg(ip).arg(inputid));
3267 
3268  if (!ping(ip,signal_timeout))
3269  {
3270  LOG(VB_GENERAL, LOG_ERR, QString("VBOX at IP (%1) failed to respond to network ping for inputid (%2) timeout (%3)")
3271  .arg(ip).arg(inputid).arg(signal_timeout));
3272  return false;
3273  }
3274 
3275  return true;
3276 }
CardUtil::HDHRdoesDVBC
static bool HDHRdoesDVBC(const QString &device)
If the device is valid, check if the model does DVB-C.
Definition: cardutil.cpp:2903
VBox::checkVersion
bool checkVersion(QString &version)
Definition: vboxutils.cpp:210
manager
static MythSystemLegacyManager * manager
Definition: mythsystemunix.cpp:56
MSqlQuery::isActive
bool isActive(void) const
Definition: mythdbcon.h:204
CardUtil::s_videoDeviceCache
static QMap< QString, QStringList > s_videoDeviceCache
Definition: cardutil.h:456
CardUtil::GetScanableInputTypes
static QString GetScanableInputTypes(void)
Definition: cardutil.cpp:62
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
CardUtil::IsTunerShared
static bool IsTunerShared(uint inputidA, uint inputidB)
Definition: cardutil.cpp:248
CardUtil::SetDeliverySystem
static int SetDeliverySystem(uint inputid)
Definition: cardutil.cpp:1095
CardUtil::GetInputIDs
static std::vector< uint > GetInputIDs(const QString &videodevice=QString(), const QString &rawtype=QString(), const QString &inputname=QString(), QString hostname=QString())
Returns all inputids of inputs that uses the specified videodevice if specified, and optionally rawty...
Definition: cardutil.cpp:1271
CardUtil::GetVBoxdesc
static QString GetVBoxdesc(const QString &id, const QString &ip, const QString &tunerNo, const QString &tunerType)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2987
CardUtil::IsInNeedOfExternalInputConf
static bool IsInNeedOfExternalInputConf(uint inputid)
Definition: cardutil.cpp:2114
DiSEqCDevTree::IsInNeedOfConf
bool IsInNeedOfConf(void) const
Definition: diseqc.cpp:830
CardUtil::CreateCardInput
static int CreateCardInput(uint inputid, uint sourceid, const QString &inputname, const QString &externalcommand, const QString &changer_device, const QString &changer_model, const QString &hostname, const QString &tunechan, const QString &startchan, const QString &displayname, bool dishnet_eit, uint recpriority, uint quicktune, uint schedorder, uint livetvorder)
Definition: cardutil.cpp:1788
ENO
#define ENO
This can be appended to the LOG args with "+".
Definition: mythlogging.h:72
CardUtil::GetDisplayName
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1723
DTVTunerType::kTunerTypeDVBC
static const int kTunerTypeDVBC
Definition: dtvconfparserhelpers.h:95
VBox::checkConnection
bool checkConnection(void)
Definition: vboxutils.cpp:204
CardUtil::GetDeviceLabel
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
Definition: cardutil.cpp:2487
error
static void error(const char *str,...)
Definition: vbi.cpp:42
CardUtil::ProbeDeliverySystems
static QStringList ProbeDeliverySystems(const QString &device)
Definition: cardutil.cpp:574
mythdb.h
CardUtil::GetOrProbeDeliverySystem
static DTVModulationSystem GetOrProbeDeliverySystem(uint inputid, int fd)
Definition: cardutil.cpp:1045
DTVModulationSystem::kModulationSystem_DVBS2
@ kModulationSystem_DVBS2
Definition: dtvconfparserhelpers.h:660
CardUtil::GetVideoDevices
static QStringList GetVideoDevices(const QString &rawtype, QString hostname=QString())
Returns the videodevices of the matching inputs, duplicates removed.
Definition: cardutil.cpp:404
false
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
CardUtil::ClearVideoDeviceCache
static void ClearVideoDeviceCache()
Definition: cardutil.cpp:449
CardUtil::GetInputName
static QString GetInputName(uint inputid)
Definition: cardutil.cpp:1700
CardUtil::ProbeCurrentDeliverySystem
static DTVModulationSystem ProbeCurrentDeliverySystem(const QString &device)
Definition: cardutil.cpp:865
CardUtil::GetASIDeviceNumber
static int GetASIDeviceNumber(const QString &device, QString *error=nullptr)
Definition: cardutil.cpp:3059
V4L2util::DriverName
QString DriverName(void) const
Definition: v4l2util.h:48
CardUtil::DeleteAllInputs
static bool DeleteAllInputs(void)
Definition: cardutil.cpp:2687
DTVTunerType::kTunerTypeDVBS1
static const int kTunerTypeDVBS1
Definition: dtvconfparserhelpers.h:93
DVB_DEV_VIDEO
@ DVB_DEV_VIDEO
Definition: cardutil.h:33
CardUtil::SetStartChannel
static bool SetStartChannel(uint inputid, const QString &channum)
Definition: cardutil.cpp:1612
DTVModulationSystem::kModulationSystem_DTMB
@ kModulationSystem_DTMB
Definition: dtvconfparserhelpers.h:667
CardUtil::ProbeVideoInputs
static QStringList ProbeVideoInputs(const QString &device, const QString &inputtype=QString())
Definition: cardutil.cpp:2376
CardUtil::ProbeBestDeliverySystem
static DTVModulationSystem ProbeBestDeliverySystem(int fd)
Definition: cardutil.cpp:994
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
arg
arg(title).arg(filename).arg(doDelete))
CardUtil::HasDVBCRCBug
static bool HasDVBCRCBug(const QString &device)
Returns true if and only if the device munges PAT/PMT tables, and then doesn't fix the CRC.
Definition: cardutil.cpp:738
V4L2util::HasTuner
bool HasTuner(void) const
Definition: v4l2util.cpp:692
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
set_on_input
bool set_on_input(const QString &to_set, uint inputid, const QString &value)
Definition: cardutil.cpp:1241
VBOX_MIN_API_VERSION
#define VBOX_MIN_API_VERSION
Definition: vboxutils.h:14
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythDownloadManager
Definition: mythdownloadmanager.h:48
DVB_DEV_CA
@ DVB_DEV_CA
Definition: cardutil.h:31
DiSEqCDevSettings::Load
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:123
read_sys
static QString read_sys(const QString &sys_dev)
Definition: cardutil.cpp:3033
CardUtil::ProbeTunerType
static DTVTunerType ProbeTunerType(int fd_frontend)
Definition: cardutil.cpp:806
CardUtil::CloneCard
static uint CloneCard(uint src_inputid, uint dst_inputid)
Definition: cardutil.cpp:1516
CardUtil::IsUniqueDisplayName
static bool IsUniqueDisplayName(const QString &name, uint exclude_inputid)
Definition: cardutil.cpp:1745
dvbchannel.h
CardUtil::GetFirewireChangerModel
static QString GetFirewireChangerModel(uint inputid)
Definition: cardutil.cpp:1571
close
#define close
Definition: compat.h:17
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
CardUtil::ProbeSubTypeName
static QString ProbeSubTypeName(uint inputid)
Definition: cardutil.cpp:935
DTVModulationSystem::kModulationSystem_UNDEFINED
@ kModulationSystem_UNDEFINED
Definition: dtvconfparserhelpers.h:654
CardUtil::GetMinSignalMonitoringDelay
static uint GetMinSignalMonitoringDelay(const QString &device)
Definition: cardutil.cpp:745
CardUtil::ProbeDefaultDeliverySystem
static QString ProbeDefaultDeliverySystem(const QString &device)
Definition: cardutil.cpp:653
DTVTunerType
Definition: dtvconfparserhelpers.h:77
CardUtil::GetASINumBuffers
static uint GetASINumBuffers(uint device_num, QString *error=nullptr)
Definition: cardutil.cpp:3140
CardUtil::ProbeDVBType
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:671
satiputils.h
CardUtil::ProbeVideoDevices
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:455
DiSEqCDevSettings
DVB-S device settings class.
Definition: diseqc.h:37
CardUtil::SetDefaultDeliverySystem
static int SetDefaultDeliverySystem(uint inputid, int fd)
Definition: cardutil.cpp:1075
CardUtil::ProbeDVBFrontendName
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:692
CardUtil::GetASIBufferSize
static uint GetASIBufferSize(uint device_num, QString *error=nullptr)
Definition: cardutil.cpp:3115
CardUtil::GetInputGroups
static std::vector< uint > GetInputGroups(uint inputid)
Definition: cardutil.cpp:1998
sourceutil.h
CardUtil::UnlinkInputGroup
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1967
InputInfo::m_recPriority
int m_recPriority
Definition: inputinfo.h:53
CardUtil::GetTimeouts
static bool GetTimeouts(uint inputid, uint &signal_timeout, uint &channel_timeout)
Definition: cardutil.cpp:2092
CardUtil::GetAllInputInfo
static QList< InputInfo > GetAllInputInfo()
Definition: cardutil.cpp:1666
dvbtypes.h
mythlogging.h
CardUtil::GetInputList
static std::vector< uint > GetInputList(void)
Definition: cardutil.cpp:2697
SatIP::probeDevices
static QStringList probeDevices(void)
Definition: satiputils.cpp:21
InputInfo::m_liveTvOrder
uint m_liveTvOrder
order for live TV use
Definition: inputinfo.h:55
CardUtil::GetV4LInfo
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:2159
v4l2util.h
CardUtil::IsSingleInputType
static bool IsSingleInputType(const QString &rawtype)
Definition: cardutil.h:206
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_B
@ kModulationSystem_DVBC_ANNEX_B
Definition: dtvconfparserhelpers.h:656
CardUtil::CreateDeviceInputGroup
static uint CreateDeviceInputGroup(uint inputid, const QString &type, const QString &host, const QString &device)
Definition: cardutil.cpp:1890
CardUtil::ProbeDVBInputs
static QStringList ProbeDVBInputs(const QString &device)
Definition: cardutil.cpp:2467
DTVTunerType::kTunerTypeUnknown
static const int kTunerTypeUnknown
Definition: dtvconfparserhelpers.h:103
hardwareprofile.i18n.t
t
Definition: i18n.py:36
CardUtil::GetChildInputIDs
static std::vector< uint > GetChildInputIDs(uint inputid)
Definition: cardutil.cpp:1339
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:178
O_NONBLOCK
#define O_NONBLOCK
Definition: mythmedia.cpp:24
CardUtil::hasV4L2
static bool hasV4L2(int videofd)
Definition: cardutil.cpp:2146
DTVTunerType::toString
QString toString() const
Definition: dtvconfparserhelpers.h:154
vboxutils.h
CardUtil::ProbeV4LAudioInputs
static InputNames ProbeV4LAudioInputs(int videofd, bool &ok)
Definition: cardutil.cpp:2263
DiSEqCDevTree::Load
bool Load(const QString &device)
Loads the device tree from the database.
Definition: diseqc.cpp:306
CardUtil::GetDeliverySystemFromDB
static QString GetDeliverySystemFromDB(uint inputid)
Definition: cardutil.h:289
DVB_DEV_AUDIO
@ DVB_DEV_AUDIO
Definition: cardutil.h:32
CardUtil::HasTuner
static bool HasTuner(const QString &rawtype, const QString &device)
Definition: cardutil.cpp:222
DiSEqCDevTree::SetRoot
void SetRoot(DiSEqCDevDevice *root)
Changes the root node of the tree.
Definition: diseqc.cpp:629
dvb_dev_type_t
dvb_dev_type_t
Definition: cardutil.h:27
CardUtil::GetDeviceInputGroup
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1903
f
QTextStream t & f
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:603
CardUtil::IsDVBInputType
static bool IsDVBInputType(const QString &inputType)
Returns true iff the input_type is one of the DVB types.
Definition: cardutil.cpp:982
CardUtil::GetTunerType
static DTVTunerType GetTunerType(uint inputid)
Definition: cardutil.cpp:798
uint
unsigned int uint
Definition: compat.h:141
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:60
DiSEqCDev::FindTree
static DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:232
DiSEqCDevTree::Root
DiSEqCDevDevice * Root(void)
Retrieves the root node in the tree.
Definition: diseqc.h:93
DTVModulationSystem::kModulationSystem_ATSC
@ kModulationSystem_ATSC
Definition: dtvconfparserhelpers.h:665
CardUtil::GetFirewireChangerNode
static QString GetFirewireChangerNode(uint inputid)
Definition: cardutil.cpp:1554
ChannelUtil::GetChannelValueInt
static int GetChannelValueInt(const QString &channel_field, uint sourceid, const QString &channum)
Definition: channelutil.cpp:976
CardUtil::IsVBoxPresent
static bool IsVBoxPresent(uint inputid)
Returns true if the VBox responds to a ping.
Definition: cardutil.cpp:3217
InputInfo::m_inputId
uint m_inputId
unique key in DB for this input
Definition: inputinfo.h:49
DTVTunerType::kTunerTypeDVBS2
static const int kTunerTypeDVBS2
Definition: dtvconfparserhelpers.h:94
InputInfo::m_quickTune
bool m_quickTune
Definition: inputinfo.h:56
sys_dev
static QString sys_dev(uint device_num, const QString &dev)
Definition: cardutil.cpp:3028
DTVModulationSystem::toString
QString toString() const
Definition: dtvconfparserhelpers.h:717
CardUtil::GetQuickTuning
static uint GetQuickTuning(uint inputid, const QString &input_name)
Definition: cardutil.cpp:2125
LOC
#define LOC
Definition: cardutil.cpp:60
CardUtil::GetDeviceName
static QString GetDeviceName(dvb_dev_type_t type, const QString &device)
Definition: cardutil.cpp:2762
CardUtil::GetConfiguredDVBInputs
static InputNames GetConfiguredDVBInputs(const QString &device)
Definition: cardutil.cpp:2295
CardUtil::GetRawInputType
static QString GetRawInputType(uint inputid)
Definition: cardutil.h:281
InputInfo::m_scheduleOrder
uint m_scheduleOrder
Definition: inputinfo.h:54
CardUtil::IsInputTypePresent
static bool IsInputTypePresent(const QString &rawtype, QString hostname=QString())
Returns true if the input type is present and connected to an input.
Definition: cardutil.cpp:295
CardUtil::OpenVideoDevice
static int OpenVideoDevice(int inputid)
Definition: cardutil.cpp:1201
InputInfo::m_sourceId
uint m_sourceId
associated channel listings source
Definition: inputinfo.h:48
CardUtil::GetTunerTypeFromMultiplex
static DTVTunerType GetTunerTypeFromMultiplex(uint mplexid)
Definition: cardutil.cpp:822
clone_capturecard
static uint clone_capturecard(uint src_inputid, uint orig_dst_inputid)
Definition: cardutil.cpp:1367
V4L2util::IsOpen
bool IsOpen(void) const
Definition: v4l2util.h:29
CardUtil::IsCableCardPresent
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:111
DVB_DEV_DEMUX
@ DVB_DEV_DEMUX
Definition: cardutil.h:30
DiSEqCDevSettings::Store
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:157
mythmiscutil.h
V4L2util
Definition: v4l2util.h:17
CardUtil::InputTypes
QMap< QString, QString > InputTypes
Definition: cardutil.h:42
DTVModulationSystem
Definition: dtvconfparserhelpers.h:643
cardutil.h
dir
QDir dir
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:1174
CardUtil::CreateCaptureCard
static int CreateCaptureCard(const QString &videodevice, const QString &audiodevice, const QString &vbidevice, const QString &inputtype, uint audioratelimit, const QString &hostname, uint dvb_swfilter, uint dvb_sat_type, bool dvb_wait_for_seqstart, bool skipbtaudio, bool dvb_on_demand, uint dvb_diseqc_type, uint firewire_speed, const QString &firewire_model, uint firewire_connection, uint signal_timeout, uint channel_timeout, uint dvb_tuning_delay, uint contrast, uint brightness, uint colour, uint hue, uint diseqcid, bool dvb_eitscan)
Definition: cardutil.cpp:2523
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
VBox
Definition: vboxutils.h:17
CardUtil::GetInputTypes
static InputTypes GetInputTypes(void)
Definition: cardutil.cpp:329
CardUtil::AddChildInput
static uint AddChildInput(uint parentid)
Definition: cardutil.cpp:1526
CardUtil::GetChildInputCount
static uint GetChildInputCount(uint inputid)
Definition: cardutil.cpp:1315
CardUtil::HDHRdoesDVB
static bool HDHRdoesDVB(const QString &device)
If the device is valid, check if the model does DVB.
Definition: cardutil.cpp:2875
CardUtil::GetDeliverySystem
static DTVModulationSystem GetDeliverySystem(uint inputid)
Definition: cardutil.cpp:856
CardUtil::ProbeAudioInputs
static QStringList ProbeAudioInputs(const QString &device, const QString &inputtype=QString())
Definition: cardutil.cpp:2390
CardUtil::GetHDHRdesc
static QString GetHDHRdesc(const QString &device)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2931
CardUtil::GetSourceID
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1769
inputinfo.h
CardUtil::GetSchedInputList
static std::vector< uint > GetSchedInputList(void)
Definition: cardutil.cpp:2718
InputInfo
Definition: inputinfo.h:15
VBox::probeDevices
static QStringList probeDevices(void)
Definition: vboxutils.cpp:27
CardUtil::IsTunerSharingCapable
static bool IsTunerSharingCapable(const QString &rawtype)
Definition: cardutil.h:171
DiSEqCDevTree
DVB-S device tree class.
Definition: diseqc.h:75
get_on_input
QString get_on_input(const QString &to_get, uint inputid)
Definition: cardutil.cpp:1224
CardUtil::GetInputTypeNames
static QStringList GetInputTypeNames(uint sourceid)
Get a list of card input types for a source id.
Definition: cardutil.cpp:376
CardUtil::ConvertToTunerType
static DTVTunerType ConvertToTunerType(DTVModulationSystem delsys)
Definition: cardutil.cpp:755
DTVTunerType::kTunerTypeATSC
static const int kTunerTypeATSC
Definition: dtvconfparserhelpers.h:98
CardUtil::GetInputInfo
static bool GetInputInfo(InputInfo &input, std::vector< uint > *groupids=nullptr)
Definition: cardutil.cpp:1630
InputNames
QMap< int, QString > InputNames
Definition: cardutil.h:20
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:859
DVB_DEV_FRONTEND
@ DVB_DEV_FRONTEND
Definition: cardutil.h:28
DiSEqCDevTree::Store
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:417
CardUtil::ProbeV4LVideoInputs
static InputNames ProbeV4LVideoInputs(int videofd, bool &ok)
Definition: cardutil.cpp:2197
musicbrainzngs.caa.hostname
string hostname
Definition: caa.py:17
DiSEqCDevDevice::GetDeviceID
uint GetDeviceID(void) const
Definition: diseqc.h:170
DTVModulationSystem::kModulationSystem_DVBT2
@ kModulationSystem_DVBT2
Definition: dtvconfparserhelpers.h:670
DTVTunerType::kTunerTypeDVBT
static const int kTunerTypeDVBT
Definition: dtvconfparserhelpers.h:96
CardUtil::GetLiveTVInputList
static std::vector< uint > GetLiveTVInputList(void)
Definition: cardutil.cpp:2740
CardUtil::CapabilitiesToString
static QStringList CapabilitiesToString(uint64_t capabilities)
Definition: cardutil.cpp:2323
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_C
@ kModulationSystem_DVBC_ANNEX_C
Definition: dtvconfparserhelpers.h:672
mythdownloadmanager.h
CardUtil::GetDeviceInputNames
static void GetDeviceInputNames(const QString &device, const QString &inputtype, QStringList &inputs)
Definition: cardutil.cpp:2509
DVB_DEV_DVR
@ DVB_DEV_DVR
Definition: cardutil.h:29
CardUtil::GetConflictingInputs
static std::vector< uint > GetConflictingInputs(uint inputid)
Definition: cardutil.cpp:2051
V4L2util::CardName
QString CardName(void) const
Definition: v4l2util.h:49
DTVTunerType::kTunerTypeDVBT2
static const int kTunerTypeDVBT2
Definition: dtvconfparserhelpers.h:97
CardUtil::GetGroupInputIDs
static std::vector< uint > GetGroupInputIDs(uint inputgroupid)
Definition: cardutil.cpp:2024
CardUtil::GetStartingChannel
static QString GetStartingChannel(uint inputid)
Definition: cardutil.cpp:1707
query
MSqlQuery query(MSqlQuery::InitCon())
nv_python_libs.bbciplayer.bbciplayer_api.version
string version
Definition: bbciplayer_api.py:81
InputInfo::m_displayName
QString m_displayName
Definition: inputinfo.h:52
CardUtil::CreateInputGroup
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:1848
CardUtil::LinkInputGroup
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1927
DTVModulationSystem::kModulationSystem_DVBS
@ kModulationSystem_DVBS
Definition: dtvconfparserhelpers.h:659
videosource.h
DTVModulationSystem::kModulationSystem_DVBT
@ kModulationSystem_DVBT
Definition: dtvconfparserhelpers.h:657
diseqcsettings.h
CardUtil::SetASIMode
static bool SetASIMode(uint device_num, uint mode, QString *error=nullptr)
Definition: cardutil.cpp:3189
CardUtil::GetVideoDevice
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:283
ping
bool ping(const QString &host, int timeout)
Can we ping host within timeout seconds?
Definition: mythmiscutil.cpp:247
DTVModulationSystem::kModulationSystem_DVBC_ANNEX_A
@ kModulationSystem_DVBC_ANNEX_A
Definition: dtvconfparserhelpers.h:655
InputInfo::m_name
QString m_name
input name
Definition: inputinfo.h:47
GetMythDownloadManager
MythDownloadManager * GetMythDownloadManager(void)
Gets the pointer to the MythDownloadManager singleton.
Definition: mythdownloadmanager.cpp:145
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808
write_sys
static bool write_sys(const QString &sys_dev, const QString &str)
Definition: cardutil.cpp:3042
DTVModulationSystem::Parse
bool Parse(const QString &_value)
Definition: dtvconfparserhelpers.h:714
CardUtil::GetASIMode
static int GetASIMode(uint device_num, QString *error=nullptr)
Definition: cardutil.cpp:3165
CardUtil::DeleteInput
static bool DeleteInput(uint inputid)
Definition: cardutil.cpp:2617