Skip to content

Commit

Permalink
Merge pull request #11879 from ksooo/pvr-fix-epg-grid-channelgroup-sw…
Browse files Browse the repository at this point in the history
…itching

[PVR] Guide window: Fix selection after channelgroup switching
  • Loading branch information
ksooo committed Mar 27, 2017
2 parents 899ec07 + 5feed5e commit 8a96c67
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 53 deletions.
53 changes: 27 additions & 26 deletions xbmc/epg/GUIEPGGridContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,14 +416,6 @@ void CGUIEPGGridContainer::RenderItem(float posX, float posY, CGUIListItem *item
g_graphicsContext.RestoreOrigin();
}

void CGUIEPGGridContainer::ResetCoordinates()
{
m_channelCursor = 0;
m_channelOffset = 0;
m_blockCursor = 0;
m_blockOffset = 0;
}

bool CGUIEPGGridContainer::OnAction(const CAction &action)
{
switch (action.GetID())
Expand Down Expand Up @@ -750,9 +742,23 @@ void CGUIEPGGridContainer::UpdateItems()

if (prevSelectedEpgTag && (oldChannelIndex != 0 || oldBlockIndex != 0))
{
if (m_gridModel->GetGridItem(newChannelIndex, newBlockIndex)->GetEPGInfoTag() != prevSelectedEpgTag)
if (newChannelIndex >= m_gridModel->ChannelItemsSize() ||
newBlockIndex >= m_gridModel->GetBlockCount() ||
m_gridModel->GetGridItem(newChannelIndex, newBlockIndex)->GetEPGInfoTag() != prevSelectedEpgTag)
{
m_gridModel->FindChannelAndBlockIndex(channelUid, broadcastUid, eventOffset, newChannelIndex, newBlockIndex);

if (newChannelIndex == CGUIEPGGridContainerModel::INVALID_INDEX ||
newBlockIndex == CGUIEPGGridContainerModel::INVALID_INDEX)
{
// previous selection is no longer in grid, goto channel 0 and now
SetInvalid();
GoToChannel(0);
GoToNow();
return;
}
}

// restore previous selection.
if (newChannelIndex == oldChannelIndex && newBlockIndex == oldBlockIndex)
{
Expand Down Expand Up @@ -1665,18 +1671,18 @@ void CGUIEPGGridContainer::SetTimelineItems(const std::unique_ptr<CFileItemList>

void CGUIEPGGridContainer::GoToChannel(int channelIndex)
{
if (channelIndex > m_gridModel->ChannelItemsSize() - m_channelsPerPage)
{
// last page
ScrollToChannelOffset(m_gridModel->ChannelItemsSize() - m_channelsPerPage);
SetChannel(channelIndex - (m_gridModel->ChannelItemsSize() - m_channelsPerPage));
}
else if (channelIndex < m_channelsPerPage)
if (channelIndex < m_channelsPerPage)
{
// first page
ScrollToChannelOffset(0);
SetChannel(channelIndex);
}
else if (channelIndex > m_gridModel->ChannelItemsSize() - m_channelsPerPage)
{
// last page
ScrollToChannelOffset(m_gridModel->ChannelItemsSize() - m_channelsPerPage);
SetChannel(channelIndex - (m_gridModel->ChannelItemsSize() - m_channelsPerPage));
}
else
{
ScrollToChannelOffset(channelIndex - m_channelCursor);
Expand All @@ -1686,17 +1692,12 @@ void CGUIEPGGridContainer::GoToChannel(int channelIndex)

void CGUIEPGGridContainer::GoToBlock(int blockIndex)
{
if (blockIndex > m_gridModel->GetBlockCount() - m_blocksPerPage)
int lastPage = m_gridModel->GetBlockCount() - m_blocksPerPage;
if (blockIndex > lastPage)
{
// last block
ScrollToBlockOffset(m_gridModel->GetBlockCount() - m_blocksPerPage);
SetBlock(blockIndex - (m_gridModel->GetBlockCount() - m_blocksPerPage));
}
else if (blockIndex < m_blocksPerPage)
{
// first block
ScrollToBlockOffset(0);
SetBlock(blockIndex);
// last page
ScrollToBlockOffset(lastPage);
SetBlock(blockIndex - lastPage);
}
else
{
Expand Down
1 change: 0 additions & 1 deletion xbmc/epg/GUIEPGGridContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ namespace EPG
* @return true if the selection was set to the given channel, false otherwise.
*/
bool SetChannel(const std::string &channel);
void ResetCoordinates();

protected:
bool OnClick(int actionID);
Expand Down
3 changes: 3 additions & 0 deletions xbmc/epg/GUIEPGGridContainerModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@ void CGUIEPGGridContainerModel::FindChannelAndBlockIndex(int channelUid, unsigne
const CDateTimeSpan blockDuration(0, 0, MINSPERBLOCK, 0);
bool bFoundPrevChannel = false;

newChannelIndex = INVALID_INDEX;
newBlockIndex = INVALID_INDEX;

for (size_t channel = 0; channel < m_channelItems.size(); ++channel)
{
CDateTime gridCursor(m_gridStart); //reset cursor for new channel
Expand Down
1 change: 1 addition & 0 deletions xbmc/epg/GUIEPGGridContainerModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ namespace EPG
void Refresh(const std::unique_ptr<CFileItemList> &items, const CDateTime &gridStart, const CDateTime &gridEnd, int iRulerUnit, int iBlocksPerPage, float fBlockSize);
void SetInvalid();

static const int INVALID_INDEX = -1;
void FindChannelAndBlockIndex(int channelUid, unsigned int broadcastUid, int eventOffset, int &newChannelIndex, int &newBlockIndex) const;

void FreeChannelMemory(int keepStart, int keepEnd);
Expand Down
95 changes: 69 additions & 26 deletions xbmc/pvr/windows/GUIWindowPVRGuide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

#include "ContextMenuManager.h"
#include "dialogs/GUIDialogBusy.h"
#include "epg/GUIEPGGridContainer.h"
#include "GUIUserMessages.h"
#include "ServiceBroker.h"
Expand All @@ -45,7 +46,6 @@ using namespace EPG;
CGUIWindowPVRGuide::CGUIWindowPVRGuide(bool bRadio) :
CGUIWindowPVRBase(bRadio, bRadio ? WINDOW_RADIO_GUIDE : WINDOW_TV_GUIDE, "MyPVRGuide.xml"),
CPVRChannelNumberInputHandler(1000),
m_cachedChannelGroup(new CPVRChannelGroup),
m_bChannelSelectionRestored(false)
{
m_bRefreshTimelineItems = false;
Expand All @@ -55,6 +55,8 @@ CGUIWindowPVRGuide::CGUIWindowPVRGuide(bool bRadio) :
CGUIWindowPVRGuide::~CGUIWindowPVRGuide(void)
{
g_EpgContainer.UnregisterObserver(this);

m_bRefreshTimelineItems = false;
StopRefreshTimelineItemsThread();
}

Expand All @@ -72,15 +74,20 @@ void CGUIWindowPVRGuide::Init()
epgGridContainer->GoToNow();
}

m_bRefreshTimelineItems = true;
if (!m_refreshTimelineItemsThread)
{
CSingleLock lock(m_critSection);
m_bRefreshTimelineItems = true; // force data update on first window open
}

StartRefreshTimelineItemsThread();
}

void CGUIWindowPVRGuide::ClearData()
{
{
CSingleLock lock(m_critSection);
m_cachedChannelGroup.reset(new CPVRChannelGroup);
m_cachedChannelGroup.reset();
m_newTimeline.reset();
}

Expand All @@ -101,10 +108,19 @@ void CGUIWindowPVRGuide::OnInitWindow()
void CGUIWindowPVRGuide::OnDeinitWindow(int nextWindowID)
{
StopRefreshTimelineItemsThread();
m_bRefreshTimelineItems = false;

m_bChannelSelectionRestored = false;

{
CSingleLock lock(m_critSection);
if (m_vecItems && !m_newTimeline)
{
// speedup: save a copy of current items for reuse when re-opening the window
m_newTimeline.reset(new CFileItemList);
m_newTimeline->Copy(*m_vecItems);
}
}

CGUIWindowPVRBase::OnDeinitWindow(nextWindowID);
}

Expand All @@ -118,16 +134,15 @@ void CGUIWindowPVRGuide::StartRefreshTimelineItemsThread()
void CGUIWindowPVRGuide::StopRefreshTimelineItemsThread()
{
if (m_refreshTimelineItemsThread)
m_refreshTimelineItemsThread->StopThread(false);
m_refreshTimelineItemsThread->Stop();
}

void CGUIWindowPVRGuide::Notify(const Observable &obs, const ObservableMessage msg)
{
if (IsActive() &&
(msg == ObservableMessageEpg ||
msg == ObservableMessageEpgContainer ||
msg == ObservableMessageChannelGroupReset ||
msg == ObservableMessageChannelGroup))
if (msg == ObservableMessageEpg ||
msg == ObservableMessageEpgContainer ||
msg == ObservableMessageChannelGroupReset ||
msg == ObservableMessageChannelGroup)
{
CSingleLock lock(m_critSection);
m_bRefreshTimelineItems = true;
Expand Down Expand Up @@ -193,27 +208,22 @@ bool CGUIWindowPVRGuide::Update(const std::string &strDirectory, bool updateFilt

bool CGUIWindowPVRGuide::GetDirectory(const std::string &strDirectory, CFileItemList &items)
{
bool bRefresh = false;
bool bRefreshTimelineItems = false;

{
CSingleLock lock(m_critSection);

// group change detected reset grid coordinates and refresh grid items
if (!m_bRefreshTimelineItems && *m_cachedChannelGroup != *GetChannelGroup())
if (m_cachedChannelGroup && *m_cachedChannelGroup != *GetChannelGroup())
{
CGUIEPGGridContainer* epgGridContainer = GetGridControl();
if (!epgGridContainer)
return true;

epgGridContainer->ResetCoordinates();
// channel group change and not very first open of this window. force immediate update.
m_bRefreshTimelineItems = true;
bRefresh = true;
bRefreshTimelineItems = true;
}
}

// never call RefreshTimelineItems with locked mutex!
if (bRefresh)
RefreshTimelineItems();
// never call DoRefresh with locked mutex!
if (bRefreshTimelineItems)
m_refreshTimelineItemsThread->DoRefresh();

{
CSingleLock lock(m_critSection);
Expand Down Expand Up @@ -443,10 +453,16 @@ bool CGUIWindowPVRGuide::OnContextButton(int itemNumber, CONTEXT_BUTTON button)

bool CGUIWindowPVRGuide::RefreshTimelineItems()
{
if (m_bRefreshTimelineItems)
bool bRefreshTimelineItems;
{
CSingleLock lock(m_critSection);

bRefreshTimelineItems = m_bRefreshTimelineItems;
m_bRefreshTimelineItems = false;
}

if (bRefreshTimelineItems)
{
CGUIEPGGridContainer* epgGridContainer = GetGridControl();
if (epgGridContainer)
{
Expand Down Expand Up @@ -554,8 +570,23 @@ void CGUIWindowPVRGuide::OnInputDone()

CPVRRefreshTimelineItemsThread::CPVRRefreshTimelineItemsThread(CGUIWindowPVRGuide *pGuideWindow)
: CThread("epg-grid-refresh-timeline-items"),
m_pGuideWindow(pGuideWindow)
m_pGuideWindow(pGuideWindow),
m_ready(true),
m_done(false)
{
}

void CPVRRefreshTimelineItemsThread::Stop()
{
StopThread(false);
m_ready.Set(); // wake up the worker thread to let it exit
}

void CPVRRefreshTimelineItemsThread::DoRefresh()
{
m_ready.Set(); // wake up the worker thread
m_done.Reset();
CGUIDialogBusy::WaitOnEvent(m_done, 100, false);
}

void CPVRRefreshTimelineItemsThread::Process()
Expand All @@ -567,12 +598,19 @@ void CPVRRefreshTimelineItemsThread::Process()

while (!m_bStop)
{
m_done.Reset();

if (m_pGuideWindow->RefreshTimelineItems() && !m_bStop)
{
CGUIMessage m(GUI_MSG_REFRESH_LIST, m_pGuideWindow->GetID(), 0, ObservableMessageEpg);
KODI::MESSAGING::CApplicationMessenger::GetInstance().SendGUIMessage(m);
}

if (m_bStop)
break;

m_done.Set();

// in order to fill the guide window asap, use a short update interval until we the
// same amount of epg events for BOOSTED_SLEEPS_THRESHOLD + 1 times in a row .
if (iUpdatesWithoutChange < BOOSTED_SLEEPS_THRESHOLD)
Expand All @@ -586,11 +624,16 @@ void CPVRRefreshTimelineItemsThread::Process()

iLastEpgItemsCount = iCurrentEpgItemsCount;

Sleep(1000); // boosted update cycle
m_ready.WaitMSec(1000); // boosted update cycle
}
else
{
Sleep(5000); // normal update cycle
m_ready.WaitMSec(5000); // normal update cycle
}

m_ready.Reset();
}

m_ready.Reset();
m_done.Set();
}
6 changes: 6 additions & 0 deletions xbmc/pvr/windows/GUIWindowPVRGuide.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <atomic>
#include <memory>
#include "threads/Event.h"
#include "threads/Thread.h"
#include "pvr/PVRChannelNumberInputHandler.h"
#include "GUIWindowPVRBase.h"
Expand Down Expand Up @@ -96,7 +97,12 @@ namespace PVR

virtual void Process();

void DoRefresh();
void Stop();

private:
CGUIWindowPVRGuide *m_pGuideWindow;
CEvent m_ready;
CEvent m_done;
};
}

0 comments on commit 8a96c67

Please sign in to comment.