Index: libs/libmythtv/analogsignalmonitor.cpp
===================================================================
--- libs/libmythtv/analogsignalmonitor.cpp.orig
+++ libs/libmythtv/analogsignalmonitor.cpp
@@ -32,6 +32,9 @@ void AnalogSignalMonitor::UpdateValues(v
     if (videofd < 0)
         return;
 
+    if (!IsChannelTuned())
+        return;
+
     bool isLocked = false;
     if (usingv4l2)
     {
Index: libs/libmythtv/channelbase.cpp
===================================================================
--- libs/libmythtv/channelbase.cpp.orig
+++ libs/libmythtv/channelbase.cpp
@@ -35,25 +35,109 @@ using namespace std;
 #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);
 
@@ -124,10 +208,8 @@ 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);
 
@@ -329,6 +411,7 @@ int ChannelBase::GetInputByName(const QS
     return -1;
 }
 
+#if 0 // Not used?
 bool ChannelBase::SwitchToInput(const QString &inputname)
 {
     int input = GetInputByName(inputname);
@@ -340,29 +423,61 @@ bool ChannelBase::SwitchToInput(const QS
                                       "%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;
@@ -374,7 +489,7 @@ bool ChannelBase::SwitchToInput(int newI
     // input switching code would go here
 
     if (setstarting)
-        return SetChannelByString((*it)->startChanNum);
+        SelectChannel((*it)->startChanNum);
 
     return true;
 }
@@ -485,8 +600,7 @@ 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;
@@ -651,15 +765,18 @@ bool ChannelBase::ChangeExternalChannel(
     }
     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));
@@ -667,10 +784,16 @@ bool ChannelBase::ChangeExternalChannel(
                 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);
Index: libs/libmythtv/channelbase.h
===================================================================
--- libs/libmythtv/channelbase.h.orig
+++ libs/libmythtv/channelbase.h
@@ -6,6 +6,9 @@
 // Qt headers
 #include <qmap.h>
 #include <qstringlist.h>
+#include <qwaitcondition.h>
+#include <qmutex.h>
+#include <qthread.h>
 
 // MythTV headers
 #include "channelutil.h"
@@ -13,6 +16,19 @@
 #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.
@@ -24,19 +40,28 @@ 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;
 
@@ -83,8 +108,9 @@ class ChannelBase
                           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);
 
@@ -109,8 +135,11 @@ class ChannelBase
 
     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;
@@ -119,6 +148,10 @@ class ChannelBase
     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;
@@ -126,6 +159,14 @@ class ChannelBase
     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
@@ -1330,7 +1330,7 @@ void ChannelScanSM::ScanTransport(const 
     }
 
     // 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
@@ -71,6 +71,7 @@ class AnalogSignalHandler : public Signa
 
   public slots:
     virtual inline void AllGood(void);
+    virtual void StatusChannelTuned(const SignalMonitorValue&) { }
     virtual void StatusSignalLock(const SignalMonitorValue&) { }
     virtual void StatusSignalStrength(const SignalMonitorValue&) { }
 
