Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PVR] Guide window: Fix selection after channelgroup switching #11879

Merged
merged 3 commits into from
Mar 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
};
}