MythTV master
channelbase.cpp
Go to the documentation of this file.
1// POSIX headers
2#include <unistd.h>
3#include <fcntl.h>
4#include <sys/stat.h>
5#include <sys/types.h>
6
7// C++ headers
8#include <algorithm>
9#include <cerrno>
10#include <cstdlib>
11#include <iostream>
12
13// Qt headers
14#include <QCoreApplication>
15
16// MythTV headers
17#include "libmythbase/compat.h"
19#include "libmythbase/mythconfig.h"
22
23#if CONFIG_FIREWIRE_OSX
25#endif
26#if CONFIG_FIREWIRE_LINUX
27#include "linuxfirewiredevice.h"
28#endif
29#include "firewirechannel.h"
30#include "cetonchannel.h"
31#include "dummychannel.h"
32#include "tvremoteutil.h"
33#include "channelbase.h"
34#include "channelutil.h"
35#include "frequencies.h"
36#include "hdhrchannel.h"
37#include "iptvchannel.h"
38#include "asichannel.h"
39#include "dtvchannel.h"
40#include "dvbchannel.h"
41#include "v4lchannel.h"
42#include "ExternalChannel.h"
43#include "sourceutil.h"
44#include "cardutil.h"
45#include "inputinfo.h"
46#include "satipchannel.h"
47
48#define LOC QString("ChannelBase[%1]: ").arg(m_inputId)
49
50ChannelBase::ChannelBase(TVRec *parent) : m_pParent(parent)
51{
52 if (m_pParent)
53 {
55 }
56}
57
59{
60 QMutexLocker locker(&m_systemLock);
61 if (m_system)
62 KillScript();
63}
64
65bool ChannelBase::Init(QString &startchannel, bool setchan)
66{
67 bool ok = false;
68
69 if (!setchan)
70 ok = IsTunable(startchannel);
71 else
72 ok = SetChannelByString(startchannel);
73
74 if (ok)
75 return true;
76
77 // Try to find a valid channel if given start channel fails.
78 QString msg1 = QString("Setting start channel '%1' failed ").arg(startchannel);
79 QString msg2 = "and no suitable channel found.";
80 bool msg_error = true;
81
82 // Attempt to find the requested startchannel
83 for (auto & channel : m_channels)
84 {
85 if (channel.m_chanNum == startchannel &&
86 IsTunable(startchannel))
87 {
88 LOG(VB_CHANNEL, LOG_INFO, LOC +
89 QString("Found startchannel '%1'").arg(startchannel));
90 return true;
91 }
92 }
93
94 uint mplexid_restriction = 0;
95 uint chanid_restriction = 0;
96
97 if (!m_channels.empty() &&
98 IsInputAvailable(mplexid_restriction, chanid_restriction))
99 {
101 m_channels, m_channels[0].m_chanId,
102 mplexid_restriction, chanid_restriction, CHANNEL_DIRECTION_UP);
103
105
106 if ((chanid != 0U) && (cit != m_channels.end()))
107 {
108 if (!setchan)
109 {
110 ok = IsTunable((mplexid_restriction || chanid_restriction)
111 ? (*cit).m_chanNum : startchannel);
112 }
113 else
114 {
115 ok = SetChannelByString((*cit).m_chanNum);
116 }
117
118 if (ok)
119 {
120 startchannel = (*cit).m_chanNum;
121 msg2 = QString("selected '%1' instead.").arg(startchannel);
122 msg_error = false;
123 }
124 }
125 }
126
127 LOG(VB_GENERAL, ((msg_error) ? LOG_ERR : LOG_WARNING), LOC + msg1 + msg2);
128
129 return ok;
130}
131
132bool ChannelBase::IsTunable(const QString &channum) const
133{
134 QString loc = LOC + QString("IsTunable(%1)").arg(channum);
135
136 if (!m_inputId)
137 {
138 LOG(VB_GENERAL, LOG_ERR, loc + " " +
139 QString("Requested non-existant input"));
140
141 return false;
142 }
143
144 uint mplexid_restriction = 0;
145 uint chanid_restriction = 0;
146 if (!IsInputAvailable(mplexid_restriction, chanid_restriction))
147 {
148 LOG(VB_GENERAL, LOG_ERR, loc + " " +
149 QString("Requested channel is on input '%1' "
150 "which is in a busy input group")
151 .arg(m_inputId));
152
153 return false;
154 }
155
156 // Fetch tuning data from the database.
157 QString name;
158 QString callsign;
159 QString tvformat;
160 QString modulation;
161 QString freqtable;
162 QString freqid;
163 QString dtv_si_std;
164 int finetune = 0;
165 uint64_t frequency = 0;
166 int mpeg_prog_num = 0;
167 uint atsc_major = 0;
168 uint atsc_minor = 0;
169 uint mplexid = 0;
170 uint chanid = 0;
171 uint tsid = 0;
172 uint netid = 0;
173 bool commfree = false;
174
175 if (!ChannelUtil::GetChannelData(m_sourceId, chanid, channum,
176 name, callsign,
177 tvformat, modulation, freqtable, freqid,
178 finetune, frequency, dtv_si_std,
179 mpeg_prog_num, atsc_major, atsc_minor,
180 tsid, netid, mplexid, commfree))
181 {
182 LOG(VB_GENERAL, LOG_ERR, loc + " " +
183 QString("Failed to find channel in DB on input '%1' ")
184 .arg(m_inputId));
185
186 return false;
187 }
188
189 if ((mplexid_restriction && (mplexid != mplexid_restriction)) ||
190 (!mplexid_restriction &&
191 chanid_restriction && (chanid != chanid_restriction)))
192 {
193 LOG(VB_GENERAL, LOG_ERR, loc + " " +
194 QString("Channel is valid, but tuner is busy "
195 "on different multiplex/channel (%1 != %2) / (%3 != %4)")
196 .arg(mplexid).arg(mplexid_restriction)
197 .arg(chanid).arg(chanid_restriction));
198
199 return false;
200 }
201
202 return true;
203}
204
206{
207 if (!chanid)
208 {
209 if (!m_inputId)
210 return 0;
211
213 }
214
215 uint mplexid_restriction = 0;
216 uint chanid_restriction = 0;
217 (void)IsInputAvailable(mplexid_restriction, chanid_restriction);
218
220 m_channels, chanid, mplexid_restriction, chanid_restriction,
221 direction);
222}
223
224uint ChannelBase::GetNextChannel(const QString &channum, ChannelChangeDirection direction) const
225{
226 if (!m_inputId)
227 return 0;
228
229 uint chanid = ChannelUtil::GetChanID(m_sourceId, channum);
230 return GetNextChannel(chanid, direction);
231}
232
234 uint &mplexid_restriction, uint &chanid_restriction) const
235{
236 if (!m_inputId)
237 {
238 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("no m_inputId"));
239 return false;
240 }
241
243
244 mplexid_restriction = 0;
245 chanid_restriction = 0;
246
247 std::vector<uint> inputids = CardUtil::GetConflictingInputs(m_inputId);
248 for (uint inputid : inputids)
249 {
250 if (RemoteIsBusy(inputid, info))
251 {
252 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
253 QString("Input %1 is busy on %2/%3")
254 .arg(info.m_inputId)
255 .arg(info.m_chanId).arg(info.m_mplexId));
256 if (info.m_sourceId != m_sourceId)
257 {
258 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Input is busy"));
259 return false;
260 }
261 mplexid_restriction = info.m_mplexId;
262 chanid_restriction = info.m_chanId;
263 }
264 }
265
266 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Input is free on %1/%2")
267 .arg(mplexid_restriction).arg(chanid_restriction));
268 return true;
269}
270
273{
274 if (!m_system)
275 return true;
276
277 m_system->Term(true);
278
279 delete m_system;
280 m_system = nullptr;
281 return true;
282}
283
285void ChannelBase::HandleScript(const QString &freqid)
286{
287 QMutexLocker locker(&m_systemLock);
288
289 bool ok = true;
290 m_systemStatus = 0; // unknown
291
292 if (!m_inputId)
293 {
294 m_systemStatus = 2; // failed
295 HandleScriptEnd(true);
296 return;
297 }
298
299 if (m_externalChanger.isEmpty())
300 {
301 m_systemStatus = 3; // success
302 HandleScriptEnd(true);
303 return;
304 }
305
306 if (freqid.isEmpty())
307 {
308 LOG(VB_GENERAL, LOG_WARNING, LOC +
309 "A channel changer is set, but the freqid field is empty."
310 "\n\t\t\tWe will return success to ease setup pains, "
311 "but no script is will actually run.");
312 m_systemStatus = 3; // success
313 HandleScriptEnd(true);
314 return;
315 }
316
317 // It's possible we simply never reaped the process, check status first.
318 if (m_system)
319 GetScriptStatus(true);
320
321 // If it's still running, try killing it. GetScriptStatus() may
322 // update m_system. (cppcheck-suppress duplicateCondition)
323 if (m_system)
324 ok = KillScript();
325
326 // The GetScriptStatus() call above can reset m_systemStatus with
327 // the exit status of the last channel change script invocation, so
328 // we must set it to pending here.
329 m_systemStatus = 1; // pending
330
331 if (!ok)
332 {
333 LOG(VB_GENERAL, LOG_ERR, LOC +
334 "Can not execute channel changer, previous call to script "
335 "is still running.");
336 m_systemStatus = 2; // failed
337 HandleScriptEnd(ok);
338 }
339 else
340 {
341 if (m_externalChanger.toLower() == "internal")
342 {
343 ok = ChangeInternalChannel(freqid, m_inputId);
344 if (!ok)
345 {
346 LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute internal channel "
347 "changer.");
348 m_systemStatus = 2; // failed
349 }
350 else
351 {
352 m_systemStatus = 3; // success
353 }
354
355 HandleScriptEnd(ok);
356 }
357 else
358 {
360 if (!ok)
361 {
362 LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute channel changer.");
363 m_systemStatus = 2; // failed
364 HandleScriptEnd(ok);
365 }
366 }
367 }
368}
369
370// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
371bool ChannelBase::ChangeInternalChannel([[maybe_unused]] const QString &freqid,
372 [[maybe_unused]] uint inputid) const
373{
374#if CONFIG_FIREWIRE
375 FirewireDevice *device = nullptr;
376 QString fwnode = CardUtil::GetFirewireChangerNode(inputid);
377 uint64_t guid = string_to_guid(fwnode);
378 QString fwmodel = CardUtil::GetFirewireChangerModel(inputid);
379
380 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Internal channel change to %1 "
381 "on inputid %2, GUID %3 (%4)").arg(freqid).arg(inputid)
382 .arg(fwnode, fwmodel));
383
384#if CONFIG_FIREWIRE_LINUX
385 device = new LinuxFirewireDevice(guid, 0, 100, true);
386#endif // CONFIG_FIREWIRE_LINUX
387
388#if CONFIG_FIREWIRE_OSX
389 device = new DarwinFirewireDevice(guid, 0, 100);
390#endif // CONFIG_FIREWIRE_OSX
391
392 if (!device)
393 return false;
394
395 if (!device->OpenPort())
396 return false;
397
398 if (!device->SetChannel(fwmodel, 0, freqid.toUInt()))
399 {
400 device->ClosePort();
401 delete device;
402 device = nullptr;
403 return false;
404 }
405
406 device->ClosePort();
407 delete device;
408 device = nullptr;
409 return true;
410#else
411 return false;
412#endif
413}
414
416bool ChannelBase::ChangeExternalChannel(const QString &changer,
417 const QString &freqid)
418{
419 if (m_system)
420 return false;
421
422 if (changer.isEmpty() || freqid.isEmpty())
423 return false;
424
425 QString command = QString("%1 %2").arg(changer, freqid);
426 LOG(VB_CHANNEL, LOG_INFO, LOC +
427 QString("Running command: %1").arg(command));
428
430 m_system->Run();
431
432 return true;
433}
434
436{
437 if (!m_system)
438 return m_systemStatus;
439
440 if (!holding_lock)
441 m_systemLock.lock();
442
446 {
447 delete m_system;
448 m_system = nullptr;
449
451 }
452
453 LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetScriptStatus() %1")
454 .arg(m_systemStatus));
455
456 uint ret = 0;
457 switch(m_systemStatus)
458 {
459 case GENERIC_EXIT_OK:
460 ret = 3; // success
461 break;
464 ret = 1; // pending
465 break;
466 default:
467 ret = 2; // fail
468 break;
469 }
470
471 LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetScriptStatus() %1 -> %2")
472 .arg(m_systemStatus). arg(ret));
473
474 m_systemStatus = ret;
475
476 if (!holding_lock)
477 m_systemLock.unlock();
478
479 return ret;
480}
481
484{
485 if (ok)
486 {
487 LOG(VB_CHANNEL, LOG_INFO, LOC + "Channel change script succeeded.");
488 if (m_inputId)
489 {
490 // Set this as the future start channel for this source
492 }
493 }
494 else
495 {
496 LOG(VB_GENERAL, LOG_ERR, LOC + "Channel change script failed.");
497 }
498}
499
501{
502 if (!m_inputId)
503 return -1;
504
505 int found = 0;
506 int visible = -1;
507 int id = -1;
509
510 query.prepare("SELECT chanid,visible FROM channel "
511 "WHERE deleted IS NULL AND "
512 " channum = :CHANNUM AND "
513 " sourceid = :SOURCEID");
514 query.bindValueNoNull(":CHANNUM", m_curChannelName);
515 query.bindValue(":SOURCEID", m_sourceId);
516
517 if (!query.exec() || !query.isActive())
518 {
519 MythDB::DBError("fetching chanid", query);
520 return -1;
521 }
522
523 while (query.next())
524 {
525 if (query.value(1).toInt() > 0)
526 {
527 ++found;
528 visible = query.value(0).toInt();
529 }
530 else
531 {
532 id = query.value(0).toInt();
533 }
534 }
535
536 if (!found)
537 {
538 LOG(VB_GENERAL, LOG_INFO,
539 QString("No visible channel ids for %1 on sourceid %2")
540 .arg(m_curChannelName).arg(m_sourceId));
541 }
542
543 if (found > 1)
544 {
545 LOG(VB_GENERAL, LOG_WARNING,
546 QString("Found multiple visible channel ids for %1 on sourceid %2")
547 .arg(m_curChannelName).arg(m_sourceId));
548 }
549
550 return (visible >= 0 ? visible : id);
551}
552
557{
558 if (!m_inputId)
559 {
560 if (m_pParent)
562 else
564 }
565
566 if (!m_inputId)
567 {
568 LOG(VB_GENERAL, LOG_ERR,
569 "InitializeInput(): Programmer error, no parent.");
570 return false;
571 }
572
574 query.prepare(
575 "SELECT sourceid, inputname, "
576 " startchan, externalcommand, "
577 " tunechan "
578 "FROM capturecard "
579 "WHERE cardid = :INPUTID");
580 query.bindValue(":INPUTID", m_inputId);
581
582 if (!query.exec() || !query.isActive())
583 {
584 MythDB::DBError("ChannelBase::InitializeInput", query);
585 return false;
586 }
587 if (!query.size())
588 {
589 LOG(VB_GENERAL, LOG_ERR, LOC +
590 QString("No capturecard record in database for input %1")
591 .arg(m_inputId));
592 return false;
593 }
594
595 query.next();
596
597 m_sourceId = query.value(0).toUInt();
598 m_name = query.value(1).toString();
599 m_startChanNum = query.value(2).toString();
600 m_externalChanger = query.value(3).toString();
601 m_tuneToChannel = query.value(4).toString();
602
603 if (0 == m_sourceId)
604 {
605 LOG(VB_GENERAL, LOG_ERR, LOC +
606 QString("No video source defined for input %1")
607 .arg(m_inputId));
608 return false;
609 }
610
612 QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
614
616 !m_externalChanger.isEmpty())
617 {
618 LOG(VB_GENERAL, LOG_WARNING, LOC + "External Channel changer is "
619 "set, but this device does not support it.");
620 m_externalChanger.clear();
621 }
622
623 // print it
624 LOG(VB_CHANNEL, LOG_INFO, LOC +
625 QString("Input #%1: '%2' schan(%3) sourceid(%4)")
627 .arg(m_sourceId));
628
629 return true;
630}
631
636 const QString &oldChanNum,
637 const QString &newChanNum)
638{
639 bool skip = (m_name.isEmpty() ||
640 m_startChanNum.isEmpty() ||
641 m_startChanNum != oldChanNum ||
642 m_sourceId != sourceid);
643 if (!skip)
644 m_startChanNum = newChanNum;
645
646 if (GetSourceID() == sourceid && oldChanNum == m_curChannelName)
647 m_curChannelName = newChanNum;
648
650}
651
656{
658
659 if (m_name.isEmpty() || m_startChanNum.isEmpty())
660 return;
661
662 query.prepare(
663 "UPDATE capturecard "
664 "SET startchan = :STARTCHAN "
665 "WHERE cardid = :CARDINPUTID");
666 query.bindValue(":STARTCHAN", m_startChanNum);
667 query.bindValue(":CARDINPUTID", m_inputId);
668
669 if (!query.exec() || !query.isActive())
670 MythDB::DBError("StoreInputChannels", query);
671}
672
673bool ChannelBase::CheckChannel(const QString &channum) const
674{
676 if (!query.isConnected())
677 return false;
678
679 query.prepare(
680 "SELECT channel.chanid "
681 "FROM channel, capturecard "
682 "WHERE channel.deleted IS NULL AND "
683 " channel.channum = :CHANNUM AND "
684 " channel.sourceid = capturecard.sourceid AND "
685 " capturecard.cardid = :INPUTID AND "
686 " capturecard.hostname = :HOSTNAME");
687 query.bindValue(":CHANNUM", channum);
688 query.bindValue(":INPUTID", m_inputId);
689 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
690
691 if (!query.exec() || !query.isActive())
692 {
693 MythDB::DBError("checkchannel", query);
694 }
695 else if (query.size() > 0)
696 {
697 return true;
698 }
699
700 LOG(VB_CHANNEL, LOG_ERR, LOC +
701 QString("Failed to find channel(%1) on input (%2).")
702 .arg(channum).arg(m_inputId));
703 return false;
704}
705
707 TVRec *tvrec,
708 const GeneralDBOptions &genOpt,
709 const DVBDBOptions &dvbOpt,
710 [[maybe_unused]] const FireWireDBOptions &fwOpt,
711 const QString &startchannel,
712 bool enter_power_save_mode,
713 QString &rbFileExt,
714 bool setchan)
715{
716 rbFileExt = "ts";
717
718 ChannelBase *channel = nullptr;
719 if (genOpt.m_inputType == "DVB")
720 {
721#if CONFIG_DVB
722 channel = new DVBChannel(genOpt.m_videoDev, tvrec);
723 auto *dvbchannel = dynamic_cast<DVBChannel*>(channel);
724 if (dvbchannel != nullptr)
725 dvbchannel->SetSlowTuning(dvbOpt.m_dvbTuningDelay);
726#endif
727 }
728#if CONFIG_FIREWIRE
729 else if (genOpt.m_inputType == "FIREWIRE")
730 {
731 channel = new FirewireChannel(tvrec, genOpt.m_videoDev, fwOpt);
732 }
733#endif
734#if CONFIG_HDHOMERUN
735 else if (genOpt.m_inputType == "HDHOMERUN")
736 {
737 channel = new HDHRChannel(tvrec, genOpt.m_videoDev);
738 }
739#endif
740#if CONFIG_SATIP
741 else if (genOpt.m_inputType == "SATIP")
742 {
743 channel = new SatIPChannel(tvrec, genOpt.m_videoDev);
744 }
745#endif
746 else if ((genOpt.m_inputType == "IMPORT") ||
747 (genOpt.m_inputType == "DEMO") ||
748 (genOpt.m_inputType == "MPEG" &&
749 genOpt.m_videoDev.startsWith("file:", Qt::CaseInsensitive)))
750 {
751 channel = new DummyChannel(tvrec);
752 rbFileExt = "mpg";
753 }
754#if CONFIG_IPTV || CONFIG_VBOX
755 else if ((genOpt.m_inputType == "FREEBOX") || // IPTV
756 (genOpt.m_inputType == "VBOX"))
757 {
758 channel = new IPTVChannel(tvrec, genOpt.m_videoDev);
759 }
760#endif
761#if CONFIG_ASI
762 else if (genOpt.m_inputType == "ASI")
763 {
764 channel = new ASIChannel(tvrec, genOpt.m_videoDev);
765 }
766#endif
767#if CONFIG_CETON
768 else if (genOpt.m_inputType == "CETON")
769 {
770 channel = new CetonChannel(tvrec, genOpt.m_videoDev);
771 }
772#endif
773 else if (genOpt.m_inputType == "V4L2ENC")
774 {
775#if CONFIG_V4L2
776 channel = new V4LChannel(tvrec, genOpt.m_videoDev);
777#endif
778 if (genOpt.m_inputType == "MPEG")
779 rbFileExt = "mpg";
780 }
781 else if (CardUtil::IsV4L(genOpt.m_inputType))
782 {
783#if CONFIG_V4L2
784 channel = new V4LChannel(tvrec, genOpt.m_videoDev);
785#endif
786 if (genOpt.m_inputType != "HDPVR")
787 {
788 if (genOpt.m_inputType != "MPEG")
789 rbFileExt = "nuv";
790 else
791 rbFileExt = "mpg";
792 }
793 }
794 else if (genOpt.m_inputType == "EXTERNAL")
795 {
796 channel = new ExternalChannel(tvrec, genOpt.m_videoDev);
797 }
798
799 if (!channel)
800 {
801 QString msg = QString(
802 "%1 card configured on video device %2, \n"
803 "but MythTV was not compiled with %3 support. \n"
804 "\n"
805 "Recompile MythTV with %4 support or remove the card \n"
806 "from the configuration and restart MythTV.")
807 .arg(genOpt.m_inputType, genOpt.m_videoDev,
808 genOpt.m_inputType, genOpt.m_inputType);
809 LOG(VB_GENERAL, LOG_ERR, "ChannelBase: CreateChannel() Error: \n" +
810 msg + "\n");
811 return nullptr;
812 }
813
814 if (!channel->Open())
815 {
816 LOG(VB_GENERAL, LOG_ERR, "ChannelBase: CreateChannel() Error: " +
817 QString("Failed to open device %1").arg(genOpt.m_videoDev));
818 delete channel;
819 return nullptr;
820 }
821
822 QString channum = startchannel;
823 channel->Init(channum, setchan);
824
825 if (enter_power_save_mode)
826 {
827 if (channel &&
828 ((genOpt.m_inputType == "DVB" && dvbOpt.m_dvbOnDemand) ||
829 genOpt.m_inputType == "HDHOMERUN" ||
830 genOpt.m_inputType == "EXTERNAL" ||
832 {
833 channel->Close();
834 }
835 else if (setchan)
836 {
837 auto *dtvchannel = dynamic_cast<DTVChannel*>(channel);
838 if (dtvchannel)
839 dtvchannel->EnterPowerSavingMode();
840 }
841 }
842
843 return channel;
844}
845
847{
849 return false;
850
851 if (!m_inputId)
852 {
853 LOG(VB_GENERAL, LOG_ERR, LOC +
854 QString("IsExternalChannelChangeInUse: "
855 "non-existant input"));
856 return false;
857 }
858
859 return !m_externalChanger.isEmpty();
860}
861
863{
865}
static uint64_t string_to_guid(const QString &guid)
Definition: avcinfo.h:17
#define LOC
Definition: channelbase.cpp:48
-*- Mode: c++ -*-
Definition: asichannel.h:15
static QString GetFirewireChangerModel(uint inputid)
Definition: cardutil.cpp:1649
static uint GetFirstInputID(const QString &videodevice)
Convenience function for GetInputIDs()
Definition: cardutil.h:270
static bool IsV4L(const QString &rawtype)
Definition: cardutil.h:147
static QString GetFirewireChangerNode(uint inputid)
Definition: cardutil.cpp:1632
static std::vector< uint > GetConflictingInputs(uint inputid)
Definition: cardutil.cpp:2253
Abstract class providing a generic interface to tuning hardware.
Definition: channelbase.h:32
QString m_name
Definition: channelbase.h:139
void HandleScript(const QString &freqid)
virtual uint GetSourceID(void) const
Definition: channelbase.h:71
ChannelBase(TVRec *parent)
Definition: channelbase.cpp:50
bool ChangeInternalChannel(const QString &freqid, uint cardinputid) const
bool ChangeExternalChannel(const QString &changer, const QString &freqid)
virtual bool Open(void)=0
Opens the channel changing hardware for use.
virtual uint GetNextChannel(uint chanid, ChannelChangeDirection direction) const
virtual bool IsInputAvailable(uint &mplexid_restriction, uint &chanid_restriction) const
Switches to another input on hardware, and sets the channel is setstarting is true.
virtual void HandleScriptEnd(bool ok)
virtual bool IsTunable(const QString &channum) const
virtual void StoreInputChannels(void)
Saves current channel as the default channel for the current input.
virtual void Close(void)=0
Closes the channel changing hardware to use.
virtual ~ChannelBase(void)
Definition: channelbase.cpp:58
QMutex m_systemLock
Definition: channelbase.h:145
ChannelInfoList m_channels
channels across all inputs
Definition: channelbase.h:143
virtual void Renumber(uint sourceid, const QString &oldChanNum, const QString &newChanNum)
Changes a channum if we have it cached anywhere.
virtual bool IsExternalChannelChangeInUse(void)
bool CheckChannel(const QString &channum) const
uint m_systemStatus
These get mapped from the GENERIC_EXIT_* to these values for use with the signalmonitor code.
Definition: channelbase.h:150
virtual int GetChanID(void) const
virtual bool IsExternalChannelChangeSupported(void)
Definition: channelbase.h:121
virtual bool Init(QString &startchannel, bool setchan)
Definition: channelbase.cpp:65
uint m_sourceId
Definition: channelbase.h:138
QString m_curChannelName
Definition: channelbase.h:135
TVRec * m_pParent
Definition: channelbase.h:134
uint m_inputId
Definition: channelbase.h:137
QString m_externalChanger
Definition: channelbase.h:141
static ChannelBase * CreateChannel(TVRec *tvrec, const GeneralDBOptions &genOpt, const DVBDBOptions &dvbOpt, const FireWireDBOptions &fwOpt, const QString &startchannel, bool enter_power_save_mode, QString &rbFileExt, bool setchan)
virtual bool SetChannelByString(const QString &chan)=0
virtual bool InitializeInput(void)
Fills in input map from DB.
int GetMajorID(void)
bool KillScript(void)
uint GetScriptStatus(bool holding_lock=false)
MythSystemLegacy * m_system
Definition: channelbase.h:146
QString m_startChanNum
Definition: channelbase.h:140
virtual QString GetDevice(void) const
Returns String representing device, useful for debugging.
Definition: channelbase.h:78
QString m_tuneToChannel
Definition: channelbase.h:142
uint m_chanId
Definition: channelinfo.h:84
static int GetChanID(int db_mplexid, int service_transport_id, int major_channel, int minor_channel, int program_number)
static void SortChannels(ChannelInfoList &list, const QString &order, bool eliminate_duplicates=false)
static bool GetChannelData(uint sourceid, uint &chanid, const QString &channum, QString &name, QString &callsign, QString &tvformat, QString &modulation, QString &freqtable, QString &freqid, int &finetune, uint64_t &frequency, QString &dtv_si_std, int &mpeg_prog_num, uint &atsc_major, uint &atsc_minor, uint &dvb_transportid, uint &dvb_networkid, uint &mplexid, bool &commfree)
static uint GetNextChannel(const ChannelInfoList &sorted, uint old_chanid, uint mplexid_restriction, uint chanid_restriction, ChannelChangeDirection direction, bool skip_non_visible=true, bool skip_same_channum_and_callsign=false, bool skip_other_sources=false)
static ChannelInfoList GetChannels(uint sourceid, bool visible_only, const QString &group_by=QString(), uint channel_groupid=0)
Definition: channelutil.h:252
Class providing a generic interface to digital tuning hardware.
Definition: dtvchannel.h:34
virtual bool EnterPowerSavingMode(void)
Enters power saving mode if the card supports it.
Definition: dtvchannel.h:65
Provides interface to the tuning hardware when using DVB drivers.
Definition: dvbchannel.h:31
void SetSlowTuning(std::chrono::milliseconds how_slow)
Definition: dvbchannel.h:46
bool m_dvbOnDemand
Definition: tv_rec.h:85
std::chrono::milliseconds m_dvbTuningDelay
Definition: tv_rec.h:86
DummyChannel.
Definition: dummychannel.h:15
-*- Mode: c++ -*-
FirewireChannel Copyright (c) 2005 by Jim Westfall and Dave Abrahams Distributed as part of MythTV un...
virtual bool OpenPort(void)=0
virtual bool SetChannel(const QString &panel_model, uint alt_method, uint channel)
virtual bool ClosePort(void)=0
QString m_inputType
Definition: tv_rec.h:72
QString m_videoDev
Definition: tv_rec.h:69
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:838
QVariant value(int i) const
Definition: mythdbcon.h:204
int size(void) const
Definition: mythdbcon.h:214
bool isActive(void) const
Definition: mythdbcon.h:215
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:137
void bindValueNoNull(const QString &placeholder, const QVariant &val)
Add a single binding, taking care not to set a NULL value.
Definition: mythdbcon.cpp:903
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:619
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:889
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:813
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:551
QString GetHostName(void)
QString GetSetting(const QString &key, const QString &defaultval="")
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:225
uint Wait(std::chrono::seconds timeout=0s)
void Term(bool force=false)
void Run(std::chrono::seconds timeout=0s)
Runs a command inside the /bin/sh shell. Returns immediately.
This is the coordinating class of the Recorder Subsystem.
Definition: tv_rec.h:142
uint GetMajorId(void)
Definition: tv_rec.h:236
uint GetInputId(void) const
Returns the inputid.
Definition: tv_rec.h:234
Implements tuning for TV cards using the V4L driver API, both versions 1 and 2.
Definition: v4lchannel.h:33
unsigned int uint
Definition: compat.h:60
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
@ GENERIC_EXIT_START
MythSystemLegacy process starting.
Definition: exitcodes.h:38
@ GENERIC_EXIT_OK
Exited with no error.
Definition: exitcodes.h:13
@ GENERIC_EXIT_RUNNING
Process is running.
Definition: exitcodes.h:28
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
@ kMSRunShell
run process through shell
Definition: mythsystem.h:43
@ kMSRunBackground
run child in the background
Definition: mythsystem.h:38
dictionary info
Definition: azlyrics.py:7
ChannelChangeDirection
ChannelChangeDirection is an enumeration of possible channel changing directions.
Definition: tv.h:32
@ CHANNEL_DIRECTION_UP
Definition: tv.h:33
bool RemoteIsBusy(uint inputid, InputInfo &busy_input)