Skip to content

Commit

Permalink
Merge pull request #10248 from ksooo/pvr-fix-directorylistprovider
Browse files Browse the repository at this point in the history
[PVR] CDirectoryProvider now supports async PVR startup. Fixes favori…
  • Loading branch information
ksooo committed Aug 10, 2016
2 parents 2a199ed + 9a51615 commit d66b47f
Show file tree
Hide file tree
Showing 16 changed files with 183 additions and 59 deletions.
2 changes: 2 additions & 0 deletions Kodi.xcodeproj/project.pbxproj
Expand Up @@ -2597,6 +2597,7 @@
2AC7EB591C21F6BA00BDAA95 /* GUIWindowPVRTimersBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowPVRTimersBase.h; sourceTree = "<group>"; };
2AC7EB5E1C34892100BDAA95 /* PVRRecordingsPath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PVRRecordingsPath.h; sourceTree = "<group>"; };
2AC7EB5F1C34893700BDAA95 /* PVRRecordingsPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PVRRecordingsPath.cpp; sourceTree = "<group>"; };
2AE16B7A1D58B11B005C20EB /* PVRManagerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PVRManagerState.h; sourceTree = "<group>"; };
2AFBB94A1CC6088000BAB340 /* GUIEPGGridContainerModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIEPGGridContainerModel.h; sourceTree = "<group>"; };
2AFBB94B1CC608A200BAB340 /* GUIEPGGridContainerModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIEPGGridContainerModel.cpp; sourceTree = "<group>"; };
2F4564D31970129A00396109 /* GUIFontCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIFontCache.cpp; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6974,6 +6975,7 @@
C848289E156CFCD8005A996F /* PVRGUIInfo.h */,
C848289F156CFCD8005A996F /* PVRManager.cpp */,
C84828A0156CFCD8005A996F /* PVRManager.h */,
2AE16B7A1D58B11B005C20EB /* PVRManagerState.h */,
2A7B2BDB1BD6F16600044BCD /* PVRSettings.cpp */,
2A7B2BDE1BD6F18B00044BCD /* PVRSettings.h */,
);
Expand Down
8 changes: 6 additions & 2 deletions addons/skin.estuary/1080i/Home.xml
Expand Up @@ -570,8 +570,10 @@
<param name="item7_vis" value="False" />
<param name="item8_vis" value="False" />
</include>
<include content="WidgetListChannels" condition="PVR.HasTVChannels">
<include content="WidgetListChannels">
<param name="content_path" value="pvr://channels/tv/All channels/"/>
<param name="sortby" value="lastplayed"/>
<param name="sortorder" value="descending"/>
<param name="widget_header" value="$LOCALIZE[31016]"/>
<param name="widget_target" value="pvr"/>
<param name="list_id" value="12200"/>
Expand Down Expand Up @@ -650,8 +652,10 @@
<param name="item7_vis" value="False" />
<param name="item8_vis" value="False" />
</include>
<include content="WidgetListChannels" condition="PVR.HasRadioChannels">
<include content="WidgetListChannels">
<param name="content_path" value="pvr://channels/radio/All channels/"/>
<param name="sortby" value="lastplayed"/>
<param name="sortorder" value="descending"/>
<param name="widget_header" value="$LOCALIZE[31018]"/>
<param name="widget_target" value="files"/>
<param name="list_id" value="13200"/>
Expand Down
8 changes: 4 additions & 4 deletions addons/skin.estuary/1080i/Includes_Home.xml
Expand Up @@ -277,7 +277,7 @@
</control>
</control>
</focusedlayout>
<content target="$PARAM[widget_target]" limit="10">$PARAM[content_path]</content>
<content sortby="$PARAM[sortby]" sortorder="$PARAM[sortorder]" target="$PARAM[widget_target]" limit="10">$PARAM[content_path]</content>
</control>
</control>
</include>
Expand Down Expand Up @@ -905,7 +905,7 @@
<top>350</top>
<width>260</width>
<height>100</height>
<label>[COLOR button_focus]$INFO[ListItem.StartTime] - $INFO[ListItem.EndTime][/COLOR][CR]$INFO[ListItem.Title]</label>
<label>[COLOR button_focus]$INFO[ListItem.StartTime,, - ]$INFO[ListItem.EndTime][/COLOR][CR]$INFO[ListItem.Title]</label>
<font>font12</font>
<shadowcolor>text_shadow</shadowcolor>
<align>center</align>
Expand Down Expand Up @@ -957,15 +957,15 @@
<top>350</top>
<width>260</width>
<height>100</height>
<label>[COLOR button_focus]$INFO[ListItem.StartTime] - $INFO[ListItem.EndTime][/COLOR][CR]$INFO[ListItem.Title]</label>
<label>[COLOR button_focus]$INFO[ListItem.StartTime,, - ]$INFO[ListItem.EndTime][/COLOR][CR]$INFO[ListItem.Title]</label>
<font>font12</font>
<shadowcolor>text_shadow</shadowcolor>
<align>center</align>
<aligny>top</aligny>
</control>
</control>
</focusedlayout>
<content target="$PARAM[widget_target]" limit="$PARAM[item_limit]">$PARAM[content_path]</content>
<content sortby="$PARAM[sortby]" sortorder="$PARAM[sortorder]" target="$PARAM[widget_target]" limit="$PARAM[item_limit]">$PARAM[content_path]</content>
</control>
</control>
</definition>
Expand Down
12 changes: 8 additions & 4 deletions xbmc/GUIInfoManager.cpp
Expand Up @@ -10101,7 +10101,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
if (item->HasPVRChannelInfoTag())
{
CEpgInfoTagPtr tag(item->GetPVRChannelInfoTag()->GetEPGNow());
return tag ? tag->StartAsLocalTime().GetAsLocalizedTime("", false) : CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false);
if (tag)
return tag->StartAsLocalTime().GetAsLocalizedTime("", false);
}
if (item->HasEPGInfoTag())
return item->GetEPGInfoTag()->StartAsLocalTime().GetAsLocalizedTime("", false);
Expand All @@ -10124,7 +10125,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
if (item->HasPVRChannelInfoTag())
{
CEpgInfoTagPtr tag(item->GetPVRChannelInfoTag()->GetEPGNow());
return tag ? tag->EndAsLocalTime().GetAsLocalizedTime("", false) : CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false);
if (tag)
return tag->EndAsLocalTime().GetAsLocalizedTime("", false);
}
else if (item->HasEPGInfoTag())
return item->GetEPGInfoTag()->EndAsLocalTime().GetAsLocalizedTime("", false);
Expand All @@ -10142,7 +10144,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
if (item->HasPVRChannelInfoTag())
{
CEpgInfoTagPtr tag(item->GetPVRChannelInfoTag()->GetEPGNow());
return tag ? tag->StartAsLocalTime().GetAsLocalizedDate(true) : CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true);
if (tag)
return tag->StartAsLocalTime().GetAsLocalizedDate(true);
}
if (item->HasEPGInfoTag())
return item->GetEPGInfoTag()->StartAsLocalTime().GetAsLocalizedDate(true);
Expand All @@ -10157,7 +10160,8 @@ std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int info, std::
if (item->HasPVRChannelInfoTag())
{
CEpgInfoTagPtr tag(item->GetPVRChannelInfoTag()->GetEPGNow());
return tag ? tag->EndAsLocalTime().GetAsLocalizedDate(true) : CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true);
if (tag)
return tag->EndAsLocalTime().GetAsLocalizedDate(true);
}
if (item->HasEPGInfoTag())
return item->GetEPGInfoTag()->EndAsLocalTime().GetAsLocalizedDate(true);
Expand Down
27 changes: 26 additions & 1 deletion xbmc/epg/EpgContainer.cpp
Expand Up @@ -43,7 +43,8 @@ using namespace EPG;
using namespace PVR;

