[video] fix selection after changing video or extra art
[xbmc.git] / xbmc / pvr / dialogs / GUIDialogPVRChannelsOSD.cpp
blob9c079c8e7e0c1ced6ab439c525db03c74209b84d
1 /*
2 * Copyright (C) 2012-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 "GUIDialogPVRChannelsOSD.h"
11 #include "FileItem.h"
12 #include "GUIInfoManager.h"
13 #include "ServiceBroker.h"
14 #include "guilib/GUIComponent.h"
15 #include "guilib/GUIMessage.h"
16 #include "input/actions/Action.h"
17 #include "input/actions/ActionIDs.h"
18 #include "messaging/ApplicationMessenger.h"
19 #include "pvr/PVRManager.h"
20 #include "pvr/PVRPlaybackState.h"
21 #include "pvr/channels/PVRChannel.h"
22 #include "pvr/channels/PVRChannelGroupMember.h"
23 #include "pvr/channels/PVRChannelGroups.h"
24 #include "pvr/channels/PVRChannelGroupsContainer.h"
25 #include "pvr/epg/EpgContainer.h"
26 #include "pvr/guilib/PVRGUIActionsChannels.h"
27 #include "pvr/guilib/PVRGUIActionsPlayback.h"
28 #include "settings/Settings.h"
29 #include "settings/SettingsComponent.h"
31 #include <memory>
32 #include <string>
33 #include <vector>
35 using namespace PVR;
37 using namespace std::chrono_literals;
39 #define MAX_INVALIDATION_FREQUENCY 2000ms // limit to one invalidation per X milliseconds
41 CGUIDialogPVRChannelsOSD::CGUIDialogPVRChannelsOSD()
42 : CGUIDialogPVRItemsViewBase(WINDOW_DIALOG_PVR_OSD_CHANNELS, "DialogPVRChannelsOSD.xml")
44 CServiceBroker::GetPVRManager().Get<PVR::GUI::Channels>().RegisterChannelNumberInputHandler(this);
47 CGUIDialogPVRChannelsOSD::~CGUIDialogPVRChannelsOSD()
49 auto& mgr = CServiceBroker::GetPVRManager();
50 mgr.Events().Unsubscribe(this);
51 mgr.Get<PVR::GUI::Channels>().DeregisterChannelNumberInputHandler(this);
54 bool CGUIDialogPVRChannelsOSD::OnMessage(CGUIMessage& message)
56 if (message.GetMessage() == GUI_MSG_REFRESH_LIST)
58 switch (static_cast<PVREvent>(message.GetParam1()))
60 case PVREvent::CurrentItem:
61 m_viewControl.SetItems(*m_vecItems);
62 return true;
64 case PVREvent::Epg:
65 case PVREvent::EpgContainer:
66 case PVREvent::EpgActiveItem:
67 if (IsActive())
68 SetInvalid();
69 return true;
71 default:
72 break;
75 return CGUIDialogPVRItemsViewBase::OnMessage(message);
78 void CGUIDialogPVRChannelsOSD::OnInitWindow()
80 if (!CServiceBroker::GetPVRManager().PlaybackState()->IsPlayingTV() &&
81 !CServiceBroker::GetPVRManager().PlaybackState()->IsPlayingRadio())
83 Close();
84 return;
87 Init();
88 Update();
89 CGUIDialogPVRItemsViewBase::OnInitWindow();
92 void CGUIDialogPVRChannelsOSD::OnDeinitWindow(int nextWindowID)
94 if (m_group)
96 CServiceBroker::GetPVRManager().Get<PVR::GUI::Channels>().SetSelectedChannelPath(
97 m_group->IsRadio(), m_viewControl.GetSelectedItemPath());
99 // next OnInitWindow will set the group which is then selected
100 m_group.reset();
103 CGUIDialogPVRItemsViewBase::OnDeinitWindow(nextWindowID);
106 bool CGUIDialogPVRChannelsOSD::OnAction(const CAction& action)
108 switch (action.GetID())
110 case ACTION_SELECT_ITEM:
111 case ACTION_MOUSE_LEFT_CLICK:
113 // If direct channel number input is active, select the entered channel.
114 if (CServiceBroker::GetPVRManager()
115 .Get<PVR::GUI::Channels>()
116 .GetChannelNumberInputHandler()
117 .CheckInputAndExecuteAction())
118 return true;
120 if (m_viewControl.HasControl(GetFocusedControlID()))
122 // Switch to channel
123 GotoChannel(m_viewControl.GetSelectedItem());
124 return true;
126 break;
128 case ACTION_PREVIOUS_CHANNELGROUP:
129 case ACTION_NEXT_CHANNELGROUP:
131 // save control states and currently selected item of group
132 SaveControlStates();
134 // switch to next or previous group
135 const CPVRChannelGroups* groups =
136 CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_group->IsRadio());
137 const std::shared_ptr<CPVRChannelGroup> nextGroup = action.GetID() == ACTION_NEXT_CHANNELGROUP
138 ? groups->GetNextGroup(*m_group)
139 : groups->GetPreviousGroup(*m_group);
140 CServiceBroker::GetPVRManager().PlaybackState()->SetActiveChannelGroup(nextGroup);
141 m_group = nextGroup;
142 Init();
143 Update();
145 // restore control states and previously selected item of group
146 RestoreControlStates();
147 return true;
149 case REMOTE_0:
150 case REMOTE_1:
151 case REMOTE_2:
152 case REMOTE_3:
153 case REMOTE_4:
154 case REMOTE_5:
155 case REMOTE_6:
156 case REMOTE_7:
157 case REMOTE_8:
158 case REMOTE_9:
160 AppendChannelNumberCharacter(static_cast<char>(action.GetID() - REMOTE_0) + '0');
161 return true;
163 case ACTION_CHANNEL_NUMBER_SEP:
165 AppendChannelNumberCharacter(CPVRChannelNumber::SEPARATOR);
166 return true;
168 default:
169 break;
172 return CGUIDialogPVRItemsViewBase::OnAction(action);
175 void CGUIDialogPVRChannelsOSD::Update()
177 CPVRManager& pvrMgr = CServiceBroker::GetPVRManager();
178 pvrMgr.Events().Subscribe(this, &CGUIDialogPVRChannelsOSD::Notify);
180 const std::shared_ptr<const CPVRChannel> channel = pvrMgr.PlaybackState()->GetPlayingChannel();
181 if (channel)
183 const std::shared_ptr<CPVRChannelGroup> group =
184 pvrMgr.PlaybackState()->GetActiveChannelGroup(channel->IsRadio());
185 if (group)
187 const std::vector<std::shared_ptr<CPVRChannelGroupMember>> groupMembers =
188 group->GetMembers(CPVRChannelGroup::Include::ONLY_VISIBLE);
189 for (const auto& groupMember : groupMembers)
191 m_vecItems->Add(std::make_shared<CFileItem>(groupMember));
194 m_viewControl.SetItems(*m_vecItems);
196 if (!m_group)
198 m_group = group;
199 m_viewControl.SetSelectedItem(
200 pvrMgr.Get<PVR::GUI::Channels>().GetSelectedChannelPath(channel->IsRadio()));
201 SaveSelectedItemPath(group->GroupID());
207 void CGUIDialogPVRChannelsOSD::SetInvalid()
209 if (m_refreshTimeout.IsTimePast())
211 for (const auto& item : *m_vecItems)
212 item->SetInvalid();
214 CGUIDialogPVRItemsViewBase::SetInvalid();
215 m_refreshTimeout.Set(MAX_INVALIDATION_FREQUENCY);
219 void CGUIDialogPVRChannelsOSD::SaveControlStates()
221 CGUIDialogPVRItemsViewBase::SaveControlStates();
223 if (m_group)
224 SaveSelectedItemPath(m_group->GroupID());
227 void CGUIDialogPVRChannelsOSD::RestoreControlStates()
229 CGUIDialogPVRItemsViewBase::RestoreControlStates();
231 if (m_group)
233 const std::string path = GetLastSelectedItemPath(m_group->GroupID());
234 if (path.empty())
235 m_viewControl.SetSelectedItem(0);
236 else
237 m_viewControl.SetSelectedItem(path);
241 void CGUIDialogPVRChannelsOSD::GotoChannel(int iItem)
243 if (iItem < 0 || iItem >= m_vecItems->Size())
244 return;
246 // Preserve the item before closing self, because this will clear m_vecItems
247 const std::shared_ptr<CFileItem> item = m_vecItems->Get(iItem);
249 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
250 CSettings::SETTING_PVRMENU_CLOSECHANNELOSDONSWITCH))
251 Close();
253 CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().SwitchToChannel(
254 *item, true /* bCheckResume */);
257 void CGUIDialogPVRChannelsOSD::Notify(const PVREvent& event)
259 const CGUIMessage m(GUI_MSG_REFRESH_LIST, GetID(), 0, static_cast<int>(event));
260 CServiceBroker::GetAppMessenger()->SendGUIMessage(m);
263 void CGUIDialogPVRChannelsOSD::SaveSelectedItemPath(int iGroupID)
265 m_groupSelectedItemPaths[iGroupID] = m_viewControl.GetSelectedItemPath();
268 std::string CGUIDialogPVRChannelsOSD::GetLastSelectedItemPath(int iGroupID) const
270 const auto it = m_groupSelectedItemPaths.find(iGroupID);
271 if (it != m_groupSelectedItemPaths.end())
272 return it->second;
274 return std::string();
277 void CGUIDialogPVRChannelsOSD::GetChannelNumbers(std::vector<std::string>& channelNumbers)
279 if (m_group)
280 m_group->GetChannelNumbers(channelNumbers);
283 void CGUIDialogPVRChannelsOSD::OnInputDone()
285 const CPVRChannelNumber channelNumber = GetChannelNumber();
286 if (channelNumber.IsValid())
288 int itemIndex = 0;
289 for (const CFileItemPtr& channel : *m_vecItems)
291 if (channel->GetPVRChannelGroupMemberInfoTag()->ChannelNumber() == channelNumber)
293 m_viewControl.SetSelectedItem(itemIndex);
294 return;
296 ++itemIndex;