Index: libs/libmythtv/analogsignalmonitor.cpp
===================================================================
--- libs/libmythtv/analogsignalmonitor.cpp.orig
+++ libs/libmythtv/analogsignalmonitor.cpp
@@ -31,8 +31,11 @@ void AnalogSignalMonitor::UpdateValues(v
     int videofd = channel->GetFd();
     if (videofd < 0)
         return;
 
+    if (!IsChannelTuned())
+        return;
+
     bool isLocked = false;
     if (usingv4l2)
     {
         struct v4l2_tuner tuner;
Index: libs/libmythtv/channelbase.cpp
===================================================================
--- libs/libmythtv/channelbase.cpp.orig
+++ libs/libmythtv/channelbase.cpp
@@ -34,27 +34,111 @@ using namespace std;
 #define LOC QString("ChannelBase(%1): ").arg(GetCardID())
 #define LOC_WARN QString("ChannelBase(%1) Warning: ").arg(GetCardID())
 #define LOC_ERR QString("ChannelBase(%1) Error: ").arg(GetCardID())
 
+/*
+ * Run the channel change thread, and report the status when done
+ */
+void ChannelThread::run(void)
+{
+    bool result = tuner->SetChannelByString(channel);
+    tuner->setStatus(result ?
+                     ChannelBase::changeSuccess : ChannelBase::changeFailed);
+}
+
 ChannelBase::ChannelBase(TVRec *parent)
     :
     pParent(parent), curchannelname(""),
-    currentInputID(-1), commfree(false), cardid(0)
+    currentInputID(-1), commfree(false), cardid(0),
+    abort_change(false)
 {
+    tuneStatus = changeUnknown;
+    tuneThread.tuner = this;
 }
 
 ChannelBase::~ChannelBase(void)
 {
+    TeardownAll();
+}
+
+void ChannelBase::TeardownAll(void)
+{
+    if (tuneThread.isRunning())
+    {
+        thread_lock.lock();
+        abort_change = true;
+        tuneCond.wakeAll();
+        thread_lock.unlock();
+        tuneThread.wait();
+    }
+}
+
+void ChannelBase::SelectChannel(const QString & chan)
+{
+    VERBOSE(VB_CHANNEL, LOC + "SelectChannel " + chan);
+    TeardownAll();
+
+    thread_lock.lock();
+    abort_change = false;
+    tuneStatus = changePending;
+    thread_lock.unlock();
+
+    curchannelname = tuneThread.channel = chan;
+    tuneThread.start();
+}
+
+/*
+ * Returns true of the channel change thread should abort
+ */
+bool ChannelBase::Aborted(void)
+{
+    bool       result;
+
+    thread_lock.lock();
+    result = abort_change;
+    thread_lock.unlock();
+
+    return result;
+}
+
+ChannelBase::Status ChannelBase::GetStatus(void)
+{
+    Status status;
+
+    thread_lock.lock();
+    status = tuneStatus;
+    thread_lock.unlock();
+
+    return status;
+}
+
+ChannelBase::Status ChannelBase::Wait(void)
+{
+    tuneThread.wait();
+    return tuneStatus;
+}
+
+void ChannelBase::setStatus(ChannelBase::Status status)
+{
+    thread_lock.lock();
+    tuneStatus = status;
+    thread_lock.unlock();
 }
 
 bool ChannelBase::Init(QString &inputname, QString &startchannel, bool setchan)
 {
     bool ok;
 
+    VERBOSE(VB_CHANNEL, LOC + QString("Init(%1, %2, %3)")
+            .arg(inputname).arg(startchannel).arg(setchan));
+
     if (!setchan)
         ok = inputname.isEmpty() ? false : IsTunable(inputname, startchannel);
     else if (inputname.isEmpty())
-        ok = SetChannelByString(startchannel);
+    {
+        SelectChannel(startchannel);
+        ok = Wait();
+    }
     else
         ok = SwitchToInput(inputname, startchannel);
 
     if (ok)
@@ -123,12 +207,10 @@ bool ChannelBase::Init(QString &inputnam
 
             if (chanid && cit != channels.end())
             {
                 if (!setchan)
-                {
                     ok = IsTunable(*it, (mplexid_restriction) ?
                                    (*cit).channum : startchannel);
-                }
                 else
                     ok = SwitchToInput(*it, (*cit).channum);
 
                 if (ok)
@@ -328,8 +410,9 @@ int ChannelBase::GetInputByName(const QS
     }
     return -1;
 }
 
+#if 0 // Not used?
 bool ChannelBase::SwitchToInput(const QString &inputname)
 {
     int input = GetInputByName(inputname);
 
@@ -339,31 +422,63 @@ bool ChannelBase::SwitchToInput(const QS
         VERBOSE(VB_IMPORTANT, QString("ChannelBase: Could not find input: "
                                       "%1 on card\n").arg(inputname));
     return false;
 }
+#endif
+
+bool ChannelBase::SelectInput(const QString &inputname, const QString &chan)
+{
+    int input = GetInputByName(inputname);
+
+    VERBOSE(VB_CHANNEL, LOC + QString("SelectInput(%1, %2) %3")
+            .arg(inputname).arg(chan).arg(input));
+
+    if (input >= 0)
+    {
+        if (!SwitchToInput(input, false))
+            return false;
+        SelectChannel(chan);
+    }
+    else
+    {
+        VERBOSE(VB_IMPORTANT,
+                QString("ChannelBase: Could not find input: %1 on card when "
+                        "setting channel %2\n").arg(inputname).arg(chan));
+        return false;
+    }
+
+    return true;
+}
 
 bool ChannelBase::SwitchToInput(const QString &inputname, const QString &chan)
 {
     int input = GetInputByName(inputname);
 
-    bool ok = false;
+    VERBOSE(VB_CHANNEL, LOC + QString("SwitchToInput(%1, %2), %3")
+            .arg(inputname).arg(chan).arg(input));
+
     if (input >= 0)
     {
-        ok = SwitchToInput(input, false);
-        if (ok)
-            ok = SetChannelByString(chan);
+        if (!SwitchToInput(input, false))
+            return false;
+        return SetChannelByString(chan);
     }
     else
     {
         VERBOSE(VB_IMPORTANT,
                 QString("ChannelBase: Could not find input: %1 on card when "
                         "setting channel %2\n").arg(inputname).arg(chan));
+        return false;
     }
-    return ok;
+
+    return true;
 }
 
 bool ChannelBase::SwitchToInput(int newInputNum, bool setstarting)
 {
+    VERBOSE(VB_CHANNEL, LOC + QString("SwitchToInput(%1, %2)")
+            .arg(newInputNum).arg(setstarting));
+
     InputMap::const_iterator it = inputs.find(newInputNum);
     if (it == inputs.end() || (*it)->startChanNum.isEmpty())
         return false;
 
@@ -373,9 +488,9 @@ bool ChannelBase::SwitchToInput(int newI
 
     // input switching code would go here
 
     if (setstarting)
-        return SetChannelByString((*it)->startChanNum);
+        SelectChannel((*it)->startChanNum);
 
     return true;
 }
 
@@ -484,10 +599,9 @@ static bool is_input_busy(
     }
     return is_busy;
 }
 
-bool ChannelBase::IsInputAvailable(
-    int inputid, uint &mplexid_restriction) const
+bool ChannelBase::IsInputAvailable(int inputid, uint &mplexid_restriction) const
 {
     if (inputid < 0)
         return false;
 
@@ -650,28 +764,40 @@ bool ChannelBase::ChangeExternalChannel(
         _exit(CHANNEL__EXIT__EXECL_ERROR); // this exit is ok
     }
     else
     {   // child contains the pid of the new process
-        int status = 0, pid = 0;
+        QMutex      lock;
+        int         status = 0, pid = 0;
+
         VERBOSE(VB_CHANNEL, "Waiting for External Tuning program to exit");
 
         bool timed_out = false;
         uint timeout = 30; // how long to wait in seconds
         time_t start_time = time(0);
-        while (-1 != pid && !timed_out)
+        while (-1 != pid && !timed_out && !Aborted())
         {
-            sleep(1);
+            lock.lock();
+            tuneCond.wait(&lock, 500);  // sleep up to 0.5 seconds
             pid = waitpid(child, &status, WUNTRACED|WNOHANG);
             VERBOSE(VB_IMPORTANT, QString("ret_pid(%1) child(%2) status(0x%3)")
                     .arg(pid).arg(child).arg(status,0,16));
             if (pid==child)
+            {
+                lock.unlock();
                 break;
+            }
             else if (time(0) > (time_t)(start_time + timeout))
                 timed_out = true;
+            lock.unlock();
         }
-        if (timed_out)
+
+        if (timed_out || Aborted())
         {
-            VERBOSE(VB_IMPORTANT, "External Tuning program timed out, killing");
+            if (Aborted())
+                VERBOSE(VB_IMPORTANT, "Aborting External Tuning program");
+            else
+                VERBOSE(VB_IMPORTANT, "External Tuning program timed out, "
+                        "killing");
             kill(child, SIGTERM);
             usleep(500);
             kill(child, SIGKILL);
             return false;
Index: libs/libmythtv/channelbase.h
===================================================================
--- libs/libmythtv/channelbase.h.orig
+++ libs/libmythtv/channelbase.h
@@ -5,15 +5,31 @@
 
 // Qt headers
 #include <qmap.h>
 #include <qstringlist.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
+#include <qthread.h>
 
 // MythTV headers
 #include "channelutil.h"
 #include "inputinfo.h"
 #include "tv.h"
 
 class TVRec;
+class ChannelBase;
+
+/*
+ * Thread to run tunning process in
+ */
+class ChannelThread : public QThread
+{
+  public:
+    virtual void run(void);
+
+    QString      channel;
+    ChannelBase *tuner;
+};
 
 /** \class ChannelBase
  *  \brief Abstract class providing a generic interface to tuning hardware.
  *
@@ -23,21 +39,30 @@ class TVRec;
  */
 
 class ChannelBase
 {
- public:
+    friend class ChannelThread;
+
+  public:
+    enum Status { changeUnknown = 'U', changePending = 'P',
+                  changeFailed = 'F', changeSuccess = 'S' };
+
     ChannelBase(TVRec *parent);
-    virtual ~ChannelBase();
+    virtual ~ChannelBase(void);
 
     virtual bool Init(QString &inputname, QString &startchannel, bool setchan);
     virtual bool IsTunable(const QString &input, const QString &channum) const;
 
+    virtual void SelectChannel(const QString & chan);
+
+    Status GetStatus(void);
+    Status Wait(void);
+
     // Methods that must be implemented.
     /// \brief Opens the channel changing hardware for use.
     virtual bool Open(void) = 0;
     /// \brief Closes the channel changing hardware to use.
     virtual void Close(void) = 0;
-    virtual bool SetChannelByString(const QString &chan) = 0;
     /// \brief Reports whether channel is already open
     virtual bool IsOpen(void) const = 0;
 
     // Methods that one might want to specialize
@@ -82,10 +107,11 @@ class ChannelBase
     virtual void Renumber(uint srcid, const QString &oldChanNum,
                           const QString &newChanNum);
 
     // Input toggling convenience methods
-    virtual bool SwitchToInput(const QString &input);
-    virtual bool SwitchToInput(const QString &input, const QString &chan);
+
+//    virtual bool SwitchToInput(const QString &input); // not used?
+    virtual bool SelectInput(const QString &input, const QString &chan);
 
     virtual bool InitializeInputs(void);
 
     // Misc. Commands
@@ -108,25 +134,40 @@ class ChannelBase
     void SetCardID(uint _cardid) { cardid = _cardid; }
 
     virtual int GetCardID(void) const;
   protected:
+    virtual bool SetChannelByString(const QString &chan) = 0;
+
     /// \brief Switches to another input on hardware, 
     ///        and sets the channel is setstarting is true.
+    virtual bool SwitchToInput(const QString &input, const QString &chan);
     virtual bool SwitchToInput(int inputNum, bool setstarting);
     virtual bool IsInputAvailable(
         int inputNum, uint &mplexid_restriction) const;
 
     virtual bool ChangeExternalChannel(const QString &newchan);
     static void StoreInputChannels(const InputMap&);
     static void StoreDefaultInput(uint cardid, const QString &input);
 
+    bool Aborted();
+    void setStatus(Status status);
+    void TeardownAll(void);
+
     TVRec   *pParent;
     QString  curchannelname;
     int      currentInputID;
     bool     commfree;
     uint     cardid;
     InputMap inputs;
     DBChanList allchannels; ///< channels across all inputs
+
+    QWaitCondition  tuneCond;
+
+  private:
+    mutable ChannelThread   tuneThread;
+    Status   tuneStatus;
+    QMutex   thread_lock;
+    bool     abort_change;
 };
 
 #endif
 
Index: libs/libmythtv/channelchangemonitor.cpp
===================================================================
--- /dev/null
+++ libs/libmythtv/channelchangemonitor.cpp
@@ -0,0 +1,38 @@
+// -*- Mode: c++ -*-
+
+#include <cerrno>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#include "videodev_myth.h"
+#include "mythcontext.h"
+#include "channelchangemonitor.h"
+#include "v4lchannel.h"
+
+#define LOC QString("ChannelChangeM: ").arg(channel->GetDevice())
+#define LOC_ERR QString("ChannelChangeM, Error: ").arg(channel->GetDevice())
+
+ChannelChangeMonitor::ChannelChangeMonitor(
+    int db_cardnum, V4LChannel *_channel, uint64_t _flags) :
+    SignalMonitor(db_cardnum, _channel, _flags)
+{
+}
+
+void ChannelChangeMonitor::UpdateValues(void)
+{
+    if (!running || exit)
+        return;
+
+    if (!IsChannelTuned())
+        return;
+
+    {
+        QMutexLocker locker(&statusLock);
+        signalLock.SetValue(true);
+        signalStrength.SetValue(100);
+    }
+
+    EmitStatus();
+    SendMessageAllGood();
+}
+
Index: libs/libmythtv/channelchangemonitor.h
===================================================================
--- /dev/null
+++ libs/libmythtv/channelchangemonitor.h
@@ -0,0 +1,22 @@
+// -*- Mode: c++ -*-
+// Copyright (c) 2005, Daniel Thor Kristjansson
+
+#ifndef _CHANNEL_CHANGE_MONITOR_H_
+#define _CHANNEL_CHANGE_MONITOR_H_
+
+// MythTV headers
+#include "signalmonitor.h"
+
+class V4LChannel;
+
+class ChannelChangeMonitor : public SignalMonitor
+{
+  public:
+    ChannelChangeMonitor(
+        int db_cardnum, V4LChannel *_channel,
+        uint64_t _flags = kSigMon_WaitForSig);
+
+    virtual void UpdateValues(void);
+};
+
+#endif // _CHANNEL_CHANGE_MONITOR_H_
Index: libs/libmythtv/channelscan/channelscan_sm.cpp
===================================================================
--- libs/libmythtv/channelscan/channelscan_sm.cpp.orig
+++ libs/libmythtv/channelscan/channelscan_sm.cpp
@@ -1501,9 +1501,9 @@ void ChannelScanSM::ScanTransport(const 
         GetDTVSignalMonitor()->SetChannel(-1,-1);
     }
 
     // Start signal monitor for this channel
-    signalMonitor->Start();
+    signalMonitor->Start(false);
 
     timer.start();
     waitingForTables = true;
 }
Index: libs/libmythtv/channelscan/channelscan_sm.h
===================================================================
--- libs/libmythtv/channelscan/channelscan_sm.h.orig
+++ libs/libmythtv/channelscan/channelscan_sm.h
@@ -73,8 +73,9 @@ class AnalogSignalHandler : public Signa
     AnalogSignalHandler(ChannelScanSM *_siscan) : siscan(_siscan) { }
 
   public slots:
     virtual inline void AllGood(void);
+    virtual void StatusChannelTuned(const SignalMonitorValue&) { }
     virtual void StatusSignalLock(const SignalMonitorValue&) { }
     virtual void StatusSignalStrength(const SignalMonitorValue&) { }
 
   private:
Index: libs/libmythtv/channelscan/channelscanner_cli.cpp
===================================================================
--- libs/libmythtv/channelscan/channelscanner_cli.cpp.orig
+++ libs/libmythtv/channelscan/channelscanner_cli.cpp
@@ -91,8 +91,10 @@ void ChannelScannerCLI::HandleEvent(cons
             status_complete = scanEvent->intValue();
             break;
         case ScannerEvent::SetStatusRotorPosition:
             break;
+        case ScannerEvent::SetStatusChannelTuned:
+            break;
         case ScannerEvent::SetStatusSignalLock:
             status_lock = scanEvent->intValue();
             break;
         case ScannerEvent::SetStatusSignalToNoise:
Index: libs/libmythtv/channelscan/channelscanner_gui.cpp
===================================================================
--- libs/libmythtv/channelscan/channelscanner_gui.cpp.orig
+++ libs/libmythtv/channelscan/channelscanner_gui.cpp
@@ -155,8 +155,10 @@ void ChannelScannerGUI::HandleEvent(cons
             break;
         case ScannerEvent::SetStatusRotorPosition:
             scanStage->SetStatusRotorPosition(scanEvent->intValue());
             break;
+        case ScannerEvent::SetStatusChannelTuned:
+            break;
         case ScannerEvent::SetStatusSignalLock:
             scanStage->SetStatusLock(scanEvent->intValue());
             break;
         case ScannerEvent::SetStatusSignalToNoise:
Index: libs/libmythtv/channelscan/scanmonitor.cpp
===================================================================
--- libs/libmythtv/channelscan/scanmonitor.cpp.orig
+++ libs/libmythtv/channelscan/scanmonitor.cpp
@@ -106,8 +106,13 @@ void ScanMonitor::StatusRotorPosition(co
     post_event(this, ScannerEvent::SetStatusRotorPosition,
                val.GetNormalizedValue(0, 65535));
 }
 
+void ScanMonitor::StatusChannelTuned(const SignalMonitorValue &val)
+{
+    post_event(this, ScannerEvent::SetStatusChannelTuned, val.GetValue());
+}
+
 void ScanMonitor::StatusSignalLock(const SignalMonitorValue &val)
 {
     post_event(this, ScannerEvent::SetStatusSignalLock, val.GetValue());
 }
Index: libs/libmythtv/channelscan/scanmonitor.h
===================================================================
--- libs/libmythtv/channelscan/scanmonitor.h.orig
+++ libs/libmythtv/channelscan/scanmonitor.h
@@ -63,8 +63,9 @@ class ScanMonitor :
     void ScanComplete(void);
 
     // SignalMonitorListener
     virtual void AllGood(void) { }
+    virtual void StatusChannelTuned(const SignalMonitorValue&);
     virtual void StatusSignalLock(const SignalMonitorValue&);
     virtual void StatusSignalStrength(const SignalMonitorValue&);
 
     // DVBSignalMonitorListener
@@ -97,8 +98,9 @@ class ScannerEvent : public QEvent
         SetStatusRotorPosition,
         SetStatusSignalToNoise,
         SetStatusSignalStrength,
         SetStatusSignalLock,
+        SetStatusChannelTuned
     };
 
     ScannerEvent(TYPE t) :
         QEvent((QEvent::Type)(t + QEvent::User)),
Index: libs/libmythtv/dtvsignalmonitor.cpp
===================================================================
--- libs/libmythtv/dtvsignalmonitor.cpp.orig
+++ libs/libmythtv/dtvsignalmonitor.cpp
@@ -24,8 +24,9 @@ DTVSignalMonitor::DTVSignalMonitor(int d
                                    DTVChannel *_channel,
                                    uint64_t wait_for_mask)
     : SignalMonitor(db_cardnum, _channel, wait_for_mask),
       stream_data(NULL),
+      channelTuned(QObject::tr("Channel Tuned"), "tuned", 3, true, 0, 3, 0),
       seenPAT(QObject::tr("Seen")+" PAT", "seen_pat", 1, true, 0, 1, 0),
       seenPMT(QObject::tr("Seen")+" PMT", "seen_pmt", 1, true, 0, 1, 0),
       seenMGT(QObject::tr("Seen")+" MGT", "seen_mgt", 1, true, 0, 1, 0),
       seenVCT(QObject::tr("Seen")+" VCT", "seen_vct", 1, true, 0, 1, 0),
@@ -62,8 +63,15 @@ DTVChannel *DTVSignalMonitor::GetDTVChan
 QStringList DTVSignalMonitor::GetStatusList(bool kick)
 {
     QStringList list = SignalMonitor::GetStatusList(kick);
     QMutexLocker locker(&statusLock);
+
+    // tuned?
+    if (flags & kSigMon_Tuned)
+    {
+        list<<channelTuned.GetName()<<channelTuned.GetStatus();
+    }
+
     // mpeg tables
     if (flags & kDTVSigMon_WaitForPAT)
     {
         list<<seenPAT.GetName()<<seenPAT.GetStatus();
@@ -137,8 +145,9 @@ void DTVSignalMonitor::RemoveFlags(uint6
 
 void DTVSignalMonitor::UpdateMonitorValues(void)
 {
     QMutexLocker locker(&statusLock);
+    channelTuned.SetValue((flags & kSigMon_Tuned)      ? 3 : 1);
     seenPAT.SetValue(    (flags & kDTVSigMon_PATSeen)  ? 1 : 0);
     seenPMT.SetValue(    (flags & kDTVSigMon_PMTSeen)  ? 1 : 0);
     seenMGT.SetValue(    (flags & kDTVSigMon_MGTSeen)  ? 1 : 0);
     seenVCT.SetValue(    (flags & kDTVSigMon_VCTSeen)  ? 1 : 0);
Index: libs/libmythtv/dtvsignalmonitor.h
===================================================================
--- libs/libmythtv/dtvsignalmonitor.h.orig
+++ libs/libmythtv/dtvsignalmonitor.h
@@ -110,8 +110,9 @@ class DTVSignalMonitor : public SignalMo
 
   protected:
     MPEGStreamData    *stream_data;
     vector<uint>       eit_pids;
+    SignalMonitorValue channelTuned;
     SignalMonitorValue seenPAT;
     SignalMonitorValue seenPMT;
     SignalMonitorValue seenMGT;
     SignalMonitorValue seenVCT;
Index: libs/libmythtv/dvbsignalmonitor.cpp
===================================================================
--- libs/libmythtv/dvbsignalmonitor.cpp.orig
+++ libs/libmythtv/dvbsignalmonitor.cpp
@@ -229,8 +229,11 @@ void DVBSignalMonitor::UpdateValues(void
         update_done = true;
         return;
     }
 
+    if (!IsChannelTuned())
+        return;
+
     AddFlags(kSigMon_WaitForSig);
  
     DVBChannel *dvbchannel = GetDVBChannel();
     if (!dvbchannel)
Index: libs/libmythtv/firewiresignalmonitor.cpp
===================================================================
--- libs/libmythtv/firewiresignalmonitor.cpp.orig
+++ libs/libmythtv/firewiresignalmonitor.cpp
@@ -189,8 +189,11 @@ void FirewireSignalMonitor::UpdateValues
 {
     if (!running || exit)
         return;
 
+    if (!IsChannelTuned())
+        return;
+
     if (dtvMonitorRunning)
     {
         EmitStatus();
         if (IsAllGood())
Index: libs/libmythtv/hdhrchannel.cpp
===================================================================
--- libs/libmythtv/hdhrchannel.cpp.orig
+++ libs/libmythtv/hdhrchannel.cpp
@@ -142,8 +142,11 @@ bool HDHRChannel::SetChannelByString(con
     uint mplexid_restriction;
     if (!IsInputAvailable(currentInputID, mplexid_restriction))
         return false;
 
+    if (Aborted())
+	return false;
+
     // Fetch tuning data from the database.
     QString tvformat, modulation, freqtable, freqid, si_std;
     int finetune;
     uint64_t frequency;
Index: libs/libmythtv/hdhrsignalmonitor.cpp
===================================================================
--- libs/libmythtv/hdhrsignalmonitor.cpp.orig
+++ libs/libmythtv/hdhrsignalmonitor.cpp
@@ -104,8 +104,11 @@ void HDHRSignalMonitor::UpdateValues(voi
         update_done = true;
         return;
     }
 
+    if (!IsChannelTuned())
+        return;
+
     struct hdhomerun_tuner_status_t status;
     streamHandler->GetTunerStatus(&status);
 
     uint sig = status.signal_strength;
Index: libs/libmythtv/iptvsignalmonitor.cpp
===================================================================
--- libs/libmythtv/iptvsignalmonitor.cpp.orig
+++ libs/libmythtv/iptvsignalmonitor.cpp
@@ -118,8 +118,11 @@ void IPTVSignalMonitor::UpdateValues(voi
 {
     if (!running || exit)
         return;
 
+    if (!IsChannelTuned())
+        return;
+
     if (dtvMonitorRunning)
     {
         EmitStatus();
         if (IsAllGood())
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro.orig
+++ libs/libmythtv/libmythtv.pro
@@ -449,8 +449,11 @@ using_backend {
         DEFINES += USING_OSS
         LIBS += $$OSS_LIBS
     }
 
+    HEADERS += channelchangemonitor.h
+    SOURCES += channelchangemonitor.cpp
+
     # Support for Video4Linux devices
     using_v4l {
         HEADERS += v4lchannel.h                analogsignalmonitor.h
         SOURCES += v4lchannel.cpp              analogsignalmonitor.cpp
Index: libs/libmythtv/signalmonitor.cpp
===================================================================
--- libs/libmythtv/signalmonitor.cpp.orig
+++ libs/libmythtv/signalmonitor.cpp
@@ -7,8 +7,9 @@
 #include <unistd.h>
 
 // MythTV headers
 #include "mythcontext.h"
+#include "tv_rec.h"
 #include "signalmonitor.h"
 #include "compat.h"
 #include "mythverbose.h"
 
@@ -41,8 +42,10 @@ extern "C" {
 #   include "firewiresignalmonitor.h"
 #   include "firewirechannel.h"
 #endif
 
+#include "channelchangemonitor.h"
+
 #undef DBG_SM
 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
     "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
 
@@ -92,17 +95,18 @@ SignalMonitor *SignalMonitor::Init(QStri
     }
 #endif
 
 #ifdef USING_V4L
+#if 0 // Just use ChannelChangeMonitor for these types
     if ((cardtype.toUpper() == "V4L") ||
-        (cardtype.toUpper() == "MPEG") || 
-        (cardtype.toUpper() == "HDPVR"))
+        (cardtype.toUpper() == "MPEG"))
     {
         V4LChannel *chan = dynamic_cast<V4LChannel*>(channel);
         if (chan)
             signalMonitor = new AnalogSignalMonitor(db_cardnum, chan);
     }
 #endif
+#endif
 
 #ifdef USING_HDHOMERUN
     if (cardtype.toUpper() == "HDHOMERUN")
     {
@@ -131,8 +135,15 @@ SignalMonitor *SignalMonitor::Init(QStri
 #endif
 
     if (!signalMonitor)
     {
+        V4LChannel *chan = dynamic_cast<V4LChannel*>(channel);
+        if (chan)
+            signalMonitor = new ChannelChangeMonitor(db_cardnum, chan);
+    }
+
+    if (!signalMonitor)
+    {
         VERBOSE(VB_IMPORTANT,
                 QString("Failed to create signal monitor in Init(%1, %2, 0x%3)")
                 .arg(cardtype).arg(db_cardnum).arg((long)channel,0,16));
     }
@@ -159,13 +170,15 @@ SignalMonitor::SignalMonitor(int _captur
       capturecardnum(_capturecardnum), flags(wait_for_mask),
       update_rate(25),                 minimum_update_rate(5),
       running(false),                  exit(false),
       update_done(false),              notify_frontend(true),
-      error(""),
+      is_tuned(false),                 tablemon(false),
+      eit_scan(false),                 error(""),
       signalLock    (QObject::tr("Signal Lock"),  "slock",
                      1, true, 0,   1, 0),
       signalStrength(QObject::tr("Signal Power"), "signal",
                      0, true, 0, 100, 0),
+      channelTuned("Channel Tuned", "tuned", 3, true, 0, 3, 0),
       statusLock(QMutex::Recursive)
 {
 }
 
@@ -201,13 +214,17 @@ bool SignalMonitor::HasAnyFlag(uint64_t 
 
 /** \fn SignalMonitor::Start()
  *  \brief Start signal monitoring thread.
  */
-void SignalMonitor::Start()
+void SignalMonitor::Start(bool waitfor_tune)
 {
     DBG_SM("Start", "begin");
     {
         QMutexLocker locker(&startStopLock);
+
+        // When used for scanning, don't wait for the tuning thread
+        is_tuned = !waitfor_tune;
+
         if (!running)
         {
             int rval = pthread_create(
                 &monitor_thread, NULL, SpawnMonitorLoop, this);
@@ -278,8 +295,9 @@ QStringList SignalMonitor::GetStatusList
         UpdateValues();
 
     QStringList list;
     statusLock.lock();
+    list<<channelTuned.GetName()<<channelTuned.GetStatus();
     list<<signalLock.GetName()<<signalLock.GetStatus();
     if (HasFlags(kSigMon_WaitForSig))
         list<<signalStrength.GetName()<<signalStrength.GetStatus();
     statusLock.unlock();
@@ -305,9 +323,8 @@ void SignalMonitor::MonitorLoop()
         {
             QStringList slist = GetStatusList(false);
             MythEvent me(QString("SIGNAL %1").arg(capturecardnum), slist);
             gContext->dispatch(me);
-            //cerr<<"sent SIGNAL"<<endl;
         }
 
         usleep(update_rate * 1000);
     }
@@ -440,8 +457,11 @@ void SignalMonitor::SendMessage(
             break;
         case kStatusSignalStrength:
             listener->StatusSignalStrength(val);
             break;
+        case kStatusChannelTuned:
+            listener->StatusChannelTuned(val);
+            break;
         case kStatusSignalToNoise:
             if (dvblistener)
                 dvblistener->StatusSignalToNoise(val);
             break;
@@ -460,8 +480,42 @@ void SignalMonitor::SendMessage(
         }
     }
 }
 
+bool SignalMonitor::IsChannelTuned(void)
+{
+    if (is_tuned)
+        return true;
+
+    ChannelBase::Status status = channel->GetStatus();
+    QMutexLocker locker(&statusLock);
+
+    switch (status) {
+      case ChannelBase::changePending:
+        channelTuned.SetValue(1);
+        break;
+      case ChannelBase::changeFailed:
+        channelTuned.SetValue(2);
+        break;
+      case ChannelBase::changeSuccess:
+        channelTuned.SetValue(3);
+        break;
+    }
+
+    EmitStatus();
+
+    if (status == ChannelBase::changeSuccess)
+    {
+        if (tablemon)
+            pParent->SetupDTVSignalMonitor(eit_scan);
+
+        is_tuned = true;
+        return true;
+    }
+
+    return false;
+}
+
 void SignalMonitor::SendMessageAllGood(void)
 {
     QMutexLocker locker(&listenerLock);
     for (uint i = 0; i < listeners.size(); i++)
@@ -469,8 +523,9 @@ void SignalMonitor::SendMessageAllGood(v
 }
 
 void SignalMonitor::EmitStatus(void)
 {
+    SendMessage(kStatusChannelTuned, channelTuned);
     SendMessage(kStatusSignalLock, signalLock);
     if (HasFlags(kSigMon_WaitForSig))
         SendMessage(kStatusSignalStrength,    signalStrength);
 }
Index: libs/libmythtv/signalmonitor.h
===================================================================
--- libs/libmythtv/signalmonitor.h.orig
+++ libs/libmythtv/signalmonitor.h
@@ -26,8 +26,10 @@ using namespace std;
     "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
 
 inline QString sm_flags_to_string(uint64_t);
 
+class TVRec;
+
 class SignalMonitor
 {
   public:
     /// Returns true iff the card type supports signal monitoring.
@@ -39,9 +41,9 @@ class SignalMonitor
 
     // // // // // // // // // // // // // // // // // // // // // // // //
     // Control  // // // // // // // // // // // // // // // // // // // //
 
-    virtual void Start();
+    virtual void Start(bool waitfor_tune);
     virtual void Stop();
     virtual void Kick();
     virtual bool WaitForLock(int timeout = -1);
 
@@ -83,8 +85,15 @@ class SignalMonitor
      *         otherwise they are not.
      */
     void SetNotifyFrontend(bool notify) { notify_frontend = notify; }
 
+    /** \brief Indicate if table monitoring is needed
+     *  \param monitor if true parent->SetupDTVSignalMonitor is called
+     *         after the channel is tuned.
+     */
+    void SetMonitoring(TVRec * parent, bool EITscan, bool monitor)
+        { pParent = parent; eit_scan = EITscan, tablemon = monitor; }
+
     /** \brief Sets the number of milliseconds between signal monitoring
      *         attempts in the signal monitoring thread.
      *
      *   Defaults to 25 milliseconds.
@@ -96,8 +105,9 @@ class SignalMonitor
     // // // // // // // // // // // // // // // // // // // // // // // //
     // Listeners   // // // // // // // // // // // // // // // // // // //
     void AddListener(SignalMonitorListener *listener);
     void RemoveListener(SignalMonitorListener *listener);
+
     void SendMessage(SignalMonitorMessageType type,
                      const SignalMonitorValue &val);
     void SendMessageAllGood(void);
     virtual void EmitStatus(void);
@@ -108,8 +118,10 @@ class SignalMonitor
     
     static void* SpawnMonitorLoop(void*);
     virtual void MonitorLoop();
 
+    bool IsChannelTuned(void);
+
     /// \brief This should be overridden to actually do signal monitoring.
     virtual void UpdateValues() { ; }
 
   public:
@@ -139,8 +151,10 @@ class SignalMonitor
     static const uint64_t kFWSigMon_PowerSeen   = 0x0000000100ULL;
     /// We've seen something indicating whether the data stream is encrypted
     static const uint64_t kDTVSigMon_CryptSeen  = 0x0000000200ULL;
 
+    static const uint64_t kSigMon_Tuned         = 0x0000000400ULL;
+
     /// We've seen a PAT matching our requirements
     static const uint64_t kDTVSigMon_PATMatch   = 0x0000001000ULL;
     /// We've seen a PMT matching our requirements
     static const uint64_t kDTVSigMon_PMTMatch   = 0x0000002000ULL;
@@ -184,20 +198,25 @@ class SignalMonitor
 
   protected:
     pthread_t    monitor_thread;
     ChannelBase *channel;
+    TVRec       *pParent;
     int          capturecardnum;
     uint64_t     flags;
     int          update_rate;
     uint         minimum_update_rate;
     bool         running;
     bool         exit;
     bool         update_done;
     bool         notify_frontend;
+    bool         is_tuned;
+    bool         tablemon;
+    bool         eit_scan;
     QString      error;
 
     SignalMonitorValue signalLock;
     SignalMonitorValue signalStrength;
+    SignalMonitorValue channelTuned;
 
     vector<SignalMonitorListener*> listeners;
 
     QMutex             startStopLock;
Index: libs/libmythtv/signalmonitorlistener.h
===================================================================
--- libs/libmythtv/signalmonitorlistener.h.orig
+++ libs/libmythtv/signalmonitorlistener.h
@@ -8,8 +8,9 @@
 #include "signalmonitorvalue.h"
 
 typedef enum {
     kAllGood,
+    kStatusChannelTuned,
     kStatusSignalLock,
     kStatusSignalStrength,
     kStatusSignalToNoise,
     kStatusBitErrorRate,
@@ -29,8 +30,15 @@ class MPUBLIC SignalMonitorListener
      *         has been started.
      */
     virtual void AllGood(void) = 0;
 
+    /** \brief Singal to be sent with change change status.
+     *
+     *   Note: Signals are only sent once the monitoring thread
+     *         has been started.
+     */
+    virtual void StatusChannelTuned(const SignalMonitorValue&) = 0;
+
     /** \brief Signal to be sent as true when it is safe to begin
      *   or continue recording, and false if it may not be safe.
      *
      *   Note: Signals are only sent once the monitoring thread 
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp.orig
+++ libs/libmythtv/tv_play.cpp
@@ -7160,8 +7160,9 @@ void TV::UpdateOSDSignal(const PlayerCon
     uint  sig  = 0;
     float snr  = 0.0f;
     uint  ber  = 0xffffffff;
     int   pos  = -1;
+    int   tuned = -1;
     QString pat(""), pmt(""), mgt(""), vct(""), nit(""), sdt(""), crypt("");
     QString err = QString::null, msg = QString::null;
     for (it = slist.begin(); it != slist.end(); ++it)
     {
@@ -7186,8 +7187,10 @@ void TV::UpdateOSDSignal(const PlayerCon
         else if ("ber" == it->GetShortName())
             ber = it->GetValue();
         else if ("pos" == it->GetShortName())
             pos = it->GetValue();
+	else if ("tuned" == it->GetShortName())
+	    tuned = it->GetValue();
         else if ("seen_pat" == it->GetShortName())
             pat = it->IsGood() ? "a" : "_";
         else if ("matching_pat" == it->GetShortName())
             pat = it->IsGood() ? "A" : pat;
@@ -7219,8 +7222,9 @@ void TV::UpdateOSDSignal(const PlayerCon
     if (sig)
         infoMap["signal"] = QString::number(sig); // use normalized value
 
     bool    allGood = SignalMonitorValue::AllGood(slist);
+    char    tuneCode;
     QString slock   = ("1" == infoMap["slock"]) ? "L" : "l";
     QString lockMsg = (slock=="L") ? tr("Partial Lock") : tr("No Lock");
     QString sigMsg  = allGood ? tr("Lock") : lockMsg;
 
@@ -7231,11 +7235,20 @@ void TV::UpdateOSDSignal(const PlayerCon
         sigDesc += " | " + tr("BE %1", "Bit Errors").arg(ber, 2);
     if ((pos >= 0) && (pos < 100))
         sigDesc += " | " + tr("Rotor %1\%").arg(pos,2);
 
-    sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8) %9")
-        .arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct)
-        .arg(nit).arg(sdt).arg(crypt).arg(sigMsg);
+    if (tuned == 1)
+        tuneCode = 't';
+    else if (tuned == 2)
+        tuneCode = 'F';
+    else if (tuned == 3)
+        tuneCode = 'T';
+    else
+        tuneCode = '_';
+
+    sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7%8%9) %10")
+	      .arg(tuneCode).arg(slock).arg(pat).arg(pmt).arg(mgt).arg(vct)
+	      .arg(nit).arg(sdt).arg(crypt).arg(sigMsg);
 
     if (!err.isEmpty())
         sigDesc = err;
     else if (!msg.isEmpty())
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp.orig	2009-11-23 23:29:25.300257067 +0000
+++ libs/libmythtv/tv_rec.cpp	2009-11-23 23:39:34.910199599 +0000
@@ -378,7 +378,8 @@
 void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft,
                           bool hasLater)
 {
-    QMutexLocker lock(&stateChangeLock);
+    QMutexLocker statelock(&stateChangeLock);
+    QMutexLocker pendlock(&pendingRecLock);
 
     if (secsleft < 0)
     {
@@ -416,10 +417,10 @@
 
     pendingRecordings[rcinfo->cardid].possibleConflicts = cardids;
 
-    stateChangeLock.unlock();
+    statelock.unlock();
     for (uint i = 0; i < cardids.size(); i++)
         RemoteRecordPending(cardids[i], rcinfo, secsleft, hasLater);
-    stateChangeLock.lock();
+    statelock.relock();
 }
 
 /** \fn TVRec::SetPseudoLiveTVRecording(ProgramInfo*)
@@ -451,6 +452,7 @@
  */
 void TVRec::CancelNextRecording(bool cancel)
 {
+    QMutexLocker pendlock(&pendingRecLock);
     VERBOSE(VB_RECORD, LOC + "CancelNextRecording("<<cancel<<") -- begin");
 
     PendingMap::iterator it = pendingRecordings.find(cardid);
@@ -535,13 +537,22 @@
         return retval;
     }
 
-    PendingMap::iterator it = pendingRecordings.find(cardid);
     bool cancelNext = false;
+    bool has_pending;
+
+    pendingRecLock.lock();
+    PendingMap::iterator it = pendingRecordings.find(cardid);
     if (it != pendingRecordings.end())
     {
         (*it).ask = (*it).doNotAsk = false;
         cancelNext = (*it).canceled;
+        has_pending = true;
     }
+    else
+        has_pending = false;
+
+    PendingInfo pendinfo = *it;
+    pendingRecLock.unlock();
 
     // Flush out events...
     WaitForEventThreadSleep();
@@ -553,11 +564,10 @@
 
     // If the needed input is in a shared input group, and we are
     // not canceling the recording anyway, check other recorders
-    if (!cancelNext &&
-        (it != pendingRecordings.end()) && (*it).possibleConflicts.size())
+    if (!cancelNext && has_pending && pendinfo.possibleConflicts.size())
     {
         VERBOSE(VB_RECORD, LOC + "Checking input group recorders - begin");
-        vector<uint> &cardids = (*it).possibleConflicts;
+        vector<uint> &cardids = pendinfo.possibleConflicts;
 
         uint mplexid = 0, sourceid = 0;
         vector<uint> cardids2;
@@ -580,8 +590,8 @@
 
             if (is_busy && !sourceid)
             {
-                mplexid  = (*it).info->GetMplexID();
-                sourceid = (*it).info->sourceid;
+                mplexid  = pendinfo.info->GetMplexID();
+                sourceid = pendinfo.info->sourceid;
             }
 
             if (is_busy &&
@@ -967,7 +977,6 @@
 void TVRec::ChangeState(TVState nextState)
 {
     QMutexLocker lock(&stateChangeLock);
-
     desiredNextState = nextState;
     changeState = true;
     WakeEventLoop();
@@ -1452,9 +1461,12 @@
             QDateTime now   = QDateTime::currentDateTime();
             bool has_finish = HasFlags(kFlagFinishRecording);
             bool has_rec    = pseudoLiveTVRecording;
+            bool enable_ui  = true;
+
+            pendingRecLock.lock();
             bool rec_soon   =
                 pendingRecordings.find(cardid) != pendingRecordings.end();
-            bool enable_ui  = true;
+            pendingRecLock.unlock();
 
             if (has_rec && (has_finish || (now > recordEndTime)))
             {
@@ -1625,6 +1637,8 @@
 
 void TVRec::HandlePendingRecordings(void)
 {
+    QMutexLocker pendlock(&pendingRecLock);
+
     if (pendingRecordings.empty())
         return;
 
@@ -1926,7 +1940,7 @@
  *   This method also grabs the ATSCStreamData() from the recorder
  *   if possible, or creates one if needed.
  */
-bool TVRec::SetupDTVSignalMonitor(void)
+bool TVRec::SetupDTVSignalMonitor(bool EITscan)
 {
     VERBOSE(VB_RECORD, LOC + "Setting up table monitoring.");
 
@@ -2060,6 +2074,12 @@
                      SignalMonitor::kDVBSigMon_WaitForPos);
         sm->SetRotorTarget(1.0f);
 
+        if (EITscan)
+        {
+            sm->GetStreamData()->SetVideoStreamsRequired(0);
+            sm->IgnoreEncrypted(true);
+        }
+
         VERBOSE(VB_RECORD, LOC + "Successfully set up MPEG table monitoring.");
         return true;
     }
@@ -2081,7 +2101,7 @@
  *  \param notify   If set we notify the frontend of the signal values
  *  \return true on success, false on failure
  */
-bool TVRec::SetupSignalMonitor(bool tablemon, bool notify)
+bool TVRec::SetupSignalMonitor(bool tablemon, bool EITscan, bool notify)
 {
     VERBOSE(VB_RECORD, LOC + "SetupSignalMonitor("
             <<tablemon<<", "<<notify<<")");
@@ -2097,27 +2117,22 @@
     // make sure statics are initialized
     SignalMonitorValue::Init();
 
-    if (SignalMonitor::IsSupported(genOpt.cardtype) && channel->Open())
-        signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid, channel);
+    if (channel->Open())
+        signalMonitor = SignalMonitor::Init(genOpt.cardtype, cardid,
+                                            channel);
 
     if (signalMonitor)
     {
         VERBOSE(VB_RECORD, LOC + "Signal monitor successfully created");
-        // If this is a monitor for Digital TV, initialize table monitors
-        if (GetDTVSignalMonitor() && tablemon && !SetupDTVSignalMonitor())
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR +
-                    "Failed to setup digital signal monitoring");
-
-            return false;
-        }
 
+        signalMonitor->SetMonitoring(this, EITscan,
+                                     GetDTVSignalMonitor() && tablemon);
         signalMonitor->AddListener(this);
         signalMonitor->SetUpdateRate(kSignalMonitoringRate);
         signalMonitor->SetNotifyFrontend(notify);
 
         // Start the monitoring thread
-        signalMonitor->Start();
+        signalMonitor->Start(true);
     }
 
     return true;
@@ -2389,7 +2404,7 @@
     {
         for (uint j = 0; j < kSpacerListSize; j++)
         {
-	    QString qprefix = add_spacer(
+            QString qprefix = add_spacer(
                 prefix, (QString(spacers[j]) == "_") ? "\\_" : spacers[j]);
             query.prepare(basequery.arg(qprefix) + cardquery[i]);
 
@@ -2522,8 +2537,6 @@
  */
 bool TVRec::IsBusy(TunedInputInfo *busy_input, int time_buffer) const
 {
-    QMutexLocker lock(&stateChangeLock);
-
     TunedInputInfo dummy;
     if (!busy_input)
         busy_input = &dummy;
@@ -2545,6 +2558,7 @@
         chanid              = channel->GetChanID();
     }
 
+    QMutexLocker pendlock(&pendingRecLock);
     PendingMap::const_iterator it = pendingRecordings.find(cardid);
     if (!busy_input->inputid && (it != pendingRecordings.end()))
     {
@@ -3227,7 +3241,7 @@
         }
         else if (BROWSE_RIGHT == direction)
         {
-	        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
+                chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
             compare = ">";
             sortorder = "asc";
         }
@@ -3717,6 +3731,11 @@
 void TVRec::TuningFrequency(const TuningRequest &request)
 {
     DTVChannel *dtvchan = GetDTVChannel();
+
+    bool livetv = request.flags & kFlagLiveTV;
+    bool antadj = request.flags & kFlagAntennaAdjust;
+    bool has_dummy = false;
+
     if (dtvchan)
     {
         MPEGStreamData *mpeg = NULL;
@@ -3733,16 +3752,14 @@
 
         if (request.minorChan && (tuningmode == "atsc"))
         {
-            channel->SetChannelByString(request.channel);
-
+            channel->SelectChannel(request.channel);
             ATSCStreamData *atsc = dynamic_cast<ATSCStreamData*>(mpeg);
             if (atsc)
                 atsc->SetDesiredChannel(request.majorChan, request.minorChan);
         }
         else if (request.progNum >= 0)
         {
-            channel->SetChannelByString(request.channel);
-
+            channel->SelectChannel(request.channel);
             if (mpeg)
                 mpeg->SetDesiredProgram(request.progNum);
         }
@@ -3771,9 +3788,11 @@
     if (channel && !channum.isEmpty())
     {
         if (!input.isEmpty())
-            ok = channel->SwitchToInput(input, channum);
+            channel->SelectInput(input, channum);
         else
-            ok = channel->SetChannelByString(channum);
+            channel->SelectChannel(channum);
+
+        ok = true;
     }
 
     if (!ok)
@@ -3800,13 +3819,7 @@
         }
     }
 
-    bool livetv = request.flags & kFlagLiveTV;
-    bool antadj = request.flags & kFlagAntennaAdjust;
-    bool use_sm = SignalMonitor::IsRequired(genOpt.cardtype);
-    bool use_dr = use_sm && (livetv || antadj);
-    bool has_dummy = false;
-
-    if (use_dr)
+    if (livetv || antadj)
     {
         // We need there to be a ringbuffer for these modes
         bool ok;
@@ -3832,60 +3845,51 @@
         has_dummy = true;
     }
 
-    // Start signal monitoring for devices capable of monitoring
-    if (use_sm)
+    // Start signal (or channel change) monitoring
+    VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor");
+    bool error = false;
+    if (!SetupSignalMonitor(!antadj, request.flags & kFlagEITScan,
+                            livetv | antadj))
     {
-        VERBOSE(VB_RECORD, LOC + "Starting Signal Monitor");
-        bool error = false;
-        if (!SetupSignalMonitor(!antadj, livetv | antadj))
-        {
-            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor");
-            if (signalMonitor)
-            {
-                delete signalMonitor;
-                signalMonitor = NULL;
-            }
-
-            // pretend the signal monitor is running to prevent segfault
-            SetFlags(kFlagSignalMonitorRunning);
-            ClearFlags(kFlagWaitingForSignal);
-            error = true;
-        }
-
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to setup signal monitor");
         if (signalMonitor)
         {
-            if (request.flags & kFlagEITScan)
-            {
-                GetDTVSignalMonitor()->GetStreamData()->
-                    SetVideoStreamsRequired(0);
-                GetDTVSignalMonitor()->IgnoreEncrypted(true);
-            }
-
-            SetFlags(kFlagSignalMonitorRunning);
-            ClearFlags(kFlagWaitingForSignal);
-            if (!antadj)
-                SetFlags(kFlagWaitingForSignal);
+            delete signalMonitor;
+            signalMonitor = NULL;
         }
 
-        if (has_dummy && ringBuffer)
-        {
-            // Make sure recorder doesn't point to bogus ringbuffer before
-            // it is potentially restarted without a new ringbuffer, if
-            // the next channel won't tune and the user exits LiveTV.
-            if (recorder)
-                recorder->SetRingBuffer(NULL);
+        // pretend the signal monitor is running to prevent segfault
+        SetFlags(kFlagSignalMonitorRunning);
+        ClearFlags(kFlagWaitingForSignal);
+        error = true;
+    }
 
-            SetFlags(kFlagDummyRecorderRunning);
-            VERBOSE(VB_RECORD, "DummyDTVRecorder -- started");
-            SetFlags(kFlagRingBufferReady);
-        }
+    if (signalMonitor)
+    {
+        SetFlags(kFlagSignalMonitorRunning);
+        ClearFlags(kFlagWaitingForSignal);
+        if (!antadj)
+            SetFlags(kFlagWaitingForSignal);
+    }
 
-        // if we had problems starting the signal monitor,
-        // we don't want to start the recorder...
-        if (error)
-            return;
+    if (has_dummy && ringBuffer)
+    {
+        // Make sure recorder doesn't point to bogus ringbuffer before
+        // it is potentially restarted without a new ringbuffer, if
+        // the next channel won't tune and the user exits LiveTV.
+        if (recorder)
+            recorder->SetRingBuffer(NULL);
+
+        SetFlags(kFlagDummyRecorderRunning);
+        VERBOSE(VB_RECORD, "DummyDTVRecorder -- started");
+        SetFlags(kFlagRingBufferReady);
     }
 
+    // if we had problems starting the signal monitor,
+    // we don't want to start the recorder...
+    if (error)
+        return;
+
     // Request a recorder, if the command is a recording command
     ClearFlags(kFlagNeedToStartRecorder);
     if (request.flags & kFlagRec && !antadj)

Index: libs/libmythtv/tv_rec.h
===================================================================
--- libs/libmythtv/tv_rec.h.orig
+++ libs/libmythtv/tv_rec.h
@@ -160,8 +160,9 @@ typedef QMap<uint,PendingInfo> PendingMa
 
 class MPUBLIC TVRec : public SignalMonitorListener
 {
     friend class TuningRequest;
+    friend class SignalMonitor;
 
   public:
     TVRec(int capturecardnum);
    ~TVRec(void);
@@ -254,16 +255,18 @@ class MPUBLIC TVRec : public SignalMonit
 
     static TVRec *GetTVRec(uint cardid);
 
     virtual void AllGood(void) { WakeEventLoop(); }
+    virtual void StatusChannelTuned(const SignalMonitorValue&) { }
     virtual void StatusSignalLock(const SignalMonitorValue&) { }
     virtual void StatusSignalStrength(const SignalMonitorValue&) { }
 
   protected:
     void RunTV(void);
     bool WaitForEventThreadSleep(bool wake = true, ulong time = ULONG_MAX);
     static void *EventThread(void *param);
     static void *RecorderThread(void *param);
+    bool SetupDTVSignalMonitor(bool EITscan);
 
   private:
     void SetRingBuffer(RingBuffer *);
     void SetPseudoLiveTVRecording(ProgramInfo*);
@@ -293,10 +296,10 @@ class MPUBLIC TVRec : public SignalMonit
     DVBChannel   *GetDVBChannel(void);
     FirewireChannel *GetFirewireChannel(void);
     V4LChannel   *GetV4LChannel(void);
 
-    bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
-    bool SetupDTVSignalMonitor(void);
+    bool SetupSignalMonitor(bool enable_table_monitoring,
+                            bool EITscan, bool notify);
     void TeardownSignalMonitor(void);
     DTVSignalMonitor *GetDTVSignalMonitor(void);
 
     bool HasFlags(uint f) const { return (stateFlags & f) == f; }
@@ -373,8 +376,9 @@ class MPUBLIC TVRec : public SignalMonit
     DBox2DBOptions     dboxOpt;
 
     // State variables
     mutable QMutex stateChangeLock;
+    mutable QMutex pendingRecLock;
     TVState        internalState;
     TVState        desiredNextState;
     bool           changeState;
     bool           pauseNotify;
Index: libs/libmythtv/v4lchannel.h
===================================================================
--- libs/libmythtv/v4lchannel.h.orig
+++ libs/libmythtv/v4lchannel.h
@@ -48,9 +48,8 @@ class V4LChannel : public DTVChannel
     QString GetDevice(void) const { return device; }
     QString GetSIStandard(void) const { return "atsc"; }
 
     // Commands
-    bool SwitchToInput(int newcapchannel, bool setstarting);
     bool Retune(void);
 
     // Picture attributes.
     bool InitPictureAttributes(void);
@@ -68,8 +67,11 @@ class V4LChannel : public DTVChannel
     // Analog scanning stuff
     bool Tune(uint frequency, QString inputname,
               QString modulation, QString si_std);
 
+  protected:
+    bool SwitchToInput(int newcapchannel, bool setstarting);
+
   private:
     // Helper Sets
     void SetFreqTable(const int index);
     int  SetFreqTable(const QString &name);
