Index: libs/libmythtv/dvbrecorder.h
===================================================================
--- libs/libmythtv/dvbrecorder.h	(revision 12461)
+++ libs/libmythtv/dvbrecorder.h	(working copy)
@@ -84,6 +84,7 @@
     void HandlePAT(const ProgramAssociationTable*);
     void HandleCAT(const ConditionalAccessTable*) {}
     void HandlePMT(uint pid, const ProgramMapTable*);
+    void HandleEncryptionStatus(uint /*pnum*/, bool /*encrypted*/) { }
 
     // ATSC Main
     void HandleSTT(const SystemTimeTable*);
Index: libs/libmythtv/hdhrrecorder.h
===================================================================
--- libs/libmythtv/hdhrrecorder.h	(revision 12461)
+++ libs/libmythtv/hdhrrecorder.h	(working copy)
@@ -46,6 +46,7 @@
     void HandlePAT(const ProgramAssociationTable*);
     void HandleCAT(const ConditionalAccessTable*) {}
     void HandlePMT(uint pid, const ProgramMapTable*);
+    void HandleEncryptionStatus(uint /*pnum*/, bool /*encrypted*/) { }
 
     // MPEG Single Program Stream Listener
     void HandleSingleProgramPAT(ProgramAssociationTable *pat);
Index: libs/libmythtv/signalmonitor.h
===================================================================
--- libs/libmythtv/signalmonitor.h	(revision 12461)
+++ libs/libmythtv/signalmonitor.h	(working copy)
@@ -148,6 +148,8 @@
     static const uint64_t kDTVSigMon_SDTSeen    = 0x0000000080ULL;
     /// We've seen the FireWire STB power state
     static const uint64_t kFWSigMon_PowerSeen   = 0x0000000100ULL;
+    /// We can encrypt the stream
+    static const uint64_t kDTVSigMon_CryptSeen  = 0x0000000200ULL;
 
     /// We've seen a PAT matching our requirements
     static const uint64_t kDTVSigMon_PATMatch   = 0x0000001000ULL;
@@ -167,6 +169,8 @@
     static const uint64_t kDTVSigMon_SDTMatch   = 0x0000080000ULL;
     /// We've seen a FireWire STB power state matching our requirements
     static const uint64_t kFWSigMon_PowerMatch  = 0x0000100000ULL;
+    /// We can encrypt the stream
+    static const uint64_t kDTVSigMon_CryptMatch = 0x0000200000ULL;
 
     static const uint64_t kDTVSigMon_WaitForPAT = 0x0001000000ULL;
     static const uint64_t kDTVSigMon_WaitForPMT = 0x0002000000ULL;
@@ -176,17 +180,18 @@
     static const uint64_t kDTVSigMon_WaitForSDT = 0x0020000000ULL;
     static const uint64_t kDTVSigMon_WaitForSig = 0x0040000000ULL;
     static const uint64_t kFWSigMon_WaitForPower= 0x0080000000ULL;
+    static const uint64_t kDTVSigMon_WaitForCrypt=0x0100000000ULL;
 
-    static const uint64_t kDTVSigMon_WaitForAll = 0x00FF000000ULL;
+    static const uint64_t kDTVSigMon_WaitForAll = 0x01FF000000ULL;
 
     /// Wait for the Signal to Noise Ratio to rise above a threshhold
-    static const uint64_t kDVBSigMon_WaitForSNR = 0x0100000000ULL;
+    static const uint64_t kDVBSigMon_WaitForSNR = 0x1000000000ULL;
     /// Wait for the Bit Error Rate to fall below a threshhold
-    static const uint64_t kDVBSigMon_WaitForBER = 0x0200000000ULL;
+    static const uint64_t kDVBSigMon_WaitForBER = 0x2000000000ULL;
     /// Wait for uncorrected FEC blocks to fall below a threshhold
-    static const uint64_t kDVBSigMon_WaitForUB  = 0x0400000000ULL;
+    static const uint64_t kDVBSigMon_WaitForUB  = 0x4000000000ULL;
     /// Wait for rotor to complete turning the antenna
-    static const uint64_t kDVBSigMon_WaitForPos = 0x0800000000ULL;
+    static const uint64_t kDVBSigMon_WaitForPos = 0x8000000000ULL;
 
   protected:
     pthread_t    monitor_thread;
@@ -228,6 +233,8 @@
         str += "SDT,";
     if (SignalMonitor::kFWSigMon_PowerSeen   & flags)
         str += "STB,";
