Index: programs/mythbackend/scheduler.cpp
===================================================================
--- programs/mythbackend/scheduler.cpp	(revision 7110)
+++ programs/mythbackend/scheduler.cpp	(working copy)
@@ -268,8 +268,22 @@
     retrylist.sort(comp_retry);
     VERBOSE(VB_SCHEDULE, "MoveHigherRecords...");
     MoveHigherRecords();
+    VERBOSE(VB_SCHEDULE, "Clear retrylist...");
     retrylist.clear();
 
+    // If user has a global setting to start recordings early or finish
+    // them late, we'll see if we can better honour this by assigning
+    // some recordings to an idle card.
+    if (gContext->GetNumSetting("RecordOverTime") > 0 ||
+        gContext->GetNumSetting("RecordPreRoll") > 0)
+    {
+        VERBOSE(VB_SCHEDULE, "Sort by time...");
+	reclist.sort(comp_recstart);
+	
+	VERBOSE(VB_SCHEDULE, "ShuffleForOverrecord...");
+	ShuffleForOverrecord();
+    }
+    
     VERBOSE(VB_SCHEDULE, "ClearListMaps...");
     ClearListMaps();
 
@@ -485,8 +499,23 @@
     recordidlistmap.clear();
 }
 
-bool Scheduler::FindNextConflict(RecList &cardlist, ProgramInfo *p, RecIter &j)
+bool Scheduler::FindNextConflict(RecList &cardlist, ProgramInfo *p, RecIter &j, bool findSoftConflicts)
 {
+
+    int prerollseconds;
+    int overrecordseconds;
+
+    // A "soft conflict" is when two programs overlap only when the
+    // global underrecord and overrecord settings are taken into
+    // consideration. These settings are considered "soft" in the sense
+    // that MythTV will ignore them when it's necessary to do so in
+    // order to record everything scheduled.
+    if (findSoftConflicts)
+    {
+      prerollseconds    = gContext->GetNumSetting("RecordPreRoll");
+      overrecordseconds = gContext->GetNumSetting("RecordOverTime");
+    }
+
     for ( ; j != cardlist.end(); j++)
     {
         ProgramInfo *q = *j;
@@ -497,8 +526,19 @@
             continue;
         if (p->cardid != 0 && p->cardid != q->cardid)
             continue;
-        if (p->recendts <= q->recstartts || p->recstartts >= q->recendts)
-            continue;
+	if (findSoftConflicts)
+        {
+            if (p->recendts.addSecs(overrecordseconds) <=
+                        q->recstartts.addSecs((-1) * prerollseconds)
+               || p->recstartts.addSecs((-1) * prerollseconds) >=
+                        q->recendts.addSecs(overrecordseconds))
+		continue;
+        }
+        else
+        {
+            if (p->recendts <= q->recstartts || p->recstartts >= q->recendts)
+                continue;
+        }
         if (p->inputid == q->inputid && p->shareable)
             continue;
 
@@ -734,6 +774,56 @@
     }
 }
 
+void Scheduler::ShuffleForOverrecord(void)
+{
+    VERBOSE(VB_SCHEDULE, "Trying to accommodate pre-roll / overrecord:");
+
+    RecIter i = reclist.begin();
+
+    for ( ; i != reclist.end(); i++)
+    {
+	ProgramInfo *p = *i;
+
+	if (p->recstatus != rsRecording && p->recstatus != rsWillRecord)
+	    continue;
+
+        // Look for soft conflicts with any other scheduled program
+        RecIter k = reclist.begin();
+        if (FindNextConflict(reclist, p, k, true))
+        {
+            // There's a soft conflict, so let's see if a different
+            // showing would give us no conflicts at all.
+
+            // Get list of alternative showings
+            RecList &showinglist = titlelistmap[p->title];
+            RecIter j = showinglist.begin();
+
+            // Cycle through showings, looking for one that won't conflict
+            for ( ; j != showinglist.end(); j++)
+            {
+                ProgramInfo *q = *j;
+
+                // No need to re-check the same showing
+                if (q == p)
+                    continue;
+
+                k = reclist.begin();
+                if (!FindNextConflict(reclist, q, k, true))
+                {
+                    // This showing is completely conflict-free, so
+                    // substitute it.
+
+                    q->recstatus = rsWillRecord;
+                    MarkOtherShowings(q);
+                    PrintRec(p, "  -");
+                    PrintRec(q, "  +");
+                    break;
+		}
+            }
+	}
+    }
+}
+
 void Scheduler::getConflicting(ProgramInfo *pginfo, QStringList &strlist)
 {
     QMutexLocker lockit(reclist_lock);
Index: programs/mythbackend/scheduler.h
===================================================================
--- programs/mythbackend/scheduler.h	(revision 7110)
+++ programs/mythbackend/scheduler.h	(working copy)
@@ -68,7 +68,7 @@
     void PruneOverlaps(void);
     void BuildListMaps(void);
     void ClearListMaps(void);
-    bool FindNextConflict(RecList &cardlist, ProgramInfo *p, RecIter &iter);
+    bool FindNextConflict(RecList &cardlist, ProgramInfo *p, RecIter &iter, bool findSoftConflicts = false);
     void MarkOtherShowings(ProgramInfo *p);
     void MarkShowingsList(RecList &showinglist, ProgramInfo *p);
     void BackupRecStatus(void);
@@ -77,6 +77,7 @@
     void SchedNewRecords(void);
     void MoveHigherRecords(void);
     void PruneRedundants(void);
+    void ShuffleForOverrecord(void);
 
 
     void findAllScheduledPrograms(list<ProgramInfo *> &proglist);