CEpgContainer::CEpgContainer(void) :
CThread("EPGUpdater")
CThread("EPGUpdater"),
m_bUpdateNotificationPending(false)
{
m_progressHandle = NULL;
m_bStop = true;
Expand Down Expand Up @@ -114,6 +115,7 @@ void CEpgContainer::Clear(bool bClearDb /* = false */)
m_bStarted = false;
m_bIsInitialising = true;
m_iNextEpgId = 0;
m_bUpdateNotificationPending = false;
}

/* clear the database entries */
Expand Down Expand Up @@ -172,6 +174,7 @@ void CEpgContainer::Start(bool bAsync)

m_iNextEpgUpdate = 0;
m_iNextEpgActiveTagCheck = 0;
m_bUpdateNotificationPending = false;
}

LoadFromDB();
Expand Down Expand Up @@ -207,6 +210,14 @@ bool CEpgContainer::Stop(void)

void CEpgContainer::Notify(const Observable &obs, const ObservableMessage msg)
{
if (msg == ObservableMessageEpg)
{
// there can be many of these notifications during short time period. Thus, announce async and not every event.
CSingleLock lock(m_critSection);
m_bUpdateNotificationPending = true;
return;
}

SetChanged();
CSingleExit ex(m_critSection);
NotifyObservers(msg);
Expand Down Expand Up @@ -355,6 +366,20 @@ void CEpgContainer::Process(void)
if (!m_bStop)
CheckPlayingEvents();

/* check for pending update notifications */
if (!m_bStop)
{
CSingleLock lock(m_critSection);
if (m_bUpdateNotificationPending)
{
m_bUpdateNotificationPending = false;
SetChanged();

CSingleExit ex(m_critSection);
NotifyObservers(ObservableMessageEpg);
}
}

/* check for changes that need to be saved every 60 seconds */
if (iNow - iLastSave > 60)
{
Expand Down
7 changes: 5 additions & 2 deletions xbmc/epg/EpgContainer.h
Expand Up @@ -297,7 +297,10 @@ namespace EPG
CCriticalSection m_critSection; /*!< a critical section for changes to this container */
CEvent m_updateEvent; /*!< trigger when an update finishes */

std::list<SUpdateRequest> m_updateRequests; /*!< list of update requests triggered by addon*/
CCriticalSection m_updateRequestsLock; /*!< protect update requests*/
std::list<SUpdateRequest> m_updateRequests; /*!< list of update requests triggered by addon */
CCriticalSection m_updateRequestsLock; /*!< protect update requests */

private:
bool m_bUpdateNotificationPending; /*!< true while an epg updated notification to observers is pending. */
};
}
25 changes: 25 additions & 0 deletions xbmc/guilib/GUIBaseContainer.cpp
Expand Up @@ -929,11 +929,15 @@ void CGUIBaseContainer::UpdateListProvider(bool forceRefresh /* = false */)
// save the current item
int currentItem = GetSelectedItem();
CGUIListItem *current = (currentItem >= 0 && currentItem < (int)m_items.size()) ? m_items[currentItem].get() : NULL;
const std::string prevSelectedPath((current && current->IsFileItem()) ? static_cast<CFileItem *>(current)->GetPath() : "");

