Index: libs/libmythtv/dbcheck.cpp
===================================================================
--- libs/libmythtv/dbcheck.cpp	(revision 20676)
+++ libs/libmythtv/dbcheck.cpp	(working copy)
@@ -18,7 +18,7 @@
 #define MINIMUM_DBMS_VERSION 5,0,15
 
 /// This is the DB schema version expected by the running MythTV instance.
-const QString currentDatabaseVersion = "1235";
+const QString currentDatabaseVersion = "1236";
 
 static bool UpdateDBVersionNumber(const QString &newnumber);
 static bool performActualUpdate(
@@ -4542,8 +4542,19 @@
         if (!performActualUpdate(updates, "1235", dbver))
             return false;
     }
+    if (dbver == "1235")
+    {
+        const char *updates[] = {
+"ALTER TABLE program"
+"    ADD COLUMN lastupdate TIMESTAMP DEFAULT CURRENT_TIMESTAMP "
+"        ON UPDATE CURRENT_TIMESTAMP, "
+"    ADD INDEX program_lastupdate (lastupdate);",
+NULL
+};
+        if (!performActualUpdate(updates, "1236", dbver))
+            return false;
+    }
 
-
     return true;
 }
 
Index: libs/libmythtv/datadirect.h
===================================================================
--- libs/libmythtv/datadirect.h	(revision 20676)
+++ libs/libmythtv/datadirect.h	(working copy)
@@ -327,7 +327,7 @@
         uint sourceid, bool insert_channels, bool filter_new_channels);
     static bool UpdateChannelsUnsafe(
         uint sourceid, bool filter_new_channels);
-    static void DataDirectProgramUpdate(void);
+    static void DataDirectProgramUpdate(int sourceid, const QDateTime &from, const QDateTime &to);
 
     // static command, makes Labs and Schedules Direct ProgramIDs compatible.
     static void FixProgramIDs(void);
Index: libs/libmythtv/datadirect.cpp
===================================================================
--- libs/libmythtv/datadirect.cpp	(revision 20676)
+++ libs/libmythtv/datadirect.cpp	(working copy)
@@ -825,10 +825,74 @@
     return true;
 }
 
