[XAudio2] share Xbox audio device enumeration with desktop and Windows 8.1 compatibility
[xbmc.git] / xbmc / platform / win10 / input / RemoteControlXbox.cpp
blob582a430a13307c519f46e0ab00e3cf5946319f95
1 /*
2 * Copyright (C) 2005-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 "RemoteControlXbox.h"
11 #include "ServiceBroker.h"
12 #include "application/AppInboundProtocol.h"
13 #include "input/remote/IRRemote.h"
14 #include "settings/AdvancedSettings.h"
15 #include "settings/SettingsComponent.h"
16 #include "utils/log.h"
18 #define XBOX_REMOTE_DEVICE_ID L"GIP:0000F50000000001"
19 #define XBOX_REMOTE_DEVICE_NAME "Xbox One Game Controller"
21 namespace winrt
23 using namespace Windows::Foundation;
25 using namespace winrt::Windows::Media;
26 using namespace winrt::Windows::System;
27 using namespace winrt::Windows::UI::Core;
29 CRemoteControlXbox::CRemoteControlXbox()
30 : m_bInitialized(false)
31 , m_repeatCount(0)
35 CRemoteControlXbox::~CRemoteControlXbox()
37 if (m_bInitialized)
38 Disconnect();
41 bool CRemoteControlXbox::IsRemoteDevice(const std::wstring &deviceId) const
43 return deviceId.compare(XBOX_REMOTE_DEVICE_ID) == 0;
46 void CRemoteControlXbox::Disconnect()
48 m_bInitialized = false;
49 auto coreWindow = CoreWindow::GetForCurrentThread();
50 if (!coreWindow) // window is destroyed already
51 return;
53 // unregister our key handler
54 coreWindow.Dispatcher().AcceleratorKeyActivated(m_token);
56 auto smtc = SystemMediaTransportControls::GetForCurrentView();
57 if (smtc)
59 smtc.ButtonPressed(m_mediatoken);
63 void CRemoteControlXbox::Initialize()
65 auto dispatcher = CoreWindow::GetForCurrentThread().Dispatcher();
66 m_token = dispatcher.AcceleratorKeyActivated([this](const CoreDispatcher& sender, const AcceleratorKeyEventArgs& args)
68 if (IsRemoteDevice(args.DeviceId().c_str()))
69 HandleAcceleratorKey(sender, args);
70 });
72 auto smtc = SystemMediaTransportControls::GetForCurrentView();
73 if (smtc)
75 m_mediatoken = smtc.ButtonPressed([this](auto&&, const SystemMediaTransportControlsButtonPressedEventArgs& args)
77 HandleMediaButton(args);
78 });
79 smtc.IsEnabled(true);
81 m_bInitialized = true;
84 void CRemoteControlXbox::HandleAcceleratorKey(const CoreDispatcher& sender, const AcceleratorKeyEventArgs& args)
86 auto button = TranslateVirtualKey(args.VirtualKey());
87 if (!button)
88 return;
90 XBMC_Event newEvent = {};
91 newEvent.type = XBMC_BUTTON;
92 newEvent.keybutton.button = button;
93 newEvent.keybutton.holdtime = 0;
95 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
97 switch (args.EventType())
99 case CoreAcceleratorKeyEventType::KeyDown:
100 case CoreAcceleratorKeyEventType::SystemKeyDown:
102 if (!args.KeyStatus().WasKeyDown) // first occurrence
104 m_firstClickTime = std::chrono::steady_clock::now();
105 if (appPort)
106 appPort->OnEvent(newEvent);
108 else
110 m_repeatCount++;
111 if (m_repeatCount > CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_remoteDelay)
113 auto now = std::chrono::steady_clock::now();
114 auto duration =
115 std::chrono::duration_cast<std::chrono::milliseconds>(now - m_firstClickTime);
117 newEvent.keybutton.holdtime = duration.count();
118 if (appPort)
119 appPort->OnEvent(newEvent);
122 break;
124 case CoreAcceleratorKeyEventType::KeyUp:
125 case CoreAcceleratorKeyEventType::SystemKeyUp:
127 m_repeatCount = 0;
128 break;
130 case CoreAcceleratorKeyEventType::Character:
131 case CoreAcceleratorKeyEventType::SystemCharacter:
132 case CoreAcceleratorKeyEventType::UnicodeCharacter:
133 case CoreAcceleratorKeyEventType::DeadCharacter:
134 case CoreAcceleratorKeyEventType::SystemDeadCharacter:
135 default:
136 break;
138 args.Handled(true);
141 void CRemoteControlXbox::HandleMediaButton(const SystemMediaTransportControlsButtonPressedEventArgs& args)
143 XBMC_Event newEvent = {};
144 newEvent.type = XBMC_BUTTON;
145 newEvent.keybutton.button = TranslateMediaKey(args.Button());
146 newEvent.keybutton.holdtime = 0;
147 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
148 if (appPort)
149 appPort->OnEvent(newEvent);
152 int32_t CRemoteControlXbox::TranslateVirtualKey(VirtualKey vk)
154 switch (vk)
156 case VirtualKey::GamepadDPadLeft:
157 return XINPUT_IR_REMOTE_LEFT;
158 case VirtualKey::GamepadDPadUp:
159 return XINPUT_IR_REMOTE_UP;
160 case VirtualKey::GamepadDPadRight:
161 return XINPUT_IR_REMOTE_RIGHT;
162 case VirtualKey::GamepadDPadDown:
163 return XINPUT_IR_REMOTE_DOWN;
164 case VirtualKey::GamepadA:
165 return XINPUT_IR_REMOTE_SELECT;
166 case VirtualKey::GamepadB:
167 return XINPUT_IR_REMOTE_BACK;
168 case VirtualKey::GamepadX:
169 return XINPUT_IR_REMOTE_CONTENTS_MENU;
170 case VirtualKey::GamepadY:
171 return XINPUT_IR_REMOTE_INFO;
172 case VirtualKey::Clear:
173 return XINPUT_IR_REMOTE_CLEAR;
174 case VirtualKey::PageDown:
175 return XINPUT_IR_REMOTE_CHANNEL_MINUS;
176 case VirtualKey::PageUp:
177 return XINPUT_IR_REMOTE_CHANNEL_PLUS;
178 case VirtualKey::Number0:
179 return XINPUT_IR_REMOTE_0;
180 case VirtualKey::Number1:
181 return XINPUT_IR_REMOTE_1;
182 case VirtualKey::Number2:
183 return XINPUT_IR_REMOTE_2;
184 case VirtualKey::Number3:
185 return XINPUT_IR_REMOTE_3;
186 case VirtualKey::Number4:
187 return XINPUT_IR_REMOTE_4;
188 case VirtualKey::Number5:
189 return XINPUT_IR_REMOTE_5;
190 case VirtualKey::Number6:
191 return XINPUT_IR_REMOTE_6;
192 case VirtualKey::Number7:
193 return XINPUT_IR_REMOTE_7;
194 case VirtualKey::Number8:
195 return XINPUT_IR_REMOTE_8;
196 case VirtualKey::Number9:
197 return XINPUT_IR_REMOTE_9;
198 case VirtualKey::Decimal:
199 return XINPUT_IR_REMOTE_STAR;
200 case VirtualKey::GamepadView:
201 return XINPUT_IR_REMOTE_DISPLAY;
202 case VirtualKey::GamepadMenu:
203 return XINPUT_IR_REMOTE_MENU;
204 default:
205 CLog::LogF(LOGDEBUG, "unknown vrtual key {}", static_cast<int>(vk));
206 return 0;
210 int32_t CRemoteControlXbox::TranslateMediaKey(SystemMediaTransportControlsButton mk)
212 switch (mk)
214 case SystemMediaTransportControlsButton::ChannelDown:
215 return XINPUT_IR_REMOTE_CHANNEL_MINUS;
216 break;
217 case SystemMediaTransportControlsButton::ChannelUp:
218 return XINPUT_IR_REMOTE_CHANNEL_PLUS;
219 case SystemMediaTransportControlsButton::FastForward:
220 return XINPUT_IR_REMOTE_FORWARD;
221 case SystemMediaTransportControlsButton::Rewind:
222 return XINPUT_IR_REMOTE_REVERSE;
223 case SystemMediaTransportControlsButton::Next:
224 return XINPUT_IR_REMOTE_SKIP_PLUS;
225 case SystemMediaTransportControlsButton::Previous:
226 return XINPUT_IR_REMOTE_SKIP_MINUS;
227 case SystemMediaTransportControlsButton::Pause:
228 return XINPUT_IR_REMOTE_PAUSE;
229 case SystemMediaTransportControlsButton::Play:
230 return XINPUT_IR_REMOTE_PLAY;
231 case SystemMediaTransportControlsButton::Stop:
232 return XINPUT_IR_REMOTE_STOP;
233 case SystemMediaTransportControlsButton::Record:
234 return XINPUT_IR_REMOTE_RECORD;
235 default:
236 return 0;