commit ea5e27ad32d6a72f58783e1e7ec12d75d48b7249
Author: Rick Scott <rwscott@users.sourceforge.net>
Date:   Sat May 4 07:10:47 2013 -0400

    Support power save mode with the Internal Firewire channel change with analog capture.
    
    Expand on d49f3f22d by adding support for EnterPowerSavingMode, allowing
    the firewire device to be powered off when not in use. Also avoids
    spinning up the port handler thread when only changing channels.

diff --git a/mythtv/libs/libmythtv/recorders/channelbase.cpp b/mythtv/libs/libmythtv/recorders/channelbase.cpp
index 35544fc..7c729e5 100644
--- a/mythtv/libs/libmythtv/recorders/channelbase.cpp
+++ b/mythtv/libs/libmythtv/recorders/channelbase.cpp
@@ -17,12 +17,6 @@ using namespace std;
 #include <QCoreApplication>
 
 // MythTV headers
-#ifdef USING_OSX_FIREWIRE
-#include "darwinfirewiredevice.h"
-#endif
-#ifdef USING_LINUX_FIREWIRE
-#include "linuxfirewiredevice.h"
-#endif
 #include "firewirechannel.h"
 #include "mythcorecontext.h"
 #include "cetonchannel.h"
@@ -700,76 +694,14 @@ void ChannelBase::HandleScript(const QString &freqid)
     }
     else
     {
-        if ((*it)->externalChanger.toLower() == "internal")
-        {
-            ok = ChangeInternalChannel(freqid, (*it)->inputid);
-            if (!ok)
-            {
-                LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute internal channel "
-                    "changer.");
-                m_system_status = 2; // failed
-            }
-            else
-                m_system_status = 3; // success
-
-            HandleScriptEnd(ok);
-        }
-        else
-        {
-            ok = ChangeExternalChannel((*it)->externalChanger, freqid);
-            if (!ok)
-            {
-                LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute channel changer.");
-                m_system_status = 2; // failed
-                HandleScriptEnd(ok);
-            }
-        }
-    }
-}
-
-bool ChannelBase::ChangeInternalChannel(const QString &freqid,
-                                        uint inputid)
-{
-#ifdef USING_FIREWIRE
-    FirewireDevice *device = NULL;
-    QString fwnode = CardUtil::GetFirewireChangerNode(inputid);
-    uint64_t guid = string_to_guid(fwnode);
-    QString fwmodel = CardUtil::GetFirewireChangerModel(inputid);
-
-    LOG(VB_GENERAL, LOG_ERR, LOC + QString("Internal channel change to %1 "
-            "on inputid %2, GUID %3 (%4)").arg(freqid).arg(inputid)
-            .arg(fwnode).arg(fwmodel));
-
-#ifdef USING_LINUX_FIREWIRE
-    device = new LinuxFirewireDevice(
-        guid, 0, 100, 1);
-#endif // USING_LINUX_FIREWIRE
-
-#ifdef USING_OSX_FIREWIRE
-    device = new DarwinFirewireDevice(guid, 0, 100);
-#endif // USING_OSX_FIREWIRE
-
-    if (!device)
-        return false;
-
-    if (!device->OpenPort())
-        return false;
-
-    if (!device->SetChannel(fwmodel, 0, freqid.toUInt()))
-    {
-        device->ClosePort();
-        delete device;
-        device = NULL;
-        return false;
+	ok = ChangeExternalChannel((*it)->externalChanger, freqid);
+	if (!ok)
+	{
+	    LOG(VB_GENERAL, LOG_ERR, LOC + "Can not execute channel changer.");
+	    m_system_status = 2; // failed
+	    HandleScriptEnd(ok);
+	}
     }
-
-    device->ClosePort();
-    delete device;
-    device = NULL;
-    return true;
-#else
-    return false;
-#endif
 }
 
 /// \note m_system_lock must be held when this is called
diff --git a/mythtv/libs/libmythtv/recorders/channelbase.h b/mythtv/libs/libmythtv/recorders/channelbase.h
index 5d87b13..751bd0f 100644
--- a/mythtv/libs/libmythtv/recorders/channelbase.h
+++ b/mythtv/libs/libmythtv/recorders/channelbase.h
@@ -151,8 +151,6 @@ class ChannelBase
 
     bool ChangeExternalChannel(const QString &changer,
                                const QString &newchan);
-    bool ChangeInternalChannel(const QString &newchan,
-                               uint cardinputid);
 
     TVRec   *m_pParent;
     QString  m_curchannelname;
