Ticket #11020: epg_v2_fixes27.patch

File epg_v2_fixes27.patch, 26.6 KB (added by Jim Stichnoth, 13 years ago)

Backport of 7f2140ce062ade5a5523565b469ff58ada9c0d0d

  • mythtv/programs/mythfrontend/guidegrid.cpp

    commit bb33339f3f0deecf6002f0edb5961509466f2e67
    Author: Jim Stichnoth <jstichnoth@mythtv.org>
    Date:   Sun Nov 3 07:09:19 2013 -0800
    
        Improve the performance of Live TV embedded in the Program Guide.
        
        Most of the Program Guide's DB and backend queries are moved out of
        the UI loop into a background helper thread, to minimize the chance
        of the embedded Live TV window stuttering.
        
        More work can and should be done to pre-cache scheduler data and
        channel tuning status, and to have the backend invalidate/update it
        when there are changes.
        
        The background computation introduces some guide navigation UI
        oddities, where the expensive-to-compute elements (the list of
        channels) update on the screen slower than other elements.
        
        There is still some slight stuttering on a single-core ION frontend,
        but most frontends should see a vast or complete reduction in Guide
        navigation stuttering.
        
        Refs #11020
        
        (cherry picked from commit 7f2140ce062ade5a5523565b469ff58ada9c0d0d)
        
        Conflicts:
        	mythtv/programs/mythfrontend/guidegrid.cpp
    
    diff --git a/mythtv/programs/mythfrontend/guidegrid.cpp b/mythtv/programs/mythfrontend/guidegrid.cpp
    index 5a5f52c..0a3e345 100644
    a b bool JumpToChannel::Update(void)  
    164164    }
    165165}
    166166
     167// GuideStatus is used for transferring the relevant read-only data
     168// from GuideGrid to the GuideUpdateProgramRow constructor.
     169class GuideStatus
     170{
     171public:
     172    GuideStatus(unsigned int firstRow, unsigned int numRows,
     173                const QVector<int> &channums,
     174                int channelInfos_size,
     175                const MythRect &gg_programRect,
     176                int gg_channelCount,
     177                const QDateTime &currentStartTime,
     178                const QDateTime &currentEndTime,
     179                uint currentStartChannel,
     180                int currentRow, int currentCol,
     181                int channelCount, int timeCount,
     182                bool verticalLayout,
     183                const QDateTime &firstTime, const QDateTime &lastTime)
     184        : m_firstRow(firstRow), m_numRows(numRows), m_channums(channums),
     185          m_channelInfos_size(channelInfos_size),
     186          m_gg_programRect(gg_programRect), m_gg_channelCount(gg_channelCount),
     187          m_currentStartTime(currentStartTime),
     188          m_currentEndTime(currentEndTime),
     189          m_currentStartChannel(currentStartChannel), m_currentRow(currentRow),
     190          m_currentCol(currentCol), m_channelCount(channelCount),
     191          m_timeCount(timeCount), m_verticalLayout(verticalLayout),
     192          m_firstTime(firstTime), m_lastTime(lastTime) {}
     193    const unsigned int m_firstRow, m_numRows;
     194    const QVector<int> m_channums;
     195    const int m_channelInfos_size;
     196    const MythRect m_gg_programRect;
     197    const int m_gg_channelCount;
     198    const QDateTime m_currentStartTime, m_currentEndTime;
     199    const uint m_currentStartChannel;
     200    const int m_currentRow, m_currentCol;
     201    const int m_channelCount, m_timeCount;
     202    const bool m_verticalLayout;
     203    const QDateTime m_firstTime, m_lastTime;
     204};
     205
     206class GuideUpdaterBase
     207{
     208public:
     209    GuideUpdaterBase(GuideGrid *guide) : m_guide(guide) {}
     210
     211    // Execute the initial non-UI part (in a separate thread).  Return
     212    // true if ExecuteUI() should be run later, or false if the work
     213    // is no longer relevant (e.g., the UI elements have scrolled
     214    // offscreen by now).
     215    virtual bool ExecuteNonUI(void) = 0;
     216    // Execute the UI part in the UI thread.
     217    virtual void ExecuteUI(void) = 0;
     218
     219protected:
     220    GuideGrid *m_guide;
     221};
     222
     223class GuideUpdateProgramRow : public GuideUpdaterBase
     224{
     225public:
     226    GuideUpdateProgramRow(GuideGrid *guide, const GuideStatus &gs,
     227                          const QVector<ProgramList*> &proglists)
     228        : GuideUpdaterBase(guide),
     229          m_firstRow(gs.m_firstRow),
     230          m_numRows(gs.m_numRows),
     231          m_channums(gs.m_channums),
     232          m_channelInfos_size(gs.m_channelInfos_size),
     233          m_gg_programRect(gs.m_gg_programRect),
     234          m_gg_channelCount(gs.m_gg_channelCount),
     235          m_currentStartTime(gs.m_currentStartTime),
     236          m_currentEndTime(gs.m_currentEndTime),
     237          m_currentStartChannel(gs.m_currentStartChannel),
     238          m_currentRow(gs.m_currentRow),
     239          m_currentCol(gs.m_currentCol),
     240          m_channelCount(gs.m_channelCount),
     241          m_timeCount(gs.m_timeCount),
     242          m_verticalLayout(gs.m_verticalLayout),
     243          m_firstTime(gs.m_firstTime),
     244          m_lastTime(gs.m_lastTime),
     245          m_proglists(proglists)
     246    {
     247        for (unsigned int i = m_firstRow;
     248             i < m_firstRow + m_numRows; ++i)
     249            for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
     250                m_programInfos[i][j] = NULL;
     251    }
     252    virtual bool ExecuteNonUI(void)
     253    {
     254        // Don't bother to do any work if the starting coordinates of
     255        // the guide have changed while the thread was waiting to
     256        // start.
     257        if (m_currentStartChannel != m_guide->GetCurrentStartChannel() ||
     258            m_currentStartTime != m_guide->GetCurrentStartTime())
     259        {
     260            return false;
     261        }
     262
     263        for (unsigned int i = 0; i < m_numRows; ++i)
     264        {
     265            unsigned int row = i + m_firstRow;
     266            if (!m_proglists[i])
     267                m_proglists[i] =
     268                    m_guide->getProgramListFromProgram(m_channums[i]);
     269            fillProgramRowInfosWith(row, m_channums[i],
     270                                    m_currentStartTime,
     271                                    m_proglists[i]);
     272        }
     273        return true;
     274    }
     275    virtual void ExecuteUI(void)
     276    {
     277        m_guide->updateProgramsUI(m_firstRow, m_numRows,
     278                                  m_progPast, m_proglists,
     279                                  m_programInfos, m_result);
     280    }
     281
     282private:
     283    void fillProgramRowInfosWith(int row, int chanNum, QDateTime start,
     284                                 ProgramList *proglist);
     285
     286    const unsigned int m_firstRow;
     287    const unsigned int m_numRows;
     288    const QVector<int> m_channums;
     289    const int m_channelInfos_size;
     290    const MythRect m_gg_programRect;
     291    const int m_gg_channelCount;
     292    const QDateTime m_currentStartTime;
     293    const QDateTime m_currentEndTime;
     294    const uint m_currentStartChannel;
     295    const int m_currentRow;
     296    const int m_currentCol;
     297    const int m_channelCount;
     298    const int m_timeCount;
     299    const bool m_verticalLayout;
     300    const QDateTime m_firstTime;
     301    const QDateTime m_lastTime;
     302
     303    QVector<ProgramList*> m_proglists;
     304    ProgInfoGuideArray m_programInfos;
     305    int m_progPast;
     306    //QVector<GuideUIElement> m_result;
     307    QLinkedList<GuideUIElement> m_result;
     308};
     309
     310class GuideUpdateChannels : public GuideUpdaterBase
     311{
     312public:
     313    GuideUpdateChannels(GuideGrid *guide, uint startChan)
     314        : GuideUpdaterBase(guide), m_currentStartChannel(startChan) {}
     315    virtual bool ExecuteNonUI(void)
     316    {
     317        if (m_currentStartChannel != m_guide->GetCurrentStartChannel())
     318            return false;
     319        m_guide->updateChannelsNonUI(m_chinfos, m_unavailables);
     320        return true;
     321    }
     322    virtual void ExecuteUI(void)
     323    {
     324        m_guide->updateChannelsUI(m_chinfos, m_unavailables);
     325    }
     326    uint m_currentStartChannel;
     327    QVector<ChannelInfo *> m_chinfos;
     328    QVector<bool> m_unavailables;
     329};
     330
     331class UpdateGuideEvent : public QEvent
     332{
     333public:
     334    UpdateGuideEvent(GuideUpdaterBase *updater) :
     335        QEvent(kEventType), m_updater(updater) {}
     336    GuideUpdaterBase *m_updater;
     337    static Type kEventType;
     338};
     339QEvent::Type UpdateGuideEvent::kEventType =
     340    (QEvent::Type) QEvent::registerEventType();
     341
     342class GuideHelper : public QRunnable
     343{
     344public:
     345    GuideHelper(GuideGrid *guide, GuideUpdaterBase *updater)
     346        : m_guide(guide), m_updater(updater)
     347    {
     348        QMutexLocker locker(&s_lock);
     349        ++s_loading[m_guide];
     350    }
     351    virtual void run(void)
     352    {
     353        QThread::currentThread()->setPriority(QThread::IdlePriority);
     354        if (m_updater)
     355        {
     356            if (m_updater->ExecuteNonUI())
     357                QCoreApplication::postEvent(m_guide,
     358                                            new UpdateGuideEvent(m_updater));
     359            else
     360            {
     361                delete m_updater;
     362                m_updater = NULL;
     363            }
     364        }
     365
     366        QMutexLocker locker(&s_lock);
     367        --s_loading[m_guide];
     368        if (!s_loading[m_guide])
     369            s_wait.wakeAll();
     370    }
     371    static bool IsLoading(GuideGrid *guide)
     372    {
     373        QMutexLocker locker(&s_lock);
     374        return s_loading[guide];
     375    }
     376    static void Wait(GuideGrid *guide)
     377    {
     378        QMutexLocker locker(&s_lock);
     379        if (!s_loading[guide])
     380            return;
     381        while (s_wait.wait(&s_lock))
     382        {
     383            if (!s_loading[guide])
     384                return;
     385        }
     386    }
     387private:
     388    GuideGrid *m_guide;
     389    GuideUpdaterBase *m_updater;
     390
     391    static QMutex                s_lock;
     392    static QWaitCondition        s_wait;
     393    static QMap<GuideGrid*,uint> s_loading;
     394};
     395QMutex                GuideHelper::s_lock;
     396QWaitCondition        GuideHelper::s_wait;
     397QMap<GuideGrid*,uint> GuideHelper::s_loading;
     398
    167399void GuideGrid::RunProgramGuide(uint chanid, const QString &channum,
    168400                                const QDateTime startTime,
    169401                                TV *player, bool embedVideo,
    GuideGrid::GuideGrid(MythScreenStack *parent,  
    241473           m_previewVideoRefreshTimer(new QTimer(this)),
    242474           m_channelOrdering(gCoreContext->GetSetting("ChannelOrdering", "channum")),
    243475           m_updateTimer(NULL),
     476           m_threadPool("GuideGridHelperPool"),
    244477           m_changrpid(changrpid),
    245478           m_changrplist(ChannelGroup::GetChannelGroups(false)),
    246479           m_jumpToChannelLock(QMutex::Recursive),
    GuideGrid::GuideGrid(MythScreenStack *parent,  
    274507    int secsoffset = -((m_originalStartTime.time().minute() % 30) * 60 +
    275508                        m_originalStartTime.time().second());
    276509    m_currentStartTime = m_originalStartTime.addSecs(secsoffset);
     510    m_threadPool.setMaxThreadCount(1);
    277511}
    278512
    279513bool GuideGrid::Create()
    void GuideGrid::Init(void)  
    356590    updateChannels();
    357591
    358592    fillProgramInfos(true);
    359     updateInfo();
    360593
    361594    m_updateTimer = new QTimer(this);
    362595    connect(m_updateTimer, SIGNAL(timeout()), SLOT(updateTimeout()) );
    void GuideGrid::Init(void)  
    374607
    375608GuideGrid::~GuideGrid()
    376609{
     610    GuideHelper::Wait(this);
     611
    377612    gCoreContext->removeListener(this);
    378613
    379614    while (!m_programs.empty())
    ProgramList GuideGrid::GetProgramList(uint chanid) const  
    728963    return proglist;
    729964}
    730965
     966static ProgramList *CopyProglist(ProgramList *proglist)
     967{
     968    if (!proglist)
     969        return NULL;
     970    ProgramList *result = new ProgramList();
     971    for (ProgramList::iterator pi = proglist->begin();
     972         pi != proglist->end(); ++pi)
     973        result->push_back(new ProgramInfo(**pi));
     974    return result;
     975}
     976
    731977uint GuideGrid::GetAlternateChannelIndex(
    732978    uint chan_idx, bool with_same_channum) const
    733979{
    void GuideGrid::fillTimeInfos()  
    10751321
    10761322void GuideGrid::fillProgramInfos(bool useExistingData)
    10771323{
    1078     m_guideGrid->ResetData();
    1079 
    1080     for (int y = 0; y < m_channelCount; ++y)
    1081     {
    1082         fillProgramRowInfos(y, useExistingData);
    1083     }
     1324    fillProgramRowInfos(-1, useExistingData);
    10841325}
    10851326
    10861327ProgramList *GuideGrid::getProgramListFromProgram(int chanNum)
    ProgramList *GuideGrid::getProgramListFromProgram(int chanNum)  
    11061347    return proglist;
    11071348}
    11081349
    1109 void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)
     1350void GuideGrid::fillProgramRowInfos(int firstRow, bool useExistingData)
    11101351{
    1111     m_guideGrid->ResetRow(row);
    1112 
    1113     // never divide by zero..
    1114     if (!m_guideGrid->getChannelCount() || !m_timeCount)
    1115         return;
    1116 
    1117     for (int x = 0; x < m_timeCount; ++x)
     1352    bool allRows = false;
     1353    unsigned int numRows = 1;
     1354    if (firstRow < 0)
    11181355    {
    1119         m_programInfos[row][x] = NULL;
     1356        firstRow = 0;
     1357        allRows = true;
     1358        numRows = min((unsigned int)m_channelInfos.size(),
     1359                      (unsigned int)m_guideGrid->getChannelCount());
    11201360    }
     1361    QVector<int> chanNums;
     1362    QVector<ProgramList*> proglists;
    11211363
    1122     if (m_channelInfos.empty())
    1123         return;
     1364    for (unsigned int i = 0; i < numRows; ++i)
     1365    {
     1366        unsigned int row = i + firstRow;
     1367        // never divide by zero..
     1368        if (!m_guideGrid->getChannelCount() || !m_timeCount)
     1369            return;
    11241370
    1125     int chanNum = row + m_currentStartChannel;
    1126     if (chanNum >= (int) m_channelInfos.size())
    1127         chanNum -= (int) m_channelInfos.size();
    1128     if (chanNum >= (int) m_channelInfos.size())
    1129         return;
     1371        for (int x = 0; x < m_timeCount; ++x)
     1372        {
     1373            m_programInfos[row][x] = NULL;
     1374        }
    11301375
    1131     if (chanNum < 0)
    1132         chanNum = 0;
     1376        if (m_channelInfos.empty())
     1377            return;
     1378
     1379        int chanNum = row + m_currentStartChannel;
     1380        if (chanNum >= (int) m_channelInfos.size())
     1381            chanNum -= (int) m_channelInfos.size();
     1382        if (chanNum >= (int) m_channelInfos.size())
     1383            return;
     1384
     1385        if (chanNum < 0)
     1386            chanNum = 0;
    11331387
    1134     if (!useExistingData)
     1388        ProgramList *proglist = NULL;
     1389        if (useExistingData)
     1390            proglist = CopyProglist(m_programs[row]);
     1391        chanNums.push_back(chanNum);
     1392        proglists.push_back(proglist);
     1393    }
     1394    if (allRows)
    11351395    {
    1136         delete m_programs[row];
    1137         m_programs[row] = getProgramListFromProgram(chanNum);
     1396        for (unsigned int i = numRows;
     1397             i < (unsigned int) m_guideGrid->getChannelCount(); ++i)
     1398        {
     1399            delete m_programs[i];
     1400            m_programs[i] = NULL;
     1401            m_guideGrid->ResetRow(i);
     1402        }
    11381403    }
     1404    GuideStatus gs(firstRow, chanNums.size(), chanNums, m_channelInfos.size(),
     1405                   m_guideGrid->GetArea(), m_guideGrid->getChannelCount(),
     1406                   m_currentStartTime, m_currentEndTime, m_currentStartChannel,
     1407                   m_currentRow, m_currentCol, m_channelCount, m_timeCount,
     1408                   m_verticalLayout, m_firstTime, m_lastTime);
     1409    GuideUpdateProgramRow *updater =
     1410        new GuideUpdateProgramRow(this, gs, proglists);
     1411    m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
     1412}
    11391413
    1140     ProgramList *proglist = m_programs[row];
    1141     if (!proglist)
     1414void GuideUpdateProgramRow::fillProgramRowInfosWith(int row, int chanNum,
     1415                                                    QDateTime start,
     1416                                                    ProgramList *proglist)
     1417{
     1418    if (row < 0 || row >= m_channelCount ||
     1419        start != m_currentStartTime)
     1420    {
     1421        delete proglist;
    11421422        return;
     1423    }
    11431424
    11441425    QDateTime ts = m_currentStartTime;
    11451426
    void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)  
    11571438            progPast = played * 100 / length;
    11581439    }
    11591440
    1160     m_guideGrid->SetProgPast(progPast);
     1441    m_progPast = progPast;
    11611442
    11621443    ProgramList::iterator program = proglist->begin();
    11631444    vector<ProgramInfo*> unknownlist;
    void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)  
    12151496    for (; it != unknownlist.end(); ++it)
    12161497        proglist->push_back(*it);
    12171498
    1218     MythRect programRect = m_guideGrid->GetArea();
     1499    MythRect programRect = m_gg_programRect;
    12191500
    12201501    /// use doubles to avoid large gaps at end..
    12211502    double ydifference = 0.0, xdifference = 0.0;
    void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)  
    12231504    if (m_verticalLayout)
    12241505    {
    12251506        ydifference = programRect.width() /
    1226             (double) m_guideGrid->getChannelCount();
     1507            (double) m_gg_channelCount;
    12271508        xdifference = programRect.height() /
    12281509            (double) m_timeCount;
    12291510    }
    12301511    else
    12311512    {
    12321513        ydifference = programRect.height() /
    1233             (double) m_guideGrid->getChannelCount();
     1514            (double) m_gg_channelCount;
    12341515        xdifference = programRect.width() /
    12351516            (double) m_timeCount;
    12361517    }
    void GuideGrid::fillProgramRowInfos(unsigned int row, bool useExistingData)  
    13491630                recStat = 0;
    13501631
    13511632            QString title = (pginfo->GetTitle() == kUnknownTitle) ?
    1352                                 tr("Unknown", "Unknown program title") :
     1633                GuideGrid::tr("Unknown", "Unknown program title") :
    13531634                                pginfo->GetTitle();
    1354             m_guideGrid->SetProgramInfo(
     1635            m_result.push_back(GuideUIElement(
    13551636                row, cnt, tempRect, title,
    13561637                pginfo->GetCategory(), arrow, recFlag,
    1357                 recStat, isCurrent);
     1638                recStat, isCurrent));
    13581639
    13591640            cnt++;
    13601641        }
    void GuideGrid::customEvent(QEvent *event)  
    13741655        {
    13751656            LoadFromScheduler(m_recList);
    13761657            fillProgramInfos();
    1377             updateInfo();
    13781658        }
    13791659        else if (message == "STOP_VIDEO_REFRESH_TIMER")
    13801660        {
    void GuideGrid::customEvent(QEvent *event)  
    15131793        else
    15141794            ScheduleCommon::customEvent(event);
    15151795    }
     1796    else if (event->type() == UpdateGuideEvent::kEventType)
     1797    {
     1798        UpdateGuideEvent *uge = static_cast<UpdateGuideEvent*>(event);
     1799        if (uge->m_updater)
     1800        {
     1801            uge->m_updater->ExecuteUI();
     1802            delete uge->m_updater;
     1803            uge->m_updater = NULL;
     1804        }
     1805    }
    15161806}
    15171807
    15181808void GuideGrid::updateDateText(void)
    void GuideGrid::updateDateText(void)  
    15241814                                                 (MythDate::kDateFull | MythDate::kSimplify)));
    15251815}
    15261816
     1817void GuideGrid::updateProgramsUI(unsigned int firstRow, unsigned int numRows,
     1818                                 int progPast,
     1819                                 const QVector<ProgramList*> &proglists,
     1820                                 const ProgInfoGuideArray &programInfos,
     1821                                 const QLinkedList<GuideUIElement> &elements)
     1822{
     1823    for (unsigned int i = 0; i < numRows; ++i)
     1824    {
     1825        unsigned int row = i + firstRow;
     1826        m_guideGrid->ResetRow(row);
     1827        if (m_programs[row] != proglists[i])
     1828        {
     1829            delete m_programs[row];
     1830            m_programs[row] = proglists[i];
     1831        }
     1832    }
     1833    m_guideGrid->SetProgPast(progPast);
     1834    for (QLinkedList<GuideUIElement>::const_iterator it = elements.begin();
     1835         it != elements.end(); ++it)
     1836    {
     1837        const GuideUIElement &r = *it;
     1838        m_guideGrid->SetProgramInfo(r.m_row, r.m_col, r.m_area, r.m_title,
     1839                                    r.m_category, r.m_arrow, r.m_recType,
     1840                                    r.m_recStat, r.m_selected);
     1841    }
     1842    for (unsigned int i = firstRow; i < firstRow + numRows; ++i)
     1843    {
     1844        for (int j = 0; j < MAX_DISPLAY_TIMES; ++j)
     1845            m_programInfos[i][j] = programInfos[i][j];
     1846        if (i == (unsigned int)m_currentRow)
     1847            updateInfo();
     1848    }
     1849    m_guideGrid->SetRedraw();
     1850}
     1851
    15271852void GuideGrid::updateChannels(void)
    15281853{
    1529     m_channelList->Reset();
     1854    GuideUpdateChannels *updater =
     1855        new GuideUpdateChannels(this, m_currentStartChannel);
     1856    m_threadPool.start(new GuideHelper(this, updater), "GuideHelper");
     1857}
    15301858
     1859void GuideGrid::updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
     1860                                    QVector<bool> &unavailables)
     1861{
    15311862    ChannelInfo *chinfo = GetChannelInfo(m_currentStartChannel);
    15321863
    15331864    if (m_player)
    void GuideGrid::updateChannels(void)  
    15751906                unavailable = (alt == m_channelInfoIdx[chanNumber]);
    15761907            }
    15771908        }
     1909        chinfos.push_back(chinfo);
     1910        unavailables.push_back(unavailable);
     1911    }
     1912}
    15781913
     1914void GuideGrid::updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
     1915                                 const QVector<bool> &unavailables)
     1916{
     1917    m_channelList->Reset();
     1918    for (int i = 0; i < chinfos.size(); ++i)
     1919    {
     1920        ChannelInfo *chinfo = chinfos[i];
     1921        bool unavailable = unavailables[i];
    15791922        MythUIButtonListItem *item =
    15801923            new MythUIButtonListItem(m_channelList,
    15811924                                     chinfo ? chinfo->GetFormatted(ChannelInfo::kChannelShort) : QString());
    void GuideGrid::updateInfo(void)  
    16602003        QString rating = QString::number(pginfo->GetStars(10));
    16612004        ratingState->DisplayState(rating);
    16622005    }
     2006    m_guideGrid->SetRedraw();
    16632007}
    16642008
    16652009void GuideGrid::toggleGuideListing()
    void GuideGrid::cursorLeft()  
    18092153    }
    18102154    else
    18112155    {
    1812         fillProgramRowInfos(m_currentRow);
    1813         m_guideGrid->SetRedraw();
    1814         updateInfo();
     2156        fillProgramRowInfos(m_currentRow, true);
    18152157    }
    18162158}
    18172159
    void GuideGrid::cursorRight()  
    18372179    }
    18382180    else
    18392181    {
    1840         fillProgramRowInfos(m_currentRow);
    1841         m_guideGrid->SetRedraw();
    1842         updateInfo();
     2182        fillProgramRowInfos(m_currentRow, true);
    18432183    }
    18442184}
    18452185
    void GuideGrid::cursorDown()  
    18542194    }
    18552195    else
    18562196    {
    1857         fillProgramRowInfos(m_currentRow);
    1858         m_guideGrid->SetRedraw();
    1859         updateInfo();
    1860         updateChannels();
     2197        fillProgramRowInfos(m_currentRow, true);
    18612198    }
    18622199}
    18632200
    void GuideGrid::cursorUp()  
    18722209    }
    18732210    else
    18742211    {
    1875         fillProgramRowInfos(m_currentRow);
    1876         m_guideGrid->SetRedraw();
    1877         updateInfo();
    1878         updateChannels();
     2212        fillProgramRowInfos(m_currentRow, true);
    18792213    }
    18802214}
    18812215
    void GuideGrid::moveLeftRight(MoveVector movement)  
    19072241
    19082242    fillTimeInfos();
    19092243    fillProgramInfos();
    1910     m_guideGrid->SetRedraw();
    1911     updateInfo();
    19122244    updateDateText();
    19132245}
    19142246
    void GuideGrid::moveUpDown(MoveVector movement)  
    19332265    }
    19342266
    19352267    fillProgramInfos();
    1936     m_guideGrid->SetRedraw();
    1937     updateInfo();
    19382268    updateChannels();
    19392269}
    19402270
    void GuideGrid::moveToTime(QDateTime datetime)  
    19472277
    19482278    fillTimeInfos();
    19492279    fillProgramInfos();
    1950     m_guideGrid->SetRedraw();
    1951     updateInfo();
    19522280    updateDateText();
    19532281}
    19542282
    void GuideGrid::quickRecord()  
    20162344    QuickRecord(pginfo);
    20172345    LoadFromScheduler(m_recList);
    20182346    fillProgramInfos();
    2019     updateInfo();
    20202347}
    20212348
    20222349void GuideGrid::editRecSchedule()
    void GuideGrid::GoTo(int start, int cur_row)  
    21632490    m_currentRow = cur_row % m_channelCount;
    21642491    updateChannels();
    21652492    fillProgramInfos();
    2166     updateInfo();
    21672493    updateJumpToChannel();
    21682494}
    21692495
  • mythtv/programs/mythfrontend/guidegrid.h

    diff --git a/mythtv/programs/mythfrontend/guidegrid.h b/mythtv/programs/mythfrontend/guidegrid.h
    index fd11d27..94dbd8c 100644
    a b using namespace std;  
    1010#include <QString>
    1111#include <QDateTime>
    1212#include <QEvent>
     13#include <QLinkedList>
    1314
    1415// myth
    1516#include "mythscreentype.h"
    using namespace std;  
    1718#include "channelgroup.h"
    1819#include "channelutil.h"
    1920#include "mythuiguidegrid.h"
     21#include "mthreadpool.h"
    2022
    2123// mythfrontend
    2224#include "schedulecommon.h"
    class MythUIGuideGrid;  
    3335
    3436typedef vector<ChannelInfo>   db_chan_list_t;
    3537typedef vector<db_chan_list_t> db_chan_list_list_t;
     38typedef ProgramInfo *ProgInfoGuideArray[MAX_DISPLAY_CHANS][MAX_DISPLAY_TIMES];
    3639
    3740class JumpToChannel;
    3841class JumpToChannelListener
    class JumpToChannel : public QObject  
    7679    static const uint kJumpToChannelTimeout = 3500; // ms
    7780};
    7881
     82// GuideUIElement encapsulates the arguments to
     83// MythUIGuideGrid::SetProgramInfo().  The elements are prepared in a
     84// background thread and then sent via an event to the UI thread for
     85// rendering.
     86class GuideUIElement {
     87public:
     88    GuideUIElement(int row, int col, const QRect &area,
     89                   const QString &title, const QString &category,
     90                   int arrow, int recType, int recStat, bool selected)
     91        : m_row(row), m_col(col), m_area(area), m_title(title),
     92          m_category(category), m_arrow(arrow), m_recType(recType),
     93          m_recStat(recStat), m_selected(selected) {}
     94    const int m_row;
     95    const int m_col;
     96    const QRect m_area;
     97    const QString m_title;
     98    const QString m_category;
     99    const int m_arrow;
     100    const int m_recType;
     101    const int m_recStat;
     102    const bool m_selected;
     103};
     104
    79105class GuideGrid : public ScheduleCommon, public JumpToChannelListener
    80106{
    81107    Q_OBJECT
    class GuideGrid : public ScheduleCommon, public JumpToChannelListener  
    102128
    103129    virtual void aboutToShow();
    104130    virtual void aboutToHide();
     131    // Allow class GuideUpdateProgramRow to figure out whether the
     132    // current start time/channel coordinates are the same, so that it can
     133    // skip the work if not.
     134    uint GetCurrentStartChannel(void) const { return m_currentStartChannel; }
     135    QDateTime GetCurrentStartTime(void) const { return m_currentStartTime; }
    105136
    106137  protected slots:
    107138    void cursorLeft();
    class GuideGrid : public ScheduleCommon, public JumpToChannelListener  
    179210    void fillChannelInfos(bool gotostartchannel = true);
    180211    void fillTimeInfos(void);
    181212    void fillProgramInfos(bool useExistingData = false);
    182     void fillProgramRowInfos(unsigned int row, bool useExistingData = false);
     213    // Set row=-1 to fill all rows.
     214    void fillProgramRowInfos(int row, bool useExistingData);
     215public:
     216    // These need to be public so that the helper classes can operate.
    183217    ProgramList *getProgramListFromProgram(int chanNum);
     218    void updateProgramsUI(unsigned int firstRow, unsigned int numRows,
     219                          int progPast,
     220                          const QVector<ProgramList*> &proglists,
     221                          const ProgInfoGuideArray &programInfos,
     222                          const QLinkedList<GuideUIElement> &elements);
     223    void updateChannelsNonUI(QVector<ChannelInfo *> &chinfos,
     224                             QVector<bool> &unavailables);
     225    void updateChannelsUI(const QVector<ChannelInfo *> &chinfos,
     226                          const QVector<bool> &unavailables);
     227private:
    184228
    185229    void setStartChannel(int newStartChannel);
    186230
    class GuideGrid : public ScheduleCommon, public JumpToChannelListener  
    201245    QMap<uint,uint>      m_channelInfoIdx;
    202246
    203247    vector<ProgramList*> m_programs;
    204     ProgramInfo *m_programInfos[MAX_DISPLAY_CHANS][MAX_DISPLAY_TIMES];
     248    ProgInfoGuideArray m_programInfos;
    205249    ProgramList  m_recList;
    206250
    207251    QDateTime m_originalStartTime;
    class GuideGrid : public ScheduleCommon, public JumpToChannelListener  
    235279
    236280    QTimer *m_updateTimer; // audited ref #5318
    237281
     282    MThreadPool       m_threadPool;
     283
    238284    int               m_changrpid;
    239285    ChannelGroupList  m_changrplist;
    240286