[mythtv] Proposed scheduler patch [PATCH]

Steve Davies steve at one47.co.uk
Tue Feb 10 19:46:22 EST 2004


David Engel wrote:
> On Mon, Feb 09, 2004 at 09:07:10PM +0000, Steve Davies wrote:
> >1) The "xmltvid is global" patch which I've posted previously - I 
> >accidentally turned this off the other day, and BOY does it make a 
> >difference. I can provide a trimmed down version which does nothing but add 
> >this feature.
> 
> I was hoping you would take this up when I was done since I don't have
> multiple sources and wouldn't have any easy way of testing it.  I do
> have a couple of questions for you in the mean time.  First, is there
> any reason a user wouldn't want this always enabled?  I'm all for
> configurability, but not when make things more complicated than it
> needs to be.  Second, have you thought about making sure
> PI::FillInRecordInfo does the right thing?  It currently looks for an
> exact match on chanid.

I checked PI::FillInRecordInfo, and can confirm that it is to be left alone 
for now as far as xmltvid goes - There are a few places where we need to cater 
for the guidegrid (and similar) behavior. In these places, the distinction 
between sources is still made, and it is fine that it is still made. It just 
means that there will be some extra "rsOtherShowing" entries floating around - 
We can tidy these away of necessary at a later time, I don't find that they 
are a problem. Perhaps in future the guidegrid will also collapse duplicate 
cross-source channels at which point the behaviour changes.

>>2) The "DoFixup" patch which was part of my previous submission - I assume 
>>that this will eventually become redundant as some of your planned changes 
>>are rolled in, so unless you think there is value in a single pass fixup to 
>>catch the worst cases of mis-scheduling, I'll leave this one out.

I tried the code with this turned off, and it made me grimace - Instead I have 
left it in, but located the methods at the end of the scheduler source file, 
and put them in "#if 1" blocks for the purposes of testing so they can easily 
be disabled if so desired.

IMHO It offers a temporary scheduler improvement in the short term.

>>3) A new "concept" patch - I have modified the scheduled programs SELECT 
>>statement to select all instances of all programs on all sources, and to 
>>pre-fill the cardid and inputid values - Then by modifying the duplicates 
>>matching slightly, the duplicates are marked as "rsOtherRecording" entries 
>>- this means that the DoMultiCard() and associated calls can be removed. 
> 
> This is interesting and could easily solve a problem I was going to
> encounter.  To make the most people happy, I was expecting to have to
> implement two slightly different alogorithms, one which schedules one
> card at a time and another which schedules across cards.  With this
> approach, I could probably get by with one algorithm and control the
> behavior by how I sort the possibilities.  Please update you patch and
> post it to the list after do my next commit later this evening.
> 
>>It 
>>would be best to prune some of these duplicates fully at a later stage (for 
>>aesthetic reasons), but I would be interested in feedback on the concept - 
>>It is working very well here so far. This patch overlaps slightly with the 
>>xmltv patch in 1) due to the duplicate matching code.
> 
> 
> Pruning would most definitely be needed to keep from confusing the
> user (and me).  They wouldn't want to see three, four or more entries
> show up when they only scheduled one program!  Does your patch try to
> filter out multiple inputs on the same card?  Since you can't use more
> than one input at a time on a card, it would be nice to remove the
> redundant entries as early as possible, ideally in the SELECT.
> 
> David

For the bulk of the patch, I ended up merging the xmltvid part of the patch 
with the new SELECT statement code. They turned out to be fundamentally the 
same thing!

I did add code to remove excess dupes, please check that this code is "safe". 
As usual, testing and comments invited, particularly by people with 2 or 3 
cards. I have 2 cards, and tested this by adding a fake 3rd.

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.108
diff -u -r1.108 programinfo.cpp
--- libs/libmythtv/programinfo.cpp	10 Feb 2004 03:34:24 -0000	1.108
+++ libs/libmythtv/programinfo.cpp	11 Feb 2004 00:39:05 -0000
@@ -47,6 +47,8 @@
     sourceid = 0;
     inputid = 0;
     cardid = 0;
+    xmltvid = "";
+    shareable = false;
     schedulerid = "";
     recpriority = 0;
     recgroup = QObject::tr("Default");
