Refactor WindowsMediaController with proper WinRT interop
Co-authored-by: jonaski <10343810+jonaski@users.noreply.github.com>
This commit is contained in:
committed by
Jonas Kvinge
parent
4e0cc1c0da
commit
0e0117b19b
@@ -25,15 +25,20 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
|
|
||||||
|
// Undefine 'interface' macro from windows.h before including WinRT headers
|
||||||
#pragma push_macro("interface")
|
#pragma push_macro("interface")
|
||||||
#undef interface
|
#undef interface
|
||||||
|
|
||||||
#include <winrt/Windows.Foundation.h>
|
#include <winrt/Windows.Foundation.h>
|
||||||
#include <winrt/Windows.Media.h>
|
#include <winrt/Windows.Media.h>
|
||||||
#include <winrt/Windows.Storage.h>
|
#include <winrt/Windows.Storage.h>
|
||||||
#include <winrt/Windows.Storage.Streams.h>
|
#include <winrt/Windows.Storage.Streams.h>
|
||||||
#include <SystemMediaTransportControlsInterop.h>
|
|
||||||
#pragma pop_macro("interface")
|
#pragma pop_macro("interface")
|
||||||
|
|
||||||
|
// Include the interop header for ISystemMediaTransportControlsInterop
|
||||||
|
#include <systemmediatransportcontrolsinterop.h>
|
||||||
|
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "windowsmediacontroller.h"
|
#include "windowsmediacontroller.h"
|
||||||
|
|
||||||
@@ -49,6 +54,11 @@ using namespace Windows::Media;
|
|||||||
using namespace Windows::Storage;
|
using namespace Windows::Storage;
|
||||||
using namespace Windows::Storage::Streams;
|
using namespace Windows::Storage::Streams;
|
||||||
|
|
||||||
|
// Helper struct to hold the WinRT object
|
||||||
|
struct WindowsMediaControllerPrivate {
|
||||||
|
SystemMediaTransportControls smtc{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
WindowsMediaController::WindowsMediaController(HWND hwnd,
|
WindowsMediaController::WindowsMediaController(HWND hwnd,
|
||||||
const SharedPtr<Player> player,
|
const SharedPtr<Player> player,
|
||||||
const SharedPtr<PlaylistManager> playlist_manager,
|
const SharedPtr<PlaylistManager> playlist_manager,
|
||||||
@@ -64,23 +74,52 @@ WindowsMediaController::WindowsMediaController(HWND hwnd,
|
|||||||
// Initialize WinRT
|
// Initialize WinRT
|
||||||
winrt::init_apartment();
|
winrt::init_apartment();
|
||||||
|
|
||||||
// Get the SystemMediaTransportControls instance using the interop interface
|
// Create private implementation
|
||||||
auto interop = winrt::get_activation_factory<SystemMediaTransportControls, ISystemMediaTransportControlsInterop>();
|
auto *priv = new WindowsMediaControllerPrivate();
|
||||||
winrt::com_ptr<IInspectable> smtc_inspectable;
|
smtc_ = priv;
|
||||||
winrt::check_hresult(interop->GetForWindow(hwnd, winrt::guid_of<SystemMediaTransportControls>(), smtc_inspectable.put_void()));
|
|
||||||
|
// Get the SystemMediaTransportControls instance for this window
|
||||||
|
// Use the interop interface
|
||||||
|
winrt::com_ptr<ISystemMediaTransportControlsInterop> interop;
|
||||||
|
winrt::check_hresult(winrt::get_activation_factory<SystemMediaTransportControls, ISystemMediaTransportControlsInterop>(
|
||||||
|
L"Windows.Media.SystemMediaTransportControls", interop.put_void()
|
||||||
|
));
|
||||||
|
|
||||||
|
if (!interop) {
|
||||||
|
qLog(Warning) << "Failed to get ISystemMediaTransportControlsInterop";
|
||||||
|
delete priv;
|
||||||
|
smtc_ = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get SMTC for the window
|
||||||
|
winrt::com_ptr<IInspectable> inspectable;
|
||||||
|
HRESULT hr = interop->GetForWindow(hwnd, winrt::guid_of<SystemMediaTransportControls>(), inspectable.put_void());
|
||||||
|
|
||||||
auto smtc = smtc_inspectable.as<SystemMediaTransportControls>();
|
if (FAILED(hr) || !inspectable) {
|
||||||
smtc_ = new SystemMediaTransportControls(smtc);
|
qLog(Warning) << "Failed to get SystemMediaTransportControls for window, HRESULT:" << Qt::hex << static_cast<unsigned int>(hr);
|
||||||
|
delete priv;
|
||||||
|
smtc_ = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to SystemMediaTransportControls
|
||||||
|
priv->smtc = inspectable.as<SystemMediaTransportControls>();
|
||||||
|
|
||||||
auto controls = static_cast<SystemMediaTransportControls*>(smtc_);
|
if (!priv->smtc) {
|
||||||
|
qLog(Warning) << "Failed to cast to SystemMediaTransportControls";
|
||||||
|
delete priv;
|
||||||
|
smtc_ = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Enable the controls
|
// Enable the controls
|
||||||
controls->IsEnabled(true);
|
priv->smtc.IsEnabled(true);
|
||||||
controls->IsPlayEnabled(true);
|
priv->smtc.IsPlayEnabled(true);
|
||||||
controls->IsPauseEnabled(true);
|
priv->smtc.IsPauseEnabled(true);
|
||||||
controls->IsStopEnabled(true);
|
priv->smtc.IsStopEnabled(true);
|
||||||
controls->IsNextEnabled(true);
|
priv->smtc.IsNextEnabled(true);
|
||||||
controls->IsPreviousEnabled(true);
|
priv->smtc.IsPreviousEnabled(true);
|
||||||
|
|
||||||
// Setup button handlers
|
// Setup button handlers
|
||||||
SetupButtonHandlers();
|
SetupButtonHandlers();
|
||||||
@@ -94,17 +133,27 @@ WindowsMediaController::WindowsMediaController(HWND hwnd,
|
|||||||
}
|
}
|
||||||
catch (const hresult_error &e) {
|
catch (const hresult_error &e) {
|
||||||
qLog(Warning) << "Failed to initialize Windows Media Transport Controls:" << QString::fromWCharArray(e.message().c_str());
|
qLog(Warning) << "Failed to initialize Windows Media Transport Controls:" << QString::fromWCharArray(e.message().c_str());
|
||||||
|
if (smtc_) {
|
||||||
|
delete static_cast<WindowsMediaControllerPrivate*>(smtc_);
|
||||||
|
smtc_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
qLog(Warning) << "Failed to initialize Windows Media Transport Controls: unknown error";
|
qLog(Warning) << "Failed to initialize Windows Media Transport Controls: unknown error";
|
||||||
|
if (smtc_) {
|
||||||
|
delete static_cast<WindowsMediaControllerPrivate*>(smtc_);
|
||||||
|
smtc_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowsMediaController::~WindowsMediaController() {
|
WindowsMediaController::~WindowsMediaController() {
|
||||||
if (smtc_) {
|
if (smtc_) {
|
||||||
auto controls = static_cast<SystemMediaTransportControls*>(smtc_);
|
auto *priv = static_cast<WindowsMediaControllerPrivate*>(smtc_);
|
||||||
controls->IsEnabled(false);
|
if (priv->smtc) {
|
||||||
delete controls;
|
priv->smtc.IsEnabled(false);
|
||||||
|
}
|
||||||
|
delete priv;
|
||||||
smtc_ = nullptr;
|
smtc_ = nullptr;
|
||||||
}
|
}
|
||||||
winrt::uninit_apartment();
|
winrt::uninit_apartment();
|
||||||
@@ -113,10 +162,11 @@ WindowsMediaController::~WindowsMediaController() {
|
|||||||
void WindowsMediaController::SetupButtonHandlers() {
|
void WindowsMediaController::SetupButtonHandlers() {
|
||||||
if (!smtc_) return;
|
if (!smtc_) return;
|
||||||
|
|
||||||
auto controls = static_cast<SystemMediaTransportControls*>(smtc_);
|
auto *priv = static_cast<WindowsMediaControllerPrivate*>(smtc_);
|
||||||
|
if (!priv->smtc) return;
|
||||||
|
|
||||||
// Handle button pressed events
|
// Handle button pressed events
|
||||||
controls->ButtonPressed([this](const SystemMediaTransportControls &, const SystemMediaTransportControlsButtonPressedEventArgs &args) {
|
priv->smtc.ButtonPressed([this](const SystemMediaTransportControls &, const SystemMediaTransportControlsButtonPressedEventArgs &args) {
|
||||||
switch (args.Button()) {
|
switch (args.Button()) {
|
||||||
case SystemMediaTransportControlsButton::Play:
|
case SystemMediaTransportControlsButton::Play:
|
||||||
player_->Play();
|
player_->Play();
|
||||||
@@ -146,19 +196,20 @@ void WindowsMediaController::EngineStateChanged(EngineBase::State newState) {
|
|||||||
void WindowsMediaController::UpdatePlaybackStatus(EngineBase::State state) {
|
void WindowsMediaController::UpdatePlaybackStatus(EngineBase::State state) {
|
||||||
if (!smtc_) return;
|
if (!smtc_) return;
|
||||||
|
|
||||||
auto controls = static_cast<SystemMediaTransportControls*>(smtc_);
|
auto *priv = static_cast<WindowsMediaControllerPrivate*>(smtc_);
|
||||||
|
if (!priv->smtc) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case EngineBase::State::Playing:
|
case EngineBase::State::Playing:
|
||||||
controls->PlaybackStatus(MediaPlaybackStatus::Playing);
|
priv->smtc.PlaybackStatus(MediaPlaybackStatus::Playing);
|
||||||
break;
|
break;
|
||||||
case EngineBase::State::Paused:
|
case EngineBase::State::Paused:
|
||||||
controls->PlaybackStatus(MediaPlaybackStatus::Paused);
|
priv->smtc.PlaybackStatus(MediaPlaybackStatus::Paused);
|
||||||
break;
|
break;
|
||||||
case EngineBase::State::Empty:
|
case EngineBase::State::Empty:
|
||||||
case EngineBase::State::Idle:
|
case EngineBase::State::Idle:
|
||||||
controls->PlaybackStatus(MediaPlaybackStatus::Stopped);
|
priv->smtc.PlaybackStatus(MediaPlaybackStatus::Stopped);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,11 +241,12 @@ void WindowsMediaController::AlbumCoverLoaded(const Song &song, const AlbumCover
|
|||||||
void WindowsMediaController::UpdateMetadata(const Song &song, const QUrl &art_url) {
|
void WindowsMediaController::UpdateMetadata(const Song &song, const QUrl &art_url) {
|
||||||
if (!smtc_) return;
|
if (!smtc_) return;
|
||||||
|
|
||||||
auto controls = static_cast<SystemMediaTransportControls*>(smtc_);
|
auto *priv = static_cast<WindowsMediaControllerPrivate*>(smtc_);
|
||||||
|
if (!priv->smtc) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get the updater
|
// Get the updater
|
||||||
SystemMediaTransportControlsDisplayUpdater updater = controls->DisplayUpdater();
|
SystemMediaTransportControlsDisplayUpdater updater = priv->smtc.DisplayUpdater();
|
||||||
updater.Type(MediaPlaybackType::Music);
|
updater.Type(MediaPlaybackType::Music);
|
||||||
|
|
||||||
// Get the music properties
|
// Get the music properties
|
||||||
|
|||||||
Reference in New Issue
Block a user