diff options
Diffstat (limited to 'xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp')
-rw-r--r-- | xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp new file mode 100644 index 0000000..b5830d4 --- /dev/null +++ b/xbmc/pvr/dialogs/GUIDialogPVRChannelsOSD.cpp @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2012-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "GUIDialogPVRChannelsOSD.h" + +#include "FileItem.h" +#include "GUIInfoManager.h" +#include "ServiceBroker.h" +#include "guilib/GUIComponent.h" +#include "guilib/GUIMessage.h" +#include "input/actions/Action.h" +#include "input/actions/ActionIDs.h" +#include "messaging/ApplicationMessenger.h" +#include "pvr/PVRManager.h" +#include "pvr/PVRPlaybackState.h" +#include "pvr/channels/PVRChannel.h" +#include "pvr/channels/PVRChannelGroupMember.h" +#include "pvr/channels/PVRChannelGroups.h" +#include "pvr/channels/PVRChannelGroupsContainer.h" +#include "pvr/epg/EpgContainer.h" +#include "pvr/guilib/PVRGUIActionsChannels.h" +#include "pvr/guilib/PVRGUIActionsPlayback.h" +#include "settings/Settings.h" +#include "settings/SettingsComponent.h" + +#include <memory> +#include <string> +#include <vector> + +using namespace PVR; + +using namespace std::chrono_literals; + +#define MAX_INVALIDATION_FREQUENCY 2000ms // limit to one invalidation per X milliseconds + +CGUIDialogPVRChannelsOSD::CGUIDialogPVRChannelsOSD() + : CGUIDialogPVRItemsViewBase(WINDOW_DIALOG_PVR_OSD_CHANNELS, "DialogPVRChannelsOSD.xml") +{ + CServiceBroker::GetPVRManager().Get<PVR::GUI::Channels>().RegisterChannelNumberInputHandler(this); +} + +CGUIDialogPVRChannelsOSD::~CGUIDialogPVRChannelsOSD() +{ + auto& mgr = CServiceBroker::GetPVRManager(); + mgr.Events().Unsubscribe(this); + mgr.Get<PVR::GUI::Channels>().DeregisterChannelNumberInputHandler(this); +} + +bool CGUIDialogPVRChannelsOSD::OnMessage(CGUIMessage& message) +{ + if (message.GetMessage() == GUI_MSG_REFRESH_LIST) + { + switch (static_cast<PVREvent>(message.GetParam1())) + { + case PVREvent::CurrentItem: + m_viewControl.SetItems(*m_vecItems); + return true; + + case PVREvent::Epg: + case PVREvent::EpgContainer: + case PVREvent::EpgActiveItem: + if (IsActive()) + SetInvalid(); + return true; + + default: + break; + } + } + return CGUIDialogPVRItemsViewBase::OnMessage(message); +} + +void CGUIDialogPVRChannelsOSD::OnInitWindow() +{ + if (!CServiceBroker::GetPVRManager().PlaybackState()->IsPlayingTV() && + !CServiceBroker::GetPVRManager().PlaybackState()->IsPlayingRadio()) + { + Close(); + return; + } + + Init(); + Update(); + CGUIDialogPVRItemsViewBase::OnInitWindow(); +} + +void CGUIDialogPVRChannelsOSD::OnDeinitWindow(int nextWindowID) +{ + if (m_group) + { + CServiceBroker::GetPVRManager().Get<PVR::GUI::Channels>().SetSelectedChannelPath( + m_group->IsRadio(), m_viewControl.GetSelectedItemPath()); + + // next OnInitWindow will set the group which is then selected + m_group.reset(); + } + + CGUIDialogPVRItemsViewBase::OnDeinitWindow(nextWindowID); +} + +bool CGUIDialogPVRChannelsOSD::OnAction(const CAction& action) +{ + switch (action.GetID()) + { + case ACTION_SELECT_ITEM: + case ACTION_MOUSE_LEFT_CLICK: + { + // If direct channel number input is active, select the entered channel. + if (CServiceBroker::GetPVRManager() + .Get<PVR::GUI::Channels>() + .GetChannelNumberInputHandler() + .CheckInputAndExecuteAction()) + return true; + + if (m_viewControl.HasControl(GetFocusedControlID())) + { + // Switch to channel + GotoChannel(m_viewControl.GetSelectedItem()); + return true; + } + break; + } + case ACTION_PREVIOUS_CHANNELGROUP: + case ACTION_NEXT_CHANNELGROUP: + { + // save control states and currently selected item of group + SaveControlStates(); + + // switch to next or previous group + const CPVRChannelGroups* groups = + CServiceBroker::GetPVRManager().ChannelGroups()->Get(m_group->IsRadio()); + const std::shared_ptr<CPVRChannelGroup> nextGroup = action.GetID() == ACTION_NEXT_CHANNELGROUP + ? groups->GetNextGroup(*m_group) + : groups->GetPreviousGroup(*m_group); + CServiceBroker::GetPVRManager().PlaybackState()->SetActiveChannelGroup(nextGroup); + m_group = nextGroup; + Init(); + Update(); + + // restore control states and previously selected item of group + RestoreControlStates(); + return true; + } + case REMOTE_0: + case REMOTE_1: + case REMOTE_2: + case REMOTE_3: + case REMOTE_4: + case REMOTE_5: + case REMOTE_6: + case REMOTE_7: + case REMOTE_8: + case REMOTE_9: + { + AppendChannelNumberCharacter(static_cast<char>(action.GetID() - REMOTE_0) + '0'); + return true; + } + case ACTION_CHANNEL_NUMBER_SEP: + { + AppendChannelNumberCharacter(CPVRChannelNumber::SEPARATOR); + return true; + } + default: + break; + } + + return CGUIDialogPVRItemsViewBase::OnAction(action); +} + +void CGUIDialogPVRChannelsOSD::Update() +{ + CPVRManager& pvrMgr = CServiceBroker::GetPVRManager(); + pvrMgr.Events().Subscribe(this, &CGUIDialogPVRChannelsOSD::Notify); + + const std::shared_ptr<CPVRChannel> channel = pvrMgr.PlaybackState()->GetPlayingChannel(); + if (channel) + { + const std::shared_ptr<CPVRChannelGroup> group = + pvrMgr.PlaybackState()->GetActiveChannelGroup(channel->IsRadio()); + if (group) + { + const std::vector<std::shared_ptr<CPVRChannelGroupMember>> groupMembers = + group->GetMembers(CPVRChannelGroup::Include::ONLY_VISIBLE); + for (const auto& groupMember : groupMembers) + { + m_vecItems->Add(std::make_shared<CFileItem>(groupMember)); + } + + m_viewControl.SetItems(*m_vecItems); + + if (!m_group) + { + m_group = group; + m_viewControl.SetSelectedItem( + pvrMgr.Get<PVR::GUI::Channels>().GetSelectedChannelPath(channel->IsRadio())); + SaveSelectedItemPath(group->GroupID()); + } + } + } +} + +void CGUIDialogPVRChannelsOSD::SetInvalid() +{ + if (m_refreshTimeout.IsTimePast()) + { + for (const auto& item : *m_vecItems) + item->SetInvalid(); + + CGUIDialogPVRItemsViewBase::SetInvalid(); + m_refreshTimeout.Set(MAX_INVALIDATION_FREQUENCY); + } +} + +void CGUIDialogPVRChannelsOSD::SaveControlStates() +{ + CGUIDialogPVRItemsViewBase::SaveControlStates(); + + if (m_group) + SaveSelectedItemPath(m_group->GroupID()); +} + +void CGUIDialogPVRChannelsOSD::RestoreControlStates() +{ + CGUIDialogPVRItemsViewBase::RestoreControlStates(); + + if (m_group) + { + const std::string path = GetLastSelectedItemPath(m_group->GroupID()); + if (path.empty()) + m_viewControl.SetSelectedItem(0); + else + m_viewControl.SetSelectedItem(path); + } +} + +void CGUIDialogPVRChannelsOSD::GotoChannel(int iItem) +{ + if (iItem < 0 || iItem >= m_vecItems->Size()) + return; + + // Preserve the item before closing self, because this will clear m_vecItems + const std::shared_ptr<CFileItem> item = m_vecItems->Get(iItem); + + if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool( + CSettings::SETTING_PVRMENU_CLOSECHANNELOSDONSWITCH)) + Close(); + + CServiceBroker::GetPVRManager().Get<PVR::GUI::Playback>().SwitchToChannel( + *item, true /* bCheckResume */); +} + +void CGUIDialogPVRChannelsOSD::Notify(const PVREvent& event) +{ + const CGUIMessage m(GUI_MSG_REFRESH_LIST, GetID(), 0, static_cast<int>(event)); + CServiceBroker::GetAppMessenger()->SendGUIMessage(m); +} + +void CGUIDialogPVRChannelsOSD::SaveSelectedItemPath(int iGroupID) +{ + m_groupSelectedItemPaths[iGroupID] = m_viewControl.GetSelectedItemPath(); +} + +std::string CGUIDialogPVRChannelsOSD::GetLastSelectedItemPath(int iGroupID) const +{ + const auto it = m_groupSelectedItemPaths.find(iGroupID); + if (it != m_groupSelectedItemPaths.end()) + return it->second; + + return std::string(); +} + +void CGUIDialogPVRChannelsOSD::GetChannelNumbers(std::vector<std::string>& channelNumbers) +{ + if (m_group) + m_group->GetChannelNumbers(channelNumbers); +} + +void CGUIDialogPVRChannelsOSD::OnInputDone() +{ + const CPVRChannelNumber channelNumber = GetChannelNumber(); + if (channelNumber.IsValid()) + { + int itemIndex = 0; + for (const CFileItemPtr& channel : *m_vecItems) + { + if (channel->GetPVRChannelGroupMemberInfoTag()->ChannelNumber() == channelNumber) + { + m_viewControl.SetSelectedItem(itemIndex); + return; + } + ++itemIndex; + } + } +} |