-void DataDirectProcessor::DataDirectProgramUpdate(void)
+void DataDirectProcessor::DataDirectProgramUpdate(int sourceid, const QDateTime &from, const QDateTime &to)
 {
     MSqlQuery query(MSqlQuery::DDCon());
 
+    QString queryString("DELETE program FROM program"
+                        " LEFT JOIN channel"
+                        "  ON program.chanid = channel.chanid"
+                        " LEFT JOIN dd_genre"
+                        "  ON program.programid = dd_genre.programid"
+                        "  AND dd_genre.relevance = '0'"
+                        " LEFT JOIN dd_v_program"
+                        "  ON program.chanid = dd_v_program.chanid"
+                        "  AND program.starttime = DATE_ADD(dd_v_program.starttime, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND program.endtime = DATE_ADD(dd_v_program.endtime, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND program.title = dd_v_program.title"
+                        "  AND program.subtitle = dd_v_program.subtitle"
+                        "  AND program.description = dd_v_program.description"
+                        "  AND program.showtype = dd_v_program.showtype"
+                        "  AND program.category_type = dd_v_program.category_type"
+                        "  AND program.airdate = dd_v_program.airdate"
+                        "  AND program.stars = dd_v_program.stars"
+                        "  AND program.stereo = dd_v_program.stereo"
+                        "  AND program.subtitled = dd_v_program.subtitled"
+                        "  AND program.subtitletypes = (dd_v_program.subtitled << 1) | dd_v_program.closecaptioned"
+                        "  AND program.videoprop = dd_v_program.hdtv"
+                        "  AND program.audioprop = (dd_v_program.dolby << 3) | dd_v_program.stereo"
+                        "  AND program.hdtv = dd_v_program.hdtv"
+                        "  AND program.closecaptioned = dd_v_program.closecaptioned"
+                        "  AND program.partnumber = dd_v_program.partnumber"
+                        "  AND program.parttotal = dd_v_program.parttotal"
+                        "  AND program.seriesid = dd_v_program.seriesid"
+                        "  AND program.originalairdate <=> dd_v_program.originalairdate"
+                        "  AND program.colorcode = dd_v_program.colorcode"
+                        "  AND program.syndicatedepisodenumber = dd_v_program.syndicatedepisodenumber"
+                        "  AND program.programid = dd_v_program.programid"
+                        " WHERE"
+                        "  (channel.chanid is NULL"
+                        "   OR (dd_genre.programid is NOT NULL"
+                        "       AND program.category <> dd_genre.class)"
+                        "   OR dd_v_program.chanid is NULL)"
+                        "  AND program.starttime >= DATE_ADD(:FROM, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND program.starttime < DATE_ADD(:TO, INTERVAL channel.tmoffset MINUTE)"
+                        "  AND channel.sourceid = :SOURCEID");
+
+    QString preferredSource(gContext->GetSetting("PreferredListingsSource"));
+    if (!preferredSource.isEmpty() && preferredSource != "datadirect")
+        queryString += "  AND program.listingsource = " + QString::number(kListingSourceDDSchedulesDirect);
+
+    queryString += ';';
+
+    query.prepare(queryString); 
+    query.bindValue(":FROM", from);
+    query.bindValue(":TO", to);
+    query.bindValue(":SOURCEID", sourceid);
+    if (!query.exec())
+        MythDB::DBError("Deleting changed entries from program table", query);
+
+    if (!query.exec("DELETE dd_v_program FROM dd_v_program"
+                    " INNER JOIN program"
+                    "  ON dd_v_program.chanid = program.chanid"
+                    "   AND ((dd_v_program.endtime > program.starttime"
+                    "     AND dd_v_program.endtime <= program.endtime)"
+                    "    OR (dd_v_program.starttime >= program.starttime"
+                    "     AND dd_v_program.starttime < program.endtime)"
+                    "    OR (dd_v_program.starttime < program.starttime"
+                    "     AND dd_v_program.endtime > program.endtime));"))
+        MythDB::DBError("Deleting up-to-date entries from listings source data", query);
+        
     //cerr << "Adding rows to main program table from view table..\n";
     query.prepare(
         "INSERT IGNORE INTO program "
@@ -860,7 +924,6 @@
         "  ( dd_v_program.programid = dd_genre.programid AND  "
         "    dd_genre.relevance     = '0' ) "
         "WHERE dd_v_program.chanid = channel.chanid");
-
     query.bindValue(":LSOURCE", kListingSourceDDSchedulesDirect);
 
     if (!query.exec())
Index: libs/libmythtv/programdata.cpp
===================================================================
--- libs/libmythtv/programdata.cpp	(revision 20676)
+++ libs/libmythtv/programdata.cpp	(working copy)
@@ -916,7 +916,7 @@
 
 bool ProgramData::ClearDataByChannel(
     uint chanid, const QDateTime &from, const QDateTime &to,
-    bool use_channel_time_offset)
+    bool use_channel_time_offset, bool clear_program)
 {
     int secs = 0;
     if (use_channel_time_offset)
@@ -926,14 +926,18 @@
     QDateTime newTo   = to.addSecs(secs);
 
     MSqlQuery query(MSqlQuery::InitCon());
-    query.prepare("DELETE FROM program "
-                  "WHERE starttime >= :FROM AND starttime < :TO "
-                  "AND chanid = :CHANID ;");
-    query.bindValue(":FROM", newFrom);
-    query.bindValue(":TO", newTo);
-    query.bindValue(":CHANID", chanid);
-    bool ok = query.exec();
+    bool ok;
 
+    if (clear_program) {
+        query.prepare("DELETE FROM program "
+                      "WHERE starttime >= :FROM AND starttime < :TO "
+                      "AND chanid = :CHANID ;");
+        query.bindValue(":FROM", newFrom);
+        query.bindValue(":TO", newTo);
+        query.bindValue(":CHANID", chanid);
+        ok = query.exec();
+    }
+
     query.prepare("DELETE FROM programrating "
                   "WHERE starttime >= :FROM AND starttime < :TO "
                   "AND chanid = :CHANID ;");
Index: libs/libmythtv/programdata.h
===================================================================
--- libs/libmythtv/programdata.h	(revision 20676)
+++ libs/libmythtv/programdata.h	(working copy)
@@ -261,7 +261,8 @@
         uint chanid,
         const QDateTime &from,
         const QDateTime &to,
-        bool use_channel_time_offset);
+        bool use_channel_time_offset,
+        bool clear_program = FALSE);
     static bool ClearDataBySource(
         uint sourceid,
         const QDateTime &from,
Index: programs/mythfilldatabase/filldata.cpp
===================================================================
--- programs/mythfilldatabase/filldata.cpp	(revision 20676)
+++ programs/mythfilldatabase/filldata.cpp	(working copy)
@@ -308,7 +308,8 @@
     VERBOSE(VB_GENERAL, "Data for source cleared.");
 
     VERBOSE(VB_GENERAL, "Updating programs.");
-    DataDirectProcessor::DataDirectProgramUpdate();
+    DataDirectProcessor::DataDirectProgramUpdate(source.id, fromlocaldt,
+                                                 tolocaldt);
     VERBOSE(VB_GENERAL, "Program table update complete.");
 
     return true;
Index: programs/mythfilldatabase/main.cpp
===================================================================
--- programs/mythfilldatabase/main.cpp	(revision 20676)
+++ programs/mythfilldatabase/main.cpp	(working copy)
@@ -713,7 +713,7 @@
         query.prepare("UPDATE program SET generic = 1 WHERE "
             "((programid = '' AND subtitle = '' AND description = '') OR "
             " (programid <> '' AND category_type = 'series' AND "
-            "  program.programid LIKE '%0000'));");
+            "  program.programid LIKE '%0000') AND generic <> 1);");
 
         if (!query.exec())
             MythDB::DBError("mark generic", query);