@@ -88,8 +90,10 @@
     dupmethod = other.dupmethod;
 
     sourceid = other.sourceid;
+    xmltvid = other.xmltvid;
     inputid = other.inputid;
     cardid = other.cardid;
+    shareable = other.shareable;
     schedulerid = other.schedulerid;
     recpriority = other.recpriority;
     recgroup = other.recgroup;
@@ -135,8 +139,10 @@
     dupmethod = other.dupmethod;
 
     sourceid = other.sourceid;
+    xmltvid = other.xmltvid;
     inputid = other.inputid;
     cardid = other.cardid;
+    shareable = other.shareable;
     schedulerid = other.schedulerid;
     recpriority = other.recpriority;
     recgroup = other.recgroup;
@@ -306,6 +312,7 @@
     progMap["channum"] = chanstr;
     progMap["chanid"] = chanid;
     progMap["iconpath"] = "";
+    progMap["xmltvid"] = xmltvid;
 
     seconds = recstartts.secsTo(recendts);
     minutes = seconds / 60;
@@ -374,7 +381,7 @@
     thequery = QString("SELECT channel.chanid,starttime,endtime,title,"
                        "subtitle,description,category,channel.channum,"
                        "channel.callsign,channel.name,previouslyshown,"
-                       "channel.commfree "
+                       "channel.commfree, channel.xmltvid "
                        "FROM program,channel ")
                        + where;
 
@@ -402,6 +409,7 @@
             proginfo->channame = query.value(9).toString();
             proginfo->repeat = query.value(10).toInt();
             proginfo->chancommfree = query.value(11).toInt();
+            proginfo->xmltvid = query.value(12).toString();
 
             proginfo->spread = -1;
 
@@ -413,6 +421,8 @@
                 proginfo->description = "";
             if (proginfo->category == QString::null)
                 proginfo->category = "";
+            if (proginfo->xmltvid == QString::null)
+                proginfo->xmltvid = "";
 
             proglist->append(proginfo);
         }
@@ -443,7 +453,8 @@
    
     thequery = QString("SELECT channel.chanid,starttime,endtime,title,subtitle,"
                        "description,category,channel.channum,channel.callsign, "
-                       "channel.name,previouslyshown,channel.commfree "
+                       "channel.name,previouslyshown,channel.commfree, "
+                       "channel.xmltvid "
                        "FROM program,channel "
                        "WHERE program.chanid = %1 AND starttime < %2 AND "
                        "endtime > %3 AND program.chanid = channel.chanid;")
@@ -472,6 +483,7 @@
         proginfo->channame = query.value(9).toString();
         proginfo->repeat = query.value(10).toInt();
         proginfo->chancommfree = query.value(11).toInt();
+        proginfo->xmltvid = query.value(12).toString();
         proginfo->spread = -1;
 
         if (proginfo->title == QString::null)
@@ -517,7 +529,8 @@
    
     thequery = QString("SELECT recorded.chanid,starttime,endtime,title, "
                        "subtitle,description,channel.channum, "
-                       "channel.callsign,channel.name,channel.commfree "
+                       "channel.callsign,channel.name,channel.commfree, "
+                       "channel.xmltvid "
                        "FROM recorded "
                        "LEFT JOIN channel "
                        "ON recorded.chanid = channel.chanid "
@@ -547,6 +560,7 @@
         proginfo->chansign = query.value(7).toString();
         proginfo->channame = query.value(8).toString();
         proginfo->chancommfree = query.value(9).toInt();
+        proginfo->xmltvid = query.value(10).toString();
         proginfo->spread = -1;
 
         if (proginfo->title == QString::null)
@@ -805,6 +819,19 @@
     if (rectype == kFindOneRecord)
         return true;
 
+    if (startts == other.startts &&
+        endts == other.endts &&
+        chanid == other.chanid &&
+        sourceid == other.sourceid)
+        return true;
+
+    if (startts == other.startts &&
+        endts == other.endts &&
+        xmltvid != "" &&
+        other.xmltvid != "" &&
+        xmltvid == other.xmltvid)
+        return true;
+
     QString tmpsubtitle = subtitle;
     QString tmpdescription = description;
 
@@ -823,8 +850,7 @@
           (description == other.description)) ||
          (~dupmethod & kDupCheckDesc)))
         return true;
