Ticket #6719: channel-thread-v1.5.patch

File channel-thread-v1.5.patch, 49.3 KB (added by hansonorders@…, 2 years ago)

channel-thread-patch for 22890

  • libs/libmythtv/analogsignalmonitor.cpp

    old new void AnalogSignalMonitor::UpdateValues(v 
    3131    int videofd = channel->GetFd(); 
    3232    if (videofd < 0) 
    3333        return; 
    3434 
     35    if (!IsChannelTuned()) 
     36        return; 
     37 
    3538    bool isLocked = false; 
    3639    if (usingv4l2) 
    3740    { 
    3841        struct v4l2_tuner tuner; 
  • libs/libmythtv/channelbase.cpp

    old new using namespace std; 
    3434#define LOC QString("ChannelBase(%1): ").arg(GetCardID()) 
    3535#define LOC_WARN QString("ChannelBase(%1) Warning: ").arg(GetCardID()) 
    3636#define LOC_ERR QString("ChannelBase(%1) Error: ").arg(GetCardID()) 
    3737 
     38/* 
     39 * Run the channel change thread, and report the status when done 
     40 */ 
     41void ChannelThread::run(void) 
     42{ 
     43    bool result = tuner->SetChannelByString(channel); 
     44    tuner->setStatus(result ? 
     45                     ChannelBase::changeSuccess : ChannelBase::changeFailed); 
     46} 
     47 
    3848ChannelBase::ChannelBase(TVRec *parent) 
    3949    : 
    4050    pParent(parent), curchannelname(""), 
    41     currentInputID(-1), commfree(false), cardid(0) 
     51    currentInputID(-1), commfree(false), cardid(0), 
     52    abort_change(false) 
    4253{ 
     54    tuneStatus = changeUnknown; 
     55    tuneThread.tuner = this; 
    4356} 
    4457 
    4558ChannelBase::~ChannelBase(void) 
    4659{ 
     60    TeardownAll(); 
     61} 
     62 
     63void ChannelBase::TeardownAll(void) 
     64{ 
     65    if (tuneThread.isRunning()) 
     66    { 
     67        thread_lock.lock(); 
     68        abort_change = true; 
     69        tuneCond.wakeAll(); 
     70        thread_lock.unlock(); 
     71        tuneThread.wait(); 
     72    } 
     73} 
     74 
     75void ChannelBase::SelectChannel(const QString & chan) 
     76{ 
     77    VERBOSE(VB_CHANNEL, LOC + "SelectChannel " + chan); 
     78    TeardownAll(); 
     79 
     80    thread_lock.lock(); 
     81    abort_change = false; 
     82    tuneStatus = changePending; 
     83    thread_lock.unlock(); 
     84 
     85    curchannelname = tuneThread.channel = chan; 
     86    tuneThread.start(); 
     87} 
     88 
     89/* 
     90 * Returns true of the channel change thread should abort 
     91 */ 
     92bool ChannelBase::Aborted(void) 
     93{ 
     94    bool       result; 
     95 
     96    thread_lock.lock(); 
     97    result = abort_change; 
     98    thread_lock.unlock(); 
     99 
     100    return result; 
     101} 
     102 
     103ChannelBase::Status ChannelBase::GetStatus(void) 
     104{ 
     105    Status status; 
     106 
     107    thread_lock.lock(); 
     108    status = tuneStatus; 
     109    thread_lock.unlock(); 
     110 
     111    return status; 
     112} 
     113 
     114ChannelBase::Status ChannelBase::Wait(void) 
     115{ 
     116    tuneThread.wait(); 
     117    return tuneStatus; 
     118} 
     119 
     120void ChannelBase::setStatus(ChannelBase::Status status) 
     121{ 
     122    thread_lock.lock(); 
     123    tuneStatus = status; 
     124    thread_lock.unlock(); 
    47125} 
    48126 
    49127bool ChannelBase::Init(QString &inputname, QString &startchannel, bool setchan) 
    50128{ 
    51129    bool ok; 
    52130 
     131    VERBOSE(VB_CHANNEL, LOC + QString("Init(%1, %2, %3)") 
     132            .arg(inputname).arg(startchannel).arg(setchan)); 
     133 
    53134    if (!setchan) 
    54135        ok = inputname.isEmpty() ? false : IsTunable(inputname, startchannel); 
    55136    else if (inputname.isEmpty()) 
    56         ok = SetChannelByString(startchannel); 
     137    { 
     138        SelectChannel(startchannel); 
     139        ok = Wait(); 
     140    } 
    57141    else 
    58142        ok = SwitchToInput(inputname, startchannel); 
    59143 
    60144    if (ok) 
    bool ChannelBase::Init(QString &inputnam 
    123207 
    124208            if (chanid && cit != channels.end()) 
    125209            { 
    126210                if (!setchan) 
    127                 { 
    128211                    ok = IsTunable(*it, (mplexid_restriction) ? 
    129212                                   (*cit).channum : startchannel); 
    130                 } 
    131213                else 
    132214                    ok = SwitchToInput(*it, (*cit).channum); 
    133215 
    134216                if (ok) 
    int ChannelBase::GetInputByName(const QS 
    328410    } 
    329411    return -1; 
    330412} 
    331413 
     414#if 0 // Not used? 
    332415bool ChannelBase::SwitchToInput(const QString &inputname) 
    333416{ 
    334417    int input = GetInputByName(inputname); 
    335418 
    bool ChannelBase::SwitchToInput(const QS 
    339422        VERBOSE(VB_IMPORTANT, QString("ChannelBase: Could not find input: " 
    340423                                      "%1 on card\n").arg(inputname)); 
    341424    return false; 
    342425} 
     426#endif 
     427 
     428bool ChannelBase::SelectInput(const QString &inputname, const QString &chan) 
     429{ 
     430    int input = GetInputByName(inputname); 
     431 
     432    VERBOSE(VB_CHANNEL, LOC + QString("SelectInput(%1, %2) %3") 
     433            .arg(inputname).arg(chan).arg(input)); 
     434 
     435    if (input >= 0) 
     436    { 
     437        if (!SwitchToInput(input, false)) 
     438            return false; 
     439        SelectChannel(chan); 
     440    } 
     441    else 
     442    { 
     443        VERBOSE(VB_IMPORTANT, 
     444                QString("ChannelBase: Could not find input: %1 on card when " 
     445                        "setting channel %2\n").arg(inputname).arg(chan)); 
     446        return false; 
     447    } 
     448 
     449    return true; 
     450} 
    343451 
    344452bool ChannelBase::SwitchToInput(const QString &inputname, const QString &chan) 
    345453{ 
    346454    int input = GetInputByName(inputname); 
    347455 
    348     bool ok = false; 
     456    VERBOSE(VB_CHANNEL, LOC + QString("SwitchToInput(%1, %2), %3") 
     457            .arg(inputname).arg(chan).arg(input)); 
     458 
    349459    if (input >= 0) 
    350460    { 
    351         ok = SwitchToInput(input, false); 
    352         if (ok) 
    353             ok = SetChannelByString(chan); 
     461        if (!SwitchToInput(input, false)) 
     462            return false; 
     463        return SetChannelByString(chan); 
    354464    } 
    355465    else 
    356466    { 
    357467        VERBOSE(VB_IMPORTANT, 
    358468                QString("ChannelBase: Could not find input: %1 on card when " 
    359469                        "setting channel %2\n").arg(inputname).arg(chan)); 
     470        return false; 
    360471    } 
    361     return ok; 
     472 
     473    return true; 
    362474} 
    363475 
    364476bool ChannelBase::SwitchToInput(int newInputNum, bool setstarting) 
    365477{ 
     478    VERBOSE(VB_CHANNEL, LOC + QString("SwitchToInput(%1, %2)") 
     479            .arg(newInputNum).arg(setstarting)); 
     480 
    366481    InputMap::const_iterator it = inputs.find(newInputNum); 
    367482    if (it == inputs.end() || (*it)->startChanNum.isEmpty()) 
    368483        return false; 
    369484 
    bool ChannelBase::SwitchToInput(int newI 
    373488 
    374489    // input switching code would go here 
    375490 
    376491    if (setstarting) 
    377         return SetChannelByString((*it)->startChanNum); 
     492        SelectChannel((*it)->startChanNum); 
    378493 
    379494    return true; 
    380495} 
    381496 
    static bool is_input_busy( 
    484599    } 
    485600    return is_busy; 
    486601} 
    487602 
    488 bool ChannelBase::IsInputAvailable( 
    489     int inputid, uint &mplexid_restriction) const 
     603bool ChannelBase::IsInputAvailable(int inputid, uint &mplexid_restriction) const 
    490604{ 
    491605    if (inputid < 0) 
    492606        return false; 
    493607 
    bool ChannelBase::ChangeExternalChannel( 
    650764        _exit(CHANNEL__EXIT__EXECL_ERROR); // this exit is ok 
    651765    } 
    652766    else 
    653767    {   // child contains the pid of the new process 
    654         int status = 0, pid = 0; 
     768        QMutex      lock; 
     769        int         status = 0, pid = 0; 
     770 
    655771        VERBOSE(VB_CHANNEL, "Waiting for External Tuning program to exit"); 
    656772 
    657773        bool timed_out = false; 
    658774        uint timeout = 30; // how long to wait in seconds 
    659775        time_t start_time = time(0); 
    660         while (-1 != pid && !timed_out) 
     776        while (-1 != pid && !timed_out && !Aborted()) 
    661777        { 
    662             sleep(1); 
     778            lock.lock(); 
     779            tuneCond.wait(&lock, 500);  // sleep up to 0.5 seconds 
    663780            pid = waitpid(child, &status, WUNTRACED|WNOHANG); 
    664781            VERBOSE(VB_IMPORTANT, QString("ret_pid(%1) child(%2) status(0x%3)") 
    665782                    .arg(pid).arg(child).arg(status,0,16)); 
    666783            if (pid==child) 
     784            { 
     785                lock.unlock(); 
    667786                break; 
     787            } 
    668788            else if (time(0) > (time_t)(start_time + timeout)) 
    669789                timed_out = true; 
     790            lock.unlock(); 
    670791        } 
    671         if (timed_out) 
     792 
     793        if (timed_out || Aborted()) 
    672794        { 
    673             VERBOSE(VB_IMPORTANT, "External Tuning program timed out, killing"); 
     795            if (Aborted()) 
     796                VERBOSE(VB_IMPORTANT, "Aborting External Tuning program"); 
     797            else 
     798                VERBOSE(VB_IMPORTANT, "External Tuning program timed out, " 
     799                        "killing"); 
    674800            kill(child, SIGTERM); 
    675801            usleep(500); 
    676802            kill(child, SIGKILL); 
    677803            return false; 
  • libs/libmythtv/channelbase.h

    old new  
    55 
    66// Qt headers 
    77#include <qmap.h> 
    88#include <qstringlist.h> 
     9#include <qwaitcondition.h> 
     10#include <qmutex.h> 
     11#include <qthread.h> 
    912 
    1013// MythTV headers 
    1114#include "channelutil.h" 
    1215#include "inputinfo.h" 
    1316#include "tv.h" 
    1417 
    1518class TVRec; 
     19class ChannelBase; 
     20 
     21/* 
     22 * Thread to run tunning process in 
     23 */ 
     24class ChannelThread : public QThread 
     25{ 
     26  public: 
     27    virtual void run(void); 
     28 
     29    QString      channel; 
     30    ChannelBase *tuner; 
     31}; 
    1632 
    1733/** \class ChannelBase 
    1834 *  \brief Abstract class providing a generic interface to tuning hardware. 
    1935 * 
    class TVRec; 
    2339 */ 
    2440 
    2541class ChannelBase 
    2642{ 
    27  public: 
     43    friend class ChannelThread; 
     44 
     45  public: 
     46    enum Status { changeUnknown = 'U', changePending = 'P', 
     47                  changeFailed = 'F', changeSuccess = 'S' }; 
     48 
    2849    ChannelBase(TVRec *parent); 
    29     virtual ~ChannelBase(); 
     50    virtual ~ChannelBase(void); 
    3051 
    3152    virtual bool Init(QString &inputname, QString &startchannel, bool setchan); 
    3253    virtual bool IsTunable(const QString &input, const QString &channum) const; 
    3354 
     55    virtual void SelectChannel(const QString & chan); 
     56 
     57    Status GetStatus(void); 
     58    Status Wait(void); 
     59 
    3460    // Methods that must be implemented. 
    3561    /// \brief Opens the channel changing hardware for use. 
    3662    virtual bool Open(void) = 0; 
    3763    /// \brief Closes the channel changing hardware to use. 
    3864    virtual void Close(void) = 0; 
    39     virtual bool SetChannelByString(const QString &chan) = 0; 
    4065    /// \brief Reports whether channel is already open 
    4166    virtual bool IsOpen(void) const = 0; 
    4267 
    4368    // Methods that one might want to specialize 
    class ChannelBase 
    82107    virtual void Renumber(uint srcid, const QString &oldChanNum, 
    83108                          const QString &newChanNum); 
    84109 
    85110    // Input toggling convenience methods 
    86     virtual bool SwitchToInput(const QString &input); 
    87     virtual bool SwitchToInput(const QString &input, const QString &chan); 
     111 
     112//    virtual bool SwitchToInput(const QString &input); // not used? 
     113    virtual bool SelectInput(const QString &input, const QString &chan); 
    88114 
    89115    virtual bool InitializeInputs(void); 
    90116 
    91117    // Misc. Commands 
    class ChannelBase 
    108134    void SetCardID(uint _cardid) { cardid = _cardid; } 
    109135 
    110136    virtual int GetCardID(void) const; 
    111137  protected: 
     138    virtual bool SetChannelByString(const QString &chan) = 0; 
     139 
    112140    /// \brief Switches to another input on hardware,  
    113141    ///        and sets the channel is setstarting is true. 
     142    virtual bool SwitchToInput(const QString &input, const QString &chan); 
    114143    virtual bool SwitchToInput(int inputNum, bool setstarting); 
    115144    virtual bool IsInputAvailable( 
    116145        int inputNum, uint &mplexid_restriction) const; 
    117146 
    118147    virtual bool ChangeExternalChannel(const QString &newchan); 
    119148    static void StoreInputChannels(const InputMap&); 
    120149    static void StoreDefaultInput(uint cardid, const QString &input); 
    121150 
     151    bool Aborted(); 
     152    void setStatus(Status status); 
     153    void TeardownAll(void); 
     154 
    122155    TVRec   *pParent; 
    123156    QString  curchannelname; 
    124157    int      currentInputID; 
    125158    bool     commfree; 
    126159    uint     cardid; 
    127160    InputMap inputs; 
    128161    DBChanList allchannels; ///< channels across all inputs 
     162 
     163    QWaitCondition  tuneCond; 
     164 
     165  private: 
     166    mutable ChannelThread   tuneThread; 
     167    Status   tuneStatus; 
     168    QMutex   thread_lock; 
     169    bool     abort_change; 
    129170}; 
    130171 
    131172#endif 
    132173 
  • 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 
     15ChannelChangeMonitor::ChannelChangeMonitor( 
     16    int db_cardnum, V4LChannel *_channel, uint64_t _flags) : 
     17    SignalMonitor(db_cardnum, _channel, _flags) 
     18{ 
     19} 
     20 
     21void 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 
     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  
    15011501        GetDTVSignalMonitor()->SetChannel(-1,-1); 
    15021502    } 
    15031503 
    15041504    // Start signal monitor for this channel 
    1505     signalMonitor->Start(); 
     1505    signalMonitor->Start(false); 
    15061506 
    15071507    timer.start(); 
    15081508    waitingForTables = true; 
    15091509} 
  • libs/libmythtv/channelscan/channelscan_sm.h

    old new class AnalogSignalHandler : public Signa 
    7373    AnalogSignalHandler(ChannelScanSM *_siscan) : siscan(_siscan) { } 
    7474 
    7575  public slots: 
    7676    virtual inline void AllGood(void); 
     77    virtual void StatusChannelTuned(const SignalMonitorValue&) { } 
    7778    virtual void StatusSignalLock(const SignalMonitorValue&) { } 
    7879    virtual void StatusSignalStrength(const SignalMonitorValue&) { } 
    7980 
    8081  private: 
  • libs/libmythtv/channelscan/channelscanner_cli.cpp

    old new void ChannelScannerCLI::HandleEvent(cons 
    9191            status_complete = scanEvent->intValue(); 
    9292            break; 
    9393        case ScannerEvent::SetStatusRotorPosition: 
    9494            break; 
     95        case ScannerEvent::SetStatusChannelTuned: 
     96            break; 
    9597        case ScannerEvent::SetStatusSignalLock: 
    9698            status_lock = scanEvent->intValue(); 
    9799            break; 
    98100        case ScannerEvent::SetStatusSignalToNoise: 
  • libs/libmythtv/channelscan/channelscanner_gui.cpp

    old new void ChannelScannerGUI::HandleEvent(cons 
    155155            break; 
    156156        case ScannerEvent::SetStatusRotorPosition: 
    157157            scanStage->SetStatusRotorPosition(scanEvent->intValue()); 
    158158            break; 
     159        case ScannerEvent::SetStatusChannelTuned: 
     160            break; 
    159161        case ScannerEvent::SetStatusSignalLock: 
    160162            scanStage->SetStatusLock(scanEvent->intValue()); 
    161163            break; 
    162164        case ScannerEvent::SetStatusSignalToNoise: 
  • libs/libmythtv/channelscan/scanmonitor.cpp

    old new void ScanMonitor::StatusRotorPosition(co 
    106106    post_event(this, ScannerEvent::SetStatusRotorPosition, 
    107107               val.GetNormalizedValue(0, 65535)); 
    108108} 
    109109 
     110void ScanMonitor::StatusChannelTuned(const SignalMonitorValue &val) 
     111{ 
     112    post_event(this, ScannerEvent::SetStatusChannelTuned, val.GetValue()); 
     113} 
     114 
    110115void ScanMonitor::StatusSignalLock(const SignalMonitorValue &val) 
    111116{ 
    112117    post_event(this, ScannerEvent::SetStatusSignalLock, val.GetValue()); 
    113118} 
  • libs/libmythtv/channelscan/scanmonitor.h

    old new class ScanMonitor : 
    6363    void ScanComplete(void); 
    6464 
    6565    // SignalMonitorListener 
    6666    virtual void AllGood(void) { } 
     67    virtual void StatusChannelTuned(const SignalMonitorValue&); 
    6768    virtual void StatusSignalLock(const SignalMonitorValue&); 
    6869    virtual void StatusSignalStrength(const SignalMonitorValue&); 
    6970 
    7071    // DVBSignalMonitorListener 
    class ScannerEvent : public QEvent 
    9798        SetStatusRotorPosition, 
    9899        SetStatusSignalToNoise, 
    99100        SetStatusSignalStrength, 
    100101        SetStatusSignalLock, 
     102        SetStatusChannelTuned 
    101103    }; 
    102104 
    103105    ScannerEvent(TYPE t) : 
    104106        QEvent((QEvent::Type)(t + QEvent::User)), 
  • libs/libmythtv/dtvsignalmonitor.cpp

    old new DTVSignalMonitor::DTVSignalMonitor(int d 
    2424                                   DTVChannel *_channel, 
    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), 
    3132      seenVCT(QObject::tr("Seen")+" VCT", "seen_vct", 1, true, 0, 1, 0), 
    DTVChannel *DTVSignalMonitor::GetDTVChan 
    6263QStringList DTVSignalMonitor::GetStatusList(bool kick) 
    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    { 
    6977        list<<seenPAT.GetName()<<seenPAT.GetStatus(); 
    void DTVSignalMonitor::RemoveFlags(uint6 
    137145 
    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); 
    144153    seenVCT.SetValue(    (flags & kDTVSigMon_VCTSeen)  ? 1 : 0); 
  • libs/libmythtv/dtvsignalmonitor.h

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

    old new void DVBSignalMonitor::UpdateValues(void 
    229229        update_done = true; 
    230230        return; 
    231231    } 
    232232 
     233    if (!IsChannelTuned()) 
     234        return; 
     235 
    233236    AddFlags(kSigMon_WaitForSig); 
    234237  
    235238    DVBChannel *dvbchannel = GetDVBChannel(); 
    236239    if (!dvbchannel) 
  • libs/libmythtv/firewiresignalmonitor.cpp

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

    old new bool HDHRChannel::SetChannelByString(con 
    142142    uint mplexid_restriction; 
    143143    if (!IsInputAvailable(currentInputID, mplexid_restriction)) 
    144144        return false; 
    145145 
     146    if (Aborted()) 
     147        return false; 
     148 
    146149    // Fetch tuning data from the database. 
    147150    QString tvformat, modulation, freqtable, freqid, si_std; 
    148151    int finetune; 
    149152    uint64_t frequency; 
  • libs/libmythtv/hdhrsignalmonitor.cpp

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

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

    old new using_backend { 
    449449        DEFINES += USING_OSS 
    450450        LIBS += $$OSS_LIBS 
    451451    } 
    452452 
     453    HEADERS += channelchangemonitor.h 
     454    SOURCES += channelchangemonitor.cpp 
     455 
    453456    # Support for Video4Linux devices 
    454457    using_v4l { 
    455458        HEADERS += v4lchannel.h                analogsignalmonitor.h 
    456459        SOURCES += v4lchannel.cpp              analogsignalmonitor.cpp 
  • libs/libmythtv/signalmonitor.cpp

    old new  
    77#include <unistd.h> 
    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" 
    1415 
    extern "C" { 
    4142#   include "firewiresignalmonitor.h" 
    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); 
    4851 
    SignalMonitor *SignalMonitor::Init(QStri 
    9295    } 
    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") 
    108112    { 
    SignalMonitor *SignalMonitor::Init(QStri 
    131135#endif 
    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)); 
    138149    } 
    SignalMonitor::SignalMonitor(int _captur 
    159170      capturecardnum(_capturecardnum), flags(wait_for_mask), 
    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} 
    171184 
    bool SignalMonitor::HasAnyFlag(uint64_t  
    201214 
    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( 
    213230                &monitor_thread, NULL, SpawnMonitorLoop, this); 
    QStringList SignalMonitor::GetStatusList 
    278295        UpdateValues(); 
    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(); 
    285303    statusLock.unlock(); 
    void SignalMonitor::MonitorLoop() 
    305323        { 
    306324            QStringList slist = GetStatusList(false); 
    307325            MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist); 
    308326            gContext->dispatch(me); 
    309             //cerr<<"sent SIGNAL"<<endl; 
    310327        } 
    311328 
    312329        usleep(update_rate * 1000); 
    313330    } 
    void SignalMonitor::SendMessage( 
    440457            break; 
    441458        case kStatusSignalStrength: 
    442459            listener->StatusSignalStrength(val); 
    443460            break; 
     461        case kStatusChannelTuned: 
     462            listener->StatusChannelTuned(val); 
     463            break; 
    444464        case kStatusSignalToNoise: 
    445465            if (dvblistener) 
    446466                dvblistener->StatusSignalToNoise(val); 
    447467            break; 
    void SignalMonitor::SendMessage( 
    460480        } 
    461481    } 
    462482} 
    463483 
     484bool 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 
    464518void SignalMonitor::SendMessageAllGood(void) 
    465519{ 
    466520    QMutexLocker locker(&listenerLock); 
    467521    for (uint i = 0; i < listeners.size(); i++) 
    void SignalMonitor::SendMessageAllGood(v 
    469523} 
    470524 
    471525void SignalMonitor::EmitStatus(void) 
    472526{ 
     527    SendMessage(kStatusChannelTuned, channelTuned); 
    473528    SendMessage(kStatusSignalLock, signalLock); 
    474529    if (HasFlags(kSigMon_WaitForSig)) 
    475530        SendMessage(kStatusSignalStrength,    signalStrength); 
    476531} 
  • libs/libmythtv/signalmonitor.h

    old new using namespace std; 
    2626    "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG); 
    2727 
    2828inline QString sm_flags_to_string(uint64_t); 
    2929 
     30class TVRec; 
     31 
    3032class SignalMonitor 
    3133{ 
    3234  public: 
    3335    /// Returns true iff the card type supports signal monitoring. 
    class SignalMonitor 
    3941 
    4042    // // // // // // // // // // // // // // // // // // // // // // // // 
    4143    // Control  // // // // // // // // // // // // // // // // // // // // 
    4244 
    43     virtual void Start(); 
     45    virtual void Start(bool waitfor_tune); 
    4446    virtual void Stop(); 
    4547    virtual void Kick(); 
    4648    virtual bool WaitForLock(int timeout = -1); 
    4749 
    class SignalMonitor 
    8385     *         otherwise they are not. 
    8486     */ 
    8587    void SetNotifyFrontend(bool notify) { notify_frontend = notify; } 
    8688 
     89    /** \brief Indicate if table monitoring is needed 
     90     *  \param monitor if true parent->SetupDTVSignalMonitor is called 
     91     *         after the channel is tuned. 
     92     */ 
     93    void SetMonitoring(TVRec * parent, bool EITscan, bool monitor) 
     94        { pParent = parent; eit_scan = EITscan, tablemon = monitor; } 
     95 
    8796    /** \brief Sets the number of milliseconds between signal monitoring 
    8897     *         attempts in the signal monitoring thread. 
    8998     * 
    9099     *   Defaults to 25 milliseconds. 
    class SignalMonitor 
    96105    // // // // // // // // // // // // // // // // // // // // // // // // 
    97106    // Listeners   // // // // // // // // // // // // // // // // // // // 
    98107    void AddListener(SignalMonitorListener *listener); 
    99108    void RemoveListener(SignalMonitorListener *listener); 
     109 
    100110    void SendMessage(SignalMonitorMessageType type, 
    101111                     const SignalMonitorValue &val); 
    102112    void SendMessageAllGood(void); 
    103113    virtual void EmitStatus(void); 
    class SignalMonitor 
    108118     
    109119    static void* SpawnMonitorLoop(void*); 
    110120    virtual void MonitorLoop(); 
    111121 
     122    bool IsChannelTuned(void); 
     123 
    112124    /// \brief This should be overridden to actually do signal monitoring. 
    113125    virtual void UpdateValues() { ; } 
    114126 
    115127  public: 
    class SignalMonitor 
    139151    static const uint64_t kFWSigMon_PowerSeen   = 0x0000000100ULL; 
    140152    /// We've seen something indicating whether the data stream is encrypted 
    141153    static const uint64_t kDTVSigMon_CryptSeen  = 0x0000000200ULL; 
    142154 
     155    static const uint64_t kSigMon_Tuned         = 0x0000000400ULL; 
     156 
    143157    /// We've seen a PAT matching our requirements 
    144158    static const uint64_t kDTVSigMon_PATMatch   = 0x0000001000ULL; 
    145159    /// We've seen a PMT matching our requirements 
    146160    static const uint64_t kDTVSigMon_PMTMatch   = 0x0000002000ULL; 
    class SignalMonitor 
    184198 
    185199  protected: 
    186200    pthread_t    monitor_thread; 
    187201    ChannelBase *channel; 
     202    TVRec       *pParent; 
    188203    int          capturecardnum; 
    189204    uint64_t     flags; 
    190205    int          update_rate; 
    191206    uint         minimum_update_rate; 
    192207    bool         running; 
    193208    bool         exit; 
    194209    bool         update_done; 
    195210    bool         notify_frontend; 
     211    bool         is_tuned; 
     212    bool         tablemon; 
     213    bool         eit_scan; 
    196214    QString      error; 
    197215 
    198216    SignalMonitorValue signalLock; 
    199217    SignalMonitorValue signalStrength; 
     218    SignalMonitorValue channelTuned; 
    200219 
    201220    vector<SignalMonitorListener*> listeners; 
    202221 
    203222    QMutex             startStopLock; 
  • libs/libmythtv/signalmonitorlistener.h

    old new  
    88#include "signalmonitorvalue.h" 
    99 
    1010typedef enum { 
    1111    kAllGood, 
     12    kStatusChannelTuned, 
    1213    kStatusSignalLock, 
    1314    kStatusSignalStrength, 
    1415    kStatusSignalToNoise, 
    1516    kStatusBitErrorRate, 
    class MPUBLIC SignalMonitorListener 
    2930     *         has been started. 
    3031     */ 
    3132    virtual void AllGood(void) = 0; 
    3233 
     34    /** \brief Singal 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     * 
    3644     *   Note: Signals are only sent once the monitoring thread  
  • libs/libmythtv/tv_play.cpp

    old new void TV::UpdateOSDSignal(const PlayerCon 
    71607160    uint  sig  = 0; 
    71617161    float snr  = 0.0f; 
    71627162    uint  ber  = 0xffffffff; 
    71637163    int   pos  = -1; 
     7164    int   tuned = -1; 
    71647165    QString pat(""), pmt(""), mgt(""), vct(""), nit(""), sdt(""), crypt(""); 
    71657166    QString err = QString::null, msg = QString::null; 
    71667167    for (it = slist.begin(); it != slist.end(); ++it) 
    71677168    { 
    void TV::UpdateOSDSignal(const PlayerCon 
    71867187        else if ("ber" == it->GetShortName()) 
    71877188            ber = it->GetValue(); 
    71887189        else if ("pos" == it->GetShortName()) 
    71897190            pos = it->GetValue(); 
     7191        else if ("tuned" == it->GetShortName()) 
     7192            tuned = it->GetValue(); 
    71907193        else if ("seen_pat" == it->GetShortName()) 
    71917194            pat = it->IsGood() ? "a" : "_"; 
    71927195        else if ("matching_pat" == it->GetShortName()) 
    71937196            pat = it->IsGood() ? "A" : pat; 
    void TV::UpdateOSDSignal(const PlayerCon 
    72197222    if (sig) 
    72207223        infoMap["signal"] = QString::number(sig); // use normalized value 
    72217224 
    72227225    bool    allGood = SignalMonitorValue::AllGood(slist); 
     7226    char    tuneCode; 
    72237227    QString slock   = ("1" == infoMap["slock"]) ? "L" : "l"; 
    72247228    QString lockMsg = (slock=="L") ? tr("Partial Lock") : tr("No Lock"); 
    72257229    QString sigMsg  = allGood ? tr("Lock") : lockMsg; 
    72267230 
    void TV::UpdateOSDSignal(const PlayerCon 
    72317235        sigDesc += " | " + tr("BE %1", "Bit Errors").arg(ber, 2); 
    72327236    if ((pos >= 0) && (pos < 100)) 
    72337237        sigDesc += " | " + tr("Rotor %1\%").arg(pos,2); 
    72347238 
    7235     sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8) %9") 
    7236         .arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct) 
    7237         .arg(nit).arg(sdt).arg(crypt).arg(sigMsg); 
     7239    if (tuned == 1) 
     7240        tuneCode = 't'; 
     7241    else if (tuned == 2) 
     7242        tuneCode = 'F'; 
     7243    else if (tuned == 3) 
     7244        tuneCode = 'T'; 
     7245    else 
     7246        tuneCode = '_'; 
     7247 
     7248    sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8%9) %10") 
     7249              .arg(tuneCode).arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct) 
     7250              .arg(nit).arg(sdt).arg(crypt).arg(sigMsg); 
    72387251 
    72397252    if (!err.isEmpty()) 
    72407253        sigDesc = err; 
    72417254    else if (!msg.isEmpty()) 
  • libs/libmythtv/tv_rec.cpp

    old new  
    378378void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft, 
    379379                          bool hasLater) 
    380380{ 
    381     QMutexLocker lock(&stateChangeLock); 
     381    QMutexLocker statelock(&stateChangeLock); 
     382    QMutexLocker pendlock(&pendingRecLock); 
    382383 
    383384    if (secsleft < 0) 
    384385    { 
     
    416417 
    417418    pendingRecordings[rcinfo->cardid].possibleConflicts = cardids; 
    418419 
    419     stateChangeLock.unlock(); 
     420    statelock.unlock(); 
    420421    for (uint i = 0; i < cardids.size(); i++) 
    421422        RemoteRecordPending(cardids[i], rcinfo, secsleft, hasLater); 
    422     stateChangeLock.lock(); 
     423    statelock.relock(); 
    423424} 
    424425 
    425426/** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*) 
     
    451452 */ 
    452453void TVRec::CancelNextRecording(bool cancel) 
    453454{ 
     455    QMutexLocker pendlock(&pendingRecLock); 
    454456    VERBOSE(VB_RECORD, LOC + "CancelNextRecording("<<cancel<<") -- begin"); 
    455457 
    456458    PendingMap::iterator it = pendingRecordings.find(cardid); 
     
    535537        return retval; 
    536538    } 
    537539 
    538     PendingMap::iterator it = pendingRecordings.find(cardid); 
    539540    bool cancelNext = false; 
     541    bool has_pending; 
     542 
     543    pendingRecLock.lock(); 
     544    PendingMap::iterator it = pendingRecordings.find(cardid); 
    540545    if (it != pendingRecordings.end()) 
    541546    { 
    542547        (*it).ask = (*it).doNotAsk = false; 
    543548        cancelNext = (*it).canceled; 
     549        has_pending = true; 
    544550    } 
     551    else 
     552        has_pending = false; 
     553 
     554    PendingInfo pendinfo = *it; 
     555    pendingRecLock.unlock(); 
    545556 
    546557    // Flush out events... 
    547558    WaitForEventThreadSleep(); 
     
    553564 
    554565    // If the needed input is in a shared input group, and we are 
    555566    // not canceling the recording anyway, check other recorders 
    556     if (!cancelNext && 
    557         (it != pendingRecordings.end()) && (*it).possibleConflicts.size()) 
     567    if (!cancelNext && has_pending && pendinfo.possibleConflicts.size()) 
    558568    { 
    559569        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin"); 
    560         vector<uint> &cardids = (*it).possibleConflicts; 
     570        vector<uint> &cardids = pendinfo.possibleConflicts; 
    561571 
    562572        uint mplexid = 0, sourceid = 0; 
    563573        vector<uint> cardids2; 
     
    580590 
    581591            if (is_busy && !sourceid) 
    582592            { 
    583                 mplexid  = (*it).info->GetMplexID(); 
    584                 sourceid = (*it).info->sourceid; 
     593                mplexid  = pendinfo.info->GetMplexID(); 
     594                sourceid = pendinfo.info->sourceid; 
    585595            } 
    586596 
    587597            if (is_busy && 
     
    967977void TVRec::ChangeState(TVState nextState) 
    968978{ 
    969979    QMutexLocker lock(&stateChangeLock); 
    970  
    971980    desiredNextState = nextState; 
    972981    changeState = true; 
    973982    WakeEventLoop(); 
     
    14521461            QDateTime now   = QDateTime::currentDateTime(); 
    14531462            bool has_finish = HasFlags(kFlagFinishRecording); 
    14541463            bool has_rec    = pseudoLiveTVRecording; 
     1464            bool enable_ui  = true; 
     1465 
     1466            pendingRecLock.lock(); 
    14551467            bool rec_soon   = 
    14561468                pendingRecordings.find(cardid) != pendingRecordings.end(); 
    1457             bool enable_ui  = true; 
     1469            pendingRecLock.unlock(); 
    14581470 
    14591471            if (has_rec && (has_finish || (now > recordEndTime))) 
    14601472            { 
     
    16251637 
    16261638void TVRec::HandlePendingRecordings(void) 
    16271639{ 
     1640    QMutexLocker pendlock(&pendingRecLock); 
     1641 
    16281642    if (pendingRecordings.empty()) 
    16291643        return; 
    16301644 
     
    19261940 *   This method also grabs the ATSCStreamData() from the recorder 
    19271941 *   if possible, or creates one if needed. 
    19281942 */ 
    1929 bool TVRec::SetupDTVSignalMonitor(void) 
     1943bool TVRec::SetupDTVSignalMonitor(bool EITscan) 
    19301944{ 
    19311945    VERBOSE(VB_RECORD, LOC + "Setting up table monitoring."); 
    19321946 
     
    20602074                     SignalMonitor::kDVBSigMon_WaitForPos); 
    20612075        sm->SetRotorTarget(1.0f); 
    20622076 
     2077        if (EITscan) 
     2078        { 
     2079            sm->GetStreamData()->SetVideoStreamsRequired(0); 
     2080            sm->IgnoreEncrypted(true); 
     2081        } 
     2082 
    20632083        VERBOSE(VB_RECORD, LOC + "Successfully set up MPEG table monitoring."); 
    20642084        return true; 
    20652085    } 
     
    20812101 *  \param notify   If set we notify the frontend of the signal values 
    20822102 *  \return true on success, false on failure 
    20832103 */ 
    2084 bool TVRec::SetupSignalMonitor(bool tablemon, bool notify) 
     2104bool TVRec::SetupSignalMonitor(bool tablemon, bool EITscan, bool notify) 
    20852105{ 
    20862106    VERBOSE(VB_RECORD, LOC + "SetupSignalMonitor(" 
    20872107            <<tablemon<<", "<<notify<<")"); 
     
    20972117    // make sure statics are initialized 
    20982118    SignalMonitorValue::Init(); 
    20992119 
    2100     if (SignalMonitor::IsSupported(genOpt.cardtype) && channel->Open()) 
    2101         signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, channel); 
     2120    if (channel->Open()) 
     2121        signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, 
     2122                                            channel); 
    21022123 
    21032124    if (signalMonitor) 
    21042125    { 
    21052126        VERBOSE(VB_RECORD, LOC + "Signal monitor successfully created"); 
    2106         // If this is a monitor for Digital TV, initialize table monitors 
    2107         if (GetDTVSignalMonitor() && tablemon && !SetupDTVSignalMonitor()) 
    2108         { 
    2109             VERBOSE(VB_IMPORTANT, LOC_ERR + 
    2110                     "Failed to setup digital signal monitoring"); 
    2111  
    2112             return false; 
    2113         } 
    21142127 
     2128        signalMonitor->SetMonitoring(this, EITscan, 
     2129                                     GetDTVSignalMonitor() && tablemon); 
    21152130        signalMonitor->AddListener(this); 
    21162131        signalMonitor->SetUpdateRate(kSignalMonitoringRate); 
    21172132        signalMonitor->SetNotifyFrontend(notify); 
    21182133 
    21192134        // Start the monitoring thread 
    2120         signalMonitor->Start(); 
     2135        signalMonitor->Start(true); 
    21212136    } 
    21222137 
    21232138    return true; 
     
    23892404    { 
    23902405        for (uint j = 0; j < kSpacerListSize; j++) 
    23912406        { 
    2392             QString qprefix = add_spacer( 
     2407            QString qprefix = add_spacer( 
    23932408                prefix, (QString(spacers[j]) == "_") ? "\\_" : spacers[j]); 
    23942409            query.prepare(basequery.arg(qprefix) + cardquery[i]); 
    23952410 
     
    25222537 */ 
    25232538bool TVRec::IsBusy(TunedInputInfo *busy_input, int time_buffer) const 
    25242539{ 
    2525     QMutexLocker lock(&stateChangeLock); 
    2526  
    25272540    TunedInputInfo dummy; 
    25282541    if (!busy_input) 
    25292542        busy_input = &dummy; 
     
    25452558        chanid              = channel->GetChanID(); 
    25462559    } 
    25472560 
     2561    QMutexLocker pendlock(&pendingRecLock); 
    25482562    PendingMap::const_iterator it = pendingRecordings.find(cardid); 
    25492563    if (!busy_input->inputid && (it != pendingRecordings.end())) 
    25502564    { 
     
    32273241        } 
    32283242        else if (BROWSE_RIGHT == direction) 
    32293243        { 
    3230                 chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME); 
     3244                chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME); 
    32313245            compare = ">"; 
    32323246            sortorder = "asc"; 
    32333247        } 
     
    37173731void TVRec::TuningFrequency(const TuningRequest &request) 
    37183732{ 
    37193733    DTVChannel *dtvchan = GetDTVChannel(); 
     3734 
     3735    bool livetv = request.flags & kFlagLiveTV; 
     3736    bool antadj = request.flags & kFlagAntennaAdjust; 
     3737    bool has_dummy = false; 
     3738 
    37203739    if (dtvchan) 
    37213740    { 
    37223741        MPEGStreamData *mpeg = NULL; 
     
    37333752 
    37343753        if (request.minorChan && (tuningmode == "atsc")) 
    37353754        { 
    3736             channel->SetChannelByString(request.channel); 
    3737  
     3755            channel->SelectChannel(request.channel); 
    37383756            ATSCStreamData *atsc = dynamic_cast<ATSCStreamData*>(mpeg); 
    37393757            if (atsc) 
    37403758                atsc->SetDesiredChannel(request.majorChan, request.minorChan); 
    37413759        } 
    37423760        else if (request.progNum >= 0) 
    37433761        { 
    3744             channel->SetChannelByString(request.channel); 
    3745  
     3762            channel->SelectChannel(request.channel); 
    37463763            if (mpeg) 
    37473764                mpeg->SetDesiredProgram(request.progNum); 
    37483765        } 
     
    37713788    if (channel && !channum.isEmpty()) 
    37723789    { 
    37733790        if (!input.isEmpty()) 
    3774             ok = channel->SwitchToInput(input, channum); 
     3791            channel->SelectInput(input, channum); 
    37753792        else 
    3776             ok = channel->SetChannelByString(channum); 
     3793            channel->SelectChannel(channum); 
     3794 
     3795        ok = true; 
    37773796    } 
    37783797 
    37793798    if (!ok) 
     
    38003819        } 
    38013820    } 
    38023821 
    3803     bool livetv = request.flags & kFlagLiveTV; 
    3804     bool antadj = request.flags & kFlagAntennaAdjust; 
    3805     bool use_sm = SignalMonitor::IsRequired(genOpt.cardtype); 
    3806     bool use_dr = use_sm && (livetv || antadj); 
    3807     bool has_dummy = false; 
    3808  
    3809     if (use_dr) 
     3822    if (livetv || antadj) 
    38103823    { 
    38113824        // We need there to be a ringbuffer for these modes 
    38123825        bool ok; 
     
    38323845        has_dummy = true; 
    38333846    } 
    38343847 
    3835     // Start signal monitoring for devices capable of monitoring 
    3836     if (use_sm) 
     3848    // Start signal (or channel change) monitoring 
     3849    VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor"); 
     3850    bool error = false; 
     3851    if (!SetupSignalMonitor(!antadj, request.flags & kFlagEITScan, 
     3852                            livetv | antadj)) 
    38373853    { 
    3838         VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor"); 
    3839         bool error = false; 
    3840         if (!SetupSignalMonitor(!antadj, livetv | antadj)) 
    3841         { 
    3842             VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor"); 
    3843             if (signalMonitor) 
    3844             { 
    3845                 delete signalMonitor; 
    3846                 signalMonitor = NULL; 
    3847             } 
    3848  
    3849             // pretend the signal monitor is running to prevent segfault 
    3850             SetFlags(kFlagSignalMonitorRunning); 
    3851             ClearFlags(kFlagWaitingForSignal); 
    3852             error = true; 
    3853         } 
    3854  
     3854        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor"); 
    38553855        if (signalMonitor) 
    38563856        { 
    3857             if (request.flags & kFlagEITScan) 
    3858             { 
    3859                 GetDTVSignalMonitor()->GetStreamData()-> 
    3860                     SetVideoStreamsRequired(0); 
    3861                 GetDTVSignalMonitor()->IgnoreEncrypted(true); 
    3862             } 
    3863  
    3864             SetFlags(kFlagSignalMonitorRunning); 
    3865             ClearFlags(kFlagWaitingForSignal); 
    3866             if (!antadj) 
    3867                 SetFlags(kFlagWaitingForSignal); 
     3857            delete signalMonitor; 
     3858            signalMonitor = NULL; 
    38683859        } 
    38693860 
    3870         if (has_dummy && ringBuffer) 
    3871         { 
    3872             // Make sure recorder doesn't point to bogus ringbuffer before 
    3873             // it is potentially restarted without a new ringbuffer, if 
    3874             // the next channel won't tune and the user exits LiveTV. 
    3875             if (recorder) 
    3876                 recorder->SetRingBuffer(NULL); 
     3861        // pretend the signal monitor is running to prevent segfault 
     3862        SetFlags(kFlagSignalMonitorRunning); 
     3863        ClearFlags(kFlagWaitingForSignal); 
     3864        error = true; 
     3865    } 
    38773866 
    3878             SetFlags(kFlagDummyRecorderRunning); 
    3879             VERBOSE(VB_RECORD, "DummyDTVRecorder -- started"); 
    3880             SetFlags(kFlagRingBufferReady); 
    3881         } 
     3867    if (signalMonitor) 
     3868    { 
     3869        SetFlags(kFlagSignalMonitorRunning); 
     3870        ClearFlags(kFlagWaitingForSignal); 
     3871        if (!antadj) 
     3872            SetFlags(kFlagWaitingForSignal); 
     3873    } 
    38823874 
    3883         // if we had problems starting the signal monitor, 
    3884         // we don't want to start the recorder... 
    3885         if (error) 
    3886             return; 
     3875    if (has_dummy && ringBuffer) 
     3876    { 
     3877        // Make sure recorder doesn't point to bogus ringbuffer before 
     3878        // it is potentially restarted without a new ringbuffer, if 
     3879        // the next channel won't tune and the user exits LiveTV. 
     3880        if (recorder) 
     3881            recorder->SetRingBuffer(NULL); 
     3882 
     3883        SetFlags(kFlagDummyRecorderRunning); 
     3884        VERBOSE(VB_RECORD, "DummyDTVRecorder -- started"); 
     3885        SetFlags(kFlagRingBufferReady); 
    38873886    } 
    38883887 
     3888    // if we had problems starting the signal monitor, 
     3889    // we don't want to start the recorder... 
     3890    if (error) 
     3891        return; 
     3892 
    38893893    // Request a recorder, if the command is a recording command 
    38903894    ClearFlags(kFlagNeedToStartRecorder); 
    38913895    if (request.flags & kFlagRec && !antadj) 
  • libs/libmythtv/tv_rec.h

    old new typedef QMap<uint,PendingInfo> PendingMa 
    160160 
    161161class MPUBLIC TVRec : public SignalMonitorListener 
    162162{ 
    163163    friend class TuningRequest; 
     164    friend class SignalMonitor; 
    164165 
    165166  public: 
    166167    TVRec(int capturecardnum); 
    167168   ~TVRec(void); 
    class MPUBLIC TVRec : public SignalMonit 
    254255 
    255256    static TVRec *GetTVRec(uint cardid); 
    256257 
    257258    virtual void AllGood(void) { WakeEventLoop(); } 
     259    virtual void StatusChannelTuned(const SignalMonitorValue&) { } 
    258260    virtual void StatusSignalLock(const SignalMonitorValue&) { } 
    259261    virtual void StatusSignalStrength(const SignalMonitorValue&) { } 
    260262 
    261263  protected: 
    262264    void RunTV(void); 
    263265    bool WaitForEventThreadSleep(bool wake = true, ulong time = ULONG_MAX); 
    264266    static void *EventThread(void *param); 
    265267    static void *RecorderThread(void *param); 
     268    bool SetupDTVSignalMonitor(bool EITscan); 
    266269 
    267270  private: 
    268271    void SetRingBuffer(RingBuffer *); 
    269272    void SetPseudoLiveTVRecording(ProgramInfo*); 
    class MPUBLIC TVRec : public SignalMonit 
    293296    DVBChannel   *GetDVBChannel(void); 
    294297    FirewireChannel *GetFirewireChannel(void); 
    295298    V4LChannel   *GetV4LChannel(void); 
    296299 
    297     bool SetupSignalMonitor(bool enable_table_monitoring, bool notify); 
    298     bool SetupDTVSignalMonitor(void); 
     300    bool SetupSignalMonitor(bool enable_table_monitoring, 
     301                            bool EITscan, bool notify); 
    299302    void TeardownSignalMonitor(void); 
    300303    DTVSignalMonitor *GetDTVSignalMonitor(void); 
    301304 
    302305    bool HasFlags(uint f) const { return (stateFlags & f) == f; } 
    class MPUBLIC TVRec : public SignalMonit 
    373376    DBox2DBOptions     dboxOpt; 
    374377 
    375378    // State variables 
    376379    mutable QMutex stateChangeLock; 
     380    mutable QMutex pendingRecLock; 
    377381    TVState        internalState; 
    378382    TVState        desiredNextState; 
    379383    bool           changeState; 
    380384    bool           pauseNotify; 
  • libs/libmythtv/v4lchannel.h

    old new class V4LChannel : public DTVChannel 
    4848    QString GetDevice(void) const { return device; } 
    4949    QString GetSIStandard(void) const { return "atsc"; } 
    5050 
    5151    // Commands 
    52     bool SwitchToInput(int newcapchannel, bool setstarting); 
    5352    bool Retune(void); 
    5453 
    5554    // Picture attributes. 
    5655    bool InitPictureAttributes(void); 
    class V4LChannel : public DTVChannel 
    6867    // Analog scanning stuff 
    6968    bool Tune(uint frequency, QString inputname, 
    7069              QString modulation, QString si_std); 
    7170 
     71  protected: 
     72    bool SwitchToInput(int newcapchannel, bool setstarting); 
     73 
    7274  private: 
    7375    // Helper Sets 
    7476    void SetFreqTable(const int index); 
    7577    int  SetFreqTable(const QString &name);