diff --git a/mythtv/libs/libmythtv/recorders/dtvchannel.cpp b/mythtv/libs/libmythtv/recorders/dtvchannel.cpp
index 204f727..e6fa5f5 100644
--- a/mythtv/libs/libmythtv/recorders/dtvchannel.cpp
+++ b/mythtv/libs/libmythtv/recorders/dtvchannel.cpp
@@ -3,6 +3,12 @@
 using namespace std;
 
 // MythTV headers
+#ifdef USING_OSX_FIREWIRE
+#include "darwinfirewiredevice.h"
+#endif
+#ifdef USING_LINUX_FIREWIRE
+#include "linuxfirewiredevice.h"
+#endif
 #include "mythdb.h"
 #include "tv_rec.h"
 #include "cardutil.h"
@@ -175,6 +181,47 @@ void DTVChannel::ReturnMasterLock(DTVChannelP &chan)
     }
 }
 
+bool DTVChannel::InternalTune(bool power, uint channel)
+{
+bool ok;
+FirewireDevice *device = NULL;
+QString fwnode = CardUtil::GetFirewireChangerNode(m_currentInputID);
+uint64_t guid = string_to_guid(fwnode);
+
+    LOG(VB_CHANNEL, LOG_INFO, LOC + "Internal channel change");
+
+#ifdef USING_LINUX_FIREWIRE
+    device = new LinuxFirewireDevice(guid, 0, 100, 1);
+#endif // USING_LINUX_FIREWIRE
+
+#ifdef USING_OSX_FIREWIRE
+    device = new DarwinFirewireDevice(guid, 0, 100);
+#endif // USING_OSX_FIREWIRE
+    if (device && device->OpenPort(false))
+    {
+	ok = device->SetPowerState(power);
+	LOG(VB_CHANNEL, LOG_INFO, LOC + QString("setting power state result %1").arg(ok));
+	if (power)
+	{
+	QString fwmodel = CardUtil::GetFirewireChangerModel(m_currentInputID);
+
+	    ok = device->SetChannel(fwmodel, 0, channel);
+	    LOG(VB_CHANNEL, LOG_INFO, LOC + QString("channel change result %1").arg(ok));
+	}
+	m_system_status = ok ? 3 : 2;
+	device->ClosePort();
+	delete device;
+	device = NULL;
+    }
+    else
+    {
+	LOG(VB_CHANNEL, LOG_ERR, LOC + "Opening firewire device port failed");
+	m_system_status = 2;
+	ok = false;
+    }
+    return(ok);
+}
+
 bool DTVChannel::SetChannelByString(const QString &channum)
 {
     QString loc = LOC + QString("SetChannelByString(%1): ").arg(channum);
@@ -339,6 +386,12 @@ bool DTVChannel::SetChannelByString(const QString &channum)
             ok = Tune(freqid, finetune);
         }
     }
+#ifdef USING_FIREWIRE
+    else if ((*it)->externalChanger.toLower() == "internal")
+    {
+	ok = InternalTune(true, freqid.toUInt());
+    }
+#endif
 
     LOG(VB_CHANNEL, LOG_INFO, loc + ((ok) ? "success" : "failure"));
 
@@ -401,7 +454,12 @@ bool DTVChannel::SetChannelByString(const QString &channum)
         m_pParent->SetVideoFiltersForChannel(GetCurrentSourceID(), channum);
     InitPictureAttributes();
 
-    HandleScript(freqid);
+#ifdef USING_FIREWIRE
+    if ((*it)->externalChanger.toLower() != "internal")
+#endif
+    {
+	HandleScript(freqid);
+    }
 
     return ok;
 }
@@ -425,3 +483,11 @@ bool DTVChannel::TuneMultiplex(uint mplexid, QString inputname)
 
     return Tune(tuning, inputname);
 }
+
+bool DTVChannel::EnterPowerSavingMode(void)
+{
+#ifdef USING_FIREWIRE
+    InternalTune(false, 0);
+#endif
+    return true;
+}
diff --git a/mythtv/libs/libmythtv/recorders/dtvchannel.h b/mythtv/libs/libmythtv/recorders/dtvchannel.h
index 36bb2ad..c835a5b 100644
--- a/mythtv/libs/libmythtv/recorders/dtvchannel.h
+++ b/mythtv/libs/libmythtv/recorders/dtvchannel.h
@@ -52,10 +52,7 @@ class DTVChannel : public ChannelBase
     /// \brief Performs IPTV Tuning. Only implemented by IPTVChannel.
     virtual bool Tune(const IPTVTuningData&) { return false; }
     /// \brief Enters power saving mode if the card supports it