-    else
-        return false;
+    return false;
 }
  
 bool ProgramInfo::IsSameTimeslot(const ProgramInfo& other) const
@@ -836,8 +862,19 @@
         cardid == other.cardid &&
         inputid == other.inputid)
         return true;
-    else
-        return false;
+    return false;
+}
+ 
+bool ProgramInfo::IsCrossCardDupe(const ProgramInfo& other) const
+{
+    if (chanid == other.chanid &&
+        startts == other.startts &&
+        endts == other.endts &&
+        sourceid == other.sourceid &&
+        (cardid != other.cardid ||
+        inputid != other.inputid))
+        return true;
+    return false;
 }
 
 bool ProgramInfo::IsSameProgramTimeslot(const ProgramInfo &other) const
Index: libs/libmythtv/programinfo.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/programinfo.h,v
retrieving revision 1.68
diff -u -r1.68 programinfo.h
--- libs/libmythtv/programinfo.h	6 Feb 2004 03:17:45 -0000	1.68
+++ libs/libmythtv/programinfo.h	11 Feb 2004 00:39:05 -0000
@@ -84,6 +84,8 @@
     bool IsSameProgram(const ProgramInfo& other) const;
     // checks chanid, start/end times, sourceid, cardid, inputid.
     bool IsSameTimeslot(const ProgramInfo& other) const;
+    // checks chanid, start/end times, sourceid, !cardid, !inputid.
+    bool IsCrossCardDupe(const ProgramInfo& other) const;
     // checks chanid, start/end times, sourceid
     bool IsSameProgramTimeslot(const ProgramInfo& other) const;
 
@@ -240,8 +242,10 @@
     RecordingDupMethodType dupmethod;
 
     int sourceid;
+    QString xmltvid;
     int inputid;
     int cardid;
+    bool shareable;
     bool conflictfixed;
 
     QString schedulerid;
Index: programs/mythbackend/scheduler.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/scheduler.cpp,v
retrieving revision 1.74
diff -u -r1.74 scheduler.cpp
--- programs/mythbackend/scheduler.cpp	10 Feb 2004 03:34:25 -0000	1.74
+++ programs/mythbackend/scheduler.cpp	11 Feb 2004 00:39:06 -0000
@@ -30,7 +30,7 @@
 
     m_mainServer = NULL;
 
-    setupCards();
+    verifyCards();
 
     threadrunning = runthread;
 
@@ -59,7 +59,7 @@
     m_mainServer = ms;
 }
 
-void Scheduler::setupCards(void)
+void Scheduler::verifyCards(void)
 {
     QString thequery;
 
@@ -67,13 +67,7 @@
 
     QSqlQuery query = db->exec(thequery);
 
-    numcards = -1;
-    numinputs = -1;
-    numsources = -1;
-    numInputsPerSource.clear();
-    sourceToInput.clear();
-    inputToCard.clear();
-
+    int numcards = -1;
     if (query.isActive())
         numcards = query.numRowsAffected();
 
@@ -88,8 +82,7 @@
 
     query = db->exec(thequery);
 
-    numsources = -1;
-
+    int numsources = -1;
     if (query.isActive())
     {
         numsources = query.numRowsAffected();
@@ -105,19 +98,9 @@
                               .arg(source);
             QSqlQuery subquery = db->exec(thequery);
             
-            if (subquery.isActive() && subquery.numRowsAffected() > 0)
-            {
-                numInputsPerSource[source] = subquery.numRowsAffected();
- 
-                while (subquery.next())
-                    sourceToInput[source].push_back(subquery.value(0).toInt());
-            }
-            else
-            {
-                numInputsPerSource[source] = -1;
+            if (!subquery.isActive() || subquery.numRowsAffected() <= 0)
                 cerr << query.value(1).toString() << " is defined, but isn't "
                      << "attached to a cardinput.\n";
-            }
         }
     }
 
@@ -126,20 +109,6 @@
         cerr << "ERROR: No channel sources defined in the database\n";
         exit(0);
     }
