Ticket #6719: channel-thread-v1.4a.patch

File channel-thread-v1.4a.patch, 51.2 KB (added by jppoet@…, 12 years ago)

Update for r22198

  • 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 ProgramInfo *TVRec::GetRecording(void) 
    377377 */
    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    {
    385386        VERBOSE(VB_RECORD, LOC + "Pending recording revoked on " +
    void TVRec::RecordPending(const ProgramI 
    415416        rcinfo->inputid, cardid);
    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*)
    426427 *  \brief Sets the pseudo LiveTV ProgramInfo
    QDateTime TVRec::GetRecordEndTime(const  
    450451 *      TV::AskAllowRecording(const QStringList&, int, bool)
    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);
    457459    if (it == pendingRecordings.end())
    RecStatusType TVRec::StartRecording(cons 
    534536        retval = rsRecording;
    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();
    548559
    549560    // If the needed input is in a shared input group, and we are
    550561    // not canceling the recording anyway, check other recorders
    551     if (!cancelNext &&
    552         (it != pendingRecordings.end()) && (*it).possibleConflicts.size())
     562    if (!cancelNext && has_pending && pendinfo.possibleConflicts.size())
    553563    {
    554564        VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin");
    555         vector<uint> &cardids = (*it).possibleConflicts;
     565        vector<uint> &cardids = pendinfo.possibleConflicts;
    556566
    557567        uint mplexid = 0, sourceid = 0;
    558568        vector<uint> cardids2;
    559569        vector<TVState> states;
    RecStatusType TVRec::StartRecording(cons 
    574584            }
    575585
    576586            if (is_busy && !sourceid)
    577587            {
    578                 mplexid  = (*it).info->GetMplexID();
    579                 sourceid = (*it).info->sourceid;
     588                mplexid  = pendinfo.info->GetMplexID();
     589                sourceid = pendinfo.info->sourceid;
    580590            }
    581591
    582592            if (is_busy &&
    583593                ((sourceid != busy_input.sourceid) ||
    void TVRec::HandleStateChange(void) 
    961971 */
    962972void TVRec::ChangeState(TVState nextState)
    963973{
    964974    QMutexLocker lock(&stateChangeLock);
    965 
    966975    desiredNextState = nextState;
    967976    changeState = true;
    968977    WakeEventLoop();
    969978}
    void TVRec::RunTV(void) 
    14461455        {
    14471456            QDateTime now   = QDateTime::currentDateTime();
    14481457            bool has_finish = HasFlags(kFlagFinishRecording);
    14491458            bool has_rec    = pseudoLiveTVRecording;
     1459            bool enable_ui  = true;
     1460
     1461            pendingRecLock.lock();
    14501462            bool rec_soon   =
    14511463                pendingRecordings.find(cardid) != pendingRecordings.end();
    1452             bool enable_ui  = true;
     1464            pendingRecLock.unlock();
    14531465
    14541466            if (has_rec && (has_finish || (now > recordEndTime)))
    14551467            {
    14561468                if (pseudoLiveTVRecording && curRecording)
    bool TVRec::WaitForEventThreadSleep(bool 
    16191631}
    16201632
    16211633void TVRec::HandlePendingRecordings(void)
    16221634{
     1635    QMutexLocker pendlock(&pendingRecLock);
     1636
    16231637    if (pendingRecordings.empty())
    16241638        return;
    16251639
    16261640    // If we have a pending recording and AskAllowRecording
    bool ApplyCachedPids(DTVSignalMonitor *d 
    19201934 *
    19211935 *   This method also grabs the ATSCStreamData() from the recorder
    19221936 *   if possible, or creates one if needed.
    19231937 */
    1924 bool TVRec::SetupDTVSignalMonitor(void)
     1938bool TVRec::SetupDTVSignalMonitor(bool EITscan)
    19251939{
    19261940    VERBOSE(VB_RECORD, LOC + "Setting up table monitoring.");
    19271941
    19281942    DTVSignalMonitor *sm = GetDTVSignalMonitor();
    bool TVRec::SetupDTVSignalMonitor(void) 
    20542068                     SignalMonitor::kDTVSigMon_WaitForPMT |
    20552069                     SignalMonitor::kDVBSigMon_WaitForPos);
    20562070        sm->SetRotorTarget(1.0f);
    20572071
     2072        if (EITscan)
     2073        {
     2074            sm->GetStreamData()->SetVideoStreamsRequired(0);
     2075            sm->IgnoreEncrypted(true);
     2076        }
     2077
    20582078        VERBOSE(VB_RECORD, LOC + "Successfully set up MPEG table monitoring.");
    20592079        return true;
    20602080    }
    20612081
    bool TVRec::SetupDTVSignalMonitor(void) 
    20752095 *  \param tablemon If set we enable table monitoring
    20762096 *  \param notify   If set we notify the frontend of the signal values
    20772097 *  \return true on success, false on failure
    20782098 */
    2079 bool TVRec::SetupSignalMonitor(bool tablemon, bool notify)
     2099bool TVRec::SetupSignalMonitor(bool tablemon, bool EITscan, bool notify)
    20802100{
    20812101    VERBOSE(VB_RECORD, LOC + "SetupSignalMonitor("
    20822102            <<tablemon<<", "<<notify<<")");
    20832103
    bool TVRec::SetupSignalMonitor(bool tabl 
    20912111
    20922112    // make sure statics are initialized
    20932113    SignalMonitorValue::Init();
    20942114
    2095     if (SignalMonitor::IsSupported(genOpt.cardtype) && channel->Open())
    2096         signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, channel);
     2115    if (channel->Open())
     2116        signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid,
     2117                                            channel);
    20972118
    20982119    if (signalMonitor)
    20992120    {
    21002121        VERBOSE(VB_RECORD, LOC + "Signal monitor successfully created");
    2101         // If this is a monitor for Digital TV, initialize table monitors
    2102         if (GetDTVSignalMonitor() && tablemon && !SetupDTVSignalMonitor())
    2103         {
    2104             VERBOSE(VB_IMPORTANT, LOC_ERR +
    2105                     "Failed to setup digital signal monitoring");
    2106 
    2107             return false;
    2108         }
    21092122
     2123        signalMonitor->SetMonitoring(this, EITscan,
     2124                                     GetDTVSignalMonitor() && tablemon);
    21102125        signalMonitor->AddListener(this);
    21112126        signalMonitor->SetUpdateRate(kSignalMonitoringRate);
    21122127        signalMonitor->SetNotifyFrontend(notify);
    21132128
    21142129        // Start the monitoring thread
    2115         signalMonitor->Start();
     2130        signalMonitor->Start(true);
    21162131    }
    21172132
    21182133    return true;
    21192134}
    bool TVRec::CheckChannelPrefix(const QSt 
    23832398    for (uint i = 0; i < 2; i++)
    23842399    {
    23852400        for (uint j = 0; j < kSpacerListSize; j++)
    23862401        {
    2387             QString qprefix = add_spacer(
     2402            QString qprefix = add_spacer(
    23882403                prefix, (QString(spacers[j]) == "_") ? "\\_" : spacers[j]);
    23892404            query.prepare(basequery.arg(qprefix) + cardquery[i]);
    23902405
    23912406            if (!query.exec() || !query.isActive())
    bool TVRec::IsReallyRecording(void) 
    25162531 *  \sa EncoderLink::IsBusy(TunedInputInfo*, int time_buffer)
    25172532 */
    25182533bool TVRec::IsBusy(TunedInputInfo *busy_input, int time_buffer) const
    25192534{
    2520     QMutexLocker lock(&stateChangeLock);
    2521 
    25222535    TunedInputInfo dummy;
    25232536    if (!busy_input)
    25242537        busy_input = &dummy;
    25252538
    bool TVRec::IsBusy(TunedInputInfo *busy_ 
    25392552        busy_input->inputid = channel->GetCurrentInputNum();
    25402553        chanid              = channel->GetChanID();
    25412554    }
    25422555
     2556    QMutexLocker pendlock(&pendingRecLock);
    25432557    PendingMap::const_iterator it = pendingRecordings.find(cardid);
    25442558    if (!busy_input->inputid && (it != pendingRecordings.end()))
    25452559    {
    25462560        int timeLeft = QDateTime::currentDateTime()
    void TVRec::GetNextProgram(int direction 
    32213235            compare = "<";
    32223236        }
    32233237        else if (BROWSE_RIGHT == direction)
    32243238        {
    3225                 chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
     3239                chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
    32263240            compare = ">";
    32273241            sortorder = "asc";
    32283242        }
    32293243    }
    void TVRec::TuningShutdowns(const Tuning 
    37113725 */
    37123726void TVRec::TuningFrequency(const TuningRequest &request)
    37133727{
    37143728    DTVChannel *dtvchan = GetDTVChannel();
     3729
     3730    bool livetv = request.flags & kFlagLiveTV;
     3731    bool antadj = request.flags & kFlagAntennaAdjust;
     3732    bool has_dummy = false;
     3733
    37153734    if (dtvchan)
    37163735    {
    37173736        MPEGStreamData *mpeg = NULL;
    37183737
    void TVRec::TuningFrequency(const Tuning 
    37273746        dtvchan->SetTuningMode(tuningmode);
    37283747
    37293748        if (request.minorChan && (tuningmode == "atsc"))
    37303749        {
    3731             channel->SetChannelByString(request.channel);
    3732 
     3750            channel->SelectChannel(request.channel);
    37333751            ATSCStreamData *atsc = dynamic_cast<ATSCStreamData*>(mpeg);
    37343752            if (atsc)
    37353753                atsc->SetDesiredChannel(request.majorChan, request.minorChan);
    37363754        }
    37373755        else if (request.progNum >= 0)
    37383756        {
    3739             channel->SetChannelByString(request.channel);
    3740 
     3757            channel->SelectChannel(request.channel);
    37413758            if (mpeg)
    37423759                mpeg->SetDesiredProgram(request.progNum);
    37433760        }
    37443761    }
    void TVRec::TuningFrequency(const Tuning 
    37653782
    37663783    if (channel && !channum.isEmpty())
    37673784    {
    37683785        if (!input.isEmpty())
    3769             ok = channel->SwitchToInput(input, channum);
     3786            channel->SelectInput(input, channum);
    37703787        else
    3771             ok = channel->SetChannelByString(channum);
     3788            channel->SelectChannel(channum);
     3789
     3790        ok = true;
    37723791    }
    37733792
    37743793    if (!ok)
    37753794    {
    void TVRec::TuningFrequency(const Tuning 
    37943813                    QString("Failed to set channel to %1.").arg(channum));
    37953814        }
    37963815    }
    37973816
    3798     bool livetv = request.flags & kFlagLiveTV;
    3799     bool antadj = request.flags & kFlagAntennaAdjust;
    3800     bool use_sm = SignalMonitor::IsRequired(genOpt.cardtype);
    3801     bool use_dr = use_sm && (livetv || antadj);
    3802     bool has_dummy = false;
    3803 
    3804     if (use_dr)
     3817    if (livetv || antadj)
    38053818    {
    38063819        // We need there to be a ringbuffer for these modes
    38073820        bool ok;
    38083821        ProgramInfo *tmp = pseudoLiveTVRecording;
    void TVRec::TuningFrequency(const Tuning 
    38263839
    38273840        has_dummy = true;
    38283841    }
    38293842
    3830     // Start signal monitoring for devices capable of monitoring
    3831     if (use_sm)
     3843    // Start signal (or channel change) monitoring
     3844    VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor");
     3845    bool error = false;
     3846    if (!SetupSignalMonitor(!antadj, request.flags & kFlagEITScan,
     3847                            livetv | antadj))
    38323848    {
    3833         VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor");
    3834         bool error = false;
    3835         if (!SetupSignalMonitor(!antadj, livetv | antadj))
    3836         {
    3837             VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor");
    3838             if (signalMonitor)
    3839             {
    3840                 delete signalMonitor;
    3841                 signalMonitor = NULL;
    3842             }
    3843 
    3844             // pretend the signal monitor is running to prevent segfault
    3845             SetFlags(kFlagSignalMonitorRunning);
    3846             ClearFlags(kFlagWaitingForSignal);
    3847             error = true;
    3848         }
    3849 
     3849        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor");
    38503850        if (signalMonitor)
    38513851        {
    3852             if (request.flags & kFlagEITScan)
    3853             {
    3854                 GetDTVSignalMonitor()->GetStreamData()->
    3855                     SetVideoStreamsRequired(0);
    3856                 GetDTVSignalMonitor()->IgnoreEncrypted(true);
    3857             }
    3858 
    3859             SetFlags(kFlagSignalMonitorRunning);
    3860             ClearFlags(kFlagWaitingForSignal);
    3861             if (!antadj)
    3862                 SetFlags(kFlagWaitingForSignal);
     3852            delete signalMonitor;
     3853            signalMonitor = NULL;
    38633854        }
    38643855
    3865         if (has_dummy && ringBuffer)
    3866         {
    3867             // Make sure recorder doesn't point to bogus ringbuffer before
    3868             // it is potentially restarted without a new ringbuffer, if
    3869             // the next channel won't tune and the user exits LiveTV.
    3870             if (recorder)
    3871                 recorder->SetRingBuffer(NULL);
     3856        // pretend the signal monitor is running to prevent segfault
     3857        SetFlags(kFlagSignalMonitorRunning);
     3858        ClearFlags(kFlagWaitingForSignal);
     3859        error = true;
     3860    }
    38723861
    3873             SetFlags(kFlagDummyRecorderRunning);
    3874             VERBOSE(VB_RECORD, "DummyDTVRecorder -- started");
    3875             SetFlags(kFlagRingBufferReady);
    3876         }
     3862    if (signalMonitor)
     3863    {
     3864        SetFlags(kFlagSignalMonitorRunning);
     3865        ClearFlags(kFlagWaitingForSignal);
     3866        if (!antadj)
     3867            SetFlags(kFlagWaitingForSignal);
     3868    }
    38773869
    3878         // if we had problems starting the signal monitor,
    3879         // we don't want to start the recorder...
    3880         if (error)
    3881             return;
     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);
     3877
     3878        SetFlags(kFlagDummyRecorderRunning);
     3879        VERBOSE(VB_RECORD, "DummyDTVRecorder -- started");
     3880        SetFlags(kFlagRingBufferReady);
    38823881    }
    38833882
     3883    // if we had problems starting the signal monitor,
     3884    // we don't want to start the recorder...
     3885    if (error)
     3886        return;
     3887
    38843888    // Request a recorder, if the command is a recording command
    38853889    ClearFlags(kFlagNeedToStartRecorder);
    38863890    if (request.flags & kFlagRec && !antadj)
    38873891        SetFlags(kFlagNeedToStartRecorder);
  • 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);