Reset();
m_listProvider->Fetch(m_items);
SetPageControlRange();
// update the newly selected item
bool found = false;

// first, try to re-identify selected item by comparing item pointers, though it is not guaranteed that item instances got not recreated on update.
for (int i = 0; i < (int)m_items.size(); i++)
{
if (m_items[i].get() == current)
Expand All @@ -946,6 +950,27 @@ void CGUIBaseContainer::UpdateListProvider(bool forceRefresh /* = false */)
}
}
}
if (!found && !prevSelectedPath.empty())
{
// as fallback, try to re-identify selected item by comparing item paths.
for (int i = 0; i < static_cast<int>(m_items.size()); i++)
{
const CGUIListItemPtr c(m_items[i]);
if (c->IsFileItem())
{
const std::string &selectedPath = static_cast<CFileItem *>(c.get())->GetPath();
if (selectedPath == prevSelectedPath)
{
found = true;
if (i != currentItem)
{
SelectItem(i);
break;
}
}
}
}
}
if (!found && currentItem >= (int)m_items.size())
SelectItem(m_items.size()-1);
SetInvalid();
Expand Down
63 changes: 47 additions & 16 deletions xbmc/listproviders/DirectoryProvider.cpp
Expand Up @@ -33,6 +33,7 @@
#include "music/dialogs/GUIDialogMusicInfo.h"
#include "music/MusicThumbLoader.h"
#include "pictures/PictureThumbLoader.h"
#include "pvr/PVRManager.h"
#include "settings/Settings.h"
#include "threads/SingleLock.h"
#include "utils/JobManager.h"
Expand All @@ -48,6 +49,7 @@
using namespace XFILE;
using namespace ANNOUNCEMENT;
using namespace KODI::MESSAGING;
using namespace PVR;

class CDirectoryJob : public CJob
{
Expand Down Expand Up @@ -224,8 +226,8 @@ bool CDirectoryProvider::Update(bool forceRefresh)

void CDirectoryProvider::Announce(AnnouncementFlag flag, const char *sender, const char *message, const CVariant &data)
{
// we are only interested in library changes
if ((flag & (VideoLibrary | AudioLibrary)) == 0)
// we are only interested in library and player changes
if ((flag & (VideoLibrary | AudioLibrary | Player)) == 0)
return;

{
Expand All @@ -238,17 +240,31 @@ void CDirectoryProvider::Announce(AnnouncementFlag flag, const char *sender, con
(std::find(m_itemTypes.begin(), m_itemTypes.end(), InfoTagType::AUDIO) == m_itemTypes.end())))
return;

// if we're in a database transaction, don't bother doing anything just yet
if (data.isMember("transaction") && data["transaction"].asBoolean())
return;

// if there was a database update, we set the update state
// to PENDING to fire off a new job in the next update
if (strcmp(message, "OnScanFinished") == 0 ||
strcmp(message, "OnCleanFinished") == 0 ||
strcmp(message, "OnUpdate") == 0 ||
strcmp(message, "OnRemove") == 0)
m_updateState = INVALIDATED;
if (flag & Player)
{
if (strcmp(message, "OnPlay") == 0 ||
strcmp(message, "OnStop") == 0)
{
if (m_currentSort.sortBy == SortByLastPlayed ||
m_currentSort.sortBy == SortByPlaycount ||
m_currentSort.sortBy == SortByLastUsed)
m_updateState = INVALIDATED;
}
}
else
{
// if we're in a database transaction, don't bother doing anything just yet
if (data.isMember("transaction") && data["transaction"].asBoolean())
return;

// if there was a database update, we set the update state
// to PENDING to fire off a new job in the next update
if (strcmp(message, "OnScanFinished") == 0 ||
strcmp(message, "OnCleanFinished") == 0 ||
strcmp(message, "OnUpdate") == 0 ||
strcmp(message, "OnRemove") == 0)
m_updateState = INVALIDATED;
}
}
}