-
-    thequery = "SELECT cardid,cardinputid FROM cardinput ORDER BY cardinputid;";
-
-    query = db->exec(thequery);
-
-    if (query.isActive() && query.numRowsAffected() > 0)
-    {
-        numinputs = query.numRowsAffected();
-
-        while (query.next())
-        {
-            inputToCard[query.value(1).toInt()] = query.value(0).toInt();
-        }  
-    }
 }
 
 bool Scheduler::CheckForChanges(void)
@@ -188,20 +157,18 @@
     {
         recordingList.sort(comp_proginfo());
         PruneOverlaps();
-        MarkKnownInputs();
         MarkConflicts();
         PruneList(now);
         MarkConflicts();
 
-        if (numcards > 1 || numinputs > 1)
-        {
-            DoMultiCard();
-            MarkConflicts();
-        }
-
         MarkConflictsToRemove();
         if (doautoconflicts)
             GuessConflicts();
+
+#if 1
+        DoFixups();
+#endif
+        TidyUpCrossCardDupes();
         MarkConflicts();
     }
 
@@ -321,23 +288,6 @@
     return (a->recstartts < b->recendts && a->recendts > b->recstartts);
 }
 
-void Scheduler::MarkKnownInputs(void)
-{
-    list<ProgramInfo *>::iterator i = recordingList.begin();
-    for (; i != recordingList.end(); i++)
-    {
-        ProgramInfo *first = (*i);
-        if (first->inputid <= 0 && first->recstatus == rsWillRecord)
-        {
-            if (numInputsPerSource[first->sourceid] == 1)
-            {
-                first->inputid = sourceToInput[first->sourceid][0];
-                first->cardid = inputToCard[first->inputid];
-            }
-        }
-    }
-}
- 
 void Scheduler::MarkConflicts(list<ProgramInfo *> *uselist)
 {
     list<ProgramInfo *> *curList = &recordingList;
@@ -398,17 +348,19 @@
                     (pfirst == psecond && first->recordid < second->recordid))
                 {
                     second->recording = false;
+                    second->conflicting = false;
                     second->recstatus = rsOverlap;
                 }
                 else
                 {
                     first->recording = false;
+                    first->conflicting = false;
                     first->recstatus = rsOverlap;
                     break;
                 }
             }
         }
-    }    
+    }
 }
 
 void Scheduler::PruneList(const QDateTime &now)
@@ -425,6 +377,7 @@
             !rec->AllowRecordingNewEpisodes(db))
         {
             rec->recording = false;
+            rec->conflicting = false;
             rec->recstatus = rsTooManyRecordings;
         }
     }
@@ -454,9 +407,7 @@
     {
         ProgramInfo *first = (*i);
 
-        if (!Recording(first) || first->rectype == kSingleRecord ||
-            (!first->rectype == kFindOneRecord &&
-            first->subtitle.length() <= 2 && first->description.length() <= 2))
+        if (!Recording(first))
             continue;
 
         list<ProgramInfo *>::reverse_iterator j = i;
@@ -470,13 +421,25 @@
 
             if (first->IsSameProgram(*second))
             {
-                if (((second->conflicting && !first->conflicting) ||
-                     second->recstartts < now.addSecs(-15) || first->override == 1) 
+                if (!second->conflicting && !first->conflicting &&
+                    second->recstartts == first->recstartts &&
+                    first->cardid < second->cardid &&
+                    second->override != 1 &&
+                    ~second->dupmethod & kDupCheckNone)
+                {
+                    second->recording = false;
+                    second->conflicting = false;
+                    second->recstatus = rsOtherShowing;
+                }
+                else if (((second->conflicting && !first->conflicting) ||
+                     second->recstartts < now.addSecs(-15) ||
+                     first->override == 1) 
                     && second->override != 1 
                     && ~second->dupmethod & kDupCheckNone
                     && second->recstatus != rsRecording)
                 {
                     second->recording = false;
+                    second->conflicting = false;
                     second->recstatus = rsOtherShowing;
                 }
                 else if (first->override != 1
@@ -484,11 +447,12 @@
                          && first->recstatus != rsRecording)
                 {
                     first->recording = false;
+                    first->conflicting = false;
                     first->recstatus = rsOtherShowing;
                 }
             }
         }
-    }    
+    }
 }
 
 void Scheduler::getAllPending(list<ProgramInfo *> *retList)