+    if (SignalMonitor::kDTVSigMon_CryptSeen  & flags)
+        str += "Crypt,";
 
     str += ") Match(";
     if (SignalMonitor::kDTVSigMon_PATMatch   & flags)
@@ -248,6 +255,8 @@
         str += "SDT,";
     if (SignalMonitor::kFWSigMon_PowerMatch  & flags)
         str += "STB,";
+    if (SignalMonitor::kDTVSigMon_CryptMatch & flags)
+        str += "Crypt,";
 
     str += ") Wait(";
     if (SignalMonitor::kDTVSigMon_WaitForPAT & flags)
@@ -266,6 +275,8 @@
         str += "Sig,";
     if (SignalMonitor::kFWSigMon_WaitForPower& flags)
         str += "STB,";
+    if (SignalMonitor::kDTVSigMon_WaitForCrypt & flags)
+        str += "Crypt,";
 
     if (SignalMonitor::kDVBSigMon_WaitForSNR & flags)
         str += "SNR,";
Index: libs/libmythtv/mpeg/mpegstreamdata.cpp
===================================================================
--- libs/libmythtv/mpeg/mpegstreamdata.cpp	(revision 12461)
+++ libs/libmythtv/mpeg/mpegstreamdata.cpp	(working copy)
@@ -1,6 +1,9 @@
 // -*- Mode: c++ -*-
 // Copyright (c) 2003-2004, Daniel Thor Kristjansson
 
+#include <algorithm> // for find
+using namespace std;
+
 // POSIX headers
 #include <sys/time.h> // for gettimeofday
 
@@ -54,7 +57,7 @@
       _local_utc_offset(0), _si_time_offset_cnt(0),
       _si_time_offset_indx(0),
       _eit_helper(NULL), _eit_rate(0.0f),
-      _listener_lock(true),
+      _encryption_lock(true), _listener_lock(true),
       _cache_tables(cacheTables), _cache_lock(true),
       // Single program stuff
       _desired_program(desiredProgram),
@@ -172,6 +175,8 @@
         _cached_pmts.clear();
     }
 
+    ResetDecryptionMonitoringState();
+
     AddListeningPID(MPEG_PAT_PID);
 }
 
@@ -777,11 +782,18 @@
 bool MPEGStreamData::ProcessTSPacket(const TSPacket& tspacket)
 {
     bool ok = !tspacket.TransportError();
+
+    if (IsEncryptionTestPID(tspacket.PID()))
+    {
+        ProcessEncryptedPacket(tspacket);
+    }
+
     if (ok && !tspacket.ScramplingControl() && tspacket.HasPayload() &&
         IsListeningPID(tspacket.PID()))
     {
         HandleTSTables(&tspacket);
     }
+
     return ok;
 }
 
@@ -1239,3 +1251,208 @@
         }
     }
 }