Index: libs/libmythtv/channelscan/channelscanner_cli.cpp
===================================================================
--- libs/libmythtv/channelscan/channelscanner_cli.cpp.orig
+++ libs/libmythtv/channelscan/channelscanner_cli.cpp
@@ -92,6 +92,8 @@ void ChannelScannerCLI::HandleEvent(cons
             break;
         case ScannerEvent::SetStatusRotorPosition:
             break;
+        case ScannerEvent::SetStatusChannelTuned:
+            break;
         case ScannerEvent::SetStatusSignalLock:
             status_lock = scanEvent->intValue();
             break;
Index: libs/libmythtv/channelscan/channelscanner_gui.cpp
===================================================================
--- libs/libmythtv/channelscan/channelscanner_gui.cpp.orig
+++ libs/libmythtv/channelscan/channelscanner_gui.cpp
@@ -151,6 +151,8 @@ void ChannelScannerGUI::HandleEvent(cons
         case ScannerEvent::SetStatusRotorPosition:
             popupProgress->SetStatusRotorPosition(scanEvent->intValue());
             break;
+        case ScannerEvent::SetStatusChannelTuned:
+            break;
         case ScannerEvent::SetStatusSignalLock:
             popupProgress->SetStatusLock(scanEvent->intValue());
             break;
Index: libs/libmythtv/channelscan/scanmonitor.cpp
===================================================================
--- libs/libmythtv/channelscan/scanmonitor.cpp.orig
+++ libs/libmythtv/channelscan/scanmonitor.cpp
@@ -107,6 +107,11 @@ void ScanMonitor::StatusRotorPosition(co
                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
@@ -64,6 +64,7 @@ class ScanMonitor :
 
     // SignalMonitorListener
     virtual void AllGood(void) { }
+    virtual void StatusChannelTuned(const SignalMonitorValue&);
     virtual void StatusSignalLock(const SignalMonitorValue&);
     virtual void StatusSignalStrength(const SignalMonitorValue&);
 
@@ -98,6 +99,7 @@ class ScannerEvent : public QEvent
         SetStatusSignalToNoise,
         SetStatusSignalStrength,
         SetStatusSignalLock,
+        SetStatusChannelTuned
     };
 
     ScannerEvent(TYPE t) :
Index: libs/libmythtv/dtvsignalmonitor.cpp
===================================================================
--- libs/libmythtv/dtvsignalmonitor.cpp.orig
+++ libs/libmythtv/dtvsignalmonitor.cpp
@@ -25,6 +25,7 @@ DTVSignalMonitor::DTVSignalMonitor(int d
                                    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),
@@ -64,6 +65,13 @@ QStringList DTVSignalMonitor::GetStatusL
 {
     QStringList list = SignalMonitor::GetStatusList(kick);
     QMutexLocker locker(&statusLock);
+
+    // tuned?
+    if (flags & kSigMon_Tuned)
+    {
+        list<<channelTuned.GetName()<<channelTuned.GetStatus();
+    }
+
     // mpeg tables
     if (flags & kDTVSigMon_WaitForPAT)
     {
@@ -139,6 +147,7 @@ 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);
Index: libs/libmythtv/dtvsignalmonitor.h
===================================================================
--- libs/libmythtv/dtvsignalmonitor.h.orig
+++ libs/libmythtv/dtvsignalmonitor.h
@@ -111,6 +111,7 @@ class DTVSignalMonitor : public SignalMo
   protected:
     MPEGStreamData    *stream_data;
     vector<uint>       eit_pids;
+    SignalMonitorValue channelTuned;
     SignalMonitorValue seenPAT;
     SignalMonitorValue seenPMT;
     SignalMonitorValue seenMGT;
Index: libs/libmythtv/dvbsignalmonitor.cpp
===================================================================
--- libs/libmythtv/dvbsignalmonitor.cpp.orig
+++ libs/libmythtv/dvbsignalmonitor.cpp
@@ -223,6 +223,9 @@ void DVBSignalMonitor::UpdateValues(void
         return;
     }
 
+    if (!IsChannelTuned())
+        return;
+
     AddFlags(kSigMon_WaitForSig);
  
     DVBChannel *dvbchannel = GetDVBChannel();
Index: libs/libmythtv/firewiresignalmonitor.cpp
===================================================================
--- libs/libmythtv/firewiresignalmonitor.cpp.orig
+++ libs/libmythtv/firewiresignalmonitor.cpp
@@ -190,6 +190,9 @@ void FirewireSignalMonitor::UpdateValues
     if (!running || exit)
         return;
 
+    if (!IsChannelTuned())
+        return;
+
     if (dtvMonitorRunning)
     {
         EmitStatus();
Index: libs/libmythtv/hdhrchannel.cpp
===================================================================
--- libs/libmythtv/hdhrchannel.cpp.orig
+++ libs/libmythtv/hdhrchannel.cpp
@@ -140,6 +140,9 @@ bool HDHRChannel::SetChannelByString(con
     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;
Index: libs/libmythtv/hdhrsignalmonitor.cpp
===================================================================
--- libs/libmythtv/hdhrsignalmonitor.cpp.orig
+++ libs/libmythtv/hdhrsignalmonitor.cpp
@@ -103,6 +103,9 @@ void HDHRSignalMonitor::UpdateValues(voi
         return;
     }
 
+    if (!IsChannelTuned())
+        return;
+
     QString msg = streamHandler->GetTunerStatus();
     //ss  = signal strength,        [0,100]
     //snq = signal to noise quality [0,100]
Index: libs/libmythtv/iptvsignalmonitor.cpp
===================================================================
--- libs/libmythtv/iptvsignalmonitor.cpp.orig
+++ libs/libmythtv/iptvsignalmonitor.cpp
@@ -119,6 +119,9 @@ void IPTVSignalMonitor::UpdateValues(voi
     if (!running || exit)
         return;
 
+    if (!IsChannelTuned())
+        return;
+
     if (dtvMonitorRunning)
     {
         EmitStatus();
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro.orig
+++ libs/libmythtv/libmythtv.pro
@@ -451,6 +451,9 @@ using_backend {
     HEADERS += NuppelVideoRecorder.h       fifowriter.h
     SOURCES += NuppelVideoRecorder.cpp     fifowriter.cpp
 
+    HEADERS += channelchangemonitor.h
+    SOURCES += channelchangemonitor.cpp
+
     # Support for Video4Linux devices
     using_v4l {
         HEADERS += v4lchannel.h                analogsignalmonitor.h
Index: libs/libmythtv/signalmonitor.cpp
===================================================================
--- libs/libmythtv/signalmonitor.cpp.orig
+++ libs/libmythtv/signalmonitor.cpp
@@ -8,6 +8,7 @@
 
 // MythTV headers
 #include "mythcontext.h"
+#include "tv_rec.h"
 #include "signalmonitor.h"
 #include "compat.h"
 #include "mythverbose.h"
@@ -42,6 +43,8 @@ extern "C" {
 #   include "firewirechannel.h"
 #endif
 
+#include "channelchangemonitor.h"
+
 #undef DBG_SM
 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
     "SM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
@@ -93,15 +96,16 @@ 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")
@@ -132,6 +136,13 @@ SignalMonitor *SignalMonitor::Init(QStri
 
     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));
@@ -160,10 +171,13 @@ SignalMonitor::SignalMonitor(int _captur
       update_rate(25),                 minimum_update_rate(5),
       running(false),                  exit(false),
       update_done(false),              notify_frontend(true),
+      is_tuned(false),                 tablemon(false),
       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,11 +215,15 @@ 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(
@@ -278,6 +296,7 @@ QStringList SignalMonitor::GetStatusList
 
     QStringList list;
     statusLock.lock();
+    list<<channelTuned.GetName()<<channelTuned.GetStatus();
     list<<signalLock.GetName()<<signalLock.GetStatus();
     if (HasFlags(kSigMon_WaitForSig))
         list<<signalStrength.GetName()<<signalStrength.GetStatus();
@@ -305,7 +324,6 @@ 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,6 +458,9 @@ void SignalMonitor::SendMessage(
         case kStatusSignalStrength:
             listener->StatusSignalStrength(val);
             break;
+        case kStatusChannelTuned:
+            listener->StatusChannelTuned(val);
+            break;
         case kStatusSignalToNoise:
             if (dvblistener)
                 dvblistener->StatusSignalToNoise(val);
@@ -460,6 +481,40 @@ 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();
+
+        is_tuned = true;
+        return true;
+    }
+
+    return false;
+}
+
 void SignalMonitor::SendMessageAllGood(void)
 {
     QMutexLocker locker(&listenerLock);
@@ -469,6 +524,7 @@ 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
@@ -27,6 +27,8 @@ using namespace std;
 
 inline QString sm_flags_to_string(uint64_t);
 
+class TVRec;
+
 class SignalMonitor
 {
   public:
@@ -40,7 +42,7 @@ 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,6 +85,13 @@ class SignalMonitor
      */
     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 monitor)
+        { pParent = parent; tablemon = monitor; }
+
     /** \brief Sets the number of milliseconds between signal monitoring
      *         attempts in the signal monitoring thread.
      *
@@ -96,6 +105,7 @@ class SignalMonitor
     // Listeners   // // // // // // // // // // // // // // // // // // //
     void AddListener(SignalMonitorListener *listener);
     void RemoveListener(SignalMonitorListener *listener);
+
     void SendMessage(SignalMonitorMessageType type,
                      const SignalMonitorValue &val);
     void SendMessageAllGood(void);
@@ -108,6 +118,8 @@ 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() { ; }
 
@@ -139,6 +151,8 @@ class SignalMonitor
     /// 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
@@ -184,6 +198,7 @@ class SignalMonitor
   protected:
     pthread_t    monitor_thread;
     ChannelBase *channel;
+    TVRec       *pParent;
     int          capturecardnum;
     uint64_t     flags;
     int          update_rate;
@@ -192,9 +207,12 @@ class SignalMonitor
     bool         exit;
     bool         update_done;
     bool         notify_frontend;
+    bool         is_tuned;
+    bool         tablemon;
 
     SignalMonitorValue signalLock;
     SignalMonitorValue signalStrength;
+    SignalMonitorValue channelTuned;
 
     vector<SignalMonitorListener*> listeners;
 
Index: libs/libmythtv/signalmonitorlistener.h
===================================================================
--- libs/libmythtv/signalmonitorlistener.h.orig
+++ libs/libmythtv/signalmonitorlistener.h
@@ -9,6 +9,7 @@
 
 typedef enum {
     kAllGood,
+    kStatusChannelTuned,
     kStatusSignalLock,
     kStatusSignalStrength,
     kStatusSignalToNoise,
@@ -30,6 +31,13 @@ class MPUBLIC SignalMonitorListener
      */
     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.
      *
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp.orig
+++ libs/libmythtv/tv_play.cpp
@@ -7119,6 +7119,7 @@ void TV::UpdateOSDSignal(const PlayerCon
     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)
@@ -7145,6 +7146,8 @@ void TV::UpdateOSDSignal(const PlayerCon
             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())
@@ -7178,6 +7181,7 @@ void TV::UpdateOSDSignal(const PlayerCon
         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;
@@ -7190,9 +7194,18 @@ void TV::UpdateOSDSignal(const PlayerCon
     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;
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp.orig
+++ libs/libmythtv/tv_rec.cpp
@@ -366,7 +366,8 @@ ProgramInfo *TVRec::GetRecording(void)
 void TVRec::RecordPending(const ProgramInfo *rcinfo, int secsleft,
                           bool hasLater)
 {
-    QMutexLocker lock(&stateChangeLock);
+    QMutexLocker statelock(&stateChangeLock);
+    QMutexLocker pendlock(&pendingRecLock);
 
     if (secsleft < 0)
     {
@@ -404,10 +405,10 @@ void TVRec::RecordPending(const ProgramI
 
     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*)
@@ -439,6 +440,7 @@ QDateTime TVRec::GetRecordEndTime(const 
  */
 void TVRec::CancelNextRecording(bool cancel)
 {
+    QMutexLocker pendlock(&pendingRecLock);
     VERBOSE(VB_RECORD, LOC + "CancelNextRecording("<<cancel<<") -- begin");
 
     PendingMap::iterator it = pendingRecordings.find(cardid);
@@ -523,24 +525,32 @@ RecStatusType TVRec::StartRecording(cons
         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();
 
     // 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;
@@ -563,8 +573,8 @@ RecStatusType TVRec::StartRecording(cons
 
             if (is_busy && !sourceid)
             {
-                mplexid  = (*it).info->GetMplexID();
-                sourceid = (*it).info->sourceid;
+                mplexid  = pendinfo.info->GetMplexID();
+                sourceid = pendinfo.info->sourceid;
             }
 
             if (is_busy &&
@@ -950,7 +960,6 @@ void TVRec::HandleStateChange(void)
 void TVRec::ChangeState(TVState nextState)
 {
     QMutexLocker lock(&stateChangeLock);
-
     desiredNextState = nextState;
     changeState = true;
     triggerEventLoop.wakeAll();
@@ -1423,9 +1432,12 @@ void TVRec::RunTV(void)
             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)))
             {
@@ -1572,6 +1584,8 @@ bool TVRec::WaitForEventThreadSleep(bool
 
 void TVRec::HandlePendingRecordings(void)
 {
+    QMutexLocker pendlock(&pendingRecLock);
+
     if (pendingRecordings.empty())
         return;
 
@@ -2044,27 +2058,21 @@ bool TVRec::SetupSignalMonitor(bool tabl
     // 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, GetDTVSignalMonitor() && tablemon);
         signalMonitor->AddListener(this);
         signalMonitor->SetUpdateRate(kSignalMonitoringRate);
         signalMonitor->SetNotifyFrontend(notify);
 
         // Start the monitoring thread
-        signalMonitor->Start();
+        signalMonitor->Start(true);
     }
 
     return true;
@@ -2336,7 +2344,7 @@ bool TVRec::CheckChannelPrefix(const QSt
     {
         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]);
 
@@ -2469,8 +2477,6 @@ bool TVRec::IsReallyRecording(void)
  */
 bool TVRec::IsBusy(TunedInputInfo *busy_input, int time_buffer) const
 {
-    QMutexLocker lock(&stateChangeLock);
-
     TunedInputInfo dummy;
     if (!busy_input)
         busy_input = &dummy;
@@ -2492,6 +2498,7 @@ bool TVRec::IsBusy(TunedInputInfo *busy_
         chanid              = channel->GetChanID();
     }
 
+    QMutexLocker pendlock(&pendingRecLock);
     PendingMap::const_iterator it = pendingRecordings.find(cardid);
     if (!busy_input->inputid && (it != pendingRecordings.end()))
     {
@@ -3177,7 +3184,7 @@ void TVRec::GetNextProgram(int direction
         }
         else if (BROWSE_RIGHT == direction)
         {
-	        chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
+                chanid = channel->GetNextChannel(channum, CHANNEL_DIRECTION_SAME);
             compare = ">";
             sortorder = "asc";
         }
@@ -3667,6 +3674,11 @@ void TVRec::TuningShutdowns(const Tuning
 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;
@@ -3683,16 +3695,14 @@ void TVRec::TuningFrequency(const Tuning
 
         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);
         }
@@ -3721,9 +3731,11 @@ void TVRec::TuningFrequency(const Tuning
     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)
@@ -3750,13 +3762,7 @@ void TVRec::TuningFrequency(const Tuning
         }
     }
 
-    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;
@@ -3782,60 +3788,57 @@ void TVRec::TuningFrequency(const Tuning
         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, 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)
         {
-            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;
+            delete signalMonitor;
+            signalMonitor = NULL;
         }
 
-        if (signalMonitor)
-        {
-            if (request.flags & kFlagEITScan)
-            {
-                GetDTVSignalMonitor()->GetStreamData()->
-                    SetVideoStreamsRequired(0);
-                GetDTVSignalMonitor()->IgnoreEncrypted(true);
-            }
+        // pretend the signal monitor is running to prevent segfault
+        SetFlags(kFlagSignalMonitorRunning);
+        ClearFlags(kFlagWaitingForSignal);
+        error = true;
+    }
 
-            SetFlags(kFlagSignalMonitorRunning);
-            ClearFlags(kFlagWaitingForSignal);
-            if (!antadj)
-                SetFlags(kFlagWaitingForSignal);
+    if (signalMonitor)
+    {
+        if (request.flags & kFlagEITScan)
+        {
+            GetDTVSignalMonitor()->GetStreamData()->
+                SetVideoStreamsRequired(0);
+            GetDTVSignalMonitor()->IgnoreEncrypted(true);
         }
 
-        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(kFlagSignalMonitorRunning);
+        ClearFlags(kFlagWaitingForSignal);
+        if (!antadj)
+            SetFlags(kFlagWaitingForSignal);
+    }
 
-            SetFlags(kFlagDummyRecorderRunning);
-            VERBOSE(VB_RECORD, "DummyDTVRecorder -- started");
-            SetFlags(kFlagRingBufferReady);
-        }
+    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);
 
-        // if we had problems starting the signal monitor,
-        // we don't want to start the recorder...
-        if (error)
-            return;
+        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
@@ -158,6 +158,7 @@ typedef QMap<uint,PendingInfo> PendingMa
 class MPUBLIC TVRec : public SignalMonitorListener
 {
     friend class TuningRequest;
+    friend class SignalMonitor;
 
   public:
     TVRec(int capturecardnum);
@@ -252,6 +253,7 @@ class MPUBLIC TVRec : public SignalMonit
     static TVRec *GetTVRec(uint cardid);
 
     virtual void AllGood(void) { triggerEventLoop.wakeAll(); }
+    virtual void StatusChannelTuned(const SignalMonitorValue&) { }
     virtual void StatusSignalLock(const SignalMonitorValue&) { }
     virtual void StatusSignalStrength(const SignalMonitorValue&) { }
 
@@ -260,6 +262,7 @@ class MPUBLIC TVRec : public SignalMonit
     bool WaitForEventThreadSleep(bool wake = true, ulong time = ULONG_MAX);
     static void *EventThread(void *param);
     static void *RecorderThread(void *param);
+    bool SetupDTVSignalMonitor(void);
 
   private:
     void SetRingBuffer(RingBuffer *);
@@ -291,7 +294,6 @@ class MPUBLIC TVRec : public SignalMonit
     V4LChannel   *GetV4LChannel(void);
 
     bool SetupSignalMonitor(bool enable_table_monitoring, bool notify);
-    bool SetupDTVSignalMonitor(void);
     void TeardownSignalMonitor(void);
     DTVSignalMonitor *GetDTVSignalMonitor(void);
 
@@ -370,6 +372,7 @@ class MPUBLIC TVRec : public SignalMonit
 
     // State variables
     mutable QMutex stateChangeLock;
+    mutable QMutex pendingRecLock;
     TVState        internalState;
     TVState        desiredNextState;
     bool           changeState;
Index: libs/libmythtv/v4lchannel.h
===================================================================
--- libs/libmythtv/v4lchannel.h.orig
+++ libs/libmythtv/v4lchannel.h
@@ -49,7 +49,6 @@ class V4LChannel : public DTVChannel
     QString GetSIStandard(void) const { return "atsc"; }
 
     // Commands
-    bool SwitchToInput(int newcapchannel, bool setstarting);
     bool Retune(void);
 
     // Picture attributes.
@@ -69,6 +68,9 @@ class V4LChannel : public DTVChannel
     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);
