[mythtv] [PATCH] Scheduler fixups

Steve Davies steve at one47.co.uk
Mon Jan 19 17:35:02 EST 2004


Okay,

I've been promising this for a week, so I'll send it around for comments. I 
hope the coding style is okay - I've tried to follow the overall trend, but 
I'm not a programmer by trade, so be gentle!

What this does:
1) Adds 2 new options in Setup->TV->RecPriorities->General
    1a. It allows different "sources" that share the same channel (xmltvid)
        to be scheduled "correctly"
    2a. It allows for DoMultiCard() to be run earlier so there is a greater
        chance of recording a program earlier rather than catching a
        repeat on the first cardid.
2) Adds a "fix up" pass - This catches programs which were un-necessarily 
suppressed by one of the autoconflict mechanisms, and also tries to resolve 
remaining conflicts if there is an "Other recording" available.
3) Should prevent the race condition mentioned today where a scheduling change 
during a global-preroll period can cause a recording to be started a second 
time on another cardid.
4) Some misc. tidyups that I hope no-one objects to.

The size of the QUERY_GETSCHEDULED backend request/response has changed. This 
means updating all front- and back-ends at the same time, or risk some 
strangeness. I don't this this is actually *necessary*, but it looked tidier 
to do this and be consistent.

_Suggested usage:_
For people with one tuner, some occasional omissions and the race condition 
should be fixed now. Nothing serious.

I think that the global XmltvID option should default to "yes", although I 
left it off for now - It improves scheduling massively on my box. Everyone 
with 2+ different sources should give it a go... I can now (sanely) combine a 
UK terrestrial input of channels 1,2,3,4 with a DVB-T card which provides the 
same 4 channels, and several others.

The option to run DoMultiCard() early only really apply to people with more 
than one of the same card/sourceid. It doesn't crash my system, but my cards 
are not the same so I cannot test this properly.

_Still to do (not in any order)_
1) Fix any bugs reported by you guys.
2) Add an option to try to avoid scheduling the first receiver for LiveTV 
watching.
2b) As 2) above, but on a per backend basis (might do this, might not.)
3) Optimise the scheduler. It's getting slow, and there is a lot of 
repetition. We can also improve on the DB indexes and access methods if we try :-)
4) A system which allows the first 'n' minutes or last 'n' minutes of a show 
to be automatically negatively pre/post-rolled by the scheduler if it can 
solve a conflict - This should fix the nastly one-minute overlaps in schedules 
sometimes.

Like I say, commments wanted.

Regards,
Steve


-- 
Steve Davies                   steve at one47.co.uk

PGP Fingerprints:
DH/DSS : 5D85 8164 91D7 E9CC 4F80  842B AB86 93D9 8938 7612
RSA    :      4E2E E60F 3D76 9E7E  70F9 901B 70FA 56C8
RSA4096: 02BE 5C0E EFA2 E1E4 EA89  C9CC 1E4F F654 3BC7 B65E
-------------- next part --------------
Index: libs/libmythtv/programinfo.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/programinfo.cpp,v
retrieving revision 1.98
diff -u -r1.98 programinfo.cpp
--- libs/libmythtv/programinfo.cpp	11 Jan 2004 17:07:37 -0000	1.98
+++ libs/libmythtv/programinfo.cpp	19 Jan 2004 22:25:50 -0000
@@ -43,6 +43,7 @@
     recdups = kRecordDupsNever;
 
     sourceid = -1;
+    xmltvid = "";
     inputid = -1;
     cardid = -1;
     schedulerid = "";
@@ -83,6 +84,7 @@
     recdups = other.recdups;
 
     sourceid = other.sourceid;
+    xmltvid = other.xmltvid;
     inputid = other.inputid;
     cardid = other.cardid;
     schedulerid = other.schedulerid;
@@ -127,6 +129,7 @@
     recdups = other.recdups;
 
     sourceid = other.sourceid;
