Ticket #6719: channel-thread-trunk-25379.patch

File channel-thread-trunk-25379.patch, 48.1 KB (added by jpoet, 22 months ago)

Fixes dvb multirec problem. Updated for trunk r25379

  • libs/libmythtv/analogsignalmonitor.cpp

    old new void AnalogSignalMonitor::UpdateValues(v 
    3333    if (videofd < 0) 
    3434        return; 
    3535 
     36    if (!IsChannelTuned()) 
     37        return; 
     38 
    3639    bool isLocked = false; 
    3740    if (usingv4l2) 
    3841    { 
  • libs/libmythtv/channelbase.cpp

    old new using namespace std; 
    3434#define LOC_WARN QString("ChannelBase(%1) Warning: ").arg(GetCardID()) 
    3535#define LOC_ERR QString("ChannelBase(%1) Error: ").arg(GetCardID()) 
    3636 
     37/* 
     38 * Run the channel change thread, and report the status when done 
     39 */ 
     40void ChannelThread::run(void) 
     41{ 
     42  VERBOSE(VB_CHANNEL, "ChannelThread::run"); 
     43    bool result = tuner->SetChannelByString(channel); 
     44    tuner->setStatus(result ? 
     45                     ChannelBase::changeSuccess : ChannelBase::changeFailed); 
     46} 
     47 
    3748ChannelBase::ChannelBase(TVRec *parent) 
    3849    : 
    3950    m_pParent(parent), m_curchannelname(""), 
    40     m_currentInputID(-1), m_commfree(false), m_cardid(0) 
     51    m_currentInputID(-1), m_commfree(false), m_cardid(0), 
     52    m_abort_change(false) 
    4153{ 
     54    m_tuneStatus = changeUnknown; 
     55    m_tuneThread.tuner = this; 
    4256} 
    4357 
    4458ChannelBase::~ChannelBase(void) 
    4559{ 
    4660    ClearInputMap(); 
     61    TeardownAll(); 
     62} 
     63 
     64void ChannelBase::TeardownAll(void) 
     65{ 
     66    if (m_tuneThread.isRunning()) 
     67    { 
     68        m_thread_lock.lock(); 
     69        m_abort_change = true; 
     70        m_tuneCond.wakeAll(); 
     71        m_thread_lock.unlock(); 
     72        m_tuneThread.wait(); 
     73    } 
     74} 
     75 
     76void ChannelBase::SelectChannel(const QString & chan) 
     77{ 
     78    VERBOSE(VB_CHANNEL, LOC + "SelectChannel " + chan); 
     79    TeardownAll(); 
     80 
     81    m_thread_lock.lock(); 
     82    m_abort_change = false; 
     83    m_tuneStatus = changePending; 
     84    m_thread_lock.unlock(); 
     85 
     86    m_curchannelname = m_tuneThread.channel = chan; 
     87    m_tuneThread.start(); 
     88} 
     89 
     90/* 
     91 * Returns true of the channel change thread should abort 
     92 */ 
     93bool ChannelBase::Aborted(void) 
     94{ 
     95    bool       result; 
     96 
     97    m_thread_lock.lock(); 
     98    result = m_abort_change; 
     99    m_thread_lock.unlock(); 
     100 
     101    return result; 
     102} 
     103 
     104ChannelBase::Status ChannelBase::GetStatus(void) 
     105{ 
     106    Status status; 
     107 
     108    m_thread_lock.lock(); 
     109    status = m_tuneStatus; 
     110    m_thread_lock.unlock(); 
     111 
     112    return status; 
     113} 
     114 
     115ChannelBase::Status ChannelBase::Wait(void) 
     116{ 
     117    m_tuneThread.wait(); 
     118    return m_tuneStatus; 
     119} 
     120 
     121void ChannelBase::setStatus(ChannelBase::Status status) 
     122{ 
     123    m_thread_lock.lock(); 
     124    m_tuneStatus = status; 
     125    m_thread_lock.unlock(); 
    47126} 
    48127 
    49128bool ChannelBase::Init(QString &inputname, QString &startchannel, bool setchan) 
    bool ChannelBase::Init(QString &inputnam 
    53132    if (!setchan) 
    54133        ok = inputname.isEmpty() ? false : IsTunable(inputname, startchannel); 
    55134    else if (inputname.isEmpty()) 
    56         ok = SetChannelByString(startchannel); 
     135    { 
     136        SelectChannel(startchannel); 
     137        ok = Wait(); 
     138    } 
    57139    else 
    58         ok = SwitchToInput(inputname, startchannel); 
     140        ok = SelectInput(inputname, startchannel, false); 
    59141 
    60142    if (ok) 
    61143        return true; 
    bool ChannelBase::Init(QString &inputnam 
    124206            if (chanid && cit != channels.end()) 
    125207            { 
    126208                if (!setchan) 
    127                 { 
    128209                    ok = IsTunable(*it, (mplexid_restriction) ? 
    129210                                   (*cit).channum : startchannel); 
    130                 } 
    131211                else 
    132                     ok = SwitchToInput(*it, (*cit).channum); 
     212                    ok = SelectInput(*it, (*cit).channum, false); 
    133213 
    134214                if (ok) 
    135215                { 
    int ChannelBase::GetInputByName(const QS 
    329409    return -1; 
    330410} 
    331411 
     412#if 0 // Not used? 
    332413bool ChannelBase::SwitchToInput(const QString &inputname) 
    333414{ 
    334415    int input = GetInputByName(inputname); 
    bool ChannelBase::SwitchToInput(const QS 
    340421                                      "%1 on card\n").arg(inputname)); 
    341422    return false; 
    342423} 
     424#endif 
    343425 
    344 bool ChannelBase::SwitchToInput(const QString &inputname, const QString &chan) 
     426bool ChannelBase::SelectInput(const QString &inputname, const QString &chan, 
     427                              bool use_sm) 
    345428{ 
    346429    int input = GetInputByName(inputname); 
    347430 
    348     bool ok = false; 
    349431    if (input >= 0) 
    350432    { 
    351         ok = SwitchToInput(input, false); 
    352         if (ok) 
    353             ok = SetChannelByString(chan); 
     433        if (!SwitchToInput(input, false)) 
     434            return false; 
     435        if (use_sm) 
     436            SelectChannel(chan); 
     437        else 
     438            return SetChannelByString(chan); 
    354439    } 
    355440    else 
    356441    { 
    357442        VERBOSE(VB_IMPORTANT, 
    358443                QString("ChannelBase: Could not find input: %1 on card when " 
    359444                        "setting channel %2\n").arg(inputname).arg(chan)); 
     445        return false; 
    360446    } 
    361     return ok; 
     447    return true; 
    362448} 
    363449 
    364450bool ChannelBase::SwitchToInput(int newInputNum, bool setstarting) 
    bool ChannelBase::SwitchToInput(int newI 
    374460    // input switching code would go here 
    375461 
    376462    if (setstarting) 
    377         return SetChannelByString((*it)->startChanNum); 
     463        SelectChannel((*it)->startChanNum); 
    378464 
    379465    return true; 
    380466} 
    static bool is_input_busy( 
    485571    return is_busy; 
    486572} 
    487573 
    488 bool ChannelBase::IsInputAvailable( 
    489     int inputid, uint &mplexid_restriction) const 
     574bool ChannelBase::IsInputAvailable(int inputid, uint &mplexid_restriction) const 
    490575{ 
    491576    if (inputid < 0) 
    492577        return false; 
    bool ChannelBase::ChangeExternalChannel( 
    651736    } 
    652737    else 
    653738    {   // child contains the pid of the new process 
    654         int status = 0, pid = 0; 
     739        QMutex      lock; 
     740        int         status = 0, pid = 0; 
     741 
    655742        VERBOSE(VB_CHANNEL, "Waiting for External Tuning program to exit"); 
    656743 
    657744        bool timed_out = false; 
    658745        uint timeout = 30; // how long to wait in seconds 
    659746        time_t start_time = time(0); 
    660         while (-1 != pid && !timed_out) 
     747        while (-1 != pid && !timed_out && !Aborted()) 
    661748        { 
    662             sleep(1); 
     749            lock.lock(); 
     750            m_tuneCond.wait(&lock, 500);  // sleep up to 0.5 seconds 
    663751            pid = waitpid(child, &status, WUNTRACED|WNOHANG); 
    664752            VERBOSE(VB_IMPORTANT, QString("ret_pid(%1) child(%2) status(0x%3)") 
    665753                    .arg(pid).arg(child).arg(status,0,16)); 
    666754            if (pid==child) 
     755            { 
     756                lock.unlock(); 
    667757                break; 
     758            } 
    668759            else if (time(0) > (time_t)(start_time + timeout)) 
    669760                timed_out = true; 
     761            lock.unlock(); 
    670762        } 
    671         if (timed_out) 
     763 
     764        if (timed_out || Aborted()) 
    672765        { 
    673             VERBOSE(VB_IMPORTANT, "External Tuning program timed out, killing"); 
     766            if (Aborted()) 
     767                VERBOSE(VB_IMPORTANT, "Aborting External Tuning program"); 
     768            else 
     769                VERBOSE(VB_IMPORTANT, "External Tuning program timed out, " 
     770                        "killing"); 
    674771            kill(child, SIGTERM); 
    675772            usleep(500); 
    676773            kill(child, SIGKILL); 
    int ChannelBase::GetChanID() const 
    752849        return -1; 
    753850 
    754851    query.next(); 
     852 
     853    VERBOSE(VB_CHANNEL, LOC + QString(" ChannelBase::GetChanID %1") 
     854            .arg(query.value(0).toInt()));; 
     855 
    755856    return query.value(0).toInt(); 
    756857} 
    757858 
  • libs/libmythtv/channelbase.h

    old new  
    55 
    66// Qt headers 
    77#include <QStringList> 
     8#include <qwaitcondition.h> 
     9#include <qmutex.h> 
     10#include <qthread.h> 
    811 
    912// MythTV headers 
    1013#include "channelutil.h" 
     
    1215#include "tv.h" 
    1316 
    1417class TVRec; 
     18class ChannelBase; 
     19 
     20/* 
     21 * Thread to run tunning process in 
     22 */ 
     23class ChannelThread : public QThread 
     24{ 
     25  public: 
     26    virtual void run(void); 
     27 
     28    QString      channel; 
     29    ChannelBase *tuner; 
     30}; 
    1531 
    1632/** \class ChannelBase 
    1733 *  \brief Abstract class providing a generic interface to tuning hardware. 
    class TVRec; 
    2339 
    2440class ChannelBase 
    2541{ 
    26  public: 
     42    friend class ChannelThread; 
     43 
     44  public: 
     45    enum Status { changeUnknown = 'U', changePending = 'P', 
     46                  changeFailed = 'F', changeSuccess = 'S' }; 
     47 
    2748    ChannelBase(TVRec *parent); 
    28     virtual ~ChannelBase(); 
     49    virtual ~ChannelBase(void); 
    2950 
    3051    virtual bool Init(QString &inputname, QString &startchannel, bool setchan); 
    3152    virtual bool IsTunable(const QString &input, const QString &channum) const; 
    3253 
     54    virtual void SelectChannel(const QString & chan); 
     55 
     56    Status GetStatus(void); 
     57    Status Wait(void); 
     58 
    3359    // Methods that must be implemented. 
    3460    /// \brief Opens the channel changing hardware for use. 
    3561    virtual bool Open(void) = 0; 
    3662    /// \brief Closes the channel changing hardware to use. 
    3763    virtual void Close(void) = 0; 
    38     virtual bool SetChannelByString(const QString &chan) = 0; 
    3964    /// \brief Reports whether channel is already open 
    4065    virtual bool IsOpen(void) const = 0; 
    4166 
    class ChannelBase 
    82107                          const QString &newChanNum); 
    83108 
    84109    // Input toggling convenience methods 
    85     virtual bool SwitchToInput(const QString &input); 
    86     virtual bool SwitchToInput(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, 
     112                             bool use_sm); 
    87113 
    88114    virtual bool InitializeInputs(void); 
    89115 
    class ChannelBase 
    108134 
    109135    virtual int GetCardID(void) const; 
    110136  protected: 
     137    virtual bool SetChannelByString(const QString &chan) = 0; 
     138 
    111139    /// \brief Switches to another input on hardware, 
    112140    ///        and sets the channel is setstarting is true. 
    113141    virtual bool SwitchToInput(int inputNum, bool setstarting); 
    class ChannelBase 
    119147    static void StoreDefaultInput(uint cardid, const QString &input); 
    120148    void ClearInputMap(void); 
    121149 
     150    bool Aborted(); 
     151    void setStatus(Status status); 
     152    void TeardownAll(void); 
     153 
    122154    TVRec   *m_pParent; 
    123155    QString  m_curchannelname; 
    124156    int      m_currentInputID; 
    class ChannelBase 
    126158    uint     m_cardid; 
    127159    InputMap m_inputs; 
    128160    DBChanList m_allchannels; ///< channels across all inputs 
     161 
     162    QWaitCondition  m_tuneCond; 
     163 
     164  private: 
     165    mutable  ChannelThread   m_tuneThread; 
     166    Status   m_tuneStatus; 
     167    QMutex   m_thread_lock; 
     168    bool     m_abort_change; 
    129169}; 
    130170 
    131171#endif 
  • 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 "mythcontext.h" 
     8#include "channelchangemonitor.h" 
     9#include "v4lchannel.h" 
     10 
     11#define LOC QString("ChannelChangeM: ").arg(channel->GetDevice()) 
     12#define LOC_ERR QString("ChannelChangeM, Error: ").arg(channel->GetDevice()) 
     13 
     14ChannelChangeMonitor::ChannelChangeMonitor( 
     15    int db_cardnum, V4LChannel *_channel, uint64_t _flags) : 
     16    SignalMonitor(db_cardnum, _channel, _flags) 
     17{ 
     18} 
     19 
     20void ChannelChangeMonitor::UpdateValues(void) 
     21{ 
     22    if (!running || exit) 
     23        return; 
     24 
     25    if (!IsChannelTuned()) 
     26        return; 
     27 
     28    { 
     29        QMutexLocker locker(&statusLock); 
     30        signalLock.SetValue(true); 
     31        signalStrength.SetValue(100); 
     32    } 
     33 
     34    EmitStatus(); 
     35    SendMessageAllGood(); 
     36} 
     37 
  • 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 
     10class V4LChannel; 
     11 
     12class 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  
    16271627    } 
    16281628 
    16291629    // Start signal monitor for this channel 
    1630     signalMonitor->Start(); 
     1630    signalMonitor->Start(false); 
    16311631 
    16321632    timer.start(); 
    16331633    waitingForTables = (item.tuning.sistandard != "analog"); 
  • libs/libmythtv/channelscan/channelscan_sm.h

    old new class AnalogSignalHandler : public Signa 
    7373  public slots: 
    7474    virtual inline void AllGood(void); 
    7575    virtual void StatusSignalLock(const SignalMonitorValue&) { } 
     76    virtual void StatusChannelTuned(const SignalMonitorValue&) { } 
    7677    virtual void StatusSignalStrength(const SignalMonitorValue&) { } 
    7778 
    7879  private: 
  • libs/libmythtv/channelscan/scanmonitor.cpp

    old new QEvent::Type ScannerEvent::SetStatusSign 
    5555    (QEvent::Type) QEvent::registerEventType(); 
    5656QEvent::Type ScannerEvent::SetStatusSignalLock = 
    5757    (QEvent::Type) QEvent::registerEventType(); 
     58QEvent::Type ScannerEvent::SetStatusChannelTuned = 
     59    (QEvent::Type) QEvent::registerEventType(); 
    5860 
    5961/// Percentage to set to after the transports have been scanned 
    6062#define TRANSPORT_PCT 6 
    void ScanMonitor::StatusSignalLock(const 
    133135    post_event(this, ScannerEvent::SetStatusSignalLock, val.GetValue()); 
    134136} 
    135137 
     138void ScanMonitor::StatusChannelTuned(const SignalMonitorValue &val) 
     139{ 
     140    post_event(this, ScannerEvent::SetStatusChannelTuned, val.GetValue()); 
     141} 
     142 
    136143void ScanMonitor::StatusSignalToNoise(const SignalMonitorValue &val) 
    137144{ 
    138145    post_event(this, ScannerEvent::SetStatusSignalToNoise, 
  • libs/libmythtv/channelscan/scanmonitor.h

    old new class ScanMonitor : 
    6565    // SignalMonitorListener 
    6666    virtual void AllGood(void) { } 
    6767    virtual void StatusSignalLock(const SignalMonitorValue&); 
     68    virtual void StatusChannelTuned(const SignalMonitorValue&); 
    6869    virtual void StatusSignalStrength(const SignalMonitorValue&); 
    6970 
    7071    // DVBSignalMonitorListener 
    class ScannerEvent : public QEvent 
    110111    static Type SetStatusSignalToNoise; 
    111112    static Type SetStatusSignalStrength; 
    112113    static Type SetStatusSignalLock; 
     114    static Type SetStatusChannelTuned; 
    113115 
    114116  private: 
    115117    ~ScannerEvent() { } 
  • libs/libmythtv/dtvsignalmonitor.cpp

    old new DTVSignalMonitor::DTVSignalMonitor(int d 
    2525                                   uint64_t wait_for_mask) 
    2626    : SignalMonitor(db_cardnum, _channel, wait_for_mask), 
    2727      stream_data(NULL), 
     28      channelTuned(QObject::tr("Channel Tuned"), "tuned", 3, true, 0, 3, 0), 
    2829      seenPAT(QObject::tr("Seen")+" PAT", "seen_pat", 1, true, 0, 1, 0), 
    2930      seenPMT(QObject::tr("Seen")+" PMT", "seen_pmt", 1, true, 0, 1, 0), 
    3031      seenMGT(QObject::tr("Seen")+" MGT", "seen_mgt", 1, true, 0, 1, 0), 
    QStringList DTVSignalMonitor::GetStatusL 
    6364{ 
    6465    QStringList list = SignalMonitor::GetStatusList(kick); 
    6566    QMutexLocker locker(&statusLock); 
     67 
     68    // tuned? 
     69    if (flags & kSigMon_Tuned) 
     70    { 
     71        list<<channelTuned.GetName()<<channelTuned.GetStatus(); 
     72    } 
     73 
    6674    // mpeg tables 
    6775    if (flags & kDTVSigMon_WaitForPAT) 
    6876    { 
    void DTVSignalMonitor::RemoveFlags(uint6 
    138146void DTVSignalMonitor::UpdateMonitorValues(void) 
    139147{ 
    140148    QMutexLocker locker(&statusLock); 
     149    channelTuned.SetValue((flags & kSigMon_Tuned)      ? 3 : 1); 
    141150    seenPAT.SetValue(    (flags & kDTVSigMon_PATSeen)  ? 1 : 0); 
    142151    seenPMT.SetValue(    (flags & kDTVSigMon_PMTSeen)  ? 1 : 0); 
    143152    seenMGT.SetValue(    (flags & kDTVSigMon_MGTSeen)  ? 1 : 0); 
  • libs/libmythtv/dtvsignalmonitor.h

    old new class DTVSignalMonitor : public SignalMo 
    111111  protected: 
    112112    MPEGStreamData    *stream_data; 
    113113    vector<uint>       eit_pids; 
     114    SignalMonitorValue channelTuned; 
    114115    SignalMonitorValue seenPAT; 
    115116    SignalMonitorValue seenPMT; 
    116117    SignalMonitorValue seenMGT; 
  • libs/libmythtv/dvbchannel.cpp

    old new bool DVBChannel::SetChannelByString(cons 
    394394    return true; 
    395395} 
    396396 
    397 bool DVBChannel::SwitchToInput(const QString &inputname, const QString &chan) 
     397bool DVBChannel::SelectInput(const QString &inputname, const QString &chan, 
     398                             bool use_sm) 
    398399{ 
    399400    int input = GetInputByName(inputname); 
    400401 
    401     bool ok = false; 
    402402    if (input >= 0) 
    403403    { 
    404404        nextInputID = input; 
    405         ok = SetChannelByString(chan); 
     405        if (use_sm) 
     406            SelectChannel(chan); 
     407        else 
     408            return SetChannelByString(chan); 
    406409    } 
    407410    else 
    408411    { 
    409412        VERBOSE(VB_IMPORTANT, 
    410413                QString("DVBChannel: Could not find input: %1 on card when " 
    411414                        "setting channel %2\n").arg(inputname).arg(chan)); 
     415        return false; 
    412416    } 
    413     return ok; 
     417    return true; 
    414418} 
    415419 
    416420bool DVBChannel::SwitchToInput(int newInputNum, bool setstarting) 
  • libs/libmythtv/dvbchannel.h

    old new class DVBChannel : public DTVChannel 
    7878    double GetUncorrectedBlockCount(bool *ok = NULL) const; 
    7979 
    8080    // Commands 
     81#if 0 
    8182    bool SwitchToInput(const QString &inputname, const QString &chan); 
     83#else 
     84    bool SelectInput(const QString &inputname, const QString &chan, 
     85                     bool use_sm); 
     86#endif 
    8287    bool SwitchToInput(int newcapchannel, bool setstarting); 
    8388    bool SetChannelByString(const QString &chan); 
    8489    bool Tune(const DTVMultiplex &tuning, QString inputname); 
  • libs/libmythtv/dvbsignalmonitor.cpp

    old new void DVBSignalMonitor::UpdateValues(void 
    232232        return; 
    233233    } 
    234234 
     235    if (!IsChannelTuned()) 
     236        return; 
     237 
    235238    AddFlags(kSigMon_WaitForSig); 
    236239 
    237240    DVBChannel *dvbchannel = GetDVBChannel(); 
  • libs/libmythtv/firewiresignalmonitor.cpp

    old new void FirewireSignalMonitor::UpdateValues 
    190190    if (!running || exit) 
    191191        return; 
    192192 
     193    if (!IsChannelTuned()) 
     194        return; 
     195 
    193196    if (dtvMonitorRunning) 
    194197    { 
    195198        EmitStatus(); 
  • libs/libmythtv/hdhrchannel.cpp

    old new bool HDHRChannel::SetChannelByString(con 
    130130    // change inputs and return, since the act of changing 
    131131    // inputs will change the channel as well. 
    132132    if (!inputName.isEmpty()) 
    133         return SwitchToInput(inputName, channum); 
     133        return SelectInput(inputName, channum, false); 
    134134 
    135135    ClearDTVInfo(); 
    136136 
    bool HDHRChannel::SetChannelByString(con 
    142142    if (!IsInputAvailable(m_currentInputID, mplexid_restriction)) 
    143143        return false; 
    144144 
     145    if (Aborted()) 
     146        return false; 
     147 
    145148    // Fetch tuning data from the database. 
    146149    QString tvformat, modulation, freqtable, freqid, si_std; 
    147150    int finetune; 
  • libs/libmythtv/hdhrsignalmonitor.cpp

    old new void HDHRSignalMonitor::UpdateValues(voi 
    105105        return; 
    106106    } 
    107107 
     108    if (!IsChannelTuned()) 
     109        return; 
     110 
    108111    struct hdhomerun_tuner_status_t status; 
    109112    streamHandler->GetTunerStatus(&status); 
    110113 
  • libs/libmythtv/iptvsignalmonitor.cpp

    old new void IPTVSignalMonitor::UpdateValues(voi 
    119119    if (!running || exit) 
    120120        return; 
    121121 
     122    if (!IsChannelTuned()) 
     123        return; 
     124 
    122125    if (dtvMonitorRunning) 
    123126    { 
    124127        EmitStatus(); 
  • libs/libmythtv/libmythtv.pro

    old new using_backend { 
    454454        DEFINES += USING_OSS 
    455455    } 
    456456 
     457    HEADERS += channelchangemonitor.h 
     458    SOURCES += channelchangemonitor.cpp 
     459 
    457460    # Support for Video4Linux devices 
    458461    using_v4l { 
    459462        HEADERS += v4lchannel.h                analogsignalmonitor.h 
  • libs/libmythtv/signalmonitor.cpp

    old new  
    88 
    99// MythTV headers 
    1010#include "mythcontext.h" 
     11#include "tv_rec.h" 
    1112#include "signalmonitor.h" 
    1213#include "compat.h" 
    1314#include "mythverbose.h" 
    extern "C" { 
    4243#   include "firewirechannel.h" 
    4344#endif 
    4445 
     46#include "channelchangemonitor.h" 
     47 
    4548#undef DBG_SM 
    4649#define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \ 
    4750    "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); 
    SignalMonitor *SignalMonitor::Init(QStri 
    9396#endif 
    9497 
    9598#ifdef USING_V4L 
     99#if 0 // Just use ChannelChangeMonitor for these types 
    96100    if ((cardtype.toUpper() == "V4L") || 
    97         (cardtype.toUpper() == "MPEG") || 
    98         (cardtype.toUpper() == "HDPVR")) 
     101        (cardtype.toUpper() == "MPEG")) 
    99102    { 
    100103        V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 
    101104        if (chan) 
    102105            signalMonitor = new AnalogSignalMonitor(db_cardnum, chan); 
    103106    } 
    104107#endif 
     108#endif 
    105109 
    106110#ifdef USING_HDHOMERUN 
    107111    if (cardtype.toUpper() == "HDHOMERUN") 
    SignalMonitor *SignalMonitor::Init(QStri 
    132136 
    133137    if (!signalMonitor) 
    134138    { 
     139        V4LChannel *chan = dynamic_cast<V4LChannel*>(channel); 
     140        if (chan) 
     141            signalMonitor = new ChannelChangeMonitor(db_cardnum, chan); 
     142    } 
     143 
     144    if (!signalMonitor) 
     145    { 
    135146        VERBOSE(VB_IMPORTANT, 
    136147                QString("Failed to create signal monitor in Init(%1, %2, 0x%3)") 
    137148                .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16)); 
    SignalMonitor::SignalMonitor(int _captur 
    160171      update_rate(25),                 minimum_update_rate(5), 
    161172      running(false),                  exit(false), 
    162173      update_done(false),              notify_frontend(true), 
    163       error(""), 
     174      is_tuned(false),                 tablemon(false), 
     175      eit_scan(false),                 error(""), 
    164176      signalLock    (QObject::tr("Signal Lock"),  "slock", 
    165177                     1, true, 0,   1, 0), 
    166178      signalStrength(QObject::tr("Signal Power"), "signal", 
    167179                     0, true, 0, 100, 0), 
     180      channelTuned("Channel Tuned", "tuned", 3, true, 0, 3, 0), 
    168181      statusLock(QMutex::Recursive) 
    169182{ 
    170183} 
    bool SignalMonitor::HasAnyFlag(uint64_t  
    202215/** \fn SignalMonitor::Start() 
    203216 *  \brief Start signal monitoring thread. 
    204217 */ 
    205 void SignalMonitor::Start() 
     218void SignalMonitor::Start(bool waitfor_tune) 
    206219{ 
    207220    DBG_SM("Start", "begin"); 
    208221    { 
    209222        QMutexLocker locker(&startStopLock); 
     223 
     224        // When used for scanning, don't wait for the tuning thread 
     225        is_tuned = !waitfor_tune; 
     226 
    210227        if (!running) 
    211228        { 
    212229            int rval = pthread_create( 
    QStringList SignalMonitor::GetStatusList 
    279296 
    280297    QStringList list; 
    281298    statusLock.lock(); 
     299    list<<channelTuned.GetName()<<channelTuned.GetStatus(); 
    282300    list<<signalLock.GetName()<<signalLock.GetStatus(); 
    283301    if (HasFlags(kSigMon_WaitForSig)) 
    284302        list<<signalStrength.GetName()<<signalStrength.GetStatus(); 
    void SignalMonitor::SendMessage( 
    441459        case kStatusSignalStrength: 
    442460            listener->StatusSignalStrength(val); 
    443461            break; 
     462        case kStatusChannelTuned: 
     463            listener->StatusChannelTuned(val); 
     464            break; 
    444465        case kStatusSignalToNoise: 
    445466            if (dvblistener) 
    446467                dvblistener->StatusSignalToNoise(val); 
    void SignalMonitor::SendMessage( 
    461482    } 
    462483} 
    463484 
     485bool SignalMonitor::IsChannelTuned(void) 
     486{ 
     487    if (is_tuned) 
     488        return true; 
     489 
     490    ChannelBase::Status status = channel->GetStatus(); 
     491    QMutexLocker locker(&statusLock); 
     492 
     493    switch (status) { 
     494      case ChannelBase::changePending: 
     495        channelTuned.SetValue(1); 
     496        break; 
     497      case ChannelBase::changeFailed: 
     498        channelTuned.SetValue(2); 
     499        break; 
     500      case ChannelBase::changeSuccess: 
     501        channelTuned.SetValue(3); 
     502        break; 
     503    } 
     504 
     505    EmitStatus(); 
     506 
     507    if (status == ChannelBase::changeSuccess) 
     508    { 
     509        if (tablemon) 
     510            pParent->SetupDTVSignalMonitor(eit_scan); 
     511 
     512        is_tuned = true; 
     513        return true; 
     514    } 
     515 
     516    return false; 
     517} 
     518 
    464519void SignalMonitor::SendMessageAllGood(void) 
    465520{ 
    466521    QMutexLocker locker(&listenerLock); 
    void SignalMonitor::SendMessageAllGood(v 
    470525 
    471526void SignalMonitor::EmitStatus(void) 
    472527{ 
     528    SendMessage(kStatusChannelTuned, channelTuned); 
    473529    SendMessage(kStatusSignalLock, signalLock); 
    474530    if (HasFlags(kSigMon_WaitForSig)) 
    475531        SendMessage(kStatusSignalStrength,    signalStrength); 
  • libs/libmythtv/signalmonitor.h

    old new using namespace std; 
    2626 
    2727inline QString sm_flags_to_string(uint64_t); 
    2828 
     29class TVRec; 
     30 
    2931class SignalMonitor 
    3032{ 
    3133  public: 
    class SignalMonitor 
    3941    // // // // // // // // // // // // // // // // // // // // // // // // 
    4042    // Control  // // // // // // // // // // // // // // // // // // // // 
    4143 
    42     virtual void Start(); 
     44    virtual void Start(bool waitfor_tune); 
    4345    virtual void Stop(); 
    4446    virtual void Kick(); 
    4547    virtual bool WaitForLock(int timeout = -1); 
    class SignalMonitor 
    8385     */ 
    8486    void SetNotifyFrontend(bool notify) { notify_frontend = notify; } 
    8587 
     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 
    8695    /** \brief Sets the number of milliseconds between signal monitoring 
    8796     *         attempts in the signal monitoring thread. 
    8897     * 
    class SignalMonitor 
    108117    static void* SpawnMonitorLoop(void*); 
    109118    virtual void MonitorLoop(); 
    110119 
     120    bool IsChannelTuned(void); 
     121 
    111122    /// \brief This should be overridden to actually do signal monitoring. 
    112123    virtual void UpdateValues() { ; } 
    113124 
    class SignalMonitor 
    139150    /// We've seen something indicating whether the data stream is encrypted 
    140151    static const uint64_t kDTVSigMon_CryptSeen  = 0x0000000200ULL; 
    141152 
     153    static const uint64_t kSigMon_Tuned         = 0x0000000400ULL; 
     154 
    142155    /// We've seen a PAT matching our requirements 
    143156    static const uint64_t kDTVSigMon_PATMatch   = 0x0000001000ULL; 
    144157    /// We've seen a PMT matching our requirements 
    class SignalMonitor 
    184197  protected: 
    185198    pthread_t    monitor_thread; 
    186199    ChannelBase *channel; 
     200    TVRec       *pParent; 
    187201    int          capturecardnum; 
    188202    uint64_t     flags; 
    189203    int          update_rate; 
    class SignalMonitor 
    192206    bool         exit; 
    193207    bool         update_done; 
    194208    bool         notify_frontend; 
     209    bool         is_tuned; 
     210    bool         tablemon; 
     211    bool         eit_scan; 
    195212    QString      error; 
    196213 
    197214    SignalMonitorValue signalLock; 
    198215    SignalMonitorValue signalStrength; 
     216    SignalMonitorValue channelTuned; 
    199217 
    200218    vector<SignalMonitorListener*> listeners; 
    201219 
  • libs/libmythtv/signalmonitorlistener.h

    old new  
    99 
    1010typedef enum { 
    1111    kAllGood, 
     12    kStatusChannelTuned, 
    1213    kStatusSignalLock, 
    1314    kStatusSignalStrength, 
    1415    kStatusSignalToNoise, 
    class MPUBLIC SignalMonitorListener 
    3031     */ 
    3132    virtual void AllGood(void) = 0; 
    3233 
     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 
    3341    /** \brief Signal to be sent as true when it is safe to begin 
    3442     *   or continue recording, and false if it may not be safe. 
    3543     * 
  • libs/libmythtv/tv_play.cpp

    old new void TV::UpdateOSDSignal(const PlayerCon 
    71437143    float snr  = 0.0f; 
    71447144    uint  ber  = 0xffffffff; 
    71457145    int   pos  = -1; 
     7146    int   tuned = -1; 
    71467147    QString pat(""), pmt(""), mgt(""), vct(""), nit(""), sdt(""), crypt(""); 
    71477148    QString err = QString::null, msg = QString::null; 
    71487149    for (it = slist.begin(); it != slist.end(); ++it) 
    void TV::UpdateOSDSignal(const PlayerCon 
    71697170            ber = it->GetValue(); 
    71707171        else if ("pos" == it->GetShortName()) 
    71717172            pos = it->GetValue(); 
     7173        else if ("tuned" == it->GetShortName()) 
     7174            tuned = it->GetValue(); 
    71727175        else if ("seen_pat" == it->GetShortName()) 
    71737176            pat = it->IsGood() ? "a" : "_"; 
    71747177        else if ("matching_pat" == it->GetShortName()) 
    void TV::UpdateOSDSignal(const PlayerCon 
    72027205        infoMap["signal"] = QString::number(sig); // use normalized value 
    72037206 
    72047207    bool    allGood = SignalMonitorValue::AllGood(slist); 
     7208    char    tuneCode; 
    72057209    QString slock   = ("1" == infoMap["slock"]) ? "L" : "l"; 
    72067210    QString lockMsg = (slock=="L") ? tr("Partial Lock") : tr("No Lock"); 
    72077211    QString sigMsg  = allGood ? tr("Lock") : lockMsg; 
    void TV::UpdateOSDSignal(const PlayerCon 
    72147218    if ((pos >= 0) && (pos < 100)) 
    72157219        sigDesc += " | " + tr("Rotor %1\%").arg(pos,2); 
    72167220 
    7217     sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8) %9") 
    7218         .arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct) 
    7219         .arg(nit).arg(sdt).arg(crypt).arg(sigMsg); 
     7221    if (tuned == 1) 
     7222        tuneCode = 't'; 
     7223    else if (tuned == 2) 
     7224        tuneCode = 'F'; 
     7225    else if (tuned == 3) 
     7226        tuneCode = 'T'; 
     7227    else 
     7228        tuneCode = '_'; 
     7229 
     7230    sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8%9) %10") 
     7231              .arg(tuneCode).arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct) 
     7232              .arg(nit).arg(sdt).arg(crypt).arg(sigMsg); 
    72207233 
    72217234    if (!err.isEmpty()) 
    72227235        sigDesc = err; 
  • libs/libmythtv/tv_rec.cpp

    old new ProgramInfo *TVRec::GetRecording(void) 
    368368void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft, 
    369369                          bool hasLater) 
    370370{ 
    371     QMutexLocker lock(&stateChangeLock); 
     371    QMutexLocker statelock(&stateChangeLock); 
     372    QMutexLocker pendlock(&pendingRecLock); 
    372373 
    373374    if (secsleft < 0) 
    374375    { 
    void TVRec::RecordPending(const ProgramI 
    406407 
    407408    pendingRecordings[rcinfo->GetCardID()].possibleConflicts = cardids; 
    408409 
    409     stateChangeLock.unlock(); 
     410    pendlock.unlock(); 
     411    statelock.unlock(); 
    410412    for (uint i = 0; i < cardids.size(); i++) 
    411413        RemoteRecordPending(cardids[i], rcinfo, secsleft, hasLater); 
    412     stateChangeLock.lock(); 
     414    statelock.relock(); 
     415    pendlock.relock(); 
    413416} 
    414417 
    415418/** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*) 
    QDateTime TVRec::GetRecordEndTime(const  
    441444 */ 
    442445void TVRec::CancelNextRecording(bool cancel) 
    443446{ 
     447    QMutexLocker pendlock(&pendingRecLock); 
    444448    VERBOSE(VB_RECORD, LOC + "CancelNextRecording("<<cancel<<") -- begin"); 
    445449 
    446450    PendingMap::iterator it = pendingRecordings.find(cardid); 
    RecStatusType TVRec::StartRecording(cons 
    524528        return retval; 
    525529    } 
    526530 
    527     PendingMap::iterator it = pendingRecordings.find(cardid); 
    528531    bool cancelNext = false; 
    529     if (it != pendingRecordings.end()) 
     532    PendingInfo pendinfo; 
     533    PendingMap::iterator it; 
     534    bool has_pending; 
     535 
     536    pendingRecLock.lock(); 
     537    if ((it = pendingRecordings.find(cardid)) != pendingRecordings.end()) 
    530538    { 
    531539        (*it).ask = (*it).doNotAsk = false; 
    532540        cancelNext = (*it).canceled; 
    533541    } 
     542    pendingRecLock.unlock(); 
    534543 
    535544    // Flush out events... 
    536545    WaitForEventThreadSleep(); 
    RecStatusType TVRec::StartRecording(cons 
    538547    // Rescan pending recordings since the event loop may have deleted 
    539548    // a stale entry.  If this happens the info pointer will not be valid 
    540549    // since the HandlePendingRecordings loop will have deleted it. 
     550    pendingRecLock.lock(); 
    541551    it = pendingRecordings.find(cardid); 
     552    has_pending = (it != pendingRecordings.end()); 
     553    if (has_pending) 
     554        pendinfo = *it; 
     555    pendingRecLock.unlock(); 
    542556 
    543557    // If the needed input is in a shared input group, and we are 
    544558    // not canceling the recording anyway, check other recorders 
    545     if (!cancelNext && 
    546         (it != pendingRecordings.end()) && (*it).possibleConflicts.size()) 
     559    if (!cancelNext && has_pending && pendinfo.possibleConflicts.size()) 
    547560    { 
    548561        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin"); 
    549         vector<uint> &cardids = (*it).possibleConflicts; 
     562        vector<uint> &cardids = pendinfo.possibleConflicts; 
    550563 
    551564        uint mplexid = 0, sourceid = 0; 
    552565        vector<uint> cardids2; 
    RecStatusType TVRec::StartRecording(cons 
    569582 
    570583            if (is_busy && !sourceid) 
    571584            { 
    572                 mplexid  = (*it).info->QueryMplexID(); 
    573                 sourceid = (*it).info->GetSourceID(); 
     585                mplexid  = pendinfo.info->QueryMplexID(); 
     586                sourceid = pendinfo.info->GetSourceID(); 
    574587            } 
    575588 
    576589            if (is_busy && 
    void TVRec::HandleStateChange(void) 
    954967void TVRec::ChangeState(TVState nextState) 
    955968{ 
    956969    QMutexLocker lock(&stateChangeLock); 
    957  
    958970    desiredNextState = nextState; 
    959971    changeState = true; 
    960972    WakeEventLoop(); 
    void TVRec::RunTV(void) 
    14281440            QDateTime now   = QDateTime::currentDateTime(); 
    14291441            bool has_finish = HasFlags(kFlagFinishRecording); 
    14301442            bool has_rec    = pseudoLiveTVRecording; 
     1443            bool enable_ui  = true; 
     1444 
     1445            pendingRecLock.lock(); 
    14311446            bool rec_soon   = 
    14321447                pendingRecordings.find(cardid) != pendingRecordings.end(); 
    1433             bool enable_ui  = true; 
     1448            pendingRecLock.unlock(); 
    14341449 
    14351450            if (has_rec && (has_finish || (now > recordEndTime))) 
    14361451            { 
    bool TVRec::WaitForEventThreadSleep(bool 
    16031618 
    16041619void TVRec::HandlePendingRecordings(void) 
    16051620{ 
     1621    QMutexLocker pendlock(&pendingRecLock); 
     1622 
    16061623    if (pendingRecordings.empty()) 
    16071624        return; 
    16081625 
    bool ApplyCachedPids(DTVSignalMonitor *d 
    18921909 *   This method also grabs the ATSCStreamData() from the recorder 
    18931910 *   if possible, or creates one if needed. 
    18941911 */ 
    1895 bool TVRec::SetupDTVSignalMonitor(void) 
     1912bool TVRec::SetupDTVSignalMonitor(bool EITscan) 
    18961913{ 
    18971914    VERBOSE(VB_RECORD, LOC + "Setting up table monitoring."); 
    18981915 
    bool TVRec::SetupDTVSignalMonitor(void) 
    20262043                     SignalMonitor::kDVBSigMon_WaitForPos); 
    20272044        sm->SetRotorTarget(1.0f); 
    20282045 
     2046        if (EITscan) 
     2047        { 
     2048            sm->GetStreamData()->SetVideoStreamsRequired(0); 
     2049            sm->IgnoreEncrypted(true); 
     2050        } 
     2051 
    20292052        VERBOSE(VB_RECORD, LOC + "Successfully set up MPEG table monitoring."); 
    20302053        return true; 
    20312054    } 
    bool TVRec::SetupDTVSignalMonitor(void) 
    20472070 *  \param notify   If set we notify the frontend of the signal values 
    20482071 *  \return true on success, false on failure 
    20492072 */ 
    2050 bool TVRec::SetupSignalMonitor(bool tablemon, bool notify) 
     2073bool TVRec::SetupSignalMonitor(bool tablemon, bool EITscan, bool notify) 
    20512074{ 
    20522075    VERBOSE(VB_RECORD, LOC + "SetupSignalMonitor(" 
    20532076            <<tablemon<<", "<<notify<<")"); 
    bool TVRec::SetupSignalMonitor(bool tabl 
    20632086    // make sure statics are initialized 
    20642087    SignalMonitorValue::Init(); 
    20652088 
    2066     if (SignalMonitor::IsSupported(genOpt.cardtype) && channel->Open()) 
    2067         signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, channel); 
     2089    if (channel->Open()) 
     2090        signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, 
     2091                                            channel); 
    20682092 
    20692093    if (signalMonitor) 
    20702094    { 
    20712095        VERBOSE(VB_RECORD, LOC + "Signal monitor successfully created"); 
    2072         // If this is a monitor for Digital TV, initialize table monitors 
    2073         if (GetDTVSignalMonitor() && tablemon && !SetupDTVSignalMonitor()) 
    2074         { 
    2075             VERBOSE(VB_IMPORTANT, LOC_ERR + 
    2076                     "Failed to setup digital signal monitoring"); 
    2077  
    2078             return false; 
    2079         } 
    20802096 
     2097        signalMonitor->SetMonitoring(this, EITscan, 
     2098                                     GetDTVSignalMonitor() && tablemon); 
    20812099        signalMonitor->AddListener(this); 
    20822100        signalMonitor->SetUpdateRate(kSignalMonitoringRate); 
    20832101        signalMonitor->SetNotifyFrontend(notify); 
    20842102 
    20852103        // Start the monitoring thread 
    2086         signalMonitor->Start(); 
     2104        signalMonitor->Start(true); 
    20872105    } 
    20882106 
    20892107    return true; 
    bool TVRec::IsReallyRecording(void) 
    24882506 */ 
    24892507bool TVRec::IsBusy(TunedInputInfo *busy_input, int time_buffer) const 
    24902508{ 
    2491     QMutexLocker lock(&stateChangeLock); 
    2492  
    24932509    TunedInputInfo dummy; 
    24942510    if (!busy_input) 
    24952511        busy_input = &dummy; 
    bool TVRec::IsBusy(TunedInputInfo *busy_ 
    25112527        chanid              = channel->GetChanID(); 
    25122528    } 
    25132529 
    2514     PendingMap::const_iterator it = pendingRecordings.find(cardid); 
    2515     if (!busy_input->inputid && (it != pendingRecordings.end())) 
     2530    PendingInfo pendinfo; 
     2531    bool        has_pending; 
     2532    { 
     2533        pendingRecLock.lock(); 
     2534        PendingMap::const_iterator it = pendingRecordings.find(cardid); 
     2535        has_pending = (it != pendingRecordings.end()); 
     2536        if (has_pending) 
     2537            pendinfo = *it; 
     2538        pendingRecLock.unlock(); 
     2539    } 
     2540 
     2541    if (!busy_input->inputid && has_pending) 
    25162542    { 
    25172543        int timeLeft = QDateTime::currentDateTime() 
    2518             .secsTo((*it).recordingStart); 
     2544            .secsTo(pendinfo.recordingStart); 
    25192545 
    25202546        if (timeLeft <= time_buffer) 
    25212547        { 
    25222548            QString channum = QString::null, input = QString::null; 
    2523             if ((*it).info->QueryTuningInfo(channum, input)) 
     2549            if (pendinfo.info->QueryTuningInfo(channum, input)) 
    25242550            { 
    25252551                busy_input->inputid = channel->GetInputByName(input); 
    2526                 chanid = (*it).info->GetChanID(); 
     2552                chanid = pendinfo.info->GetChanID(); 
    25272553            } 
    25282554        } 
    25292555    } 
    void TVRec::TuningShutdowns(const Tuning 
    36673693void TVRec::TuningFrequency(const TuningRequest &request) 
    36683694{ 
    36693695    DTVChannel *dtvchan = GetDTVChannel(); 
     3696 
     3697    bool livetv = request.flags & kFlagLiveTV; 
     3698    bool antadj = request.flags & kFlagAntennaAdjust; 
     3699    bool has_dummy = false; 
     3700 
    36703701    if (dtvchan) 
    36713702    { 
    36723703        MPEGStreamData *mpeg = NULL; 
    void TVRec::TuningFrequency(const Tuning 
    36833714 
    36843715        if (request.minorChan && (tuningmode == "atsc")) 
    36853716        { 
    3686             channel->SetChannelByString(request.channel); 
    3687  
     3717            channel->SelectChannel(request.channel); 
    36883718            ATSCStreamData *atsc = dynamic_cast<ATSCStreamData*>(mpeg); 
    36893719            if (atsc) 
    36903720                atsc->SetDesiredChannel(request.majorChan, request.minorChan); 
    36913721        } 
    36923722        else if (request.progNum >= 0) 
    36933723        { 
    3694             channel->SetChannelByString(request.channel); 
    3695  
     3724            channel->SelectChannel(request.channel); 
    36963725            if (mpeg) 
    36973726                mpeg->SetDesiredProgram(request.progNum); 
    36983727        } 
    void TVRec::TuningFrequency(const Tuning 
    37213750    if (channel && !channum.isEmpty()) 
    37223751    { 
    37233752        if (!input.isEmpty()) 
    3724             ok = channel->SwitchToInput(input, channum); 
     3753            ok = channel->SelectInput(input, channum, true); 
    37253754        else 
    3726             ok = channel->SetChannelByString(channum); 
     3755        { 
     3756            channel->SelectChannel(channum); 
     3757            ok = true; 
     3758        } 
    37273759    } 
    37283760 
    37293761    if (!ok) 
    void TVRec::TuningFrequency(const Tuning 
    37503782        } 
    37513783    } 
    37523784 
    3753     bool livetv = request.flags & kFlagLiveTV; 
    3754     bool antadj = request.flags & kFlagAntennaAdjust; 
    3755     bool use_sm = SignalMonitor::IsRequired(genOpt.cardtype); 
    3756     bool use_dr = use_sm && (livetv || antadj); 
    3757     bool has_dummy = false; 
    3758  
    3759     if (use_dr) 
     3785    if (livetv || antadj) 
    37603786    { 
    37613787        // We need there to be a ringbuffer for these modes 
    37623788        bool ok; 
    void TVRec::TuningFrequency(const Tuning 
    37823808        has_dummy = true; 
    37833809    } 
    37843810 
    3785     // Start signal monitoring for devices capable of monitoring 
    3786     if (use_sm) 
     3811    // Start signal (or channel change) monitoring 
     3812    VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor"); 
     3813    bool error = false; 
     3814    if (!SetupSignalMonitor(!antadj, request.flags & kFlagEITScan, 
     3815                            livetv | antadj)) 
    37873816    { 
    3788         VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor"); 
    3789         bool error = false; 
    3790         if (!SetupSignalMonitor(!antadj, livetv | antadj)) 
    3791         { 
    3792             VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor"); 
    3793             if (signalMonitor) 
    3794             { 
    3795                 delete signalMonitor; 
    3796                 signalMonitor = NULL; 
    3797             } 
    3798  
    3799             // pretend the signal monitor is running to prevent segfault 
    3800             SetFlags(kFlagSignalMonitorRunning); 
    3801             ClearFlags(kFlagWaitingForSignal); 
    3802             error = true; 
    3803         } 
    3804  
     3817        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor"); 
    38053818        if (signalMonitor) 
    38063819        { 
    3807             if (request.flags & kFlagEITScan) 
    3808             { 
    3809                 GetDTVSignalMonitor()->GetStreamData()-> 
    3810                     SetVideoStreamsRequired(0); 
    3811                 GetDTVSignalMonitor()->IgnoreEncrypted(true); 
    3812             } 
    3813  
    3814             SetFlags(kFlagSignalMonitorRunning); 
    3815             ClearFlags(kFlagWaitingForSignal); 
    3816             if (!antadj) 
    3817                 SetFlags(kFlagWaitingForSignal); 
     3820            delete signalMonitor; 
     3821            signalMonitor = NULL; 
    38183822        } 
    38193823 
    3820         if (has_dummy && ringBuffer) 
    3821         { 
    3822             // Make sure recorder doesn't point to bogus ringbuffer before 
    3823             // it is potentially restarted without a new ringbuffer, if 
    3824             // the next channel won't tune and the user exits LiveTV. 
    3825             if (recorder) 
    3826                 recorder->SetRingBuffer(NULL); 
     3824        // pretend the signal monitor is running to prevent segfault 
     3825        SetFlags(kFlagSignalMonitorRunning); 
     3826        ClearFlags(kFlagWaitingForSignal); 
     3827        error = true; 
     3828    } 
    38273829 
    3828             SetFlags(kFlagDummyRecorderRunning); 
    3829             VERBOSE(VB_RECORD, "DummyDTVRecorder -- started"); 
    3830             SetFlags(kFlagRingBufferReady); 
    3831         } 
     3830    if (signalMonitor) 
     3831    { 
     3832        SetFlags(kFlagSignalMonitorRunning); 
     3833        ClearFlags(kFlagWaitingForSignal); 
     3834        if (!antadj) 
     3835            SetFlags(kFlagWaitingForSignal); 
     3836    } 
    38323837 
    3833         // if we had problems starting the signal monitor, 
    3834         // we don't want to start the recorder... 
    3835         if (error) 
    3836             return; 
     3838    if (has_dummy && ringBuffer) 
     3839    { 
     3840        // Make sure recorder doesn't point to bogus ringbuffer before 
     3841        // it is potentially restarted without a new ringbuffer, if 
     3842        // the next channel won't tune and the user exits LiveTV. 
     3843        if (recorder) 
     3844            recorder->SetRingBuffer(NULL); 
     3845 
     3846        SetFlags(kFlagDummyRecorderRunning); 
     3847        VERBOSE(VB_RECORD, "DummyDTVRecorder -- started"); 
     3848        SetFlags(kFlagRingBufferReady); 
    38373849    } 
    38383850 
     3851    // if we had problems starting the signal monitor, 
     3852    // we don't want to start the recorder... 
     3853    if (error) 
     3854        return; 
     3855 
    38393856    // Request a recorder, if the command is a recording command 
    38403857    ClearFlags(kFlagNeedToStartRecorder); 
    38413858    if (request.flags & kFlagRec && !antadj) 
  • libs/libmythtv/tv_rec.h

    old new typedef QMap<uint,PendingInfo> PendingMa 
    137137class MPUBLIC TVRec : public SignalMonitorListener 
    138138{ 
    139139    friend class TuningRequest; 
     140    friend class SignalMonitor; 
    140141 
    141142  public: 
    142143    TVRec(int capturecardnum); 
    class MPUBLIC TVRec : public SignalMonit 
    231232    static TVRec *GetTVRec(uint cardid); 
    232233 
    233234    virtual void AllGood(void) { WakeEventLoop(); } 
     235    virtual void StatusChannelTuned(const SignalMonitorValue&) { } 
    234236    virtual void StatusSignalLock(const SignalMonitorValue&) { } 
    235237    virtual void StatusSignalStrength(const SignalMonitorValue&) { } 
    236238 
    class MPUBLIC TVRec : public SignalMonit 
    239241    bool WaitForEventThreadSleep(bool wake = true, ulong time = ULONG_MAX); 
    240242    static void *EventThread(void *param); 
    241243    static void *RecorderThread(void *param); 
     244    bool SetupDTVSignalMonitor(bool EITscan); 
    242245 
    243246  private: 
    244247    void SetRingBuffer(RingBuffer *); 
    class MPUBLIC TVRec : public SignalMonit 
    268271    FirewireChannel *GetFirewireChannel(void); 
    269272    V4LChannel   *GetV4LChannel(void); 
    270273 
    271     bool SetupSignalMonitor(bool enable_table_monitoring, bool notify); 
    272     bool SetupDTVSignalMonitor(void); 
     274    bool SetupSignalMonitor(bool enable_table_monitoring, 
     275                            bool EITscan, bool notify); 
    273276    void TeardownSignalMonitor(void); 
    274277    DTVSignalMonitor *GetDTVSignalMonitor(void); 
    275278 
    class MPUBLIC TVRec : public SignalMonit 
    347350 
    348351    // State variables 
    349352    mutable QMutex stateChangeLock; 
     353    mutable QMutex pendingRecLock; 
    350354    TVState        internalState; 
    351355    TVState        desiredNextState; 
    352356    bool           changeState; 
  • libs/libmythtv/v4lchannel.cpp

    old new bool V4LChannel::SetChannelByString(cons 
    441441    // change inputs and return, since the act of changing 
    442442    // inputs will change the channel as well. 
    443443    if (!inputName.isEmpty()) 
    444         return ChannelBase::SwitchToInput(inputName, channum); 
     444        return ChannelBase::SelectInput(inputName, channum, false); 
    445445 
    446446    ClearDTVInfo(); 
    447447 
  • libs/libmythtv/v4lchannel.h

    old new class V4LChannel : public DTVChannel 
    5353    QString GetSIStandard(void) const { return "atsc"; } 
    5454 
    5555    // Commands 
    56     bool SwitchToInput(int newcapchannel, bool setstarting); 
    5756    bool Retune(void); 
    5857 
    5958    // Picture attributes. 
    class V4LChannel : public DTVChannel 
    7372    bool Tune(uint frequency, QString inputname, 
    7473              QString modulation, QString si_std); 
    7574 
     75  protected: 
     76    bool SwitchToInput(int newcapchannel, bool setstarting); 
     77 
    7678  private: 
    7779    // Helper Sets 
    7880    void SetFreqTable(const int index);