@@ -814,7 +814,6 @@
     if (grab_data)
     {
         MSqlQuery updt(MSqlQuery::InitCon());
-        updt.exec("UPDATE program SET first = 0, last = 0;");
 
         VERBOSE(VB_GENERAL, "Marking episode first showings.");
 
@@ -828,10 +827,19 @@
             {
                 updt.prepare("UPDATE program set first = 1 "
                              "WHERE starttime = :STARTTIME "
-                             "  AND programid = :PROGRAMID;");
+                             "  AND programid = :PROGRAMID "
+                             "  AND first <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":PROGRAMID", query.value(1).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set first = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND programid = :PROGRAMID "
+                             "  AND first <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":PROGRAMID", query.value(1).toString());
+                updt.exec();
             }
         }
         int found = query.size();
@@ -848,12 +856,25 @@
                              "WHERE starttime = :STARTTIME "
                              "  AND title = :TITLE "
                              "  AND subtitle = :SUBTITLE "
-                             "  AND description = :DESCRIPTION");
+                             "  AND description = :DESCRIPTION "
+                             "  AND first <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":TITLE", query.value(1).toString());
                 updt.bindValue(":SUBTITLE", query.value(2).toString());
                 updt.bindValue(":DESCRIPTION", query.value(3).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set first = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND title = :TITLE "
+                             "  AND subtitle = :SUBTITLE "
+                             "  AND description = :DESCRIPTION "
+                             "  AND first <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":TITLE", query.value(1).toString());
+                updt.bindValue(":SUBTITLE", query.value(2).toString());
+                updt.bindValue(":DESCRIPTION", query.value(3).toString());
+                updt.exec();
             }
         }
         found += query.size();
@@ -870,10 +891,19 @@
             {
                 updt.prepare("UPDATE program set last = 1 "
                              "WHERE starttime = :STARTTIME "
-                             "  AND programid = :PROGRAMID;");
+                             "  AND programid = :PROGRAMID "
+                             "  AND last <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":PROGRAMID", query.value(1).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set last = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND programid = :PROGRAMID "
+                             "  AND last <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":PROGRAMID", query.value(1).toString());
+                updt.exec();
             }
         }
         found = query.size();
@@ -890,12 +920,25 @@
                              "WHERE starttime = :STARTTIME "
                              "  AND title = :TITLE "
                              "  AND subtitle = :SUBTITLE "
-                             "  AND description = :DESCRIPTION");
+                             "  AND description = :DESCRIPTION "
+                             "  AND last <> 1;");
                 updt.bindValue(":STARTTIME", query.value(0).toDateTime());
                 updt.bindValue(":TITLE", query.value(1).toString());
                 updt.bindValue(":SUBTITLE", query.value(2).toString());
                 updt.bindValue(":DESCRIPTION", query.value(3).toString());
                 updt.exec();
+
+                updt.prepare("UPDATE program set last = 0 "
+                             "WHERE starttime <> :STARTTIME "
+                             "  AND title = :TITLE "
+                             "  AND subtitle = :SUBTITLE "
+                             "  AND description = :DESCRIPTION "
+                             "  AND last <> 0;");
+                updt.bindValue(":STARTTIME", query.value(0).toDateTime());
+                updt.bindValue(":TITLE", query.value(1).toString());
+                updt.bindValue(":SUBTITLE", query.value(2).toString());
+                updt.bindValue(":DESCRIPTION", query.value(3).toString());
+                updt.exec();
             }
         }
         found += query.size();
