Ticket #6719: channel-thread-0.23-fixes-24052.patch
File channel-thread-0.23-fixes-24052.patch, 54.3 KB (added by , 14 years ago) |
---|
-
libs/libmythtv/analogsignalmonitor.cpp
old new void AnalogSignalMonitor::UpdateValues(v 30 30 31 31 int videofd = channel->GetFd(); 32 32 if (videofd < 0) 33 33 return; 34 34 35 if (!IsChannelTuned()) 36 return; 37 35 38 bool isLocked = false; 36 39 if (usingv4l2) 37 40 { 38 41 struct v4l2_tuner tuner; 39 42 bzero(&tuner, sizeof(tuner)); -
libs/libmythtv/channelbase.cpp
old new using namespace std; 33 33 34 34 #define LOC QString("ChannelBase(%1): ").arg(GetCardID()) 35 35 #define LOC_WARN QString("ChannelBase(%1) Warning: ").arg(GetCardID()) 36 36 #define LOC_ERR QString("ChannelBase(%1) Error: ").arg(GetCardID()) 37 37 38 /* 39 * Run the channel change thread, and report the status when done 40 */ 41 void ChannelThread::run(void) 42 { 43 bool result = tuner->SetChannelByString(channel); 44 tuner->setStatus(result ? 45 ChannelBase::changeSuccess : ChannelBase::changeFailed); 46 } 47 38 48 ChannelBase::ChannelBase(TVRec *parent) 39 49 : 40 50 pParent(parent), curchannelname(""), 41 currentInputID(-1), commfree(false), cardid(0) 51 currentInputID(-1), commfree(false), cardid(0), 52 abort_change(false) 42 53 { 54 tuneStatus = changeUnknown; 55 tuneThread.tuner = this; 43 56 } 44 57 45 58 ChannelBase::~ChannelBase(void) 46 59 { 47 60 ClearInputMap(); 61 TeardownAll(); 62 } 63 64 void ChannelBase::TeardownAll(void) 65 { 66 if (tuneThread.isRunning()) 67 { 68 thread_lock.lock(); 69 abort_change = true; 70 tuneCond.wakeAll(); 71 thread_lock.unlock(); 72 tuneThread.wait(); 73 } 74 } 75 76 void ChannelBase::SelectChannel(const QString & chan) 77 { 78 VERBOSE(VB_CHANNEL, LOC + "SelectChannel " + chan); 79 TeardownAll(); 80 81 thread_lock.lock(); 82 abort_change = false; 83 tuneStatus = changePending; 84 thread_lock.unlock(); 85 86 curchannelname = tuneThread.channel = chan; 87 tuneThread.start(); 88 } 89 90 /* 91 * Returns true of the channel change thread should abort 92 */ 93 bool ChannelBase::Aborted(void) 94 { 95 bool result; 96 97 thread_lock.lock(); 98 result = abort_change; 99 thread_lock.unlock(); 100 101 return result; 102 } 103 104 ChannelBase::Status ChannelBase::GetStatus(void) 105 { 106 Status status; 107 108 thread_lock.lock(); 109 status = tuneStatus; 110 thread_lock.unlock(); 111 112 return status; 113 } 114 115 ChannelBase::Status ChannelBase::Wait(void) 116 { 117 tuneThread.wait(); 118 return tuneStatus; 119 } 120 121 void ChannelBase::setStatus(ChannelBase::Status status) 122 { 123 thread_lock.lock(); 124 tuneStatus = status; 125 thread_lock.unlock(); 48 126 } 49 127 50 128 bool ChannelBase::Init(QString &inputname, QString &startchannel, bool setchan) 51 129 { 52 130 bool ok; 53 131 132 VERBOSE(VB_CHANNEL, LOC + QString("Init(%1, %2, %3)") 133 .arg(inputname).arg(startchannel).arg(setchan)); 134 54 135 if (!setchan) 55 136 ok = inputname.isEmpty() ? false : IsTunable(inputname, startchannel); 56 137 else if (inputname.isEmpty()) 57 ok = SetChannelByString(startchannel); 138 { 139 SelectChannel(startchannel); 140 ok = Wait(); 141 } 58 142 else 59 143 ok = SwitchToInput(inputname, startchannel); 60 144 61 145 if (ok) 62 146 return true; … … bool ChannelBase::Init(QString &inputnam 123 207 find(channels.begin(), channels.end(), chanid); 124 208 125 209 if (chanid && cit != channels.end()) 126 210 { 127 211 if (!setchan) 128 {129 212 ok = IsTunable(*it, (mplexid_restriction) ? 130 213 (*cit).channum : startchannel); 131 }132 214 else 133 215 ok = SwitchToInput(*it, (*cit).channum); 134 216 135 217 if (ok) 136 218 { … … int ChannelBase::GetInputByName(const QS 328 410 return (int)it.key(); 329 411 } 330 412 return -1; 331 413 } 332 414 415 #if 0 // Not used? 333 416 bool ChannelBase::SwitchToInput(const QString &inputname) 334 417 { 335 418 int input = GetInputByName(inputname); 336 419 337 420 if (input >= 0) … … bool ChannelBase::SwitchToInput(const QS 339 422 else 340 423 VERBOSE(VB_IMPORTANT, QString("ChannelBase: Could not find input: " 341 424 "%1 on card\n").arg(inputname)); 342 425 return false; 343 426 } 427 #endif 428 429 bool ChannelBase::SelectInput(const QString &inputname, const QString &chan) 430 { 431 int input = GetInputByName(inputname); 432 433 VERBOSE(VB_CHANNEL, LOC + QString("SelectInput(%1, %2) %3") 434 .arg(inputname).arg(chan).arg(input)); 435 436 if (input >= 0) 437 { 438 if (!SwitchToInput(input, false)) 439 return false; 440 SelectChannel(chan); 441 } 442 else 443 { 444 VERBOSE(VB_IMPORTANT, 445 QString("ChannelBase: Could not find input: %1 on card when " 446 "setting channel %2\n").arg(inputname).arg(chan)); 447 return false; 448 } 449 450 return true; 451 } 344 452 345 453 bool ChannelBase::SwitchToInput(const QString &inputname, const QString &chan) 346 454 { 347 455 int input = GetInputByName(inputname); 348 456 349 bool ok = false; 457 VERBOSE(VB_CHANNEL, LOC + QString("SwitchToInput(%1, %2), %3") 458 .arg(inputname).arg(chan).arg(input)); 459 350 460 if (input >= 0) 351 461 { 352 ok = SwitchToInput(input, false);353 if (ok)354 ok =SetChannelByString(chan);462 if (!SwitchToInput(input, false)) 463 return false; 464 return SetChannelByString(chan); 355 465 } 356 466 else 357 467 { 358 468 VERBOSE(VB_IMPORTANT, 359 469 QString("ChannelBase: Could not find input: %1 on card when " 360 470 "setting channel %2\n").arg(inputname).arg(chan)); 471 return false; 361 472 } 362 return ok; 473 474 return true; 363 475 } 364 476 365 477 bool ChannelBase::SwitchToInput(int newInputNum, bool setstarting) 366 478 { 479 VERBOSE(VB_CHANNEL, LOC + QString("SwitchToInput(%1, %2)") 480 .arg(newInputNum).arg(setstarting)); 481 367 482 InputMap::const_iterator it = inputs.find(newInputNum); 368 483 if (it == inputs.end() || (*it)->startChanNum.isEmpty()) 369 484 return false; 370 485 371 486 uint mplexid_restriction; … … bool ChannelBase::SwitchToInput(int newI 373 488 return false; 374 489 375 490 // input switching code would go here 376 491 377 492 if (setstarting) 378 return SetChannelByString((*it)->startChanNum);493 SelectChannel((*it)->startChanNum); 379 494 380 495 return true; 381 496 } 382 497 383 498 static bool is_input_group_busy( … … static bool is_input_busy( 484 599 busygrp, busyrec, busyin, mplexid_restriction); 485 600 } 486 601 return is_busy; 487 602 } 488 603 489 bool ChannelBase::IsInputAvailable( 490 int inputid, uint &mplexid_restriction) const 604 bool ChannelBase::IsInputAvailable(int inputid, uint &mplexid_restriction) const 491 605 { 492 606 if (inputid < 0) 493 607 return false; 494 608 495 609 // Check each input to make sure it doesn't belong to an … … bool ChannelBase::ChangeExternalChannel( 650 764 VERBOSE(VB_IMPORTANT, msg); 651 765 _exit(CHANNEL__EXIT__EXECL_ERROR); // this exit is ok 652 766 } 653 767 else 654 768 { // child contains the pid of the new process 655 int status = 0, pid = 0; 769 QMutex lock; 770 int status = 0, pid = 0; 771 656 772 VERBOSE(VB_CHANNEL, "Waiting for External Tuning program to exit"); 657 773 658 774 bool timed_out = false; 659 775 uint timeout = 30; // how long to wait in seconds 660 776 time_t start_time = time(0); 661 while (-1 != pid && !timed_out )777 while (-1 != pid && !timed_out && !Aborted()) 662 778 { 663 sleep(1); 779 lock.lock(); 780 tuneCond.wait(&lock, 500); // sleep up to 0.5 seconds 664 781 pid = waitpid(child, &status, WUNTRACED|WNOHANG); 665 782 VERBOSE(VB_IMPORTANT, QString("ret_pid(%1) child(%2) status(0x%3)") 666 783 .arg(pid).arg(child).arg(status,0,16)); 667 784 if (pid==child) 785 { 786 lock.unlock(); 668 787 break; 788 } 669 789 else if (time(0) > (time_t)(start_time + timeout)) 670 790 timed_out = true; 791 lock.unlock(); 671 792 } 672 if (timed_out) 793 794 if (timed_out || Aborted()) 673 795 { 674 VERBOSE(VB_IMPORTANT, "External Tuning program timed out, killing"); 796 if (Aborted()) 797 VERBOSE(VB_IMPORTANT, "Aborting External Tuning program"); 798 else 799 VERBOSE(VB_IMPORTANT, "External Tuning program timed out, " 800 "killing"); 675 801 kill(child, SIGTERM); 676 802 usleep(500); 677 803 kill(child, SIGKILL); 678 804 return false; 679 805 } -
libs/libmythtv/channelbase.h
old new 3 3 #ifndef CHANNELBASE_H 4 4 #define CHANNELBASE_H 5 5 6 6 // Qt headers 7 7 #include <QStringList> 8 #include <qwaitcondition.h> 9 #include <qmutex.h> 10 #include <qthread.h> 8 11 9 12 // MythTV headers 10 13 #include "channelutil.h" 11 14 #include "inputinfo.h" 12 15 #include "tv.h" 13 16 14 17 class TVRec; 18 class ChannelBase; 19 20 /* 21 * Thread to run tunning process in 22 */ 23 class ChannelThread : public QThread 24 { 25 public: 26 virtual void run(void); 27 28 QString channel; 29 ChannelBase *tuner; 30 }; 15 31 16 32 /** \class ChannelBase 17 33 * \brief Abstract class providing a generic interface to tuning hardware. 18 34 * 19 35 * This class abstracts channel implementations for analog TV, ATSC, DVB, etc. … … class TVRec; 21 37 * It is responsible for tuning, i.e. switching channels. 22 38 */ 23 39 24 40 class ChannelBase 25 41 { 26 public: 42 friend class ChannelThread; 43 44 public: 45 enum Status { changeUnknown = 'U', changePending = 'P', 46 changeFailed = 'F', changeSuccess = 'S' }; 47 27 48 ChannelBase(TVRec *parent); 28 virtual ~ChannelBase( );49 virtual ~ChannelBase(void); 29 50 30 51 virtual bool Init(QString &inputname, QString &startchannel, bool setchan); 31 52 virtual bool IsTunable(const QString &input, const QString &channum) const; 32 53 54 virtual void SelectChannel(const QString & chan); 55 56 Status GetStatus(void); 57 Status Wait(void); 58 33 59 // Methods that must be implemented. 34 60 /// \brief Opens the channel changing hardware for use. 35 61 virtual bool Open(void) = 0; 36 62 /// \brief Closes the channel changing hardware to use. 37 63 virtual void Close(void) = 0; 38 virtual bool SetChannelByString(const QString &chan) = 0;39 64 /// \brief Reports whether channel is already open 40 65 virtual bool IsOpen(void) const = 0; 41 66 42 67 // Methods that one might want to specialize 43 68 /// \brief Sets file descriptor. … … class ChannelBase 80 105 // Sets 81 106 virtual void Renumber(uint srcid, const QString &oldChanNum, 82 107 const QString &newChanNum); 83 108 84 109 // Input toggling convenience methods 85 virtual bool SwitchToInput(const QString &input); 86 virtual bool S witchToInput(const QString &input, const QString &chan);110 // virtual bool SwitchToInput(const QString &input); // not used? 111 virtual bool SelectInput(const QString &input, const QString &chan); 87 112 88 113 virtual bool InitializeInputs(void); 89 114 90 115 // Misc. Commands 91 116 virtual bool Retune(void) { return false; } … … class ChannelBase 106 131 // \brief Set cardid for scanning 107 132 void SetCardID(uint _cardid) { cardid = _cardid; } 108 133 109 134 virtual int GetCardID(void) const; 110 135 protected: 136 virtual bool SetChannelByString(const QString &chan) = 0; 137 111 138 /// \brief Switches to another input on hardware, 112 139 /// and sets the channel is setstarting is true. 140 virtual bool SwitchToInput(const QString &input, const QString &chan); 113 141 virtual bool SwitchToInput(int inputNum, bool setstarting); 114 142 virtual bool IsInputAvailable( 115 143 int inputNum, uint &mplexid_restriction) const; 116 144 117 145 virtual bool ChangeExternalChannel(const QString &newchan); 118 146 static void StoreInputChannels(const InputMap&); 119 147 static void StoreDefaultInput(uint cardid, const QString &input); 120 148 void ClearInputMap(void); 121 149 150 bool Aborted(); 151 void setStatus(Status status); 152 void TeardownAll(void); 153 122 154 TVRec *pParent; 123 155 QString curchannelname; 124 156 int currentInputID; 125 157 bool commfree; 126 158 uint cardid; 127 159 InputMap inputs; 128 160 DBChanList allchannels; ///< channels across all inputs 161 162 QWaitCondition tuneCond; 163 164 private: 165 mutable ChannelThread tuneThread; 166 Status tuneStatus; 167 QMutex thread_lock; 168 bool abort_change; 129 169 }; 130 170 131 171 #endif 132 172 -
new file libs/libmythtv/channelchangemonitor.cpp
- + 1 // -*- Mode: c++ -*- 2 3 #include <cerrno> 4 #include <unistd.h> 5 #include <sys/ioctl.h> 6 7 #include "videodev_myth.h" 8 #include "mythcontext.h" 9 #include "channelchangemonitor.h" 10 #include "v4lchannel.h" 11 12 #define LOC QString("ChannelChangeM: ").arg(channel->GetDevice()) 13 #define LOC_ERR QString("ChannelChangeM, Error: ").arg(channel->GetDevice()) 14 15 ChannelChangeMonitor::ChannelChangeMonitor( 16 int db_cardnum, V4LChannel *_channel, uint64_t _flags) : 17 SignalMonitor(db_cardnum, _channel, _flags) 18 { 19 } 20 21 void ChannelChangeMonitor::UpdateValues(void) 22 { 23 if (!running || exit) 24 return; 25 26 if (!IsChannelTuned()) 27 return; 28 29 { 30 QMutexLocker locker(&statusLock); 31 signalLock.SetValue(true); 32 signalStrength.SetValue(100); 33 } 34 35 EmitStatus(); 36 SendMessageAllGood(); 37 } 38 -
new file libs/libmythtv/channelchangemonitor.h
- + 1 // -*- Mode: c++ -*- 2 // Copyright (c) 2005, Daniel Thor Kristjansson 3 4 #ifndef _CHANNEL_CHANGE_MONITOR_H_ 5 #define _CHANNEL_CHANGE_MONITOR_H_ 6 7 // MythTV headers 8 #include "signalmonitor.h" 9 10 class V4LChannel; 11 12 class ChannelChangeMonitor : public SignalMonitor 13 { 14 public: 15 ChannelChangeMonitor( 16 int db_cardnum, V4LChannel *_channel, 17 uint64_t _flags = kSigMon_WaitForSig); 18 19 virtual void UpdateValues(void); 20 }; 21 22 #endif // _CHANNEL_CHANGE_MONITOR_H_ -
libs/libmythtv/channelscan/channelscan_sm.cpp
old new void ChannelScanSM::ScanTransport(const 1624 1624 GetDTVSignalMonitor()->GetScanStreamData()->Reset(); 1625 1625 GetDTVSignalMonitor()->SetChannel(-1,-1); 1626 1626 } 1627 1627 1628 1628 // Start signal monitor for this channel 1629 signalMonitor->Start( );1629 signalMonitor->Start(false); 1630 1630 1631 1631 timer.start(); 1632 1632 waitingForTables = (item.tuning.sistandard != "analog"); 1633 1633 } 1634 1634 -
libs/libmythtv/channelscan/channelscan_sm.h
old new class AnalogSignalHandler : public Signa 71 71 AnalogSignalHandler(ChannelScanSM *_siscan) : siscan(_siscan) { } 72 72 73 73 public slots: 74 74 virtual inline void AllGood(void); 75 75 virtual void StatusSignalLock(const SignalMonitorValue&) { } 76 virtual void StatusChannelTuned(const SignalMonitorValue&) { } 76 77 virtual void StatusSignalStrength(const SignalMonitorValue&) { } 77 78 78 79 private: 79 80 ChannelScanSM *siscan; 80 81 }; -
libs/libmythtv/channelscan/scanmonitor.cpp
old new QEvent::Type ScannerEvent::SetStatusSign 53 53 (QEvent::Type) QEvent::registerEventType(); 54 54 QEvent::Type ScannerEvent::SetStatusSignalStrength = 55 55 (QEvent::Type) QEvent::registerEventType(); 56 56 QEvent::Type ScannerEvent::SetStatusSignalLock = 57 57 (QEvent::Type) QEvent::registerEventType(); 58 QEvent::Type ScannerEvent::SetStatusChannelTuned = 59 (QEvent::Type) QEvent::registerEventType(); 58 60 59 61 /// Percentage to set to after the transports have been scanned 60 62 #define TRANSPORT_PCT 6 61 63 /// Percentage to set to after the first tune 62 64 #define TUNED_PCT 3 … … void ScanMonitor::StatusRotorPosition(co 131 133 void ScanMonitor::StatusSignalLock(const SignalMonitorValue &val) 132 134 { 133 135 post_event(this, ScannerEvent::SetStatusSignalLock, val.GetValue()); 134 136 } 135 137 138 void ScanMonitor::StatusChannelTuned(const SignalMonitorValue &val) 139 { 140 post_event(this, ScannerEvent::SetStatusChannelTuned, val.GetValue()); 141 } 142 136 143 void ScanMonitor::StatusSignalToNoise(const SignalMonitorValue &val) 137 144 { 138 145 post_event(this, ScannerEvent::SetStatusSignalToNoise, 139 146 val.GetNormalizedValue(0, 65535)); 140 147 } -
libs/libmythtv/channelscan/scanmonitor.h
old new class ScanMonitor : 63 63 void ScanComplete(void); 64 64 65 65 // SignalMonitorListener 66 66 virtual void AllGood(void) { } 67 67 virtual void StatusSignalLock(const SignalMonitorValue&); 68 virtual void StatusChannelTuned(const SignalMonitorValue&); 68 69 virtual void StatusSignalStrength(const SignalMonitorValue&); 69 70 70 71 // DVBSignalMonitorListener 71 72 virtual void StatusSignalToNoise(const SignalMonitorValue&); 72 73 virtual void StatusBitErrorRate(const SignalMonitorValue&) { } … … class ScannerEvent : public QEvent 108 109 static Type SetPercentComplete; 109 110 static Type SetStatusRotorPosition; 110 111 static Type SetStatusSignalToNoise; 111 112 static Type SetStatusSignalStrength; 112 113 static Type SetStatusSignalLock; 114 static Type SetStatusChannelTuned; 113 115 114 116 private: 115 117 ~ScannerEvent() { } 116 118 117 119 private: -
libs/libmythtv/dtvsignalmonitor.cpp
old new 23 23 DTVSignalMonitor::DTVSignalMonitor(int db_cardnum, 24 24 DTVChannel *_channel, 25 25 uint64_t wait_for_mask) 26 26 : SignalMonitor(db_cardnum, _channel, wait_for_mask), 27 27 stream_data(NULL), 28 channelTuned(QObject::tr("Channel Tuned"), "tuned", 3, true, 0, 3, 0), 28 29 seenPAT(QObject::tr("Seen")+" PAT", "seen_pat", 1, true, 0, 1, 0), 29 30 seenPMT(QObject::tr("Seen")+" PMT", "seen_pmt", 1, true, 0, 1, 0), 30 31 seenMGT(QObject::tr("Seen")+" MGT", "seen_mgt", 1, true, 0, 1, 0), 31 32 seenVCT(QObject::tr("Seen")+" VCT", "seen_vct", 1, true, 0, 1, 0), 32 33 seenNIT(QObject::tr("Seen")+" NIT", "seen_nit", 1, true, 0, 1, 0), … … DTVChannel *DTVSignalMonitor::GetDTVChan 61 62 62 63 QStringList DTVSignalMonitor::GetStatusList(bool kick) 63 64 { 64 65 QStringList list = SignalMonitor::GetStatusList(kick); 65 66 QMutexLocker locker(&statusLock); 67 68 // tuned? 69 if (flags & kSigMon_Tuned) 70 { 71 list<<channelTuned.GetName()<<channelTuned.GetStatus(); 72 } 73 66 74 // mpeg tables 67 75 if (flags & kDTVSigMon_WaitForPAT) 68 76 { 69 77 list<<seenPAT.GetName()<<seenPAT.GetStatus(); 70 78 list<<matchingPAT.GetName()<<matchingPAT.GetStatus(); … … void DTVSignalMonitor::RemoveFlags(uint6 136 144 } 137 145 138 146 void DTVSignalMonitor::UpdateMonitorValues(void) 139 147 { 140 148 QMutexLocker locker(&statusLock); 149 channelTuned.SetValue((flags & kSigMon_Tuned) ? 3 : 1); 141 150 seenPAT.SetValue( (flags & kDTVSigMon_PATSeen) ? 1 : 0); 142 151 seenPMT.SetValue( (flags & kDTVSigMon_PMTSeen) ? 1 : 0); 143 152 seenMGT.SetValue( (flags & kDTVSigMon_MGTSeen) ? 1 : 0); 144 153 seenVCT.SetValue( (flags & kDTVSigMon_VCTSeen) ? 1 : 0); 145 154 seenNIT.SetValue( (flags & kDTVSigMon_NITSeen) ? 1 : 0); -
libs/libmythtv/dtvsignalmonitor.h
old new class DTVSignalMonitor : public SignalMo 109 109 void UpdateListeningForEIT(void); 110 110 111 111 protected: 112 112 MPEGStreamData *stream_data; 113 113 vector<uint> eit_pids; 114 SignalMonitorValue channelTuned; 114 115 SignalMonitorValue seenPAT; 115 116 SignalMonitorValue seenPMT; 116 117 SignalMonitorValue seenMGT; 117 118 SignalMonitorValue seenVCT; 118 119 SignalMonitorValue seenNIT; -
libs/libmythtv/dvbsignalmonitor.cpp
old new void DVBSignalMonitor::UpdateValues(void 228 228 229 229 update_done = true; 230 230 return; 231 231 } 232 232 233 if (!IsChannelTuned()) 234 return; 235 233 236 AddFlags(kSigMon_WaitForSig); 234 237 235 238 DVBChannel *dvbchannel = GetDVBChannel(); 236 239 if (!dvbchannel) 237 240 return; -
libs/libmythtv/firewiresignalmonitor.cpp
old new void FirewireSignalMonitor::AddData(cons 188 188 void FirewireSignalMonitor::UpdateValues(void) 189 189 { 190 190 if (!running || exit) 191 191 return; 192 192 193 if (!IsChannelTuned()) 194 return; 195 193 196 if (dtvMonitorRunning) 194 197 { 195 198 EmitStatus(); 196 199 if (IsAllGood()) 197 200 SendMessageAllGood(); -
libs/libmythtv/hdhrchannel.cpp
old new bool HDHRChannel::SetChannelByString(con 141 141 142 142 uint mplexid_restriction; 143 143 if (!IsInputAvailable(currentInputID, mplexid_restriction)) 144 144 return false; 145 145 146 if (Aborted()) 147 return false; 148 146 149 // Fetch tuning data from the database. 147 150 QString tvformat, modulation, freqtable, freqid, si_std; 148 151 int finetune; 149 152 uint64_t frequency; 150 153 int mpeg_prog_num; -
libs/libmythtv/hdhrsignalmonitor.cpp
old new void HDHRSignalMonitor::UpdateValues(voi 103 103 104 104 update_done = true; 105 105 return; 106 106 } 107 107 108 if (!IsChannelTuned()) 109 return; 110 108 111 struct hdhomerun_tuner_status_t status; 109 112 streamHandler->GetTunerStatus(&status); 110 113 111 114 uint sig = status.signal_strength; 112 115 uint snq = status.signal_to_noise_quality; -
libs/libmythtv/iptvsignalmonitor.cpp
old new void IPTVSignalMonitor::AddData( 117 117 void IPTVSignalMonitor::UpdateValues(void) 118 118 { 119 119 if (!running || exit) 120 120 return; 121 121 122 if (!IsChannelTuned()) 123 return; 124 122 125 if (dtvMonitorRunning) 123 126 { 124 127 EmitStatus(); 125 128 if (IsAllGood()) 126 129 SendMessageAllGood(); -
libs/libmythtv/libmythtv.pro
old new using_backend { 443 443 SOURCES += audioinputoss.cpp 444 444 DEFINES += USING_OSS 445 445 LIBS += $$OSS_LIBS 446 446 } 447 447 448 HEADERS += channelchangemonitor.h 449 SOURCES += channelchangemonitor.cpp 450 448 451 # Support for Video4Linux devices 449 452 using_v4l { 450 453 HEADERS += v4lchannel.h analogsignalmonitor.h 451 454 SOURCES += v4lchannel.cpp analogsignalmonitor.cpp 452 455 -
libs/libmythtv/signalmonitor.cpp
old new 6 6 #include <signal.h> 7 7 #include <unistd.h> 8 8 9 9 // MythTV headers 10 10 #include "mythcontext.h" 11 #include "tv_rec.h" 11 12 #include "signalmonitor.h" 12 13 #include "compat.h" 13 14 #include "mythverbose.h" 14 15 15 16 extern "C" { … … extern "C" { 40 41 #ifdef USING_FIREWIRE 41 42 # include "firewiresignalmonitor.h" 42 43 # include "firewirechannel.h" 43 44 #endif 44 45 46 #include "channelchangemonitor.h" 47 45 48 #undef DBG_SM 46 49 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 47 50 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); 48 51 49 52 /** \class SignalMonitor … … SignalMonitor *SignalMonitor::Init(QStri 91 94 signalMonitor = new DVBSignalMonitor(db_cardnum, dvbc); 92 95 } 93 96 #endif 94 97 95 98 #ifdef USING_V4L 99 #if 0 // Just use ChannelChangeMonitor for these types 96 100 if ((cardtype.toUpper() == "V4L") || 97 (cardtype.toUpper() == "MPEG") || 98 (cardtype.toUpper() == "HDPVR")) 101 (cardtype.toUpper() == "MPEG")) 99 102 { 100 103 V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 101 104 if (chan) 102 105 signalMonitor = new AnalogSignalMonitor(db_cardnum, chan); 103 106 } 104 107 #endif 108 #endif 105 109 106 110 #ifdef USING_HDHOMERUN 107 111 if (cardtype.toUpper() == "HDHOMERUN") 108 112 { 109 113 HDHRChannel *hdhrc = dynamic_cast<HDHRChannel*>(channel); … … SignalMonitor *SignalMonitor::Init(QStri 130 134 } 131 135 #endif 132 136 133 137 if (!signalMonitor) 134 138 { 139 V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 140 if (chan) 141 signalMonitor = new ChannelChangeMonitor(db_cardnum, chan); 142 } 143 144 if (!signalMonitor) 145 { 135 146 VERBOSE(VB_IMPORTANT, 136 147 QString("Failed to create signal monitor in Init(%1, %2, 0x%3)") 137 148 .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16)); 138 149 } 139 150 … … SignalMonitor::SignalMonitor(int _captur 158 169 : channel(_channel), 159 170 capturecardnum(_capturecardnum), flags(wait_for_mask), 160 171 update_rate(25), minimum_update_rate(5), 161 172 running(false), exit(false), 162 173 update_done(false), notify_frontend(true), 163 error(""), 174 is_tuned(false), tablemon(false), 175 eit_scan(false), error(""), 164 176 signalLock (QObject::tr("Signal Lock"), "slock", 165 177 1, true, 0, 1, 0), 166 178 signalStrength(QObject::tr("Signal Power"), "signal", 167 179 0, true, 0, 100, 0), 180 channelTuned("Channel Tuned", "tuned", 3, true, 0, 3, 0), 168 181 statusLock(QMutex::Recursive) 169 182 { 170 183 } 171 184 172 185 /** \fn SignalMonitor::~SignalMonitor() … … bool SignalMonitor::HasAnyFlag(uint64_t 200 213 } 201 214 202 215 /** \fn SignalMonitor::Start() 203 216 * \brief Start signal monitoring thread. 204 217 */ 205 void SignalMonitor::Start( )218 void SignalMonitor::Start(bool waitfor_tune) 206 219 { 207 220 DBG_SM("Start", "begin"); 208 221 { 209 222 QMutexLocker locker(&startStopLock); 223 224 // When used for scanning, don't wait for the tuning thread 225 is_tuned = !waitfor_tune; 226 210 227 if (!running) 211 228 { 212 229 int rval = pthread_create( 213 230 &monitor_thread, NULL, SpawnMonitorLoop, this); 214 231 … … QStringList SignalMonitor::GetStatusList 277 294 else if (!running) 278 295 UpdateValues(); 279 296 280 297 QStringList list; 281 298 statusLock.lock(); 299 list<<channelTuned.GetName()<<channelTuned.GetStatus(); 282 300 list<<signalLock.GetName()<<signalLock.GetStatus(); 283 301 if (HasFlags(kSigMon_WaitForSig)) 284 302 list<<signalStrength.GetName()<<signalStrength.GetStatus(); 285 303 statusLock.unlock(); 286 304 … … void SignalMonitor::MonitorLoop() 304 322 if (notify_frontend && capturecardnum>=0) 305 323 { 306 324 QStringList slist = GetStatusList(false); 307 325 MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist); 308 326 gContext->dispatch(me); 309 //cerr<<"sent SIGNAL"<<endl;310 327 } 311 328 312 329 usleep(update_rate * 1000); 313 330 } 314 331 … … void SignalMonitor::SendMessage( 439 456 listener->AllGood(); 440 457 break; 441 458 case kStatusSignalStrength: 442 459 listener->StatusSignalStrength(val); 443 460 break; 461 case kStatusChannelTuned: 462 listener->StatusChannelTuned(val); 463 break; 444 464 case kStatusSignalToNoise: 445 465 if (dvblistener) 446 466 dvblistener->StatusSignalToNoise(val); 447 467 break; 448 468 case kStatusBitErrorRate: … … void SignalMonitor::SendMessage( 459 479 break; 460 480 } 461 481 } 462 482 } 463 483 484 bool SignalMonitor::IsChannelTuned(void) 485 { 486 if (is_tuned) 487 return true; 488 489 ChannelBase::Status status = channel->GetStatus(); 490 QMutexLocker locker(&statusLock); 491 492 switch (status) { 493 case ChannelBase::changePending: 494 channelTuned.SetValue(1); 495 break; 496 case ChannelBase::changeFailed: 497 channelTuned.SetValue(2); 498 break; 499 case ChannelBase::changeSuccess: 500 channelTuned.SetValue(3); 501 break; 502 } 503 504 EmitStatus(); 505 506 if (status == ChannelBase::changeSuccess) 507 { 508 if (tablemon) 509 pParent->SetupDTVSignalMonitor(eit_scan); 510 511 is_tuned = true; 512 return true; 513 } 514 515 return false; 516 } 517 464 518 void SignalMonitor::SendMessageAllGood(void) 465 519 { 466 520 QMutexLocker locker(&listenerLock); 467 521 for (uint i = 0; i < listeners.size(); i++) 468 522 listeners[i]->AllGood(); 469 523 } 470 524 471 525 void SignalMonitor::EmitStatus(void) 472 526 { 527 SendMessage(kStatusChannelTuned, channelTuned); 473 528 SendMessage(kStatusSignalLock, signalLock); 474 529 if (HasFlags(kSigMon_WaitForSig)) 475 530 SendMessage(kStatusSignalStrength, signalStrength); 476 531 } -
libs/libmythtv/signalmonitor.h
old new using namespace std; 24 24 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 25 25 "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); 26 26 27 27 inline QString sm_flags_to_string(uint64_t); 28 28 29 class TVRec; 30 29 31 class SignalMonitor 30 32 { 31 33 public: 32 34 /// Returns true iff the card type supports signal monitoring. 33 35 static inline bool IsRequired(const QString &cardtype); … … class SignalMonitor 37 39 virtual ~SignalMonitor(); 38 40 39 41 // // // // // // // // // // // // // // // // // // // // // // // // 40 42 // Control // // // // // // // // // // // // // // // // // // // // 41 43 42 virtual void Start( );44 virtual void Start(bool waitfor_tune); 43 45 virtual void Stop(); 44 46 virtual void Kick(); 45 47 virtual bool WaitForLock(int timeout = -1); 46 48 47 49 // // // // // // // // // // // // // // // // // // // // // // // // … … class SignalMonitor 81 83 * \param notify if true SIGNAL MythEvents are sent to the frontend, 82 84 * otherwise they are not. 83 85 */ 84 86 void SetNotifyFrontend(bool notify) { notify_frontend = notify; } 85 87 88 /** \brief Indicate if table monitoring is needed 89 * \param monitor if true parent->SetupDTVSignalMonitor is called 90 * after the channel is tuned. 91 */ 92 void SetMonitoring(TVRec * parent, bool EITscan, bool monitor) 93 { pParent = parent; eit_scan = EITscan, tablemon = monitor; } 94 86 95 /** \brief Sets the number of milliseconds between signal monitoring 87 96 * attempts in the signal monitoring thread. 88 97 * 89 98 * Defaults to 25 milliseconds. 90 99 * \param msec Milliseconds between signal monitoring events. … … class SignalMonitor 106 115 uint64_t wait_for_mask); 107 116 108 117 static void* SpawnMonitorLoop(void*); 109 118 virtual void MonitorLoop(); 110 119 120 bool IsChannelTuned(void); 121 111 122 /// \brief This should be overridden to actually do signal monitoring. 112 123 virtual void UpdateValues() { ; } 113 124 114 125 public: 115 126 /// We've seen a PAT, … … class SignalMonitor 137 148 /// We've seen the FireWire STB power state 138 149 static const uint64_t kFWSigMon_PowerSeen = 0x0000000100ULL; 139 150 /// We've seen something indicating whether the data stream is encrypted 140 151 static const uint64_t kDTVSigMon_CryptSeen = 0x0000000200ULL; 141 152 153 static const uint64_t kSigMon_Tuned = 0x0000000400ULL; 154 142 155 /// We've seen a PAT matching our requirements 143 156 static const uint64_t kDTVSigMon_PATMatch = 0x0000001000ULL; 144 157 /// We've seen a PMT matching our requirements 145 158 static const uint64_t kDTVSigMon_PMTMatch = 0x0000002000ULL; 146 159 /// We've seen an MGT matching our requirements … … class SignalMonitor 182 195 static const uint64_t kDVBSigMon_WaitForPos = 0x8000000000ULL; 183 196 184 197 protected: 185 198 pthread_t monitor_thread; 186 199 ChannelBase *channel; 200 TVRec *pParent; 187 201 int capturecardnum; 188 202 uint64_t flags; 189 203 int update_rate; 190 204 uint minimum_update_rate; 191 205 bool running; 192 206 bool exit; 193 207 bool update_done; 194 208 bool notify_frontend; 209 bool is_tuned; 210 bool tablemon; 211 bool eit_scan; 195 212 QString error; 196 213 197 214 SignalMonitorValue signalLock; 198 215 SignalMonitorValue signalStrength; 216 SignalMonitorValue channelTuned; 199 217 200 218 vector<SignalMonitorListener*> listeners; 201 219 202 220 QMutex startStopLock; 203 221 mutable QMutex statusLock; -
libs/libmythtv/signalmonitorlistener.h
old new 7 7 #include "mythexp.h" 8 8 #include "signalmonitorvalue.h" 9 9 10 10 typedef enum { 11 11 kAllGood, 12 kStatusChannelTuned, 12 13 kStatusSignalLock, 13 14 kStatusSignalStrength, 14 15 kStatusSignalToNoise, 15 16 kStatusBitErrorRate, 16 17 kStatusUncorrectedBlocks, … … class MPUBLIC SignalMonitorListener 28 29 * Note: Signals are only sent once the monitoring thread 29 30 * has been started. 30 31 */ 31 32 virtual void AllGood(void) = 0; 32 33 34 /** \brief Signal to be sent with change change status. 35 * 36 * Note: Signals are only sent once the monitoring thread 37 * has been started. 38 */ 39 virtual void StatusChannelTuned(const SignalMonitorValue&) = 0; 40 33 41 /** \brief Signal to be sent as true when it is safe to begin 34 42 * or continue recording, and false if it may not be safe. 35 43 * 36 44 * Note: Signals are only sent once the monitoring thread 37 45 * has been started. -
libs/libmythtv/tv_play.cpp
old new void TV::UpdateOSDSignal(const PlayerCon 7446 7446 7447 7447 uint sig = 0; 7448 7448 float snr = 0.0f; 7449 7449 uint ber = 0xffffffff; 7450 7450 int pos = -1; 7451 int tuned = -1; 7451 7452 QString pat(""), pmt(""), mgt(""), vct(""), nit(""), sdt(""), crypt(""); 7452 7453 QString err = QString::null, msg = QString::null; 7453 7454 for (it = slist.begin(); it != slist.end(); ++it) 7454 7455 { 7455 7456 if ("error" == it->GetShortName()) … … void TV::UpdateOSDSignal(const PlayerCon 7472 7473 snr = it->GetValue(); 7473 7474 else if ("ber" == it->GetShortName()) 7474 7475 ber = it->GetValue(); 7475 7476 else if ("pos" == it->GetShortName()) 7476 7477 pos = it->GetValue(); 7478 else if ("tuned" == it->GetShortName()) 7479 tuned = it->GetValue(); 7477 7480 else if ("seen_pat" == it->GetShortName()) 7478 7481 pat = it->IsGood() ? "a" : "_"; 7479 7482 else if ("matching_pat" == it->GetShortName()) 7480 7483 pat = it->IsGood() ? "A" : pat; 7481 7484 else if ("seen_pmt" == it->GetShortName()) … … void TV::UpdateOSDSignal(const PlayerCon 7505 7508 } 7506 7509 if (sig) 7507 7510 infoMap["signal"] = QString::number(sig); // use normalized value 7508 7511 7509 7512 bool allGood = SignalMonitorValue::AllGood(slist); 7513 char tuneCode; 7510 7514 QString slock = ("1" == infoMap["slock"]) ? "L" : "l"; 7511 7515 QString lockMsg = (slock=="L") ? tr("Partial Lock") : tr("No Lock"); 7512 7516 QString sigMsg = allGood ? tr("Lock") : lockMsg; 7513 7517 7514 7518 QString sigDesc = tr("Signal %1\%").arg(sig,2); … … void TV::UpdateOSDSignal(const PlayerCon 7517 7521 if (ber != 0xffffffff) 7518 7522 sigDesc += " | " + tr("BE %1", "Bit Errors").arg(ber, 2); 7519 7523 if ((pos >= 0) && (pos < 100)) 7520 7524 sigDesc += " | " + tr("Rotor %1\%").arg(pos,2); 7521 7525 7522 sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8) %9") 7523 .arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct) 7524 .arg(nit).arg(sdt).arg(crypt).arg(sigMsg); 7526 if (tuned == 1) 7527 tuneCode = 't'; 7528 else if (tuned == 2) 7529 tuneCode = 'F'; 7530 else if (tuned == 3) 7531 tuneCode = 'T'; 7532 else 7533 tuneCode = '_'; 7534 7535 sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8%9) %10") 7536 .arg(tuneCode).arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct) 7537 .arg(nit).arg(sdt).arg(crypt).arg(sigMsg); 7525 7538 7526 7539 if (!err.isEmpty()) 7527 7540 sigDesc = err; 7528 7541 else if (!msg.isEmpty()) 7529 7542 sigDesc = msg; -
libs/libmythtv/tv_rec.cpp
old new ProgramInfo *TVRec::GetRecording(void) 365 365 * \param hasLater If true, a later non-conflicting showing is available. 366 366 */ 367 367 void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft, 368 368 bool hasLater) 369 369 { 370 QMutexLocker lock(&stateChangeLock); 370 QMutexLocker statelock(&stateChangeLock); 371 QMutexLocker pendlock(&pendingRecLock); 371 372 372 373 if (secsleft < 0) 373 374 { 374 375 VERBOSE(VB_RECORD, LOC + "Pending recording revoked on " + 375 376 QString("inputid %1").arg(rcinfo->inputid)); … … void TVRec::RecordPending(const ProgramI 403 404 vector<uint> cardids = CardUtil::GetConflictingCards( 404 405 rcinfo->inputid, cardid); 405 406 406 407 pendingRecordings[rcinfo->cardid].possibleConflicts = cardids; 407 408 408 state ChangeLock.unlock();409 statelock.unlock(); 409 410 for (uint i = 0; i < cardids.size(); i++) 410 411 RemoteRecordPending(cardids[i], rcinfo, secsleft, hasLater); 411 state ChangeLock.lock();412 statelock.relock(); 412 413 } 413 414 414 415 /** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*) 415 416 * \brief Sets the pseudo LiveTV ProgramInfo 416 417 */ … … QDateTime TVRec::GetRecordEndTime(const 438 439 * \sa RecordPending(const ProgramInfo*, int, bool), 439 440 * TV::AskAllowRecording(const QStringList&, int, bool) 440 441 */ 441 442 void TVRec::CancelNextRecording(bool cancel) 442 443 { 444 QMutexLocker pendlock(&pendingRecLock); 443 445 VERBOSE(VB_RECORD, LOC + "CancelNextRecording("<<cancel<<") -- begin"); 444 446 445 447 PendingMap::iterator it = pendingRecordings.find(cardid); 446 448 if (it == pendingRecordings.end()) 447 449 { … … RecStatusType TVRec::StartRecording(cons 521 523 retval = rsRecording; 522 524 return retval; 523 525 } 524 526 525 527 PendingMap::iterator it = pendingRecordings.find(cardid); 528 PendingInfo pendinfo; 526 529 bool cancelNext = false; 530 bool has_pending; 531 527 532 if (it != pendingRecordings.end()) 528 533 { 529 534 (*it).ask = (*it).doNotAsk = false; 530 535 cancelNext = (*it).canceled; 531 536 } … … RecStatusType TVRec::StartRecording(cons 534 539 WaitForEventThreadSleep(); 535 540 536 541 // Rescan pending recordings since the event loop may have deleted 537 542 // a stale entry. If this happens the info pointer will not be valid 538 543 // since the HandlePendingRecordings loop will have deleted it. 544 pendingRecLock.lock(); 539 545 it = pendingRecordings.find(cardid); 546 pendinfo = *it; 547 has_pending = (it != pendingRecordings.end()); 548 pendingRecLock.unlock(); 540 549 541 550 // If the needed input is in a shared input group, and we are 542 551 // not canceling the recording anyway, check other recorders 543 if (!cancelNext && 544 (it != pendingRecordings.end()) && (*it).possibleConflicts.size()) 552 if (!cancelNext && has_pending && pendinfo.possibleConflicts.size()) 545 553 { 546 554 VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin"); 547 vector<uint> &cardids = (*it).possibleConflicts;555 vector<uint> &cardids = pendinfo.possibleConflicts; 548 556 549 557 uint mplexid = 0, sourceid = 0; 550 558 vector<uint> cardids2; 551 559 vector<TVState> states; 552 560 … … RecStatusType TVRec::StartRecording(cons 565 573 busy_input.inputid, rcinfo->inputid); 566 574 } 567 575 568 576 if (is_busy && !sourceid) 569 577 { 570 mplexid = (*it).info->GetMplexID();571 sourceid = (*it).info->sourceid;578 mplexid = pendinfo.info->GetMplexID(); 579 sourceid = pendinfo.info->sourceid; 572 580 } 573 581 574 582 if (is_busy && 575 583 ((sourceid != busy_input.sourceid) || 576 584 (mplexid != busy_input.mplexid))) … … void TVRec::HandleStateChange(void) 953 961 * \brief Puts a state change on the nextState queue. 954 962 */ 955 963 void TVRec::ChangeState(TVState nextState) 956 964 { 957 965 QMutexLocker lock(&stateChangeLock); 958 959 966 desiredNextState = nextState; 960 967 changeState = true; 961 968 WakeEventLoop(); 962 969 } 963 970 … … void TVRec::RunTV(void) 1426 1433 if (GetState() == kState_WatchingLiveTV) 1427 1434 { 1428 1435 QDateTime now = QDateTime::currentDateTime(); 1429 1436 bool has_finish = HasFlags(kFlagFinishRecording); 1430 1437 bool has_rec = pseudoLiveTVRecording; 1438 bool enable_ui = true; 1439 1440 pendingRecLock.lock(); 1431 1441 bool rec_soon = 1432 1442 pendingRecordings.find(cardid) != pendingRecordings.end(); 1433 bool enable_ui = true;1443 pendingRecLock.unlock(); 1434 1444 1435 1445 if (has_rec && (has_finish || (now > recordEndTime))) 1436 1446 { 1437 1447 if (pseudoLiveTVRecording && curRecording) 1438 1448 { … … bool TVRec::WaitForEventThreadSleep(bool 1599 1609 return ok; 1600 1610 } 1601 1611 1602 1612 void TVRec::HandlePendingRecordings(void) 1603 1613 { 1614 QMutexLocker pendlock(&pendingRecLock); 1615 1604 1616 if (pendingRecordings.empty()) 1605 1617 return; 1606 1618 1607 1619 // If we have a pending recording and AskAllowRecording 1608 1620 // or DoNotAskAllowRecording is set and the frontend is … … bool ApplyCachedPids(DTVSignalMonitor *d 1887 1899 * program number in the PAT. 1888 1900 * 1889 1901 * This method also grabs the ATSCStreamData() from the recorder 1890 1902 * if possible, or creates one if needed. 1891 1903 */ 1892 bool TVRec::SetupDTVSignalMonitor( void)1904 bool TVRec::SetupDTVSignalMonitor(bool EITscan) 1893 1905 { 1894 1906 VERBOSE(VB_RECORD, LOC + "Setting up table monitoring."); 1895 1907 1896 1908 DTVSignalMonitor *sm = GetDTVSignalMonitor(); 1897 1909 DTVChannel *dtvchan = GetDTVChannel(); … … bool TVRec::SetupDTVSignalMonitor(void) 2021 2033 sm->AddFlags(SignalMonitor::kDTVSigMon_WaitForPAT | 2022 2034 SignalMonitor::kDTVSigMon_WaitForPMT | 2023 2035 SignalMonitor::kDVBSigMon_WaitForPos); 2024 2036 sm->SetRotorTarget(1.0f); 2025 2037 2038 if (EITscan) 2039 { 2040 sm->GetStreamData()->SetVideoStreamsRequired(0); 2041 sm->IgnoreEncrypted(true); 2042 } 2043 2026 2044 VERBOSE(VB_RECORD, LOC + "Successfully set up MPEG table monitoring."); 2027 2045 return true; 2028 2046 } 2029 2047 2030 2048 QString msg = "No valid DTV info, ATSC maj(%1) min(%2), MPEG pn(%3)"; … … bool TVRec::SetupDTVSignalMonitor(void) 2042 2060 * 2043 2061 * \param tablemon If set we enable table monitoring 2044 2062 * \param notify If set we notify the frontend of the signal values 2045 2063 * \return true on success, false on failure 2046 2064 */ 2047 bool TVRec::SetupSignalMonitor(bool tablemon, bool notify)2065 bool TVRec::SetupSignalMonitor(bool tablemon, bool EITscan, bool notify) 2048 2066 { 2049 2067 VERBOSE(VB_RECORD, LOC + "SetupSignalMonitor(" 2050 2068 <<tablemon<<", "<<notify<<")"); 2051 2069 2052 2070 // if it already exists, there no need to initialize it … … bool TVRec::SetupSignalMonitor(bool tabl 2058 2076 return false; 2059 2077 2060 2078 // make sure statics are initialized 2061 2079 SignalMonitorValue::Init(); 2062 2080 2063 if (SignalMonitor::IsSupported(genOpt.cardtype) && channel->Open()) 2064 signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, channel); 2081 if (channel->Open()) 2082 signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, 2083 channel); 2065 2084 2066 2085 if (signalMonitor) 2067 2086 { 2068 2087 VERBOSE(VB_RECORD, LOC + "Signal monitor successfully created"); 2069 // If this is a monitor for Digital TV, initialize table monitors2070 if (GetDTVSignalMonitor() && tablemon && !SetupDTVSignalMonitor())2071 {2072 VERBOSE(VB_IMPORTANT, LOC_ERR +2073 "Failed to setup digital signal monitoring");2074 2075 return false;2076 }2077 2088 2089 signalMonitor->SetMonitoring(this, EITscan, 2090 GetDTVSignalMonitor() && tablemon); 2078 2091 signalMonitor->AddListener(this); 2079 2092 signalMonitor->SetUpdateRate(kSignalMonitoringRate); 2080 2093 signalMonitor->SetNotifyFrontend(notify); 2081 2094 2082 2095 // Start the monitoring thread 2083 signalMonitor->Start( );2096 signalMonitor->Start(true); 2084 2097 } 2085 2098 2086 2099 return true; 2087 2100 } 2088 2101 … … bool TVRec::IsReallyRecording(void) 2483 2496 * the next time_buffer seconds. 2484 2497 * \sa EncoderLink::IsBusy(TunedInputInfo*, int time_buffer) 2485 2498 */ 2486 2499 bool TVRec::IsBusy(TunedInputInfo *busy_input, int time_buffer) const 2487 2500 { 2488 QMutexLocker lock(&stateChangeLock);2489 2490 2501 TunedInputInfo dummy; 2491 2502 if (!busy_input) 2492 2503 busy_input = &dummy; 2493 2504 2494 2505 busy_input->Clear(); … … bool TVRec::IsBusy(TunedInputInfo *busy_ 2506 2517 { 2507 2518 busy_input->inputid = channel->GetCurrentInputNum(); 2508 2519 chanid = channel->GetChanID(); 2509 2520 } 2510 2521 2522 QMutexLocker pendlock(&pendingRecLock); 2511 2523 PendingMap::const_iterator it = pendingRecordings.find(cardid); 2512 2524 if (!busy_input->inputid && (it != pendingRecordings.end())) 2513 2525 { 2514 2526 int timeLeft = QDateTime::currentDateTime() 2515 2527 .secsTo((*it).recordingStart); … … void TVRec::TuningShutdowns(const Tuning 3676 3688 * appropriate. 3677 3689 */ 3678 3690 void TVRec::TuningFrequency(const TuningRequest &request) 3679 3691 { 3680 3692 DTVChannel *dtvchan = GetDTVChannel(); 3693 3694 bool livetv = request.flags & kFlagLiveTV; 3695 bool antadj = request.flags & kFlagAntennaAdjust; 3696 bool has_dummy = false; 3697 3681 3698 if (dtvchan) 3682 3699 { 3683 3700 MPEGStreamData *mpeg = NULL; 3684 3701 3685 3702 if (GetDTVRecorder()) … … void TVRec::TuningFrequency(const Tuning 3692 3709 3693 3710 dtvchan->SetTuningMode(tuningmode); 3694 3711 3695 3712 if (request.minorChan && (tuningmode == "atsc")) 3696 3713 { 3697 channel->SetChannelByString(request.channel); 3698 3714 channel->SelectChannel(request.channel); 3699 3715 ATSCStreamData *atsc = dynamic_cast<ATSCStreamData*>(mpeg); 3700 3716 if (atsc) 3701 3717 atsc->SetDesiredChannel(request.majorChan, request.minorChan); 3702 3718 } 3703 3719 else if (request.progNum >= 0) 3704 3720 { 3705 channel->SetChannelByString(request.channel); 3706 3721 channel->SelectChannel(request.channel); 3707 3722 if (mpeg) 3708 3723 mpeg->SetDesiredProgram(request.progNum); 3709 3724 } 3710 3725 } 3711 3726 … … void TVRec::TuningFrequency(const Tuning 3730 3745 ok = true; 3731 3746 3732 3747 if (channel && !channum.isEmpty()) 3733 3748 { 3734 3749 if (!input.isEmpty()) 3735 ok = channel->SwitchToInput(input, channum);3750 channel->SelectInput(input, channum); 3736 3751 else 3737 ok = channel->SetChannelByString(channum); 3752 channel->SelectChannel(channum); 3753 3754 ok = true; 3738 3755 } 3739 3756 3740 3757 if (!ok) 3741 3758 { 3742 3759 if (!(request.flags & kFlagLiveTV) || !(request.flags & kFlagEITScan)) … … void TVRec::TuningFrequency(const Tuning 3759 3776 VERBOSE(VB_IMPORTANT, LOC_ERR + 3760 3777 QString("Failed to set channel to %1.").arg(channum)); 3761 3778 } 3762 3779 } 3763 3780 3764 bool livetv = request.flags & kFlagLiveTV; 3765 bool antadj = request.flags & kFlagAntennaAdjust; 3766 bool use_sm = SignalMonitor::IsRequired(genOpt.cardtype); 3767 bool use_dr = use_sm && (livetv || antadj); 3768 bool has_dummy = false; 3769 3770 if (use_dr) 3781 if (livetv || antadj) 3771 3782 { 3772 3783 // We need there to be a ringbuffer for these modes 3773 3784 bool ok; 3774 3785 ProgramInfo *tmp = pseudoLiveTVRecording; 3775 3786 pseudoLiveTVRecording = NULL; … … void TVRec::TuningFrequency(const Tuning 3791 3802 } 3792 3803 3793 3804 has_dummy = true; 3794 3805 } 3795 3806 3796 // Start signal monitoring for devices capable of monitoring 3797 if (use_sm) 3807 // Start signal (or channel change) monitoring 3808 VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor"); 3809 bool error = false; 3810 if (!SetupSignalMonitor(!antadj, request.flags & kFlagEITScan, 3811 livetv | antadj)) 3798 3812 { 3799 VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor"); 3800 bool error = false; 3801 if (!SetupSignalMonitor(!antadj, livetv | antadj)) 3802 { 3803 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor"); 3804 if (signalMonitor) 3805 { 3806 delete signalMonitor; 3807 signalMonitor = NULL; 3808 } 3809 3810 // pretend the signal monitor is running to prevent segfault 3811 SetFlags(kFlagSignalMonitorRunning); 3812 ClearFlags(kFlagWaitingForSignal); 3813 error = true; 3814 } 3815 3813 VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor"); 3816 3814 if (signalMonitor) 3817 3815 { 3818 if (request.flags & kFlagEITScan) 3819 { 3820 GetDTVSignalMonitor()->GetStreamData()-> 3821 SetVideoStreamsRequired(0); 3822 GetDTVSignalMonitor()->IgnoreEncrypted(true); 3823 } 3824 3825 SetFlags(kFlagSignalMonitorRunning); 3826 ClearFlags(kFlagWaitingForSignal); 3827 if (!antadj) 3828 SetFlags(kFlagWaitingForSignal); 3816 delete signalMonitor; 3817 signalMonitor = NULL; 3829 3818 } 3830 3819 3831 if (has_dummy && ringBuffer) 3832 { 3833 // Make sure recorder doesn't point to bogus ringbuffer before 3834 // it is potentially restarted without a new ringbuffer, if 3835 // the next channel won't tune and the user exits LiveTV. 3836 if (recorder) 3837 recorder->SetRingBuffer(NULL); 3820 // pretend the signal monitor is running to prevent segfault 3821 SetFlags(kFlagSignalMonitorRunning); 3822 ClearFlags(kFlagWaitingForSignal); 3823 error = true; 3824 } 3838 3825 3839 SetFlags(kFlagDummyRecorderRunning); 3840 VERBOSE(VB_RECORD, "DummyDTVRecorder -- started"); 3841 SetFlags(kFlagRingBufferReady); 3842 } 3826 if (signalMonitor) 3827 { 3828 SetFlags(kFlagSignalMonitorRunning); 3829 ClearFlags(kFlagWaitingForSignal); 3830 if (!antadj) 3831 SetFlags(kFlagWaitingForSignal); 3832 } 3843 3833 3844 // if we had problems starting the signal monitor, 3845 // we don't want to start the recorder... 3846 if (error) 3847 return; 3834 if (has_dummy && ringBuffer) 3835 { 3836 // Make sure recorder doesn't point to bogus ringbuffer before 3837 // it is potentially restarted without a new ringbuffer, if 3838 // the next channel won't tune and the user exits LiveTV. 3839 if (recorder) 3840 recorder->SetRingBuffer(NULL); 3841 3842 SetFlags(kFlagDummyRecorderRunning); 3843 VERBOSE(VB_RECORD, "DummyDTVRecorder -- started"); 3844 SetFlags(kFlagRingBufferReady); 3848 3845 } 3849 3846 3847 // if we had problems starting the signal monitor, 3848 // we don't want to start the recorder... 3849 if (error) 3850 return; 3851 3850 3852 // Request a recorder, if the command is a recording command 3851 3853 ClearFlags(kFlagNeedToStartRecorder); 3852 3854 if (request.flags & kFlagRec && !antadj) 3853 3855 SetFlags(kFlagNeedToStartRecorder); 3854 3856 } -
libs/libmythtv/tv_rec.h
old new class PendingInfo 148 148 typedef QMap<uint,PendingInfo> PendingMap; 149 149 150 150 class MPUBLIC TVRec : public SignalMonitorListener 151 151 { 152 152 friend class TuningRequest; 153 friend class SignalMonitor; 153 154 154 155 public: 155 156 TVRec(int capturecardnum); 156 157 ~TVRec(void); 157 158 … … class MPUBLIC TVRec : public SignalMonit 242 243 uint GetFlags(void) const { return stateFlags; } 243 244 244 245 static TVRec *GetTVRec(uint cardid); 245 246 246 247 virtual void AllGood(void) { WakeEventLoop(); } 248 virtual void StatusChannelTuned(const SignalMonitorValue&) { } 247 249 virtual void StatusSignalLock(const SignalMonitorValue&) { } 248 250 virtual void StatusSignalStrength(const SignalMonitorValue&) { } 249 251 250 252 protected: 251 253 void RunTV(void); 252 254 bool WaitForEventThreadSleep(bool wake = true, ulong time = ULONG_MAX); 253 255 static void *EventThread(void *param); 254 256 static void *RecorderThread(void *param); 257 bool SetupDTVSignalMonitor(bool EITscan); 255 258 256 259 private: 257 260 void SetRingBuffer(RingBuffer *); 258 261 void SetPseudoLiveTVRecording(ProgramInfo*); 259 262 void TeardownAll(void); … … class MPUBLIC TVRec : public SignalMonit 279 282 HDHRChannel *GetHDHRChannel(void); 280 283 DVBChannel *GetDVBChannel(void); 281 284 FirewireChannel *GetFirewireChannel(void); 282 285 V4LChannel *GetV4LChannel(void); 283 286 284 bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);285 bool SetupDTVSignalMonitor(void);287 bool SetupSignalMonitor(bool enable_table_monitoring, 288 bool EITscan, bool notify); 286 289 void TeardownSignalMonitor(void); 287 290 DTVSignalMonitor *GetDTVSignalMonitor(void); 288 291 289 292 bool HasFlags(uint f) const { return (stateFlags & f) == f; } 290 293 void SetFlags(uint f); … … class MPUBLIC TVRec : public SignalMonit 358 361 DVBDBOptions dvbOpt; 359 362 FireWireDBOptions fwOpt; 360 363 361 364 // State variables 362 365 mutable QMutex stateChangeLock; 366 mutable QMutex pendingRecLock; 363 367 TVState internalState; 364 368 TVState desiredNextState; 365 369 bool changeState; 366 370 bool pauseNotify; 367 371 uint stateFlags; -
libs/libmythtv/v4lchannel.h
old new class V4LChannel : public DTVChannel 47 47 int GetFd(void) const { return videofd; } 48 48 QString GetDevice(void) const { return device; } 49 49 QString GetSIStandard(void) const { return "atsc"; } 50 50 51 51 // Commands 52 bool SwitchToInput(int newcapchannel, bool setstarting);53 52 bool Retune(void); 54 53 55 54 // Picture attributes. 56 55 bool InitPictureAttributes(void); 57 56 int GetPictureAttribute(PictureAttribute) const; … … class V4LChannel : public DTVChannel 67 66 68 67 // Analog scanning stuff 69 68 bool Tune(uint frequency, QString inputname, 70 69 QString modulation, QString si_std); 71 70 71 protected: 72 bool SwitchToInput(int newcapchannel, bool setstarting); 73 72 74 private: 73 75 // Helper Sets 74 76 void SetFreqTable(const int index); 75 77 int SetFreqTable(const QString &name); 76 78 bool SetInputAndFormat(int newcapchannel, QString newFmt);