6 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(_WIN32)
9 #include <sys/sysmacros.h>
17 #include <QCoreApplication>
24 #include <QStringList>
25 #include <QTextStream>
31 #include "libmythbase/mythconfig.h"
60 #ifdef USING_HDHOMERUN
61 #include HDHOMERUN_HEADERFILE
66 bool _must_have_mplexid) :
67 m_initialSourceId(_initial_sourceid),
68 m_cardTypes(std::move(_card_types)),
69 m_mustHaveMplexId(_must_have_mplexid)
74 "Select a video source that is connected to one "
75 "or more capture cards. Default is the video source "
76 "selected in the Channel Editor page."
85 "SELECT DISTINCT videosource.name, videosource.sourceid "
86 "FROM capturecard, videosource";
91 "WHERE capturecard.sourceid = videosource.sourceid AND "
92 " capturecard.hostname = :HOSTNAME ";
96 querystr += QString(
" AND capturecard.cardtype in %1 ")
103 " AND channel.sourceid = videosource.sourceid "
104 " AND channel.mplexid != 32767 "
105 " AND channel.mplexid != 0 ";
116 for (; query.
next(); cnt++)
119 query.
value(1).toString());
134 m_initialSourceId(_initial_sourceid)
139 "The video source that is "
140 "selected in the Channel Editor page."
149 "SELECT DISTINCT videosource.name, videosource.sourceid "
150 "FROM capturecard, videosource "
151 "WHERE capturecard.sourceid = videosource.sourceid AND "
152 " capturecard.hostname = :HOSTNAME AND "
153 " videosource.sourceid = :SOURCEID ";
178 setLabel(QObject::tr(
"Max recordings"));
182 "Maximum number of simultaneous recordings MythTV will "
183 "attempt using this device. If set to a value other than "
184 "1, MythTV can sometimes record multiple programs on "
185 "the same multiplex or overlapping copies of the same "
186 "program on a single channel."
197 setLabel(QObject::tr(
"Schedule as group"));
201 "Schedule all virtual inputs on this device as a group. "
202 "This is more efficient than scheduling each input "
203 "individually. Additional, virtual inputs will be "
204 "automatically added as needed to fulfill the recording "
212 QString sourceidTag(
":WHERESOURCEID");
214 QString query(
"sourceid = " + sourceidTag);
223 QString sourceidTag(
":SETSOURCEID");
226 QString query(
"sourceid = " + sourceidTag +
", " +
237 QString cardidTag(
":WHERECARDID");
239 QString query(
"cardid = " + cardidTag);
248 QString cardidTag(
":SETCARDID");
251 QString query(
"cardid = " + cardidTag +
", " +
268 setLabel(QObject::tr(
"Listings grabber"));
277 QObject::tr(
"Transmitted guide only (EIT)"),
"eitonly");
288 #pragma message( "tv_find_grabbers is not supported yet on windows." )
294 QMutexLocker lock(&
m_lock);
302 find_grabber_proc.
Run(25s);
303 LOG(VB_GENERAL, LOG_INFO,
304 loc +
"Running 'tv_find_grabbers " +
args.join(
" ") +
"'.");
305 uint status = find_grabber_proc.
Wait();
309 QTextStream ostream(find_grabber_proc.
ReadAll());
310 while (!ostream.atEnd())
312 QString grabber_list(ostream.readLine());
313 QStringList grabber_split =
314 grabber_list.split(
"|", Qt::SkipEmptyParts);
315 QString grabber_name = grabber_split[1] +
" (xmltv)";
316 QFileInfo grabber_file(grabber_split[0]);
319 m_progList.push_back(grabber_file.fileName());
320 LOG(VB_GENERAL, LOG_DEBUG,
"Found " + grabber_split[0]);
322 LOG(VB_GENERAL, LOG_INFO, loc +
"Finished running tv_find_grabbers");
326 LOG(VB_GENERAL, LOG_ERR, loc +
"Failed to run tv_find_grabbers");
331 LOG(VB_GENERAL, LOG_INFO, loc +
"Loading results of tv_find_grabbers");
345 "UPDATE videosource "
346 "SET userid=NULL, password=NULL "
347 "WHERE xmltvgrabber NOT IN ( 'technovera' )");
354 if (name_list.size() != prog_list.size())
361 for (
uint i = 0; i < (
uint) name_list.size(); i++)
369 if (!selValue.isEmpty())
392 std::chrono::milliseconds min_val,
393 std::chrono::milliseconds max_val,
394 std::chrono::milliseconds step,
395 const QString &setting) :
397 min_val.count(), max_val.count(), step.count())
404 template<typename T, typename = std::enable_if_t<!std::is_integral<T>()>>
406 {
setValueMs(duration_cast<std::chrono::milliseconds>(newSecs)); }
413 const QString &setting) :
425 setLabel(QObject::tr(
"Scan Frequency"));
426 setHelpText(QObject::tr(
"The frequency to start scanning this video source. "
427 "This is then default for 'Full Scan (Tuned)' channel scanning. "
428 "Frequency value in Hz for DVB-T/T2/C, in kHz for DVB-S/S2. "
429 "Leave at 0 if not known. "));
440 setLabel(QObject::tr(
"Network ID"));
443 setHelpText(QObject::tr(
"If your provider has asked you to configure a "
444 "specific network identifier (Network_ID), "
445 "enter it here. Leave it at -1 otherwise."));
457 setLabel(QObject::tr(
"Bouquet ID"));
458 setHelpText(QObject::tr(
"Bouquet ID for Freesat or Sky on satellite Astra-2 28.2E. "
459 "Leave this at 0 if you do not receive this satellite. "
460 "This is needed to get the Freesat and Sky channel numbers. "
461 "Value 272 selects Freesat bouquet 'England HD'. "
462 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
475 setHelpText(QObject::tr(
"Region ID for Freesat or Sky on satellite Astra-2 28.2E. "
476 "Leave this at 0 you do not receive this satellite. "
477 "This is needed to get the Freesat and Sky channel numbers. "
478 "Value 1 selects region London. "
479 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
491 setLabel(QObject::tr(
"Logical Channel Number Offset"));
492 setHelpText(QObject::tr(
"The offset is added to each logical channel number found "
493 "during a scan of a DVB video source. This makes it possible "
494 "to give different video sources a non-overlapping range "
495 "of channel numbers. Leave at 0 if you have only one video source "
496 "or if the video sources do not have DVB logical channel numbers."));
504 setLabel(QObject::tr(
"Channel frequency table"));
510 setHelpText(QObject::tr(
"Use default unless this source uses a "
511 "different frequency table than the system wide table "
512 "defined in the General settings."));
516 m_sourceId(_sourceid)
518 setLabel(QObject::tr(
"Channel frequency table"));
537 "WHERE sourceid = :SOURCEID");
563 LOG(VB_GENERAL, LOG_INFO,
"TransFreqTableSelector::Save(void)");
574 "UPDATE videosource "
575 "SET freqtable = :FREQTABLE "
576 "WHERE sourceid = :SOURCEID");
600 setLabel(QObject::tr(
"Perform EIT scan"));
602 "If enabled, program guide data for channels on this "
603 "source will be updated with data provided by the "
604 "channels themselves 'Over-the-Air'."));
609 const QString& _grabber,
611 m_parent(_parent), m_grabber(_grabber)
615 QString
filename = QString(
"%1/%2.xmltv")
625 config->setHelpText(tr(
"Run XMLTV configure command."));
636 QString err_msg = QObject::tr(
637 "You MUST run 'mythfilldatabase --manual' the first time,\n"
638 "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
639 "channel numbers, so you have to set them manually.");
643 LOG(VB_GENERAL, LOG_ERR, err_msg);
662 : m_useEit(new
UseEIT(_parent))
671 label->setValue(QObject::tr(
"Use only the transmitted guide data."));
673 QObject::tr(
"This will usually only work with ATSC or DVB channels, "
674 "and generally provides data only for the next few days."));
686 : m_useEit(new
UseEIT(_parent))
693 label->setValue(QObject::tr(
"Do not configure a grabber"));
709 setLabel(QObject::tr(
"Video Source Setup"));
731 const QString &thecardtype)
734 query.
prepare(
"SELECT count(cardtype)"
736 " WHERE capturecard.sourceid = :SOURCEID "
737 " AND capturecard.cardtype = :CARDTYPE ;");
739 query.
bindValue(
":CARDTYPE", thecardtype);
743 int count = query.
value(0).toInt();
755 result.
prepare(
"SELECT name, sourceid FROM videosource;");
759 while (result.
next())
762 source->setLabel(result.
value(0).toString());
763 source->loadByID(result.
value(1).toInt());
772 result.
prepare(
"SELECT name, sourceid FROM videosource;");
776 while (result.
next())
779 result.
value(1).toString());
794 uint minor_max = UINT_MAX,
795 const QString& card = QString(),
796 const QRegularExpression& driver = QRegularExpression()) :
799 setLabel(QObject::tr(
"Video device"));
802 QDir dev(
"/dev/v4l",
"video*", QDir::Name, QDir::System);
804 card, driver,
false);
809 card, driver,
false);
812 dev.setPath(
"/dev/dtv");
814 card, driver,
false);
818 dev.setNameFilters(QStringList(
"dtv*"));
820 card, driver,
false);
828 [[maybe_unused]]
bool absPath =
true)
835 const QString& card,
const QRegularExpression& driver,
836 bool allow_duplicates)
839 QFileInfoList entries = dir.entryInfoList();
840 for (
const auto & fi : std::as_const(entries))
843 QString filepath = fi.absoluteFilePath();
844 int err =
lstat(filepath.toLocal8Bit().constData(), &st);
848 LOG(VB_GENERAL, LOG_ERR,
849 QString(
"Could not stat file: %1").arg(filepath));
854 if (!S_ISCHR(st.st_mode))
859 if (minor_min > minor_num || minor_max < minor_num)
867 QByteArray
tmp = filepath.toLatin1();
868 int videofd = open(
tmp.constData(), O_RDWR);
875 auto match = driver.match(driver_name);
876 if ((!driver.pattern().isEmpty() || match.hasMatch()) &&
877 (card.isEmpty() || (card_name == card)))
909 setLabel(QObject::tr(
"VBI device"));
911 setHelpText(QObject::tr(
"Device to read VBI (captions) from."));
917 QDir dev(
"/dev/v4l",
"vbi*", QDir::Name, QDir::System);
923 if ((count == 0U) && !
getValue().isEmpty())
937 [[maybe_unused]]
bool absPath =
true)
943 const QString &driver)
946 QFileInfoList entries = dir.entryInfoList();
947 for (
const auto & fi : std::as_const(entries))
949 QString device = fi.absoluteFilePath();
950 QByteArray adevice = device.toLatin1();
951 int vbifd = open(adevice.constData(), O_RDWR);
958 (driver.isEmpty() || (dn == driver)) &&
959 (card.isEmpty() || (cn == card)))
961 devices.push_back(device);
968 for (
const QString& device : std::as_const(devices))
971 return (
uint) devices.size();
984 setHelpText(QObject::tr(
"Specify the command to run, with any "
985 "needed arguments."));
1008 setLabel(QObject::tr(
"Audio device"));
1010 QDir dev(
"/dev",
"dsp*", QDir::Name, QDir::System);
1012 dev.setPath(
"/dev/sound");
1019 setHelpText(QObject::tr(
"Device to read audio from, "
1020 "if audio is separate from the video."));
1029 std::chrono::milliseconds min_val) :
1032 setLabel(QObject::tr(
"Signal timeout (ms)"));
1035 "Maximum time (in milliseconds) MythTV waits for "
1036 "a signal when scanning for channels."));
1039 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1041 SignalTimeout(parent, value, duration_cast<std::chrono::milliseconds>(min_secs)) {};
1042 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1045 duration_cast<std::chrono::milliseconds>(value),
1046 duration_cast<std::chrono::milliseconds>(min_secs)) {};
1054 std::chrono::milliseconds min_val) :
1057 setLabel(QObject::tr(
"Tuning timeout (ms)"));
1060 "Maximum time (in milliseconds) MythTV waits for "
1061 "a channel lock. For recordings, if this time is "
1062 "exceeded, the recording will be marked as failed."));
1065 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1067 ChannelTimeout(parent, value, duration_cast<std::chrono::milliseconds>(min_secs)) {};
1068 template<
typename T,
typename = std::enable_if_t<std::is_
floating_po
int_v<T>> >
1070 ChannelTimeout(parent, value, duration_cast<std::chrono::milliseconds>(min_secs)) {};
1079 setLabel(QObject::tr(
"Force audio sampling rate"));
1081 QObject::tr(
"If non-zero, override the audio sampling "
1082 "rate in the recording profile when this card is "
1083 "used. Use this if your capture card does not "
1084 "support all of the standard rates."));
1099 setLabel(QObject::tr(
"Do not adjust volume"));
1101 QObject::tr(
"Enable this option for budget BT878 based "
1102 "DVB-T cards such as the AverTV DVB-T which "
1103 "require the audio volume to be left alone."));
1113 setLabel(QObject::tr(
"DVB device"));
1115 QObject::tr(
"When you change this setting, the text below "
1116 "should change to the name and type of your card. "
1117 "If the card cannot be opened, an error message "
1118 "will be displayed."));
1136 std::stable_sort(sdevs.begin(), sdevs.end());
1141 QMap<QString,bool> in_use;
1143 for (
const QString& dev : std::as_const(sdevs))
1145 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1146 if (sel.isEmpty() && !in_use[dev])
1150 if (sel.isEmpty() && !sdevs.empty())
1153 QString usestr = QString(
" -- ");
1154 usestr += QObject::tr(
"Warning: already in use");
1156 for (
const QString& dev : std::as_const(sdevs))
1158 QString desc = dev + (in_use[dev] ? usestr :
"");
1159 desc = (
current == dev) ? dev : desc;
1183 setLabel(QObject::tr(
"Delivery system"));
1185 QObject::tr(
"If your card supports more than one delivery system "
1186 "then you can select here the one that you want to use."));
1195 setLabel(QObject::tr(
"Frontend ID"));
1197 QObject::tr(
"Identification string reported by the card. "
1198 "If the message \"Could not get card info...\" appears "
1199 "the card can be in use by another program."));
1210 setLabel(QObject::tr(
"Wait for SEQ start header"));
1213 QObject::tr(
"If enabled, drop packets from the start of a DVB "
1214 "recording until a sequence start header is seen."));
1225 setLabel(QObject::tr(
"Open DVB card on demand"));
1228 QObject::tr(
"If enabled, only open the DVB card when required, "
1229 "leaving it free for other programs at other times."));
1240 setLabel(QObject::tr(
"Use DVB card for active EIT scan"));
1243 QObject::tr(
"If enabled, activate active scanning for "
1244 "program data (EIT). When this option is enabled "
1245 "the DVB card is constantly in use."));
1255 setLabel(QObject::tr(
"DVB tuning delay (ms)"));
1258 QObject::tr(
"Some Linux DVB drivers, in particular for the "
1259 "Hauppauge Nova-T, require that we slow down "
1260 "the tuning process by specifying a delay "
1261 "(in milliseconds)."));
1272 #ifdef USING_FIREWIRE
1274 for (
auto & i : list)
1276 QString guid = i.GetGUIDString();
1280 #endif // USING_FIREWIRE
1295 setLabel(QObject::tr(
"Cable box model"));
1296 addSelection(QObject::tr(
"Motorola Generic"),
"MOTO GENERIC");
1297 addSelection(QObject::tr(
"SA/Cisco Generic"),
"SA GENERIC");
1313 QString
help = QObject::tr(
1314 "Choose the model that most closely resembles your set top box. "
1315 "Depending on firmware revision SA4200HD may work better for a "
1322 #ifdef USING_FIREWIRE
1326 #endif // USING_FIREWIRE
1333 #ifdef USING_FIREWIRE
1335 name.replace(
"Scientific-Atlanta",
"SA");
1336 name.replace(
", Inc.",
"");
1337 name.replace(
"Explorer(R)",
"");
1338 name = name.simplified();
1339 setValue((name.isEmpty()) ?
"" : name);
1340 #endif // USING_FIREWIRE
1348 "firewire_connection"))
1350 setLabel(QObject::tr(
"Connection Type"));
1371 #ifdef USING_FIREWIRE
1383 #ifdef USING_LINUX_FIREWIRE
1386 #endif // USING_LINUX_FIREWIRE
1391 model->SetGUID(dev->getValue());
1392 desc->SetGUID(dev->getValue());
1400 #ifdef USING_HDHOMERUN
1434 setLabel(QObject::tr(
"Use HDHomeRun for active EIT scan"));
1437 QObject::tr(
"If enabled, activate active scanning for "
1438 "program data (EIT). When this option is enabled "
1439 "the HDHomeRun is constantly in use."));
1450 setLabel(QObject::tr(
"Use HDHomeRun %1 (%2 %3)")
1451 .arg(deviceid, model, ipaddr));
1454 QObject::tr(
"If enabled, use tuners from this HDHomeRun "
1469 QMap<QString, HDHomeRunDevice>::iterator dit;
1470 for (dit = m_deviceList.begin(); dit != m_deviceList.end(); ++dit)
1482 buttonRecOpt->setLabel(tr(
"Recording Options"));
1483 buttonRecOpt->addChild(
new SignalTimeout(m_parent, 3s, 0.25s));
1497 for (
const auto & dev : std::as_const(devs))
1499 QStringList devinfo = dev.split(
" ");
1500 const QString& devid = devinfo.at(0);
1501 const QString& devip = devinfo.at(1);
1502 const QString& model = devinfo.at(2);
1516 QMap<QString, HDHomeRunDevice>::iterator debugit;
1519 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: %2 %3")
1520 .arg(debugit.key()).arg((*debugit).model)
1521 .arg((*debugit).cardip));
1528 QStringList devstrs = devices.split(
",");
1529 for (
const QString& devstr : std::as_const(devstrs))
1534 QByteArray ba = devstr.toUtf8();
1535 hdhomerun_device_t *device = hdhomerun_device_create_from_str(
1536 ba.data(),
nullptr);
1539 QString devid = QString(
"%1").arg(
1540 hdhomerun_device_get_device_id(device), 8, 16).toUpper();
1541 hdhomerun_device_destroy(device);
1544 QMap<QString, HDHomeRunDevice>::iterator dit;
1547 (*dit).m_checkbox->setValue(
true);
1555 QStringList devstrs;
1556 QMap<QString, HDHomeRunDevice>::iterator dit;
1559 if ((*dit).m_checkbox->boolValue())
1560 devstrs << (*dit).m_deviceId;
1562 QString devices = devstrs.join(
",");
1574 setLabel(QObject::tr(
"IP Address"));
1575 setHelpText(QObject::tr(
"Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1605 setHelpText(QObject::tr(
"Number and type of the tuner to use. eg '1-DVBT/T2'."));
1674 m_deviceId(deviceid),
1677 m_cardTuner(cardtuner),
1678 m_deviceList(devicelist),
1681 setLabel(QObject::tr(
"Available devices"));
1684 "Device IP or ID, tuner number and tuner type of available VBox devices."));
1695 std::vector<QString> devs;
1696 QMap<QString, bool> in_use;
1702 devs.push_back(it.key());
1703 in_use[it.key()] = (*it).m_inUse;
1706 QString man_addr = VBoxDeviceIDList::tr(
"Manually Enter IP Address");
1707 QString sel = man_addr;
1708 devs.push_back(sel);
1710 for (
const auto & dev : devs)
1711 sel = (
current == dev) ? dev : sel;
1713 QString usestr = QString(
" -- ");
1714 usestr += QObject::tr(
"Warning: already in use");
1716 for (
const auto & dev : devs)
1718 QString desc = dev + (in_use[dev] ? usestr :
"");
1726 else if (sel == man_addr && !
current.isEmpty())
1729 QStringList selection =
current.split(
"-");
1750 if (v == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1755 else if (!v.isEmpty())
1757 if (
m_oldValue == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1782 setValue(
"http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1785 QObject::tr(
"URL of M3U file containing RTSP/RTP/UDP/HTTP channel URLs,"
1786 " example for HDHomeRun: http://<ipv4>/lineup.m3u and for Freebox:"
1787 " http://mafreebox.freebox.fr/freeboxtv/playlist.m3u."
1806 setLabel(QObject::tr(
"ASI device"));
1824 std::stable_sort(sdevs.begin(), sdevs.end());
1833 QMap<QString,bool> in_use;
1835 for (
const QString& dev : std::as_const(sdevs))
1837 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1838 if (sel.isEmpty() && !in_use[dev])
1843 if (sel.isEmpty() && !sdevs.empty())
1846 QString usestr = QString(
" -- ");
1847 usestr += QObject::tr(
"Warning: already in use");
1851 for (
const QString& dev : std::as_const(sdevs))
1853 QString desc = dev + (in_use[dev] ? usestr :
"");
1854 desc = (
current == dev) ? dev : desc;
1856 found |= (dev == sel);
1860 if (!found && !
current.isEmpty())
1862 QString desc =
current +
" -- " +
1863 QObject::tr(
"Warning: unable to open");
1901 if (device.isEmpty())
1918 LOG(VB_GENERAL, LOG_WARNING,
1919 "ASIConfigurationGroup::probeCard(), Warning: " +
error);
1935 device->setHelpText(tr(
"A local file used to simulate a recording."
1936 " Leave empty to use MythEvents to trigger an"
1937 " external program to import recording files."));
1959 QFileInfo fileInfo(device);
1962 if (device.startsWith(
"file:", Qt::CaseInsensitive))
1963 fileInfo.setFile(device.mid(5));
1965 if (fileInfo.exists())
1967 if (fileInfo.isReadable() && (fileInfo.isFile()))
1970 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
1974 ci = tr(
"File not readable");
1979 ci = tr(
"File %1 does not exist").arg(device);
2003 m_desc->setLabel(tr(
"Description"));
2005 m_deviceId, m_desc, m_cardIp, m_cardTuner, &m_deviceList, m_parent);
2031 for (
const auto & dev : std::as_const(devs))
2033 QStringList devinfo = dev.split(
" ");
2034 const QString&
id = devinfo.at(0);
2035 const QString& ip = devinfo.at(1);
2036 const QString& tunerNo = devinfo.at(2);
2037 const QString& tunerType = devinfo.at(3);
2056 for (
const auto & dev : std::as_const(db))
2058 QMap<QString, VBoxDevice>::iterator dit;
2062 (*dit).m_inUse =
true;
2099 static const QRegularExpression ipV4Regex
2100 {
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$" };
2101 auto match = ipV4Regex.match(ip +
".");
2102 if (match.hasMatch())
2111 static const QRegularExpression oneDigit {
"^\\d$" };
2112 auto match = oneDigit.match(tuner);
2113 if (match.hasMatch())
2128 static const QRegularExpression newstyle { R
"(^([0-9.]+)-(\d|RTP)\.(\d)$)" };
2129 auto match = newstyle.match(
getValue());
2130 if (match.hasMatch())
2141 desc->setLabel(tr(
"CetonConfigurationGroup",
"Description"));
2143 tr(
"IP Address of the Ceton device (192.168.200.1 by default)"));
2145 tr(
"Number of the tuner on the Ceton device (first tuner is number 0)"));
2181 const QString &inputtype) :
2187 QRegularExpression drv {
"^(?!ivtv|hdpvr|(saa7164(.*))).*$" };
2211 QString cn = tr(
"Failed to open");
2215 QByteArray adevice = device.toLatin1();
2216 int videofd = open(adevice.constData(), O_RDWR);
2220 ci = cn = tr(
"Failed to probe");
2221 else if (!dn.isEmpty())
2222 ci = cn +
" [" + dn +
"]";
2237 QRegularExpression drv {
"^(ivtv|(saa7164(.*)))$" };
2260 QString cn = tr(
"Failed to open");
2264 QByteArray adevice = device.toLatin1();
2265 int videofd = open(adevice.constData(), O_RDWR);
2269 ci = cn = tr(
"Failed to probe");
2270 else if (!dn.isEmpty())
2271 ci = cn +
" [" + dn +
"]";
2287 device->setHelpText(tr(
"A local MPEG file used to simulate a recording."));
2310 QFileInfo fileInfo(device);
2311 if (fileInfo.exists())
2313 if (fileInfo.isReadable() && (fileInfo.isFile()))
2316 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
2320 ci = tr(
"File not readable");
2325 ci = tr(
"File does not exist");
2332 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2333 ExternalConfigurationGroup::ExternalConfigurationGroup(
CaptureCard &a_parent,
2340 device->setLabel(tr(
"Command path"));
2341 device->setHelpText(tr(
"A 'black box' application controlled via stdin, status on "
2342 "stderr and TransportStream read from stdout.\n"
2343 "Use absolute path or path relative to the current directory."));
2353 this, &ExternalConfigurationGroup::probeApp);
2355 probeApp(device->getValue());
2358 void ExternalConfigurationGroup::probeApp(
const QString & path)
2360 int idx1 = path.startsWith(
"file:", Qt::CaseInsensitive) ? 5 : 0;
2361 int idx2 = path.indexOf(
' ', idx1);
2364 QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2366 if (fileInfo.exists())
2368 ci = tr(
"File '%1' is valid.").arg(fileInfo.absoluteFilePath());
2369 if (!fileInfo.isReadable() || !fileInfo.isFile())
2370 ci = tr(
"WARNING: File '%1' is not readable.")
2371 .arg(fileInfo.absoluteFilePath());
2372 if (!fileInfo.isExecutable())
2373 ci = tr(
"WARNING: File '%1' is not executable.")
2374 .arg(fileInfo.absoluteFilePath());
2378 ci = tr(
"WARNING: File '%1' does not exist.")
2379 .arg(fileInfo.absoluteFilePath());
2382 m_info->setValue(ci);
2383 m_info->setHelpText(ci);
2385 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2395 QRegularExpression(
"^hdpvr$"));
2418 QString cn = tr(
"Failed to open");
2422 int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2426 ci = cn = tr(
"Failed to probe");
2427 else if (!dn.isEmpty())
2428 ci = cn +
" [" + dn +
"]";
2444 setLabel(QObject::tr(
"V4L2 encoder devices (multirec capable)"));
2459 if (!device_name.isEmpty())
2466 QString card_name = tr(
"Failed to open");
2467 QString card_info = card_name;
2486 if (audioinput->fillSelections(device_name) > 1)
2488 audioinput->setName(
"AudioInput");
2501 vbidev->setName(
"VBIDevice");
2514 #endif // USING_V4L2
2519 setLabel(QObject::tr(
"Capture Card Setup"));
2521 auto* cardtype =
new CardType(parent);
2525 cardtype->addTargetedChild(
"DVB",
2530 cardtype->addTargetedChild(
"HDPVR",
2532 #endif // USING_V4L2
2534 #ifdef USING_HDHOMERUN
2535 cardtype->addTargetedChild(
"HDHOMERUN",
2537 #endif // USING_HDHOMERUN
2540 cardtype->addTargetedChild(
"VBOX",
2542 #endif // USING_VBOX
2545 cardtype->addTargetedChild(
"SATIP",
2546 new SatIPConfigurationGroup(parent, *cardtype));
2547 #endif // USING_SATIP
2549 #ifdef USING_FIREWIRE
2551 #endif // USING_FIREWIRE
2555 #endif // USING_CETON
2559 #endif // USING_IPTV
2562 cardtype->addTargetedChild(
"V4L2ENC",
new V4L2encGroup(parent, *cardtype));
2563 cardtype->addTargetedChild(
"V4L",
2565 cardtype->addTargetedChild(
"MJPEG",
2567 cardtype->addTargetedChild(
"GO7007",
2569 cardtype->addTargetedChild(
"MPEG",
2571 #endif // USING_V4L2
2574 cardtype->addTargetedChild(
"ASI",
2579 cardtype->addTargetedChild(
"IMPORT",
2581 cardtype->addTargetedChild(
"DEMO",
2583 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2584 cardtype->addTargetedChild(
"EXTERNAL",
2585 new ExternalConfigurationGroup(parent,
2611 "SELECT cardid, videodevice, cardtype, displayname "
2613 "WHERE hostname = :HOSTNAME AND parentid = 0 "
2627 while (query.
next())
2630 QString videodevice = query.
value(1).toString();
2631 QString cardtype = query.
value(2).toString();
2632 QString displayname = query.
value(3).toString();
2634 QString label = QString(
"%1 (%2)")
2638 card->loadByID(cardid);
2639 card->setLabel(label);
2676 if (dev != init_dev)
2678 if (!init_dev.isEmpty())
2697 for (
uint clone : clones)
2714 setLabel(QObject::tr(
"Card type"));
2715 setHelpText(QObject::tr(
"Change the cardtype to the appropriate type for "
2716 "the capture card you are configuring."));
2724 QObject::tr(
"DVB-T/S/C, ATSC or ISDB-T tuner card"),
"DVB");
2729 QObject::tr(
"V4L2 encoder"),
"V4L2ENC");
2731 QObject::tr(
"HD-PVR H.264 encoder"),
"HDPVR");
2732 #endif // USING_V4L2
2734 #ifdef USING_HDHOMERUN
2736 QObject::tr(
"HDHomeRun networked tuner"),
"HDHOMERUN");
2737 #endif // USING_HDHOMERUN
2741 QObject::tr(
"Sat>IP networked tuner"),
"SATIP");
2742 #endif // USING_SATIP
2746 QObject::tr(
"V@Box TV Gateway networked tuner"),
"VBOX");
2747 #endif // USING_VBOX
2749 #ifdef USING_FIREWIRE
2751 QObject::tr(
"FireWire cable box"),
"FIREWIRE");
2752 #endif // USING_FIREWIRE
2756 QObject::tr(
"Ceton Cablecard tuner"),
"CETON");
2757 #endif // USING_CETON
2760 setting->
addSelection(QObject::tr(
"IPTV recorder"),
"FREEBOX");
2761 #endif // USING_IPTV
2765 QObject::tr(
"Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"),
"MPEG");
2767 QObject::tr(
"Analog to MJPEG encoder card (Matrox G200, DC10, etc)"),
"MJPEG");
2769 QObject::tr(
"Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2772 QObject::tr(
"Analog capture card"),
"V4L");
2773 #endif // USING_V4L2
2776 setting->
addSelection(QObject::tr(
"DVEO ASI recorder"),
"ASI");
2779 setting->
addSelection(QObject::tr(
"Import test recorder"),
"IMPORT");
2780 setting->
addSelection(QObject::tr(
"Demo test recorder"),
"DEMO");
2781 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2782 setting->
addSelection(QObject::tr(
"External (black box) recorder"),
2793 setLabel(QObject::tr(
"Input name"));
2806 if (storage ==
nullptr)
2813 while (!inputs.isEmpty())
2826 setLabel(QObject::tr(
"Delivery system"));
2828 "This shows the delivery system (modulation), for instance DVB-T2, "
2829 "that you have selected when you configured the capture card. "
2830 "This must be the same as the modulation used by the video source. "));
2842 setLabel(QObject::tr(
"Display name"));
2844 "This name is displayed on screen when Live TV begins "
2845 "and in various other places. Make sure the last two "
2846 "characters are unique for each input or use a "
2847 "slash ('/') to designate the unique portion."));
2873 setLabel(QObject::tr(
"Video source"));
2897 setLabel(QObject::tr(
"Input group") +
2900 "Leave as 'Generic' unless this input is shared with "
2901 "another device. Only one of the inputs in an input "
2902 "group will be allowed to record at any given time."));
2905 void Load(
void)
override;
2930 LOG(VB_GENERAL, LOG_DEBUG, QString(
"InputGroup::Load() %1 %2")
2935 QMap<uint, uint> grpcnt;
2936 std::vector<QString> names;
2937 std::vector<uint> grpid;
2938 std::vector<uint> selected_groupids;
2940 names.push_back(QObject::tr(
"Generic"));
2946 "SELECT cardinputid, inputgroupid, inputgroupname "
2948 "WHERE inputgroupname LIKE 'user:%' "
2949 "ORDER BY inputgroupid, cardinputid, inputgroupname");
2957 while (query.
next())
2960 if ((inputid != 0U) && (query.
value(0).toUInt() == inputid))
2961 selected_groupids.push_back(groupid);
2965 if (grpcnt[groupid] == 1)
2967 names.push_back(query.
value(2).toString().mid(5, -1));
2968 grpid.push_back(groupid);
2979 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group num: %1 id: %2")
2983 for (
uint i = 0; i < selected_groupids.size(); i++)
2984 msg += QString(
"%1 ").arg(selected_groupids[i]);
2985 LOG(VB_GENERAL, LOG_DEBUG, msg);
2992 for (
size_t i = 0; i < names.size(); i++)
2995 index = (sel) ? i : index;
2998 LOG(VB_GENERAL, LOG_DEBUG, QString(
"grpid %1, name '%2', i %3, s %4")
2999 .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ?
"T" :
"F"));
3002 addSelection(names[i], QString::number(grpid[i]), sel);
3006 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group index: %1").arg(index));
3021 setLabel(QObject::tr(
"Use quick tuning"));
3026 "If enabled, MythTV will tune using only the "
3027 "MPEG program number. The program numbers "
3028 "change more often than DVB or ATSC tuning "
3029 "parameters, so this is slightly less reliable. "
3030 "This will also inhibit EIT gathering during "
3031 "Live TV and recording."));
3041 setLabel(QObject::tr(
"External channel change command"));
3043 setHelpText(QObject::tr(
"If specified, this command will be run to "
3044 "change the channel for inputs which have an external "
3045 "tuner device such as a cable box. The first argument "
3046 "will be the channel number."));
3056 setLabel(QObject::tr(
"Preset tuner to channel"));
3058 setHelpText(QObject::tr(
"Leave this blank unless you have an external "
3059 "tuner that is connected to the tuner input of your card. "
3060 "If so, you will need to specify the preset channel for "
3061 "the signal (normally 3 or 4)."));
3068 if (sourceid.isEmpty() || !sourceid.toUInt())
3073 if (storage ==
nullptr)
3080 if (channels.empty())
3083 startChan.isEmpty() ?
"0" : startChan);
3091 bool has_visible =
false;
3092 for (
size_t i = 0; i < channels.size() && !has_visible; i++)
3095 for (
auto & channel : channels)
3097 const QString channum = channel.m_chanNum;
3098 bool sel = channum == startChan;
3099 if (!has_visible || channel.m_visible || sel)
3113 setLabel(QObject::tr(
"Input priority"));
3115 setHelpText(QObject::tr(
"If the input priority is not equal for "
3116 "all inputs, the scheduler may choose to record a show "
3117 "at a later time so that it can record on an input with "
3118 "a higher value."));
3129 setLabel(QObject::tr(
"Schedule order"));
3131 setHelpText(QObject::tr(
"If priorities and other factors are equal "
3132 "the scheduler will choose the available "
3133 "input with the lowest, non-zero value. "
3134 "Setting this value to zero will make the "
3135 "input unavailable to the scheduler."));
3146 setLabel(QObject::tr(
"Live TV order"));
3148 setHelpText(QObject::tr(
"When entering Live TV, the available, local "
3149 "input with the lowest, non-zero value will "
3150 "be used. If no local inputs are available, "
3151 "the available, remote input with the lowest, "
3152 "non-zero value will be used. "
3153 "Setting this value to zero will make the "
3154 "input unavailable to live TV."));
3165 setLabel(QObject::tr(
"Use DishNet long-term EIT data"));
3169 "If you point your satellite dish toward DishNet's birds, "
3170 "you may wish to enable this feature. For best results, "
3171 "enable general EIT collection as well."));
3197 if (
"DVB" == cardtype)
3219 if (
"DVB" == cardtype)
3224 tr(
"Use channel scanner to find channels for this input."));
3227 tr(
"This uses the listings data source to "
3228 "provide the channels for this input.") +
" " +
3229 tr(
"This can take a long time to run."));
3238 interact->setLabel(QObject::tr(
"Interactions between inputs"));
3248 interact->addChild(
new LiveTVOrder(*
this, _cardid));
3252 ingrpbtn->setHelpText(
3253 QObject::tr(
"Input groups are only needed when two or more cards "
3254 "share the same resource such as a FireWire card and "
3255 "an analog card input controlling the same set top box."));
3256 interact->addChild(ingrpbtn);
3262 setObjectName(
"CardInput");
3288 bool enable = (sourceid.toInt() > 0);
3305 auto *settingdialog =
3308 if (settingdialog->Create())
3316 delete settingdialog;
3324 ShowOkPopup(tr(
"Sorry, this Input Group name cannot be blank."));
3328 QString new_name = QString(
"user:") + name;
3331 query.
prepare(
"SELECT inputgroupname "
3333 "WHERE inputgroupname = :GROUPNAME");
3334 query.
bindValue(
":GROUPNAME", new_name);
3344 ShowOkPopup(tr(
"Sorry, this Input Group name is already in use."));
3371 #ifdef USING_BACKEND
3379 LOG(VB_GENERAL, LOG_ERR,
3380 QString(
"Sorry, %1 cards do not yet support scanning.")
3392 [srcid,
this, num_channels_before]()
3396 if (num_channels_before)
3410 LOG(VB_GENERAL, LOG_ERR,
"You must compile the backend "
3411 "to be able to scan for channels");
3431 cardtype !=
"HDHOMERUN" &&
3432 !num_channels_before)
3434 LOG(VB_GENERAL, LOG_ERR,
"Skipping channel fetch, you need to "
3435 "scan for channels first.");
3444 if (num_channels_before)
3453 QString cardinputidTag(
":WHERECARDID");
3455 QString query(
"cardid = " + cardinputidTag);
3464 QString cardinputidTag(
":SETCARDID");
3467 QString query(
"cardid = " + cardinputidTag +
", " +
3486 query.
prepare(
"SELECT cardid FROM capturecard "
3487 "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3489 query.
bindValue(
":INPUTNAME", _inputname);
3542 tr(
"Are you sure you want to delete "
3551 tr(
"Are you sure you want to delete "
3552 "ALL capture cards?"),
3560 card->setLabel(tr(
"New capture card"));
3586 "WHERE hostname = :HOSTNAME");
3592 tr(
"Error getting list of cards for this host. "
3593 "Unable to delete capturecards for %1")
3600 while (cards.
next())
3616 AddSelection(QObject::tr(
"(Delete all capture cards on %1)")
3619 AddSelection(QObject::tr(
"(Delete all capture cards)"),
3633 AddSelection(QObject::tr(
"(Delete all video sources)"),
3656 tr(
"Are you sure you want to delete "
3657 "ALL video sources?"),
3675 source->setLabel(tr(
"New video source"));
3697 "SELECT cardid, videodevice, cardtype, displayname "
3699 "WHERE hostname = :HOSTNAME "
3700 " AND parentid = 0 "
3710 while (query.
next())
3713 QString videodevice = query.
value(1).toString();
3714 QString cardtype = query.
value(2).toString();
3715 QString displayname = query.
value(3).toString();
3717 auto *cardinput =
new CardInput(cardtype, videodevice, cardid);
3718 cardinput->loadByID(cardid);
3719 QString inputlabel = QString(
"%1 (%2) -> %3")
3721 displayname, cardinput->getSourceName());
3723 cardinput->setLabel(inputlabel);
3734 QString short_name = name;
3735 if (short_name.startsWith(
"LG Electronics"))
3736 short_name = short_name.right(short_name.length() - 15);
3737 if (short_name.startsWith(
"Oren"))
3738 short_name = short_name.right(short_name.length() - 5);
3739 if (short_name.startsWith(
"Nextwave"))
3740 short_name = short_name.right(short_name.length() - 9);
3741 if (short_name.startsWith(
"frontend", Qt::CaseInsensitive))
3742 short_name = short_name.left(short_name.length() - 9);
3743 if (short_name.endsWith(
"VSB/QAM"))
3744 short_name = short_name.left(short_name.length() - 8);
3745 if (short_name.endsWith(
"VSB"))
3746 short_name = short_name.left(short_name.length() - 4);
3747 if (short_name.endsWith(
"DVB-T"))
3748 short_name = short_name.left(short_name.length() - 6);
3754 short_name = short_name.simplified();
3755 if (short_name.startsWith(
"or51211", Qt::CaseInsensitive))
3756 short_name =
"pcHDTV HD-2000";
3757 else if (short_name.startsWith(
"or51132", Qt::CaseInsensitive))
3758 short_name =
"pcHDTV HD-3000";
3759 else if (short_name.startsWith(
"bcm3510", Qt::CaseInsensitive))
3760 short_name =
"Air2PC v1";
3761 else if (short_name.startsWith(
"nxt2002", Qt::CaseInsensitive) ||
3762 short_name.startsWith(
"nxt200x", Qt::CaseInsensitive))
3763 short_name =
"Air2PC v2";
3764 else if (short_name.startsWith(
"lgdt3302", Qt::CaseInsensitive))
3765 short_name =
"DViCO HDTV3";
3766 else if (short_name.startsWith(
"lgdt3303", Qt::CaseInsensitive))
3767 short_name =
"DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3792 if (videodevice.isEmpty())
3810 QString err_open = tr(
"Could not open card %1").arg(videodevice);
3811 QString err_other = tr(
"Could not get card info for card %1").arg(videodevice);
3857 if (frontend_name.toLower().indexOf(
"usb") >= 0)
3864 if ((frontend_name ==
"DiBcom 3000P/M-C DVB-T") ||
3866 "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
3871 #if 0 // frontends on hybrid DVB-T/Analog cards
3873 m_buttonAnalog->setVisible(
3874 short_name.startsWith(
"zarlink zl10353",
3875 Qt::CaseInsensitive) ||
3876 short_name.startsWith(
"wintv hvr 900 m/r: 65008/a1c0",
3877 Qt::CaseInsensitive) ||
3878 short_name.startsWith(
"philips tda10046h",
3879 Qt::CaseInsensitive));
3893 if (frontend_name ==
"Nextwave NXT200X VSB/QAM frontend")
3899 #if 0 // frontends on hybrid DVB-T/Analog cards
3900 if (frontend_name.toLower().indexOf(
"usb") < 0)
3902 m_buttonAnalog->setVisible(
3903 short_name.startsWith(
"pchdtv", Qt::CaseInsensitive) ||
3904 short_name.startsWith(
"dvico", Qt::CaseInsensitive) ||
3905 short_name.startsWith(
"nextwave", Qt::CaseInsensitive));
3918 for (
const auto & item : std::as_const(delsyslist))
3920 LOG(VB_GENERAL, LOG_DEBUG, QString(
"DVBCardType: add deliverysystem:%1")
3928 if (!delsys.isEmpty())
3940 QString dev, QString
type) :
3942 m_lastDevice(std::move(dev)), m_lastCardType(std::move(
type))
3944 setLabel(QObject::tr(
"Audio input"));
3945 setHelpText(QObject::tr(
"If there is more than one audio input, "
3946 "select which one to use."));
3959 if (device.isEmpty())
3963 QStringList inputs =
3966 for (
uint i = 0; i < (
uint)inputs.size(); i++)
3971 return inputs.size();
4054 explicit DiSEqCPosition(
const CaptureCard &parent,
int value,
int min_val) :
4058 setLabel(QObject::tr(
"DiSEqC position"));
4059 setHelpText(QObject::tr(
"Position of the LNB on the DiSEqC switch. "
4060 "Leave at 1 if there is no DiSEqC switch "
4061 "and the LNB is directly connected to the SatIP server. "
4062 "This value is used as signal source (attribute src) in "
4063 "the SatIP tune command."));
4068 SatIPConfigurationGroup::SatIPConfigurationGroup
4071 m_deviceId(new SatIPDeviceID(a_parent))
4077 m_friendlyName =
new SatIPDeviceAttribute(tr(
"Friendly name"), tr(
"Friendly name of the Sat>IP server"));
4078 m_tunerType =
new SatIPDeviceAttribute(tr(
"Tuner type"), tr(
"Type of the selected tuner"));
4079 m_tunerIndex =
new SatIPDeviceAttribute(tr(
"Tuner index"), tr(
"Index of the tuner on the Sat>IP server"));
4081 m_deviceIdList =
new SatIPDeviceIDList(
4082 m_deviceId, m_friendlyName, m_tunerType, m_tunerIndex, &m_deviceList,
m_parent);
4094 connect(m_deviceIdList, &SatIPDeviceIDList::NewTuner,
4095 m_deviceId, &SatIPDeviceID::SetTuner);
4098 void SatIPConfigurationGroup::FillDeviceList(
void)
4100 m_deviceList.clear();
4106 for (
const auto & dev : std::as_const(devs))
4108 QStringList devparts = dev.split(
" ");
4109 const QString&
id = devparts.value(0);
4110 const QString& name = devparts.value(1);
4111 const QString& ip = devparts.value(2);
4112 const QString& tunerno = devparts.value(3);
4113 const QString& tunertype = devparts.value(4);
4116 device.m_deviceId = id;
4117 device.m_cardIP = ip;
4118 device.m_inUse =
false;
4119 device.m_friendlyName = name;
4120 device.m_tunerNo = tunerno;
4121 device.m_tunerType = tunertype;
4122 device.m_mythDeviceId = QString(
"%1:%2:%3").arg(
id, tunertype, tunerno);
4124 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3").arg(name, tunertype, tunerno);
4126 m_deviceList[device.m_mythDeviceId] = device;
4128 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"SatIP: Add %1 '%2' '%3'")
4129 .arg(device.m_mythDeviceId, device.m_friendlyName, friendlyIdentifier));
4135 for (
const auto& dev : std::as_const(db))
4137 auto dit = m_deviceList.find(dev);
4138 if (dit != m_deviceList.end())
4140 (*dit).m_inUse =
true;
4145 SatIPDeviceIDList::SatIPDeviceIDList(
4146 SatIPDeviceID *deviceId,
4147 SatIPDeviceAttribute *friendlyName,
4148 SatIPDeviceAttribute *tunerType,
4149 SatIPDeviceAttribute *tunerIndex,
4150 SatIPDeviceList *deviceList,
4152 m_deviceId(deviceId),
4153 m_friendlyName(friendlyName),
4154 m_tunerType(tunerType),
4155 m_tunerIndex(tunerIndex),
4156 m_deviceList(deviceList),
4160 setHelpText(tr(
"Device IP or ID, tuner number and tuner type of available Sat>IP device"));
4163 this, &SatIPDeviceIDList::UpdateDevices);
4166 void SatIPDeviceIDList::Load(
void)
4170 int cardid = m_parent.getCardID();
4173 fillSelections(device);
4176 void SatIPDeviceIDList::UpdateDevices(
const QString &v)
4178 SatIPDevice dev = (*m_deviceList)[v];
4179 m_deviceId->setValue(dev.m_mythDeviceId);
4180 m_friendlyName->setValue(dev.m_friendlyName);
4181 m_tunerType->setValue(dev.m_tunerType);
4182 m_tunerIndex->setValue(dev.m_tunerNo);
4185 void SatIPDeviceIDList::fillSelections(
const QString &cur)
4189 std::vector<QString> names;
4190 std::vector<QString> devs;
4191 QMap<QString, bool> in_use;
4196 SatIPDeviceList::iterator it = m_deviceList->begin();
4197 for(; it != m_deviceList->end(); ++it)
4199 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3")
4200 .arg((*it).m_friendlyName, (*it).m_tunerType, (*it).m_tunerNo);
4201 names.push_back(friendlyIdentifier);
4203 devs.push_back(it.key());
4204 in_use[it.key()] = (*it).m_inUse;
4207 for (
const auto& it2s : devs)
4209 sel = (
current == it2s) ? it2s : sel;
4212 QString usestr = QString(
" -- ");
4213 usestr += tr(
"Warning: already in use");
4215 for (
uint i = 0; i < devs.size(); ++i)
4217 const QString& dev = devs[i];
4218 const QString& name = names[i];
4219 bool dev_in_use = (dev == sel) ?
false : in_use[devs[i]];
4220 QString desc = name + (dev_in_use ? usestr :
"");
4221 addSelection(desc, dev, dev == sel);
4225 SatIPDeviceID::SatIPDeviceID(
const CaptureCard &parent) :
4235 void SatIPDeviceID::Load(
void)
4240 void SatIPDeviceID::SetTuner(
const QString &tuner)
4245 SatIPDeviceAttribute::SatIPDeviceAttribute(
const QString& label,
const QString& helptext)
4248 setHelpText(helptext);
4250 #endif // USING_SATIP