+    xmltvid = other.xmltvid;
     inputid = other.inputid;
     cardid = other.cardid;
     schedulerid = other.schedulerid;
@@ -181,6 +184,7 @@
     list << recendts.toString(Qt::ISODate);
     list << QString::number(repeat);
     list << QString::number(programflags);
+    list << ((xmltvid != "") ? xmltvid : QString(" "));
 }
 
 void ProgramInfo::FromStringList(QStringList &list, int offset)
@@ -227,6 +231,7 @@
     recendts = QDateTime::fromString(*(it++), Qt::ISODate);
     repeat = (*(it++)).toInt();
     programflags = (*(it++)).toInt();
+    xmltvid = *(it++);
 
     if (title == " ")
         title = "";
@@ -252,6 +257,8 @@
         chansign = "";
     if (recpriority == " ")
         recpriority = "";
+    if (xmltvid == " ")
+        xmltvid = "";
 }
 
 void ProgramInfo::ToMap(QSqlDatabase *db, QMap<QString, QString> &progMap)
@@ -290,6 +297,7 @@
     progMap["channum"] = chanstr;
     progMap["chanid"] = chanid;
     progMap["iconpath"] = "";
+    progMap["xmltvid"] = xmltvid;
 
     seconds = recstartts.secsTo(recendts);
     minutes = seconds / 60;
@@ -397,7 +405,8 @@
 
     thequery = QString("SELECT channel.chanid,starttime,endtime,title,"
                        "subtitle,description,category,channel.channum,"
-                       "channel.callsign,channel.name,previouslyshown "
+                       "channel.callsign,channel.name,previouslyshown,"
+                       "channel.xmltvid "
                        "FROM program,channel ")
                        + where;
 
@@ -424,6 +433,7 @@
             proginfo->chansign = query.value(8).toString();
             proginfo->channame = query.value(9).toString();
             proginfo->repeat = query.value(10).toInt();
+            proginfo->xmltvid = query.value(11).toString();
             proginfo->spread = -1;
 
             if (proginfo->title == QString::null)
@@ -434,6 +444,8 @@
                 proginfo->description = "";
             if (proginfo->category == QString::null)
                 proginfo->category = "";
+            if (proginfo->xmltvid == QString::null)
+                proginfo->xmltvid = "";
 
             proglist->append(proginfo);
         }
@@ -464,7 +476,8 @@
    
     thequery = QString("SELECT channel.chanid,starttime,endtime,title,subtitle,"
                        "description,category,channel.channum,channel.callsign, "
-                       "channel.name,previouslyshown FROM program,channel "
+                       "channel.name,previouslyshown,channel.xmltvid "
+                       "FROM program,channel "
                        "WHERE program.chanid = %1 AND starttime < %2 AND "
                        "endtime > %3 AND program.chanid = channel.chanid;")
                        .arg(channel).arg(ltime).arg(ltime);
@@ -491,6 +504,7 @@
         proginfo->chansign = query.value(8).toString();
         proginfo->channame = query.value(9).toString();
         proginfo->repeat = query.value(10).toInt();
+        proginfo->xmltvid = query.value(11).toString();
         proginfo->spread = -1;
 
         if (proginfo->title == QString::null)
@@ -536,7 +550,8 @@
    
     thequery = QString("SELECT recorded.chanid,starttime,endtime,title, "
                                "subtitle,description,channel.channum, "
-                               "channel.callsign,channel.name "
+                               "channel.callsign,channel.name,"
+                               "channel.xmltvid "
                            "FROM recorded "
                            "LEFT JOIN channel "
                                "ON recorded.chanid = channel.chanid "
@@ -565,6 +580,7 @@
         proginfo->chanstr = query.value(6).toString();
         proginfo->chansign = query.value(7).toString();
         proginfo->channame = query.value(8).toString();
+        proginfo->xmltvid = query.value(9).toString();
         proginfo->spread = -1;
 
         if (proginfo->title == QString::null)
@@ -797,8 +813,7 @@
         subtitle == other.subtitle &&
         description == other.description)
         return true;
