Merge pull request #25922 from sarbes/shader-cleanup
[xbmc.git] / xbmc / pvr / guilib / PVRGUIChannelNavigator.cpp
blob95ca4923e66ce9625da767e8ddd620aedb00e458
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "PVRGUIChannelNavigator.h"
11 #include "FileItem.h"
12 #include "GUIInfoManager.h"
13 #include "ServiceBroker.h"
14 #include "guilib/GUIComponent.h"
15 #include "pvr/PVRManager.h"
16 #include "pvr/PVRPlaybackState.h"
17 #include "pvr/channels/PVRChannelGroup.h"
18 #include "pvr/guilib/PVRGUIActionsPlayback.h"
19 #include "settings/Settings.h"
20 #include "settings/SettingsComponent.h"
21 #include "threads/SystemClock.h"
22 #include "utils/Job.h"
23 #include "utils/JobManager.h"
24 #include "utils/XTimeUtils.h"
26 #include <memory>
27 #include <mutex>
29 using namespace KODI::GUILIB::GUIINFO;
30 using namespace PVR;
31 using namespace std::chrono_literals;
33 namespace
35 class CPVRChannelTimeoutJobBase : public CJob, public IJobCallback
37 public:
38 CPVRChannelTimeoutJobBase() = delete;
39 CPVRChannelTimeoutJobBase(PVR::CPVRGUIChannelNavigator& channelNavigator,
40 std::chrono::milliseconds timeout)
41 : m_channelNavigator(channelNavigator)
43 m_delayTimer.Set(timeout);
46 ~CPVRChannelTimeoutJobBase() override = default;
48 virtual void OnTimeout() = 0;
50 void OnJobComplete(unsigned int iJobID, bool bSuccess, CJob* job) override {}
52 bool DoWork() override
54 while (!ShouldCancel(0, 0))
56 if (m_delayTimer.IsTimePast())
58 OnTimeout();
59 return true;
61 KODI::TIME::Sleep(10ms);
63 return false;
66 protected:
67 PVR::CPVRGUIChannelNavigator& m_channelNavigator;
69 private:
70 XbmcThreads::EndTime<> m_delayTimer;
73 class CPVRChannelEntryTimeoutJob : public CPVRChannelTimeoutJobBase
75 public:
76 CPVRChannelEntryTimeoutJob(PVR::CPVRGUIChannelNavigator& channelNavigator,
77 std::chrono::milliseconds timeout)
78 : CPVRChannelTimeoutJobBase(channelNavigator, timeout)
81 ~CPVRChannelEntryTimeoutJob() override = default;
82 const char* GetType() const override { return "pvr-channel-entry-timeout-job"; }
83 void OnTimeout() override { m_channelNavigator.SwitchToCurrentChannel(); }
86 class CPVRChannelInfoTimeoutJob : public CPVRChannelTimeoutJobBase
88 public:
89 CPVRChannelInfoTimeoutJob(PVR::CPVRGUIChannelNavigator& channelNavigator,
90 std::chrono::milliseconds timeout)
91 : CPVRChannelTimeoutJobBase(channelNavigator, timeout)
94 ~CPVRChannelInfoTimeoutJob() override = default;
95 const char* GetType() const override { return "pvr-channel-info-timeout-job"; }
96 void OnTimeout() override { m_channelNavigator.HideInfo(); }
98 } // unnamed namespace
100 CPVRGUIChannelNavigator::CPVRGUIChannelNavigator()
102 // Note: we cannot subscribe to PlayerInfoProvider here, as we're getting constructed
103 // before the info providers. We will subscribe once our first subscriber appears.
106 CPVRGUIChannelNavigator::~CPVRGUIChannelNavigator()
108 const auto gui = CServiceBroker::GetGUI();
109 if (!gui)
110 return;
112 gui->GetInfoManager().GetInfoProviders().GetPlayerInfoProvider().Events().Unsubscribe(this);
115 void CPVRGUIChannelNavigator::SubscribeToShowInfoEventStream()
117 CServiceBroker::GetGUI()
118 ->GetInfoManager()
119 .GetInfoProviders()
120 .GetPlayerInfoProvider()
121 .Events()
122 .Subscribe(this, &CPVRGUIChannelNavigator::Notify);
125 void CPVRGUIChannelNavigator::CheckAndPublishPreviewAndPlayerShowInfoChangedEvent()
127 std::unique_lock<CCriticalSection> lock(m_critSection);
129 const bool currentValue = IsPreview() && m_playerShowInfo;
130 if (m_previewAndPlayerShowInfo != currentValue)
132 m_previewAndPlayerShowInfo = currentValue;
134 // inform subscribers
135 m_events.Publish(PVRPreviewAndPlayerShowInfoChangedEvent(currentValue));
139 void CPVRGUIChannelNavigator::Notify(const PlayerShowInfoChangedEvent& event)
141 std::unique_lock<CCriticalSection> lock(m_critSection);
143 m_playerShowInfo = event.m_showInfo;
144 CheckAndPublishPreviewAndPlayerShowInfoChangedEvent();
147 void CPVRGUIChannelNavigator::SelectNextChannel(ChannelSwitchMode eSwitchMode)
149 std::unique_lock<CCriticalSection> lock(m_critSection);
151 if (!m_playerShowInfo && eSwitchMode == ChannelSwitchMode::NO_SWITCH)
153 // show info for current channel on first next channel selection.
154 ShowInfo(false);
155 return;
158 const std::shared_ptr<CPVRChannelGroupMember> nextMember = GetNextOrPrevChannel(true);
159 if (nextMember)
160 SelectChannel(nextMember, eSwitchMode);
163 void CPVRGUIChannelNavigator::SelectPreviousChannel(ChannelSwitchMode eSwitchMode)
165 std::unique_lock<CCriticalSection> lock(m_critSection);
167 if (!m_playerShowInfo && eSwitchMode == ChannelSwitchMode::NO_SWITCH)
169 // show info for current channel on first previous channel selection.
170 ShowInfo(false);
171 return;
174 const std::shared_ptr<CPVRChannelGroupMember> prevMember = GetNextOrPrevChannel(false);
175 if (prevMember)
176 SelectChannel(prevMember, eSwitchMode);
179 std::shared_ptr<CPVRChannelGroupMember> CPVRGUIChannelNavigator::GetNextOrPrevChannel(bool bNext)
181 const bool bPlayingRadio = CServiceBroker::GetPVRManager().PlaybackState()->IsPlayingRadio();
182 const bool bPlayingTV = CServiceBroker::GetPVRManager().PlaybackState()->IsPlayingTV();
184 if (bPlayingTV || bPlayingRadio)
186 const std::shared_ptr<const CPVRChannelGroup> group =
187 CServiceBroker::GetPVRManager().PlaybackState()->GetActiveChannelGroup(bPlayingRadio);
188 if (group)
190 std::unique_lock<CCriticalSection> lock(m_critSection);
191 return bNext ? group->GetNextChannelGroupMember(m_currentChannel)
192 : group->GetPreviousChannelGroupMember(m_currentChannel);
195 return {};
198 void CPVRGUIChannelNavigator::SelectChannel(
199 const std::shared_ptr<CPVRChannelGroupMember>& groupMember, ChannelSwitchMode eSwitchMode)
201 CServiceBroker::GetGUI()->GetInfoManager().SetCurrentItem(CFileItem(groupMember));
203 std::unique_lock<CCriticalSection> lock(m_critSection);
205 m_currentChannel = groupMember;
206 ShowInfo(false);
208 CheckAndPublishPreviewAndPlayerShowInfoChangedEvent();
210 if (IsPreview() && eSwitchMode == ChannelSwitchMode::INSTANT_OR_DELAYED_SWITCH)
212 auto timeout =
213 std::chrono::milliseconds(CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
214 CSettings::SETTING_PVRPLAYBACK_CHANNELENTRYTIMEOUT));
215 if (timeout > 0ms)
217 // delayed switch
218 if (m_iChannelEntryJobId >= 0)
219 CServiceBroker::GetJobManager()->CancelJob(m_iChannelEntryJobId);
221 CPVRChannelEntryTimeoutJob* job = new CPVRChannelEntryTimeoutJob(*this, timeout);
222 m_iChannelEntryJobId =
223 CServiceBroker::GetJobManager()->AddJob(job, dynamic_cast<IJobCallback*>(job));
225 else
227 // instant switch
228 SwitchToCurrentChannel();
233 void CPVRGUIChannelNavigator::SwitchToCurrentChannel()
235 std::unique_ptr<CFileItem> item;
238 std::unique_lock<CCriticalSection> lock(m_critSection);
240 if (m_iChannelEntryJobId >= 0)
242 CServiceBroker::GetJobManager()->CancelJob(m_iChannelEntryJobId);
243 m_iChannelEntryJobId = -1;
246 item = std::make_unique<CFileItem>(m_currentChannel);
249 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().SwitchToChannel(*item, false);
252 bool CPVRGUIChannelNavigator::IsPreview() const
254 std::unique_lock<CCriticalSection> lock(m_critSection);
255 return m_currentChannel != m_playingChannel;
258 bool CPVRGUIChannelNavigator::IsPreviewAndShowInfo() const
260 std::unique_lock<CCriticalSection> lock(m_critSection);
261 return m_previewAndPlayerShowInfo;
264 void CPVRGUIChannelNavigator::ShowInfo()
266 ShowInfo(true);
269 void CPVRGUIChannelNavigator::ShowInfo(bool bForce)
271 auto timeout = std::chrono::seconds(CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(
272 CSettings::SETTING_PVRMENU_DISPLAYCHANNELINFO));
274 if (bForce || timeout > 0s)
276 CServiceBroker::GetGUI()
277 ->GetInfoManager()
278 .GetInfoProviders()
279 .GetPlayerInfoProvider()
280 .SetShowInfo(true);
282 std::unique_lock<CCriticalSection> lock(m_critSection);
284 if (m_iChannelInfoJobId >= 0)
286 CServiceBroker::GetJobManager()->CancelJob(m_iChannelInfoJobId);
287 m_iChannelInfoJobId = -1;
290 if (!bForce && timeout > 0s)
292 CPVRChannelInfoTimeoutJob* job = new CPVRChannelInfoTimeoutJob(*this, timeout);
293 m_iChannelInfoJobId =
294 CServiceBroker::GetJobManager()->AddJob(job, dynamic_cast<IJobCallback*>(job));
299 void CPVRGUIChannelNavigator::HideInfo()
301 CServiceBroker::GetGUI()->GetInfoManager().GetInfoProviders().GetPlayerInfoProvider().SetShowInfo(
302 false);
304 CFileItemPtr item;
307 std::unique_lock<CCriticalSection> lock(m_critSection);
309 if (m_iChannelInfoJobId >= 0)
311 CServiceBroker::GetJobManager()->CancelJob(m_iChannelInfoJobId);
312 m_iChannelInfoJobId = -1;
315 if (m_currentChannel != m_playingChannel)
317 m_currentChannel = m_playingChannel;
318 if (m_playingChannel)
319 item = std::make_shared<CFileItem>(m_playingChannel);
322 CheckAndPublishPreviewAndPlayerShowInfoChangedEvent();
325 if (item)
326 CServiceBroker::GetGUI()->GetInfoManager().SetCurrentItem(*item);
329 void CPVRGUIChannelNavigator::ToggleInfo()
331 std::unique_lock<CCriticalSection> lock(m_critSection);
333 if (m_playerShowInfo)
334 HideInfo();
335 else
336 ShowInfo();
339 void CPVRGUIChannelNavigator::SetPlayingChannel(
340 const std::shared_ptr<CPVRChannelGroupMember>& groupMember)
342 CFileItemPtr item;
344 if (groupMember)
346 std::unique_lock<CCriticalSection> lock(m_critSection);
348 m_playingChannel = groupMember;
349 if (m_currentChannel != m_playingChannel)
351 m_currentChannel = m_playingChannel;
352 if (m_playingChannel)
353 item = std::make_shared<CFileItem>(m_playingChannel);
356 CheckAndPublishPreviewAndPlayerShowInfoChangedEvent();
359 if (item)
360 CServiceBroker::GetGUI()->GetInfoManager().SetCurrentItem(*item);
362 ShowInfo(false);
365 void CPVRGUIChannelNavigator::ClearPlayingChannel()
367 std::unique_lock<CCriticalSection> lock(m_critSection);
369 m_playingChannel.reset();
370 HideInfo();
372 CheckAndPublishPreviewAndPlayerShowInfoChangedEvent();