[video] fix selection after changing video or extra art
[xbmc.git] / xbmc / pvr / PVRChannelNumberInputHandler.cpp
bloba57c774096d4e6fab8e049b8184b09db17493bca
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 "PVRChannelNumberInputHandler.h"
11 #include "ServiceBroker.h"
12 #include "settings/AdvancedSettings.h"
13 #include "settings/SettingsComponent.h"
14 #include "utils/StringUtils.h"
16 #include <algorithm>
17 #include <cstdlib>
18 #include <mutex>
19 #include <string>
21 using namespace PVR;
22 using namespace std::chrono_literals;
24 CPVRChannelNumberInputHandler::CPVRChannelNumberInputHandler()
25 : CPVRChannelNumberInputHandler(CServiceBroker::GetSettingsComponent()
26 ->GetAdvancedSettings()
27 ->m_iPVRNumericChannelSwitchTimeout,
28 CHANNEL_NUMBER_INPUT_MAX_DIGITS)
32 CPVRChannelNumberInputHandler::CPVRChannelNumberInputHandler(
33 int iDelay, int iMaxDigits /* = CHANNEL_NUMBER_INPUT_MAX_DIGITS */)
34 : m_iDelay(iDelay), m_iMaxDigits(iMaxDigits), m_timer(this)
38 void CPVRChannelNumberInputHandler::OnTimeout()
40 if (m_inputBuffer.empty())
42 std::unique_lock<CCriticalSection> lock(m_mutex);
43 SetLabel("");
45 else
47 // call the overridden worker method
48 OnInputDone();
50 std::unique_lock<CCriticalSection> lock(m_mutex);
52 // erase input buffer immediately , but...
53 m_inputBuffer.erase();
55 // ... display the label for another .5 secs if we stopped the timer before regular timeout.
56 if (m_timer.IsRunning())
57 SetLabel("");
58 else
59 m_timer.Start(500ms);
63 void CPVRChannelNumberInputHandler::ExecuteAction()
65 m_timer.Stop(true /* wait until worker thread ended */);
66 OnTimeout();
69 bool CPVRChannelNumberInputHandler::CheckInputAndExecuteAction()
71 const CPVRChannelNumber channelNumber = GetChannelNumber();
72 if (channelNumber.IsValid())
74 // we have a valid channel number; execute the associated action now.
75 ExecuteAction();
76 return true;
78 return false;
81 void CPVRChannelNumberInputHandler::AppendChannelNumberCharacter(char cCharacter)
83 if (cCharacter != CPVRChannelNumber::SEPARATOR && (cCharacter < '0' || cCharacter > '9'))
84 return;
86 std::unique_lock<CCriticalSection> lock(m_mutex);
88 if (cCharacter == CPVRChannelNumber::SEPARATOR)
90 // no leading separator
91 if (m_inputBuffer.empty())
92 return;
94 // max one separator
95 if (m_inputBuffer.find(CPVRChannelNumber::SEPARATOR) != std::string::npos)
96 return;
99 if (m_inputBuffer.size() == static_cast<size_t>(m_iMaxDigits))
101 m_inputBuffer.erase(m_inputBuffer.begin());
102 SetLabel(m_inputBuffer);
104 else if (m_inputBuffer.empty())
106 m_sortedChannelNumbers.clear();
107 GetChannelNumbers(m_sortedChannelNumbers);
109 std::sort(m_sortedChannelNumbers.begin(), m_sortedChannelNumbers.end());
112 m_inputBuffer.append(&cCharacter, 1);
113 SetLabel(m_inputBuffer);
115 for (auto it = m_sortedChannelNumbers.begin(); it != m_sortedChannelNumbers.end();)
117 const std::string channel = *it;
118 ++it;
120 if (StringUtils::StartsWith(channel, m_inputBuffer))
122 if (it != m_sortedChannelNumbers.end() && StringUtils::StartsWith(*it, m_inputBuffer))
124 // there are alternative numbers; wait for more input
125 break;
128 // no alternatives; complete the number and fire immediately
129 m_inputBuffer = channel;
130 SetLabel(m_inputBuffer);
131 ExecuteAction();
132 return;
136 if (!m_timer.IsRunning())
137 m_timer.Start(std::chrono::milliseconds(m_iDelay));
138 else
139 m_timer.Restart();
142 CPVRChannelNumber CPVRChannelNumberInputHandler::GetChannelNumber() const
144 int iChannelNumber = 0;
145 int iSubChannelNumber = 0;
147 std::unique_lock<CCriticalSection> lock(m_mutex);
149 size_t pos = m_inputBuffer.find(CPVRChannelNumber::SEPARATOR);
150 if (pos != std::string::npos)
152 // main + sub
153 if (pos != 0)
155 iChannelNumber = std::atoi(m_inputBuffer.substr(0, pos).c_str());
156 if (pos != m_inputBuffer.size() - 1)
157 iSubChannelNumber = std::atoi(m_inputBuffer.substr(pos + 1).c_str());
160 else
162 // only main
163 iChannelNumber = std::atoi(m_inputBuffer.c_str());
166 return CPVRChannelNumber(iChannelNumber, iSubChannelNumber);
169 bool CPVRChannelNumberInputHandler::HasChannelNumber() const
171 return !m_inputBuffer.empty();
174 std::string CPVRChannelNumberInputHandler::GetChannelNumberLabel() const
176 std::unique_lock<CCriticalSection> lock(m_mutex);
177 return m_label;
180 void CPVRChannelNumberInputHandler::SetLabel(const std::string& label)
182 std::unique_lock<CCriticalSection> lock(m_mutex);
183 if (label != m_label)
185 m_label = label;
187 // inform subscribers
188 m_events.Publish(PVRChannelNumberInputChangedEvent(m_label));