@@ -628,6 +592,7 @@
             && second->recstatus != rsRecording)
         {
             second->recording = false;
+            second->conflicting = false;
             second->recstatus = rsLowerRecPriority;
             resolved++;
         }
@@ -669,6 +634,7 @@
                 continue;
 
             del->recording = false;
+            del->conflicting = false;
             del->recstatus = rsManualConflict;
             resolved++;
         }
@@ -716,6 +682,7 @@
                     test->endts == badend && test->recstatus != rsRecording)
                 {
                     test->recording = false;
+                    test->conflicting = false;
                     test->recstatus = rsManualConflict;
                 }
             }
@@ -755,6 +722,7 @@
                 if (test->title == badtitle && test->recstatus != rsRecording)
                 {
                     test->recording = false;
+                    test->conflicting = false;
                     test->recstatus = rsManualConflict;
                 }
             }
@@ -904,6 +872,7 @@
         {
             ProgramInfo *pginfo = (*i);
             pginfo->recording = false;
+            pginfo->conflicting = false;
             pginfo->recstatus = rsAutoConflict;
         }
         best->conflicting = false;
@@ -911,6 +880,7 @@
     else
     {
         info->recording = false;
+        info->conflicting = false;
         info->recstatus = rsAutoConflict;
     } 
 }
@@ -931,289 +901,6 @@
     }
 }
 
