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 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 tvformat, modulation, freqtable, freqid,
177 finetune, frequency, dtv_si_std,
178 mpeg_prog_num, atsc_major, atsc_minor,
179 tsid, netid, mplexid, commfree))
180 {
181 LOG(VB_GENERAL, LOG_ERR, loc + " " +
182 QString("Failed to find channel in DB on input '%1' ")
183 .arg(m_inputId));
184
185 return false;
186 }
187
188 if ((mplexid_restriction && (mplexid != mplexid_restriction)) ||
189 (!mplexid_restriction &&
190 chanid_restriction && (chanid != chanid_restriction)))
191 {
192 LOG(VB_GENERAL, LOG_ERR, loc + " " +
193 QString("Channel is valid, but tuner is busy "
194 "on different multiplex/channel (%1 != %2) / (%3 != %4)")
195 .arg(mplexid).arg(mplexid_restriction)
196 .arg(chanid).arg(chanid_restriction));
197
198 return false;
199 }
200
201 return true;
202}
203
205{
206 if (!chanid)
207 {
208 if (!m_inputId)
209 return 0;
210
212 }
213
214 uint mplexid_restriction = 0;
215 uint chanid_restriction = 0;
216 (void)IsInputAvailable(mplexid_restriction, chanid_restriction);
217
219 m_channels, chanid, mplexid_restriction, chanid_restriction,
220 direction);
221}
222
223uint ChannelBase::GetNextChannel(const QString &channum, ChannelChangeDirection direction) const
224{
225 if (!m_inputId)
226 return 0;
227
228 uint chanid = ChannelUtil::GetChanID(m_sourceId, channum);
229 return GetNextChannel(chanid, direction);
230}
231
233 uint &mplexid_restriction, uint &chanid_restriction) const
234{
235 if (!m_inputId)
236 {
237 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("no m_inputId"));
238 return false;
239 }
240
242
243 mplexid_restriction = 0;
244 chanid_restriction = 0;
245
246 std::vector<uint> inputids = CardUtil::GetConflictingInputs(m_inputId);
247 for (uint inputid : inputids)
248 {
249 if (RemoteIsBusy(inputid, info))
250 {
251 LOG(VB_CHANNEL, LOG_DEBUG, LOC +
252 QString("Input %1 is busy on %2/%3")
253 .arg(info.m_inputId)
254 .arg(info.m_chanId).arg(info.m_mplexId));
255 if (info.m_sourceId != m_sourceId)
256 {
257 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Input is busy"));
258 return false;
259 }
260 mplexid_restriction = info.m_mplexId;
261 chanid_restriction = info.m_chanId;
262 }
263 }
264
265 LOG(VB_CHANNEL, LOG_INFO, LOC + QString("Input is free on %1/%2")
266 .arg(mplexid_restriction).arg(chanid_restriction));
267 return true;
268}
269
272{
273 if (!m_system)
274 return true;
275
276 m_system->Term(true);
277
278 delete m_system;
279 m_system = nullptr;
280 return true;
281}
282
284void ChannelBase::HandleScript(const QString &freqid)
285{
286 QMutexLocker locker(&m_systemLock);
287
288 bool ok = true;
289 m_systemStatus = 0; // unknown
290
291 if (!m_inputId)
292 {
293 m_systemStatus = 2; // failed
294 HandleScriptEnd(true);
295 return;
296 }
297
298 if (m_externalChanger.isEmpty())
299 {
300 m_systemStatus = 3; // success
301 HandleScriptEnd(true);
302 return;
303 }
304
305 if (freqid.isEmpty())
306 {
307 LOG(VB_GENERAL, LOG_WARNING, LOC +
308 "A channel changer is set, but the freqid field is empty."
309 "\n\t\t\tWe will return success to ease setup pains, "
310 "but no script is will actually run.");
311 m_systemStatus = 3; // success
312 HandleScriptEnd(true);
313 return;
314 }
315
316 // It's possible we simply never reaped the process, check status first.
317 if (m_system)
318 GetScriptStatus(true);
319
320 // If it's still running, try killing it. GetScriptStatus() may
321 // update m_system. (cppcheck-suppress duplicateCondition)
322 if (m_system)
323 ok = KillScript();
324
325 // The GetScriptStatus() call above can reset m_systemStatus with
326 // the exit status of the last channel change script invocation, so
327 // we must set it to pending here.
328 m_systemStatus = 1; // pending
329
330 if (!ok)
331 {
332 LOG(VB_GENERAL, LOG_ERR, LOC +
333 "Can not execute channel changer, previous call to script "
334 "is still running.");
335 m_systemStatus = 2; // failed
336 HandleScriptEnd(ok);
337 }
338 else
339 {
340 if (m_externalChanger.toLower() == "internal")
341 {
342 ok = ChangeInternalChannel(freqid, m_inputId);
343 if (!ok)
344 {
345 LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute internal channel "
346 "changer.");
347 m_systemStatus = 2; // failed
348 }
349 else
350 {
351 m_systemStatus = 3; // success
352 }
353
354 HandleScriptEnd(ok);
355 }
356 else
357 {
359 if (!ok)
360 {
361 LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute channel changer.");
362 m_systemStatus = 2; // failed
363 HandleScriptEnd(ok);
364 }
365 }
366 }
367}
368
369bool ChannelBase::ChangeInternalChannel([[maybe_unused]] const QString &freqid,
370 [[maybe_unused]] uint inputid) const
371{
372#if CONFIG_FIREWIRE
373 FirewireDevice *device = nullptr;
374 QString fwnode = CardUtil::GetFirewireChangerNode(inputid);
375 uint64_t guid = string_to_guid(fwnode);
376 QString fwmodel = CardUtil::GetFirewireChangerModel(inputid);
377
378 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Internal channel change to %1 "
379 "on inputid %2, GUID %3 (%4)").arg(freqid).arg(inputid)
380 .arg(fwnode, fwmodel));
381
382#if CONFIG_FIREWIRE_LINUX
383 device = new LinuxFirewireDevice(guid, 0, 100, true);
384#endif // CONFIG_FIREWIRE_LINUX
385
386#if CONFIG_FIREWIRE_OSX
387 device = new DarwinFirewireDevice(guid, 0, 100);
388#endif // CONFIG_FIREWIRE_OSX
389
390 if (!device)
391 return false;
392
393 if (!device->OpenPort())
394 return false;
395
396 if (!device->SetChannel(fwmodel, 0, freqid.toUInt()))
397 {
398 device->ClosePort();
399 delete device;
400 device = nullptr;
401 return false;
402 }
403
404 device->ClosePort();
405 delete device;
406 device = nullptr;
407 return true;
408#else
409 return false;
410#endif
411}
412
414bool ChannelBase::ChangeExternalChannel(const QString &changer,
415 const QString &freqid)
416{
417 if (m_system)
418 return false;
419
420 if (changer.isEmpty() || freqid.isEmpty())
421 return false;
422
423 QString command = QString("%1 %2").arg(changer, freqid);
424 LOG(VB_CHANNEL, LOG_INFO, LOC +
425 QString("Running command: %1").arg(command));
426
428 m_system->Run();
429
430 return true;
431}
432
434{
435 if (!m_system)
436 return m_systemStatus;
437
438 if (!holding_lock)
439 m_systemLock.lock();
440
444 {
445 delete m_system;
446 m_system = nullptr;
447
449 }
450
451 LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetScriptStatus() %1")
452 .arg(m_systemStatus));
453
454 uint ret = 0;
455 switch(m_systemStatus)
456 {
457 case GENERIC_EXIT_OK:
458 ret = 3; // success
459 break;
462 ret = 1; // pending
463 break;
464 default:
465 ret = 2; // fail
466 break;
467 }
468
469 LOG(VB_CHANNEL, LOG_DEBUG, LOC + QString("GetScriptStatus() %1 -> %2")
470 .arg(m_systemStatus). arg(ret));
471
472 m_systemStatus = ret;
473
474 if (!holding_lock)
475 m_systemLock.unlock();
476
477 return ret;
478}
479
482{
483 if (ok)
484 {
485 LOG(VB_CHANNEL, LOG_INFO, LOC + "Channel change script succeeded.");
486 if (m_inputId)
487 {
488 // Set this as the future start channel for this source
490 }
491 }
492 else
493 {
494 LOG(VB_GENERAL, LOG_ERR, LOC + "Channel change script failed.");
495 }
496}
497
499{
500 if (!m_inputId)
501 return -1;
502
503 int found = 0;
504 int visible = -1;
505 int id = -1;
507
508 query.prepare("SELECT chanid,visible FROM channel "
509 "WHERE deleted IS NULL AND "
510 " channum = :CHANNUM AND "
511 " sourceid = :SOURCEID");
512 query.bindValueNoNull(":CHANNUM", m_curChannelName);
513 query.bindValue(":SOURCEID", m_sourceId);
514
515 if (!query.exec() || !query.isActive())
516 {
517 MythDB::DBError("fetching chanid", query);
518 return -1;
519 }
520
521 while (query.next())
522 {
523 if (query.value(1).toInt() > 0)
524 {
525 ++found;
526 visible = query.value(0).toInt();
527 }
528 else
529 {
530 id = query.value(0).toInt();
531 }
532 }
533
534 if (!found)
535 {
536 LOG(VB_GENERAL, LOG_INFO,
537 QString("No visible channel ids for %1 on sourceid %2")
538 .arg(m_curChannelName).arg(m_sourceId));
539 }
540
541 if (found > 1)
542 {
543 LOG(VB_GENERAL, LOG_WARNING,
544 QString("Found multiple visible channel ids for %1 on sourceid %2")
545 .arg(m_curChannelName).arg(m_sourceId));
546 }
547
548 return (visible >= 0 ? visible : id);
549}
550
555{
556 if (!m_inputId)
557 {
558 if (m_pParent)
560 else
562 }
563
564 if (!m_inputId)
565 {
566 LOG(VB_GENERAL, LOG_ERR,
567 "InitializeInput(): Programmer error, no parent.");
568 return false;
569 }
570
572 query.prepare(
573 "SELECT sourceid, inputname, "
574 " startchan, externalcommand, "
575 " tunechan "
576 "FROM capturecard "
577 "WHERE cardid = :INPUTID");
578 query.bindValue(":INPUTID", m_inputId);
579
580 if (!query.exec() || !query.isActive())
581 {
582 MythDB::DBError("ChannelBase::InitializeInput", query);
583 return false;
584 }
585 if (!query.size())
586 {
587 LOG(VB_GENERAL, LOG_ERR, LOC +
588 QString("No capturecard record in database for input %1")
589 .arg(m_inputId));
590 return false;
591 }
592
593 query.next();
594
595 m_sourceId = query.value(0).toUInt();
596 m_name = query.value(1).toString();
597 m_startChanNum = query.value(2).toString();
598 m_externalChanger = query.value(3).toString();
599 m_tuneToChannel = query.value(4).toString();
600
601 if (0 == m_sourceId)
602 {
603 LOG(VB_GENERAL, LOG_ERR, LOC +
604 QString("No video source defined for input %1")
605 .arg(m_inputId));
606 return false;
607 }
608
610 QString order = gCoreContext->GetSetting("ChannelOrdering", "channum");
612
614 !m_externalChanger.isEmpty())
615 {
616 LOG(VB_GENERAL, LOG_WARNING, LOC + "External Channel changer is "
617 "set, but this device does not support it.");
618 m_externalChanger.clear();
619 }
620
621 // print it
622 LOG(VB_CHANNEL, LOG_INFO, LOC +
623 QString("Input #%1: '%2' schan(%3) sourceid(%4)")
625 .arg(m_sourceId));
626
627 return true;
628}
629
634 const QString &oldChanNum,
635 const QString &newChanNum)
636{
637 bool skip = (m_name.isEmpty() ||
638 m_startChanNum.isEmpty() ||
639 m_startChanNum != oldChanNum ||
640 m_sourceId != sourceid);
641 if (!skip)
642 m_startChanNum = newChanNum;
643
644 if (GetSourceID() == sourceid && oldChanNum == m_curChannelName)
645 m_curChannelName = newChanNum;
646
648}
649
654{
656
657 if (m_name.isEmpty() || m_startChanNum.isEmpty())
658 return;
659
660 query.prepare(
661 "UPDATE capturecard "
662 "SET startchan = :STARTCHAN "
663 "WHERE cardid = :CARDINPUTID");
664 query.bindValue(":STARTCHAN", m_startChanNum);
665 query.bindValue(":CARDINPUTID", m_inputId);
666
667 if (!query.exec() || !query.isActive())
668 MythDB::DBError("StoreInputChannels", query);
669}
670
671bool ChannelBase::CheckChannel(const QString &channum) const
672{
674 if (!query.isConnected())
675 return false;
676
677 query.prepare(
678 "SELECT channel.chanid "
679 "FROM channel, capturecard "
680 "WHERE channel.deleted IS NULL AND "
681 " channel.channum = :CHANNUM AND "
682 " channel.sourceid = capturecard.sourceid AND "
683 " capturecard.cardid = :INPUTID AND "
684 " capturecard.hostname = :HOSTNAME");
685 query.bindValue(":CHANNUM", channum);
686 query.bindValue(":INPUTID", m_inputId);
687 query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
688
689 if (!query.exec() || !query.isActive())
690 {
691 MythDB::DBError("checkchannel", query);
692 }
693 else if (query.size() > 0)
694 {
695 return true;
696 }
697
698 LOG(VB_CHANNEL, LOG_ERR, LOC +
699 QString("Failed to find channel(%1) on input (%2).")
700 .arg(channum).arg(m_inputId));
701 return false;
702}
703
705 TVRec *tvrec,
706 const GeneralDBOptions &genOpt,
707 const DVBDBOptions &dvbOpt,
708 [[maybe_unused]] const FireWireDBOptions &fwOpt,
709 const QString &startchannel,
710 bool enter_power_save_mode,
711 QString &rbFileExt,
712 bool setchan)
713{
714 rbFileExt = "ts";
715
716 ChannelBase *channel = nullptr;
717 if (genOpt.m_inputType == "DVB")
718 {
719#if CONFIG_DVB
720 channel = new DVBChannel(genOpt.m_videoDev, tvrec);
721 auto *dvbchannel = dynamic_cast<DVBChannel*>(channel);
722 if (dvbchannel != nullptr)
723 dvbchannel->SetSlowTuning(dvbOpt.m_dvbTuningDelay);
724#endif
725 }
726 else if (genOpt.m_inputType == "FIREWIRE")
727 {
728#if CONFIG_FIREWIRE
729 channel = new FirewireChannel(tvrec, genOpt.m_videoDev, fwOpt);
730#endif
731 }
732#if CONFIG_HDHOMERUN
733 else if (genOpt.m_inputType == "HDHOMERUN")
734 {
735 channel = new HDHRChannel(tvrec, genOpt.m_videoDev);
736 }
737#endif
738#if CONFIG_SATIP
739 else if (genOpt.m_inputType == "SATIP")
740 {
741 channel = new SatIPChannel(tvrec, genOpt.m_videoDev);
742 }
743#endif
744 else if ((genOpt.m_inputType == "IMPORT") ||
745 (genOpt.m_inputType == "DEMO") ||
746 (genOpt.m_inputType == "MPEG" &&
747 genOpt.m_videoDev.startsWith("file:", Qt::CaseInsensitive)))
748 {
749 channel = new DummyChannel(tvrec);
750 rbFileExt = "mpg";
751 }
752#if CONFIG_IPTV || CONFIG_VBOX
753 else if ((genOpt.m_inputType == "FREEBOX") || // IPTV
754 (genOpt.m_inputType == "VBOX"))
755 {
756 channel = new IPTVChannel(tvrec, genOpt.m_videoDev);
757 }
758#endif
759#if CONFIG_ASI
760 else if (genOpt.m_inputType == "ASI")
761 {
762 channel = new ASIChannel(tvrec, genOpt.m_videoDev);
763 }
764#endif
765#if CONFIG_CETON
766 else if (genOpt.m_inputType == "CETON")
767 {
768 channel = new CetonChannel(tvrec, genOpt.m_videoDev);
769 }
770#endif
771 else if (genOpt.m_inputType == "V4L2ENC")
772 {
773#if CONFIG_V4L2
774 channel = new V4LChannel(tvrec, genOpt.m_videoDev);
775#endif
776 if (genOpt.m_inputType == "MPEG")
777 rbFileExt = "mpg";
778 }
779 else if (CardUtil::IsV4L(genOpt.m_inputType))
780 {
781#if CONFIG_V4L2
782 channel = new V4LChannel(tvrec, genOpt.m_videoDev);
783#endif
784 if (genOpt.m_inputType != "HDPVR")
785 {
786 if (genOpt.m_inputType != "MPEG")
787 rbFileExt = "nuv";
788 else
789 rbFileExt = "mpg";
790 }
791 }
792 else if (genOpt.m_inputType == "EXTERNAL")
793 {
794 channel = new ExternalChannel(tvrec, genOpt.m_videoDev);
795 }
796
797 if (!channel)
798 {
799 QString msg = QString(
800 "%1 card configured on video device %2, \n"
801 "but MythTV was not compiled with %3 support. \n"
802 "\n"
803 "Recompile MythTV with %4 support or remove the card \n"
804 "from the configuration and restart MythTV.")
805 .arg(genOpt.m_inputType, genOpt.m_videoDev,
806 genOpt.m_inputType, genOpt.m_inputType);
807 LOG(VB_GENERAL, LOG_ERR, "ChannelBase: CreateChannel() Error: \n" +
808 msg + "\n");
809 return nullptr;
810 }
811
812 if (!channel->Open())
813 {
814 LOG(VB_GENERAL, LOG_ERR, "ChannelBase: CreateChannel() Error: " +
815 QString("Failed to open device %1").arg(genOpt.m_videoDev));
816 delete channel;
817 return nullptr;
818 }
819
820 QString channum = startchannel;
821 channel->Init(channum, setchan);
822
823 if (enter_power_save_mode)
824 {
825 if (channel &&
826 ((genOpt.m_inputType == "DVB" && dvbOpt.m_dvbOnDemand) ||
827 genOpt.m_inputType == "HDHOMERUN" ||
828 genOpt.m_inputType == "EXTERNAL" ||
830 {
831 channel->Close();
832 }
833 else if (setchan)
834 {
835 auto *dtvchannel = dynamic_cast<DTVChannel*>(channel);
836 if (dtvchannel)
837 dtvchannel->EnterPowerSavingMode();
838 }
839 }
840
841 return channel;
842}
843
845{
847 return false;
848
849 if (!m_inputId)
850 {
851 LOG(VB_GENERAL, LOG_ERR, LOC +
852 QString("IsExternalChannelChangeInUse: "
853 "non-existant input"));
854 return false;
855 }
856
857 return !m_externalChanger.isEmpty();
858}
859
861{
863}
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:1639
static uint GetFirstInputID(const QString &videodevice)
Convenience function for GetInputIDs()
Definition: cardutil.h:268
static bool IsV4L(const QString &rawtype)
Definition: cardutil.h:145
static QString GetFirewireChangerNode(uint inputid)
Definition: cardutil.cpp:1622
static std::vector< uint > GetConflictingInputs(uint inputid)
Definition: cardutil.cpp:2241
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 &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:251
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:86
std::chrono::milliseconds m_dvbTuningDelay
Definition: tv_rec.h:87
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:73
QString m_videoDev
Definition: tv_rec.h:70
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
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:902
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
QString GetHostName(void)
QString GetSetting(const QString &key, const QString &defaultval="")
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
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:143
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:32
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
unsigned int uint
Definition: freesurround.h:24
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)