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