+
+void MPEGStreamData::AddEncryptionTestPID(uint pnum, uint pid, bool isvideo)
+{
+    QMutexLocker locker(&_encryption_lock);
+
+    //VERBOSE(VB_IMPORTANT, "AddEncryptionTestPID("<<pnum
+    //        <<", 0x"<<hex<<pid<<dec<<")");
+
+    _encryption_pid_to_info[pid] = CryptInfo((isvideo) ? 10000 : 500, 8);
+    
+    _encryption_pid_to_pnums[pid].push_back(pnum);
+    _encryption_pnum_to_pids[pnum].push_back(pid);
+    _encryption_pnum_to_status[pnum] = kEncUnknown;
+}
+
+void MPEGStreamData::RemoveEncryptionTestPIDs(uint pnum)
+{
+    QMutexLocker locker(&_encryption_lock);
+
+    //VERBOSE(VB_RECORD,
+    //        QString("Tearing down up decryption monitoring "
+    //                "for program %1").arg(pnum));
+
+    QMap<uint, uint_vec_t>::iterator list;
+    uint_vec_t::iterator it;
+
+    uint_vec_t pids = _encryption_pnum_to_pids[pnum];
+    for (uint i = 0; i < pids.size(); i++)
+    {
+        uint pid = pids[i];
+
+        //VERBOSE(VB_IMPORTANT, QString("Removing 0x%1 PID Enc monitoring")
+        //        .arg(pid,0,16));
+
+        list = _encryption_pid_to_pnums.find(pid);
+        if (list != _encryption_pid_to_pnums.end())
+        {
+            it = find((*list).begin(), (*list).end(), pnum);
+
+            if (it != (*list).end())
+                (*list).erase(it);
+
+            if ((*list).empty())
+            {
+                _encryption_pid_to_pnums.erase(pid);
+                _encryption_pid_to_info.erase(pid);
+            }
+        }
+    }
+
+    _encryption_pnum_to_pids.erase(pnum);
+}
+
+bool MPEGStreamData::IsEncryptionTestPID(uint pid) const
+{
+    QMutexLocker locker(&_encryption_lock);
+
+    QMap<uint, CryptInfo>::const_iterator it =
+        _encryption_pid_to_info.find(pid);
+
+    return it != _encryption_pid_to_info.end();
+}
+
+void MPEGStreamData::TestDecryption(const ProgramMapTable *pmt)
+{
+    QMutexLocker locker(&_encryption_lock);
+
+    //VERBOSE(VB_RECORD,
+    //        QString("Setting up decryption monitoring "
+    //                "for program %1").arg(pmt->ProgramNumber()));
+
+    bool encrypted = pmt->IsProgramEncrypted();
+    for (uint i = 0; i < pmt->StreamCount(); i++)
+    {
+        if (!encrypted && !pmt->IsStreamEncrypted(i))
+            continue;
+
+        bool is_vid = pmt->IsVideo(i, _sistandard);
+        bool is_aud = pmt->IsAudio(i, _sistandard);
+        if (is_vid || is_aud)
+        {
+            AddEncryptionTestPID(
+                pmt->ProgramNumber(), pmt->StreamPID(i), is_vid);
+        }
+    }
+}
+
+void MPEGStreamData::ResetDecryptionMonitoringState(void)
+{
+    QMutexLocker locker(&_encryption_lock);
+
+    _encryption_pid_to_info.clear();
+    _encryption_pid_to_pnums.clear();
+    _encryption_pnum_to_pids.clear();
+}
+
+bool MPEGStreamData::IsProgramDecrypted(uint pnum) const
+{
+    QMutexLocker locker(&_encryption_lock);
+    return _encryption_pnum_to_status[pnum] == kEncDecrypted;
+}
+
+bool MPEGStreamData::IsProgramEncrypted(uint pnum) const
+{
+    QMutexLocker locker(&_encryption_lock);
+    return _encryption_pnum_to_status[pnum] == kEncEncrypted;
+}
+
+static QString toString(CryptStatus status)
+{
+    if (kEncDecrypted == status)
+        return "Decrypted";
+    else if (kEncEncrypted == status)
+        return "Encrypted";
+    else
+        return "Unknown";
+}
+
+/** \fn MPEGStreamData::ProcessEncryptedPacket(const TSPacket& tspacket)
+ *  \brief counts en/decrypted packets to decide if a stream is en/decrypted
+ */
+void MPEGStreamData::ProcessEncryptedPacket(const TSPacket& tspacket)
+{
+    QMutexLocker locker(&_encryption_lock);
+
+    const uint pid = tspacket.PID();
+    CryptInfo &info = _encryption_pid_to_info[pid];
+
+    CryptStatus status = kEncUnknown;
+
+    if (tspacket.ScramplingControl())
+    {
+        info.decrypted_packets = 0;
+
+        // If a fair amount of encrypted packets is passed assume that
+        // the stream is not decryptable
+        if (++info.encrypted_packets >= info.encrypted_min)
+            status = kEncEncrypted;
+    }
+    else
+    {
+        info.encrypted_packets = 0;
+        if (++info.decrypted_packets > info.decrypted_min)
+            status = kEncDecrypted;
+    }
+
+    if (status == info.status)
+        return; // pid encryption status unchanged
+
+    info.status = status;
+
+    VERBOSE(VB_IMPORTANT, QString("PID 0x%1 status: %2")
+            .arg(pid,0,16).arg(status));
+
+    uint_vec_t pnum_del_list;
+    const uint_vec_t &pnums = _encryption_pid_to_pnums[pid];
+    for (uint i = 0; i < pnums.size(); i++)
+    {
+        CryptStatus status = _encryption_pnum_to_status[pnums[i]];
+
+        const uint_vec_t &pids = _encryption_pnum_to_pids[pnums[i]];
+        if (!pids.empty())
+        {
+            uint enc_cnt[3] = { 0, 0, 0 };
+            for (uint j = 0; j < pids.size(); j++)
+            {
+                CryptStatus stat = _encryption_pid_to_info[pids[j]].status;
+                enc_cnt[stat]++;
+
+                //VERBOSE(VB_IMPORTANT,
+                //        QString("\tpnum %1 PID 0x%2 status: %3")
+                //        .arg(pnums[i]).arg(pids[j],0,16)
+                //        .arg(toString(stat)));
+            }
+            status = kEncUnknown;
+
+            if (enc_cnt[kEncEncrypted])
+                status = kEncEncrypted;
+            else if (enc_cnt[kEncDecrypted] >= 2)
+                status = kEncDecrypted;
+        }
+
+        if (status == _encryption_pnum_to_status[pnums[i]])
+            continue; // program encryption status unchanged
+
+        VERBOSE(VB_RECORD, QString("Program %1 status: %2")
+                .arg(pnums[i]).arg(toString(status)));
+
+        _encryption_pnum_to_status[pnums[i]] = status;
+
+        _listener_lock.lock();
+        for (uint j = 0; j < _mpeg_listeners.size(); j++)
+        {
+            _mpeg_listeners[j]->HandleEncryptionStatus(
+                pnums[i], toString(status));
+        }
+        _listener_lock.unlock();
+
+        if (status != kEncUnknown)
+            pnum_del_list.push_back(pnums[i]);
+    }
+
+    for (uint i = 0; i < pnum_del_list.size(); i++)
+        RemoveEncryptionTestPIDs(pnums[i]);
+}
Index: libs/libmythtv/mpeg/mpegtables.h
===================================================================
--- libs/libmythtv/mpeg/mpegtables.h	(revision 12461)
+++ libs/libmythtv/mpeg/mpegtables.h	(working copy)
@@ -528,6 +528,8 @@
     bool IsVideo(uint i, QString sistandard) const;
     bool IsAudio(uint i, QString sistandard) const;
     bool IsEncrypted(void) const;