-    virtual bool EnterPowerSavingMode(void)
-    {
-        return true;
-    }
+    virtual bool EnterPowerSavingMode(void);
     /// \brief This tunes on the frequency Identification parameter for
     ///        hardware that supports it.
     ///
@@ -134,6 +131,7 @@ class DTVChannel : public ChannelBase
     void SetTuningMode(const QString &tuningmode);
 
     void SaveCachedPids(const pid_cache_t &pid_cache) const;
+    bool InternalTune(bool power, uint channel);
 
   protected:
     /// \brief Sets PSIP table standard: MPEG, DVB, ATSC, or OpenCable
diff --git a/mythtv/libs/libmythtv/recorders/firewiredevice.h b/mythtv/libs/libmythtv/recorders/firewiredevice.h
index 4151220..58841b2 100644
--- a/mythtv/libs/libmythtv/recorders/firewiredevice.h
+++ b/mythtv/libs/libmythtv/recorders/firewiredevice.h
@@ -194,6 +194,7 @@ class FirewireDevice
 
     // Commands
     virtual bool OpenPort(void) = 0;
+    virtual bool OpenPort(bool allow_recording) = 0;
     virtual bool ClosePort(void) = 0;
     virtual bool ResetBus(void) { return false; }
 
diff --git a/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.cpp b/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.cpp
index 0fd86a2..bdf27bb 100644
--- a/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.cpp
+++ b/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.cpp
@@ -235,11 +235,14 @@ void LinuxFirewireDevice::HandleBusReset(void)
     }
 }
 
-bool LinuxFirewireDevice::OpenPort(void)
+bool LinuxFirewireDevice::OpenPort(bool allow_record)
 {
+    if (allow_record)
+    {
     LOG(VB_RECORD, LOG_INFO, LOC + "Starting Port Handler Thread");
     QMutexLocker locker(&m_priv->start_stop_port_handler_lock);
     LOG(VB_RECORD, LOG_INFO, LOC + "Starting Port Handler Thread -- locked");
+    }
 
     LOG(VB_RECORD, LOG_INFO, LOC + "OpenPort()");
 
@@ -279,6 +282,8 @@ bool LinuxFirewireDevice::OpenPort(void)
         return false;
     }
 
+    if (allow_record && !m_priv->port_handler_thread)
+    {
     m_priv->run_port_handler = true;
 
     LOG(VB_RECORD, LOG_INFO, LOC + "Starting port handler thread");
@@ -289,12 +294,18 @@ bool LinuxFirewireDevice::OpenPort(void)
         m_priv->port_handler_wait.wait(mlocker.mutex(), 100);
 
     LOG(VB_RECORD, LOG_INFO, LOC + "Port handler thread started");
+    }
 
     m_open_port_cnt++;
 
     return true;
 }
 
+bool LinuxFirewireDevice::OpenPort(void)
+{
+    return OpenPort(true);
+}
+
 bool LinuxFirewireDevice::ClosePort(void)
 {
     LOG(VB_RECORD, LOG_INFO, LOC + "Stopping Port Handler Thread");
@@ -321,6 +332,8 @@ bool LinuxFirewireDevice::ClosePort(void)
         if (IsNodeOpen())
             CloseNode();
 
+        if (m_priv->port_handler_thread)
+        {
         LOG(VB_RECORD, LOG_INFO,
             LOC + "Waiting for port handler thread to stop");
         m_priv->run_port_handler = false;
@@ -334,6 +347,7 @@ bool LinuxFirewireDevice::ClosePort(void)
         m_priv->port_handler_thread = NULL;
 
         LOG(VB_RECORD, LOG_INFO, LOC + "Joined port handler thread");
+        }
 
         remove_handle(GetInfoPtr()->fw_handle);
 
diff --git a/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.h b/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.h
index ee1ca0f..36ae48f 100644
--- a/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.h
+++ b/mythtv/libs/libmythtv/recorders/linuxfirewiredevice.h
@@ -29,6 +29,7 @@ class LinuxFirewireDevice : public FirewireDevice, public QRunnable
 
     // Commands
     virtual bool OpenPort(void);
+    virtual bool OpenPort(bool allow_recording);
     virtual bool ClosePort(void);
     virtual bool ResetBus(void);
 
