6 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__) || defined(_WIN32)
9 #include <sys/sysmacros.h>
17 #include <QCoreApplication>
24 #include <QStringList>
25 #include <QTextStream>
32 #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 #if QT_VERSION < QT_VERSION_CHECK(5,14,0)
314 QStringList grabber_split =
315 grabber_list.split(
"|", QString::SkipEmptyParts);
317 QStringList grabber_split =
318 grabber_list.split(
"|", Qt::SkipEmptyParts);
320 QString grabber_name = grabber_split[1] +
" (xmltv)";
321 QFileInfo grabber_file(grabber_split[0]);
324 m_progList.push_back(grabber_file.fileName());
325 LOG(VB_GENERAL, LOG_DEBUG,
"Found " + grabber_split[0]);
327 LOG(VB_GENERAL, LOG_INFO, loc +
"Finished running tv_find_grabbers");
331 LOG(VB_GENERAL, LOG_ERR, loc +
"Failed to run tv_find_grabbers");
336 LOG(VB_GENERAL, LOG_INFO, loc +
"Loading results of tv_find_grabbers");
350 "UPDATE videosource "
351 "SET userid=NULL, password=NULL "
352 "WHERE xmltvgrabber NOT IN ( 'technovera' )");
359 if (name_list.size() != prog_list.size())
366 for (
uint i = 0; i < (
uint) name_list.size(); i++)
374 if (!selValue.isEmpty())
397 std::chrono::milliseconds min_val,
398 std::chrono::milliseconds max_val,
399 std::chrono::milliseconds step,
400 const QString &setting) :
402 min_val.count(), max_val.count(), step.count())
409 template<typename T, typename = typename std::enable_if<!std::is_integral<T>()>>
411 {
setValueMs(duration_cast<std::chrono::milliseconds>(newSecs)); }
418 const QString &setting) :
430 setLabel(QObject::tr(
"Scan Frequency"));
431 setHelpText(QObject::tr(
"The frequency to start scanning this video source. "
432 "This is then default for 'Full Scan (Tuned)' channel scanning. "
433 "Frequency value in Hz for DVB-T/T2/C, in kHz for DVB-S/S2. "
434 "Leave at 0 if not known. "));
445 setLabel(QObject::tr(
"Network ID"));
448 setHelpText(QObject::tr(
"If your provider has asked you to configure a "
449 "specific network identifier (Network_ID), "
450 "enter it here. Leave it at -1 otherwise."));
462 setLabel(QObject::tr(
"Bouquet ID"));
463 setHelpText(QObject::tr(
"Bouquet ID for Freesat or Sky on satellite Astra-2 28.2E. "
464 "Leave this at 0 if you do not receive this satellite. "
465 "This is needed to get the Freesat and Sky channel numbers. "
466 "Value 272 selects Freesat bouquet 'England HD'. "
467 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
480 setHelpText(QObject::tr(
"Region ID for Freesat or Sky on satellite Astra-2 28.2E. "
481 "Leave this at 0 you do not receive this satellite. "
482 "This is needed to get the Freesat and Sky channel numbers. "
483 "Value 1 selects region London. "
484 "See the MythTV Wiki https://www.mythtv.org/wiki/DVB_UK."));
496 setLabel(QObject::tr(
"Logical Channel Number Offset"));
497 setHelpText(QObject::tr(
"The offset is added to each logical channel number found "
498 "during a scan of a DVB video source. This makes it possible "
499 "to give different video sources a non-overlapping range "
500 "of channel numbers. Leave at 0 if you have only one video source "
501 "or if the video sources do not have DVB logical channel numbers."));
509 setLabel(QObject::tr(
"Channel frequency table"));
515 setHelpText(QObject::tr(
"Use default unless this source uses a "
516 "different frequency table than the system wide table "
517 "defined in the General settings."));
521 m_sourceId(_sourceid)
523 setLabel(QObject::tr(
"Channel frequency table"));
542 "WHERE sourceid = :SOURCEID");
568 LOG(VB_GENERAL, LOG_INFO,
"TransFreqTableSelector::Save(void)");
579 "UPDATE videosource "
580 "SET freqtable = :FREQTABLE "
581 "WHERE sourceid = :SOURCEID");
605 setLabel(QObject::tr(
"Perform EIT scan"));
607 "If enabled, program guide data for channels on this "
608 "source will be updated with data provided by the "
609 "channels themselves 'Over-the-Air'."));
614 const QString& _grabber,
616 m_parent(_parent), m_grabber(_grabber)
620 QString
filename = QString(
"%1/%2.xmltv")
630 config->setHelpText(tr(
"Run XMLTV configure command."));
641 QString err_msg = QObject::tr(
642 "You MUST run 'mythfilldatabase --manual' the first time,\n"
643 "instead of just 'mythfilldatabase'.\nYour grabber does not provide "
644 "channel numbers, so you have to set them manually.");
648 LOG(VB_GENERAL, LOG_ERR, err_msg);
676 label->setValue(QObject::tr(
"Use only the transmitted guide data."));
678 QObject::tr(
"This will usually only work with ATSC or DVB channels, "
679 "and generally provides data only for the next few days."));
698 label->setValue(QObject::tr(
"Do not configure a grabber"));
714 setLabel(QObject::tr(
"Video Source Setup"));
736 const QString &thecardtype)
739 query.
prepare(
"SELECT count(cardtype)"
741 " WHERE capturecard.sourceid = :SOURCEID "
742 " AND capturecard.cardtype = :CARDTYPE ;");
744 query.
bindValue(
":CARDTYPE", thecardtype);
748 int count = query.
value(0).toInt();
760 result.
prepare(
"SELECT name, sourceid FROM videosource;");
764 while (result.
next())
767 source->setLabel(result.
value(0).toString());
768 source->loadByID(result.
value(1).toInt());
777 result.
prepare(
"SELECT name, sourceid FROM videosource;");
781 while (result.
next())
784 result.
value(1).toString());
799 uint minor_max = UINT_MAX,
800 const QString& card = QString(),
801 const QRegularExpression& driver = QRegularExpression()) :
804 setLabel(QObject::tr(
"Video device"));
807 QDir dev(
"/dev/v4l",
"video*", QDir::Name, QDir::System);
809 card, driver,
false);
814 card, driver,
false);
817 dev.setPath(
"/dev/dtv");
819 card, driver,
false);
823 dev.setNameFilters(QStringList(
"dtv*"));
825 card, driver,
false);
842 const QString& card,
const QRegularExpression& driver,
843 bool allow_duplicates)
846 QFileInfoList entries = dir.entryInfoList();
847 for (
const auto & fi : qAsConst(entries))
850 QString filepath = fi.absoluteFilePath();
851 int err =
lstat(filepath.toLocal8Bit().constData(), &st);
855 LOG(VB_GENERAL, LOG_ERR,
856 QString(
"Could not stat file: %1").arg(filepath));
861 if (!S_ISCHR(st.st_mode))
866 if (minor_min > minor_num || minor_max < minor_num)
874 QByteArray
tmp = filepath.toLatin1();
875 int videofd = open(
tmp.constData(), O_RDWR);
882 auto match = driver.match(driver_name);
883 if ((!driver.pattern().isEmpty() || match.hasMatch()) &&
884 (card.isEmpty() || (card_name == card)))
916 setLabel(QObject::tr(
"VBI device"));
918 setHelpText(QObject::tr(
"Device to read VBI (captions) from."));
925 QDir dev(
"/dev/v4l",
"vbi*", QDir::Name, QDir::System);
952 const QString &driver)
955 QFileInfoList entries = dir.entryInfoList();
956 for (
const auto & fi : qAsConst(entries))
958 QString device = fi.absoluteFilePath();
959 QByteArray adevice = device.toLatin1();
960 int vbifd = open(adevice.constData(), O_RDWR);
967 (driver.isEmpty() || (dn == driver)) &&
968 (card.isEmpty() || (cn == card)))
970 devices.push_back(device);
977 for (
const QString& device : qAsConst(devices))
980 return (
uint) devices.size();
993 setHelpText(QObject::tr(
"Specify the command to run, with any "
994 "needed arguments."));
1006 setLabel(QObject::tr(
"File path"));
1017 setLabel(QObject::tr(
"Audio device"));
1019 QDir dev(
"/dev",
"dsp*", QDir::Name, QDir::System);
1021 dev.setPath(
"/dev/sound");
1028 setHelpText(QObject::tr(
"Device to read audio from, "
1029 "if audio is separate from the video."));
1038 std::chrono::milliseconds min_val) :
1041 setLabel(QObject::tr(
"Signal timeout (ms)"));
1044 "Maximum time (in milliseconds) MythTV waits for "
1045 "a signal when scanning for channels."));
1048 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1050 SignalTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1051 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1054 duration_cast<
std::chrono::milliseconds>(value),
1055 duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1063 std::chrono::milliseconds min_val) :
1066 setLabel(QObject::tr(
"Tuning timeout (ms)"));
1069 "Maximum time (in milliseconds) MythTV waits for "
1070 "a channel lock. For recordings, if this time is "
1071 "exceeded, the recording will be marked as failed."));
1074 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1076 ChannelTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1077 template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value>
::type >
1079 ChannelTimeout(parent, value, duration_cast<
std::chrono::milliseconds>(min_secs)) {};
1088 setLabel(QObject::tr(
"Force audio sampling rate"));
1090 QObject::tr(
"If non-zero, override the audio sampling "
1091 "rate in the recording profile when this card is "
1092 "used. Use this if your capture card does not "
1093 "support all of the standard rates."));
1108 setLabel(QObject::tr(
"Do not adjust volume"));
1110 QObject::tr(
"Enable this option for budget BT878 based "
1111 "DVB-T cards such as the AverTV DVB-T which "
1112 "require the audio volume to be left alone."));
1122 setLabel(QObject::tr(
"DVB device"));
1124 QObject::tr(
"When you change this setting, the text below "
1125 "should change to the name and type of your card. "
1126 "If the card cannot be opened, an error message "
1127 "will be displayed."));
1145 std::stable_sort(sdevs.begin(), sdevs.end());
1150 QMap<QString,bool> in_use;
1152 for (
const QString& dev : qAsConst(sdevs))
1154 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1155 if (sel.isEmpty() && !in_use[dev])
1159 if (sel.isEmpty() && !sdevs.empty())
1162 QString usestr = QString(
" -- ");
1163 usestr += QObject::tr(
"Warning: already in use");
1165 for (
const QString& dev : qAsConst(sdevs))
1167 QString desc = dev + (in_use[dev] ? usestr :
"");
1168 desc = (
current == dev) ? dev : desc;
1192 setLabel(QObject::tr(
"Delivery system"));
1194 QObject::tr(
"If your card supports more than one delivery system "
1195 "then you can select here the one that you want to use."));
1204 setLabel(QObject::tr(
"Frontend ID"));
1206 QObject::tr(
"Identification string reported by the card. "
1207 "If the message \"Could not get card info...\" appears "
1208 "the card can be in use by another program."));
1219 setLabel(QObject::tr(
"Wait for SEQ start header"));
1222 QObject::tr(
"If enabled, drop packets from the start of a DVB "
1223 "recording until a sequence start header is seen."));
1234 setLabel(QObject::tr(
"Open DVB card on demand"));
1237 QObject::tr(
"If enabled, only open the DVB card when required, "
1238 "leaving it free for other programs at other times."));
1249 setLabel(QObject::tr(
"Use DVB card for active EIT scan"));
1252 QObject::tr(
"If enabled, activate active scanning for "
1253 "program data (EIT). When this option is enabled "
1254 "the DVB card is constantly in use."));
1264 setLabel(QObject::tr(
"DVB tuning delay (ms)"));
1267 QObject::tr(
"Some Linux DVB drivers, in particular for the "
1268 "Hauppauge Nova-T, require that we slow down "
1269 "the tuning process by specifying a delay "
1270 "(in milliseconds)."));
1281 #ifdef USING_FIREWIRE
1283 for (
auto & i : list)
1285 QString guid = i.GetGUIDString();
1289 #endif // USING_FIREWIRE
1304 setLabel(QObject::tr(
"Cable box model"));
1305 addSelection(QObject::tr(
"Motorola Generic"),
"MOTO GENERIC");
1306 addSelection(QObject::tr(
"SA/Cisco Generic"),
"SA GENERIC");
1322 QString
help = QObject::tr(
1323 "Choose the model that most closely resembles your set top box. "
1324 "Depending on firmware revision SA4200HD may work better for a "
1333 #ifdef USING_FIREWIRE
1337 #endif // USING_FIREWIRE
1346 #ifdef USING_FIREWIRE
1348 name.replace(
"Scientific-Atlanta",
"SA");
1349 name.replace(
", Inc.",
"");
1350 name.replace(
"Explorer(R)",
"");
1351 name = name.simplified();
1352 setValue((name.isEmpty()) ?
"" : name);
1353 #endif // USING_FIREWIRE
1361 "firewire_connection"))
1363 setLabel(QObject::tr(
"Connection Type"));
1384 #ifdef USING_FIREWIRE
1396 #ifdef USING_LINUX_FIREWIRE
1399 #endif // USING_LINUX_FIREWIRE
1404 model->SetGUID(dev->getValue());
1405 desc->SetGUID(dev->getValue());
1447 setLabel(QObject::tr(
"Use HDHomeRun for active EIT scan"));
1450 QObject::tr(
"If enabled, activate active scanning for "
1451 "program data (EIT). When this option is enabled "
1452 "the HDHomeRun is constantly in use."));
1463 setLabel(QObject::tr(
"Use HDHomeRun %1 (%2 %3)")
1464 .arg(deviceid, model, ipaddr));
1467 QObject::tr(
"If enabled, use tuners from this HDHomeRun "
1483 QMap<QString, HDHomeRunDevice>::iterator dit;
1484 for (dit = m_deviceList.begin(); dit != m_deviceList.end(); ++dit)
1496 buttonRecOpt->setLabel(tr(
"Recording Options"));
1497 buttonRecOpt->addChild(
new SignalTimeout(m_parent, 3s, 0.25s));
1511 for (
const auto & dev : qAsConst(devs))
1513 QStringList devinfo = dev.split(
" ");
1514 const QString& devid = devinfo.at(0);
1515 const QString& devip = devinfo.at(1);
1516 const QString& model = devinfo.at(2);
1530 QMap<QString, HDHomeRunDevice>::iterator debugit;
1533 LOG(VB_GENERAL, LOG_DEBUG, QString(
"%1: %2 %3")
1534 .arg(debugit.key()).arg((*debugit).model)
1535 .arg((*debugit).cardip));
1542 QStringList devstrs = devices.split(
",");
1543 for (
const QString& devstr : qAsConst(devstrs))
1548 QByteArray ba = devstr.toUtf8();
1549 hdhomerun_device_t *device = hdhomerun_device_create_from_str(
1550 ba.data(),
nullptr);
1553 QString devid = QString(
"%1").arg(
1554 hdhomerun_device_get_device_id(device), 8, 16).toUpper();
1555 hdhomerun_device_destroy(device);
1558 QMap<QString, HDHomeRunDevice>::iterator dit;
1561 (*dit).m_checkbox->setValue(
true);
1569 QStringList devstrs;
1570 QMap<QString, HDHomeRunDevice>::iterator dit;
1573 if ((*dit).m_checkbox->boolValue())
1574 devstrs << (*dit).m_deviceId;
1576 QString devices = devstrs.join(
",");
1588 setLabel(QObject::tr(
"IP Address"));
1589 setHelpText(QObject::tr(
"Device IP or ID of a VBox device. eg. '192.168.1.100' or 'vbox_3718'"));
1619 setHelpText(QObject::tr(
"Number and type of the tuner to use. eg '1-DVBT/T2'."));
1688 m_deviceId(deviceid),
1691 m_cardTuner(cardtuner),
1692 m_deviceList(devicelist),
1695 setLabel(QObject::tr(
"Available devices"));
1698 "Device IP or ID, tuner number and tuner type of available VBox devices."));
1709 std::vector<QString> devs;
1710 QMap<QString, bool> in_use;
1716 devs.push_back(it.key());
1717 in_use[it.key()] = (*it).m_inUse;
1720 QString man_addr = VBoxDeviceIDList::tr(
"Manually Enter IP Address");
1721 QString sel = man_addr;
1722 devs.push_back(sel);
1724 for (
const auto & dev : devs)
1725 sel = (
current == dev) ? dev : sel;
1727 QString usestr = QString(
" -- ");
1728 usestr += QObject::tr(
"Warning: already in use");
1730 for (
const auto & dev : devs)
1732 QString desc = dev + (in_use[dev] ? usestr :
"");
1740 else if (sel == man_addr && !
current.isEmpty())
1743 QStringList selection =
current.split(
"-");
1764 if (v == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1769 else if (!v.isEmpty())
1771 if (
m_oldValue == VBoxDeviceIDList::tr(
"Manually Enter IP Address"))
1796 setValue(
"http://mafreebox.freebox.fr/freeboxtv/playlist.m3u");
1799 QObject::tr(
"URL of M3U containing RTSP/RTP/UDP channel URLs."));
1817 setLabel(QObject::tr(
"ASI device"));
1835 std::stable_sort(sdevs.begin(), sdevs.end());
1844 QMap<QString,bool> in_use;
1846 for (
const QString& dev : qAsConst(sdevs))
1848 in_use[dev] =
std::find(db.begin(), db.end(), dev) != db.end();
1849 if (sel.isEmpty() && !in_use[dev])
1854 if (sel.isEmpty() && !sdevs.empty())
1857 QString usestr = QString(
" -- ");
1858 usestr += QObject::tr(
"Warning: already in use");
1862 for (
const QString& dev : qAsConst(sdevs))
1864 QString desc = dev + (in_use[dev] ? usestr :
"");
1865 desc = (
current == dev) ? dev : desc;
1867 found |= (dev == sel);
1871 if (!found && !
current.isEmpty())
1873 QString desc =
current +
" -- " +
1874 QObject::tr(
"Warning: unable to open");
1912 if (device.isEmpty())
1929 LOG(VB_GENERAL, LOG_WARNING,
1930 "ASIConfigurationGroup::probeCard(), Warning: " +
error);
1947 device->setHelpText(tr(
"A local file used to simulate a recording."
1948 " Leave empty to use MythEvents to trigger an"
1949 " external program to import recording files."));
1971 QFileInfo fileInfo(device);
1974 if (device.startsWith(
"file:", Qt::CaseInsensitive))
1975 fileInfo.setFile(device.mid(5));
1977 if (fileInfo.exists())
1979 if (fileInfo.isReadable() && (fileInfo.isFile()))
1982 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
1985 ci = tr(
"File not readable");
1989 ci = tr(
"File %1 does not exist").arg(device);
2011 m_desc->setLabel(tr(
"Description"));
2015 m_deviceId, m_desc, m_cardIp, m_cardTuner, &m_deviceList, m_parent);
2041 for (
const auto & dev : qAsConst(devs))
2043 QStringList devinfo = dev.split(
" ");
2044 const QString&
id = devinfo.at(0);
2045 const QString& ip = devinfo.at(1);
2046 const QString& tunerNo = devinfo.at(2);
2047 const QString& tunerType = devinfo.at(3);
2066 for (
const auto & dev : qAsConst(db))
2068 QMap<QString, VBoxDevice>::iterator dit;
2072 (*dit).m_inUse =
true;
2109 static const QRegularExpression ipV4Regex
2110 {
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){4}$" };
2111 auto match = ipV4Regex.match(ip +
".");
2112 if (match.hasMatch())
2121 static const QRegularExpression oneDigit {
"^\\d$" };
2122 auto match = oneDigit.match(tuner);
2123 if (match.hasMatch())
2138 static const QRegularExpression newstyle { R
"(^([0-9.]+)-(\d|RTP)\.(\d)$)" };
2139 auto match = newstyle.match(
getValue());
2140 if (match.hasMatch())
2151 desc->setLabel(tr(
"CetonConfigurationGroup",
"Description"));
2153 tr(
"IP Address of the Ceton device (192.168.200.1 by default)"));
2155 tr(
"Number of the tuner on the Ceton device (first tuner is number 0)"));
2191 const QString &inputtype) :
2197 QRegularExpression drv {
"^(?!ivtv|hdpvr|(saa7164(.*))).*$" };
2221 QString cn = tr(
"Failed to open");
2225 QByteArray adevice = device.toLatin1();
2226 int videofd = open(adevice.constData(), O_RDWR);
2230 ci = cn = tr(
"Failed to probe");
2231 else if (!dn.isEmpty())
2232 ci = cn +
" [" + dn +
"]";
2246 QRegularExpression drv {
"^(ivtv|(saa7164(.*)))$" };
2270 QString cn = tr(
"Failed to open");
2274 QByteArray adevice = device.toLatin1();
2275 int videofd = open(adevice.constData(), O_RDWR);
2279 ci = cn = tr(
"Failed to probe");
2280 else if (!dn.isEmpty())
2281 ci = cn +
" [" + dn +
"]";
2297 device->setHelpText(tr(
"A local MPEG file used to simulate a recording."));
2320 QFileInfo fileInfo(device);
2321 if (fileInfo.exists())
2323 if (fileInfo.isReadable() && (fileInfo.isFile()))
2326 cs = tr(
"%1 MB").arg(fileInfo.size() / 1024 / 1024);
2329 ci = tr(
"File not readable");
2333 ci = tr(
"File does not exist");
2340 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2341 ExternalConfigurationGroup::ExternalConfigurationGroup(
CaptureCard &a_parent,
2348 device->setLabel(tr(
"Command path"));
2349 device->setHelpText(tr(
"A 'black box' application controlled via stdin, status on "
2350 "stderr and TransportStream read from stdout.\n"
2351 "Use absolute path or path relative to the current directory."));
2361 this, &ExternalConfigurationGroup::probeApp);
2363 probeApp(device->getValue());
2366 void ExternalConfigurationGroup::probeApp(
const QString & path)
2368 int idx1 = path.startsWith(
"file:", Qt::CaseInsensitive) ? 5 : 0;
2369 int idx2 = path.indexOf(
' ', idx1);
2372 QFileInfo fileInfo(path.mid(idx1, idx2 - idx1));
2374 if (fileInfo.exists())
2376 ci = tr(
"File '%1' is valid.").arg(fileInfo.absoluteFilePath());
2377 if (!fileInfo.isReadable() || !fileInfo.isFile())
2378 ci = tr(
"WARNING: File '%1' is not readable.")
2379 .arg(fileInfo.absoluteFilePath());
2380 if (!fileInfo.isExecutable())
2381 ci = tr(
"WARNING: File '%1' is not executable.")
2382 .arg(fileInfo.absoluteFilePath());
2386 ci = tr(
"WARNING: File '%1' does not exist.")
2387 .arg(fileInfo.absoluteFilePath());
2390 m_info->setValue(ci);
2391 m_info->setHelpText(ci);
2393 #endif // !defined( USING_MINGW ) && !defined( _MSC_VER )
2403 QRegularExpression(
"^hdpvr$"));
2426 QString cn = tr(
"Failed to open");
2430 int videofd = open(device.toLocal8Bit().constData(), O_RDWR);
2434 ci = cn = tr(
"Failed to probe");
2435 else if (!dn.isEmpty())
2436 ci = cn +
" [" + dn +
"]";
2452 setLabel(QObject::tr(
"V4L2 encoder devices (multirec capable)"));
2467 if (!device_name.isEmpty())
2474 QString card_name = tr(
"Failed to open");
2475 QString card_info = card_name;
2494 if (audioinput->fillSelections(device_name) > 1)
2496 audioinput->setName(
"AudioInput");
2507 vbidev->setName(
"VBIDevice");
2519 Q_UNUSED(device_name);
2520 #endif // USING_V4L2
2525 setLabel(QObject::tr(
"Capture Card Setup"));
2527 auto* cardtype =
new CardType(parent);
2531 cardtype->addTargetedChild(
"DVB",
2536 cardtype->addTargetedChild(
"HDPVR",
2538 #endif // USING_V4L2
2540 #ifdef USING_HDHOMERUN
2541 cardtype->addTargetedChild(
"HDHOMERUN",
2543 #endif // USING_HDHOMERUN
2546 cardtype->addTargetedChild(
"VBOX",
2548 #endif // USING_VBOX
2551 cardtype->addTargetedChild(
"SATIP",
2552 new SatIPConfigurationGroup(parent, *cardtype));
2553 #endif // USING_SATIP
2555 #ifdef USING_FIREWIRE
2557 #endif // USING_FIREWIRE
2561 #endif // USING_CETON
2565 #endif // USING_IPTV
2568 cardtype->addTargetedChild(
"V4L2ENC",
new V4L2encGroup(parent, *cardtype));
2569 cardtype->addTargetedChild(
"V4L",
2571 cardtype->addTargetedChild(
"MJPEG",
2573 cardtype->addTargetedChild(
"GO7007",
2575 cardtype->addTargetedChild(
"MPEG",
2577 #endif // USING_V4L2
2580 cardtype->addTargetedChild(
"ASI",
2585 cardtype->addTargetedChild(
"IMPORT",
2587 cardtype->addTargetedChild(
"DEMO",
2589 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2590 cardtype->addTargetedChild(
"EXTERNAL",
2591 new ExternalConfigurationGroup(parent,
2617 "SELECT cardid, videodevice, cardtype, displayname "
2619 "WHERE hostname = :HOSTNAME AND parentid = 0 "
2633 while (query.
next())
2636 QString videodevice = query.
value(1).toString();
2637 QString cardtype = query.
value(2).toString();
2638 QString displayname = query.
value(3).toString();
2640 QString label = QString(
"%1 (%2)")
2644 card->loadByID(cardid);
2645 card->setLabel(label);
2682 if (dev != init_dev)
2684 if (!init_dev.isEmpty())
2703 for (
uint clone : clones)
2720 setLabel(QObject::tr(
"Card type"));
2721 setHelpText(QObject::tr(
"Change the cardtype to the appropriate type for "
2722 "the capture card you are configuring."));
2730 QObject::tr(
"DVB-T/S/C, ATSC or ISDB-T tuner card"),
"DVB");
2735 QObject::tr(
"V4L2 encoder"),
"V4L2ENC");
2737 QObject::tr(
"HD-PVR H.264 encoder"),
"HDPVR");
2738 #endif // USING_V4L2
2740 #ifdef USING_HDHOMERUN
2742 QObject::tr(
"HDHomeRun networked tuner"),
"HDHOMERUN");
2743 #endif // USING_HDHOMERUN
2747 QObject::tr(
"Sat>IP networked tuner"),
"SATIP");
2748 #endif // USING_SATIP
2752 QObject::tr(
"V@Box TV Gateway networked tuner"),
"VBOX");
2753 #endif // USING_VBOX
2755 #ifdef USING_FIREWIRE
2757 QObject::tr(
"FireWire cable box"),
"FIREWIRE");
2758 #endif // USING_FIREWIRE
2762 QObject::tr(
"Ceton Cablecard tuner"),
"CETON");
2763 #endif // USING_CETON
2766 setting->
addSelection(QObject::tr(
"IPTV recorder"),
"FREEBOX");
2767 #endif // USING_IPTV
2771 QObject::tr(
"Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"),
"MPEG");
2773 QObject::tr(
"Analog to MJPEG encoder card (Matrox G200, DC10, etc)"),
"MJPEG");
2775 QObject::tr(
"Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
2778 QObject::tr(
"Analog capture card"),
"V4L");
2779 #endif // USING_V4L2
2782 setting->
addSelection(QObject::tr(
"DVEO ASI recorder"),
"ASI");
2785 setting->
addSelection(QObject::tr(
"Import test recorder"),
"IMPORT");
2786 setting->
addSelection(QObject::tr(
"Demo test recorder"),
"DEMO");
2787 #if !defined( USING_MINGW ) && !defined( _MSC_VER )
2788 setting->
addSelection(QObject::tr(
"External (black box) recorder"),
2799 setLabel(QObject::tr(
"Input name"));
2812 if (storage ==
nullptr)
2819 while (!inputs.isEmpty())
2832 setLabel(QObject::tr(
"Delivery system"));
2834 "This shows the delivery system (modulation), for instance DVB-T2, "
2835 "that you have selected when you configured the capture card. "
2836 "This must be the same as the modulation used by the video source. "));
2848 setLabel(QObject::tr(
"Display name"));
2850 "This name is displayed on screen when Live TV begins "
2851 "and in various other places. Make sure the last two "
2852 "characters are unique for each input or use a "
2853 "slash ('/') to designate the unique portion."));
2879 setLabel(QObject::tr(
"Video source"));
2903 setLabel(QObject::tr(
"Input group") +
2906 "Leave as 'Generic' unless this input is shared with "
2907 "another device. Only one of the inputs in an input "
2908 "group will be allowed to record at any given time."));
2911 void Load(
void)
override;
2936 LOG(VB_GENERAL, LOG_DEBUG, QString(
"InputGroup::Load() %1 %2")
2941 QMap<uint, uint> grpcnt;
2942 std::vector<QString> names;
2943 std::vector<uint> grpid;
2944 std::vector<uint> selected_groupids;
2946 names.push_back(QObject::tr(
"Generic"));
2952 "SELECT cardinputid, inputgroupid, inputgroupname "
2954 "WHERE inputgroupname LIKE 'user:%' "
2955 "ORDER BY inputgroupid, cardinputid, inputgroupname");
2963 while (query.
next())
2966 if ((inputid != 0U) && (query.
value(0).toUInt() == inputid))
2967 selected_groupids.push_back(groupid);
2971 if (grpcnt[groupid] == 1)
2973 names.push_back(query.
value(2).toString().mid(5, -1));
2974 grpid.push_back(groupid);
2985 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group num: %1 id: %2")
2989 for (
uint i = 0; i < selected_groupids.size(); i++)
2990 msg += QString(
"%1 ").arg(selected_groupids[i]);
2991 LOG(VB_GENERAL, LOG_DEBUG, msg);
2998 for (
size_t i = 0; i < names.size(); i++)
3001 index = (sel) ? i : index;
3004 LOG(VB_GENERAL, LOG_DEBUG, QString(
"grpid %1, name '%2', i %3, s %4")
3005 .arg(grpid[i]).arg(names[i]) .arg(index).arg(sel ?
"T" :
"F"));
3008 addSelection(names[i], QString::number(grpid[i]), sel);
3012 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Group index: %1").arg(index));
3027 setLabel(QObject::tr(
"Use quick tuning"));
3032 "If enabled, MythTV will tune using only the "
3033 "MPEG program number. The program numbers "
3034 "change more often than DVB or ATSC tuning "
3035 "parameters, so this is slightly less reliable. "
3036 "This will also inhibit EIT gathering during "
3037 "Live TV and recording."));
3047 setLabel(QObject::tr(
"External channel change command"));
3049 setHelpText(QObject::tr(
"If specified, this command will be run to "
3050 "change the channel for inputs which have an external "
3051 "tuner device such as a cable box. The first argument "
3052 "will be the channel number."));
3062 setLabel(QObject::tr(
"Preset tuner to channel"));
3064 setHelpText(QObject::tr(
"Leave this blank unless you have an external "
3065 "tuner that is connected to the tuner input of your card. "
3066 "If so, you will need to specify the preset channel for "
3067 "the signal (normally 3 or 4)."));
3074 if (sourceid.isEmpty() || !sourceid.toUInt())
3079 if (storage ==
nullptr)
3086 if (channels.empty())
3089 startChan.isEmpty() ?
"0" : startChan);
3097 bool has_visible =
false;
3098 for (
size_t i = 0; i < channels.size() && !has_visible; i++)
3101 for (
auto & channel : channels)
3103 const QString channum = channel.m_chanNum;
3104 bool sel = channum == startChan;
3105 if (!has_visible || channel.m_visible || sel)
3119 setLabel(QObject::tr(
"Input priority"));
3121 setHelpText(QObject::tr(
"If the input priority is not equal for "
3122 "all inputs, the scheduler may choose to record a show "
3123 "at a later time so that it can record on an input with "
3124 "a higher value."));
3135 setLabel(QObject::tr(
"Schedule order"));
3137 setHelpText(QObject::tr(
"If priorities and other factors are equal "
3138 "the scheduler will choose the available "
3139 "input with the lowest, non-zero value. "
3140 "Setting this value to zero will make the "
3141 "input unavailable to the scheduler."));
3152 setLabel(QObject::tr(
"Live TV order"));
3154 setHelpText(QObject::tr(
"When entering Live TV, the available, local "
3155 "input with the lowest, non-zero value will "
3156 "be used. If no local inputs are available, "
3157 "the available, remote input with the lowest, "
3158 "non-zero value will be used. "
3159 "Setting this value to zero will make the "
3160 "input unavailable to live TV."));
3171 setLabel(QObject::tr(
"Use DishNet long-term EIT data"));
3175 "If you point your satellite dish toward DishNet's birds, "
3176 "you may wish to enable this feature. For best results, "
3177 "enable general EIT collection as well."));
3203 if (
"DVB" == cardtype)
3225 if (
"DVB" == cardtype)
3230 tr(
"Use channel scanner to find channels for this input."));
3233 tr(
"This uses the listings data source to "
3234 "provide the channels for this input.") +
" " +
3235 tr(
"This can take a long time to run."));
3244 interact->setLabel(QObject::tr(
"Interactions between inputs"));
3254 interact->addChild(
new LiveTVOrder(*
this, _cardid));
3258 ingrpbtn->setHelpText(
3259 QObject::tr(
"Input groups are only needed when two or more cards "
3260 "share the same resource such as a FireWire card and "
3261 "an analog card input controlling the same set top box."));
3262 interact->addChild(ingrpbtn);
3268 setObjectName(
"CardInput");
3294 bool enable = (sourceid.toInt() > 0);
3311 auto *settingdialog =
3314 if (settingdialog->Create())
3321 delete settingdialog;
3328 ShowOkPopup(tr(
"Sorry, this Input Group name cannot be blank."));
3332 QString new_name = QString(
"user:") + name;
3335 query.
prepare(
"SELECT inputgroupname "
3337 "WHERE inputgroupname = :GROUPNAME");
3338 query.
bindValue(
":GROUPNAME", new_name);
3348 ShowOkPopup(tr(
"Sorry, this Input Group name is already in use."));
3375 #ifdef USING_BACKEND
3383 LOG(VB_GENERAL, LOG_ERR,
3384 QString(
"Sorry, %1 cards do not yet support scanning.")
3400 if (num_channels_before)
3412 LOG(VB_GENERAL, LOG_ERR,
"You must compile the backend "
3413 "to be able to scan for channels");
3433 cardtype !=
"HDHOMERUN" &&
3434 !num_channels_before)
3436 LOG(VB_GENERAL, LOG_ERR,
"Skipping channel fetch, you need to "
3437 "scan for channels first.");
3446 if (num_channels_before)
3455 QString cardinputidTag(
":WHERECARDID");
3457 QString query(
"cardid = " + cardinputidTag);
3466 QString cardinputidTag(
":SETCARDID");
3469 QString query(
"cardid = " + cardinputidTag +
", " +
3488 query.
prepare(
"SELECT cardid FROM capturecard "
3489 "WHERE cardid = :CARDID AND inputname = :INPUTNAME");
3491 query.
bindValue(
":INPUTNAME", _inputname);
3544 tr(
"Are you sure you want to delete "
3553 tr(
"Are you sure you want to delete "
3554 "ALL capture cards?"),
3562 card->setLabel(tr(
"New capture card"));
3588 "WHERE hostname = :HOSTNAME");
3594 tr(
"Error getting list of cards for this host. "
3595 "Unable to delete capturecards for %1")
3602 while (cards.
next())
3618 AddSelection(QObject::tr(
"(Delete all capture cards on %1)")
3621 AddSelection(QObject::tr(
"(Delete all capture cards)"),
3635 AddSelection(QObject::tr(
"(Delete all video sources)"),
3658 tr(
"Are you sure you want to delete "
3659 "ALL video sources?"),
3677 source->setLabel(tr(
"New video source"));
3699 "SELECT cardid, videodevice, cardtype, displayname "
3701 "WHERE hostname = :HOSTNAME "
3702 " AND parentid = 0 "
3712 while (query.
next())
3715 QString videodevice = query.
value(1).toString();
3716 QString cardtype = query.
value(2).toString();
3717 QString displayname = query.
value(3).toString();
3719 auto *cardinput =
new CardInput(cardtype, videodevice, cardid);
3720 cardinput->loadByID(cardid);
3721 QString inputlabel = QString(
"%1 (%2) -> %3")
3723 displayname, cardinput->getSourceName());
3725 cardinput->setLabel(inputlabel);
3736 QString short_name = name;
3737 if (short_name.startsWith(
"LG Electronics"))
3738 short_name = short_name.right(short_name.length() - 15);
3739 if (short_name.startsWith(
"Oren"))
3740 short_name = short_name.right(short_name.length() - 5);
3741 if (short_name.startsWith(
"Nextwave"))
3742 short_name = short_name.right(short_name.length() - 9);
3743 if (short_name.startsWith(
"frontend", Qt::CaseInsensitive))
3744 short_name = short_name.left(short_name.length() - 9);
3745 if (short_name.endsWith(
"VSB/QAM"))
3746 short_name = short_name.left(short_name.length() - 8);
3747 if (short_name.endsWith(
"VSB"))
3748 short_name = short_name.left(short_name.length() - 4);
3749 if (short_name.endsWith(
"DVB-T"))
3750 short_name = short_name.left(short_name.length() - 6);
3756 short_name = short_name.simplified();
3757 if (short_name.startsWith(
"or51211", Qt::CaseInsensitive))
3758 short_name =
"pcHDTV HD-2000";
3759 else if (short_name.startsWith(
"or51132", Qt::CaseInsensitive))
3760 short_name =
"pcHDTV HD-3000";
3761 else if (short_name.startsWith(
"bcm3510", Qt::CaseInsensitive))
3762 short_name =
"Air2PC v1";
3763 else if (short_name.startsWith(
"nxt2002", Qt::CaseInsensitive) ||
3764 short_name.startsWith(
"nxt200x", Qt::CaseInsensitive))
3765 short_name =
"Air2PC v2";
3766 else if (short_name.startsWith(
"lgdt3302", Qt::CaseInsensitive))
3767 short_name =
"DViCO HDTV3";
3768 else if (short_name.startsWith(
"lgdt3303", Qt::CaseInsensitive))
3769 short_name =
"DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
3794 if (videodevice.isEmpty())
3812 QString err_open = tr(
"Could not open card %1").arg(videodevice);
3813 QString err_other = tr(
"Could not get card info for card %1").arg(videodevice);
3859 if (frontend_name.toLower().indexOf(
"usb") >= 0)
3866 if ((frontend_name ==
"DiBcom 3000P/M-C DVB-T") ||
3868 "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
3873 #if 0 // frontends on hybrid DVB-T/Analog cards
3875 m_buttonAnalog->setVisible(
3876 short_name.startsWith(
"zarlink zl10353",
3877 Qt::CaseInsensitive) ||
3878 short_name.startsWith(
"wintv hvr 900 m/r: 65008/a1c0",
3879 Qt::CaseInsensitive) ||
3880 short_name.startsWith(
"philips tda10046h",
3881 Qt::CaseInsensitive));
3895 if (frontend_name ==
"Nextwave NXT200X VSB/QAM frontend")
3901 #if 0 // frontends on hybrid DVB-T/Analog cards
3902 if (frontend_name.toLower().indexOf(
"usb") < 0)
3904 m_buttonAnalog->setVisible(
3905 short_name.startsWith(
"pchdtv", Qt::CaseInsensitive) ||
3906 short_name.startsWith(
"dvico", Qt::CaseInsensitive) ||
3907 short_name.startsWith(
"nextwave", Qt::CaseInsensitive));
3920 for (
const auto & item : qAsConst(delsyslist))
3922 LOG(VB_GENERAL, LOG_DEBUG, QString(
"DVBCardType: add deliverysystem:%1")
3930 if (!delsys.isEmpty())
3942 QString dev, QString
type) :
3944 m_lastDevice(
std::move(dev)), m_lastCardType(
std::move(
type))
3946 setLabel(QObject::tr(
"Audio input"));
3947 setHelpText(QObject::tr(
"If there is more than one audio input, "
3948 "select which one to use."));
3961 if (device.isEmpty())
3965 QStringList inputs =
3968 for (
uint i = 0; i < (
uint)inputs.size(); i++)
3973 return inputs.size();
4057 explicit DiSEqCPosition(
const CaptureCard &parent,
int value,
int min_val) :
4061 setLabel(QObject::tr(
"DiSEqC position"));
4062 setHelpText(QObject::tr(
"Position of the LNB on the DiSEqC switch. "
4063 "Leave at 1 if there is no DiSEqC switch "
4064 "and the LNB is directly connected to the SatIP server. "
4065 "This value is used as signal source (attribute src) in "
4066 "the SatIP tune command."));
4071 SatIPConfigurationGroup::SatIPConfigurationGroup
4079 m_friendlyName =
new SatIPDeviceAttribute(tr(
"Friendly name"), tr(
"Friendly name of the Sat>IP server"));
4080 m_tunerType =
new SatIPDeviceAttribute(tr(
"Tuner type"), tr(
"Type of the selected tuner"));
4081 m_tunerIndex =
new SatIPDeviceAttribute(tr(
"Tuner index"), tr(
"Index of the tuner on the Sat>IP server"));
4082 m_deviceId =
new SatIPDeviceID(
m_parent);
4084 m_deviceIdList =
new SatIPDeviceIDList(
4085 m_deviceId, m_friendlyName, m_tunerType, m_tunerIndex, &m_deviceList,
m_parent);
4097 connect(m_deviceIdList, &SatIPDeviceIDList::NewTuner,
4098 m_deviceId, &SatIPDeviceID::SetTuner);
4101 void SatIPConfigurationGroup::FillDeviceList(
void)
4103 m_deviceList.clear();
4109 for (
const auto & dev : qAsConst(devs))
4111 QStringList devparts = dev.split(
" ");
4112 const QString&
id = devparts.value(0);
4113 const QString& name = devparts.value(1);
4114 const QString& ip = devparts.value(2);
4115 const QString& tunerno = devparts.value(3);
4116 const QString& tunertype = devparts.value(4);
4119 device.m_deviceId = id;
4120 device.m_cardIP = ip;
4121 device.m_inUse =
false;
4122 device.m_friendlyName = name;
4123 device.m_tunerNo = tunerno;
4124 device.m_tunerType = tunertype;
4125 device.m_mythDeviceId = QString(
"%1:%2:%3").arg(
id, tunertype, tunerno);
4127 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3").arg(name, tunertype, tunerno);
4129 m_deviceList[device.m_mythDeviceId] = device;
4131 LOG(VB_CHANNEL, LOG_DEBUG, QString(
"SatIP: Add %1 '%2' '%3'")
4132 .arg(device.m_mythDeviceId, device.m_friendlyName, friendlyIdentifier));
4138 for (
const auto& dev : db)
4140 auto dit = m_deviceList.find(dev);
4141 if (dit != m_deviceList.end())
4143 (*dit).m_inUse =
true;
4148 SatIPDeviceIDList::SatIPDeviceIDList(
4149 SatIPDeviceID *deviceId,
4150 SatIPDeviceAttribute *friendlyName,
4151 SatIPDeviceAttribute *tunerType,
4152 SatIPDeviceAttribute *tunerIndex,
4153 SatIPDeviceList *deviceList,
4155 m_deviceId(deviceId),
4156 m_friendlyName(friendlyName),
4157 m_tunerType(tunerType),
4158 m_tunerIndex(tunerIndex),
4159 m_deviceList(deviceList),
4163 setHelpText(tr(
"Device IP or ID, tuner number and tuner type of available Sat>IP device"));
4166 this, &SatIPDeviceIDList::UpdateDevices);
4169 void SatIPDeviceIDList::Load(
void)
4173 int cardid = m_parent.getCardID();
4176 fillSelections(device);
4179 void SatIPDeviceIDList::UpdateDevices(
const QString &v)
4181 SatIPDevice dev = (*m_deviceList)[v];
4182 m_deviceId->setValue(dev.m_mythDeviceId);
4183 m_friendlyName->setValue(dev.m_friendlyName);
4184 m_tunerType->setValue(dev.m_tunerType);
4185 m_tunerIndex->setValue(dev.m_tunerNo);
4188 void SatIPDeviceIDList::fillSelections(
const QString &cur)
4192 std::vector<QString> names;
4193 std::vector<QString> devs;
4194 QMap<QString, bool> in_use;
4199 SatIPDeviceList::iterator it = m_deviceList->begin();
4200 for(; it != m_deviceList->end(); ++it)
4202 QString friendlyIdentifier = QString(
"%1, %2, Tuner #%3")
4203 .arg((*it).m_friendlyName, (*it).m_tunerType, (*it).m_tunerNo);
4204 names.push_back(friendlyIdentifier);
4206 devs.push_back(it.key());
4207 in_use[it.key()] = (*it).m_inUse;
4210 for (
const auto& it2s : devs)
4212 sel = (
current == it2s) ? it2s : sel;
4215 QString usestr = QString(
" -- ");
4216 usestr += tr(
"Warning: already in use");
4218 for (
uint i = 0; i < devs.size(); ++i)
4220 const QString dev = devs[i];
4221 const QString name = names[i];
4222 bool dev_in_use = (dev == sel) ?
false : in_use[devs[i]];
4223 QString desc = name + (dev_in_use ? usestr :
"");
4224 addSelection(desc, dev, dev == sel);
4228 SatIPDeviceID::SatIPDeviceID(
const CaptureCard &parent) :
4238 void SatIPDeviceID::Load(
void)
4243 void SatIPDeviceID::SetTuner(
const QString &tuner)
4248 SatIPDeviceAttribute::SatIPDeviceAttribute(
const QString& label,
const QString& helptext)
4251 setHelpText(helptext);
4253 #endif // USING_SATIP