+    bool IsProgramEncrypted(void) const;
+    bool IsStreamEncrypted(uint pid) const;
     /// Returns true iff PMT contains a still-picture video stream
     bool IsStillPicture(QString sistandard) const;
     /// Returns a string representation of type at stream index i
Index: libs/libmythtv/mpeg/streamlisteners.h
===================================================================
--- libs/libmythtv/mpeg/streamlisteners.h	(revision 12461)
+++ libs/libmythtv/mpeg/streamlisteners.h	(working copy)
@@ -1,3 +1,4 @@
+// -*- Mode: c++ -*-
 #ifndef _STREAMLISTENERS_H_
 #define _STREAMLISTENERS_H_
 
@@ -42,6 +43,7 @@
     virtual void HandlePAT(const ProgramAssociationTable*) = 0;
     virtual void HandleCAT(const ConditionalAccessTable*) = 0;
     virtual void HandlePMT(uint program_num, const ProgramMapTable*) = 0;
+    virtual void HandleEncryptionStatus(uint program_number, bool) = 0;
 };
 
 class MPEGSingleProgramStreamListener
Index: libs/libmythtv/mpeg/mpegstreamdata.h
===================================================================
--- libs/libmythtv/mpeg/mpegstreamdata.h	(revision 12461)
+++ libs/libmythtv/mpeg/mpegstreamdata.h	(working copy)
@@ -40,6 +40,31 @@
 typedef vector<MPEGStreamListener*>     mpeg_listener_vec_t;
 typedef vector<MPEGSingleProgramStreamListener*> mpeg_sp_listener_vec_t;
 
+typedef enum
+{
+    kEncUnknown   = 0,
+    kEncDecrypted = 1,
+    kEncEncrypted = 2,
+} CryptStatus;
+
+class CryptInfo
+{
+  public:
+    CryptInfo() :
+        status(kEncUnknown), encrypted_packets(0), decrypted_packets(0),
+        encrypted_min(1000), decrypted_min(8) { }
+    CryptInfo(uint e, uint d) :
+        status(kEncUnknown), encrypted_packets(0), decrypted_packets(0),
+        encrypted_min(e), decrypted_min(d) { }
+
+  public:
+    CryptStatus status;
+    uint encrypted_packets;
+    uint decrypted_packets;
+    uint encrypted_min;
+    uint decrypted_min;
+};
+
 void init_sections(sections_t &sect, uint last_section);
 
 class MPEGStreamData : public EITSource
@@ -158,6 +183,17 @@
     virtual void ReturnCachedPMTTables(pmt_vec_t&) const;
     virtual void ReturnCachedPMTTables(pmt_map_t&) const;
 