Expand All @@ -263,7 +279,7 @@ void CDirectoryProvider::Fetch(std::vector<CGUIListItemPtr> &items) const
}
}

void CDirectoryProvider::OnEvent(const ADDON::AddonEvent& event)
void CDirectoryProvider::OnAddonEvent(const ADDON::AddonEvent& event)
{
CSingleLock lock(m_section);
if (URIUtils::IsProtocol(m_currentUrl, "addons"))
Expand All @@ -272,7 +288,20 @@ void CDirectoryProvider::OnEvent(const ADDON::AddonEvent& event)
typeid(event) == typeid(ADDON::AddonEvents::Disabled) ||
typeid(event) == typeid(ADDON::AddonEvents::InstalledChanged) ||
typeid(event) == typeid(ADDON::AddonEvents::MetadataChanged))
m_updateState = INVALIDATED;
m_updateState = INVALIDATED;
}
}

void CDirectoryProvider::OnPVRManagerEvent(const PVR::ManagerState& event)
{
CSingleLock lock(m_section);
if (URIUtils::IsProtocol(m_currentUrl, "pvr"))
{
if (event == ManagerStateStarted ||
event == ManagerStateStopped ||
event == ManagerStateError ||
event == ManagerStateInterrupted)
m_updateState = INVALIDATED;
}
}

Expand Down Expand Up @@ -300,6 +329,7 @@ void CDirectoryProvider::Reset(bool immediately /* = false */)
m_isAnnounced = false;
CAnnouncementManager::GetInstance().RemoveAnnouncer(this);
ADDON::CAddonMgr::GetInstance().Events().Unsubscribe(this);
g_PVRManager.Events().Unsubscribe(this);
}
}
}
Expand Down Expand Up @@ -393,7 +423,8 @@ bool CDirectoryProvider::UpdateURL()
{
m_isAnnounced = true;
CAnnouncementManager::GetInstance().AddAnnouncer(this);
ADDON::CAddonMgr::GetInstance().Events().Subscribe(this, &CDirectoryProvider::OnEvent);
ADDON::CAddonMgr::GetInstance().Events().Subscribe(this, &CDirectoryProvider::OnAddonEvent);
g_PVRManager.Events().Subscribe(this, &CDirectoryProvider::OnPVRManagerEvent);
}
return true;
}
Expand Down
4 changes: 3 additions & 1 deletion xbmc/listproviders/DirectoryProvider.h
Expand Up @@ -25,6 +25,7 @@
#include "addons/AddonEvents.h"
#include "IListProvider.h"
#include "guilib/GUIStaticItem.h"
#include "pvr/PVRManagerState.h"
#include "utils/Job.h"
#include "threads/CriticalSection.h"
#include "interfaces/IAnnouncer.h"
Expand Down Expand Up @@ -87,5 +88,6 @@ class CDirectoryProvider :
bool UpdateURL();
bool UpdateLimit();
bool UpdateSort();
void OnEvent(const ADDON::AddonEvent& event);
void OnAddonEvent(const ADDON::AddonEvent& event);
void OnPVRManagerEvent(const PVR::ManagerState& event);
};
1 change: 1 addition & 0 deletions xbmc/pvr/CMakeLists.txt
Expand Up @@ -8,6 +8,7 @@ set(HEADERS PVRActionListener.h
PVRDatabase.h
PVRGUIInfo.h
PVRManager.h
PVRManagerState.h
PVRSettings.h)

core_add_library(pvr)
11 changes: 5 additions & 6 deletions xbmc/pvr/PVRManager.cpp
Expand Up @@ -361,13 +361,12 @@ ManagerState CPVRManager::GetState(void) const

void CPVRManager::SetState(ManagerState state)
{
{
CSingleLock lock(m_managerStateMutex);
m_managerState = state;
SetChanged();
}
CSingleLock lock(m_managerStateMutex);
if (m_managerState == state)
return;

NotifyObservers(ObservableMessageManagerStateChanged);
m_managerState = state;
m_events.Publish(m_managerState);
}

void CPVRManager::Process(void)
Expand Down

0 comments on commit d66b47f

Please sign in to comment.