MythTV  master
v2capture.cpp
Go to the documentation of this file.
1 // 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"
37 #include "libmythbase/mythdate.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 
193  MSqlQuery query(MSqlQuery::InitCon());
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);
280  CardUtil::INPUT_TYPES cardType = CardUtil::toInputType(subtype);
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 {
324  return CardUtil::DeleteAllInputs();
325 }
326 
327 bool V2Capture::RemoveCaptureCard( int nCardId )
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 
341 int 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 
384 bool V2Capture::UpdateCaptureCard ( int nCardId,
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 
396 bool 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 
406 int 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 
439 bool 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 
523  MSqlQuery query(MSqlQuery::InitCon());
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 
550 int V2Capture::AddUserInputGroup(const QString & Name)
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 
567 bool V2Capture::LinkInputGroup(const uint InputId,
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
594 static 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") {
650  return getFirewireList(CardType);
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 {
810  MSqlQuery query(MSqlQuery::InitCon());
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 {
897  MSqlQuery query(MSqlQuery::InitCon());
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 {
998  MSqlQuery query(MSqlQuery::InitCon());
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
1064  MSqlQuery query(MSqlQuery::InitCon());
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 
1097  MSqlQuery query(MSqlQuery::InitCon());
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 {
1136  MSqlQuery query(MSqlQuery::InitCon());
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 {
1163  MSqlQuery query(MSqlQuery::InitCon());
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 
1176 V2RecProfileGroupList* V2Capture::GetRecProfileGroupList ( uint GroupId, uint ProfileId, bool OnlyInUse ) {
1177 
1178  MSqlQuery query(MSqlQuery::InitCon());
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 
1270 int 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 
1280  MSqlQuery query(MSqlQuery::InitCon());
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 {
1328  MSqlQuery query(MSqlQuery::InitCon());
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
1372  MSqlQuery query(MSqlQuery::InitCon());
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 
1397 bool V2Capture::UpdateRecProfileParam ( uint ProfileId, const QString &Name, const QString &Value )
1398 {
1399  MSqlQuery query(MSqlQuery::InitCon());
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 }
CardUtil::HDHRdoesDVBC
static bool HDHRdoesDVBC(const QString &device)
If the device is valid, check if the model does DVB-C.
Definition: cardutil.cpp:3106
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:127
CardUtil::GetVBoxdesc
static QString GetVBoxdesc(const QString &id, const QString &ip, const QString &tunerNo, const QString &tunerType)
Get a nicely formatted string describing the device.
Definition: cardutil.cpp:3185
V2CardTypeList
Definition: v2captureCardList.h:58
CardUtil::INPUT_TYPES::HDHOMERUN
@ HDHOMERUN
CardUtil::CreateCardInput
static int CreateCardInput(uint inputid, uint sourceid, const QString &inputname, const QString &externalcommand, const QString &changer_device, const QString &changer_model, const QString &hostname, const QString &tunechan, const QString &startchan, const QString &displayname, bool dishnet_eit, uint recpriority, uint quicktune, uint schedorder, uint livetvorder)
Definition: cardutil.cpp:1967
CardUtil::INPUT_TYPES::ERROR_PROBE
@ ERROR_PROBE
MSqlQuery::isNull
bool isNull(int field) const
Definition: mythdbcon.h:219
V2Capture::UpdateCardInput
static bool UpdateCardInput(int CardInputId, const QString &Setting, const QString &Value)
Definition: v2capture.cpp:439
V2Capture::UpdateRecProfileParam
static bool UpdateRecProfileParam(uint ProfileId, const QString &Name, const QString &Value)
Definition: v2capture.cpp:1397
V2Capture::LinkInputGroup
static bool LinkInputGroup(uint InputId, uint InputGroupId)
Definition: v2capture.cpp:567
mythdb.h
CardUtil::DeleteAllInputs
static bool DeleteAllInputs(void)
Definition: cardutil.cpp:2893
CardUtil::INPUT_TYPES::QAM
@ QAM
CardUtil::INPUT_TYPES::DVBS2
@ DVBS2
MSqlQuery::lastInsertId
QVariant lastInsertId()
Return the id of the last inserted row.
Definition: mythdbcon.cpp:935
V2DiseqcConfigList
Definition: v2captureCardList.h:213
V2Capture::GetRecProfileGroupList
static V2RecProfileGroupList * GetRecProfileGroupList(uint GroupId, uint ProfileId, bool OnlyInUse)
Definition: v2capture.cpp:1176
V2Capture::AddCardInput
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
V2Capture::RemoveAllCaptureCards
static bool RemoveAllCaptureCards(void)
Definition: v2capture.cpp:322
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:204
V2Capture::GetDiseqcTreeList
static V2DiseqcTreeList * GetDiseqcTreeList(void)
Definition: v2capture.cpp:808
mythhttpmetaservice.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
V2Capture::GetCaptureCardList
static V2CaptureCardList * GetCaptureCardList(const QString &HostName, const QString &CardType)
Definition: v2capture.cpp:83
set_on_input
bool set_on_input(const QString &to_set, uint inputid, const QString &value)
Definition: cardutil.cpp:1275
V2CaptureCardList
Definition: v2captureCardList.h:21
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
CardUtil::INPUT_TYPES::OFDM
@ OFDM
V2Capture::UpdateCaptureCard
static bool UpdateCaptureCard(int CardId, const QString &Setting, const QString &Value)
Definition: v2capture.cpp:384
getV4l2List
V2CaptureDeviceList * getV4l2List(const QRegularExpression &driver, const QString &cardType)
Definition: v2serviceUtil.cpp:1045
V2CaptureDeviceList
Definition: v2captureCardList.h:97
V2Capture::UpdateRecProfile
static bool UpdateRecProfile(uint ProfileId, const QString &VideoCodec, const QString &AudioCodec)
Definition: v2capture.cpp:1324
CardUtil::IsUniqueDisplayName
static bool IsUniqueDisplayName(const QString &name, uint exclude_inputid)
Definition: cardutil.cpp:1898
CardUtil::ProbeSubTypeName
static QString ProbeSubTypeName(uint inputid)
Definition: cardutil.cpp:983
CardUtil::ProbeDefaultDeliverySystem
static QString ProbeDefaultDeliverySystem(const QString &device)
Definition: cardutil.cpp:709
CardUtil::ProbeDVBType
static QString ProbeDVBType(const QString &device)
Definition: cardutil.cpp:725
V2Capture::SetInputMaxRecordings
static bool SetInputMaxRecordings(uint InputId, uint Max)
Definition: v2capture.cpp:586
satiputils.h
CardUtil::ProbeVideoDevices
static QStringList ProbeVideoDevices(const QString &rawtype)
Definition: cardutil.cpp:449
V2InputGroupList
Definition: v2captureCardList.h:134
CardUtil::ProbeDVBFrontendName
static QString ProbeDVBFrontendName(const QString &device)
Returns the input type from the video device.
Definition: cardutil.cpp:746
mythdate.h
CardUtil::UnlinkInputGroup
static bool UnlinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:2157
mythlogging.h
v2serviceUtil.h
hardwareprofile.scan.profile
profile
Definition: scan.py:96
CardUtil::INPUT_TYPES::ERROR_OPEN
@ ERROR_OPEN
V2Capture::AddDiseqcConfig
static bool AddDiseqcConfig(uint CardId, uint DiSEqCId, const QString &Value)
Definition: v2capture.cpp:1132
V2RecProfileGroupList
Definition: v2recordingProfile.h:113
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
compat.h
V2RecProfile
Definition: v2recordingProfile.h:42
MythDB::DBError
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
SatIP::toDVBInputType
static CardUtil::INPUT_TYPES toDVBInputType(const QString &deviceid)
Definition: satiputils.cpp:171
V2CaptureCard
Definition: v2captureCard.h:21
v2capture.h
V2Capture::GetUserInputGroupList
static V2InputGroupList * GetUserInputGroupList(void)
Definition: v2capture.cpp:519
CAPTURE_HANDLE
#define CAPTURE_HANDLE
Definition: v2capture.h:34
CardUtil::INPUT_TYPES::ATSC
@ ATSC
MSqlQuery::isConnected
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:137
V2Capture::AddDiseqcTree
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
CardUtil::ProbeDeliverySystems
static QStringList ProbeDeliverySystems(const QString &device)
MythHTTPService
Definition: mythhttpservice.h:19
CardUtil::InputSetMaxRecordings
static bool InputSetMaxRecordings(uint parentid, uint max_recordings)
Definition: cardutil.cpp:1561
V2Capture::V2Capture
V2Capture()
Definition: v2capture.cpp:74
V2Capture::RemoveDiseqcTree
static bool RemoveDiseqcTree(uint DiSEqCId)
Definition: v2capture.cpp:1061
CardType
Definition: videosource.h:347
standardsettings.h
Q_GLOBAL_STATIC_WITH_ARGS
Q_GLOBAL_STATIC_WITH_ARGS(MythHTTPMetaService, s_service,(CAPTURE_HANDLE, V2Capture::staticMetaObject, &V2Capture::RegisterCustomTypes)) void V2Capture
Definition: v2capture.cpp:50
CardUtil::INPUT_TYPES::QPSK
@ QPSK
MythHTTPService::Name
QString & Name()
Definition: mythhttpservice.cpp:276
getFirewireList
V2CaptureDeviceList * getFirewireList([[maybe_unused]] const QString &cardType)
Definition: v2serviceUtil.cpp:1147
V2Capture::RegisterCustomTypes
static void RegisterCustomTypes()
V2Capture::RemoveDiseqcConfig
static bool RemoveDiseqcConfig(uint CardId)
Definition: v2capture.cpp:1161
V2Capture::DeleteRecProfile
static bool DeleteRecProfile(uint ProfileId)
Definition: v2capture.cpp:1369
V2Capture::GetDiseqcConfigList
static V2DiseqcConfigList * GetDiseqcConfigList(void)
Definition: v2capture.cpp:1094
cardutil.h
CardUtil::CreateCaptureCard
static int CreateCaptureCard(const QString &videodevice, const QString &audiodevice, const QString &vbidevice, const QString &inputtype, uint audioratelimit, const QString &hostname, uint dvb_swfilter, uint dvb_sat_type, bool dvb_wait_for_seqstart, bool skipbtaudio, bool dvb_on_demand, uint dvb_diseqc_type, uint firewire_speed, const QString &firewire_model, uint firewire_connection, 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
Name
Definition: channelsettings.cpp:103
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
CardUtil::INPUT_TYPES::DVBT2
@ DVBT2
CardUtil::HDHRdoesDVB
static bool HDHRdoesDVB(const QString &device)
If the device is valid, check if the model does DVB.
Definition: cardutil.cpp:3080
V2RecProfileGroup
Definition: v2recordingProfile.h:79
V2DiseqcTreeList
Definition: v2captureCardList.h:177
V2Capture::UnlinkInputGroup
static bool UnlinkInputGroup(uint InputId, uint InputGroupId)
Definition: v2capture.cpp:577
V2RecProfileGroup::AddProfile
V2RecProfile * AddProfile()
Definition: v2recordingProfile.h:97
V2Capture::GetCardTypeList
static V2CardTypeList * GetCardTypeList(void)
Definition: v2capture.cpp:449
V2CardSubType
Definition: v2captureCard.h:307
V2Capture::RemoveCaptureCard
static bool RemoveCaptureCard(int CardId)
Definition: v2capture.cpp:327
V2Capture::UpdateDiseqcTree
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
CardUtil::INPUT_TYPES::ERROR_UNKNOWN
@ ERROR_UNKNOWN
V2Capture::AddCaptureCard
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
MSqlQuery::numRowsAffected
int numRowsAffected() const
Definition: mythdbcon.h:217
recordingprofile.h
V2Capture::AddUserInputGroup
static int AddUserInputGroup(const QString &Name)
Definition: v2capture.cpp:550
V2Capture::GetCardSubType
static V2CardSubType * GetCardSubType(int CardId)
Definition: v2capture.cpp:276
RecordingProfile
Definition: recordingprofile.h:41
V2RecProfile::AddParam
V2RecProfParam * AddParam()
Definition: v2recordingProfile.h:56
CardUtil::INPUT_TYPES
INPUT_TYPES
all the different inputs
Definition: cardutil.h:49
V2Capture::GetCaptureDeviceList
static V2CaptureDeviceList * GetCaptureDeviceList(const QString &CardType)
Definition: v2capture.cpp:638
V2Capture::GetCaptureCard
static V2CaptureCard * GetCaptureCard(int CardId)
Definition: v2capture.cpp:188
CardUtil::CreateInputGroup
static uint CreateInputGroup(const QString &name)
Definition: cardutil.cpp:2027
CardUtil::LinkInputGroup
static bool LinkInputGroup(uint inputid, uint inputgroupid)
Definition: cardutil.cpp:2106
MythHTTPMetaService
Definition: mythhttpmetaservice.h:10
CardUtil::INPUT_TYPES::SATIP
@ SATIP
V2Capture::AddRecProfile
static int AddRecProfile(uint GroupId, const QString &ProfileName, const QString &VideoCodec, const QString &AudioCodec)
Definition: v2capture.cpp:1270
CardUtil::GetVideoDevice
static QString GetVideoDevice(uint inputid)
Definition: cardutil.h:294
uint
unsigned int uint
Definition: freesurround.h:24
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
CardUtil::toInputType
static INPUT_TYPES toInputType(const QString &name)
Definition: cardutil.h:78
CardUtil::DeleteInput
static bool DeleteInput(uint inputid)
Definition: cardutil.cpp:2823
V2Capture::RemoveCardInput
static bool RemoveCardInput(int CardInputId)
Definition: v2capture.cpp:396