+    // Encryption Monitoring
+    void AddEncryptionTestPID(uint pnum, uint pid, bool isvideo);
+    void RemoveEncryptionTestPIDs(uint pnum);
+    bool IsEncryptionTestPID(uint pid) const;
+
+    void TestDecryption(const ProgramMapTable* pmt);
+    void ResetDecryptionMonitoringState(void);
+
+    bool IsProgramDecrypted(uint pnum) const;
+    bool IsProgramEncrypted(uint pnum) const;
+
     // "signals"
     void AddMPEGListener(MPEGStreamListener*);
     void RemoveMPEGListener(MPEGStreamListener*);
@@ -218,6 +254,7 @@
     void DeletePartialPES(uint pid);
     void ProcessPAT(const ProgramAssociationTable *pat);
     void ProcessPMT(const ProgramMapTable *pmt);
+    void ProcessEncryptedPacket(const TSPacket&);
 
     static int ResyncStream(unsigned char *buffer, int curr_pos, int len);
 
@@ -251,6 +288,13 @@
     QMap<uint, bool>          _pids_writing;
     QMap<uint, bool>          _pids_audio;
 
+    // Encryption monitoring
+    mutable QMutex            _encryption_lock;
+    QMap<uint, CryptInfo>     _encryption_pid_to_info;
+    QMap<uint, uint_vec_t>    _encryption_pnum_to_pids;
+    QMap<uint, uint_vec_t>    _encryption_pid_to_pnums;
+    QMap<uint, CryptStatus>   _encryption_pnum_to_status;
+
     // Signals
     mutable QMutex            _listener_lock;
     mpeg_listener_vec_t       _mpeg_listeners;
Index: libs/libmythtv/mpeg/mpegtables.cpp
===================================================================
--- libs/libmythtv/mpeg/mpegtables.cpp	(revision 12461)
+++ libs/libmythtv/mpeg/mpegtables.cpp	(working copy)
@@ -281,6 +281,19 @@
  */
 bool ProgramMapTable::IsEncrypted(void) const
 {
+    bool encrypted = IsProgramEncrypted();
+
+    for (uint i = 0; !encrypted && i < StreamCount(); i++)
+        encrypted |= IsStreamEncrypted(i);
+
+    return encrypted;
+}
+
+/** \fn ProgramMapTable::IsProgramEncrypted(void) const
+ *  \brief Returns true iff PMT's ProgramInfo contains CA descriptor.
+ */
+bool ProgramMapTable::IsProgramEncrypted(void) const
+{
     desc_list_t descs = MPEGDescriptor::ParseOnlyInclude(
         ProgramInfo(), ProgramInfoLength(), DescriptorID::conditional_access);
 
@@ -295,20 +308,28 @@
         //VERBOSE(VB_IMPORTANT, "DTVsm: "<<cad.toString());
     }
 