-list<ProgramInfo *> *Scheduler::CopyList(list<ProgramInfo *> *sourcelist)
-{
-    list<ProgramInfo *> *retlist = new list<ProgramInfo *>;
-
-    list<ProgramInfo *>::iterator i = sourcelist->begin();
-    for (; i != sourcelist->end(); i++)
-    {
-        ProgramInfo *first = (*i);
-        ProgramInfo *second = new ProgramInfo(*first);
-
-        second->conflictfixed = false;
-
-        if (second->cardid <= 0 && second->recstatus == rsWillRecord)
-        {
-            int numinputs = numInputsPerSource[first->sourceid];
-            bool placed = false;
-
-            for (int z = 0; z < numinputs; z++)
-            {
-                second->inputid = sourceToInput[first->sourceid][z];
-                second->cardid = inputToCard[second->inputid];
-
-                if (!m_tvList->contains(second->cardid))
-                {
-                    if (m_tvList->size())
-                    {
-                        cerr << "Missing: " << second->cardid << " in tvList\n";
-                    }
-                    continue;
-                }
-
-                EncoderLink *enc = (*m_tvList)[second->cardid];
-                if (enc->WouldConflict(second))
-                    continue;
-                if (enc->isLowOnFreeSpace())
-                    continue;
-                if (enc->isTunerLocked())
-                    continue;
-                placed = true;
-                break;
-            }
-
-            if (!placed)
-            {
-                if (numinputs > 0)
-                {
-                    second->inputid = sourceToInput[first->sourceid][0];
-                    second->cardid = inputToCard[second->inputid];
-                }
-                else
-                {
-                    cerr << "Source: " << first->sourceid << " is not attached"
-                         << " to an input on a capture card.\n";
-                    cerr << "Unable to schedule:\n";
-                    cerr << first->title.leftJustify(22, ' ', true)
-                         << first->chanstr.rightJustify(4, ' ') << "  " 
-                         << first->chanid 
-                         << first->recstartts.toString("  MMM dd hh:mmap  ")
-                         << endl;
-                    cerr << " for recording.  It will be removed.";
-                    delete second;
-                    second = NULL;
-                }
-            }
-        }
-
-        if (second)
-            retlist->push_back(second);
-    }
-
-    return retlist;
-}
-        
-void Scheduler::DoMultiCard(void)
-{
-    bool highermove, lowermove;
-    ProgramInfo *higher, *lower;
-
-    list<ProgramInfo *> *copylist = CopyList(&recordingList);
-
-    MarkConflicts(copylist);
-
-    int numconflicts = 0;
-
-    list<ProgramInfo *> allConflictList;
-    list<bool> canMoveList;
-
-    list<ProgramInfo *>::iterator i;
-    for (i = copylist->begin(); i != copylist->end(); i++)
-    {
-        ProgramInfo *first = (*i);
-        if (Recording(first) && first->conflicting)
-        {
-            numconflicts++;
-            allConflictList.push_back(first);
-            if (numInputsPerSource[first->sourceid] == 1
-                || first->recstatus == rsRecording) 
-                canMoveList.push_back(false);
-            else
-                canMoveList.push_back(true);
-        }
-    }
-
-    list<ProgramInfo *> fixedList;
-    
-    list<bool>::iterator biter;
-    for (biter = canMoveList.begin(), i = allConflictList.begin(); 
-         biter != canMoveList.end(); biter++, i++)
-    {
-        ProgramInfo *first = (*i);
-
-        list<ProgramInfo *> *conflictList = getConflicting(first, true, 
-                                                           copylist);
-
-        bool firstmove = *biter;
-
-        list<ProgramInfo *>::iterator j = conflictList->begin();
-        for (; j != conflictList->end(); j++)
-        {
-            ProgramInfo *second = (*j);
-
-            bool secondmove = 
-                (numInputsPerSource[second->sourceid] > 1 && 
-                 second->recstatus != rsRecording);
-
-            if (second->conflictfixed)
-                secondmove = false;
-
-            if (doRecPriority && 
-                second->recpriority > first->recpriority)
-            {
-                highermove = secondmove;
-                higher = second;
-                lowermove = firstmove;
-                lower = first;
-            }
-            else
-            {
-                highermove = firstmove;
-                higher = first;
-                lowermove = secondmove;
-                lower = second;
-            }
-
-            bool fixed = false;
-            if (lowermove)
-            {
-                int storeinput = lower->inputid;
-                int numinputs = numInputsPerSource[lower->sourceid];
-
-                for (int z = 0; z < numinputs; z++)
-                {
-                    lower->inputid = sourceToInput[lower->sourceid][z];
-                    lower->cardid = inputToCard[lower->inputid];
-
-                    if (!m_tvList->contains(lower->cardid))
-                    {
-                        if (m_tvList->size())
-                        {
-                            cerr << "Missing: " << lower->cardid <<
-                                    " in tvList\n";
-                        }
-                        continue;
-                    }
-
-                    EncoderLink *this_encoder = (*m_tvList)[lower->cardid];
-                    if ((this_encoder->WouldConflict(lower)) ||
-                        (this_encoder->isLowOnFreeSpace()) ||
-                        (this_encoder->isTunerLocked()))
-                        continue;
-
-                    if (!Conflict(higher, lower))
-                    {
-                        bool allclear = true;
-                        list<ProgramInfo *>::iterator k = fixedList.begin();
-                        for (; k != fixedList.end(); k++)
-                        {
-                            ProgramInfo *test = (*k);
-                            if (Conflict(test, lower))
-                            {
-                                allclear = false;
-                                break;
-                            }
-                        }
-
-                        if (allclear)
-                        {
-                            fixed = true;
-                            break;
-                        }
-                    }
-                }
-                if (!fixed)
-                {
-                    lower->inputid = storeinput;
-                    lower->cardid = inputToCard[lower->inputid];
-                }
-            }
-
-            if (!fixed && highermove)
-            {
-                int storeinput = higher->inputid;
-                int numinputs = numInputsPerSource[higher->sourceid];
-
-                for (int z = 0; z < numinputs; z++)
-                {
-                    higher->inputid = sourceToInput[higher->sourceid][z];
-                    higher->cardid = inputToCard[higher->inputid];
-
-                    if (!m_tvList->contains(higher->cardid))
-                    {
-                        if (m_tvList->size())
-                        {
-                            cerr << "Missing: " << higher->cardid <<
-                                    " in tvList\n";
-                        }
-                        continue;
-                    }
-
-                    EncoderLink *this_encoder = (*m_tvList)[higher->cardid];
-                    if ((this_encoder->WouldConflict(higher)) ||
-                        (this_encoder->isLowOnFreeSpace()) ||
-                        (this_encoder->isTunerLocked()))
-                        continue;
-
-                    if (!Conflict(higher, second))
-                    {
-                        bool allclear = true;
-                        list<ProgramInfo *>::iterator k = fixedList.begin();
-                        for (; k != fixedList.end(); k++)
-                        {
-                            ProgramInfo *test = (*k);
-                            if (Conflict(test, second))
-                            {
-                                allclear = false;
-                                break;
-                            }
-                        }
-
-                        if (allclear)
-                        {
-                            fixed = true;
-                            break;
-                        }
-                    }
-                }
-                if (!fixed)
-                {
-                    higher->inputid = storeinput;
-                    higher->cardid = inputToCard[higher->inputid];
-                }
-            }
-        }
-
-        delete conflictList;
-        conflictList = getConflicting(first, true, copylist);
-        if (!conflictList || conflictList->size() == 0)
-        {
-            first->conflictfixed = true;
-            fixedList.push_back(first);
-        }
-
-        delete conflictList;
-    }
-
-
-    for (i = recordingList.begin(); i != recordingList.end(); i++)
-    {
-        ProgramInfo *first = (*i);
-        delete first;
-    }
-
-    recordingList.clear();
-
-    for (i = copylist->begin(); i != copylist->end(); i++)
-    {
-        ProgramInfo *first = (*i);
-        recordingList.push_back(first);
-    }
-
-    delete copylist;
-}
-
 void Scheduler::RunScheduler(void)
 {
     int prerollseconds = 0;
@@ -1611,10 +1298,15 @@
 "record.recordid, recordoverride.type, "
 "program.starttime - INTERVAL record.startoffset minute, "
 "program.endtime + INTERVAL record.endoffset minute, "
-"program.previouslyshown, record.recgroup, record.dupmethod "
+"program.previouslyshown, record.recgroup, record.dupmethod, "
+"channel.xmltvid, capturecard.cardid, cardinput.cardinputid, "
+"UPPER(cardinput.shareable) = 'Y' AS shareable "
 "FROM record "
-" INNER JOIN channel ON (channel.chanid = program.chanid) "
 " INNER JOIN program ON (program.title = record.title) "
+" INNER JOIN channel ON (channel.chanid = program.chanid) "
+" LEFT JOIN channel AS chantmp ON (record.chanid = chantmp.chanid) "
+" INNER JOIN cardinput ON (channel.sourceid = cardinput.sourceid) "
+" INNER JOIN capturecard ON (capturecard.cardid = cardinput.cardid) "
 " LEFT JOIN oldrecorded ON "
 "  ( "
 "    oldrecorded.title IS NOT NULL AND oldrecorded.title <> '' AND program.title = oldrecorded.title "
@@ -1645,7 +1337,8 @@
 "((record.type = %1 " // allrecord
 "OR record.type = %2) " // findonerecord
 " OR "
-" ((record.chanid = program.chanid) " // channel matches
+" (((chantmp.xmltvid = channel.xmltvid AND chantmp.xmltvid IS NOT NULL) "
+" OR record.chanid = program.chanid) " // channel matches
 "  AND "
 "  ((record.type = %3) " // channelrecord
 "   OR"
@@ -1691,7 +1384,11 @@
         proginfo->recording = true;
         proginfo->recstatus = rsWillRecord;
         proginfo->chanid = result.value(0).toString();
+        proginfo->xmltvid = result.value(23).toString();
         proginfo->sourceid = result.value(1).toInt();
+        proginfo->cardid = result.value(24).toInt();
+        proginfo->inputid = result.value(25).toInt();
+        proginfo->shareable = result.value(26).toInt();
         proginfo->startts = result.value(2).toDateTime();
         proginfo->endts = result.value(3).toDateTime();
         proginfo->title = QString::fromUtf8(result.value(4).toString());
@@ -1770,6 +1467,8 @@
             proginfo->description = "";
         if (proginfo->category == QString::null)
             proginfo->category = "";
+        if (proginfo->xmltvid == QString::null)
+            proginfo->xmltvid = "";
 
         if (proginfo->recendts < now)
             delete proginfo;
@@ -1867,3 +1566,139 @@
         }
 }
 
