[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / windowing / win10 / WinEventsWin10.cpp
blobb534ff56609f84a89ba01bf55c999772164a4990
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 "WinEventsWin10.h"
11 #include "GUIUserMessages.h"
12 #include "ServiceBroker.h"
13 #include "application/AppInboundProtocol.h"
14 #include "application/Application.h"
15 #include "guilib/GUIComponent.h"
16 #include "guilib/GUIWindowManager.h"
17 #include "input/actions/Action.h"
18 #include "input/actions/ActionIDs.h"
19 #include "input/mouse/MouseStat.h"
20 #include "input/touch/generic/GenericTouchInputHandler.h"
21 #include "interfaces/AnnouncementManager.h"
22 #include "messaging/ApplicationMessenger.h"
23 #include "rendering/dx/DeviceResources.h"
24 #include "rendering/dx/RenderContext.h"
25 #include "settings/AdvancedSettings.h"
26 #include "settings/SettingsComponent.h"
27 #include "utils/SystemInfo.h"
28 #include "utils/Variant.h"
29 #include "utils/log.h"
30 #include "windowing/windows/WinKeyMap.h"
32 #include "platform/win10/input/RemoteControlXbox.h"
34 #include <winrt/Windows.Devices.Input.h>
36 namespace winrt
38 using namespace Windows::Foundation;
40 using namespace winrt::Windows::ApplicationModel::Core;
41 using namespace winrt::Windows::Devices::Input;
42 using namespace winrt::Windows::Graphics::Display;
43 using namespace winrt::Windows::Media;
44 using namespace winrt::Windows::System;
45 using namespace winrt::Windows::UI::Core;
46 using namespace winrt::Windows::UI::Input;
47 using namespace winrt::Windows::UI::ViewManagement;
49 using namespace PERIPHERALS;
51 static winrt::Point GetScreenPoint(winrt::Point point)
53 auto dpi = DX::DeviceResources::Get()->GetDpi();
54 return winrt::Point(DX::ConvertDipsToPixels(point.X, dpi), DX::ConvertDipsToPixels(point.Y, dpi));
57 CWinEventsWin10::CWinEventsWin10() = default;
58 CWinEventsWin10::~CWinEventsWin10() = default;
60 void CWinEventsWin10::InitOSKeymap(void)
62 KODI::WINDOWING::WINDOWS::DIB_InitOSKeymap();
65 void CWinEventsWin10::MessagePush(XBMC_Event *newEvent)
67 // push input events in the queue they may init modal dialog which init
68 // deeper message loop and call the deeper MessagePump from there.
69 if ( newEvent->type == XBMC_KEYDOWN
70 || newEvent->type == XBMC_KEYUP
71 || newEvent->type == XBMC_MOUSEMOTION
72 || newEvent->type == XBMC_MOUSEBUTTONDOWN
73 || newEvent->type == XBMC_MOUSEBUTTONUP
74 || newEvent->type == XBMC_TOUCH)
76 m_events.push(*newEvent);
78 else
80 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
81 if (appPort)
82 appPort->OnEvent(*newEvent);
86 bool CWinEventsWin10::MessagePump()
88 bool ret = false;
89 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
91 // processes all pending events and exits immediately
92 CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
94 XBMC_Event pumpEvent;
95 while (m_events.try_pop(pumpEvent))
97 if (appPort)
98 ret |= appPort->OnEvent(pumpEvent);
100 if (pumpEvent.type == XBMC_MOUSEBUTTONUP)
101 CServiceBroker::GetGUI()->GetWindowManager().SendMessage(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
103 return ret;
106 size_t CWinEventsWin10::GetQueueSize()
108 return m_events.unsafe_size();
111 void CWinEventsWin10::InitEventHandlers(const CoreWindow& window)
113 CWinEventsWin10::InitOSKeymap();
115 //window->SetPointerCapture();
117 // window
118 window.SizeChanged({ this, &CWinEventsWin10::OnWindowSizeChanged });
119 window.ResizeStarted({ this, &CWinEventsWin10::OnWindowResizeStarted });
120 window.ResizeCompleted({ this, &CWinEventsWin10::OnWindowResizeCompleted });
121 window.Closed({ this, &CWinEventsWin10::OnWindowClosed});
122 window.VisibilityChanged(CWinEventsWin10::OnVisibilityChanged);
123 window.Activated(CWinEventsWin10::OnWindowActivationChanged);
124 // mouse, touch and pen
125 window.PointerPressed({ this, &CWinEventsWin10::OnPointerPressed });
126 window.PointerMoved({ this, &CWinEventsWin10::OnPointerMoved });
127 window.PointerReleased({ this, &CWinEventsWin10::OnPointerReleased });
128 window.PointerExited({ this, &CWinEventsWin10::OnPointerExited });
129 window.PointerWheelChanged({ this, &CWinEventsWin10::OnPointerWheelChanged });
130 // keyboard
131 window.Dispatcher().AcceleratorKeyActivated({ this, &CWinEventsWin10::OnAcceleratorKeyActivated });
132 // display
133 DisplayInformation currentDisplayInformation = DisplayInformation::GetForCurrentView();
134 currentDisplayInformation.DpiChanged(CWinEventsWin10::OnDpiChanged);
135 currentDisplayInformation.OrientationChanged(CWinEventsWin10::OnOrientationChanged);
136 DisplayInformation::DisplayContentsInvalidated(CWinEventsWin10::OnDisplayContentsInvalidated);
137 // system
138 SystemNavigationManager sysNavManager = SystemNavigationManager::GetForCurrentView();
139 sysNavManager.BackRequested(CWinEventsWin10::OnBackRequested);
141 // requirement for backgroup playback
142 m_smtc = SystemMediaTransportControls::GetForCurrentView();
143 if (m_smtc)
145 m_smtc.IsPlayEnabled(true);
146 m_smtc.IsPauseEnabled(true);
147 m_smtc.IsStopEnabled(true);
148 m_smtc.IsRecordEnabled(true);
149 m_smtc.IsNextEnabled(true);
150 m_smtc.IsPreviousEnabled(true);
151 m_smtc.IsFastForwardEnabled(true);
152 m_smtc.IsRewindEnabled(true);
153 m_smtc.IsChannelUpEnabled(true);
154 m_smtc.IsChannelDownEnabled(true);
155 if (CSysInfo::GetWindowsDeviceFamily() != CSysInfo::WindowsDeviceFamily::Xbox)
157 m_smtc.ButtonPressed(CWinEventsWin10::OnSystemMediaButtonPressed);
159 m_smtc.IsEnabled(true);;
160 CServiceBroker::GetAnnouncementManager()->AddAnnouncer(this);
162 if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::WindowsDeviceFamily::Xbox)
164 m_remote = std::make_unique<CRemoteControlXbox>();
165 m_remote->Initialize();
169 void CWinEventsWin10::UpdateWindowSize()
171 auto size = DX::DeviceResources::Get()->GetOutputSize();
173 CLog::Log(LOGDEBUG, __FUNCTION__ ": window resize event {:f} x {:f} (as:{})", size.Width,
174 size.Height,
175 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen ? "true"
176 : "false");
178 auto appView = ApplicationView::GetForCurrentView();
179 appView.SetDesiredBoundsMode(ApplicationViewBoundsMode::UseCoreWindow);
181 // seems app has lost FS mode it may occurs if an user use core window's button
182 if (CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen && !appView.IsFullScreenMode())
183 CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_fullScreen = false;
185 XBMC_Event newEvent = {};
186 newEvent.type = XBMC_VIDEORESIZE;
187 newEvent.resize.w = size.Width;
188 newEvent.resize.h = size.Height;
189 if (g_application.GetRenderGUI() && !DX::Windowing()->IsAlteringWindow() && newEvent.resize.w > 0 && newEvent.resize.h > 0)
190 MessagePush(&newEvent);
193 void CWinEventsWin10::OnResize(float width, float height)
195 CLog::Log(LOGDEBUG, __FUNCTION__": window size changed.");
196 m_logicalWidth = width;
197 m_logicalHeight = height;
198 m_bResized = true;
200 if (m_sizeChanging)
201 return;
203 HandleWindowSizeChanged();
206 // Window event handlers.
207 void CWinEventsWin10::OnWindowSizeChanged(const CoreWindow&, const WindowSizeChangedEventArgs& args)
209 OnResize(args.Size().Width, args.Size().Height);
212 void CWinEventsWin10::OnWindowResizeStarted(const CoreWindow& sender, const winrt::IInspectable&)
214 CLog::Log(LOGDEBUG, __FUNCTION__": window resize started.");
215 m_logicalPosX = sender.Bounds().X;
216 m_logicalPosY = sender.Bounds().Y;
217 m_sizeChanging = true;
220 void CWinEventsWin10::OnWindowResizeCompleted(const CoreWindow& sender, const winrt::IInspectable&)
222 CLog::Log(LOGDEBUG, __FUNCTION__": window resize completed.");
223 m_sizeChanging = false;
225 if (m_logicalPosX != sender.Bounds().X || m_logicalPosY != sender.Bounds().Y)
226 m_bMoved = true;
228 HandleWindowSizeChanged();
231 void CWinEventsWin10::HandleWindowSizeChanged()
233 CLog::Log(LOGDEBUG, __FUNCTION__": window size/move handled.");
234 if (m_bMoved)
236 // it will get position from CoreWindow
237 DX::Windowing()->OnMove(0, 0);
239 if (m_bResized)
241 DX::Windowing()->OnResize(m_logicalWidth, m_logicalHeight);
242 UpdateWindowSize();
244 m_bResized = false;
245 m_bMoved = false;
248 void CWinEventsWin10::OnVisibilityChanged(const CoreWindow& sender, const VisibilityChangedEventArgs& args)
250 bool active = g_application.GetRenderGUI();
251 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
252 if (appPort)
253 appPort->SetRenderGUI(args.Visible());
255 if (g_application.GetRenderGUI() != active)
256 DX::Windowing()->NotifyAppActiveChange(g_application.GetRenderGUI());
257 CLog::Log(LOGDEBUG, __FUNCTION__ ": window is {}",
258 g_application.GetRenderGUI() ? "shown" : "hidden");
261 void CWinEventsWin10::OnWindowActivationChanged(const CoreWindow& sender, const WindowActivatedEventArgs& args)
263 bool active = g_application.GetRenderGUI();
264 if (args.WindowActivationState() == CoreWindowActivationState::Deactivated)
266 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
267 if (appPort)
268 appPort->SetRenderGUI(DX::Windowing()->WindowedMode());
270 else if (args.WindowActivationState() == CoreWindowActivationState::PointerActivated
271 || args.WindowActivationState() == CoreWindowActivationState::CodeActivated)
273 std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
274 if (appPort)
275 appPort->SetRenderGUI(true);
277 if (g_application.GetRenderGUI() != active)
278 DX::Windowing()->NotifyAppActiveChange(g_application.GetRenderGUI());
280 if (CServiceBroker::IsLoggingUp())
281 CLog::Log(LOGDEBUG, __FUNCTION__ ": window is {}",
282 g_application.GetRenderGUI() ? "active" : "inactive");
285 void CWinEventsWin10::OnWindowClosed(const CoreWindow& sender, const CoreWindowEventArgs& args)
287 // send quit command to the application if it's still running
288 if (!g_application.m_bStop)
290 XBMC_Event newEvent = {};
291 newEvent.type = XBMC_QUIT;
292 MessagePush(&newEvent);
296 void CWinEventsWin10::OnPointerPressed(const CoreWindow&, const PointerEventArgs& args)
298 XBMC_Event newEvent = {};
300 PointerPoint point = args.CurrentPoint();
301 auto position = GetScreenPoint(point.Position());
303 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
305 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputDown, position.X, position.Y, point.Timestamp(), 0, 10);
306 return;
308 else
310 newEvent.type = XBMC_MOUSEBUTTONDOWN;
311 newEvent.button.x = position.X;
312 newEvent.button.y = position.Y;
313 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Mouse)
315 if (point.Properties().IsLeftButtonPressed())
316 newEvent.button.button = XBMC_BUTTON_LEFT;
317 else if (point.Properties().IsMiddleButtonPressed())
318 newEvent.button.button = XBMC_BUTTON_MIDDLE;
319 else if (point.Properties().IsRightButtonPressed())
320 newEvent.button.button = XBMC_BUTTON_RIGHT;
322 else if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Pen)
324 // pen
325 // TODO
328 MessagePush(&newEvent);
331 void CWinEventsWin10::OnPointerMoved(const CoreWindow&, const PointerEventArgs& args)
333 PointerPoint point = args.CurrentPoint();
334 auto position = GetScreenPoint(point.Position());
336 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
338 if (point.IsInContact())
340 CGenericTouchInputHandler::GetInstance().UpdateTouchPointer(0, position.X, position.Y, point.Timestamp(), 10.f);
341 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputMove, position.X, position.Y, point.Timestamp(), 0, 10.f);
343 return;
346 XBMC_Event newEvent = {};
347 newEvent.type = XBMC_MOUSEMOTION;
348 newEvent.motion.x = position.X;
349 newEvent.motion.y = position.Y;
350 MessagePush(&newEvent);
353 void CWinEventsWin10::OnPointerReleased(const CoreWindow&, const PointerEventArgs& args)
355 PointerPoint point = args.CurrentPoint();
356 auto position = GetScreenPoint(point.Position());
358 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
360 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputUp, position.X, position.Y, point.Timestamp(), 0, 10);
361 return;
364 XBMC_Event newEvent = {};
365 newEvent.type = XBMC_MOUSEBUTTONUP;
366 newEvent.button.x = position.X;
367 newEvent.button.y = position.Y;
369 if (point.Properties().PointerUpdateKind() == PointerUpdateKind::LeftButtonReleased)
370 newEvent.button.button = XBMC_BUTTON_LEFT;
371 else if (point.Properties().PointerUpdateKind() == PointerUpdateKind::MiddleButtonReleased)
372 newEvent.button.button = XBMC_BUTTON_MIDDLE;
373 else if (point.Properties().PointerUpdateKind() == PointerUpdateKind::RightButtonReleased)
374 newEvent.button.button = XBMC_BUTTON_RIGHT;
376 MessagePush(&newEvent);
379 void CWinEventsWin10::OnPointerExited(const CoreWindow&, const PointerEventArgs& args)
381 const PointerPoint& point = args.CurrentPoint();
382 auto position = GetScreenPoint(point.Position());
384 if (point.PointerDevice().PointerDeviceType() == PointerDeviceType::Touch)
386 CGenericTouchInputHandler::GetInstance().HandleTouchInput(TouchInputAbort, position.X, position.Y, point.Timestamp(), 0, 10);
390 void CWinEventsWin10::OnPointerWheelChanged(const CoreWindow&, const PointerEventArgs& args)
392 XBMC_Event newEvent = {};
393 newEvent.type = XBMC_MOUSEBUTTONDOWN;
394 newEvent.button.x = args.CurrentPoint().Position().X;
395 newEvent.button.y = args.CurrentPoint().Position().Y;
396 newEvent.button.button = args.CurrentPoint().Properties().MouseWheelDelta() > 0 ? XBMC_BUTTON_WHEELUP : XBMC_BUTTON_WHEELDOWN;
397 MessagePush(&newEvent);
398 newEvent.type = XBMC_MOUSEBUTTONUP;
399 MessagePush(&newEvent);
402 void CWinEventsWin10::Kodi_KeyEvent(unsigned int vkey, unsigned scancode, unsigned keycode, bool isDown)
404 using State = CoreVirtualKeyStates;
406 XBMC_keysym keysym = {};
407 keysym.scancode = scancode;
408 keysym.sym = KODI::WINDOWING::WINDOWS::VK_keymap[vkey];
409 keysym.unicode = keycode;
411 auto window = CoreWindow::GetForCurrentThread();
413 uint16_t mod = (uint16_t)XBMCKMOD_NONE;
414 // If left control and right alt are down this usually means that AltGr is down
415 if ((window.GetKeyState(VirtualKey::LeftControl) & State::Down) == State::Down
416 && (window.GetKeyState(VirtualKey::RightMenu) & State::Down) == State::Down)
418 mod |= XBMCKMOD_MODE;
419 mod |= XBMCKMOD_MODE;
421 else
423 if ((window.GetKeyState(VirtualKey::LeftControl) & State::Down) == State::Down)
424 mod |= XBMCKMOD_LCTRL;
425 if ((window.GetKeyState(VirtualKey::RightMenu) & State::Down) == State::Down)
426 mod |= XBMCKMOD_RALT;
429 // Check the remaining modifiers
430 if ((window.GetKeyState(VirtualKey::LeftShift) & State::Down) == State::Down)
431 mod |= XBMCKMOD_LSHIFT;
432 if ((window.GetKeyState(VirtualKey::RightShift) & State::Down) == State::Down)
433 mod |= XBMCKMOD_RSHIFT;
434 if ((window.GetKeyState(VirtualKey::RightControl) & State::Down) == State::Down)
435 mod |= XBMCKMOD_RCTRL;
436 if ((window.GetKeyState(VirtualKey::LeftMenu) & State::Down) == State::Down)
437 mod |= XBMCKMOD_LALT;
438 if ((window.GetKeyState(VirtualKey::LeftWindows) & State::Down) == State::Down)
439 mod |= XBMCKMOD_LSUPER;
440 if ((window.GetKeyState(VirtualKey::RightWindows) & State::Down) == State::Down)
441 mod |= XBMCKMOD_LSUPER;
443 keysym.mod = static_cast<XBMCMod>(mod);
445 XBMC_Event newEvent = {};
446 newEvent.type = isDown ? XBMC_KEYDOWN : XBMC_KEYUP;
447 newEvent.key.keysym = keysym;
448 MessagePush(&newEvent);
451 void CWinEventsWin10::OnAcceleratorKeyActivated(const CoreDispatcher&, const AcceleratorKeyEventArgs& args)
453 static auto lockedState = CoreVirtualKeyStates::Locked;
454 static VirtualKey keyStore = VirtualKey::None;
456 // skip if device is remote control
457 if (m_remote && m_remote->IsRemoteDevice(args.DeviceId().c_str()))
458 return;
460 bool isDown = false;
461 unsigned keyCode = 0;
462 unsigned vk = static_cast<unsigned>(args.VirtualKey());
464 auto window = CoreWindow::GetForCurrentThread();
465 bool numLockLocked = ((window.GetKeyState(VirtualKey::NumberKeyLock) & lockedState) == lockedState);
467 switch (args.EventType())
469 case CoreAcceleratorKeyEventType::KeyDown:
470 case CoreAcceleratorKeyEventType::SystemKeyDown:
472 if ( (vk == 0x08) // VK_BACK
473 || (vk == 0x09) // VK_TAB
474 || (vk == 0x0C) // VK_CLEAR
475 || (vk == 0x0D) // VK_RETURN
476 || (vk == 0x1B) // VK_ESCAPE
477 || (vk == 0x20) // VK_SPACE
478 || (vk >= 0x30 && vk <= 0x39) // numeric keys
479 || (vk >= 0x41 && vk <= 0x5A) // alphabetic keys
480 || (vk >= 0x60 && vk <= 0x69 && numLockLocked) // keypad numeric (if numlock is on)
481 || (vk >= 0x6A && vk <= 0x6F) // keypad keys except numeric
482 || (vk >= 0x92 && vk <= 0x96) // OEM specific
483 || (vk >= 0xBA && vk <= 0xC0) // OEM specific
484 || (vk >= 0xDB && vk <= 0xDF) // OEM specific
485 || (vk >= 0xE1 && vk <= 0xF5 && vk != 0xE5 && vk != 0xE7 && vk != 0xE8) // OEM specific
488 // store this for character events, because VirtualKey is key code on character event.
489 keyStore = args.VirtualKey();
490 return;
492 isDown = true;
493 break;
495 case CoreAcceleratorKeyEventType::KeyUp:
496 case CoreAcceleratorKeyEventType::SystemKeyUp:
497 break;
498 case CoreAcceleratorKeyEventType::Character:
499 case CoreAcceleratorKeyEventType::SystemCharacter:
500 case CoreAcceleratorKeyEventType::UnicodeCharacter:
501 case CoreAcceleratorKeyEventType::DeadCharacter:
502 case CoreAcceleratorKeyEventType::SystemDeadCharacter:
504 // VirtualKey is KeyCode
505 keyCode = static_cast<unsigned>(args.VirtualKey());
506 // rewrite vk with stored value
507 vk = static_cast<unsigned>(keyStore);
508 // reset stored value
509 keyStore = VirtualKey::None;
510 isDown = true;
512 default:
513 break;
516 Kodi_KeyEvent(vk, args.KeyStatus().ScanCode, keyCode, isDown);
517 args.Handled(true);
520 // DisplayInformation event handlers.
521 void CWinEventsWin10::OnDpiChanged(const DisplayInformation& sender, const winrt::IInspectable&)
523 // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app
524 // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources,
525 // you should always retrieve it using the GetDpi method.
526 // See DeviceResources.cpp for more details.
527 //critical_section::scoped_lock lock(m_deviceResources->GetCriticalSection());
528 RECT resizeRect = { 0,0,0,0 };
529 DX::Windowing()->DPIChanged(sender.LogicalDpi(), resizeRect);
530 CGenericTouchInputHandler::GetInstance().SetScreenDPI(DX::DisplayMetrics::Dpi100);
533 void CWinEventsWin10::OnOrientationChanged(const DisplayInformation&, const winrt::IInspectable&)
535 //critical_section::scoped_lock lock(m_deviceResources->GetCriticalSection());
536 //m_deviceResources->SetCurrentOrientation(sender->CurrentOrientation);
538 //auto size = DX::DeviceResources::Get()->GetOutputSize();
539 //UpdateWindowSize(size.Width, size.Height);
542 void CWinEventsWin10::OnDisplayContentsInvalidated(const DisplayInformation&, const winrt::IInspectable&)
544 CLog::Log(LOGDEBUG, __FUNCTION__": onevent.");
545 DX::DeviceResources::Get()->ValidateDevice();
548 void CWinEventsWin10::OnBackRequested(const winrt::IInspectable&, const BackRequestedEventArgs& args)
550 // handle this only on windows mobile
551 if (CSysInfo::GetWindowsDeviceFamily() == CSysInfo::WindowsDeviceFamily::Mobile)
553 CServiceBroker::GetAppMessenger()->PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1,
554 static_cast<void*>(new CAction(ACTION_NAV_BACK)));
556 args.Handled(true);
559 void CWinEventsWin10::OnSystemMediaButtonPressed(const SystemMediaTransportControls&, const SystemMediaTransportControlsButtonPressedEventArgs& args)
561 int action = ACTION_NONE;
562 switch (args.Button())
564 case SystemMediaTransportControlsButton::ChannelDown:
565 action = ACTION_CHANNEL_DOWN;
566 break;
567 case SystemMediaTransportControlsButton::ChannelUp:
568 action = ACTION_CHANNEL_UP;
569 break;
570 case SystemMediaTransportControlsButton::FastForward:
571 action = ACTION_PLAYER_FORWARD;
572 break;
573 case SystemMediaTransportControlsButton::Rewind:
574 action = ACTION_PLAYER_REWIND;
575 break;
576 case SystemMediaTransportControlsButton::Next:
577 action = ACTION_NEXT_ITEM;
578 break;
579 case SystemMediaTransportControlsButton::Previous:
580 action = ACTION_PREV_ITEM;
581 break;
582 case SystemMediaTransportControlsButton::Pause:
583 case SystemMediaTransportControlsButton::Play:
584 action = ACTION_PLAYER_PLAYPAUSE;
585 break;
586 case SystemMediaTransportControlsButton::Stop:
587 action = ACTION_STOP;
588 break;
589 case SystemMediaTransportControlsButton::Record:
590 action = ACTION_RECORD;
591 break;
592 default:
593 break;
595 if (action != ACTION_NONE)
597 CServiceBroker::GetAppMessenger()->PostMsg(TMSG_GUI_ACTION, WINDOW_INVALID, -1,
598 static_cast<void*>(new CAction(action)));
602 void CWinEventsWin10::Announce(ANNOUNCEMENT::AnnouncementFlag flag,
603 const std::string& sender,
604 const std::string& message,
605 const CVariant& data)
607 if (flag & ANNOUNCEMENT::Player)
609 double speed = 1.0;
610 if (data.isMember("player") && data["player"].isMember("speed"))
611 speed = data["player"]["speed"].asDouble(1.0);
613 bool changed = false;
614 MediaPlaybackStatus status = MediaPlaybackStatus::Changing;
616 if (message == "OnPlay" || message == "OnResume")
618 changed = true;
619 status = MediaPlaybackStatus::Playing;
621 else if (message == "OnStop")
623 changed = true;
624 status = MediaPlaybackStatus::Stopped;
626 else if (message == "OnPause")
628 changed = true;
629 status = MediaPlaybackStatus::Paused;
631 else if (message == "OnSpeedChanged")
633 changed = true;
634 status = speed != 0.0 ? MediaPlaybackStatus::Playing : MediaPlaybackStatus::Paused;
637 if (changed)
641 auto dispatcher = CoreApplication::MainView().Dispatcher();
642 if (dispatcher)
644 dispatcher.RunAsync(CoreDispatcherPriority::Normal, DispatchedHandler([status, speed]
646 auto smtc = SystemMediaTransportControls::GetForCurrentView();
647 if (!smtc)
648 return;
650 smtc.PlaybackStatus(status);
651 smtc.PlaybackRate(speed);
652 }));
655 catch (const winrt::hresult_error&)