-    for (uint i = 0; i < StreamCount(); i++)
+    return encrypted;
+}
+
+/** \fn ProgramMapTable::IsStreamEncrypted(uint i) const
+ *  \brief Returns true iff PMT contains CA descriptor.
+ *
+ *  \param i index of stream
+ */
+bool ProgramMapTable::IsStreamEncrypted(uint i) const
+{
+    desc_list_t descs = MPEGDescriptor::ParseOnlyInclude(
+        StreamInfo(i), StreamInfoLength(i), DescriptorID::conditional_access);
+
+    bool encrypted = false;
+    QMap<uint,uint> encryption_system;
+    for (uint j = 0; j < descs.size(); j++)
     {
-        desc_list_t descs = MPEGDescriptor::ParseOnlyInclude(
-            StreamInfo(i), StreamInfoLength(i),
-            DescriptorID::conditional_access);
+        ConditionalAccessDescriptor cad(descs[j]);
+        encryption_system[cad.PID()] = cad.SystemID();
+        encrypted |= cad.SystemID();
 
-        for (uint j = 0; j < descs.size(); j++)
-        {
-            ConditionalAccessDescriptor cad(descs[j]);
-            encryption_system[cad.PID()] = cad.SystemID();
-            encrypted |= cad.SystemID();
-
-            //VERBOSE(VB_IMPORTANT, "DTVsm: "<<cad.toString());
-        }
+        //VERBOSE(VB_IMPORTANT, "DTVsm: "<<cad.toString());
     }
 
     return encrypted;
Index: libs/libmythtv/tv_play.cpp
===================================================================
--- libs/libmythtv/tv_play.cpp	(revision 12461)
+++ libs/libmythtv/tv_play.cpp	(working copy)
@@ -4686,7 +4686,7 @@
     float snr  = 0.0f;
     uint  ber  = 0xffffffff;
     int   pos  = -1;
-    QString pat(""), pmt(""), mgt(""), vct(""), nit(""), sdt("");
+    QString pat(""), pmt(""), mgt(""), vct(""), nit(""), sdt(""), crypt("");
     QString err = QString::null, msg = QString::null;
     for (it = slist.begin(); it != slist.end(); ++it)
     {
@@ -4736,6 +4736,10 @@
             sdt = it->IsGood() ? "s" : "_";
         else if ("matching_sdt" == it->GetShortName())
             sdt = it->IsGood() ? "S" : sdt;
+        else if ("seen_crypt" == it->GetShortName())
+            crypt = it->IsGood() ? "c" : "_";
+        else if ("matching_crypt" == it->GetShortName())
+            crypt = it->IsGood() ? "C" : crypt;
     }
     if (sig)
         infoMap["signal"] = QString::number(sig); // use normalized value
@@ -4753,9 +4757,9 @@
     if ((pos >= 0) && (pos < 100))
         sigDesc += " | " + tr("Rotor %1\%").arg(pos,2);
 
-    sigDesc = sigDesc + QString(" | (%1%2%3%4%5%6%7) %8")
+    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(sigMsg);
+        .arg(nit).arg(sdt).arg(crypt).arg(sigMsg);
 
     if (!err.isEmpty())
         sigDesc = err;
Index: libs/libmythtv/siscan.h
===================================================================
--- libs/libmythtv/siscan.h	(revision 12461)
+++ libs/libmythtv/siscan.h	(working copy)
@@ -85,6 +85,7 @@
     void HandlePAT(const ProgramAssociationTable*);
     void HandleCAT(const ConditionalAccessTable*) { }
     void HandlePMT(uint, const ProgramMapTable*) { }
+    void HandleEncryptionStatus(uint /*pnum*/, bool /*encrypted*/) { }
 
     // ATSC Main
     void HandleSTT(const SystemTimeTable*) {}
Index: libs/libmythtv/dtvsignalmonitor.h
===================================================================
--- libs/libmythtv/dtvsignalmonitor.h	(revision 12461)
+++ libs/libmythtv/dtvsignalmonitor.h	(working copy)
@@ -47,9 +47,6 @@
     uint GetDetectedNetworkID(void)   const  { return detectedNetworkID; }
     uint GetDetectedTransportID(void) const  { return detectedTransportID; }
 
-    void SetFTAOnly(bool fta)    { ignoreEncrypted = fta;  }
-    bool GetFTAOnly() const      { return ignoreEncrypted; }
-
     /// Sets rotor target pos from 0.0 to 1.0
     virtual void SetRotorTarget(float) {}
 
@@ -86,6 +83,7 @@
     void HandlePAT(const ProgramAssociationTable*);
     void HandleCAT(const ConditionalAccessTable*) {}
     void HandlePMT(uint, const ProgramMapTable*);
+    void HandleEncryptionStatus(uint, bool enc_status);
 
     // ATSC Main
     void HandleSTT(const SystemTimeTable*);
@@ -119,12 +117,14 @@
     SignalMonitorValue seenVCT;
     SignalMonitorValue seenNIT;
     SignalMonitorValue seenSDT;
+    SignalMonitorValue seenCrypt;
     SignalMonitorValue matchingPAT;
     SignalMonitorValue matchingPMT;
     SignalMonitorValue matchingMGT;
     SignalMonitorValue matchingVCT;
     SignalMonitorValue matchingNIT;
     SignalMonitorValue matchingSDT;
+    SignalMonitorValue matchingCrypt;
 
     // ATSC tuning info
     int                majorChannel;
@@ -138,7 +138,6 @@
     // MPEG/DVB/ATSC tuning info
     int                programNumber;
 
-    bool               ignoreEncrypted;
     QString            error;
 };
 
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 12461)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -1664,9 +1664,6 @@
         sd->SetCaching(true);
     }
 
-    bool fta = CardUtil::IgnoreEncrypted(
-        GetCaptureCardNum(), channel->GetCurrentInput());
-
     QString sistandard = dtvchan->GetSIStandard();
 
     // Check if this is an ATSC Channel
@@ -1690,7 +1687,6 @@
         sm->SetStreamData(sd);
         sm->SetChannel(major, minor);
         sd->SetVideoStreamsRequired(1);
-        sm->SetFTAOnly(fta);
 
         // Try to get pid of VCT from cache and
         // require MGT if we don't have VCT pid.
@@ -1746,7 +1742,6 @@
         sm->SetDVBService(netid, tsid, progNum);
         sd->SetVideoStreamsRequired(neededVideo);
         sd->SetAudioStreamsRequired(neededAudio);
-        sm->SetFTAOnly(fta);
 
         sm->AddFlags(SignalMonitor::kDTVSigMon_WaitForPMT |
                      SignalMonitor::kDTVSigMon_WaitForSDT |
@@ -1784,7 +1779,6 @@
         sm->SetStreamData(sd);
         sm->SetProgramNumber(progNum);
         sd->SetVideoStreamsRequired(1);
-        sm->SetFTAOnly(fta);
         sm->AddFlags(SignalMonitor::kDTVSigMon_WaitForPAT |
                      SignalMonitor::kDTVSigMon_WaitForPMT |
                      SignalMonitor::kDVBSigMon_WaitForPos);
Index: libs/libmythtv/dtvsignalmonitor.cpp
===================================================================
--- libs/libmythtv/dtvsignalmonitor.cpp	(revision 12461)
+++ libs/libmythtv/dtvsignalmonitor.cpp	(working copy)
@@ -1,6 +1,7 @@
 #include <unistd.h>
 
 #include "dtvchannel.h"
+#include "dvbchannel.h"
 #include "dtvsignalmonitor.h"
 #include "scanstreamdata.h"
 #include "mpegtables.h"
@@ -30,17 +31,19 @@
       seenVCT(tr("Seen")+" VCT", "seen_vct", 1, true, 0, 1, 0),
       seenNIT(tr("Seen")+" NIT", "seen_nit", 1, true, 0, 1, 0),
       seenSDT(tr("Seen")+" SDT", "seen_sdt", 1, true, 0, 1, 0),
+      seenCrypt(tr("Seen")+" Crypt", "seen_crypt", 1, true, 0, 1, 0),
       matchingPAT(tr("Matching")+" PAT", "matching_pat", 1, true, 0, 1, 0),
       matchingPMT(tr("Matching")+" PMT", "matching_pmt", 1, true, 0, 1, 0),
       matchingMGT(tr("Matching")+" MGT", "matching_mgt", 1, true, 0, 1, 0),
       matchingVCT(tr("Matching")+" VCT", "matching_vct", 1, true, 0, 1, 0),
       matchingNIT(tr("Matching")+" NIT", "matching_nit", 1, true, 0, 1, 0),
       matchingSDT(tr("Matching")+" SDT", "matching_sdt", 1, true, 0, 1, 0),
+      matchingCrypt(tr("Matching")+" Crypt", "matching_crypt",
+                    1, true, 0, 1, 0),
       majorChannel(-1), minorChannel(-1),
       networkID(0), transportID(0),
       detectedNetworkID(0), detectedTransportID(0),
       programNumber(-1),
-      ignoreEncrypted(true),
       error("")
 {
 }
@@ -112,6 +115,11 @@
         list<<seenSDT.GetName()<<seenSDT.GetStatus();
         list<<matchingSDT.GetName()<<matchingSDT.GetStatus();
     }
+    if (flags & kDTVSigMon_WaitForCrypt)
+    {
+        list<<seenCrypt.GetName()<<seenCrypt.GetStatus();
+        list<<matchingCrypt.GetName()<<matchingCrypt.GetStatus();
+    }
     if (error != "")
     {
         list<<"error"<<error;
@@ -140,12 +148,14 @@
     seenVCT.SetValue(    (flags & kDTVSigMon_VCTSeen)  ? 1 : 0);
     seenNIT.SetValue(    (flags & kDTVSigMon_NITSeen)  ? 1 : 0);
     seenSDT.SetValue(    (flags & kDTVSigMon_SDTSeen)  ? 1 : 0);
+    seenCrypt.SetValue(  (flags & kDTVSigMon_CryptSeen)? 1 : 0);
     matchingPAT.SetValue((flags & kDTVSigMon_PATMatch) ? 1 : 0);
     matchingPMT.SetValue((flags & kDTVSigMon_PMTMatch) ? 1 : 0);
     matchingMGT.SetValue((flags & kDTVSigMon_MGTMatch) ? 1 : 0);
     matchingVCT.SetValue((flags & kDTVSigMon_VCTMatch) ? 1 : 0);
     matchingNIT.SetValue((flags & kDTVSigMon_NITMatch) ? 1 : 0);
     matchingSDT.SetValue((flags & kDTVSigMon_SDTMatch) ? 1 : 0);
+    matchingCrypt.SetValue((flags & kDTVSigMon_CryptMatch) ? 1 : 0);
 }
 
 void DTVSignalMonitor::UpdateListeningForEIT(void)
