From 1d38357077bbe75aa88e49ae55cbae2907b2dc6d Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Mon, 8 Aug 2016 10:21:19 +0200 Subject: [PATCH 1/8] [PVR] PVRManager: Add CEventStream support. --- xbmc/pvr/PVRManager.cpp | 4 ++++ xbmc/pvr/PVRManager.h | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp index 0f9fcb4cfe303..afa362669eb0f 100644 --- a/xbmc/pvr/PVRManager.cpp +++ b/xbmc/pvr/PVRManager.cpp @@ -363,7 +363,11 @@ void CPVRManager::SetState(ManagerState state) { { CSingleLock lock(m_managerStateMutex); + if (m_managerState == state) + return; + m_managerState = state; + m_events.Publish(m_managerState); SetChanged(); } diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h index ff732aaf5fc5f..472cfd03f1b08 100644 --- a/xbmc/pvr/PVRManager.h +++ b/xbmc/pvr/PVRManager.h @@ -25,6 +25,7 @@ #include "settings/lib/ISettingCallback.h" #include "threads/Event.h" #include "threads/Thread.h" +#include "utils/EventStream.h" #include "utils/JobManager.h" #include "utils/Observer.h" @@ -569,6 +570,11 @@ namespace PVR */ bool IsChannelPreview() const; + /*! + * @brief Query the events available for CEventStream + */ + CEventStream& Events() { return m_events; } + protected: /*! * @brief Start the PVRManager, which loads all PVR data and starts some threads to update the PVR data. @@ -667,6 +673,7 @@ namespace PVR static const int m_pvrWindowIds[12]; std::atomic_bool m_isChannelPreview; + CEventSource m_events; }; class CPVRStartupJob : public CJob From cda3b3a6462026efb4b0734b75e77c8e499ab3f7 Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Sun, 7 Aug 2016 12:04:52 +0200 Subject: [PATCH 2/8] [PVR] CDirectoryProvider: Now supports async PVR startup. Fixes favorite tv and radio channels not appearing on Home screen. --- Kodi.xcodeproj/project.pbxproj | 2 ++ xbmc/listproviders/DirectoryProvider.cpp | 23 ++++++++++++++--- xbmc/listproviders/DirectoryProvider.h | 4 ++- xbmc/pvr/CMakeLists.txt | 1 + xbmc/pvr/PVRManager.h | 11 +------- xbmc/pvr/PVRManagerState.h | 33 ++++++++++++++++++++++++ 6 files changed, 60 insertions(+), 14 deletions(-) create mode 100644 xbmc/pvr/PVRManagerState.h diff --git a/Kodi.xcodeproj/project.pbxproj b/Kodi.xcodeproj/project.pbxproj index e94340a0cf756..68df9e9cec9b3 100644 --- a/Kodi.xcodeproj/project.pbxproj +++ b/Kodi.xcodeproj/project.pbxproj @@ -2597,6 +2597,7 @@ 2AC7EB591C21F6BA00BDAA95 /* GUIWindowPVRTimersBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIWindowPVRTimersBase.h; sourceTree = ""; }; 2AC7EB5E1C34892100BDAA95 /* PVRRecordingsPath.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PVRRecordingsPath.h; sourceTree = ""; }; 2AC7EB5F1C34893700BDAA95 /* PVRRecordingsPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PVRRecordingsPath.cpp; sourceTree = ""; }; + 2AE16B7A1D58B11B005C20EB /* PVRManagerState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PVRManagerState.h; sourceTree = ""; }; 2AFBB94A1CC6088000BAB340 /* GUIEPGGridContainerModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIEPGGridContainerModel.h; sourceTree = ""; }; 2AFBB94B1CC608A200BAB340 /* GUIEPGGridContainerModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIEPGGridContainerModel.cpp; sourceTree = ""; }; 2F4564D31970129A00396109 /* GUIFontCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIFontCache.cpp; sourceTree = ""; }; @@ -6974,6 +6975,7 @@ C848289E156CFCD8005A996F /* PVRGUIInfo.h */, C848289F156CFCD8005A996F /* PVRManager.cpp */, C84828A0156CFCD8005A996F /* PVRManager.h */, + 2AE16B7A1D58B11B005C20EB /* PVRManagerState.h */, 2A7B2BDB1BD6F16600044BCD /* PVRSettings.cpp */, 2A7B2BDE1BD6F18B00044BCD /* PVRSettings.h */, ); diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp index 732d5ec556fae..577578d4d2997 100644 --- a/xbmc/listproviders/DirectoryProvider.cpp +++ b/xbmc/listproviders/DirectoryProvider.cpp @@ -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" @@ -48,6 +49,7 @@ using namespace XFILE; using namespace ANNOUNCEMENT; using namespace KODI::MESSAGING; +using namespace PVR; class CDirectoryJob : public CJob { @@ -263,7 +265,7 @@ void CDirectoryProvider::Fetch(std::vector &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")) @@ -272,7 +274,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; } } @@ -300,6 +315,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); } } } @@ -393,7 +409,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; } diff --git a/xbmc/listproviders/DirectoryProvider.h b/xbmc/listproviders/DirectoryProvider.h index c12c49b8c38b4..bda3d8f877861 100644 --- a/xbmc/listproviders/DirectoryProvider.h +++ b/xbmc/listproviders/DirectoryProvider.h @@ -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" @@ -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); }; diff --git a/xbmc/pvr/CMakeLists.txt b/xbmc/pvr/CMakeLists.txt index 6569f8ab71b72..068eba0a48bf7 100644 --- a/xbmc/pvr/CMakeLists.txt +++ b/xbmc/pvr/CMakeLists.txt @@ -8,6 +8,7 @@ set(HEADERS PVRActionListener.h PVRDatabase.h PVRGUIInfo.h PVRManager.h + PVRManagerState.h PVRSettings.h) core_add_library(pvr) diff --git a/xbmc/pvr/PVRManager.h b/xbmc/pvr/PVRManager.h index 472cfd03f1b08..4be4b48cf7ae6 100644 --- a/xbmc/pvr/PVRManager.h +++ b/xbmc/pvr/PVRManager.h @@ -29,6 +29,7 @@ #include "utils/JobManager.h" #include "utils/Observer.h" +#include "pvr/PVRManagerState.h" #include "pvr/recordings/PVRRecording.h" #include @@ -61,16 +62,6 @@ namespace PVR class CPVRDatabase; class CGUIWindowPVRCommon; - enum ManagerState - { - ManagerStateError = 0, - ManagerStateStopped, - ManagerStateStarting, - ManagerStateStopping, - ManagerStateInterrupted, - ManagerStateStarted - }; - enum PlaybackType { PlaybackTypeAny = 0, diff --git a/xbmc/pvr/PVRManagerState.h b/xbmc/pvr/PVRManagerState.h new file mode 100644 index 0000000000000..d45ca12029441 --- /dev/null +++ b/xbmc/pvr/PVRManagerState.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2012-2016 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +namespace PVR +{ + enum ManagerState + { + ManagerStateError = 0, + ManagerStateStopped, + ManagerStateStarting, + ManagerStateStopping, + ManagerStateInterrupted, + ManagerStateStarted + }; +} // namespace PVR From 429fd02d24509141ea26ca6535141683f5acac82 Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Mon, 8 Aug 2016 12:11:29 +0200 Subject: [PATCH 3/8] [Estuary][PVR] Fix sort attribute and order for tv and radio channels on home screen. --- addons/skin.estuary/1080i/Home.xml | 8 ++++++-- addons/skin.estuary/1080i/Includes_Home.xml | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/skin.estuary/1080i/Home.xml b/addons/skin.estuary/1080i/Home.xml index 6653180059c3c..f776a4e4d8573 100644 --- a/addons/skin.estuary/1080i/Home.xml +++ b/addons/skin.estuary/1080i/Home.xml @@ -570,8 +570,10 @@ - + + + @@ -650,8 +652,10 @@ - + + + diff --git a/addons/skin.estuary/1080i/Includes_Home.xml b/addons/skin.estuary/1080i/Includes_Home.xml index 1d836074973cd..34341a348eac2 100644 --- a/addons/skin.estuary/1080i/Includes_Home.xml +++ b/addons/skin.estuary/1080i/Includes_Home.xml @@ -277,7 +277,7 @@ - $PARAM[content_path] + $PARAM[content_path] @@ -965,7 +965,7 @@ - $PARAM[content_path] + $PARAM[content_path] From 8e480285d131e91f3ecbca30189d87d436d5d1b1 Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Mon, 8 Aug 2016 13:01:05 +0200 Subject: [PATCH 4/8] [listproviders][PVR] CDirectoryProvider: Fix live update of lists sorted by last played, last used, play count. --- xbmc/listproviders/DirectoryProvider.cpp | 40 ++++++++++++++++-------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/xbmc/listproviders/DirectoryProvider.cpp b/xbmc/listproviders/DirectoryProvider.cpp index 577578d4d2997..185503df71fab 100644 --- a/xbmc/listproviders/DirectoryProvider.cpp +++ b/xbmc/listproviders/DirectoryProvider.cpp @@ -226,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; { @@ -240,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; + } } } From 2fcfed89945f9b9c468b9bba3f9f6a5017f35b8d Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Mon, 8 Aug 2016 17:17:08 +0200 Subject: [PATCH 5/8] [PVR] Cleanup: CPVRChannelGroupInternal no longer needs to be an Observer. Now uses new CEventStream based PVR Manager messaging. --- xbmc/pvr/PVRManager.cpp | 15 +++++---------- xbmc/pvr/channels/PVRChannelGroupInternal.cpp | 11 ++++------- xbmc/pvr/channels/PVRChannelGroupInternal.h | 9 +++++---- xbmc/utils/Observer.h | 3 +-- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/xbmc/pvr/PVRManager.cpp b/xbmc/pvr/PVRManager.cpp index afa362669eb0f..0b324200fbe6d 100644 --- a/xbmc/pvr/PVRManager.cpp +++ b/xbmc/pvr/PVRManager.cpp @@ -361,17 +361,12 @@ ManagerState CPVRManager::GetState(void) const void CPVRManager::SetState(ManagerState state) { - { - CSingleLock lock(m_managerStateMutex); - if (m_managerState == state) - return; - - m_managerState = state; - m_events.Publish(m_managerState); - SetChanged(); - } + CSingleLock lock(m_managerStateMutex); + if (m_managerState == state) + return; - NotifyObservers(ObservableMessageManagerStateChanged); + m_managerState = state; + m_events.Publish(m_managerState); } void CPVRManager::Process(void) diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp index 8aa195c4145c7..38b07cc134bcf 100644 --- a/xbmc/pvr/channels/PVRChannelGroupInternal.cpp +++ b/xbmc/pvr/channels/PVRChannelGroupInternal.cpp @@ -54,7 +54,7 @@ CPVRChannelGroupInternal::CPVRChannelGroupInternal(const CPVRChannelGroup &group CPVRChannelGroupInternal::~CPVRChannelGroupInternal(void) { Unload(); - g_PVRManager.UnregisterObserver(this); + g_PVRManager.Events().Unsubscribe(this); } bool CPVRChannelGroupInternal::Load(void) @@ -62,8 +62,7 @@ bool CPVRChannelGroupInternal::Load(void) if (CPVRChannelGroup::Load()) { UpdateChannelPaths(); - g_PVRManager.RegisterObserver(this); - + g_PVRManager.Events().Subscribe(this, &CPVRChannelGroupInternal::OnPVRManagerEvent); return true; } @@ -348,10 +347,8 @@ bool CPVRChannelGroupInternal::CreateChannelEpgs(bool bForce /* = false */) return true; } -void CPVRChannelGroupInternal::Notify(const Observable &obs, const ObservableMessage msg) +void CPVRChannelGroupInternal::OnPVRManagerEvent(const PVR::ManagerState& event) { - if (msg == ObservableMessageManagerStateChanged) - { + if (event == ManagerStateStarted) g_PVRManager.TriggerEpgsCreate(); - } } diff --git a/xbmc/pvr/channels/PVRChannelGroupInternal.h b/xbmc/pvr/channels/PVRChannelGroupInternal.h index 09d4c7e39316b..2622d7275c38a 100644 --- a/xbmc/pvr/channels/PVRChannelGroupInternal.h +++ b/xbmc/pvr/channels/PVRChannelGroupInternal.h @@ -19,7 +19,7 @@ * */ -#include "utils/Observer.h" +#include "pvr/PVRManagerState.h" #include "PVRChannelGroup.h" @@ -30,7 +30,7 @@ namespace PVR /** XBMC's internal group, the group containing all channels */ - class CPVRChannelGroupInternal : public CPVRChannelGroup, public Observer + class CPVRChannelGroupInternal : public CPVRChannelGroup { friend class CPVRChannelGroups; friend class CPVRDatabase; @@ -46,8 +46,6 @@ namespace PVR virtual ~CPVRChannelGroupInternal(void); - virtual void Notify(const Observable &obs, const ObservableMessage msg); - /** * @brief The amount of channels in this container. * @return The amount of channels in this container. @@ -154,5 +152,8 @@ namespace PVR void CreateChannelEpg(CPVRChannelPtr channel, bool bForce = false); size_t m_iHiddenChannels; /*!< the amount of hidden channels in this container */ + + private: + void OnPVRManagerEvent(const PVR::ManagerState& event); }; } diff --git a/xbmc/utils/Observer.h b/xbmc/utils/Observer.h index 87b544d7a4c02..0bcb1a3f94dfc 100644 --- a/xbmc/utils/Observer.h +++ b/xbmc/utils/Observer.h @@ -40,8 +40,7 @@ typedef enum ObservableMessageTimers, ObservableMessageTimersReset, ObservableMessageRecordings, - ObservableMessagePeripheralsChanged, - ObservableMessageManagerStateChanged + ObservableMessagePeripheralsChanged } ObservableMessage; class Observer From 503bd67c2ecf82927832489eebbdfeca1fcf6a99 Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Mon, 8 Aug 2016 19:50:03 +0200 Subject: [PATCH 6/8] [guilib] CGUIBaseContainer::UpdateListProvider : Fix item re-selection after update. --- xbmc/guilib/GUIBaseContainer.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/xbmc/guilib/GUIBaseContainer.cpp b/xbmc/guilib/GUIBaseContainer.cpp index 43aae479e24a7..fd4b096d76d7b 100644 --- a/xbmc/guilib/GUIBaseContainer.cpp +++ b/xbmc/guilib/GUIBaseContainer.cpp @@ -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(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) @@ -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(m_items.size()); i++) + { + const CGUIListItemPtr c(m_items[i]); + if (c->IsFileItem()) + { + const std::string &selectedPath = static_cast(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(); From fc0b7aa69bed48a8b45b5fd594207d48c8e19644 Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Mon, 8 Aug 2016 23:39:24 +0200 Subject: [PATCH 7/8] [PVR][Estuary] Fix home screen channel widget's start and end time when no epg available. --- addons/skin.estuary/1080i/Includes_Home.xml | 4 ++-- xbmc/GUIInfoManager.cpp | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/addons/skin.estuary/1080i/Includes_Home.xml b/addons/skin.estuary/1080i/Includes_Home.xml index 34341a348eac2..61a45e6188bdf 100644 --- a/addons/skin.estuary/1080i/Includes_Home.xml +++ b/addons/skin.estuary/1080i/Includes_Home.xml @@ -905,7 +905,7 @@ 350 260 100 - + font12 text_shadow center @@ -957,7 +957,7 @@ 350 260 100 - + font12 text_shadow center diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index 8cbe810c8b68c..335b78b2f87bc 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -10092,7 +10092,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); @@ -10115,7 +10116,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); @@ -10133,7 +10135,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); @@ -10148,7 +10151,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); From 9a51615c7539866200b41cedc40a386529bcbc6b Mon Sep 17 00:00:00 2001 From: Kai Sommerfeld Date: Tue, 9 Aug 2016 15:48:50 +0200 Subject: [PATCH 8/8] [EPG] CEpgContainer: Dramatically reduce number of ObservableMessageEpg notified, esp. when in async epg transfer mode. --- xbmc/epg/EpgContainer.cpp | 27 ++++++++++++++++++++++++++- xbmc/epg/EpgContainer.h | 7 +++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/xbmc/epg/EpgContainer.cpp b/xbmc/epg/EpgContainer.cpp index 023aa7de65cb7..349a468663462 100644 --- a/xbmc/epg/EpgContainer.cpp +++ b/xbmc/epg/EpgContainer.cpp @@ -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; @@ -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 */ @@ -172,6 +174,7 @@ void CEpgContainer::Start(bool bAsync) m_iNextEpgUpdate = 0; m_iNextEpgActiveTagCheck = 0; + m_bUpdateNotificationPending = false; } LoadFromDB(); @@ -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); @@ -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) { diff --git a/xbmc/epg/EpgContainer.h b/xbmc/epg/EpgContainer.h index 5c0bfb9862d66..8faec15a29855 100644 --- a/xbmc/epg/EpgContainer.h +++ b/xbmc/epg/EpgContainer.h @@ -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 m_updateRequests; /*!< list of update requests triggered by addon*/ - CCriticalSection m_updateRequestsLock; /*!< protect update requests*/ + std::list 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. */ }; }