-    else
-        return false;
+    return false;
 }
  
 bool ProgramInfo::IsSameTimeslot(const ProgramInfo& other) const
@@ -810,8 +825,7 @@
         cardid == other.cardid &&
         inputid == other.inputid)
         return true;
-    else
-        return false;
+    return false;
 }
 
 bool ProgramInfo::IsSameProgramTimeslot(const ProgramInfo &other) const
@@ -824,6 +838,21 @@
     return false;
 }
 
+bool ProgramInfo::IsSameProgramTimeslot(const ProgramInfo &other,
+                                        const bool use_xmltvid) const
+{
+    if (IsSameProgramTimeslot(other))
+        return true;
+    if (use_xmltvid &&
+        startts == other.startts &&
+        endts == other.endts &&
+        xmltvid != "" &&
+        other.xmltvid != "" &&
+        xmltvid == other.xmltvid)
+        return true;
+    return false;
+}
+
 QString ProgramInfo::GetRecordBasename(void)
 {
     QString starts = recstartts.toString("yyyyMMddhhmm");
Index: libs/libmythtv/programinfo.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/programinfo.h,v
retrieving revision 1.64
diff -u -r1.64 programinfo.h
--- libs/libmythtv/programinfo.h	11 Jan 2004 17:07:37 -0000	1.64
+++ libs/libmythtv/programinfo.h	19 Jan 2004 22:25:50 -0000
@@ -7,7 +7,7 @@
 #include <qmap.h>
 #include "scheduledrecording.h"
 
-#define NUMPROGRAMLINES 29
+#define NUMPROGRAMLINES 30
 
 enum MarkTypes {
     MARK_UPDATED_CUT = -3,
@@ -79,6 +79,8 @@
     bool IsSameTimeslot(const ProgramInfo& other) const;
     // checks chanid, start/end times, sourceid
     bool IsSameProgramTimeslot(const ProgramInfo& other) const;
+    // checks chanid, start/end times, sourceid/xmltvid
+    bool IsSameProgramTimeslot(const ProgramInfo& other, const bool) const;
 
     void Save(QSqlDatabase *db);
 
@@ -221,6 +223,7 @@
     RecordingDupsType recdups;
 
     int sourceid;
+    QString xmltvid;
     int inputid;
     int cardid;
     bool conflictfixed;
Index: libs/libmythtv/remoteutil.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/remoteutil.cpp,v
retrieving revision 1.23
diff -u -r1.23 remoteutil.cpp
--- libs/libmythtv/remoteutil.cpp	11 Dec 2003 22:48:34 -0000	1.23
+++ libs/libmythtv/remoteutil.cpp	19 Jan 2004 22:25:51 -0000
@@ -27,6 +27,9 @@
         if (numrecordings * NUMPROGRAMLINES + 1 > (int)strlist.size())
         {
             cerr << "length mismatch between programinfo\n";
+            cerr << QString("got %1 expected %2\n")
+                             .arg(numrecordings * NUMPROGRAMLINES + 1)
+                             .arg((int)strlist.size());
             return info;
         }
 
@@ -122,6 +125,9 @@
         if (numrecordings * NUMPROGRAMLINES + 2 > (int)strlist.size())
         {
             cerr << "length mismatch between programinfo\n";
+            cerr << QString("got %1 expected %2\n")
+                             .arg(numrecordings * NUMPROGRAMLINES + 2)
+                             .arg((int)strlist.size());
             return conflicting;
         }
 
@@ -151,6 +157,9 @@
         if (numrecordings * NUMPROGRAMLINES + 1 > (int)strlist.size())
         {
             cerr << "length mismatch between programinfo\n";
+            cerr << QString("got %1 expected %2\n")
+                             .arg(numrecordings * NUMPROGRAMLINES + 1)
+                             .arg((int)strlist.size());
             return;
         }
 
@@ -183,6 +192,9 @@
         if (numrecordings * NUMPROGRAMLINES + 1 > (int)strlist.size())
         {
             cerr << "length mismatch between programinfo\n";
+            cerr << QString("got %1 expected %2\n")
+                             .arg(numrecordings * NUMPROGRAMLINES + 1)
+                             .arg((int)strlist.size());
             return retlist;
         }
 
Index: libs/libmythtv/scheduledrecording.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/scheduledrecording.cpp,v
retrieving revision 1.59
diff -u -r1.59 scheduledrecording.cpp
--- libs/libmythtv/scheduledrecording.cpp	16 Dec 2003 22:58:55 -0000	1.59
+++ libs/libmythtv/scheduledrecording.cpp	19 Jan 2004 22:25:51 -0000
@@ -262,9 +262,29 @@
 }
 
 void ScheduledRecording::findAllProgramsToRecord(QSqlDatabase* db,
-                                                 list<ProgramInfo*>& proglist) {
-     QString query = QString(
-"SELECT DISTINCT channel.chanid, channel.sourceid, "
+                                                 list<ProgramInfo*>& proglist,
+                                                 bool useXmltvid /* = false */) {
+
+    QString channeljoin;
+    QString channelwhere;
+    if (useXmltvid)
+    {
+        channeljoin = " INNER JOIN channel AS channel ON "
+                                   "(channel.chanid = program.chanid) "
+                      " LEFT JOIN channel AS chantmp ON "
+                                   "(record.chanid = chantmp.chanid) ";
+        channelwhere = " ((chantmp.xmltvid = channel.xmltvid AND "
+                       "   chantmp.xmltvid IS NOT NULL) ";
+    }
+    else
+    {
+        channeljoin = " INNER JOIN channel ON "
+                                   "(channel.chanid = program.chanid) ";
+        channelwhere = " ((record.chanid = program.chanid) ";
+    }
+
+    QString query = QString(
+"SELECT DISTINCT channel.chanid, channel.sourceid, channel.xmltvid, "
 "program.starttime, program.endtime, "
 "program.title, program.subtitle, program.description, "
 "channel.channum, channel.callsign, channel.name, "
@@ -276,8 +296,8 @@
 "program.endtime + INTERVAL record.postroll minute, "
 "program.previouslyshown "
 "FROM record "
-" INNER JOIN channel ON (channel.chanid = program.chanid) "
 " INNER JOIN program ON (program.title = record.title) "
++ channeljoin +
 " LEFT JOIN oldrecorded ON "
 "  ( "
 "    oldrecorded.title IS NOT NULL AND oldrecorded.title <> '' AND program.title = oldrecorded.title "
@@ -307,23 +327,23 @@
 "WHERE "
 "((record.type = %1) " // allrecord
 " OR "
-" ((record.chanid = program.chanid) " // channel matches
-"  AND "
-"  ((record.type = %2) " // channelrecord
++ channelwhere + // channel matches
+" AND "
+" ((record.type = %2) " // channelrecord
 "   OR"
 "   ((TIME_TO_SEC(record.starttime) = TIME_TO_SEC(program.starttime)) " // timeslot matches
-"    AND "
-"    ((record.type = %3) " // timeslotrecord
+"   AND "
+"   ((record.type = %3) " // timeslotrecord
 "     OR"
 "     ((DAYOFWEEK(record.startdate) = DAYOFWEEK(program.starttime) "
-"      AND "
-"      ((record.type = %4) " // weekslotrecord
+"     AND "
+"     ((record.type = %4) " // weekslotrecord
 "       OR"
 "       ((TO_DAYS(record.startdate) = TO_DAYS(program.starttime)) " // date matches
-"        AND "
-"        (TIME_TO_SEC(record.endtime) = TIME_TO_SEC(program.endtime)) "
-"        AND "
-"        (TO_DAYS(record.enddate) = TO_DAYS(program.endtime)) "
+"       AND "
+"       (TIME_TO_SEC(record.endtime) = TIME_TO_SEC(program.endtime)) "
+"       AND "
+"       (TO_DAYS(record.enddate) = TO_DAYS(program.endtime)) "
 "        )"
 "       )"
 "      )"
@@ -348,23 +368,24 @@
              proginfo->recording = true;
              proginfo->chanid = result.value(0).toString();
              proginfo->sourceid = result.value(1).toInt();
-             proginfo->startts = result.value(2).toDateTime();
-             proginfo->endts = result.value(3).toDateTime();
-             proginfo->title = QString::fromUtf8(result.value(4).toString());
-             proginfo->subtitle = QString::fromUtf8(result.value(5).toString());
-             proginfo->description = QString::fromUtf8(result.value(6).toString());
-             proginfo->chanstr = result.value(7).toString();
-             proginfo->chansign = result.value(8).toString();
-             proginfo->channame = result.value(9).toString();
-             proginfo->category = QString::fromUtf8(result.value(11).toString());
-             proginfo->recpriority = result.value(12).toString();
-             proginfo->recdups = RecordingDupsType(result.value(13).toInt());
-             proginfo->rectype = RecordingType(result.value(15).toInt());
-             proginfo->recordid = result.value(16).toInt();
-             proginfo->override = result.value(17).toInt();
+             proginfo->xmltvid = result.value(2).toString();
+             proginfo->startts = result.value(3).toDateTime();
+             proginfo->endts = result.value(4).toDateTime();
+             proginfo->title = QString::fromUtf8(result.value(5).toString());
+             proginfo->subtitle = QString::fromUtf8(result.value(6).toString());
+             proginfo->description = QString::fromUtf8(result.value(7).toString());
+             proginfo->chanstr = result.value(8).toString();
+             proginfo->chansign = result.value(9).toString();
+             proginfo->channame = result.value(10).toString();
+             proginfo->category = QString::fromUtf8(result.value(12).toString());
+             proginfo->recpriority = result.value(13).toString();
+             proginfo->recdups = RecordingDupsType(result.value(14).toInt());
+             proginfo->rectype = RecordingType(result.value(16).toInt());
+             proginfo->recordid = result.value(17).toInt();
+             proginfo->override = result.value(18).toInt();
 
-             proginfo->recstartts = result.value(18).toDateTime();
-             proginfo->recendts = result.value(19).toDateTime();
+             proginfo->recstartts = result.value(19).toDateTime();
+             proginfo->recendts = result.value(20).toDateTime();
 
              if (proginfo->recstartts >= proginfo->recendts)
              {
@@ -373,7 +394,7 @@
                  proginfo->recendts = proginfo->endts;
              }
 
-             proginfo->repeat = result.value(20).toInt();
+             proginfo->repeat = result.value(21).toInt();
 
              if (proginfo->override == 2)
              {
@@ -386,7 +407,7 @@
              {
                  if (proginfo->recdups == kRecordDupsIfDeleted)
                  {
-                     if (result.value(14).toInt())
+                     if (result.value(15).toInt())
                      {
                          proginfo->recording = false;
                          proginfo->norecord = nrCurrentRecording;
@@ -394,7 +415,7 @@
                  }
                  else
                  {
-                     if (result.value(10).toInt())
+                     if (result.value(11).toInt())
                      {
                          proginfo->recording = false;
                          proginfo->norecord = nrPreviousRecording;
@@ -415,6 +436,8 @@
                  proginfo->description = "";
              if (proginfo->category == QString::null)
                  proginfo->category = "";
+             if (proginfo->xmltvid == QString::null)
+                 proginfo->xmltvid = "";
 
              if (proginfo->endts < now)
                  delete proginfo;
Index: libs/libmythtv/scheduledrecording.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/scheduledrecording.h,v
retrieving revision 1.20
diff -u -r1.20 scheduledrecording.h
--- libs/libmythtv/scheduledrecording.h	21 Nov 2003 17:41:25 -0000	1.20
+++ libs/libmythtv/scheduledrecording.h	19 Jan 2004 22:25:52 -0000
@@ -61,7 +61,8 @@
     QString getProfileName(void) const;
 
     static void findAllProgramsToRecord(QSqlDatabase* db, 
-                                        list<ProgramInfo*>& proglist);
+                                        list<ProgramInfo*>& proglist,
+                                        bool useXmltvid = false);
     static void findAllScheduledPrograms(QSqlDatabase *db, 
                                          list<ProgramInfo*>& proglist);
     void findMatchingPrograms(QSqlDatabase* db, list<ProgramInfo*>& proglist);
Index: programs/mythbackend/scheduler.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/scheduler.cpp,v
retrieving revision 1.61
diff -u -r1.61 scheduler.cpp
--- programs/mythbackend/scheduler.cpp	22 Dec 2003 21:34:14 -0000	1.61
+++ programs/mythbackend/scheduler.cpp	19 Jan 2004 22:25:53 -0000
@@ -174,6 +174,8 @@
 {
     doRecPriority = (bool)gContext->GetNumSetting("RecPriorityActive");
     doRecPriorityFirst = (bool)gContext->GetNumSetting("RecPriorityOrder");
+    useXmltvid = (bool)gContext->GetNumSetting("XmltvidIsGlobal", 0);
+    schedAcrossCards = (bool)gContext->GetNumSetting("ScheduleAcrossCards", 0);
 
     if (recpriorityMap.size() > 0)
         recpriorityMap.clear();
@@ -193,17 +195,13 @@
 
     PruneDontRecords();
 
-    ScheduledRecording::findAllProgramsToRecord(db, recordingList);
-
-    QMap<QString, bool> foundlist;
+    ScheduledRecording::findAllProgramsToRecord(db, recordingList, useXmltvid);
 
     list<ProgramInfo *>::iterator iter = recordingList.begin();
     for (; iter != recordingList.end(); iter++)
     {
         ProgramInfo *pginfo = (*iter);
         pginfo->schedulerid = pginfo->startts.toString() + "_" + pginfo->chanid;
-
-        foundlist[pginfo->schedulerid] = true;
     }
 
     if (recordingList.size() > 0)
@@ -212,10 +210,15 @@
         MarkKnownInputs();
         PruneOverlaps();
         MarkConflicts();
-        PruneList();
+        if (schedAcrossCards && (numcards > 1 || numinputs > 1))
+        {
+            DoMultiCard();
+            MarkConflicts();
+        }
+        PruneList();        // Mark not recording stuff as not recording
         MarkConflicts();
 
-        if (numcards > 1 || numinputs > 1)
+        if (!schedAcrossCards && (numcards > 1 || numinputs > 1))
         {
             DoMultiCard();
             MarkConflicts();
@@ -223,11 +226,9 @@
 
         MarkConflictsToRemove();
         if (doautoconflicts)
-        {
-            //RemoveConflicts();
             GuessConflicts();
-            //RemoveConflicts();
-        }
+
+        DoFixups();        // Tidy up some easy mistakes and omissions...
         MarkConflicts();
     }
 
@@ -439,6 +440,7 @@
 {
     list<ProgramInfo *>::reverse_iterator i;
     list<ProgramInfo *>::iterator q;
+    list<ProgramInfo *>::iterator j;
 
     QDateTime now = QDateTime::currentDateTime();
 
@@ -487,6 +489,23 @@
             EncoderLink *elink = enciter.data();
             if (elink->isRecording(rec))
             {
+                // Before deleting, find all IDENTICAL entries,
+                // and mark them nrCurrentRecording
+                j = recordingList.begin();
+                for (; j != recordingList.end(); j++)
+                {
+                    ProgramInfo *second = (*j);
+
+                    if (second->recording &&
+                        second->override != 1 &&
+                        second->recdups != kRecordDupsAlways &&
+                        (second->IsSameProgram(*rec) ||
+                        second->IsSameProgramTimeslot(*rec, useXmltvid)))
+                    {
+                        second->recording = false;
+                        second->norecord = nrCurrentRecording;
+                    }
+                }
                 delete rec;
                 rec = NULL;
                 recordingList.erase(q++);
@@ -503,8 +522,9 @@
     {
         ProgramInfo *first = (*i);
 
-        if (!first->recording || first->rectype == kSingleRecord ||
-            first->subtitle.length() <= 2 && first->description.length() <= 2)
+        if (!first->recording ||
+            (!useXmltvid && first->subtitle.length() <= 2 &&
+            first->description.length() <= 2))
             continue;
 
         list<ProgramInfo *>::reverse_iterator j = i;
@@ -516,7 +536,8 @@
             if (!second->recording)
                 continue;
 
-            if (first->IsSameProgram(*second))
+            if (first->IsSameProgram(*second) ||
+                first->IsSameProgramTimeslot(*second, useXmltvid))
             {
                 if (((second->conflicting && !first->conflicting) ||
                      second->recstartts < now.addSecs(-15) || first->override == 1) 
@@ -534,7 +555,7 @@
                 }
             }
         }
-    }    
+    }
 }
 
 void Scheduler::getAllPending(list<ProgramInfo *> *retList)
@@ -899,25 +920,6 @@
     }
 }
 
-void Scheduler::RemoveConflicts(void)
-{
-    list<ProgramInfo *>::iterator del;
-    list<ProgramInfo *>::iterator i = recordingList.begin();
-    while (i != recordingList.end())
-    {
-        ProgramInfo *first = (*i);
-
-        del = i;
-        i++;
-
-        if (!first->recording)
-        {
-            delete first;
-            recordingList.erase(del);
-        }
-    }
-}
-
 ProgramInfo *Scheduler::GetBest(ProgramInfo *info, 
                                 list<ProgramInfo *> *conflictList)
 {
@@ -1005,6 +1007,74 @@
     }
 }
 
+void Scheduler::findOtherShowing(ProgramInfo* first)
+{
+    list<ProgramInfo *>::iterator i = recordingList.begin();
+    for (; i != recordingList.end(); i++)
+    {
+        ProgramInfo *second = (*i);
+        if( second->recording || second->norecord != nrOtherShowing )
+            continue;
+
+        if (first->IsSameProgram(*second) ||
+            first->IsSameProgramTimeslot(*second, useXmltvid))
+        {
+            second->recording = true;
+            second->conflicting = true;
+            list<ProgramInfo *> *conflictList = getConflicting(second);
+            second->recording = false;
+            second->conflicting = false;
+            int numConflicts = conflictList->size();
+            delete conflictList;
+            if (numConflicts == 0)
+            {
+                first->recording = false;
+                first->norecord = nrOtherShowing;
+                first->conflicting = false;
+                second->recording = true;
+                second->norecord = nrUnknown;
+                second->conflicting = false;
+                return;
+            }
+        }
+    }
+}
+
+void Scheduler::DoFixups(void)
+{
+    list<ProgramInfo *>::iterator i = recordingList.begin();
+    for (; i != recordingList.end(); i++)
+    {
+        ProgramInfo *first = (*i);
+        if (first->recording)
+            continue;
+
+        switch(first->norecord) {
+            case nrLowerRecPriority:
+            case nrAutoConflict:
+            case nrManualConflict:
+            {
+                first->recording = true;
+                first->conflicting = true;
+                list<ProgramInfo *> *conflictList = getConflicting(first);
+                first->recording = false;
+                first->conflicting = false;
+                int numConflicts = conflictList->size();
+                delete conflictList;
+                if (numConflicts == 0)
+                {
+                    first->recording = true;
+                    first->norecord = nrUnknown;
+                }
+                else
+                    findOtherShowing(first);
+            }
+            default:
+                ;;  // To silence some compiler warnings.
+        }
+    }
+}
+
 list<ProgramInfo *> *Scheduler::CopyList(list<ProgramInfo *> *sourcelist)
 {
     list<ProgramInfo *> *retlist = new list<ProgramInfo *>;
Index: programs/mythbackend/scheduler.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/scheduler.h,v
retrieving revision 1.23
diff -u -r1.23 scheduler.h
--- programs/mythbackend/scheduler.h	4 Dec 2003 21:49:36 -0000	1.23
+++ programs/mythbackend/scheduler.h	19 Jan 2004 22:25:53 -0000
@@ -70,7 +70,6 @@
     int totalRecPriority(ProgramInfo *info);
     void CheckRecPriority(ProgramInfo *info, list<ProgramInfo *> *conflictList);
     void CheckOverride(ProgramInfo *info, list<ProgramInfo *> *conflictList);
-    void RemoveConflicts(void);
     void GuessSingle(ProgramInfo *info, list<ProgramInfo *> *conflictList);
     void GuessConflicts(void);
 
@@ -96,6 +95,8 @@
 
     bool doRecPriority;
     bool doRecPriorityFirst;
+    bool useXmltvid;
+    bool schedAcrossCards;
 
     QMap<QString, int> recpriorityMap;
     QMap<QString, int> channelRecPriorityMap;
@@ -119,6 +120,8 @@
 
     void AddToDontRecord(ProgramInfo *pginfo);
     void PruneDontRecords(void);
+    void findOtherShowing(ProgramInfo*);
+    void DoFixups();
 
     QValueList<ProgramInfo> dontRecordList;
 
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.126
diff -u -r1.126 globalsettings.cpp
--- programs/mythfrontend/globalsettings.cpp	18 Jan 2004 18:39:28 -0000	1.126
+++ programs/mythfrontend/globalsettings.cpp	19 Jan 2004 22:25:55 -0000
@@ -1222,6 +1222,31 @@
     };
 };
 
+class GRRecPrioritiesXmltvid: public CheckBoxSetting, public BackendSetting {
+public:
+    GRRecPrioritiesXmltvid():
+        BackendSetting("XmltvidIsGlobal") {
+        setLabel(QObject::tr("Xmltv ID identifies a channel."));
+        setHelpText(QObject::tr("The scheduler can try to use a different "
+                    "\"source\" to solve a conflict if a channel with the same "
+                    "xmltv ID is found."));
+        setValue(false);
+    };
+};
+
+class GRRecPrioritiesMoreCards: public CheckBoxSetting, public BackendSetting {
+public:
+    GRRecPrioritiesMoreCards():
+        BackendSetting("ScheduleAcrossCards") {
+        setLabel(QObject::tr("Use more cards and record sooner."));
+        setHelpText(QObject::tr("The scheduler can use more recorders in order "
+                    "to try and record earlier showings of conflicting "
+                    "programs. By default (off) a repeat will be scheduled "
+                    "if one is available."));
+        setValue(false);
+    };
+};
+
 class GRSingleRecordRecPriority: public SpinBoxSetting, public BackendSetting {
 public:
     GRSingleRecordRecPriority():
@@ -1639,6 +1664,8 @@
 
     gr->addChild(new GRUseRecPriorities());
     gr->addChild(new GRRecPrioritiesFirst());
+    gr->addChild(new GRRecPrioritiesXmltvid());
+    gr->addChild(new GRRecPrioritiesMoreCards());
     gr->addChild(new GRSingleRecordRecPriority());
     gr->addChild(new GRWeekslotRecordRecPriority());
     gr->addChild(new GRTimeslotRecordRecPriority());


More information about the mythtv-dev mailing list