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

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

Fixes dvb multirec problem. Updated for trunk r25379

  • libs/libmythtv/analogsignalmonitor.cpp

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

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

    old new  
    55
    66// Qt headers
    77#include <QStringList>
     8#include <qwaitcondition.h>
     9#include <qmutex.h>
     10#include <qthread.h>
    811
    912// MythTV headers
    1013#include "channelutil.h"
     
    1215#include "tv.h"
    1316
    1417class TVRec;
     18class ChannelBase;
     19
     20/*
     21 * Thread to run tunning process in
     22 */
     23class ChannelThread : public QThread
     24{
     25  public:
     26    virtual void run(void);
     27
     28    QString      channel;
     29    ChannelBase *tuner;
     30};
    1531
    1632/** \class ChannelBase
    1733 *  \brief Abstract class providing a generic interface to tuning hardware.
    class TVRec; 
    2339
    2440class ChannelBase
    2541{
    26  public:
     42    friend class ChannelThread;
     43
     44  public:
     45    enum Status { changeUnknown = 'U', changePending = 'P',
     46                  changeFailed = 'F', changeSuccess = 'S' };
     47
    2748    ChannelBase(TVRec *parent);
    28     virtual ~ChannelBase();
     49    virtual ~ChannelBase(void);
    2950
    3051    virtual bool Init(QString &inputname, QString &startchannel, bool setchan);
    3152    virtual bool IsTunable(const QString &input, const QString &channum) const;
    3253
     54    virtual void SelectChannel(const QString & chan);
     55
     56    Status GetStatus(void);
     57    Status Wait(void);
     58
    3359    // Methods that must be implemented.
    3460    /// \brief Opens the channel changing hardware for use.
    3561    virtual bool Open(void) = 0;
    3662    /// \brief Closes the channel changing hardware to use.
    3763    virtual void Close(void) = 0;
    38     virtual bool SetChannelByString(const QString &chan) = 0;
    3964    /// \brief Reports whether channel is already open
    4065    virtual bool IsOpen(void) const = 0;
    4166
    class ChannelBase 
    82107                          const QString &newChanNum);
    83108
    84109    // Input toggling convenience methods
    85     virtual bool SwitchToInput(const QString &input);
    86     virtual bool SwitchToInput(const QString &input, const QString &chan);
     110//    virtual bool SwitchToInput(const QString &input); // not used?
     111    virtual bool SelectInput(const QString &input, const QString &chan,
     112                             bool use_sm);
    87113
    88114    virtual bool InitializeInputs(void);
    89115
    class ChannelBase 
    108134
    109135    virtual int GetCardID(void) const;
    110136  protected:
     137    virtual bool SetChannelByString(const QString &chan) = 0;
     138
    111139    /// \brief Switches to another input on hardware,
    112140    ///        and sets the channel is setstarting is true.
    113141    virtual bool SwitchToInput(int inputNum, bool setstarting);
    class ChannelBase 
    119147    static void StoreDefaultInput(uint cardid, const QString &input);
    120148    void ClearInputMap(void);
    121149
     150    bool Aborted();
     151    void setStatus(Status status);
     152    void TeardownAll(void);
     153
    122154    TVRec   *m_pParent;
    123155    QString  m_curchannelname;
    124156    int      m_currentInputID;
    class ChannelBase 
    126158    uint     m_cardid;
    127159    InputMap m_inputs;
    128160    DBChanList m_allchannels; ///< channels across all inputs
     161
     162    QWaitCondition  m_tuneCond;
     163
     164  private:
     165    mutable  ChannelThread   m_tuneThread;
     166    Status   m_tuneStatus;
     167    QMutex   m_thread_lock;
     168    bool     m_abort_change;
    129169};
    130170
    131171#endif
  • new file libs/libmythtv/channelchangemonitor.cpp

    - +  
     1// -*- Mode: c++ -*-
     2
     3#include <cerrno>
     4#include <unistd.h>
     5#include <sys/ioctl.h>
     6
     7#include "mythcontext.h"
     8#include "channelchangemonitor.h"
     9#include "v4lchannel.h"
     10
     11#define LOC QString("ChannelChangeM: ").arg(channel->GetDevice())
     12#define LOC_ERR QString("ChannelChangeM, Error: ").arg(channel->GetDevice())
     13
     14ChannelChangeMonitor::ChannelChangeMonitor(
     15    int db_cardnum, V4LChannel *_channel, uint64_t _flags) :
     16    SignalMonitor(db_cardnum, _channel, _flags)
     17{
     18}
     19
     20void ChannelChangeMonitor::UpdateValues(void)
     21{
     22    if (!running || exit)
     23        return;
     24
     25    if (!IsChannelTuned())
     26        return;
     27
     28    {
     29        QMutexLocker locker(&statusLock);
     30        signalLock.SetValue(true);
     31        signalStrength.SetValue(100);
     32    }
     33
     34    EmitStatus();
     35    SendMessageAllGood();
     36}
     37
  • new file libs/libmythtv/channelchangemonitor.h

    - +  
     1// -*- Mode: c++ -*-
     2// Copyright (c) 2005, Daniel Thor Kristjansson
     3
     4#ifndef _CHANNEL_CHANGE_MONITOR_H_
     5#define _CHANNEL_CHANGE_MONITOR_H_
     6
     7// MythTV headers
     8#include "signalmonitor.h"
     9
     10class V4LChannel;
     11
     12class ChannelChangeMonitor : public SignalMonitor
     13{
     14  public:
     15    ChannelChangeMonitor(
     16        int db_cardnum, V4LChannel *_channel,
     17        uint64_t _flags = kSigMon_WaitForSig);
     18
     19    virtual void UpdateValues(void);
     20};
     21
     22#endif // _CHANNEL_CHANGE_MONITOR_H_
  • libs/libmythtv/channelscan/channelscan_sm.cpp

    old new void ChannelScanSM::ScanTransport(const  
    16271627    }
    16281628
    16291629    // Start signal monitor for this channel
    1630     signalMonitor->Start();
     1630    signalMonitor->Start(false);
    16311631
    16321632    timer.start();
    16331633    waitingForTables = (item.tuning.sistandard != "analog");
  • libs/libmythtv/channelscan/channelscan_sm.h

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    old new  
    99
    1010typedef enum {
    1111    kAllGood,
     12    kStatusChannelTuned,
    1213    kStatusSignalLock,
    1314    kStatusSignalStrength,
    1415    kStatusSignalToNoise,
    class MPUBLIC SignalMonitorListener 
    3031     */
    3132    virtual void AllGood(void) = 0;
    3233
     34    /** \brief Signal to be sent with change change status.
     35     *
     36     *   Note: Signals are only sent once the monitoring thread
     37     *         has been started.
     38     */
     39    virtual void StatusChannelTuned(const SignalMonitorValue&) = 0;
     40
    3341    /** \brief Signal to be sent as true when it is safe to begin
    3442     *   or continue recording, and false if it may not be safe.
    3543     *
  • libs/libmythtv/tv_play.cpp

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

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

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

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

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