mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
Add native Windows media SMTC metadata publishing
This commit is contained in:
parent
f2d3eb036b
commit
83a3972d44
4 changed files with 611 additions and 1 deletions
|
|
@ -967,6 +967,10 @@ var gBrowserInit = {
|
|||
Services.obs.addObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed", false);
|
||||
|
||||
window.addEventListener("AppCommand", HandleAppCommandEvent, true);
|
||||
gBrowser.addEventListener("DOMAudioPlaybackStarted", HandleWindowsSMTCAudioPlaybackEvent, true);
|
||||
gBrowser.addEventListener("DOMAudioPlaybackStopped", HandleWindowsSMTCAudioPlaybackEvent, true);
|
||||
gBrowser.tabContainer.addEventListener("TabAttrModified", HandleWindowsSMTCTabAttrModified, false);
|
||||
Services.obs.addObserver(HandleSMTCControlCommand, "smtc-control-command", false);
|
||||
|
||||
// These routines add message listeners. They must run before
|
||||
// loading the frame script to ensure that we don't miss any
|
||||
|
|
@ -1453,6 +1457,11 @@ var gBrowserInit = {
|
|||
FullScreen.uninit();
|
||||
|
||||
Services.obs.removeObserver(gPluginHandler.NPAPIPluginCrashed, "plugin-crashed");
|
||||
window.removeEventListener("AppCommand", HandleAppCommandEvent, true);
|
||||
gBrowser.removeEventListener("DOMAudioPlaybackStarted", HandleWindowsSMTCAudioPlaybackEvent, true);
|
||||
gBrowser.removeEventListener("DOMAudioPlaybackStopped", HandleWindowsSMTCAudioPlaybackEvent, true);
|
||||
gBrowser.tabContainer.removeEventListener("TabAttrModified", HandleWindowsSMTCTabAttrModified, false);
|
||||
Services.obs.removeObserver(HandleSMTCControlCommand, "smtc-control-command");
|
||||
|
||||
try {
|
||||
gBrowser.removeProgressListener(window.XULBrowserWindow);
|
||||
|
|
@ -1690,6 +1699,22 @@ function HandleAppCommandEvent(evt) {
|
|||
case "SendMail":
|
||||
MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser);
|
||||
break;
|
||||
case "MediaPlayPause":
|
||||
if (!HandleMediaControlAppCommand("playpause"))
|
||||
return;
|
||||
break;
|
||||
case "MediaStop":
|
||||
if (!HandleMediaControlAppCommand("stop"))
|
||||
return;
|
||||
break;
|
||||
case "MediaNextTrack":
|
||||
if (!HandleMediaControlAppCommand("next"))
|
||||
return;
|
||||
break;
|
||||
case "MediaPrevTrack":
|
||||
if (!HandleMediaControlAppCommand("previous"))
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
@ -1697,6 +1722,197 @@ function HandleAppCommandEvent(evt) {
|
|||
evt.preventDefault();
|
||||
}
|
||||
|
||||
function GetActiveMediaTab() {
|
||||
if (gBrowser.selectedTab &&
|
||||
(gBrowser.selectedTab.soundPlaying || gBrowser.selectedTab.linkedBrowser.audioBlocked)) {
|
||||
return gBrowser.selectedTab;
|
||||
}
|
||||
|
||||
for (let tab of gBrowser.visibleTabs) {
|
||||
if (tab.soundPlaying || tab.linkedBrowser.audioBlocked) {
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
|
||||
return gBrowser.selectedTab || null;
|
||||
}
|
||||
|
||||
function HandleMediaControlAppCommand(action) {
|
||||
let tab = GetActiveMediaTab();
|
||||
if (!tab || !tab.linkedBrowser) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
switch (action) {
|
||||
case "playpause":
|
||||
if (tab.soundPlaying && !browser.audioBlocked) {
|
||||
browser.pauseMedia(true);
|
||||
} else {
|
||||
browser.resumeMedia();
|
||||
}
|
||||
return true;
|
||||
case "stop":
|
||||
browser.stopMedia();
|
||||
return true;
|
||||
case "next":
|
||||
browser.messageManager.sendAsyncMessage("MediaControl:Key", { key: "MediaTrackNext" });
|
||||
return true;
|
||||
case "previous":
|
||||
browser.messageManager.sendAsyncMessage("MediaControl:Key", { key: "MediaTrackPrevious" });
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getWindowsUIUtils() {
|
||||
if (AppConstants.platform != "win") {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Cc["@mozilla.org/windows-ui-utils;1"]
|
||||
.getService(Ci.nsIWindowsUIUtils);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var gLastSMTCMediaTab = null;
|
||||
|
||||
function isSMTCTabOpen(aTab) {
|
||||
if (!aTab || !gBrowser || !gBrowser.tabs) {
|
||||
return false;
|
||||
}
|
||||
for (let tab of gBrowser.tabs) {
|
||||
if (tab == aTab) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateWindowsSMTCMetadataFromTab(aTab, aPlaying) {
|
||||
let uiUtils = getWindowsUIUtils();
|
||||
if (!uiUtils) {
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = aTab;
|
||||
if (!tab && isSMTCTabOpen(gLastSMTCMediaTab)) {
|
||||
tab = gLastSMTCMediaTab;
|
||||
}
|
||||
|
||||
if (!tab) {
|
||||
gLastSMTCMediaTab = null;
|
||||
uiUtils.clearSMTCMetadata();
|
||||
return;
|
||||
}
|
||||
|
||||
let title = tab.label || "";
|
||||
let artist = "";
|
||||
let album = "";
|
||||
let thumbnailURL = "";
|
||||
|
||||
try {
|
||||
let browser = tab.linkedBrowser;
|
||||
if (browser && browser.currentURI) {
|
||||
album = browser.currentURI.host || browser.currentURI.spec || "";
|
||||
|
||||
let spec = browser.currentURI.spec || "";
|
||||
let host = (browser.currentURI.host || "").toLowerCase();
|
||||
if (host == "www.youtube.com" || host == "youtube.com" || host == "m.youtube.com") {
|
||||
let match = spec.match(/[?&]v=([^&]+)/);
|
||||
if (match && match[1]) {
|
||||
thumbnailURL = "https://i.ytimg.com/vi/" + match[1] + "/hqdefault.jpg";
|
||||
}
|
||||
} else if (host == "youtu.be") {
|
||||
let path = browser.currentURI.pathQueryRef || "";
|
||||
let id = path.replace(/^\//, "").split(/[?#]/)[0];
|
||||
if (id) {
|
||||
thumbnailURL = "https://i.ytimg.com/vi/" + id + "/hqdefault.jpg";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Best-effort metadata extraction.
|
||||
}
|
||||
|
||||
uiUtils.setSMTCMetadata(title, artist, album);
|
||||
if (thumbnailURL) {
|
||||
uiUtils.setSMTCThumbnailURL(thumbnailURL);
|
||||
}
|
||||
uiUtils.setSMTCPlaybackState(!!aPlaying);
|
||||
gLastSMTCMediaTab = tab;
|
||||
}
|
||||
|
||||
function HandleWindowsSMTCAudioPlaybackEvent(aEvent) {
|
||||
let tab = gBrowser.getTabForBrowser(aEvent.target);
|
||||
if (!tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aEvent.type == "DOMAudioPlaybackStarted") {
|
||||
updateWindowsSMTCMetadataFromTab(tab, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aEvent.type == "DOMAudioPlaybackStopped") {
|
||||
let activeTab = GetActiveMediaTab();
|
||||
if (activeTab && activeTab.soundPlaying) {
|
||||
updateWindowsSMTCMetadataFromTab(activeTab, true);
|
||||
} else {
|
||||
updateWindowsSMTCMetadataFromTab(null, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function HandleWindowsSMTCTabAttrModified(aEvent) {
|
||||
let changed = aEvent.detail && aEvent.detail.changed;
|
||||
if (!changed || (changed.indexOf("soundplaying") < 0 &&
|
||||
changed.indexOf("blocked") < 0 &&
|
||||
changed.indexOf("muted") < 0 &&
|
||||
changed.indexOf("label") < 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let activeTab = GetActiveMediaTab();
|
||||
if (activeTab && activeTab.soundPlaying) {
|
||||
updateWindowsSMTCMetadataFromTab(activeTab, true);
|
||||
} else {
|
||||
updateWindowsSMTCMetadataFromTab(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
function HandleSMTCControlCommand(subject, topic, data) {
|
||||
if (topic != "smtc-control-command") {
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = (GetActiveMediaTab() && GetActiveMediaTab().soundPlaying) ?
|
||||
GetActiveMediaTab() :
|
||||
(isSMTCTabOpen(gLastSMTCMediaTab) ? gLastSMTCMediaTab : null);
|
||||
if (!tab || !tab.linkedBrowser) {
|
||||
return;
|
||||
}
|
||||
|
||||
let browser = tab.linkedBrowser;
|
||||
switch (data) {
|
||||
case "play":
|
||||
browser.resumeMedia();
|
||||
updateWindowsSMTCMetadataFromTab(tab, true);
|
||||
break;
|
||||
case "pause":
|
||||
browser.pauseMedia(true);
|
||||
updateWindowsSMTCMetadataFromTab(tab, false);
|
||||
break;
|
||||
case "stop":
|
||||
browser.stopMedia();
|
||||
updateWindowsSMTCMetadataFromTab(tab, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function gotoHistoryIndex(aEvent) {
|
||||
let index = aEvent.target.getAttribute("index");
|
||||
if (!index)
|
||||
|
|
|
|||
|
|
@ -1017,6 +1017,31 @@ var AudioPlaybackListener = {
|
|||
};
|
||||
AudioPlaybackListener.init();
|
||||
|
||||
addMessageListener("MediaControl:Key", function(msg) {
|
||||
let targetWindow = content;
|
||||
if (!targetWindow || !targetWindow.document) {
|
||||
return;
|
||||
}
|
||||
|
||||
let key = msg.data && msg.data.key;
|
||||
if (!key) {
|
||||
return;
|
||||
}
|
||||
|
||||
let eventInit = {
|
||||
key,
|
||||
code: key,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
};
|
||||
|
||||
let downEvent = new targetWindow.KeyboardEvent("keydown", eventInit);
|
||||
targetWindow.document.dispatchEvent(downEvent);
|
||||
|
||||
let upEvent = new targetWindow.KeyboardEvent("keyup", eventInit);
|
||||
targetWindow.document.dispatchEvent(upEvent);
|
||||
});
|
||||
|
||||
addMessageListener("Browser:PurgeSessionHistory", function BrowserPurgeHistory() {
|
||||
let sessionHistory = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory;
|
||||
if (!sessionHistory) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "nsISupports.idl"
|
||||
|
||||
|
||||
[scriptable, uuid(aa8a0ecf-96a1-418c-b80e-f24ae18bbedc)]
|
||||
[scriptable, uuid(8eb5da7b-ec94-4cf4-9f2e-9d2b8f8bc763)]
|
||||
interface nsIWindowsUIUtils : nsISupports
|
||||
{
|
||||
/**
|
||||
|
|
@ -20,5 +20,31 @@ interface nsIWindowsUIUtils : nsISupports
|
|||
* Update the tablet mode state
|
||||
*/
|
||||
void updateTabletModeState();
|
||||
|
||||
/**
|
||||
* Update native Windows System Media Transport Controls playback state.
|
||||
* No-op on unsupported Windows versions.
|
||||
*/
|
||||
void setSMTCPlaybackState(in boolean aPlaying);
|
||||
|
||||
/**
|
||||
* Publish media metadata to native Windows System Media Transport Controls.
|
||||
* No-op on unsupported Windows versions.
|
||||
*/
|
||||
void setSMTCMetadata(in AString aTitle,
|
||||
in AString aArtist,
|
||||
in AString aAlbum);
|
||||
|
||||
/**
|
||||
* Publish artwork URL to native Windows System Media Transport Controls.
|
||||
* No-op on unsupported Windows versions.
|
||||
*/
|
||||
void setSMTCThumbnailURL(in AString aThumbnailURL);
|
||||
|
||||
/**
|
||||
* Clear native Windows System Media Transport Controls metadata.
|
||||
* No-op on unsupported Windows versions.
|
||||
*/
|
||||
void clearSMTCMetadata();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,18 @@
|
|||
#ifndef __MINGW32__
|
||||
|
||||
#include <windows.ui.viewmanagement.h>
|
||||
#include <windows.media.h>
|
||||
#include <windows.foundation.h>
|
||||
#include <windows.storage.streams.h>
|
||||
#include <systemmediatransportcontrolsinterop.h>
|
||||
|
||||
#pragma comment(lib, "runtimeobject.lib")
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace ABI::Windows::UI;
|
||||
using namespace ABI::Windows::UI::ViewManagement;
|
||||
using namespace ABI::Windows::Media;
|
||||
using namespace ABI::Windows::Storage::Streams;
|
||||
using namespace Microsoft::WRL;
|
||||
using namespace Microsoft::WRL::Wrappers;
|
||||
using namespace ABI::Windows::Foundation;
|
||||
|
|
@ -57,6 +63,32 @@ namespace ABI {
|
|||
#define RuntimeClass_Windows_UI_ViewManagement_UIViewSettings L"Windows.UI.ViewManagement.UIViewSettings"
|
||||
#endif
|
||||
|
||||
#ifndef RuntimeClass_Windows_Media_SystemMediaTransportControls
|
||||
#define RuntimeClass_Windows_Media_SystemMediaTransportControls L"Windows.Media.SystemMediaTransportControls"
|
||||
#endif
|
||||
|
||||
#ifndef RuntimeClass_Windows_Foundation_Uri
|
||||
#define RuntimeClass_Windows_Foundation_Uri L"Windows.Foundation.Uri"
|
||||
#endif
|
||||
|
||||
#ifndef RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference
|
||||
#define RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference L"Windows.Storage.Streams.RandomAccessStreamReference"
|
||||
#endif
|
||||
|
||||
// Some SDK configurations only forward-declare this interface unless newer
|
||||
// NTDDI guards are enabled. Provide a local fallback definition.
|
||||
#ifndef __ISystemMediaTransportControlsInterop_INTERFACE_DEFINED__
|
||||
MIDL_INTERFACE("ddb0472d-c911-4a1f-86d9-dc3d71a95f5a")
|
||||
ISystemMediaTransportControlsInterop : public IInspectable
|
||||
{
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetForWindow(
|
||||
HWND appWindow,
|
||||
REFIID riid,
|
||||
void** mediaTransportControl) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if WINVER_MAXVER < 0x0A00
|
||||
namespace ABI {
|
||||
namespace Windows {
|
||||
|
|
@ -91,6 +123,151 @@ public:
|
|||
|
||||
#endif
|
||||
|
||||
#ifndef __MINGW32__
|
||||
namespace {
|
||||
ComPtr<ISystemMediaTransportControls> gSMTC;
|
||||
EventRegistrationToken gSMTCButtonPressedToken;
|
||||
|
||||
void
|
||||
NotifySMTCControlCommand(const char16_t* aCommand)
|
||||
{
|
||||
if (!aCommand) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->NotifyObservers(nullptr, "smtc-control-command", aCommand);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetHiddenWindowHWND(HWND* aHwnd)
|
||||
{
|
||||
if (!aHwnd) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
*aHwnd = nullptr;
|
||||
|
||||
nsCOMPtr<nsIAppShellService> appShell(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
|
||||
if (!appShell) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXULWindow> hiddenWindow;
|
||||
nsresult rv = appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(hiddenWindow, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell;
|
||||
rv = hiddenWindow->GetDocShell(getter_AddRefs(docShell));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
|
||||
NS_ENSURE_TRUE(baseWindow, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
baseWindow->GetMainWidget(getter_AddRefs(widget));
|
||||
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
|
||||
|
||||
*aHwnd = reinterpret_cast<HWND>(widget->GetNativeData(NS_NATIVE_WINDOW));
|
||||
return *aHwnd ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
GetSMTCTargetHWND(HWND* aHwnd)
|
||||
{
|
||||
if (!aHwnd) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
*aHwnd = nullptr;
|
||||
|
||||
// Prefer an interactive browser window for SMTC interop.
|
||||
HWND hwnd = ::GetForegroundWindow();
|
||||
if (!hwnd) {
|
||||
hwnd = ::GetActiveWindow();
|
||||
}
|
||||
if (hwnd) {
|
||||
*aHwnd = hwnd;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Fall back to hidden window if no foreground window is available.
|
||||
return GetHiddenWindowHWND(aHwnd);
|
||||
}
|
||||
|
||||
nsresult
|
||||
EnsureSMTC()
|
||||
{
|
||||
if (gSMTC) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!IsWin10OrLater()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
HWND hwnd = nullptr;
|
||||
nsresult rv = GetSMTCTargetHWND(&hwnd);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
ComPtr<ISystemMediaTransportControlsInterop> interop;
|
||||
HRESULT hr = GetActivationFactory(
|
||||
HStringReference(RuntimeClass_Windows_Media_SystemMediaTransportControls).Get(),
|
||||
&interop);
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
hr = interop->GetForWindow(hwnd, IID_PPV_ARGS(&gSMTC));
|
||||
if (FAILED(hr)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
gSMTC->put_IsEnabled(TRUE);
|
||||
gSMTC->put_IsPlayEnabled(TRUE);
|
||||
gSMTC->put_IsPauseEnabled(TRUE);
|
||||
gSMTC->put_IsStopEnabled(TRUE);
|
||||
gSMTC->put_IsNextEnabled(TRUE);
|
||||
gSMTC->put_IsPreviousEnabled(TRUE);
|
||||
|
||||
auto buttonHandler = Callback<
|
||||
__FITypedEventHandler_2_Windows__CMedia__CSystemMediaTransportControls_Windows__CMedia__CSystemMediaTransportControlsButtonPressedEventArgs>(
|
||||
[](ABI::Windows::Media::ISystemMediaTransportControls*,
|
||||
ABI::Windows::Media::ISystemMediaTransportControlsButtonPressedEventArgs* aArgs) -> HRESULT {
|
||||
if (!aArgs) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
SystemMediaTransportControlsButton button;
|
||||
if (FAILED(aArgs->get_Button(&button))) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
switch (button) {
|
||||
case SystemMediaTransportControlsButton_Play:
|
||||
NotifySMTCControlCommand(u"play");
|
||||
break;
|
||||
case SystemMediaTransportControlsButton_Pause:
|
||||
NotifySMTCControlCommand(u"pause");
|
||||
break;
|
||||
case SystemMediaTransportControlsButton_Stop:
|
||||
NotifySMTCControlCommand(u"stop");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
});
|
||||
|
||||
if (buttonHandler) {
|
||||
gSMTC->add_ButtonPressed(buttonHandler.Get(), &gSMTCButtonPressedToken);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
WindowsUIUtils::WindowsUIUtils() :
|
||||
mInTabletMode(eTabletModeUnknown)
|
||||
{
|
||||
|
|
@ -180,3 +357,169 @@ WindowsUIUtils::UpdateTabletModeState()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsUIUtils::SetSMTCPlaybackState(bool aPlaying)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (!IsWin10OrLater()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = EnsureSMTC();
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!gSMTC) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (aPlaying) {
|
||||
gSMTC->put_IsEnabled(TRUE);
|
||||
gSMTC->put_PlaybackStatus(MediaPlaybackStatus_Playing);
|
||||
} else {
|
||||
gSMTC->put_IsEnabled(TRUE);
|
||||
gSMTC->put_PlaybackStatus(MediaPlaybackStatus_Paused);
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsUIUtils::SetSMTCMetadata(const nsAString& aTitle,
|
||||
const nsAString& aArtist,
|
||||
const nsAString& aAlbum)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (!IsWin10OrLater()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = EnsureSMTC();
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!gSMTC) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<ISystemMediaTransportControlsDisplayUpdater> updater;
|
||||
HRESULT hr = gSMTC->get_DisplayUpdater(&updater);
|
||||
if (FAILED(hr) || !updater) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
updater->put_Type(MediaPlaybackType_Music);
|
||||
|
||||
ComPtr<IMusicDisplayProperties> music;
|
||||
hr = updater->get_MusicProperties(&music);
|
||||
if (FAILED(hr) || !music) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString titleString(aTitle);
|
||||
nsAutoString artistString(aArtist);
|
||||
nsAutoString albumString(aAlbum);
|
||||
|
||||
HString title;
|
||||
HString artist;
|
||||
HString album;
|
||||
title.Set(titleString.get(), static_cast<UINT32>(titleString.Length()));
|
||||
artist.Set(artistString.get(), static_cast<UINT32>(artistString.Length()));
|
||||
album.Set(albumString.get(), static_cast<UINT32>(albumString.Length()));
|
||||
|
||||
music->put_Title(title.Get());
|
||||
music->put_Artist(artist.Get());
|
||||
music->put_AlbumArtist(album.Get());
|
||||
|
||||
updater->Update();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsUIUtils::SetSMTCThumbnailURL(const nsAString& aThumbnailURL)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (!IsWin10OrLater()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = EnsureSMTC();
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!gSMTC || aThumbnailURL.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<ISystemMediaTransportControlsDisplayUpdater> updater;
|
||||
HRESULT hr = gSMTC->get_DisplayUpdater(&updater);
|
||||
if (FAILED(hr) || !updater) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IUriRuntimeClassFactory> uriFactory;
|
||||
hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
|
||||
if (FAILED(hr) || !uriFactory) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoString urlString(aThumbnailURL);
|
||||
HString url;
|
||||
url.Set(urlString.get(), static_cast<UINT32>(urlString.Length()));
|
||||
|
||||
ComPtr<IUriRuntimeClass> uri;
|
||||
hr = uriFactory->CreateUri(url.Get(), &uri);
|
||||
if (FAILED(hr) || !uri) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IRandomAccessStreamReferenceStatics> streamRefStatics;
|
||||
hr = GetActivationFactory(
|
||||
HStringReference(RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference).Get(),
|
||||
&streamRefStatics);
|
||||
if (FAILED(hr) || !streamRefStatics) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<IRandomAccessStreamReference> thumbnail;
|
||||
hr = streamRefStatics->CreateFromUri(uri.Get(), &thumbnail);
|
||||
if (FAILED(hr) || !thumbnail) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
updater->put_Thumbnail(thumbnail.Get());
|
||||
updater->Update();
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
WindowsUIUtils::ClearSMTCMetadata()
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (!IsWin10OrLater()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = EnsureSMTC();
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (!gSMTC) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ComPtr<ISystemMediaTransportControlsDisplayUpdater> updater;
|
||||
HRESULT hr = gSMTC->get_DisplayUpdater(&updater);
|
||||
if (SUCCEEDED(hr) && updater) {
|
||||
updater->ClearAll();
|
||||
updater->Update();
|
||||
}
|
||||
|
||||
gSMTC->put_PlaybackStatus(MediaPlaybackStatus_Stopped);
|
||||
gSMTC->put_IsEnabled(FALSE);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue