Index: libs/libmythtv/cardutil.h
===================================================================
--- libs/libmythtv/cardutil.h	(revision 14331)
+++ libs/libmythtv/cardutil.h	(working copy)
@@ -107,6 +107,18 @@
             (rawtype == "HDHOMERUN");
     }
 
+    static bool         IsTuningDigital(const QString &rawtype)
+    {
+        return
+            (rawtype == "DVB")       || (rawtype == "HDTV")  ||
+            (rawtype == "HDHOMERUN");
+    }
+
+    static bool         IsTuningAnalog(const QString &rawtype)
+    {
+        return (rawtype == "V4L");
+    }
+
     static int          GetCardID(const QString &videodevice,
                                   QString hostname = QString::null);
     static uint         GetChildCardID(uint cardid);
Index: libs/libmythtv/sourceutil.h
===================================================================
--- libs/libmythtv/sourceutil.h	(revision 14331)
+++ libs/libmythtv/sourceutil.h	(working copy)
@@ -16,6 +16,8 @@
     static bool    GetListingsLoginData(uint sourceid,
                                         QString &grabber, QString &userid,
                                         QString &passwd,  QString &lineupid);
+    static uint    GetConnectionCount(uint sourceid);
+    static bool    IsProperlyConnected(uint sourceid, bool strich = false);
     static bool    IsEncoder(uint sourceid, bool strict = false);
     static bool    IsUnscanable(uint sourceid);
     static bool    IsAnySourceScanable(void);
Index: libs/libmythtv/datadirect.cpp
===================================================================
--- libs/libmythtv/datadirect.cpp	(revision 14331)
+++ libs/libmythtv/datadirect.cpp	(working copy)
@@ -686,6 +686,17 @@
 {
     int new_channels = 0;
 
+    if (!SourceUtil::GetConnectionCount(sourceid))
+    {
+        VERBOSE(VB_IMPORTANT, LOC +
+                "Not inserting channels into disconnected source "
+                <<sourceid<<".");
+        return -1;
+    }
+
+    if (!SourceUtil::IsProperlyConnected(sourceid, true))
+        return -1;
+
     // Find all the channels in the dd_v_station temp table
     // where there is no channel with the same xmltvid in the
     // DB using the same source.
@@ -706,7 +717,8 @@
         return -1;
     }
 
-    bool is_encoder = SourceUtil::IsEncoder(sourceid, true);
+    bool is_encoder = (SourceUtil::IsEncoder(sourceid, true) ||
+                       SourceUtil::IsUnscanable(sourceid));
 
     while (query.next())
     {
@@ -750,6 +762,12 @@
 bool DataDirectProcessor::UpdateChannelsUnsafe(
     uint sourceid, bool filter_new_channels)
 {
+    if (filter_new_channels &&
+        !SourceUtil::IsProperlyConnected(sourceid, false))
+    {
+        return false;
+    }
+
     MSqlQuery dd_station_info(MSqlQuery::DDCon());
     dd_station_info.prepare(
         "SELECT callsign,         stationname, stationid,"
@@ -770,7 +788,8 @@
         "    atsc_minor_chan = :MINORCHAN "
         "WHERE xmltvid = :STATIONID AND sourceid = :SOURCEID");
 
-    bool is_encoder = SourceUtil::IsEncoder(sourceid, true);
+    bool is_encoder = (SourceUtil::IsEncoder(sourceid, true) ||
+                       SourceUtil::IsUnscanable(sourceid));
 
     while (dd_station_info.next())        
     {
Index: libs/libmythtv/videosource.cpp
===================================================================
--- libs/libmythtv/videosource.cpp	(revision 14333)
+++ libs/libmythtv/videosource.cpp	(working copy)
@@ -1924,6 +1924,8 @@
 
     if (cardid && srcid)
     {
+        save(); // save info for fetch..
+
         QString cardtype = CardUtil::GetRawCardType(crdid, 0);
 
         if (!CardUtil::IsUnscanable(cardtype) &&
Index: libs/libmythtv/sourceutil.cpp
===================================================================
--- libs/libmythtv/sourceutil.cpp	(revision 14331)
+++ libs/libmythtv/sourceutil.cpp	(working copy)
@@ -114,6 +114,93 @@
     return list;
 }
 
+uint SourceUtil::GetConnectionCount(uint sourceid)
+{
+    QStringList types = get_cardtypes(sourceid);
+    return types.size();
+}
+
+bool SourceUtil::IsProperlyConnected(uint sourceid, bool strict)
+{
+    QStringList types = get_cardtypes(sourceid);
+    QMap<QString,uint> counts;
+    QStringList::const_iterator it = types.begin();
+    for (; it != types.end(); ++it)
+    {
+        counts[*it]++;
+
+        counts[CardUtil::IsEncoder(*it)    ? "ENCODER" : "NOT_ENCODER"]++;
+        counts[CardUtil::IsUnscanable(*it) ? "NO_SCAN" : "SCAN"]++;
+
+        if (CardUtil::IsTuningAnalog(*it))
+            counts["ANALOG_TUNING"]++;
+        else if (CardUtil::IsTuningDigital(*it))
+            counts["DIGITAL_TUNING"]++;
+        else
+            counts["OTHER_TUNING"]++;
+    }
+
+    bool tune_mismatch = counts["ANALOG_TUNING"]   && counts["DIGITAL_TUNING"];
+    bool enc_mismatch  = counts["ENCODER"]         && counts["NOT_ENCODER"];
+    bool scan_mismatch = counts["SCAN"]            && counts["NO_SCAN"];
+    bool fw_mismatch   = (counts["FIREWIRE"] &&
+                          (counts["FIREWIRE"] < types.size()));
+
+    if (tune_mismatch)
+    {
+        uint a = counts["ANALOG_TUNERS"];
+        uint d = counts["DIGITAL_TUNERS"];
+        VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
+                QString("Source ID %1 ").arg(sourceid) +
+                QString("appears to be connected\n\t\t\tto %1 analog tuner%2,")
+                .arg(a).arg((1 == a) ? "":"s") +
+                QString("and %1 digital tuner%2.\n\t\t\t")
+                .arg(d).arg((1 == d) ? "":"s") +
+                QString("Can't mix analog and digital tuning information."));
+    }
+
+    if (enc_mismatch)
+    {
+        uint a = counts["ENCODER"];
+        uint d = counts["NOT_ENCODER"];
+        VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
+                QString("Source ID %1 ").arg(sourceid) +
+                QString("appears to be connected\n\t\t\tto %1 encoder%2, ")
+                .arg(a).arg((1 == a) ? "":"s") +
+                QString("and %1 non-encoder%2. ")
+                .arg(d).arg((1 == d) ? "":"s") +
+                QString("This is probably a bad idea."));
+    }
+
+    if (scan_mismatch)
+    {
+        uint a = counts["SCAN"];
+        uint d = counts["NO_SCAN"];
+        VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
+                QString("Source ID %1 ").arg(sourceid) +
+                QString("appears to be connected\n\t\t\t"
+                        "to %1 scanable input%2, ")
+                .arg(a).arg((1 == a) ? "":"s") +
+                QString("and %1 non-scanable input%2. ")
+                .arg(d).arg((1 == d) ? "":"s") +
+                QString("This may be a problem."));
+    }
+
+    if (fw_mismatch)
+    {
+        VERBOSE(VB_GENERAL, QString("SourceUtil::IsProperlyConnected(): ") +
+                QString(
+                    "Source ID %1 appears to be connected\n\t\t\t"
+                    "to both firewire and non-firewire inputs. "
+                    "This is probably a bad idea.").arg(sourceid));
+    }
+
+    if (!strict)
+        return !tune_mismatch;
+
+    return !tune_mismatch && !enc_mismatch && !scan_mismatch && !fw_mismatch;
+}
+
 bool SourceUtil::IsEncoder(uint sourceid, bool strict)
 {
     bool encoder = true;