@@ -177,9 +187,10 @@
     DBG_SM(QString("SetChannel(%1, %2)").arg(major).arg(minor), "");
     if (GetATSCStreamData() && (majorChannel != major || minorChannel != minor))
     {
-        RemoveFlags(kDTVSigMon_PATSeen | kDTVSigMon_PATMatch |
-                    kDTVSigMon_PMTSeen | kDTVSigMon_PMTMatch |
-                    kDTVSigMon_VCTSeen | kDTVSigMon_VCTMatch);
+        RemoveFlags(kDTVSigMon_PATSeen   | kDTVSigMon_PATMatch |
+                    kDTVSigMon_PMTSeen   | kDTVSigMon_PMTMatch |
+                    kDTVSigMon_VCTSeen   | kDTVSigMon_VCTMatch |
+                    kDTVSigMon_CryptSeen | kDTVSigMon_CryptMatch);
         majorChannel = major;
         minorChannel = minor;
         GetATSCStreamData()->SetDesiredChannel(major, minor);
@@ -192,7 +203,8 @@
     DBG_SM(QString("SetProgramNumber(%1)").arg(progNum), "");
     if (programNumber != progNum)
     {
-        RemoveFlags(kDTVSigMon_PMTSeen | kDTVSigMon_PMTMatch);
+        RemoveFlags(kDTVSigMon_PMTSeen   | kDTVSigMon_PMTMatch |
+                    kDTVSigMon_CryptSeen | kDTVSigMon_CryptMatch);
         programNumber = progNum;
         if (GetStreamData())
             GetStreamData()->SetDesiredProgram(programNumber);
@@ -211,8 +223,9 @@
         return;
     }
 
-    RemoveFlags(kDTVSigMon_PMTSeen | kDTVSigMon_PMTMatch |
-                kDTVSigMon_SDTSeen | kDTVSigMon_SDTMatch);
+    RemoveFlags(kDTVSigMon_PMTSeen   | kDTVSigMon_PMTMatch |
+                kDTVSigMon_SDTSeen   | kDTVSigMon_SDTMatch |
+                kDTVSigMon_CryptSeen | kDTVSigMon_CryptMatch);
 
     transportID   = tsid;
     networkID     = netid;
@@ -298,6 +311,9 @@
 {
     AddFlags(kDTVSigMon_PMTSeen);
 
+    if (pmt->IsEncrypted())
+        GetStreamData()->TestDecryption(pmt);
+
     if (programNumber < 0)
         return; // don't print error messages during channel scan.
 
@@ -309,12 +325,6 @@
         return; // Not the PMT we are looking for...
     }
 
-    if (ignoreEncrypted && pmt->IsEncrypted())
-    {
-        VERBOSE(VB_IMPORTANT, LOC + "Ignoring encrypted program");
-        return;
-    }
-
     // if PMT contains audio and/or video stream set as matching.
     uint hasAudio = 0;
     uint hasVideo = 0;
@@ -328,6 +338,15 @@
     if ((hasVideo >= GetStreamData()->GetVideoStreamsRequired()) &&
         (hasAudio >= GetStreamData()->GetAudioStreamsRequired()))
     {
+#ifdef USING_DVB
+        DVBChannel* dvbchan = dynamic_cast<DVBChannel*>(GetDTVChannel());
+        if (dvbchan)
+            dvbchan->SetPMT(pmt);
+#endif // USING_DVB
+
+        if (pmt->IsEncrypted())
+            AddFlags(kDTVSigMon_WaitForCrypt);
+
         AddFlags(kDTVSigMon_PMTMatch);
     }
     else
@@ -442,6 +461,13 @@
     }
 }
 
+void DTVSignalMonitor::HandleEncryptionStatus(uint, bool enc_status)
+{
+    AddFlags(kDTVSigMon_CryptSeen);
+    if (!enc_status)
+        AddFlags(kDTVSigMon_CryptMatch);
+}
+
 ATSCStreamData *DTVSignalMonitor::GetATSCStreamData()
 {
     return dynamic_cast<ATSCStreamData*>(stream_data);
@@ -489,6 +515,8 @@
             return false;
     if ((flags & kDTVSigMon_WaitForSDT) && !matchingSDT.IsGood())
             return false;
+    if ((flags & kDTVSigMon_WaitForCrypt) && !matchingCrypt.IsGood())
+            return false;
 
     return true;
 }
