MythTV  0.28pre
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 
26 #ifdef USING_DVB
27 #include "dvbtypes.h"
28 #endif
29 
30 #ifdef USING_V4L1
31 #include <linux/videodev.h>
32 #endif
33 
34 #ifdef USING_V4L2
35 #include "v4l2util.h"
36 #endif
37 
38 #ifdef USING_HDHOMERUN
39 #include "hdhomerun.h"
40 #endif
41 
42 #ifdef USING_VBOX
43 #include "vboxutils.h"
44 #endif
45 
46 #ifdef USING_ASI
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <dveo/asi.h>
50 #include <dveo/master.h>
51 #endif
52 
53 #define LOC QString("CardUtil: ")
54 
56 {
57  QString inputTypes = "";
58 
59 #ifdef USING_DVB
60  inputTypes += "'DVB'";
61 #endif // USING_DVB
62 
63 #ifdef USING_V4L2
64  if (!inputTypes.isEmpty())
65  inputTypes += ",";
66  inputTypes += "'V4L'";
67 # ifdef USING_IVTV
68  inputTypes += ",'MPEG'";
69 # endif // USING_IVTV
70 #endif // USING_V4L2
71 
72 #ifdef USING_IPTV
73  if (!inputTypes.isEmpty())
74  inputTypes += ",";
75  inputTypes += "'FREEBOX'";
76 #endif // USING_IPTV
77 
78 #ifdef USING_VBOX
79  if (!inputTypes.isEmpty())
80  inputTypes += ",";
81  inputTypes += "'VBOX'";
82 #endif // USING_VBOX
83 
84 #ifdef USING_HDHOMERUN
85  if (!inputTypes.isEmpty())
86  inputTypes += ",";
87  inputTypes += "'HDHOMERUN'";
88 #endif // USING_HDHOMERUN
89 
90 #ifdef USING_ASI
91  if (!inputTypes.isEmpty())
92  inputTypes += ",";
93  inputTypes += "'ASI'";
94 #endif
95 
96 #ifdef USING_CETON
97  if (!inputTypes.isEmpty())
98  inputTypes += ",";
99  inputTypes += "'CETON'";
100 #endif // USING_CETON
101 
102 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
103  if (!inputTypes.isEmpty())
104  inputTypes += ",";
105  inputTypes += "'EXTERNAL'";
106 #endif
107 
108  if (inputTypes.isEmpty())
109  inputTypes = "'DUMMY'";
110 
111  return QString("(%1)").arg(inputTypes);
112 }
113 
115  const QString &inputType)
116 {
117  if (inputType == "HDHOMERUN")
118  {
119 #ifdef USING_HDHOMERUN
120  hdhomerun_device_t *hdhr;
121  hdhomerun_tuner_status_t status;
122  QString device = GetVideoDevice(inputid);
123  hdhr = hdhomerun_device_create_from_str(device.toLatin1(), NULL);
124  if (!hdhr)
125  return false;
126 
127  int oob = -1;
128  oob = hdhomerun_device_get_oob_status(hdhr, NULL, &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  else if (inputType == "CETON")
145  {
146 #ifdef USING_CETON
147  // TODO FIXME implement detection of Cablecard presence
148  LOG(VB_GENERAL, LOG_INFO, "Cardutil: TODO Ceton Is Cablecard Present?");
149  return true;
150 #else
151  return false;
152 #endif
153  }
154  else
155  return false;
156 }
157 
158 bool CardUtil::HasTuner(const QString &rawtype, const QString & device)
159 {
160  if (rawtype == "DVB" || rawtype == "HDHOMERUN" ||
161  rawtype == "FREEBOX" || rawtype == "CETON")
162  return true;
163 
164 #ifdef USING_V4L2
165  if (rawtype == "V4L2ENC")
166  {
167  V4L2util v4l2(device);
168  return !v4l2 ? false : v4l2.HasTuner();
169  }
170 #endif
171 
172  if (rawtype == "EXTERNAL")
173  {
174  // TODO: query EXTERNAL for capability
175  return true;
176  }
177 
178  return false;
179 }
180 
181 bool CardUtil::IsTunerShared(uint inputidA, uint inputidB)
182 {
183  LOG(VB_GENERAL, LOG_DEBUG, QString("IsTunerShared(%1,%2)")
184  .arg(inputidA).arg(inputidB));
185 
186  MSqlQuery query(MSqlQuery::InitCon());
187  query.prepare("SELECT videodevice, hostname, cardtype "
188  "FROM capturecard "
189  "WHERE ( (cardid = :INPUTID_A) OR "
190  " (cardid = :INPUTID_B) )");
191  query.bindValue(":INPUTID_A", inputidA);
192  query.bindValue(":INPUTID_B", inputidB);
193 
194  if (!query.exec())
195  {
196  MythDB::DBError("CardUtil::is_tuner_shared", query);
197  return false;
198  }
199 
200  if (!query.next())
201  return false;
202 
203  const QString vdevice = query.value(0).toString();
204  const QString hostname = query.value(1).toString();
205  const QString inputtype = query.value(2).toString();
206 
207  if (!IsTunerSharingCapable(inputtype.toUpper()))
208  return false;
209 
210  if (!query.next())
211  return false;
212 
213  bool ret = ((vdevice == query.value(0).toString()) &&
214  (hostname == query.value(1).toString()) &&
215  (inputtype == query.value(2).toString()));
216 
217  LOG(VB_RECORD, LOG_DEBUG, QString("IsTunerShared(%1,%2) -> %3")
218  .arg(inputidA).arg(inputidB).arg(ret));
219 
220  return ret;
221 }
222 
228 bool CardUtil::IsInputTypePresent(const QString &rawtype, QString hostname)
229 {
230  if (hostname.isEmpty())
231  hostname = gCoreContext->GetHostName();
232 
233  MSqlQuery query(MSqlQuery::InitCon());
234  QString qstr =
235  "SELECT count(cardtype) "
236  "FROM capturecard "
237  "WHERE capturecard.hostname = :HOSTNAME ";
238 
239  if (!rawtype.isEmpty())
240  qstr += " AND capturecard.cardtype = :INPUTTYPE";
241 
242  query.prepare(qstr);
243 
244  if (!rawtype.isEmpty())
245  query.bindValue(":INPUTTYPE", rawtype.toUpper());
246 
247  query.bindValue(":HOSTNAME", hostname);
248 
249  if (!query.exec())
250  {
251  MythDB::DBError("CardUtil::IsInputTypePresent", query);
252  return false;
253  }
254 
255  uint count = 0;
256  if (query.next())
257  count = query.value(0).toUInt();
258 
259  return count > 0;
260 }
261 
263 {
264  InputTypes inputtypes;
265 
266  MSqlQuery query(MSqlQuery::InitCon());
267  query.prepare("SELECT DISTINCT cardtype, videodevice "
268  "FROM capturecard");
269 
270  if (!query.exec())
271  {
272  MythDB::DBError("CardUtil::GetInputTypes()", query);
273  }
274  else
275  {
276  QString cardtype;
277 
278  while (query.next())
279  {
280  cardtype = query.value(0).toString();
281  if (cardtype != "V4L2ENC")
282  inputtypes[cardtype] = "";
283 #ifdef USING_V4L2
284  else
285  {
286  V4L2util v4l2(query.value(1).toString());
287  if (v4l2.IsOpen())
288  {
289  QString driver_name = "V4L2:" + v4l2.DriverName();
290  inputtypes[driver_name] = v4l2.CardName();
291  }
292  }
293 #endif
294  }
295  }
296 
297  return inputtypes;
298 }
299 
305 QStringList CardUtil::GetVideoDevices(const QString &rawtype, QString hostname)
306 {
307  QStringList list;
308 
309  if (hostname.isEmpty())
310  hostname = gCoreContext->GetHostName();
311 
312  MSqlQuery query(MSqlQuery::InitCon());
313  QString qstr =
314  "SELECT videodevice "
315  "FROM capturecard "
316  "WHERE hostname = :HOSTNAME";
317 
318  if (!rawtype.isEmpty())
319  qstr += " AND cardtype = :INPUTTYPE";
320 
321  query.prepare(qstr);
322 
323  if (!rawtype.isEmpty())
324  query.bindValue(":INPUTTYPE", rawtype.toUpper());
325 
326  query.bindValue(":HOSTNAME", hostname);
327 
328  if (!query.exec())
329  {
330  MythDB::DBError("CardUtil::GetVideoDevices", query);
331  return list;
332  }
333 
334  QMap<QString,bool> dup;
335  while (query.next())
336  {
337  QString videodevice = query.value(0).toString();
338  if (dup[videodevice])
339  continue;
340 
341  list.push_back(videodevice);
342  dup[videodevice] = true;
343  }
344 
345  return list;
346 }
347 
348 QStringList CardUtil::ProbeVideoDevices(const QString &rawtype)
349 {
350  QStringList devs;
351 
352  if (rawtype.toUpper() == "DVB")
353  {
354  QDir dir("/dev/dvb", "adapter*", QDir::Name, QDir::Dirs);
355  const QFileInfoList il = dir.entryInfoList();
356  if (il.isEmpty())
357  return devs;
358 
359  QFileInfoList::const_iterator it = il.begin();
360 
361  for (; it != il.end(); ++it)
362  {
363  QDir subdir(it->filePath(), "frontend*", QDir::Name, QDir::Files | QDir::System);
364  const QFileInfoList subil = subdir.entryInfoList();
365  if (subil.isEmpty())
366  continue;
367 
368  QFileInfoList::const_iterator subit = subil.begin();
369  for (; subit != subil.end(); ++subit)
370  devs.push_back(subit->filePath());
371  }
372  }
373  else if (rawtype.toUpper() == "ASI")
374  {
375  QDir dir("/dev/", "asirx*", QDir::Name, QDir::System);
376  const QFileInfoList il = dir.entryInfoList();
377  if (il.isEmpty())
378  return devs;
379 
380  QFileInfoList::const_iterator it = il.begin();
381  for (; it != il.end(); ++it)
382  {
383  if (GetASIDeviceNumber(it->filePath()) >= 0)
384  {
385  devs.push_back(it->filePath());
386  continue;
387  }
388  break;
389  }
390  }
391 #ifdef USING_HDHOMERUN
392  else if (rawtype.toUpper() == "HDHOMERUN")
393  {
394  uint32_t target_ip = 0;
395  uint32_t device_type = HDHOMERUN_DEVICE_TYPE_TUNER;
396  uint32_t device_id = HDHOMERUN_DEVICE_ID_WILDCARD;
397  const int max_count = 50;
398  hdhomerun_discover_device_t result_list[max_count];
399 
400  int result = hdhomerun_discover_find_devices_custom(
401  target_ip, device_type, device_id, result_list, max_count);
402 
403  if (result == -1)
404  {
405  LOG(VB_GENERAL, LOG_ERR, "Error finding HDHomerun devices");
406  return devs;
407  }
408 
409  if (result >= max_count)
410  {
411  LOG(VB_GENERAL, LOG_WARNING,
412  "Warning: may be > 50 HDHomerun devices");
413  }
414 
415  // Return "deviceid ipaddress" pairs
416  for (int i = 0; i < result; i++)
417  {
418  QString id = QString("%1").arg(result_list[i].device_id, 0, 16);
419  QString ip = QString("%1.%2.%3.%4")
420  .arg((result_list[i].ip_addr>>24) & 0xFF)
421  .arg((result_list[i].ip_addr>>16) & 0xFF)
422  .arg((result_list[i].ip_addr>> 8) & 0xFF)
423  .arg((result_list[i].ip_addr>> 0) & 0xFF);
424 
425  for (int tuner = 0; tuner < result_list[i].tuner_count; tuner++)
426  {
427  QString hdhrdev = id.toUpper() + " " + ip + " " +
428  QString("%1").arg(tuner);
429  devs.push_back(hdhrdev);
430  }
431  }
432  }
433 #endif // USING_HDHOMERUN
434 #ifdef USING_VBOX
435  else if (rawtype.toUpper() == "VBOX")
436  {
437  devs = VBox::probeDevices();
438  }
439 #endif // USING_VBOX
440 #ifdef USING_CETON
441  else if (rawtype.toUpper() == "CETON")
442  {
443  // TODO implement CETON probing.
444  LOG(VB_GENERAL, LOG_INFO, "CardUtil::ProbeVideoDevices: "
445  "TODO Probe Ceton devices");
446  }
447 #endif // USING_CETON
448  else
449  {
450  LOG(VB_GENERAL, LOG_ERR, QString("Raw Type: '%1' is not supported")
451  .arg(rawtype));
452  }
453 
454  return devs;
455 }
456 
457 QString CardUtil::ProbeDVBType(const QString &device)
458 {
459  QString ret = "ERROR_UNKNOWN";
460 
461  if (device.isEmpty())
462  return ret;
463 
464 #ifdef USING_DVB
465  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_FRONTEND, device);
466  QByteArray dev = dvbdev.toLatin1();
467 
468  int fd_frontend = open(dev.constData(), O_RDWR | O_NONBLOCK);
469  if (fd_frontend < 0)
470  {
471  LOG(VB_GENERAL, LOG_ERR, QString("Can't open DVB frontend (%1) for %2.")
472  .arg(dvbdev).arg(device));
473  return ret;
474  }
475 
476  struct dvb_frontend_info info;
477  memset(&info, 0, sizeof(info));
478  int err = ioctl(fd_frontend, FE_GET_INFO, &info);
479  if (err < 0)
480  {
481  close(fd_frontend);
482  LOG(VB_GENERAL, LOG_ERR, QString("FE_GET_INFO ioctl failed (%1)")
483  .arg(dvbdev) + ENO);
484  return ret;
485  }
486  close(fd_frontend);
487 
488  DTVTunerType type(info.type);
489 #if HAVE_FE_CAN_2G_MODULATION
490  if (info.caps & FE_CAN_2G_MODULATION)
491  {
492  if (type == DTVTunerType::kTunerTypeDVBS1)
494  else if (type == DTVTunerType::kTunerTypeDVBT)
496  }
497 #endif // HAVE_FE_CAN_2G_MODULATION
498  ret = (type.toString() != "UNKNOWN") ? type.toString().toUpper() : ret;
499 #endif // USING_DVB
500 
501  return ret;
502 }
503 
507 QString CardUtil::ProbeDVBFrontendName(const QString &device)
508 {
509  QString ret = "ERROR_UNKNOWN";
510  (void) device;
511 
512 #ifdef USING_DVB
513  QString dvbdev = CardUtil::GetDeviceName(DVB_DEV_FRONTEND, device);
514  QByteArray dev = dvbdev.toLatin1();
515  int fd_frontend = open(dev.constData(), O_RDWR | O_NONBLOCK);
516  if (fd_frontend < 0)
517  return "ERROR_OPEN";
518 
519  struct dvb_frontend_info info;
520  memset(&info, 0, sizeof(info));
521  int err = ioctl(fd_frontend, FE_GET_INFO, &info);
522  if (err < 0)
523  {
524  close(fd_frontend);
525  return "ERROR_PROBE";
526  }
527 
528  ret = info.name;
529 
530  close(fd_frontend);
531 #endif // USING_DVB
532 
533  return ret;
534 }
535 
553 bool CardUtil::HasDVBCRCBug(const QString &device)
554 {
555  QString name = ProbeDVBFrontendName(device);
556  return ((name == "VLSI VES1x93 DVB-S") || // munges PMT
557  (name == "ST STV0299 DVB-S")); // munges PAT
558 }
559 
561 {
562  QString name = ProbeDVBFrontendName(device);
563  if (name.indexOf("DVB-S") >= 0)
564  return 300;
565  if (name == "DiBcom 3000P/M-C DVB-T")
566  return 100;
567  return 25;
568 }
569 
571 {
572  QString type = GetRawInputType(inputid);
573  if ("DVB" != type)
574  return type;
575 
576  QString device = GetVideoDevice(inputid);
577 
578  if (device.isEmpty())
579  return "ERROR_OPEN";
580 
581  return ProbeDVBType(device);
582 }
583 
585 bool CardUtil::IsDVBInputType(const QString &inputType)
586 {
587  QString t = inputType.toUpper();
588  return (t == "DVB") || (t == "QAM") || (t == "QPSK") ||
589  (t == "OFDM") || (t == "ATSC") || (t == "DVB_S2");
590 }
591 
592 QString get_on_input(const QString &to_get, uint inputid)
593 {
594  MSqlQuery query(MSqlQuery::InitCon());
595  query.prepare(
596  QString("SELECT %1 ").arg(to_get) +
597  "FROM capturecard "
598  "WHERE capturecard.cardid = :INPUTID");
599  query.bindValue(":INPUTID", inputid);
600 
601  if (!query.exec())
602  MythDB::DBError("CardUtil::get_on_source", query);
603  else if (query.next())
604  return query.value(0).toString();
605 
606  return QString::null;
607 }
608 
609 bool set_on_input(const QString &to_set, uint inputid, const QString &value)
610 {
611  QString tmp = get_on_input("capturecard.cardid", inputid);
612  if (tmp.isEmpty())
613  return false;
614 
615  MSqlQuery query(MSqlQuery::InitCon());
616  query.prepare(
617  QString("UPDATE capturecard SET %1 = :VALUE ").arg(to_set) +
618  "WHERE cardid = :INPUTID");
619  query.bindValue(":INPUTID", inputid);
620  query.bindValue(":VALUE", value);
621 
622  if (query.exec())
623  return true;
624 
625  MythDB::DBError("CardUtil::set_on_input", query);
626  return false;
627 }
628 
638 vector<uint> CardUtil::GetInputIDs(QString videodevice,
639  QString rawtype,
640  QString inputname,
641  QString hostname)
642 {
643  vector<uint> list;
644 
645  if (hostname.isEmpty())
646  hostname = gCoreContext->GetHostName();
647 
648  MSqlQuery query(MSqlQuery::InitCon());
649  QString qstr =
650  "SELECT cardid "
651  "FROM capturecard "
652  "WHERE hostname = :HOSTNAME ";
653  if (!videodevice.isEmpty())
654  qstr += "AND videodevice = :DEVICE ";
655  if (!inputname.isEmpty())
656  qstr += "AND inputname = :INPUTNAME ";
657  if (!rawtype.isEmpty())
658  qstr += "AND cardtype = :INPUTTYPE ";
659  qstr += "ORDER BY cardid";
660 
661  query.prepare(qstr);
662 
663  query.bindValue(":HOSTNAME", hostname);
664  if (!videodevice.isEmpty())
665  query.bindValue(":DEVICE", videodevice);
666  if (!inputname.isEmpty())
667  query.bindValue(":INPUTNAME", inputname);
668  if (!rawtype.isEmpty())
669  query.bindValue(":INPUTTYPE", rawtype.toUpper());
670 
671  if (!query.exec())
672  MythDB::DBError("CardUtil::GetInputIDs(videodevice...)", query);
673  else
674  {
675  while (query.next())
676  list.push_back(query.value(0).toUInt());
677  }
678 
679  return list;
680 }
681 
683 {
684  if (!inputid)
685  return 0;
686 
687  MSqlQuery query(MSqlQuery::InitCon());
688  QString qstr =
689  "SELECT COUNT(*) "
690  "FROM capturecard "
691  "WHERE parentid = :INPUTID";
692 
693  query.prepare(qstr);
694  query.bindValue(":INPUTID", inputid);
695 
696  uint count = 0;
697 
698  if (!query.exec())
699  MythDB::DBError("CardUtil::GetChildInputCount()", query);
700  else if (query.next())
701  count = query.value(0).toUInt();
702 
703  return count;
704 }
705 
706 vector<uint> CardUtil::GetChildInputIDs(uint inputid)
707 {
708  vector<uint> list;
709 
710  if (!inputid)
711  return list;
712 
713  MSqlQuery query(MSqlQuery::InitCon());
714  QString qstr =
715  "SELECT cardid "
716  "FROM capturecard "
717  "WHERE parentid = :INPUTID "
718  "ORDER BY cardid";
719 
720  query.prepare(qstr);
721  query.bindValue(":INPUTID", inputid);
722 
723  if (!query.exec())
724  MythDB::DBError("CardUtil::GetChildInputIDs()", query);
725  else
726  {
727  while (query.next())
728  list.push_back(query.value(0).toUInt());
729  }
730 
731  return list;
732 }
733 
734 static uint clone_capturecard(uint src_inputid, uint orig_dst_inputid)
735 {
736  uint dst_inputid = orig_dst_inputid;
737 
738  MSqlQuery query(MSqlQuery::InitCon());
739  if (!dst_inputid)
740  {
741  query.prepare(
742  "DELETE FROM capturecard "
743  "WHERE videodevice = 'temp_dummy'");
744 
745  if (!query.exec())
746  {
747  MythDB::DBError("clone_capturecard -- delete temp", query);
748  return 0;
749  }
750 
751  query.prepare(
752  "INSERT INTO capturecard "
753  "SET videodevice = 'temp_dummy'");
754 
755  if (!query.exec())
756  {
757  MythDB::DBError("clone_capturecard -- insert temp", query);
758  return 0;
759  }
760 
761  query.prepare(
762  "SELECT cardid "
763  "FROM capturecard "
764  "WHERE videodevice = 'temp_dummy'");
765 
766  if (!query.exec())
767  {
768  MythDB::DBError("clone_capturecard -- get temp id", query);
769  return 0;
770  }
771 
772  if (!query.next())
773  {
774  LOG(VB_GENERAL, LOG_ERR, "clone_capturecard -- get temp id");
775  return 0;
776  }
777 
778  dst_inputid = query.value(0).toUInt();
779  }
780 
781  query.prepare(
782  "SELECT videodevice, audiodevice, vbidevice, "
783  " cardtype, hostname, signal_timeout, "
784  " channel_timeout, dvb_wait_for_seqstart, dvb_on_demand, "
785  " dvb_tuning_delay, dvb_diseqc_type, diseqcid, "
786  " dvb_eitscan, inputname, sourceid, "
787  " externalcommand, changer_device, changer_model, "
788  " tunechan, startchan, displayname, "
789  " dishnet_eit, recpriority, quicktune, "
790  " schedorder, livetvorder "
791  "FROM capturecard "
792  "WHERE cardid = :INPUTID");
793  query.bindValue(":INPUTID", src_inputid);
794 
795  if (!query.exec())
796  {
797  MythDB::DBError("clone_capturecard -- get data", query);
798  return 0;
799  }
800  if (!query.next())
801  {
802  LOG(VB_GENERAL, LOG_ERR, "clone_cardinput -- get data 2");
803  return 0;
804  }
805 
806  MSqlQuery query2(MSqlQuery::InitCon());
807  query2.prepare(
808  "UPDATE capturecard "
809  "SET videodevice = :V0, "
810  " audiodevice = :V1, "
811  " vbidevice = :V2, "
812  " cardtype = :V3, "
813  " hostname = :V4, "
814  " signal_timeout = :V5, "
815  " channel_timeout = :V6, "
816  " dvb_wait_for_seqstart = :V7, "
817  " dvb_on_demand = :V8, "
818  " dvb_tuning_delay = :V9, "
819  " dvb_diseqc_type = :V10, "
820  " diseqcid = :V11,"
821  " dvb_eitscan = :V12, "
822  " inputname = :V13, "
823  " sourceid = :V14, "
824  " externalcommand = :V15, "
825  " changer_device = :V16, "
826  " changer_model = :V17, "
827  " tunechan = :V18, "
828  " startchan = :V19, "
829  " displayname = :V20, "
830  " dishnet_eit = :V21, "
831  " recpriority = :V22, "
832  " quicktune = :V23, "
833  " schedorder = :V24, "
834  " livetvorder = :V25, "
835  " parentid = :PARENTID "
836  "WHERE cardid = :INPUTID");
837  for (uint i = 0; i < 26; ++i)
838  query2.bindValue(QString(":V%1").arg(i), query.value(i).toString());
839  query2.bindValue(":INPUTID", dst_inputid);
840  query2.bindValue(":PARENTID", src_inputid);
841 
842  if (!query2.exec())
843  {
844  MythDB::DBError("clone_capturecard -- save data", query2);
845  if (!orig_dst_inputid)
846  CardUtil::DeleteCard(dst_inputid);
847  return 0;
848  }
849 
850  // copy input group linkages
851  vector<uint> src_grps = CardUtil::GetInputGroups(src_inputid);
852  vector<uint> dst_grps = CardUtil::GetInputGroups(dst_inputid);
853  for (uint j = 0; j < dst_grps.size(); j++)
854  CardUtil::UnlinkInputGroup(dst_inputid, dst_grps[j]);
855  for (uint j = 0; j < src_grps.size(); j++)
856  CardUtil::LinkInputGroup(dst_inputid, src_grps[j]);
857 
858  // clone diseqc_config (just points to the same diseqc_tree row)
859  DiSEqCDevSettings diseqc;
860  if (diseqc.Load(src_inputid))
861  diseqc.Store(dst_inputid);
862 
863  return dst_inputid;
864 }
865 
866 bool CardUtil::CloneCard(uint src_inputid, uint orig_dst_inputid)
867 {
868  QString type = CardUtil::GetRawInputType(src_inputid);
869  if (!IsTunerSharingCapable(type))
870  return false;
871 
872  uint dst_inputid = clone_capturecard(src_inputid, orig_dst_inputid);
873  if (!dst_inputid)
874  return false;
875 
876  return true;
877 }
878 
880 {
881  QString fwnode;
882 
883  MSqlQuery query(MSqlQuery::InitCon());
884  query.prepare("SELECT changer_device "
885  "FROM capturecard WHERE cardid = :INPUTID ");
886  query.bindValue(":INPUTID", inputid);
887 
888  if (query.exec() && query.next())
889  {
890  fwnode = query.value(0).toString();
891  }
892 
893  return fwnode;
894 }
895 
897 {
898  QString fwnode;
899 
900  MSqlQuery query(MSqlQuery::InitCon());
901  query.prepare("SELECT changer_model "
902  "FROM capturecard WHERE cardid = :INPUTID ");
903  query.bindValue(":INPUTID", inputid);
904 
905  if (query.exec() && query.next())
906  {
907  fwnode = query.value(0).toString();
908  }
909 
910  return fwnode;
911 }
912 
913 vector<uint> CardUtil::GetInputIDs(uint sourceid)
914 {
915  MSqlQuery query(MSqlQuery::InitCon());
916 
917  query.prepare(
918  "SELECT DISTINCT cardid "
919  "FROM capturecard "
920  "WHERE sourceid = :SOURCEID");
921  query.bindValue(":SOURCEID", sourceid);
922 
923  vector<uint> list;
924 
925  if (!query.exec())
926  {
927  MythDB::DBError("CardUtil::GetInputIDs()", query);
928  return list;
929  }
930 
931  while (query.next())
932  list.push_back(query.value(0).toUInt());
933 
934  return list;
935 }
936 
937 bool CardUtil::SetStartChannel(uint inputid, const QString &channum)
938 {
939  MSqlQuery query(MSqlQuery::InitCon());
940  query.prepare("UPDATE capturecard "
941  "SET startchan = :CHANNUM "
942  "WHERE cardid = :INPUTID");
943  query.bindValue(":CHANNUM", channum);
944  query.bindValue(":INPUTID", inputid);
945 
946  if (!query.exec())
947  {
948  MythDB::DBError("set_startchan", query);
949  return false;
950  }
951 
952  return true;
953 }
954 
955 bool CardUtil::GetInputInfo(InputInfo &input, vector<uint> *groupids)
956 {
957  if (!input.inputid)
958  return false;
959 
960  MSqlQuery query(MSqlQuery::InitCon());
961  query.prepare("SELECT "
962  "inputname, sourceid, livetvorder, "
963  "schedorder, displayname, recpriority, quicktune "
964  "FROM capturecard "
965  "WHERE cardid = :INPUTID");
966  query.bindValue(":INPUTID", input.inputid);
967 
968  if (!query.exec())
969  {
970  MythDB::DBError("CardUtil::GetInputInfo()", query);
971  return false;
972  }
973 
974  if (!query.next())
975  return false;
976 
977  input.name = query.value(0).toString();
978  input.sourceid = query.value(1).toUInt();
979  input.livetvorder = query.value(2).toUInt();
980  input.scheduleOrder = query.value(3).toUInt();
981  input.displayName = query.value(4).toString();
982  input.recPriority = query.value(5).toInt();
983  input.quickTune = query.value(6).toBool();
984 
985  if (input.displayName.isEmpty())
986  input.displayName = QObject::tr("Input %1:%2")
987  .arg(input.inputid).arg(input.name);
988 
989  if (groupids)
990  *groupids = GetInputGroups(input.inputid);
991 
992  return true;
993 }
994 
995 QList<InputInfo> CardUtil::GetAllInputInfo()
996 {
997  QList<InputInfo> infoInputList;
998 
999  MSqlQuery query(MSqlQuery::InitCon());
1000  query.prepare("SELECT cardid, "
1001  "inputname, sourceid, livetvorder, "
1002  "schedorder, displayname, recpriority, quicktune "
1003  "FROM capturecard");
1004 
1005  if (!query.exec())
1006  {
1007  MythDB::DBError("CardUtil::GetAllInputInfo()", query);
1008  return infoInputList;
1009  }
1010 
1011  while (query.next())
1012  {
1013  InputInfo input;
1014  input.inputid = query.value(0).toUInt();
1015  input.name = query.value(1).toString();
1016  input.sourceid = query.value(2).toUInt();
1017  input.livetvorder = query.value(3).toUInt();
1018  input.scheduleOrder = query.value(4).toUInt();
1019  input.displayName = query.value(5).toString();
1020  input.recPriority = query.value(6).toInt();
1021  input.quickTune = query.value(7).toBool();
1022 
1023  infoInputList.push_back(input);
1024  }
1025 
1026  return infoInputList;
1027 }
1028 
1030 {
1031  InputInfo info("None", 0, inputid, 0, 0, 0);
1032  GetInputInfo(info);
1033  return info.name;
1034 }
1035 
1037 {
1038  MSqlQuery query(MSqlQuery::InitCon());
1039  query.prepare("SELECT startchan "
1040  "FROM capturecard "
1041  "WHERE cardid = :INPUTID");
1042  query.bindValue(":INPUTID", inputid);
1043 
1044  if (!query.exec())
1045  MythDB::DBError("CardUtil::GetStartingChannel(uint)", query);
1046  else if (query.next())
1047  return query.value(0).toString();
1048 
1049  return QString::null;
1050 }
1051 
1053 {
1054  if (!inputid)
1055  return QString::null;
1056 
1057  MSqlQuery query(MSqlQuery::InitCon());
1058  query.prepare("SELECT displayname, cardid, cardtype, inputname "
1059  "FROM capturecard "
1060  "WHERE cardid = :INPUTID");
1061  query.bindValue(":INPUTID", inputid);
1062 
1063  if (!query.exec())
1064  MythDB::DBError("CardUtil::GetDisplayName(uint)", query);
1065  else if (query.next())
1066  {
1067  QString result = query.value(0).toString();
1068  if (result.isEmpty())
1069  result = QString("%1: %2/%3").arg(query.value(1).toInt())
1070  .arg(query.value(2).toString()).arg(query.value(3).toString());
1071  return result;
1072  }
1073 
1074  return QString::null;
1075 }
1076 
1078 {
1079  MSqlQuery query(MSqlQuery::InitCon());
1080  query.prepare(
1081  "SELECT sourceid "
1082  "FROM capturecard "
1083  "WHERE cardid = :INPUTID");
1084  query.bindValue(":INPUTID", inputid);
1085  if (!query.exec() || !query.isActive())
1086  MythDB::DBError("CardUtil::GetSourceID()", query);
1087  else if (query.next())
1088  return query.value(0).toUInt();
1089 
1090  return 0;
1091 }
1092 
1094  const uint sourceid,
1095  const QString &inputname,
1096  const QString &externalcommand,
1097  const QString &changer_device,
1098  const QString &changer_model,
1099  const QString &hostname,
1100  const QString &tunechan,
1101  const QString &startchan,
1102  const QString &displayname,
1103  bool dishnet_eit,
1104  const uint recpriority,
1105  const uint quicktune,
1106  const uint schedorder,
1107  const uint livetvorder)
1108 {
1109  MSqlQuery query(MSqlQuery::InitCon());
1110 
1111  query.prepare(
1112  "UPDATE capturecard "
1113  "SET sourceid = :SOURCEID, "
1114  " inputname = :INPUTNAME, "
1115  " externalcommand = :EXTERNALCOMMAND, "
1116  " changer_device = :CHANGERDEVICE, "
1117  " changer_model = :CHANGERMODEL, "
1118  " tunechan = :TUNECHAN, "
1119  " startchan = :STARTCHAN, "
1120  " displayname = :DISPLAYNAME, "
1121  " dishnet_eit = :DISHNETEIT, "
1122  " recpriority = :RECPRIORITY, "
1123  " quicktune = :QUICKTUNE, "
1124  " schedorder = :SCHEDORDER, "
1125  " livetvorder = :LIVETVORDER "
1126  "WHERE cardid = :INPUTID AND "
1127  " inputname = 'None'");
1128 
1129  query.bindValue(":INPUTID", inputid);
1130  query.bindValue(":SOURCEID", sourceid);
1131  query.bindValue(":INPUTNAME", inputname);
1132  query.bindValue(":EXTERNALCOMMAND", externalcommand);
1133  query.bindValue(":CHANGERDEVICE", changer_device);
1134  query.bindValue(":CHANGERMODEL", changer_model);
1135  query.bindValue(":TUNECHAN", tunechan);
1136  query.bindValue(":STARTCHAN", startchan);
1137  query.bindValue(":DISPLAYNAME", displayname.isNull() ? "" : displayname);
1138  query.bindValue(":DISHNETEIT", dishnet_eit);
1139  query.bindValue(":RECPRIORITY", recpriority);
1140  query.bindValue(":QUICKTUNE", quicktune);
1141  query.bindValue(":SCHEDORDER", schedorder);
1142  query.bindValue(":LIVETVORDER", livetvorder);
1143 
1144  if (!query.exec())
1145  {
1146  MythDB::DBError("CreateCardInput", query);
1147  return -1;
1148  }
1149 
1150  return inputid;
1151 }
1152 
1154 {
1155  MSqlQuery query(MSqlQuery::InitCon());
1156  query.prepare(
1157  "UPDATE capturecard "
1158  "SET sourceid = 0, "
1159  " inputname = 'None', "
1160  " externalcommand = '', "
1161  " changer_device = '', "
1162  " changer_model = '', "
1163  " tunechan = '', "
1164  " startchan = '', "
1165  " displayname = '', "
1166  " dishnet_eit = 0, "
1167  " recpriority = 0, "
1168  " quicktune = 0, "
1169  " schedorder = 1, "
1170  " livetvorder = 1 "
1171  "WHERE cardid = :INPUTID");
1172  query.bindValue(":INPUTID", inputid);
1173 
1174  if (!query.exec())
1175  {
1176  MythDB::DBError("DeleteInput", query);
1177  return false;
1178  }
1179 
1180  query.prepare("DELETE FROM inputgroup "
1181  "WHERE cardinputid = :INPUTID AND "
1182  " inputgroupname LIKE 'user:%'");
1183  query.bindValue(":INPUTID", inputid);
1184 
1185  if (!query.exec())
1186  {
1187  MythDB::DBError("DeleteInput2", query);
1188  return false;
1189  }
1190 
1191  return true;
1192 }
1193 
1195 {
1196  MSqlQuery query(MSqlQuery::InitCon());
1197 
1198  query.prepare("SELECT inputgroupid FROM inputgroup "
1199  "WHERE inputgroupname = :GROUPNAME "
1200  "LIMIT 1");
1201  query.bindValue(":GROUPNAME", name);
1202  if (!query.exec())
1203  {
1204  MythDB::DBError("CreateNewInputGroup 0", query);
1205  return 0;
1206  }
1207 
1208  if (query.next())
1209  return query.value(0).toUInt();
1210 
1211  query.prepare("SELECT MAX(inputgroupid) FROM inputgroup");
1212  if (!query.exec())
1213  {
1214  MythDB::DBError("CreateNewInputGroup 1", query);
1215  return 0;
1216  }
1217 
1218  uint inputgroupid = (query.next()) ? query.value(0).toUInt() + 1 : 1;
1219 
1220  query.prepare(
1221  "INSERT INTO inputgroup "
1222  " (cardinputid, inputgroupid, inputgroupname) "
1223  "VALUES (:INPUTID, :GROUPID, :GROUPNAME ) ");
1224  query.bindValue(":INPUTID", 0);
1225  query.bindValue(":GROUPID", inputgroupid);
1226  query.bindValue(":GROUPNAME", name);
1227  if (!query.exec())
1228  {
1229  MythDB::DBError("CreateNewInputGroup 2", query);
1230  return 0;
1231  }
1232 
1233  return inputgroupid;
1234 }
1235 
1237  const QString &type,
1238  const QString &host,
1239  const QString &device)
1240 {
1241  QString name = host + '|' + device;
1242  if (type == "FREEBOX" || type == "IMPORT" ||
1243  type == "DEMO" || type == "EXTERNAL")
1244  name += QString("|%1").arg(inputid);
1245  return CreateInputGroup(name);
1246 }
1247 
1249 {
1250  MSqlQuery query(MSqlQuery::InitCon());
1251  query.prepare(
1252  "SELECT inputgroupid "
1253  "FROM inputgroup "
1254  "WHERE cardinputid = :INPUTID "
1255  " AND inputgroupname REGEXP '^[a-z_-]*\\\\|'");
1256  query.bindValue(":INPUTID", inputid);
1257 
1258  if (!query.exec())
1259  {
1260  MythDB::DBError("CardUtil::GetDeviceInputGroup()", query);
1261  return false;
1262  }
1263 
1264  if (query.next())
1265  {
1266  return query.value(0).toUInt();
1267  }
1268 
1269  return 0;
1270 }
1271 
1272 bool CardUtil::LinkInputGroup(uint inputid, uint inputgroupid)
1273 {
1274  MSqlQuery query(MSqlQuery::InitCon());
1275 
1276  query.prepare(
1277  "SELECT cardinputid, inputgroupid, inputgroupname "
1278  "FROM inputgroup "
1279  "WHERE inputgroupid = :GROUPID "
1280  "ORDER BY inputgroupid, cardinputid, inputgroupname");
1281  query.bindValue(":GROUPID", inputgroupid);
1282 
1283  if (!query.exec())
1284  {
1285  MythDB::DBError("CardUtil::CreateInputGroup() 1", query);
1286  return false;
1287  }
1288 
1289  if (!query.next())
1290  return false;
1291 
1292  const QString name = query.value(2).toString();
1293 
1294  query.prepare(
1295  "INSERT INTO inputgroup "
1296  " (cardinputid, inputgroupid, inputgroupname) "
1297  "VALUES (:INPUTID, :GROUPID, :GROUPNAME ) ");
1298 
1299  query.bindValue(":INPUTID", inputid);
1300  query.bindValue(":GROUPID", inputgroupid);
1301  query.bindValue(":GROUPNAME", name);
1302 
1303  if (!query.exec())
1304  {
1305  MythDB::DBError("CardUtil::CreateInputGroup() 2", query);
1306  return false;
1307  }
1308 
1309  return true;
1310 }
1311 
1312 bool CardUtil::UnlinkInputGroup(uint inputid, uint inputgroupid)
1313 {
1314  MSqlQuery query(MSqlQuery::InitCon());
1315 
1316  if (!inputid && !inputgroupid)
1317  {
1318  query.prepare(
1319  "DELETE FROM inputgroup "
1320  "WHERE cardinputid NOT IN "
1321  "( SELECT cardid FROM capturecard )");
1322  }
1323  else
1324  {
1325  query.prepare(
1326  "DELETE FROM inputgroup "
1327  "WHERE cardinputid = :INPUTID AND "
1328  " inputgroupid = :GROUPID ");
1329 
1330  query.bindValue(":INPUTID", inputid);
1331  query.bindValue(":GROUPID", inputgroupid);
1332  }
1333 
1334  if (!query.exec())
1335  {
1336  MythDB::DBError("CardUtil::DeleteInputGroup()", query);
1337  return false;
1338  }
1339 
1340  return true;
1341 }
1342 
1343 vector<uint> CardUtil::GetInputGroups(uint inputid)
1344 {
1345  vector<uint> list;
1346 
1347  MSqlQuery query(MSqlQuery::InitCon());
1348 
1349  query.prepare(
1350  "SELECT inputgroupid "
1351  "FROM inputgroup "
1352  "WHERE cardinputid = :INPUTID "
1353  "ORDER BY inputgroupid, cardinputid, inputgroupname");
1354 
1355  query.bindValue(":INPUTID", inputid);
1356 
1357  if (!query.exec())
1358  {
1359  MythDB::DBError("CardUtil::GetInputGroups()", query);
1360  return list;
1361  }
1362 
1363  while (query.next())
1364  list.push_back(query.value(0).toUInt());
1365 
1366  return list;
1367 }
1368 
1369 vector<uint> CardUtil::GetGroupInputIDs(uint inputgroupid)
1370 {
1371  vector<uint> list;
1372 
1373  MSqlQuery query(MSqlQuery::InitCon());
1374 
1375  query.prepare(
1376  "SELECT DISTINCT cardid "
1377  "FROM capturecard, inputgroup "
1378  "WHERE inputgroupid = :GROUPID AND "
1379  " capturecard.cardid = inputgroup.cardinputid "
1380  "ORDER BY cardid");
1381 
1382  query.bindValue(":GROUPID", inputgroupid);
1383 
1384  if (!query.exec())
1385  {
1386  MythDB::DBError("CardUtil::GetGroupInputIDs()", query);
1387  return list;
1388  }
1389 
1390  while (query.next())
1391  list.push_back(query.value(0).toUInt());
1392 
1393  return list;
1394 }
1395 
1397 {
1398  vector<uint> inputids;
1399  vector<uint> inputgroupids = CardUtil::GetInputGroups(inputid);
1400 
1401  for (uint i = 0; i < inputgroupids.size(); i++)
1402  {
1403  LOG(VB_RECORD, LOG_INFO, LOC + QString(" Group ID %1")
1404  .arg(inputgroupids[i]));
1405 
1406  vector<uint> tmp = CardUtil::GetGroupInputIDs(inputgroupids[i]);
1407  for (uint j = 0; j < tmp.size(); j++)
1408  {
1409  if (tmp[j] == inputid)
1410  continue;
1411  if (find(inputids.begin(), inputids.end(), tmp[j])
1412  != inputids.end())
1413  continue;
1414  inputids.push_back(tmp[j]);
1415  }
1416  }
1417 
1418  for (uint i = 0; i < inputids.size(); i++)
1419  LOG(VB_RECORD, LOG_INFO,
1420  LOC + QString(" Input ID %1").arg(inputids[i]));
1421 
1422  return inputids;
1423 }
1424 
1426  uint &signal_timeout, uint &channel_timeout)
1427 {
1428  MSqlQuery query(MSqlQuery::InitCon());
1429  query.prepare(
1430  "SELECT signal_timeout, channel_timeout "
1431  "FROM capturecard "
1432  "WHERE cardid = :INPUTID");
1433  query.bindValue(":INPUTID", inputid);
1434 
1435  if (!query.exec() || !query.isActive())
1436  MythDB::DBError("CardUtil::GetTimeouts()", query);
1437  else if (query.next())
1438  {
1439  signal_timeout = (uint) max(query.value(0).toInt(), 250);
1440  channel_timeout = (uint) max(query.value(1).toInt(), 500);
1441  return true;
1442  }
1443 
1444  return false;
1445 }
1446 
1448 {
1449  DiSEqCDev dev;
1450  DiSEqCDevTree *diseqc_tree = dev.FindTree(inputid);
1451 
1452  bool needsConf = false;
1453  if (diseqc_tree)
1454  needsConf = diseqc_tree->IsInNeedOfConf();
1455 
1456  return needsConf;
1457 }
1458 
1459 uint CardUtil::GetQuickTuning(uint inputid, const QString &input_name)
1460 {
1461  uint quicktune = 0;
1462 
1463  MSqlQuery query(MSqlQuery::InitCon());
1464  query.prepare(
1465  "SELECT quicktune "
1466  "FROM capturecard "
1467  "WHERE cardid = :INPUTID AND "
1468  " inputname = :INPUTNAME");
1469  query.bindValue(":INPUTID", inputid);
1470  query.bindValue(":INPUTNAME", input_name);
1471 
1472  if (!query.exec() || !query.isActive())
1473  MythDB::DBError("CardUtil::GetQuickTuning()", query);
1474  else if (query.next())
1475  quicktune = query.value(0).toUInt();
1476 
1477  return quicktune;
1478 }
1479 
1480 bool CardUtil::hasV4L2(int videofd)
1481 {
1482  (void) videofd;
1483 #ifdef USING_V4L2
1484  struct v4l2_capability vcap;
1485  memset(&vcap, 0, sizeof(vcap));
1486 
1487  return ((ioctl(videofd, VIDIOC_QUERYCAP, &vcap) >= 0) &&
1488  (vcap.capabilities & V4L2_CAP_VIDEO_CAPTURE));
1489 #else // if !USING_V4L2
1490  return false;
1491 #endif // !USING_V4L2
1492 }
1493 
1495  int videofd, QString &input, QString &driver, uint32_t &version,
1496  uint32_t &capabilities)
1497 {
1498  input = driver = QString::null;
1499  version = 0;
1500  capabilities = 0;
1501 
1502  if (videofd < 0)
1503  return false;
1504 
1505 #ifdef USING_V4L2
1506  // First try V4L2 query
1507  struct v4l2_capability capability;
1508  memset(&capability, 0, sizeof(struct v4l2_capability));
1509  if (ioctl(videofd, VIDIOC_QUERYCAP, &capability) >= 0)
1510  {
1511  input = QString::fromLatin1((const char*)capability.card);
1512  driver = QString::fromLatin1((const char*)capability.driver);
1513  version = capability.version;
1514  capabilities = capability.capabilities;
1515  }
1516 #ifdef USING_V4L1
1517  else // Fallback to V4L1 query
1518  {
1519  struct video_capability capability;
1520  if (ioctl(videofd, VIDIOCGCAP, &capability) >= 0)
1521  input = QString::fromLatin1((const char*)capability.name);
1522  }
1523 #endif // USING_V4L1
1524 #endif // USING_V4L2
1525 
1526  if (!driver.isEmpty())
1527  driver.remove( QRegExp("\\[[0-9]\\]$") );
1528 
1529  return !input.isEmpty();
1530 }
1531 
1533 {
1534  (void) videofd;
1535 
1536  InputNames list;
1537  ok = false;
1538 
1539 #ifdef USING_V4L2
1540  bool usingv4l2 = hasV4L2(videofd);
1541 
1542  // V4L v2 query
1543  struct v4l2_input vin;
1544  memset(&vin, 0, sizeof(vin));
1545  while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMINPUT, &vin) >= 0))
1546  {
1547  QString input((char *)vin.name);
1548  list[vin.index] = input;
1549  vin.index++;
1550  }
1551  if (vin.index)
1552  {
1553  ok = true;
1554  return list;
1555  }
1556 
1557 #ifdef USING_V4L1
1558  // V4L v1 query
1559  struct video_capability vidcap;
1560  memset(&vidcap, 0, sizeof(vidcap));
1561  if (ioctl(videofd, VIDIOCGCAP, &vidcap) != 0)
1562  {
1563  QString msg = QObject::tr("Could not query inputs.");
1564  LOG(VB_GENERAL, LOG_ERR, "ProbeV4LVideoInputs(): Error, " + msg + ENO);
1565  list[-1] = msg;
1566  vidcap.channels = 0;
1567  }
1568 
1569  for (int i = 0; i < vidcap.channels; i++)
1570  {
1571  struct video_channel test;
1572  memset(&test, 0, sizeof(test));
1573  test.channel = i;
1574 
1575  if (ioctl(videofd, VIDIOCGCHAN, &test) != 0)
1576  {
1577  LOG(VB_GENERAL, LOG_ERR, "ProbeV4LVideoInputs(): Error, " +
1578  QString("Could determine name of input #%1"
1579  "\n\t\t\tNot adding it to the list.")
1580  .arg(test.channel) + ENO);
1581  continue;
1582  }
1583 
1584  list[i] = test.name;
1585  }
1586 #endif // USING_V4L1
1587 
1588  // Create an input when none are advertised
1589  if (list.isEmpty())
1590  list[0] = "Television";
1591 
1592  ok = true;
1593 #else // if !USING_V4L2
1594  list[-1] += QObject::tr("ERROR, Compile with V4L support to query inputs");
1595 #endif // !USING_V4L2
1596  return list;
1597 }
1598 
1600 {
1601  (void) videofd;
1602 
1603  InputNames list;
1604  ok = false;
1605 
1606 #ifdef USING_V4L2
1607  bool usingv4l2 = hasV4L2(videofd);
1608 
1609  // V4L v2 query
1610  struct v4l2_audio ain;
1611  memset(&ain, 0, sizeof(ain));
1612  while (usingv4l2 && (ioctl(videofd, VIDIOC_ENUMAUDIO, &ain) >= 0))
1613  {
1614  QString input((char *)ain.name);
1615  list[ain.index] = input;
1616  ain.index++;
1617  }
1618  if (ain.index)
1619  {
1620  ok = true;
1621  return list;
1622  }
1623 
1624  ok = true;
1625 #else // if !USING_V4L2
1626  list[-1] += QObject::tr(
1627  "ERROR, Compile with V4L support to query audio inputs");
1628 #endif // !USING_V4L2
1629  return list;
1630 }
1631 
1633 {
1634  InputNames list;
1635  MSqlQuery query(MSqlQuery::InitCon());
1636  query.prepare(
1637  "SELECT cardid, inputname "
1638  "FROM capturecard "
1639  "WHERE hostname = :HOSTNAME "
1640  " AND videodevice = :DEVICE "
1641  " AND parentid = 0 "
1642  " AND inputname <> 'None'");
1643  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
1644  query.bindValue(":DEVICE", device);
1645 
1646  if (!query.exec() || !query.isActive())
1647  MythDB::DBError("CardUtil::GetConfiguredDVBInputs", query);
1648  else
1649  {
1650  while (query.next())
1651  list[query.value(0).toUInt()] = query.value(1).toString();
1652  }
1653  return list;
1654 }
1655 
1656 QStringList CardUtil::ProbeVideoInputs(QString device, QString inputtype)
1657 {
1658  QStringList ret;
1659 
1660  if (IsSingleInputType(inputtype))
1661  ret += "MPEG2TS";
1662  else if ("DVB" == inputtype)
1663  ret += ProbeDVBInputs(device);
1664  else
1665  ret += ProbeV4LVideoInputs(device);
1666 
1667  return ret;
1668 }
1669 
1670 QStringList CardUtil::ProbeAudioInputs(QString device, QString inputtype)
1671 {
1672  LOG(VB_GENERAL, LOG_DEBUG, QString("ProbeAudioInputs(%1,%2)")
1673  .arg(device).arg(inputtype));
1674  QStringList ret;
1675 
1676  if ("HDPVR" == inputtype ||
1677  "V4L2" == inputtype)
1678  ret += ProbeV4LAudioInputs(device);
1679 
1680  return ret;
1681 }
1682 
1683 QStringList CardUtil::ProbeV4LVideoInputs(QString device)
1684 {
1685  bool ok;
1686  QStringList ret;
1687  QByteArray dev = device.toLatin1();
1688  int videofd = open(dev.constData(), O_RDWR);
1689  if (videofd < 0)
1690  {
1691  ret += QObject::tr("Could not open '%1' "
1692  "to probe its inputs.").arg(device);
1693  return ret;
1694  }
1695  InputNames list = CardUtil::ProbeV4LVideoInputs(videofd, ok);
1696  close(videofd);
1697 
1698  if (!ok)
1699  {
1700  ret += list[-1];
1701  return ret;
1702  }
1703 
1704  InputNames::iterator it;
1705  for (it = list.begin(); it != list.end(); ++it)
1706  {
1707  if (it.key() >= 0)
1708  ret += *it;
1709  }
1710 
1711  return ret;
1712 }
1713 
1714 QStringList CardUtil::ProbeV4LAudioInputs(QString device)
1715 {
1716  LOG(VB_GENERAL, LOG_DEBUG, QString("ProbeV4LAudioInputs(%1)").arg(device));
1717 
1718  bool ok;
1719  QStringList ret;
1720  int videofd = open(device.toLatin1().constData(), O_RDWR);
1721  if (videofd < 0)
1722  {
1723  LOG(VB_GENERAL, LOG_ERR, "ProbeAudioInputs() -> couldn't open device");
1724  ret += QObject::tr("Could not open '%1' to probe its inputs.")
1725  .arg(device);
1726  return ret;
1727  }
1728  InputNames list = CardUtil::ProbeV4LAudioInputs(videofd, ok);
1729  close(videofd);
1730 
1731  if (!ok)
1732  {
1733  ret += list[-1];
1734  return ret;
1735  }
1736 
1737  InputNames::iterator it;
1738  for (it = list.begin(); it != list.end(); ++it)
1739  {
1740  if (it.key() >= 0)
1741  ret += *it;
1742  }
1743 
1744  return ret;
1745 }
1746 
1747 QStringList CardUtil::ProbeDVBInputs(QString device)
1748 {
1749  QStringList ret;
1750 
1751 #ifdef USING_DVB
1752  InputNames list = GetConfiguredDVBInputs(device);
1753  InputNames::iterator it;
1754  for (it = list.begin(); it != list.end(); ++it)
1755  {
1756  if (it.key())
1757  ret += *it;
1758  }
1759 #else
1760  (void) device;
1761  ret += QObject::tr("ERROR, Compile with DVB support to query inputs");
1762 #endif
1763 
1764  return ret;
1765 }
1766 
1767 QString CardUtil::GetDeviceLabel(const QString &inputtype,
1768  const QString &videodevice)
1769 {
1770  return QString("[ %1 : %2 ]").arg(inputtype).arg(videodevice);
1771 }
1772 
1774 {
1775  QString devlabel;
1776  MSqlQuery query(MSqlQuery::InitCon());
1777  query.prepare("SELECT cardtype, videodevice "
1778  "FROM capturecard WHERE cardid = :INPUTID ");
1779  query.bindValue(":INPUTID", inputid);
1780 
1781  if (query.exec() && query.next())
1782  {
1783  return GetDeviceLabel(query.value(0).toString(),
1784  query.value(1).toString());
1785  }
1786 
1787  return "[ UNKNOWN ]";
1788 }
1789 
1791  uint inputid,
1792  const QString &device,
1793  const QString &inputtype,
1794  QStringList &inputs)
1795 {
1796  inputs.clear();
1797  if (IsSingleInputType(inputtype))
1798  inputs += "MPEG2TS";
1799  else if (inputtype == "DVB")
1800  inputs += "DVBInput";
1801  else
1802  inputs += ProbeV4LVideoInputs(device);
1803 }
1804 
1805 int CardUtil::CreateCaptureCard(const QString &videodevice,
1806  const QString &audiodevice,
1807  const QString &vbidevice,
1808  const QString &inputtype,
1809  const uint audioratelimit,
1810  const QString &hostname,
1811  const uint dvb_swfilter,
1812  const uint dvb_sat_type,
1813  bool dvb_wait_for_seqstart,
1814  bool skipbtaudio,
1815  bool dvb_on_demand,
1816  const uint dvb_diseqc_type,
1817  const uint firewire_speed,
1818  const QString &firewire_model,
1819  const uint firewire_connection,
1820  const uint signal_timeout,
1821  const uint channel_timeout,
1822  const uint dvb_tuning_delay,
1823  const uint contrast,
1824  const uint brightness,
1825  const uint colour,
1826  const uint hue,
1827  const uint diseqcid,
1828  bool dvb_eitscan)
1829 {
1830  MSqlQuery query(MSqlQuery::InitCon());
1831 
1832  query.prepare(
1833  "INSERT INTO capturecard "
1834  "(videodevice, audiodevice, vbidevice, cardtype, "
1835  "audioratelimit, hostname, dvb_swfilter, dvb_sat_type, "
1836  "dvb_wait_for_seqstart, skipbtaudio, dvb_on_demand, dvb_diseqc_type, "
1837  "firewire_speed, firewire_model, firewire_connection, signal_timeout, "
1838  "channel_timeout, dvb_tuning_delay, contrast, brightness, colour, "
1839  "hue, diseqcid, dvb_eitscan) "
1840  "VALUES (:VIDEODEVICE, :AUDIODEVICE, :VBIDEVICE, :INPUTTYPE, "
1841  ":AUDIORATELIMIT, :HOSTNAME, :DVBSWFILTER, :DVBSATTYPE, "
1842  ":DVBWAITFORSEQSTART, :SKIPBTAUDIO, :DVBONDEMAND, :DVBDISEQCTYPE, "
1843  ":FIREWIRESPEED, :FIREWIREMODEL, :FIREWIRECONNECTION, :SIGNALTIMEOUT, "
1844  ":CHANNELTIMEOUT, :DVBTUNINGDELAY, :CONTRAST, :BRIGHTNESS, :COLOUR, "
1845  ":HUE, :DISEQCID, :DVBEITSCAN ) ");
1846 
1847  query.bindValue(":VIDEODEVICE", videodevice);
1848  query.bindValue(":AUDIODEVICE", audiodevice);
1849  query.bindValue(":VBIDEVICE", vbidevice);
1850  query.bindValue(":INPUTTYPE", inputtype);
1851  query.bindValue(":AUDIORATELIMIT", audioratelimit);
1852  query.bindValue(":HOSTNAME", hostname);
1853  query.bindValue(":DVBSWFILTER", dvb_swfilter);
1854  query.bindValue(":DVBSATTYPE", dvb_sat_type);
1855  query.bindValue(":DVBWAITFORSEQSTART", dvb_wait_for_seqstart);
1856  query.bindValue(":SKIPBTAUDIO", skipbtaudio);
1857  query.bindValue(":DVBONDEMAND", dvb_on_demand);
1858  query.bindValue(":DVBDISEQCTYPE", dvb_diseqc_type);
1859  query.bindValue(":FIREWIRESPEED", firewire_speed);
1860  query.bindValue(":FIREWIREMODEL", firewire_model);
1861  query.bindValue(":FIREWIRECONNECTION", firewire_connection);
1862  query.bindValue(":SIGNALTIMEOUT", signal_timeout);
1863  query.bindValue(":CHANNELTIMEOUT", channel_timeout);
1864  query.bindValue(":DVBTUNINGDELAY", dvb_tuning_delay);
1865  query.bindValue(":CONTRAST", contrast);
1866  query.bindValue(":BRIGHTNESS", brightness);
1867  query.bindValue(":COLOUR", colour);
1868  query.bindValue(":HUE", hue);
1869  query.bindValue(":DISEQCID", diseqcid);
1870  query.bindValue(":DVBEITSCAN", dvb_eitscan);
1871 
1872  if (!query.exec())
1873  {
1874  MythDB::DBError("CreateCaptureCard", query);
1875  return -1;
1876  }
1877 
1878  query.prepare("SELECT MAX(cardid) FROM capturecard");
1879 
1880  if (!query.exec())
1881  {
1882  MythDB::DBError("CreateCaptureCard maxinput", query);
1883  return -1;
1884  }
1885 
1886  int inputid = -1; /* must be int not uint because of return type. */
1887 
1888  if (query.next())
1889  {
1890  inputid = query.value(0).toInt();
1891  uint groupid = CardUtil::CreateDeviceInputGroup(inputid, inputtype,
1892  hostname, videodevice);
1893  CardUtil::LinkInputGroup(inputid, groupid);
1894  }
1895 
1896  return inputid;
1897 }
1898 
1900 {
1901  MSqlQuery query(MSqlQuery::InitCon());
1902  bool ok = true;
1903 
1904  if (!inputid)
1905  return true;
1906 
1907  DiSEqCDevTree tree;
1908  tree.Load(inputid);
1909 
1910  // delete any clones
1911  QString rawtype = GetRawInputType(inputid);
1912  QString videodevice = GetVideoDevice(inputid);
1913  if (IsTunerSharingCapable(rawtype) && !videodevice.isEmpty())
1914  {
1915  query.prepare(
1916  "SELECT cardid "
1917  "FROM capturecard "
1918  "WHERE parentid = :INPUTID");
1919  query.bindValue(":INPUTID", inputid);
1920 
1921  if (!query.exec())
1922  {
1923  MythDB::DBError("DeleteCard -- find clone inputs", query);
1924  return false;
1925  }
1926 
1927  while (query.next())
1928  ok &= DeleteCard(query.value(0).toUInt());
1929 
1930  if (!ok)
1931  return false;
1932  }
1933 
1934  ok &= CardUtil::DeleteInput(inputid);
1935 
1936  if (!ok)
1937  return false;
1938 
1939  // actually delete the capturecard row for this input
1940  query.prepare("DELETE FROM capturecard WHERE cardid = :INPUTID");
1941  query.bindValue(":INPUTID", inputid);
1942 
1943  if (!query.exec())
1944  {
1945  MythDB::DBError("DeleteCard -- delete row", query);
1946  ok = false;
1947  }
1948 
1949  if (ok)
1950  {
1951  // Delete the diseqc tree if no more inputs reference it.
1952  if (tree.Root())
1953  {
1954  query.prepare("SELECT cardid FROM capturecard "
1955  "WHERE diseqcid = :DISEQCID LIMIT 1");
1956  query.bindValue(":DISEQCID", tree.Root()->GetDeviceID());
1957  if (!query.exec())
1958  {
1959  MythDB::DBError("DeleteCard -- find diseqc tree", query);
1960  }
1961  else if (!query.next())
1962  {
1963  tree.SetRoot(NULL);
1964  tree.Store(inputid);
1965  }
1966  }
1967 
1968  // delete any unused input groups
1969  UnlinkInputGroup(0,0);
1970  }
1971 
1972  return ok;
1973 }
1974 
1976 {
1977  MSqlQuery query(MSqlQuery::InitCon());
1978  return (query.exec("TRUNCATE TABLE inputgroup") &&
1979  query.exec("TRUNCATE TABLE diseqc_config") &&
1980  query.exec("TRUNCATE TABLE diseqc_tree") &&
1981  query.exec("TRUNCATE TABLE capturecard"));
1982 }
1983 
1984 vector<uint> CardUtil::GetInputList(void)
1985 {
1986  vector<uint> list;
1987 
1988  MSqlQuery query(MSqlQuery::InitCon());
1989  query.prepare(
1990  "SELECT cardid "
1991  "FROM capturecard "
1992  "ORDER BY cardid");
1993 
1994  if (!query.exec())
1995  MythDB::DBError("CardUtil::GetInputList()", query);
1996  else
1997  {
1998  while (query.next())
1999  list.push_back(query.value(0).toUInt());
2000  }
2001 
2002  return list;
2003 }
2004 
2006 {
2007  vector<uint> list;
2008 
2009  MSqlQuery query(MSqlQuery::InitCon());
2010  query.prepare(
2011  "SELECT DISTINCT cardid "
2012  "FROM capturecard "
2013  "WHERE livetvorder <> 0 "
2014  "ORDER BY livetvorder");
2015 
2016  if (!query.exec())
2017  MythDB::DBError("CardUtil::GetInputList()", query);
2018  else
2019  {
2020  while (query.next())
2021  list.push_back(query.value(0).toUInt());
2022  }
2023 
2024  return list;
2025 }
2026 
2027 
2028 QString CardUtil::GetDeviceName(dvb_dev_type_t type, const QString &device)
2029 {
2030  QString devname = QString(device);
2031 
2032  if (DVB_DEV_FRONTEND == type)
2033  return devname;
2034  else if (DVB_DEV_DVR == type)
2035  return devname.replace(devname.indexOf("frontend"), 8, "dvr");
2036  else if (DVB_DEV_DEMUX == type)
2037  return devname.replace(devname.indexOf("frontend"), 8, "demux");
2038  else if (DVB_DEV_CA == type)
2039  return devname.replace(devname.indexOf("frontend"), 8, "ca");
2040  else if (DVB_DEV_AUDIO == type)
2041  return devname.replace(devname.indexOf("frontend"), 8, "audio");
2042  else if (DVB_DEV_VIDEO == type)
2043  return devname.replace(devname.indexOf("frontend"), 8, "video");
2044 
2045  return "";
2046 }
2047 
2057 bool CardUtil::HDHRdoesDVB(const QString &device)
2058 {
2059  (void) device;
2060 
2061 #ifdef USING_HDHOMERUN
2062  hdhomerun_device_t *hdhr;
2063  hdhr = hdhomerun_device_create_from_str(device.toLatin1(), NULL);
2064  if (!hdhr)
2065  return false;
2066 
2067  const char *model = hdhomerun_device_get_model_str(hdhr);
2068  if (model && strstr(model, "dvb"))
2069  {
2070  hdhomerun_device_destroy(hdhr);
2071  return true;
2072  }
2073 
2074  hdhomerun_device_destroy(hdhr);
2075 
2076 #endif
2077 
2078  return false;
2079 }
2080 
2085 QString CardUtil::GetHDHRdesc(const QString &device)
2086 {
2087  QString connectErr = QObject::tr("Unable to connect to device.");
2088 
2089 #ifdef USING_HDHOMERUN
2090  bool deviceIsIP = false;
2091  uint32_t dev;
2092 
2093  if (device.contains('.')) // Simplistic check, but also allows DNS names
2094  deviceIsIP = true;
2095  else
2096  {
2097  bool validID;
2098 
2099  dev = device.toUInt(&validID, 16);
2100  if (!validID || !hdhomerun_discover_validate_device_id(dev))
2101  return QObject::tr("Invalid Device ID");
2102  }
2103  (void) deviceIsIP;
2104 
2105  LOG(VB_GENERAL, LOG_INFO, "CardUtil::GetHDHRdescription(" + device +
2106  ") - trying to locate device");
2107 
2108  hdhomerun_device_t *hdhr;
2109  hdhr = hdhomerun_device_create_from_str(device.toLatin1(), NULL);
2110  if (!hdhr)
2111  return QObject::tr("Invalid Device ID or address.");
2112 
2113  const char *model = hdhomerun_device_get_model_str(hdhr);
2114  if (!model)
2115  {
2116  hdhomerun_device_destroy(hdhr);
2117  return connectErr;
2118  }
2119 
2120 
2121  QString description = model;
2122  char *sVersion;
2123  uint32_t iVersion;
2124 
2125  if (hdhomerun_device_get_version(hdhr, &sVersion, &iVersion))
2126  description += QObject::tr(", firmware: %2").arg(sVersion);
2127 
2128  hdhomerun_device_destroy(hdhr);
2129 
2130  return description;
2131 #else
2132 
2133  (void) device;
2134  return connectErr;
2135 #endif
2136 }
2137 
2142 QString CardUtil::GetVBoxdesc(const QString &id, const QString &ip,
2143  const QString &tunerNo, const QString &tunerType)
2144 {
2145  QString connectErr = QObject::tr("Unable to connect to device.");
2146 
2147 #ifdef USING_VBOX
2148  VBox *vbox = new VBox(ip);
2149 
2150  if (!vbox->checkConnection())
2151  {
2152  delete vbox;
2153  return connectErr;
2154  }
2155 
2156  QString version;
2157 
2158  if (!vbox->checkVersion(version))
2159  {
2160  QString apiVersionErr = QObject::tr("The VBox software version is too old (%1), we require %2")
2161  .arg(version).arg(VBOX_MIN_API_VERSION);
2162  delete vbox;
2163  return apiVersionErr;
2164 
2165  }
2166 
2167  delete vbox;
2168 
2169  return QString("V@Box TV Gateway - ID: %1, IP: %2, Tuner: %3-%4").arg(id)
2170  .arg(ip).arg(tunerNo).arg(tunerType);
2171 
2172 #else
2173  (void) id;
2174  (void) ip;
2175  (void) tunerNo;
2176  (void) tunerType;
2177 
2178  return connectErr;
2179 #endif
2180 }
2181 
2182 #ifdef USING_ASI
2183 static QString sys_dev(uint device_num, QString dev)
2184 {
2185  return QString("/sys/class/asi/asirx%1/%2").arg(device_num).arg(dev);
2186 }
2187 
2188 static QString read_sys(QString sys_dev)
2189 {
2190  QFile f(sys_dev);
2191  f.open(QIODevice::ReadOnly);
2192  QByteArray sdba = f.readAll();
2193  f.close();
2194  return sdba;
2195 }
2196 
2197 static bool write_sys(QString sys_dev, QString str)
2198 {
2199  QFile f(sys_dev);
2200  f.open(QIODevice::WriteOnly);
2201  QByteArray ba = str.toLocal8Bit();
2202  qint64 offset = 0;
2203  for (uint tries = 0; (offset < ba.size()) && tries < 5; tries++)
2204  {
2205  qint64 written = f.write(ba.data()+offset, ba.size()-offset);
2206  if (written < 0)
2207  return false;
2208  offset += written;
2209  }
2210  return true;
2211 }
2212 #endif
2213 
2214 int CardUtil::GetASIDeviceNumber(const QString &device, QString *error)
2215 {
2216 #ifdef USING_ASI
2217  // basic confirmation
2218  struct stat statbuf;
2219  memset(&statbuf, 0, sizeof(statbuf));
2220  if (stat(device.toLocal8Bit().constData(), &statbuf) < 0)
2221  {
2222  if (error)
2223  *error = QString("Unable to stat '%1'").arg(device) + ENO;
2224  return -1;
2225  }
2226 
2227  if (!S_ISCHR(statbuf.st_mode))
2228  {
2229  if (error)
2230  *error = QString("'%1' is not a character device").arg(device);
2231  return -1;
2232  }
2233 
2234  if (!(statbuf.st_rdev & 0x0080))
2235  {
2236  if (error)
2237  *error = QString("'%1' not a DVEO ASI receiver").arg(device);
2238  return -1;
2239  }
2240 
2241  int device_num = statbuf.st_rdev & 0x007f;
2242 
2243  // extra confirmation
2244  QString sys_dev_contents = read_sys(sys_dev(device_num, "dev"));
2245  QStringList sys_dev_clist = sys_dev_contents.split(":");
2246  if (2 != sys_dev_clist.size())
2247  {
2248  if (error)
2249  {
2250  *error = QString("Unable to read '%1'")
2251  .arg(sys_dev(device_num, "dev"));
2252  }
2253  return -1;
2254  }
2255  if (sys_dev_clist[0].toUInt() != (statbuf.st_rdev>>8))
2256  {
2257  if (error)
2258  *error = QString("'%1' not a DVEO ASI device").arg(device);
2259  return -1;
2260  }
2261 
2262  return device_num;
2263 #else
2264  (void) device;
2265  if (error)
2266  *error = "Not compiled with ASI support.";
2267  return -1;
2268 #endif
2269 }
2270 
2272 {
2273 #ifdef USING_ASI
2274  // get the buffer size
2275  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "bufsize"));
2276  bool ok;
2277  uint buf_size = sys_bufsize_contents.toUInt(&ok);
2278  if (!ok)
2279  {
2280  if (error)
2281  {
2282  *error = QString("Failed to read buffer size from '%1'")
2283  .arg(sys_dev(device_num, "bufsize"));
2284  }
2285  return 0;
2286  }
2287  return buf_size;
2288 #else
2289  (void) device_num;
2290  if (error)
2291  *error = "Not compiled with ASI support.";
2292  return 0;
2293 #endif
2294 }
2295 
2297 {
2298 #ifdef USING_ASI
2299  // get the buffer size
2300  QString sys_numbuffers_contents = read_sys(sys_dev(device_num, "buffers"));
2301  bool ok;
2302  uint num_buffers = sys_numbuffers_contents.toUInt(&ok);
2303  if (!ok)
2304  {
2305  if (error)
2306  {
2307  *error = QString("Failed to read num buffers from '%1'")
2308  .arg(sys_dev(device_num, "buffers"));
2309  }
2310  return 0;
2311  }
2312  return num_buffers;
2313 #else
2314  (void) device_num;
2315  if (error)
2316  *error = "Not compiled with ASI support.";
2317  return 0;
2318 #endif
2319 }
2320 
2321 int CardUtil::GetASIMode(uint device_num, QString *error)
2322 {
2323 #ifdef USING_ASI
2324  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "mode"));
2325  bool ok;
2326  uint mode = sys_bufsize_contents.toUInt(&ok);
2327  if (!ok)
2328  {
2329  if (error)
2330  {
2331  *error = QString("Failed to read mode from '%1'")
2332  .arg(sys_dev(device_num, "mode"));
2333  }
2334  return -1;
2335  }
2336  return mode;
2337 #else
2338  (void) device_num;
2339  if (error)
2340  *error = "Not compiled with ASI support.";
2341  return -1;
2342 #endif
2343 }
2344 
2345 bool CardUtil::SetASIMode(uint device_num, uint mode, QString *error)
2346 {
2347 #ifdef USING_ASI
2348  QString sys_bufsize_contents = read_sys(sys_dev(device_num, "mode"));
2349  bool ok;
2350  uint old_mode = sys_bufsize_contents.toUInt(&ok);
2351  if (ok && old_mode == mode)
2352  return true;
2353  ok = write_sys(sys_dev(device_num, "mode"), QString("%1\n").arg(mode));
2354  if (!ok && error)
2355  {
2356  *error = QString("Failed to set mode to %1 using '%2'")
2357  .arg(mode).arg(sys_dev(device_num, "mode"));
2358  }
2359  return ok;
2360 #else
2361  (void) device_num;
2362  if (error)
2363  *error = "Not compiled with ASI support.";
2364  return false;
2365 #endif
2366 }
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:785
uint scheduleOrder
Definition: inputinfo.h:77
dvb_dev_type_t
Definition: cardutil.h:29
static bool IsTunerSharingCapable(const QString &rawtype)
Definition: cardutil.h:163
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:553
int recPriority
Definition: inputinfo.h:76
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:348
void bindValue(const QString &placeholder, const QVariant &val)
Definition: mythdbcon.cpp:884
DVB-S device settings class.
Definition: diseqc.h:37
__u8 driver[16]
Definition: videodev2.h:386
static QString GetInputName(uint inputid)
Definition: cardutil.cpp:1029
DiSEqCDevDevice * Root(void)
Retrieves the root node in the tree.
Definition: diseqc.h:94
static uint GetASINumBuffers(uint device_num, QString *error=NULL)
Definition: cardutil.cpp:2296
static bool IsTunerShared(uint inputidA, uint inputidB)
Definition: cardutil.cpp:181
DiSEqCDevTree * FindTree(uint cardid)
Retrieve device tree.
Definition: diseqc.cpp:248
__u32 index
Definition: videodev2.h:1369
static const int kTunerTypeDVBT
static bool SetStartChannel(uint inputid, const QString &channum)
Definition: cardutil.cpp:937
static QStringList GetVideoDevices(const QString &rawtype, QString hostname=QString::null)
Returns the videodevices of the matching inputs, duplicates removed.
Definition: cardutil.cpp:305
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:1194
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:457
static vector< uint > GetInputIDs(QString videodevice=QString::null, QString rawtype=QString::null, QString inputname=QString::null, QString hostname=QString::null)
Returns all inputids of inputs that uses the specified videodevice if specified, and optionally rawty...
Definition: cardutil.cpp:638
static vector< uint > GetConflictingInputs(uint inputid)
Definition: cardutil.cpp:1396
QString DriverName(void) const
Definition: v4l2util.h:45
static QString GetDeviceLabel(const QString &inputtype, const QString &videodevice)
Definition: cardutil.cpp:1767
QVariant value(int i) const
Definition: mythdbcon.h:182
static QString ProbeSubTypeName(uint inputid)
Definition: cardutil.cpp:570
static void error(const char *str,...)
Definition: vbi.c:41
static int CreateCaptureCard(const QString &videodevice, const QString &audiodevice, const QString &vbidevice, const QString &inputtype, const uint audioratelimit, const QString &hostname, const uint dvb_swfilter, const uint dvb_sat_type, bool dvb_wait_for_seqstart, bool skipbtaudio, bool dvb_on_demand, const uint dvb_diseqc_type, const uint firewire_speed, const QString &firewire_model, const uint firewire_connection, const uint signal_timeout, const uint channel_timeout, const uint dvb_tuning_delay, const uint contrast, const uint brightness, const uint colour, const uint hue, const uint diseqcid, bool dvb_eitscan)
Definition: cardutil.cpp:1805
uint sourceid
associated channel listings source
Definition: inputinfo.h:71
bool checkVersion(QString &version)
Definition: vboxutils.cpp:220
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:125
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
Definition: vboxutils.h:13
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:507
static QStringList ProbeDVBInputs(QString device)
Definition: cardutil.cpp:1747
static bool IsInNeedOfExternalInputConf(uint inputid)
Definition: cardutil.cpp:1447
static bool write_sys(QString sys_dev, QString str)
Definition: cardutil.cpp:2197
__u8 name[32]
Definition: videodev2.h:1673
QMap< QString, QString > InputTypes
Definition: cardutil.h:45
unsigned int uint
Definition: compat.h:136
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static bool GetInputInfo(InputInfo &info, vector< uint > *groupids=NULL)
Definition: cardutil.cpp:955
bool set_on_input(const QString &to_set, uint inputid, const QString &value)
Definition: cardutil.cpp:609
static bool DeleteInput(uint inputid)
Definition: cardutil.cpp:1153
static const int kTunerTypeDVBS1
static bool HasTuner(const QString &rawtype, const QString &device)
Definition: cardutil.cpp:158
bool Load(uint card_input_id)
Loads configuration chain from DB for specified card input id.
Definition: diseqc.cpp:137
bool Store(uint cardid, const QString &device="")
Stores the device tree to the database.
Definition: diseqc.cpp:434
static QString sys_dev(uint device_num, QString dev)
Definition: cardutil.cpp:2183
static bool GetV4LInfo(int videofd, QString &input, QString &driver, uint32_t &version, uint32_t &capabilities)
Definition: cardutil.cpp:1494
static vector< uint > GetLiveTVInputList(void)
Definition: cardutil.cpp:2005
static bool GetTimeouts(uint inputid, uint &signal_timeout, uint &channel_timeout)
Definition: cardutil.cpp:1425
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:2142
QString displayName
Definition: inputinfo.h:75
voidpf uLong offset
Definition: ioapi.h:142
static const int kTunerTypeDVBS2
static QStringList ProbeAudioInputs(QString device, QString inputtype=QString::null)
Definition: cardutil.cpp:1670
const char * name
Definition: ParseText.cpp:338
static const int kTunerTypeDVBT2
struct v4l2_capability - Describes V4L2 device caps returned by VIDIOC_QUERYCAP
Definition: videodev2.h:385
static InputNames ProbeV4LAudioInputs(int videofd, bool &ok)
Definition: cardutil.cpp:1599
void SetRoot(DiSEqCDevDevice *root)
Changes the root node of the tree.
Definition: diseqc.cpp:647
static bool IsDVBInputType(const QString &input_type)
Returns true iff the input_type is one of the DVB types.
Definition: cardutil.cpp:585
uint livetvorder
order for live TV use
Definition: inputinfo.h:78
static bool IsSingleInputType(const QString &rawtype)
Definition: cardutil.h:197
unsigned char t
Definition: ParseText.cpp:339
__u8 card[32]
Definition: videodev2.h:387
static QString GetDeviceName(dvb_dev_type_t, const QString &device)
Definition: cardutil.cpp:2028
static bool IsCableCardPresent(uint inputid, const QString &inputType)
Definition: cardutil.cpp:114
static uint GetDeviceInputGroup(uint inputid)
Definition: cardutil.cpp:1248
static QString GetFirewireChangerModel(uint inputid)
Definition: cardutil.cpp:896
string hostname
Definition: caa.py:17
static vector< uint > GetGroupInputIDs(uint inputgroupid)
Definition: cardutil.cpp:1369
static vector< uint > GetChildInputIDs(uint inputid)
Definition: cardutil.cpp:706
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1312
static MSqlQueryInfo InitCon(ConnectionReuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:542
static QList< InputInfo > GetAllInputInfo()
Definition: cardutil.cpp:995
static InputNames GetConfiguredDVBInputs(const QString &device)
Definition: cardutil.cpp:1632
static uint GetQuickTuning(uint inputid, const QString &inputname)
Definition: cardutil.cpp:1459
static bool HDHRdoesDVB(const QString &device)
If the device is valid, check if the model does DVB.
Definition: cardutil.cpp:2057
__u32 index
Definition: videodev2.h:1672
static uint GetASIBufferSize(uint device_num, QString *error=NULL)
Definition: cardutil.cpp:2271
uint inputid
unique key in DB for this input
Definition: inputinfo.h:72
bool isActive(void) const
Definition: mythdbcon.h:188
static int GetASIDeviceNumber(const QString &device, QString *error=NULL)
Definition: cardutil.cpp:2214
static QStringList ProbeVideoInputs(QString device, QString inputtype=QString::null)
Definition: cardutil.cpp:1656
static bool SetASIMode(uint device_num, uint mode, QString *error=NULL)
Definition: cardutil.cpp:2345
static bool CloneCard(uint src_inputid, uint dst_inputid)
Definition: cardutil.cpp:866
static vector< uint > GetInputList(void)
Definition: cardutil.cpp:1984
bool Load(const QString &device)
Definition: diseqc.cpp:331
QString toString() const
static QString GetFirewireChangerNode(uint inputid)
Definition: cardutil.cpp:879
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:272
static QStringList probeDevices(void)
Definition: vboxutils.cpp:36
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:810
bool quickTune
Definition: inputinfo.h:79
static uint GetChildInputCount(uint inputid)
Definition: cardutil.cpp:682
__u32 capabilities
Definition: videodev2.h:1045
typedef void(APIENTRY *MYTH_GLTEXIMAGE1DPROC)(GLenum target
QString name
input name
Definition: inputinfo.h:70
__u8 name[32]
Definition: videodev2.h:1370
GLint GLenum GLsizei GLint GLenum GLenum type
static uint clone_capturecard(uint src_inputid, uint orig_dst_inputid)
Definition: cardutil.cpp:734
static int CreateCardInput(const uint inputid, const 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, const uint recpriority, const uint quicktune, const uint schedorder, const uint livetvorder)
Definition: cardutil.cpp:1093
QString get_on_input(const QString &to_get, uint inputid)
Definition: cardutil.cpp:592
static bool DeleteCard(uint inputid)
Definition: cardutil.cpp:1899
QMap< int, QString > InputNames
Definition: cardutil.h:22
static const QString LOC
static uint GetSourceID(uint inputid)
Definition: cardutil.cpp:1077
static bool hasV4L2(int videofd)
Definition: cardutil.cpp:1480
const char int mode
Definition: ioapi.h:135
bool Store(uint card_input_id) const
Stores configuration chain to DB for specified card input id.
Definition: diseqc.cpp:171
static QString GetRawInputType(uint inputid)
Definition: cardutil.h:270
uint GetDeviceID(void) const
Definition: diseqc.h:164
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:610
bool checkConnection(void)
Definition: vboxutils.cpp:214
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:1272
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:181
static bool DeleteAllCards(void)
Definition: cardutil.cpp:1975
QString GetHostName(void)
__s32 value
Definition: videodev2.h:1042
static InputTypes GetInputTypes(void)
Definition: cardutil.cpp:262
DVB-S device tree class.
Definition: diseqc.h:75
bool IsInNeedOfConf(void) const
Definition: diseqc.cpp:846
static InputNames ProbeV4LVideoInputs(int videofd, bool &ok)
Definition: cardutil.cpp:1532
__u32 capabilities
Definition: videodev2.h:390
static int GetASIMode(uint device_num, QString *error=NULL)
Definition: cardutil.cpp:2321
static bool IsInputTypePresent(const QString &rawtype, QString hostname=QString::null)
Returns true if the input type is present and connected to an input.
Definition: cardutil.cpp:228
bool HasTuner(void) const
Definition: v4l2util.cpp:693
static QString GetHDHRdesc(const QString &device)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:2085
static QString GetScanableInputTypes(void)
Definition: cardutil.cpp:55
static vector< uint > GetInputGroups(uint inputid)
Definition: cardutil.cpp:1343
static uint GetMinSignalMonitoringDelay(const QString &device)
Definition: cardutil.cpp:560
static uint CreateDeviceInputGroup(uint inputid, const QString &type, const QString &host, const QString &device)
Definition: cardutil.cpp:1236
static QString GetStartingChannel(uint inputid)
Definition: cardutil.cpp:1036
Main DVB-S device interface.
Definition: diseqc.h:52
static void GetDeviceInputNames(uint inputid, const QString &device, const QString &inputtype, QStringList &inputs)
Definition: cardutil.cpp:1790
static QString read_sys(QString sys_dev)
Definition: cardutil.cpp:2188
static QString GetDisplayName(uint inputid)
Definition: cardutil.cpp:1052