+void Scheduler::TidyUpCrossCardDupes()
+{
+    ProgramInfo *higher;
+    ProgramInfo *lower;
+    ProgramInfo *erase;
+
+    list<ProgramInfo *>::iterator i = recordingList.begin();
+    while (i != recordingList.end())
+    {
+        erase = NULL;
+        ProgramInfo *first = (*i);
+
+        list<ProgramInfo *>::iterator j = i;
+        j++;
+        while (j != recordingList.end())
+        {
+            erase = NULL;
+            ProgramInfo *second = (*j);
+
+            if (!first->IsCrossCardDupe(*second))
+            {
+                j++;
+                continue;
+            }
+
+            higher = second;
+            lower = first;
+            if (first->cardid < second->cardid ||
+               (first->cardid ==  second->cardid &&
+                first->inputid < second->inputid))
+            {
+                higher = first;
+                lower = second;
+            }
+
+        // Assume for now that rsOverlap is good enough to
+        // hide the record. Later we must delete it.
+            if (Recording(higher) && Recording(lower))
+            {
+                j++;
+                continue;
+            }
+	    if (!Recording(lower) && Recording(higher))
+                  erase = lower;
+            else if (!Recording(higher) && Recording(lower))
+                  erase = higher;
+            else if (lower->recstatus == rsOtherShowing ||
+                     lower->recstatus == higher->recstatus)
+                  erase = lower;
+            else if (lower->recstatus == rsOtherShowing)
+                  erase = higher;
+
+            if (erase == first)
+                break;
+            if (erase == second)
+            {
+                delete erase;
+                j = recordingList.erase(j);
+            }
+            else
+                j++;
+        }
+        if (erase == first)
+        {
+            delete erase;
+            i = recordingList.erase(i);
+        }
+        else
+            i++;
+    }
+}
+
+#if 1
+void Scheduler::findOtherShowing(ProgramInfo* first)
+{
+    list<ProgramInfo *>::iterator i = recordingList.begin();
+    for (; i != recordingList.end(); i++)
+    {
+        ProgramInfo *second = (*i);
+        if( Recording(second) || second->recstatus != rsOtherShowing )
+            continue;
+
+        if (first->IsSameProgram(*second))
+        {
+            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->recstatus = rsOtherShowing;
+                first->conflicting = false;
+                second->recording = true;
+                second->recstatus = rsWillRecord;
+                second->conflicting = false;
+                return;
+            }
+        }
+    }
+}
+
+void Scheduler::DoFixups(void)
+{
+    list<ProgramInfo *>::iterator i = recordingList.begin();
+    for (; i != recordingList.end(); i++)
+    {
+        ProgramInfo *first = (*i);
+        if (Recording(first))
+            continue;
+
+        if (first->recstatus == rsLowerRecPriority ||
+                 first->recstatus == rsAutoConflict ||
+                 first->recstatus == rsManualConflict)
+        {
+            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->recstatus = rsWillRecord;
+            }
+            else
+                findOtherShowing(first);
+        }
+    }
+}
+#endif
Index: programs/mythbackend/scheduler.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythbackend/scheduler.h,v
retrieving revision 1.29
diff -u -r1.29 scheduler.h
--- programs/mythbackend/scheduler.h	10 Feb 2004 03:34:25 -0000	1.29
+++ programs/mythbackend/scheduler.h	11 Feb 2004 00:39:06 -0000
@@ -56,7 +56,7 @@
     static void *SchedulerThread(void *param);
 
   private:
-    void setupCards(void);
+    void verifyCards(void);
 
     void AddFuturePrograms(const QDateTime &now);
     void findAllScheduledPrograms(list<ProgramInfo*>& proglist);
@@ -101,14 +101,6 @@
 
     bool hasconflicts;
 
-    int numcards;
-    int numsources;
-    int numinputs;
-
-    QMap<int, int> numInputsPerSource;
-    QMap<int, vector<int> > sourceToInput;
-    QMap<int, int> inputToCard;
-
     QMap<int, EncoderLink *> *m_tvList;   
 
     QMap<QString, bool> recPendingList;
@@ -116,6 +108,11 @@
     bool threadrunning;
 
     void PruneRecordList(const QDateTime &now);
+    void TidyUpCrossCardDupes();
+#if 1
+    void findOtherShowing(ProgramInfo*);
+    void DoFixups();
+#endif
 
     MainServer *m_mainServer;
 };


More information about the mythtv-dev mailing list