MythTV master
v2capture.cpp
Go to the documentation of this file.
1
2// Program Name: capture.cpp
3// Created : Sep. 21, 2011
4//
5// Copyright (c) 2011 Robert McNamara <rmcnamara@mythtv.org>
6//
7// This program is free software; you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation; either version 2 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20//
21// You should have received a copy of the GNU General Public License
22// along with this program. If not, see <http://www.gnu.org/licenses/>.
23//
25
26// Qt
27#include <QList>
28#include <QFile>
29#include <QMutex>
30
31// MythTV
32#include "libmythbase/mythconfig.h"
33
35#include "libmythbase/compat.h"
38#include "libmythbase/mythdb.h"
40#include "libmythbase/mythversion.h"
41#include "libmythtv/cardutil.h"
44
45// MythBackend
46#include "v2capture.h"
47#include "v2serviceUtil.h"
48
49// This will be initialised in a thread safe manner on first use
51 (CAPTURE_HANDLE, V2Capture::staticMetaObject, &V2Capture::RegisterCustomTypes))
52
54{
55 qRegisterMetaType<V2CaptureCardList*>("V2CaptureCardList");
56 qRegisterMetaType<V2CaptureCard*>("V2CaptureCard");
57 qRegisterMetaType<V2CardTypeList*>("V2CardTypeList");
58 qRegisterMetaType<V2CardType*>("V2CardType");
59 qRegisterMetaType<V2CaptureDeviceList*>("V2CaptureDeviceList");
60 qRegisterMetaType<V2CaptureDevice*>("V2CaptureDevice");
61 qRegisterMetaType<V2DiseqcTree*>("V2DiseqcTree");
62 qRegisterMetaType<V2DiseqcTreeList*>("V2DiseqcTreeList");
63 qRegisterMetaType<V2InputGroupList*>("V2InputGroupList");
64 qRegisterMetaType<V2InputGroup*>("V2InputGroup");
65 qRegisterMetaType<V2DiseqcConfig*>("V2DiseqcConfig");
66 qRegisterMetaType<V2DiseqcConfigList*>("V2DiseqcConfigList");
67 qRegisterMetaType<V2RecProfParam*>("V2RecProfParam");
68 qRegisterMetaType<V2RecProfile*>("V2RecProfile");
69 qRegisterMetaType<V2RecProfileGroup*>("V2RecProfileGroup");
70 qRegisterMetaType<V2RecProfileGroupList*>("V2RecProfileGroupList");
71 qRegisterMetaType<V2CardSubType*>("V2CardSubType");
72}
73
75 : MythHTTPService(s_service)
76{
77}
78
80//
82
84 const QString &CardType )
85{
87
88 if (!query.isConnected())
89 throw( QString("Database not open while trying to list "
90 "V2Capture Cards."));
91
92 QString str = "SELECT cardid, parentid, videodevice, audiodevice, vbidevice, "
93 "cardtype, defaultinput, audioratelimit, hostname, "
94 "dvb_swfilter, dvb_sat_type, dvb_wait_for_seqstart, "
95 "skipbtaudio, dvb_on_demand, dvb_diseqc_type, "
96 "firewire_speed, firewire_model, firewire_connection, "
97 "signal_timeout, channel_timeout, dvb_tuning_delay, "
98 "contrast, brightness, colour, hue, diseqcid, dvb_eitscan, "
99 "inputname, sourceid, externalcommand, changer_device, "
100 "changer_model, tunechan, startchan, displayname, "
101 "dishnet_eit, recpriority, quicktune, schedorder, "
102 "livetvorder, reclimit, schedgroup "
103 "from capturecard";
104
105 if (!sHostName.isEmpty())
106 str += " WHERE hostname = :HOSTNAME";
107 else if (!CardType.isEmpty())
108 str += " WHERE cardtype = :CARDTYPE";
109
110 if (!sHostName.isEmpty() && !CardType.isEmpty())
111 str += " AND cardtype = :CARDTYPE";
112
113 query.prepare(str);
114
115 if (!sHostName.isEmpty())
116 query.bindValue(":HOSTNAME", sHostName);
117 if (!CardType.isEmpty())
118 query.bindValue(":CARDTYPE", CardType);
119
120 if (!query.exec())
121 {
122 MythDB::DBError("MythAPI::GetCaptureCardList()", query);
123 throw( QString( "Database Error executing query." ));
124 }
125
126 // ----------------------------------------------------------------------
127 // return the results of the query
128 // ----------------------------------------------------------------------
129
130 auto* pList = new V2CaptureCardList();
131
132 while (query.next())
133 {
134
135 V2CaptureCard *pCaptureCard = pList->AddNewCaptureCard();
136
137 pCaptureCard->setCardId ( query.value(0).toInt() );
138 pCaptureCard->setParentId ( query.value(1).toInt() );
139 pCaptureCard->setVideoDevice ( query.value(2).toString() );
140 pCaptureCard->setAudioDevice ( query.value(3).toString() );
141 pCaptureCard->setVBIDevice ( query.value(4).toString() );
142 pCaptureCard->setCardType ( query.value(5).toString() );
143 pCaptureCard->setDefaultInput ( query.value(6).toString() );
144 pCaptureCard->setAudioRateLimit ( query.value(7).toUInt() );
145 pCaptureCard->setHostName ( query.value(8).toString() );
146 pCaptureCard->setDVBSWFilter ( query.value(9).toUInt() );
147 pCaptureCard->setDVBSatType ( query.value(10).toUInt() );
148 pCaptureCard->setDVBWaitForSeqStart( query.value(11).toBool() );
149 pCaptureCard->setSkipBTAudio ( query.value(12).toBool() );
150 pCaptureCard->setDVBOnDemand ( query.value(13).toBool() );
151 pCaptureCard->setDVBDiSEqCType ( query.value(14).toUInt() );
152 pCaptureCard->setFirewireSpeed ( query.value(15).toUInt() );
153 pCaptureCard->setFirewireModel ( query.value(16).toString() );
154 pCaptureCard->setFirewireConnection( query.value(17).toUInt() );
155 pCaptureCard->setSignalTimeout ( query.value(18).toUInt() );
156 pCaptureCard->setChannelTimeout ( query.value(19).toUInt() );
157 pCaptureCard->setDVBTuningDelay ( query.value(20).toUInt() );
158 pCaptureCard->setContrast ( query.value(21).toUInt() );
159 pCaptureCard->setBrightness ( query.value(22).toUInt() );
160 pCaptureCard->setColour ( query.value(23).toUInt() );
161 pCaptureCard->setHue ( query.value(24).toUInt() );
162 pCaptureCard->setDiSEqCId ( query.value(25).toUInt() );
163 pCaptureCard->setDVBEITScan ( query.value(26).toBool() );
164 pCaptureCard->setInputName ( query.value(27).toString() );
165 pCaptureCard->setSourceId ( query.value(28).toInt() );
166 pCaptureCard->setExternalCommand ( query.value(29).toString() );
167 pCaptureCard->setChangerDevice ( query.value(30).toString() );
168 pCaptureCard->setChangerModel ( query.value(31).toString() );
169 pCaptureCard->setTuneChannel ( query.value(32).toString() );
170 pCaptureCard->setStartChannel ( query.value(33).toString() );
171 pCaptureCard->setDisplayName ( query.value(34).toString() );
172 pCaptureCard->setDishnetEit ( query.value(35).toBool() );
173 pCaptureCard->setRecPriority ( query.value(36).toInt() );
174 pCaptureCard->setQuickTune ( query.value(37).toBool() );
175 pCaptureCard->setSchedOrder ( query.value(38).toUInt() );
176 pCaptureCard->setLiveTVOrder ( query.value(39).toUInt() );
177 pCaptureCard->setRecLimit ( query.value(40).toUInt() );
178 pCaptureCard->setSchedGroup ( query.value(41).toBool() );
179 }
180
181 return pList;
182}
183
185//
187
189{
190 if ( nCardId < 1 )
191 throw( QString( "The Card ID is invalid."));
192
194
195 if (!query.isConnected())
196 throw( QString("Database not open while trying to list "
197 "V2Capture Cards."));
198
199 QString str = "SELECT cardid, parentid, videodevice, audiodevice, vbidevice, "
200 "cardtype, defaultinput, audioratelimit, hostname, "
201 "dvb_swfilter, dvb_sat_type, dvb_wait_for_seqstart, "
202 "skipbtaudio, dvb_on_demand, dvb_diseqc_type, "
203 "firewire_speed, firewire_model, firewire_connection, "
204 "signal_timeout, channel_timeout, dvb_tuning_delay, "
205 "contrast, brightness, colour, hue, diseqcid, dvb_eitscan, "
206 "inputname, sourceid, externalcommand, changer_device, "
207 "changer_model, tunechan, startchan, displayname, "
208 "dishnet_eit, recpriority, quicktune, schedorder, "
209 "livetvorder, reclimit, schedgroup "
210 "from capturecard WHERE cardid = :CARDID";
211
212 query.prepare(str);
213 query.bindValue(":CARDID", nCardId);
214
215 if (!query.exec())
216 {
217 MythDB::DBError("MythAPI::GetCaptureCard()", query);
218 throw( QString( "Database Error executing query." ));
219 }
220
221 auto* pCaptureCard = new V2CaptureCard();
222
223 if (query.next())
224 {
225 pCaptureCard->setCardId ( query.value(0).toInt() );
226 pCaptureCard->setParentId ( query.value(1).toInt() );
227 pCaptureCard->setVideoDevice ( query.value(2).toString() );
228 pCaptureCard->setAudioDevice ( query.value(3).toString() );
229 pCaptureCard->setVBIDevice ( query.value(4).toString() );
230 pCaptureCard->setCardType ( query.value(5).toString() );
231 pCaptureCard->setDefaultInput ( query.value(6).toString() );
232 pCaptureCard->setAudioRateLimit ( query.value(7).toUInt() );
233 pCaptureCard->setHostName ( query.value(8).toString() );
234 pCaptureCard->setDVBSWFilter ( query.value(9).toUInt() );
235 pCaptureCard->setDVBSatType ( query.value(10).toUInt() );
236 pCaptureCard->setDVBWaitForSeqStart( query.value(11).toBool() );
237 pCaptureCard->setSkipBTAudio ( query.value(12).toBool() );
238 pCaptureCard->setDVBOnDemand ( query.value(13).toBool() );
239 pCaptureCard->setDVBDiSEqCType ( query.value(14).toUInt() );
240 pCaptureCard->setFirewireSpeed ( query.value(15).toUInt() );
241 pCaptureCard->setFirewireModel ( query.value(16).toString() );
242 pCaptureCard->setFirewireConnection( query.value(17).toUInt() );
243 pCaptureCard->setSignalTimeout ( query.value(18).toUInt() );
244 pCaptureCard->setChannelTimeout ( query.value(19).toUInt() );
245 pCaptureCard->setDVBTuningDelay ( query.value(20).toUInt() );
246 pCaptureCard->setContrast ( query.value(21).toUInt() );
247 pCaptureCard->setBrightness ( query.value(22).toUInt() );
248 pCaptureCard->setColour ( query.value(23).toUInt() );
249 pCaptureCard->setHue ( query.value(24).toUInt() );
250 pCaptureCard->setDiSEqCId ( query.value(25).toUInt() );
251 pCaptureCard->setDVBEITScan ( query.value(26).toBool() );
252 pCaptureCard->setInputName ( query.value(27).toString() );
253 pCaptureCard->setSourceId ( query.value(28).toInt() );
254 pCaptureCard->setExternalCommand ( query.value(29).toString() );
255 pCaptureCard->setChangerDevice ( query.value(30).toString() );
256 pCaptureCard->setChangerModel ( query.value(31).toString() );
257 pCaptureCard->setTuneChannel ( query.value(32).toString() );
258 pCaptureCard->setStartChannel ( query.value(33).toString() );
259 pCaptureCard->setDisplayName ( query.value(34).toString() );
260 pCaptureCard->setDishnetEit ( query.value(35).toBool() );
261 pCaptureCard->setRecPriority ( query.value(36).toInt() );
262 pCaptureCard->setQuickTune ( query.value(37).toBool() );
263 pCaptureCard->setSchedOrder ( query.value(38).toUInt() );
264 pCaptureCard->setLiveTVOrder ( query.value(39).toUInt() );
265 pCaptureCard->setRecLimit ( query.value(40).toUInt() );
266 pCaptureCard->setSchedGroup ( query.value(41).toBool() );
267 }
268
269 return pCaptureCard;
270}
271
273//
275
277{
278 auto* pCardType = new V2CardSubType();
279 QString subtype = CardUtil::ProbeSubTypeName(CardId);
281
282#if CONFIG_SATIP
283 if (cardType == CardUtil::INPUT_TYPES::SATIP)
285#endif // CONFIG_SATIP
286
287 bool HDHRdoesDVBC = false;
288 bool HDHRdoesDVB = false;
289
290#if CONFIG_HDHOMERUN
291 if (cardType == CardUtil::INPUT_TYPES::HDHOMERUN)
292 {
293 QString device = CardUtil::GetVideoDevice(CardId);
294 HDHRdoesDVBC = CardUtil::HDHRdoesDVBC(device);
295 HDHRdoesDVB = CardUtil::HDHRdoesDVB(device);
296 }
297#endif // CONFIG_HDHOMERUN
298
299 pCardType->setCardId(CardId);
300 pCardType->setSubType (subtype);
301 // This enum is handled differently from others because it has
302 // two names for the same value in a few cases. We choose
303 // the name that starts with "DV" when this happens
304 QMetaEnum meta = QMetaEnum::fromType<CardUtil::INPUT_TYPES>();
305 QString key = meta.valueToKeys(static_cast<uint>(cardType));
306 QStringList keyList = key.split("|");
307 key = keyList[0];
308 if (keyList.length() > 1 && keyList[1].startsWith("DV"))
309 key = keyList[1];
310 // pCardType->setInputType (cardType);
311 pCardType->setInputType (key);
312 pCardType->setHDHRdoesDVBC (HDHRdoesDVBC);
313 pCardType->setHDHRdoesDVB (HDHRdoesDVB);
314 return pCardType;
315}
316
317
319//
321
323{
325}
326
328{
329 if ( nCardId < 1 )
330 throw( QString( "The Card ID is invalid."));
331
332 bool bResult = CardUtil::DeleteInput(nCardId);
333
334 return bResult;
335}
336
338//
340
341int V2Capture::AddCaptureCard ( const QString &sVideoDevice,
342 const QString &sAudioDevice,
343 const QString &sVBIDevice,
344 const QString &CardType,
345 const uint nAudioRateLimit,
346 const QString &sHostName,
347 const uint nDVBSWFilter,
348 const uint nDVBSatType,
349 bool bDVBWaitForSeqStart,
350 bool bSkipBTAudio,
351 bool bDVBOnDemand,
352 const uint nDVBDiSEqCType,
353 const uint nFirewireSpeed,
354 const QString &sFirewireModel,
355 const uint nFirewireConnection,
356 const uint nSignalTimeout,
357 const uint nChannelTimeout,
358 const uint nDVBTuningDelay,
359 const uint nContrast,
360 const uint nBrightness,
361 const uint nColour,
362 const uint nHue,
363 const uint nDiSEqCId,
364 bool bDVBEITScan)
365{
366 if ( sVideoDevice.isEmpty() || CardType.isEmpty() || sHostName.isEmpty() )
367 throw( QString( "This API requires at least a video device node, a card type, "
368 "and a hostname." ));
369
370 int nResult = CardUtil::CreateCaptureCard(sVideoDevice, sAudioDevice,
371 sVBIDevice, CardType, nAudioRateLimit,
372 sHostName, nDVBSWFilter, nDVBSatType, bDVBWaitForSeqStart,
373 bSkipBTAudio, bDVBOnDemand, nDVBDiSEqCType, nFirewireSpeed,
374 sFirewireModel, nFirewireConnection, std::chrono::milliseconds(nSignalTimeout),
375 std::chrono::milliseconds(nChannelTimeout), nDVBTuningDelay, nContrast, nBrightness,
376 nColour, nHue, nDiSEqCId, bDVBEITScan);
377
378 if ( nResult < 1 )
379 throw( QString( "Unable to create capture device." ));
380
381 return nResult;
382}
383
385 const QString &sSetting,
386 const QString &sValue )
387{
388 if ( nCardId < 1 || sSetting.isEmpty() || sValue.isEmpty() )
389 throw( QString( "Card ID, Setting Name, and Value are required." ));
390
391 return set_on_input(sSetting, nCardId, sValue);
392}
393
394// Card Inputs
395
396bool V2Capture::RemoveCardInput( int nCardInputId )
397{
398 if ( nCardInputId < 1 )
399 throw( QString( "The Input ID is invalid."));
400
401 bool bResult = CardUtil::DeleteInput(nCardInputId);
402
403 return bResult;
404}
405
406int V2Capture::AddCardInput ( const uint nCardId,
407 const uint nSourceId,
408 const QString &sInputName,
409 const QString &sExternalCommand,
410 const QString &sChangerDevice,
411 const QString &sChangerModel,
412 const QString &sHostName,
413 const QString &sTuneChan,
414 const QString &sStartChan,
415 const QString &sDisplayName,
416 bool bDishnetEIT,
417 const uint nRecPriority,
418 const uint nQuicktune,
419 const uint nSchedOrder,
420 const uint nLiveTVOrder)
421{
422 if ( nCardId < 1 || nSourceId < 1 ||
423 sInputName.isEmpty() || sInputName == "None" )
424 throw( QString( "This API requires at least a card ID, a source ID, "
425 "and an input name." ));
426
427 if ( !CardUtil::IsUniqueDisplayName(sDisplayName, 0 ))
428 throw QString(" DisplayName is not set or is not unique.");
429
430 int nResult = CardUtil::CreateCardInput(nCardId, nSourceId, sInputName,
431 sExternalCommand, sChangerDevice, sChangerModel,
432 sHostName, sTuneChan, sStartChan, sDisplayName,
433 bDishnetEIT, nRecPriority, nQuicktune, nSchedOrder,
434 nLiveTVOrder);
435
436 return nResult;
437}
438
439bool V2Capture::UpdateCardInput ( int nCardInputId,
440 const QString &sSetting,
441 const QString &sValue )
442{
443 if ( nCardInputId < 1 || sSetting.isEmpty() || sValue.isEmpty() )
444 throw( QString( "Input ID, Setting Name, and Value are required." ));
445
446 return set_on_input(sSetting, nCardInputId, sValue);
447}
448
450{
451 auto* pCardTypeList = new V2CardTypeList();
452
453#if CONFIG_DVB
454 pCardTypeList->AddCardType(
455 QObject::tr("DVB-T/S/C, ATSC or ISDB-T tuner card"), "DVB");
456#endif // CONFIG_DVB
457
458#if CONFIG_V4L2
459 pCardTypeList->AddCardType(
460 QObject::tr("V4L2 encoder"), "V4L2ENC");
461 pCardTypeList->AddCardType(
462 QObject::tr("HD-PVR H.264 encoder"), "HDPVR");
463#endif // CONFIG_V4L2
464
465#if CONFIG_HDHOMERUN
466 pCardTypeList->AddCardType(
467 QObject::tr("HDHomeRun networked tuner"), "HDHOMERUN");
468#endif // CONFIG_HDHOMERUN
469
470#if CONFIG_SATIP
471 pCardTypeList->AddCardType(
472 QObject::tr("Sat>IP networked tuner"), "SATIP");
473#endif // CONFIG_SATIP
474
475#if CONFIG_VBOX
476 pCardTypeList->AddCardType(
477 QObject::tr("V@Box TV Gateway networked tuner"), "VBOX");
478#endif // CONFIG_VBOX
479
480#if CONFIG_FIREWIRE
481 pCardTypeList->AddCardType(
482 QObject::tr("FireWire cable box"), "FIREWIRE");
483#endif // CONFIG_FIREWIRE
484
485#if CONFIG_CETON
486 pCardTypeList->AddCardType(
487 QObject::tr("Ceton Cablecard tuner"), "CETON");
488#endif // CONFIG_CETON
489
490#if CONFIG_IPTV
491 pCardTypeList->AddCardType(QObject::tr("IPTV recorder"), "FREEBOX");
492#endif // CONFIG_IPTV
493
494#if CONFIG_V4L2
495 pCardTypeList->AddCardType(
496 QObject::tr("Analog to MPEG-2 encoder card (PVR-150/250/350, etc)"), "MPEG");
497 pCardTypeList->AddCardType(
498 QObject::tr("Analog to MJPEG encoder card (Matrox G200, DC10, etc)"), "MJPEG");
499 pCardTypeList->AddCardType(
500 QObject::tr("Analog to MPEG-4 encoder (Plextor ConvertX USB, etc)"),
501 "GO7007");
502 pCardTypeList->AddCardType(
503 QObject::tr("Analog capture card"), "V4L");
504#endif // CONFIG_V4L2
505
506#if CONFIG_ASI
507 pCardTypeList->AddCardType(QObject::tr("DVEO ASI recorder"), "ASI");
508#endif
509
510 pCardTypeList->AddCardType(QObject::tr("Import test recorder"), "IMPORT");
511 pCardTypeList->AddCardType(QObject::tr("Demo test recorder"), "DEMO");
512#if !defined( _WIN32 )
513 pCardTypeList->AddCardType(QObject::tr("External (black box) recorder"),
514 "EXTERNAL");
515#endif
516 return pCardTypeList;
517}
518
520{
521 auto* pInputGroupList = new V2InputGroupList();
522
524
525 if (!query.isConnected())
526 throw( QString("Database not open while trying to list "
527 "Input Groups."));
528
529 QString q = "SELECT cardinputid,inputgroupid,inputgroupname "
530 "FROM inputgroup WHERE inputgroupname LIKE 'user:%' "
531 "ORDER BY inputgroupid, cardinputid";
532 query.prepare(q);
533
534 if (!query.exec())
535 {
536 MythDB::DBError("GetUserInputGroupList", query);
537 return pInputGroupList;
538 }
539
540 while (query.next())
541 {
542 pInputGroupList->AddInputGroup(query.value(0).toUInt(),
543 query.value(1).toUInt(),
544 query.value(2).toString());
545 }
546
547 return pInputGroupList;
548}
549
551{
552 if (Name.isEmpty())
553 throw( QString( "Input group name cannot be empty." ) );
554
555 QString new_name = QString("user:") + Name;
556
557 uint inputgroupid = CardUtil::CreateInputGroup(new_name);
558
559 if (inputgroupid == 0)
560 {
561 throw( QString( "Failed to add or retrieve %1" ).arg(new_name) );
562 }
563
564 return inputgroupid;
565}
566
568 const uint InputGroupId)
569{
570 if (!CardUtil::LinkInputGroup(InputId, InputGroupId))
571 throw( QString ( "Failed to link input %1 to group %2" )
572 .arg(InputId).arg(InputGroupId));
573 return true;
574}
575
576
578 const uint InputGroupId)
579{
580 if (!CardUtil::UnlinkInputGroup(InputId, InputGroupId))
581 throw( QString ( "Failed to unlink input %1 from group %2" )
582 .arg(InputId).arg(InputGroupId));
583 return true;
584}
585
587 const uint Max )
588{
589 return CardUtil::InputSetMaxRecordings(InputId, Max);
590}
591
592
593#if CONFIG_DVB
594static QString remove_chaff(const QString &name)
595{
596 // Trim off some of the chaff.
597 QString short_name = name;
598 if (short_name.startsWith("LG Electronics"))
599 short_name = short_name.right(short_name.length() - 15);
600 if (short_name.startsWith("Oren"))
601 short_name = short_name.right(short_name.length() - 5);
602 if (short_name.startsWith("Nextwave"))
603 short_name = short_name.right(short_name.length() - 9);
604 if (short_name.startsWith("frontend", Qt::CaseInsensitive))
605 short_name = short_name.left(short_name.length() - 9);
606 if (short_name.endsWith("VSB/QAM"))
607 short_name = short_name.left(short_name.length() - 8);
608 if (short_name.endsWith("VSB"))
609 short_name = short_name.left(short_name.length() - 4);
610 if (short_name.endsWith("DVB-T"))
611 short_name = short_name.left(short_name.length() - 6);
612
613 // It would be infinitely better if DVB allowed us to query
614 // the vendor ID. But instead we have to guess based on the
615 // demodulator name. This means cards like the Air2PC HD5000
616 // and DViCO Fusion HDTV cards are not identified correctly.
617 short_name = short_name.simplified();
618 if (short_name.startsWith("or51211", Qt::CaseInsensitive))
619 short_name = "pcHDTV HD-2000";
620 else if (short_name.startsWith("or51132", Qt::CaseInsensitive))
621 short_name = "pcHDTV HD-3000";
622 else if (short_name.startsWith("bcm3510", Qt::CaseInsensitive))
623 short_name = "Air2PC v1";
624 else if (short_name.startsWith("nxt2002", Qt::CaseInsensitive) ||
625 short_name.startsWith("nxt200x", Qt::CaseInsensitive))
626 short_name = "Air2PC v2";
627 else if (short_name.startsWith("lgdt3302", Qt::CaseInsensitive))
628 short_name = "DViCO HDTV3";
629 else if (short_name.startsWith("lgdt3303", Qt::CaseInsensitive))
630 short_name = "DViCO v2 or Air2PC v3 or pcHDTV HD-5500";
631
632 return short_name;
633}
634#endif // CONFIG_DVB
635
636
637
639{
640
641 if (CardType == "V4L2ENC") {
642 QRegularExpression drv { "^(?!ivtv|hdpvr|(saa7164(.*))).*$" };
643 return getV4l2List(drv, CardType);
644 }
645 if (CardType == "HDPVR") {
646 QRegularExpression drv { "^hdpvr$" };
647 return getV4l2List(drv, CardType);
648 }
649 if (CardType == "FIREWIRE") {
651 }
652
653 // Get devices from system
654 QStringList sdevs = CardUtil::ProbeVideoDevices(CardType);
655
656 auto* pList = new V2CaptureDeviceList();
657 for (const auto & it : std::as_const(sdevs))
658 {
659 auto* pDev = pList->AddCaptureDevice();
660 pDev->setCardType (CardType);
661 pDev->setVideoDevice (it);
662#if CONFIG_DVB
663 // From DVBConfigurationGroup::probeCard in Videosource.cpp
664 if (CardType == "DVB")
665 {
666 QString frontendName = CardUtil::ProbeDVBFrontendName(it);
667 pDev->setInputNames( CardUtil::ProbeDeliverySystems (it));
668 pDev->setDefaultInputName( CardUtil::ProbeDefaultDeliverySystem (it));
669 QString subType = CardUtil::ProbeDVBType(it);
670 int signalTimeout = 0;
671 int channelTimeout = 0;
672 int tuningDelay = 0;
673 QString err_open = tr("Could not open card %1").arg(it);
674 QString err_other = tr("Could not get card info for card %1").arg(it);
675
676 switch (CardUtil::toInputType(subType))
677 {
679 frontendName = err_open;
680 subType = strerror(errno);
681 break;
683 frontendName = err_other;
684 subType = "Unknown error";
685 break;
687 frontendName = err_other;
688 subType = strerror(errno);
689 break;
691 subType = "DVB-S";
692 signalTimeout = 7000;
693 channelTimeout = 10000;
694 break;
696 subType = "DVB-S2";
697 signalTimeout = 7000;
698 channelTimeout = 10000;
699 break;
701 subType = "DVB-C";
702 signalTimeout = 3000;
703 channelTimeout = 6000;
704 break;
706 subType = "DVB-T2";
707 signalTimeout = 3000;
708 channelTimeout = 6000;
709 break;
711 {
712 subType = "DVB-T";
713 signalTimeout = 3000;
714 channelTimeout = 6000;
715 if (frontendName.toLower().indexOf("usb") >= 0)
716 {
717 signalTimeout = 40000;
718 channelTimeout = 42500;
719 }
720
721 // slow down tuning for buggy drivers
722 if ((frontendName == "DiBcom 3000P/M-C DVB-T") ||
723 (frontendName ==
724 "TerraTec/qanu USB2.0 Highspeed DVB-T Receiver"))
725 {
726 tuningDelay = 200;
727 }
728 break;
729 }
731 {
732 QString short_name = remove_chaff(frontendName);
733 subType = "ATSC";
734 frontendName = short_name;
735 signalTimeout = 2000;
736 channelTimeout = 4000;
737
738 // According to #1779 and #1935 the AverMedia 180 needs
739 // a 3000 ms signal timeout, at least for QAM tuning.
740 if (frontendName == "Nextwave NXT200X VSB/QAM frontend")
741 {
742 signalTimeout = 3000;
743 channelTimeout = 5500;
744 }
745 break;
746 }
747 default:
748 break;
749 }
750
751 pDev->setFrontendName ( frontendName );
752 pDev->setSubType ( subType );
753 pDev->setSignalTimeout ( signalTimeout );
754 pDev->setChannelTimeout ( channelTimeout );
755 pDev->setTuningDelay ( tuningDelay );
756 } // endif (CardType == "DVB")
757#endif // CONFIG_DVB
758 if (CardType == "HDHOMERUN")
759 {
760 pDev->setSignalTimeout ( 3000 );
761 pDev->setChannelTimeout ( 6000 );
762 }
763#if CONFIG_SATIP
764 if (CardType == "SATIP")
765 {
766 pDev->setSignalTimeout ( 7000 );
767 pDev->setChannelTimeout ( 10000 );
768 // Split video device into its parts and populate the output
769 // "deviceid friendlyname ip tunernum tunertype"
770 auto word = it.split(' ');
771 // VideoDevice is set as deviceid:tunertype:tunernum
772 if (word.size() == 5) {
773 pDev->setVideoDevice(QString("%1:%2:%3").arg(word[0], word[4], word[3]));
774 pDev->setVideoDevicePrompt(QString("%1, %2, Tuner #%3").arg(word[0], word[4], word[3]));
775 pDev->setDescription(word[1]);
776 pDev->setIPAddress(word[2]);
777 pDev->setTunerType(word[4]);
778 pDev->setTunerNumber(word[3].toUInt());
779 }
780 }
781#endif // CONFIG_SATIP
782#if CONFIG_VBOX
783 if (CardType == "VBOX")
784 {
785 pDev->setSignalTimeout ( 7000 );
786 pDev->setChannelTimeout ( 10000 );
787 // Split video device into its parts and populate the output
788 // "deviceid ip tunernum tunertype"
789 auto word = it.split(" ");
790 if (word.size() == 4) {
791 QString device = QString("%1-%2-%3").arg(word[0], word[2], word[3]);
792 pDev->setVideoDevice(device);
793 pDev->setVideoDevicePrompt(device);
794 QString desc = CardUtil::GetVBoxdesc(word[0], word[1], word[2], word[3]);
795 pDev->setDescription(desc);
796 pDev->setIPAddress(word[1]);
797 pDev->setTunerType(word[3]);
798 pDev->setTunerNumber(word[2].toUInt());
799 }
800 }
801#endif // CONFIG_VBOX
802 } // endfor (const auto & it : std::as_const(sdevs))
803 return pList;
804}
805
806
807
809{
811
812 if (!query.isConnected())
813 throw( QString("Database not open while trying to list "
814 "DiseqcTrees."));
815
816 QString str = "SELECT diseqcid, "
817 "parentid, "
818 "ordinal, "
819 "type, "
820 "subtype, "
821 "description, "
822 "switch_ports, "
823 "rotor_hi_speed, "
824 "rotor_lo_speed, "
825 "rotor_positions, "
826 "lnb_lof_switch, "
827 "lnb_lof_hi, "
828 "lnb_lof_lo, "
829 "cmd_repeat, "
830 "lnb_pol_inv, "
831 "address, "
832 "scr_userband, "
833 "scr_frequency, "
834 "scr_pin "
835 "FROM diseqc_tree ORDER BY diseqcid";
836
837 query.prepare(str);
838
839 if (!query.exec())
840 {
841 MythDB::DBError("MythAPI::GetDiseqcTreeList()", query);
842 throw( QString( "Database Error executing query." ));
843 }
844
845 // ----------------------------------------------------------------------
846 // return the results of the query
847 // ----------------------------------------------------------------------
848
849 auto* pList = new V2DiseqcTreeList();
850
851 while (query.next())
852 {
853 auto *pRec = pList->AddDiseqcTree();
854 pRec->setDiSEqCId ( query.value( 0 ).toUInt() );
855 pRec->setParentId ( query.value( 1 ).toUInt() );
856 pRec->setOrdinal ( query.value( 2 ).toUInt() );
857 pRec->setType ( query.value( 3 ).toString() );
858 pRec->setSubType ( query.value( 4 ).toString() );
859 pRec->setDescription ( query.value( 5 ).toString() );
860 pRec->setSwitchPorts ( query.value( 6 ).toUInt() );
861 pRec->setRotorHiSpeed ( query.value( 7 ).toFloat() );
862 pRec->setRotorLoSpeed ( query.value( 8 ).toFloat() );
863 pRec->setRotorPositions ( query.value( 9 ).toString() );
864 pRec->setLnbLofSwitch ( query.value( 10 ).toInt() );
865 pRec->setLnbLofHi ( query.value( 11 ).toInt() );
866 pRec->setLnbLofLo ( query.value( 12 ).toInt() );
867 pRec->setCmdRepeat ( query.value( 13 ).toInt() );
868 pRec->setLnbPolInv ( query.value( 14 ).toBool() );
869 pRec->setAddress ( query.value( 15 ).toInt() );
870 pRec->setScrUserband ( query.value( 16 ).toUInt() );
871 pRec->setScrFrequency ( query.value( 17 ).toUInt() );
872 pRec->setScrPin ( query.value( 18 ).toInt() );
873 }
874
875 return pList;
876}
877
879 uint Ordinal,
880 const QString& Type,
881 const QString& SubType,
882 const QString& Description,
883 uint SwitchPorts,
884 float RotorHiSpeed,
885 float RotorLoSpeed,
886 const QString& RotorPositions,
887 int LnbLofSwitch,
888 int LnbLofHi,
889 int LnbLofLo,
890 int CmdRepeat,
891 bool LnbPolInv,
892 int Address,
893 uint ScrUserband,
894 uint ScrFrequency,
895 int ScrPin)
896{
898
899 query.prepare(
900 "INSERT INTO diseqc_tree "
901 "(parentid, "
902 "ordinal, "
903 "type, "
904 "subtype, "
905 "description, "
906 "switch_ports, "
907 "rotor_hi_speed, "
908 "rotor_lo_speed, "
909 "rotor_positions, "
910 "lnb_lof_switch, "
911 "lnb_lof_hi, "
912 "lnb_lof_lo, "
913 "cmd_repeat, "
914 "lnb_pol_inv, "
915 "address, "
916 "scr_userband, "
917 "scr_frequency, "
918 "scr_pin) "
919 "VALUES "
920 "(:PARENTID, "
921 ":ORDINAL, "
922 ":TYPE, "
923 ":SUBTYPE, "
924 ":DESCRIPTION, "
925 ":SWITCH_PORTS, "
926 ":ROTOR_HI_SPEED, "
927 ":ROTOR_LO_SPEED, "
928 ":ROTOR_POSITIONS, "
929 ":LNB_LOF_SWITCH, "
930 ":LNB_LOF_HI, "
931 ":LNB_LOF_LO, "
932 ":CMD_REPEAT, "
933 ":LNB_POL_INV, "
934 ":ADDRESS, "
935 ":SCR_USERBAND, "
936 ":SCR_FREQUENCY, "
937 ":SCR_PIN ) " );
938
939 if (ParentId == 0) // Value 0 is set to null
940 {
941#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
942 query.bindValue(":PARENTID", QVariant(QVariant::UInt));
943#else
944 query.bindValue(":PARENTID", QVariant(QMetaType(QMetaType::UInt)));
945#endif
946 }
947 else
948 {
949 query.bindValue(":PARENTID", ParentId);
950 }
951 query.bindValue(":ORDINAL", Ordinal);
952 query.bindValue(":TYPE", Type);
953 query.bindValue(":SUBTYPE", SubType);
954 query.bindValue(":DESCRIPTION", Description);
955 query.bindValue(":SWITCH_PORTS", SwitchPorts);
956 query.bindValue(":ROTOR_HI_SPEED", RotorHiSpeed);
957 query.bindValue(":ROTOR_LO_SPEED", RotorLoSpeed);
958 query.bindValue(":ROTOR_POSITIONS", RotorPositions);
959 query.bindValue(":LNB_LOF_SWITCH", LnbLofSwitch);
960 query.bindValue(":LNB_LOF_HI", LnbLofHi);
961 query.bindValue(":LNB_LOF_LO", LnbLofLo);
962 query.bindValue(":CMD_REPEAT", CmdRepeat);
963 query.bindValue(":LNB_POL_INV", LnbPolInv);
964 query.bindValue(":ADDRESS", Address);
965 query.bindValue(":SCR_USERBAND", ScrUserband);
966 query.bindValue(":SCR_FREQUENCY", ScrFrequency);
967 query.bindValue(":SCR_PIN", ScrPin);
968
969 if (!query.exec())
970 {
971 MythDB::DBError("MythAPI::AddDiseqcTree()", query);
972 throw( QString( "Database Error executing query." ));
973 }
974 uint DiSEqCId = query.lastInsertId().toInt();
975 return DiSEqCId;
976}
977
979 uint ParentId,
980 uint Ordinal,
981 const QString& Type,
982 const QString& SubType,
983 const QString& Description,
984 uint SwitchPorts,
985 float RotorHiSpeed,
986 float RotorLoSpeed,
987 const QString& RotorPositions,
988 int LnbLofSwitch,
989 int LnbLofHi,
990 int LnbLofLo,
991 int CmdRepeat,
992 bool LnbPolInv,
993 int Address,
994 uint ScrUserband,
995 uint ScrFrequency,
996 int ScrPin)
997{
999
1000 query.prepare(
1001 "UPDATE diseqc_tree SET "
1002 "parentid = :PARENTID, "
1003 "ordinal = :ORDINAL, "
1004 "type = :TYPE, "
1005 "subtype = :SUBTYPE, "
1006 "description = :DESCRIPTION, "
1007 "switch_ports = :SWITCH_PORTS, "
1008 "rotor_hi_speed = :ROTOR_HI_SPEED, "
1009 "rotor_lo_speed = :ROTOR_LO_SPEED, "
1010 "rotor_positions = :ROTOR_POSITIONS, "
1011 "lnb_lof_switch = :LNB_LOF_SWITCH, "
1012 "lnb_lof_hi = :LNB_LOF_HI, "
1013 "lnb_lof_lo = :LNB_LOF_LO, "
1014 "cmd_repeat = :CMD_REPEAT, "
1015 "lnb_pol_inv = :LNB_POL_INV, "
1016 "address = :ADDRESS, "
1017 "scr_userband = :SCR_USERBAND, "
1018 "scr_frequency = :SCR_FREQUENCY, "
1019 "scr_pin = :SCR_PIN "
1020 "WHERE diseqcid = :DISEQCID " );
1021
1022 query.bindValue(":DISEQCID", DiSEqCId);
1023 if (ParentId == 0) // Value 0 is set to null
1024 {
1025#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
1026 query.bindValue(":PARENTID", QVariant(QVariant::UInt));
1027#else
1028 query.bindValue(":PARENTID", QVariant(QMetaType(QMetaType::UInt)));
1029#endif
1030 }
1031 else
1032 {
1033 query.bindValue(":PARENTID", ParentId);
1034 }
1035 query.bindValue(":ORDINAL", Ordinal);
1036 query.bindValue(":TYPE", Type);
1037 query.bindValue(":SUBTYPE", SubType);
1038 query.bindValue(":DESCRIPTION", Description);
1039 query.bindValue(":SWITCH_PORTS", SwitchPorts);
1040 query.bindValue(":ROTOR_HI_SPEED", RotorHiSpeed);
1041 query.bindValue(":ROTOR_LO_SPEED", RotorLoSpeed);
1042 query.bindValue(":ROTOR_POSITIONS", RotorPositions);
1043 query.bindValue(":LNB_LOF_SWITCH", LnbLofSwitch);
1044 query.bindValue(":LNB_LOF_HI", LnbLofHi);
1045 query.bindValue(":LNB_LOF_LO", LnbLofLo);
1046 query.bindValue(":CMD_REPEAT", CmdRepeat);
1047 query.bindValue(":LNB_POL_INV", LnbPolInv);
1048 query.bindValue(":ADDRESS", Address);
1049 query.bindValue(":SCR_USERBAND", ScrUserband);
1050 query.bindValue(":SCR_FREQUENCY", ScrFrequency);
1051 query.bindValue(":SCR_PIN", ScrPin);
1052
1053 if (!query.exec())
1054 {
1055 MythDB::DBError("MythAPI::UpdateDiseqcTree()", query);
1056 throw( QString( "Database Error executing query." ));
1057 }
1058 return true;
1059}
1060
1062{
1063 // Find and remove children
1065 query.prepare("SELECT diseqcid FROM diseqc_tree WHERE parentid = :PARENTID ");
1066 query.bindValue(":PARENTID", DiSEqCId);
1067
1068 if (!query.exec())
1069 {
1070 MythDB::DBError("MythAPI::RemoveDiseqcTree()", query);
1071 throw( QString( "Database Error executing query." ));
1072 }
1073
1074 bool childOK = true;
1075 while (query.next())
1076 {
1077 uint child = query.value( 0 ).toUInt();
1078 childOK = RemoveDiseqcTree(child) && childOK;
1079 }
1080 // remove this row
1081 MSqlQuery query2(MSqlQuery::InitCon());
1082 query2.prepare("DELETE FROM diseqc_tree WHERE diseqcid = :DISEQCID ");
1083 query2.bindValue(":DISEQCID", DiSEqCId);
1084 if (!query2.exec())
1085 {
1086 MythDB::DBError("MythAPI::RemoveDiseqcTree()", query2);
1087 throw( QString( "Database Error executing query." ));
1088 }
1089 int numrows = query2.numRowsAffected();
1090 return numrows > 0 && childOK;
1091}
1092
1093
1095{
1096
1098
1099 if (!query.isConnected())
1100 throw( QString("Database not open while trying to list "
1101 "DiseqcConfigs."));
1102
1103 QString str = "SELECT cardinputid, "
1104 "diseqcid, "
1105 "value "
1106 "FROM diseqc_config ORDER BY cardinputid, diseqcid";
1107
1108 query.prepare(str);
1109
1110 if (!query.exec())
1111 {
1112 MythDB::DBError("MythAPI::GetDiseqcConfigList()", query);
1113 throw( QString( "Database Error executing query." ));
1114 }
1115
1116 // ----------------------------------------------------------------------
1117 // return the results of the query
1118 // ----------------------------------------------------------------------
1119
1120 auto* pList = new V2DiseqcConfigList();
1121
1122 while (query.next())
1123 {
1124 auto *pRec = pList->AddDiseqcConfig();
1125 pRec->setCardId ( query.value( 0 ).toUInt() );
1126 pRec->setDiSEqCId ( query.value( 1 ).toUInt() );
1127 pRec->setValue ( query.value( 2 ).toString() );
1128 }
1129 return pList;
1130}
1131
1133 uint DiSEqCId,
1134 const QString& Value)
1135{
1137
1138 query.prepare(
1139 "INSERT INTO diseqc_config "
1140 "(cardinputid, "
1141 "diseqcid, "
1142 "value) "
1143 "VALUES "
1144 "(:CARDID, "
1145 ":DISEQCID, "
1146 ":VALUE) ");
1147
1148 query.bindValue(":CARDID", CardId);
1149 query.bindValue(":DISEQCID", DiSEqCId);
1150 query.bindValue(":VALUE", Value);
1151
1152 if (!query.exec())
1153 {
1154 MythDB::DBError("MythAPI::AddDiseqcConfig()", query);
1155 throw( QString( "Database Error executing query." ));
1156 }
1157 return true;
1158}
1159
1160
1162{
1164 query.prepare("DELETE FROM diseqc_config WHERE cardinputid = :CARDID ");
1165 query.bindValue(":CARDID", CardId);
1166 if (!query.exec())
1167 {
1168 MythDB::DBError("MythAPI::RemoveDiseqcConfig()", query);
1169 throw( QString( "Database Error executing query." ));
1170 }
1171 int numrows = query.numRowsAffected();
1172 return numrows > 0;
1173}
1174
1175
1176V2RecProfileGroupList* V2Capture::GetRecProfileGroupList ( uint GroupId, uint ProfileId, bool OnlyInUse ) {
1177
1179
1180 QString str =
1181 "SELECT profilegroups.id, profilegroups.name, cardtype, recordingprofiles.id, recordingprofiles.name, "
1182 "videocodec, audiocodec, "
1183 "codecparams.name, codecparams.value "
1184 "FROM profilegroups "
1185 "INNER JOIN recordingprofiles on profilegroups.id = recordingprofiles.profilegroup "
1186 "LEFT OUTER JOIN codecparams on codecparams.profile = recordingprofiles.id ";
1187 QString where = "WHERE ";
1188 if (OnlyInUse)
1189 {
1190 str.append(where).append("CARDTYPE = 'TRANSCODE' OR (cardtype in (SELECT cardtype FROM capturecard)) ");
1191 where = "AND ";
1192 }
1193 if (GroupId > 0)
1194 {
1195 str.append(where).append("profilegroups.id = :GROUPID ");
1196 where = "AND ";
1197 }
1198 if (ProfileId > 0)
1199 {
1200 str.append(where).append("recordingprofiles.id = :PROFILEID ");
1201 where = "AND ";
1202 }
1203 str.append(
1204 // Force TRANSCODE entry to be at the end
1205 "ORDER BY IF(cardtype = 'TRANSCODE', 9999, profilegroups.id), recordingprofiles.id, codecparams.name ");
1206
1207 query.prepare(str);
1208
1209 if (GroupId > 0)
1210 query.bindValue(":GROUPID", GroupId);
1211 if (ProfileId > 0)
1212 query.bindValue(":PROFILEID", ProfileId);
1213
1214 if (!query.exec())
1215 {
1216 MythDB::DBError("MythAPI::GetRecProfileGroupList()", query);
1217 throw( QString( "Database Error executing query." ));
1218 }
1219
1220 // ----------------------------------------------------------------------
1221 // return the results of the query
1222 // ----------------------------------------------------------------------
1223
1224 auto* pList = new V2RecProfileGroupList();
1225
1226 int prevGroupId = -1;
1227 int prevProfileId = -1;
1228
1229 V2RecProfileGroup * pGroup = nullptr;
1230 V2RecProfile *pProfile = nullptr;
1231
1232 while (query.next())
1233 {
1234 int groupId = query.value(0).toInt();
1235 if (groupId != prevGroupId)
1236 {
1237 pGroup = pList->AddProfileGroup();
1238 pGroup->setId ( groupId );
1239 pGroup->setName ( query.value(1).toString() );
1240 pGroup->setCardType ( query.value(2).toString() );
1241 prevGroupId = groupId;
1242 }
1243 int profileId = query.value(3).toInt();
1244 // the pGroup != nullptr check is to satisfy clang-tidy.
1245 // pGroup should never be null unless the groupId on
1246 // the database is -1, which should not happen.
1247 if (profileId != prevProfileId && pGroup != nullptr)
1248 {
1249 pProfile = pGroup->AddProfile();
1250 pProfile->setId ( profileId );
1251 pProfile->setName ( query.value(4).toString() );
1252 pProfile->setVideoCodec ( query.value(5).toString() );
1253 pProfile->setAudioCodec ( query.value(6).toString() );
1254 prevProfileId = profileId;
1255 }
1256 // the pProfile != nullptr check is to satisfy clang-tidy.
1257 // pProfile should never be null unless the profileId on
1258 // the database is -1, which should not happen.
1259 if (!query.isNull(7) && pProfile != nullptr)
1260 {
1261 auto *pParam = pProfile->AddParam();
1262 pParam->setName ( query.value(7).toString() );
1263 pParam->setValue ( query.value(8).toString() );
1264 }
1265 }
1266
1267 return pList;
1268}
1269
1270int V2Capture::AddRecProfile ( uint GroupId, const QString& ProfileName,
1271 const QString& VideoCodec, const QString& AudioCodec )
1272{
1273 if (GroupId == 0 || ProfileName.isEmpty())
1274 {
1275 LOG(VB_GENERAL, LOG_ERR,
1276 QString( "AddRecProfile: GroupId and ProfileName are required." ));
1277 return 0;
1278 }
1279
1281
1282 // Check if it already exists
1283 query.prepare(
1284 "SELECT id "
1285 "FROM recordingprofiles "
1286 "WHERE name = :NAME AND profilegroup = :PROFILEGROUP;");
1287 query.bindValue(":NAME", ProfileName);
1288 query.bindValue(":PROFILEGROUP", GroupId);
1289 if (!query.exec())
1290 {
1291 MythDB::DBError("V2Capture::AddRecProfile", query);
1292 throw( QString( "Database Error executing SELECT." ));
1293 }
1294 if (query.next())
1295 {
1296 int id = query.value(0).toInt();
1297 LOG(VB_GENERAL, LOG_ERR,
1298 QString( "Profile %1 already exists in group id %2 with id %3").arg(ProfileName).arg(GroupId).arg(id));
1299 return 0;
1300 }
1301
1302 query.prepare(
1303 "INSERT INTO recordingprofiles "
1304 "(name, videocodec, audiocodec, profilegroup) "
1305 "VALUES "
1306 "(:NAME, :VIDEOCODEC, :AUDIOCODEC, :PROFILEGROUP);");
1307 query.bindValue(":NAME", ProfileName);
1308 query.bindValue(":VIDEOCODEC", VideoCodec);
1309 query.bindValue(":AUDIOCODEC", AudioCodec);
1310 query.bindValue(":PROFILEGROUP", GroupId);
1311 if (!query.exec())
1312 {
1313 MythDB::DBError("V2Capture::AddRecProfile", query);
1314 throw( QString( "Database Error executing INSERT." ));
1315 }
1316 int id = query.lastInsertId().toInt();
1317 RecordingProfile profile(ProfileName);
1318 profile.loadByID(id);
1319 profile.setCodecTypes();
1320 profile.Save();
1321 return id;
1322}
1323
1325 const QString& VideoCodec,
1326 const QString& AudioCodec )
1327{
1329 query.prepare(
1330 "SELECT id from recordingprofiles "
1331 "WHERE id = :ID; ");
1332 query.bindValue(":ID", ProfileId);
1333 if (!query.exec())
1334 {
1335 MythDB::DBError("V2Capture::UpdateRecProfileParam", query);
1336 throw( QString( "Database Error executing SELECT." ));
1337 }
1338 uint id = -1;
1339 if (query.next())
1340 {
1341 id = query.value(0).toUInt();
1342 }
1343 if (id != ProfileId)
1344 {
1345 LOG(VB_GENERAL, LOG_ERR,
1346 QString("UpdateRecProfile: Profile id %1 does not exist").arg(ProfileId));
1347 return false;
1348 }
1349 query.prepare(
1350 "UPDATE recordingprofiles "
1351 "SET videocodec = :VIDEOCODEC, "
1352 "audiocodec = :AUDIOCODEC "
1353 "WHERE id = :ID; ");
1354 query.bindValue(":VIDEOCODEC", VideoCodec);
1355 query.bindValue(":AUDIOCODEC", AudioCodec);
1356 query.bindValue(":ID", ProfileId);
1357 if (!query.exec())
1358 {
1359 MythDB::DBError("V2Capture::UpdateRecProfileParam", query);
1360 throw( QString( "Database Error executing UPDATE." ));
1361 }
1363 profile.loadByID(ProfileId);
1364 profile.setCodecTypes();
1365 profile.Save();
1366 return true;
1367}
1368
1370{
1371 // Delete profile parameters
1373 query.prepare(
1374 "DELETE from codecparams "
1375 "WHERE profile = :ID; ");
1376 query.bindValue(":ID", ProfileId);
1377 if (!query.exec())
1378 {
1379 MythDB::DBError("V2Capture::UpdateRecProfileParam", query);
1380 throw( QString( "Database Error executing DELETE." ));
1381 }
1382 int rows = query.numRowsAffected();
1383 query.prepare(
1384 "DELETE from recordingprofiles "
1385 "WHERE id = :ID; ");
1386 query.bindValue(":ID", ProfileId);
1387 if (!query.exec())
1388 {
1389 MythDB::DBError("V2Capture::UpdateRecProfileParam", query);
1390 throw( QString( "Database Error executing DELETE." ));
1391 }
1392 return (rows > 0);
1393}
1394
1395
1396
1397bool V2Capture::UpdateRecProfileParam ( uint ProfileId, const QString &Name, const QString &Value )
1398{
1400 query.prepare(
1401 "REPLACE INTO codecparams "
1402 "(profile, name, value) "
1403 "VALUES "
1404 "(:PROFILE, :NAME, :VALUE);");
1405 query.bindValue(":PROFILE", ProfileId);
1406 query.bindValue(":NAME", Name);
1407 query.bindValue(":VALUE", Value);
1408 if (!query.exec())
1409 {
1410 MythDB::DBError("V2Capture::UpdateRecProfileParam", query);
1411 throw( QString( "Database Error executing REPLACE." ));
1412 }
1413 return true;
1414}
bool set_on_input(const QString &to_set, uint inputid, const QString &value)
Definition: cardutil.cpp:1275
static INPUT_TYPES toInputType(const QString &name)
Definition: cardutil.h:78
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:2027
static bool HDHRdoesDVB(const QString &device)
If the device is valid, check if the model does DVB.
Definition: cardutil.cpp:3080
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:746
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:725
INPUT_TYPES
all the different inputs
Definition: cardutil.h:50
static bool InputSetMaxRecordings(uint parentid, uint max_recordings)
Definition: cardutil.cpp:1561
static QStringList ProbeDeliverySystems(const QString &device)
Definition: cardutil.cpp:634
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:3185
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:2157
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:2106
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:294
static bool HDHRdoesDVBC(const QString &device)
If the device is valid, check if the model does DVB-C.
Definition: cardutil.cpp:3106
static bool DeleteInput(uint inputid)
Definition: cardutil.cpp:2823
static QString ProbeDefaultDeliverySystem(const QString &device)
Definition: cardutil.cpp:709
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:449
static bool IsUniqueDisplayName(const QString &name, uint exclude_inputid)
Definition: cardutil.cpp:1898
static int CreateCardInput(uint inputid, uint sourceid, const QString &inputname, const QString &externalcommand, const QString &changer_device, const QString &changer_model, const QString &hostname, const QString &tunechan, const QString &startchan, const QString &displayname, bool dishnet_eit, uint recpriority, uint quicktune, uint schedorder, uint livetvorder)
Definition: cardutil.cpp:1967
static QString ProbeSubTypeName(uint inputid)
Definition: cardutil.cpp:983
static bool DeleteAllInputs(void)
Definition: cardutil.cpp:2893
static int CreateCaptureCard(const QString &videodevice, const QString &audiodevice, const QString &vbidevice, const QString &inputtype, uint audioratelimit, const QString &hostname, uint dvb_swfilter, uint dvb_sat_type, bool dvb_wait_for_seqstart, bool skipbtaudio, bool dvb_on_demand, uint dvb_diseqc_type, uint firewire_speed, const QString &firewire_model, uint firewire_connection, std::chrono::milliseconds signal_timeout, std::chrono::milliseconds channel_timeout, uint dvb_tuning_delay, uint contrast, uint brightness, uint colour, uint hue, uint diseqcid, bool dvb_eitscan)
Definition: cardutil.cpp:2674
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
bool isNull(int field) const
Definition: mythdbcon.h:219
QVariant value(int i) const
Definition: mythdbcon.h:204
int numRowsAffected() const
Definition: mythdbcon.h:217
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:137
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:935
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
static CardUtil::INPUT_TYPES toDVBInputType(const QString &deviceid)
Definition: satiputils.cpp:171
static bool UpdateCardInput(int CardInputId, const QString &Setting, const QString &Value)
Definition: v2capture.cpp:439
static int AddUserInputGroup(const QString &Name)
Definition: v2capture.cpp:550
static bool LinkInputGroup(uint InputId, uint InputGroupId)
Definition: v2capture.cpp:567
static bool UpdateCaptureCard(int CardId, const QString &Setting, const QString &Value)
Definition: v2capture.cpp:384
static void RegisterCustomTypes()
static bool RemoveCaptureCard(int CardId)
Definition: v2capture.cpp:327
static V2RecProfileGroupList * GetRecProfileGroupList(uint GroupId, uint ProfileId, bool OnlyInUse)
Definition: v2capture.cpp:1176
static V2CaptureCardList * GetCaptureCardList(const QString &HostName, const QString &CardType)
Definition: v2capture.cpp:83
static int AddCaptureCard(const QString &VideoDevice, const QString &AudioDevice, const QString &VBIDevice, const QString &CardType, uint AudioRateLimit, const QString &HostName, uint DVBSWFilter, uint DVBSatType, bool DVBWaitForSeqStart, bool SkipBTAudio, bool DVBOnDemand, uint DVBDiSEqCType, uint FirewireSpeed, const QString &FirewireModel, uint FirewireConnection, uint SignalTimeout, uint ChannelTimeout, uint DVBTuningDelay, uint Contrast, uint Brightness, uint Colour, uint Hue, uint DiSEqCId, bool DVBEITScan)
Definition: v2capture.cpp:341
static V2CardSubType * GetCardSubType(int CardId)
Definition: v2capture.cpp:276
static V2CardTypeList * GetCardTypeList(void)
Definition: v2capture.cpp:449
static bool UpdateDiseqcTree(uint DiSEqCId, uint ParentId, uint Ordinal, const QString &Type, const QString &SubType, const QString &Description, uint SwitchPorts, float RotorHiSpeed, float RotorLoSpeed, const QString &RotorPositions, int LnbLofSwitch, int LnbLofHi, int LnbLofLo, int CmdRepeat, bool LnbPolInv, int Address, uint ScrUserband, uint ScrFrequency, int ScrPin)
Definition: v2capture.cpp:978
static bool RemoveDiseqcConfig(uint CardId)
Definition: v2capture.cpp:1161
static int AddCardInput(uint CardId, uint SourceId, const QString &InputName, const QString &ExternalCommand, const QString &ChangerDevice, const QString &ChangerModel, const QString &HostName, const QString &TuneChan, const QString &StartChan, const QString &DisplayName, bool DishnetEIT, uint RecPriority, uint Quicktune, uint SchedOrder, uint LiveTVOrder)
Definition: v2capture.cpp:406
static bool UnlinkInputGroup(uint InputId, uint InputGroupId)
Definition: v2capture.cpp:577
static bool RemoveCardInput(int CardInputId)
Definition: v2capture.cpp:396
static bool DeleteRecProfile(uint ProfileId)
Definition: v2capture.cpp:1369
static int AddDiseqcTree(uint ParentId, uint Ordinal, const QString &Type, const QString &SubType, const QString &Description, uint SwitchPorts, float RotorHiSpeed, float RotorLoSpeed, const QString &RotorPositions, int LnbLofSwitch, int LnbLofHi, int LnbLofLo, int CmdRepeat, bool LnbPolInv, int Address, uint ScrUserband, uint ScrFrequency, int ScrPin)
Definition: v2capture.cpp:878
static V2CaptureDeviceList * GetCaptureDeviceList(const QString &CardType)
Definition: v2capture.cpp:638
static V2CaptureCard * GetCaptureCard(int CardId)
Definition: v2capture.cpp:188
static bool RemoveDiseqcTree(uint DiSEqCId)
Definition: v2capture.cpp:1061
static int AddRecProfile(uint GroupId, const QString &ProfileName, const QString &VideoCodec, const QString &AudioCodec)
Definition: v2capture.cpp:1270
static V2DiseqcConfigList * GetDiseqcConfigList(void)
Definition: v2capture.cpp:1094
static V2InputGroupList * GetUserInputGroupList(void)
Definition: v2capture.cpp:519
static bool UpdateRecProfileParam(uint ProfileId, const QString &Name, const QString &Value)
Definition: v2capture.cpp:1397
static bool SetInputMaxRecordings(uint InputId, uint Max)
Definition: v2capture.cpp:586
static bool RemoveAllCaptureCards(void)
Definition: v2capture.cpp:322
static bool UpdateRecProfile(uint ProfileId, const QString &VideoCodec, const QString &AudioCodec)
Definition: v2capture.cpp:1324
static V2DiseqcTreeList * GetDiseqcTreeList(void)
Definition: v2capture.cpp:808
static bool AddDiseqcConfig(uint CardId, uint DiSEqCId, const QString &Value)
Definition: v2capture.cpp:1132
V2RecProfile * AddProfile()
V2RecProfParam * AddParam()
unsigned int uint
Definition: freesurround.h:24
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(CAPTURE_HANDLE, V2Capture::staticMetaObject, &V2Capture::RegisterCustomTypes)) void V2Capture
Definition: v2capture.cpp:50
#define CAPTURE_HANDLE
Definition: v2capture.h:34
V2CaptureDeviceList * getV4l2List(const QRegularExpression &driver, const QString &cardType)
V2CaptureDeviceList * getFirewireList(const QString &cardType)