mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 01:08:39 +09:00
Add mac-media-control
This commit is contained in:
parent
5b48f5878c
commit
503a1e48d1
9 changed files with 320 additions and 5 deletions
|
|
@ -1795,12 +1795,16 @@ function HandleMediaControlAppCommand(action) {
|
|||
}
|
||||
|
||||
function getWindowsUIUtils() {
|
||||
if (AppConstants.platform != "win") {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return Cc["@mozilla.org/windows-ui-utils;1"]
|
||||
.getService(Ci.nsIWindowsUIUtils);
|
||||
if (AppConstants.platform == "win") {
|
||||
return Cc["@mozilla.org/windows-ui-utils;1"]
|
||||
.getService(Ci.nsIWindowsUIUtils);
|
||||
}
|
||||
if (AppConstants.platform == "macosx") {
|
||||
return Cc["@mozilla.org/mac-media-control;1"]
|
||||
.getService(Ci.nsIMacMediaControl);
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
23
widget/cocoa/MacMediaControlUtils.h
Normal file
23
widget/cocoa/MacMediaControlUtils.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_widget_MacMediaControlUtils_h__
|
||||
#define mozilla_widget_MacMediaControlUtils_h__
|
||||
|
||||
#include "nsIMacMediaControl.h"
|
||||
|
||||
#define NS_MAC_MEDIACONTROL_CONTRACTID "@mozilla.org/mac-media-control;1"
|
||||
|
||||
class MacMediaControlUtils final : public nsIMacMediaControl {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIMACMEDIACONTROL
|
||||
|
||||
MacMediaControlUtils() = default;
|
||||
|
||||
private:
|
||||
~MacMediaControlUtils() = default;
|
||||
};
|
||||
|
||||
#endif // mozilla_widget_MacMediaControlUtils_h__
|
||||
243
widget/cocoa/MacMediaControlUtils.mm
Normal file
243
widget/cocoa/MacMediaControlUtils.mm
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <objc/message.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "MacMediaControlUtils.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
|
||||
// This must be included last:
|
||||
#include "nsObjCExceptions.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(MacMediaControlUtils, nsIMacMediaControl)
|
||||
|
||||
namespace {
|
||||
|
||||
static NSMutableDictionary* sNowPlayingInfo = nil;
|
||||
static bool sTriedLoadMediaPlayerFramework = false;
|
||||
static void* sMediaPlayerHandle = nullptr;
|
||||
|
||||
static void EnsureMediaPlayerFrameworkLoaded();
|
||||
|
||||
static NSString*
|
||||
GetMediaPlayerStringConstant(const char* aSymbolName, NSString* aFallback)
|
||||
{
|
||||
EnsureMediaPlayerFrameworkLoaded();
|
||||
|
||||
if (!sMediaPlayerHandle) {
|
||||
sMediaPlayerHandle = dlopen("/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer",
|
||||
RTLD_LAZY | RTLD_NOLOAD);
|
||||
if (!sMediaPlayerHandle) {
|
||||
sMediaPlayerHandle = dlopen("/System/Library/Frameworks/MediaPlayer.framework/MediaPlayer",
|
||||
RTLD_LAZY);
|
||||
}
|
||||
}
|
||||
|
||||
if (!sMediaPlayerHandle) {
|
||||
return aFallback;
|
||||
}
|
||||
|
||||
NSString* const* key = static_cast<NSString* const*>(dlsym(sMediaPlayerHandle, aSymbolName));
|
||||
return (key && *key) ? *key : aFallback;
|
||||
}
|
||||
|
||||
static NSString*
|
||||
NowPlayingPlaybackRateKey()
|
||||
{
|
||||
static NSString* key = GetMediaPlayerStringConstant("MPNowPlayingInfoPropertyPlaybackRate",
|
||||
@"playbackRate");
|
||||
return key;
|
||||
}
|
||||
|
||||
static NSString*
|
||||
NowPlayingElapsedTimeKey()
|
||||
{
|
||||
static NSString* key = GetMediaPlayerStringConstant("MPNowPlayingInfoPropertyElapsedPlaybackTime",
|
||||
@"elapsedPlaybackTime");
|
||||
return key;
|
||||
}
|
||||
|
||||
static NSString*
|
||||
MediaItemTitleKey()
|
||||
{
|
||||
static NSString* key = GetMediaPlayerStringConstant("MPMediaItemPropertyTitle",
|
||||
@"title");
|
||||
return key;
|
||||
}
|
||||
|
||||
static NSString*
|
||||
MediaItemArtistKey()
|
||||
{
|
||||
static NSString* key = GetMediaPlayerStringConstant("MPMediaItemPropertyArtist",
|
||||
@"artist");
|
||||
return key;
|
||||
}
|
||||
|
||||
static NSString*
|
||||
MediaItemAlbumTitleKey()
|
||||
{
|
||||
static NSString* key = GetMediaPlayerStringConstant("MPMediaItemPropertyAlbumTitle",
|
||||
@"albumTitle");
|
||||
return key;
|
||||
}
|
||||
|
||||
static void
|
||||
EnsureMediaPlayerFrameworkLoaded()
|
||||
{
|
||||
if (sTriedLoadMediaPlayerFramework) {
|
||||
return;
|
||||
}
|
||||
sTriedLoadMediaPlayerFramework = true;
|
||||
|
||||
NSString* frameworkPath = @"/System/Library/Frameworks/MediaPlayer.framework";
|
||||
NSBundle* mediaPlayerBundle = [NSBundle bundleWithPath:frameworkPath];
|
||||
if (mediaPlayerBundle) {
|
||||
[mediaPlayerBundle load];
|
||||
}
|
||||
}
|
||||
|
||||
static id
|
||||
GetNowPlayingInfoCenter()
|
||||
{
|
||||
EnsureMediaPlayerFrameworkLoaded();
|
||||
|
||||
Class centerClass = NSClassFromString(@"MPNowPlayingInfoCenter");
|
||||
if (!centerClass) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
SEL defaultCenterSel = NSSelectorFromString(@"defaultCenter");
|
||||
if (![centerClass respondsToSelector:defaultCenterSel]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return ((id (*)(id, SEL))objc_msgSend)(centerClass, defaultCenterSel);
|
||||
}
|
||||
|
||||
static void
|
||||
ApplyNowPlayingInfo()
|
||||
{
|
||||
id center = GetNowPlayingInfoCenter();
|
||||
if (!center) {
|
||||
return;
|
||||
}
|
||||
|
||||
SEL setInfoSel = NSSelectorFromString(@"setNowPlayingInfo:");
|
||||
if (![center respondsToSelector:setInfoSel]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSDictionary* info = (sNowPlayingInfo && [sNowPlayingInfo count] > 0)
|
||||
? [NSDictionary dictionaryWithDictionary:sNowPlayingInfo]
|
||||
: nil;
|
||||
|
||||
((void (*)(id, SEL, id))objc_msgSend)(center, setInfoSel, info);
|
||||
}
|
||||
|
||||
static void
|
||||
EnsureNowPlayingInfo()
|
||||
{
|
||||
if (!sNowPlayingInfo) {
|
||||
sNowPlayingInfo = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NS_IMETHODIMP
|
||||
MacMediaControlUtils::SetSMTCPlaybackState(bool aPlaying)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
EnsureNowPlayingInfo();
|
||||
[sNowPlayingInfo setObject:[NSNumber numberWithDouble:(aPlaying ? 1.0 : 0.0)]
|
||||
forKey:NowPlayingPlaybackRateKey()];
|
||||
[sNowPlayingInfo setObject:[NSNumber numberWithDouble:0.0]
|
||||
forKey:NowPlayingElapsedTimeKey()];
|
||||
|
||||
id center = GetNowPlayingInfoCenter();
|
||||
if (center) {
|
||||
SEL setPlaybackStateSel = NSSelectorFromString(@"setPlaybackState:");
|
||||
if ([center respondsToSelector:setPlaybackStateSel]) {
|
||||
// MPNowPlayingPlaybackState: 1 = playing, 2 = paused
|
||||
NSInteger state = aPlaying ? 1 : 2;
|
||||
((void (*)(id, SEL, NSInteger))objc_msgSend)(center, setPlaybackStateSel, state);
|
||||
}
|
||||
}
|
||||
|
||||
ApplyNowPlayingInfo();
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MacMediaControlUtils::SetSMTCMetadata(const nsAString& aTitle,
|
||||
const nsAString& aArtist,
|
||||
const nsAString& aAlbum)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
EnsureNowPlayingInfo();
|
||||
|
||||
NSString* title = nsCocoaUtils::ToNSString(aTitle);
|
||||
NSString* artist = nsCocoaUtils::ToNSString(aArtist);
|
||||
NSString* album = nsCocoaUtils::ToNSString(aAlbum);
|
||||
NSString* fallbackTitle = [[NSProcessInfo processInfo] processName];
|
||||
|
||||
if (title && [title length] > 0) {
|
||||
[sNowPlayingInfo setObject:title forKey:MediaItemTitleKey()];
|
||||
} else if (fallbackTitle && [fallbackTitle length] > 0) {
|
||||
[sNowPlayingInfo setObject:fallbackTitle forKey:MediaItemTitleKey()];
|
||||
} else {
|
||||
[sNowPlayingInfo removeObjectForKey:MediaItemTitleKey()];
|
||||
}
|
||||
|
||||
if (artist && [artist length] > 0) {
|
||||
[sNowPlayingInfo setObject:artist forKey:MediaItemArtistKey()];
|
||||
} else {
|
||||
[sNowPlayingInfo removeObjectForKey:MediaItemArtistKey()];
|
||||
}
|
||||
|
||||
if (album && [album length] > 0) {
|
||||
[sNowPlayingInfo setObject:album forKey:MediaItemAlbumTitleKey()];
|
||||
} else {
|
||||
[sNowPlayingInfo removeObjectForKey:MediaItemAlbumTitleKey()];
|
||||
}
|
||||
|
||||
ApplyNowPlayingInfo();
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MacMediaControlUtils::SetSMTCThumbnailURL(const nsAString& aThumbnailURL)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
// Best effort: Artwork publishing requires MediaPlayer artwork classes that
|
||||
// vary by macOS version. Keep this no-op for compatibility.
|
||||
Unused << aThumbnailURL;
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MacMediaControlUtils::ClearSMTCMetadata()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
|
||||
if (sNowPlayingInfo) {
|
||||
[sNowPlayingInfo removeAllObjects];
|
||||
}
|
||||
ApplyNowPlayingInfo();
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ EXPORTS += [
|
|||
UNIFIED_SOURCES += [
|
||||
'ComplexTextInputPanel.mm',
|
||||
'GfxInfo.mm',
|
||||
'MacMediaControlUtils.mm',
|
||||
'NativeKeyBindings.mm',
|
||||
'nsAppShell.mm',
|
||||
'nsBidiKeyboard.mm',
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
#include "nsIServiceManager.h"
|
||||
#include "nsPrintOptionsX.h"
|
||||
#include "nsPrintSettingsX.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "nsIWebBrowserPrint.h"
|
||||
|
||||
// The constants for paper orientation were renamed in 10.9. __MAC_10_9 is
|
||||
// defined on OS X 10.9 and later. Although 10.8 and earlier are not supported
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeCocoa)
|
|||
#include "nsMacDockSupport.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacDockSupport)
|
||||
|
||||
#include "MacMediaControlUtils.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(MacMediaControlUtils)
|
||||
|
||||
#include "nsMacWebAppUtils.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWebAppUtils)
|
||||
|
||||
|
|
@ -112,6 +115,7 @@ NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_NATIVEMENUSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MACDOCKSUPPORT_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MAC_MEDIA_CONTROL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MACWEBAPPUTILS_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_STANDALONENATIVEMENU_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_MACSYSTEMSTATUSBAR_CID);
|
||||
|
|
@ -148,6 +152,7 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, OSXNotificationCenterConstructor },
|
||||
{ &kNS_NATIVEMENUSERVICE_CID, false, NULL, nsNativeMenuServiceXConstructor },
|
||||
{ &kNS_MACDOCKSUPPORT_CID, false, NULL, nsMacDockSupportConstructor },
|
||||
{ &kNS_MAC_MEDIA_CONTROL_CID, false, NULL, MacMediaControlUtilsConstructor },
|
||||
{ &kNS_MACWEBAPPUTILS_CID, false, NULL, nsMacWebAppUtilsConstructor },
|
||||
{ &kNS_STANDALONENATIVEMENU_CID, false, NULL, nsStandaloneNativeMenuConstructor },
|
||||
{ &kNS_MACSYSTEMSTATUSBAR_CID, false, NULL, nsSystemStatusBarCocoaConstructor },
|
||||
|
|
@ -186,6 +191,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/system-alerts-service;1", &kNS_SYSTEMALERTSSERVICE_CID },
|
||||
{ "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID },
|
||||
{ "@mozilla.org/widget/macdocksupport;1", &kNS_MACDOCKSUPPORT_CID },
|
||||
{ "@mozilla.org/mac-media-control;1", &kNS_MAC_MEDIA_CONTROL_CID },
|
||||
{ "@mozilla.org/widget/mac-web-app-utils;1", &kNS_MACWEBAPPUTILS_CID },
|
||||
{ "@mozilla.org/widget/standalonenativemenu;1", &kNS_STANDALONENATIVEMENU_CID },
|
||||
{ "@mozilla.org/widget/macsystemstatusbar;1", &kNS_MACSYSTEMSTATUSBAR_CID },
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ if toolkit == 'windows':
|
|||
elif toolkit == 'cocoa':
|
||||
XPIDL_SOURCES += [
|
||||
'nsIMacDockSupport.idl',
|
||||
'nsIMacMediaControl.idl',
|
||||
'nsIMacWebAppUtils.idl',
|
||||
'nsIStandaloneNativeMenu.idl',
|
||||
'nsISystemStatusBar.idl',
|
||||
|
|
|
|||
31
widget/nsIMacMediaControl.idl
Normal file
31
widget/nsIMacMediaControl.idl
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(9d16f8ac-9d47-4f16-95cf-5ec9b42d3e11)]
|
||||
interface nsIMacMediaControl : nsISupports
|
||||
{
|
||||
/**
|
||||
* Publish playback state to macOS now playing surfaces.
|
||||
*/
|
||||
void setSMTCPlaybackState(in boolean aPlaying);
|
||||
|
||||
/**
|
||||
* Publish media metadata to macOS now playing surfaces.
|
||||
*/
|
||||
void setSMTCMetadata(in AString aTitle,
|
||||
in AString aArtist,
|
||||
in AString aAlbum);
|
||||
|
||||
/**
|
||||
* Publish media artwork URL. Best effort; may be ignored by implementation.
|
||||
*/
|
||||
void setSMTCThumbnailURL(in AString aThumbnailURL);
|
||||
|
||||
/**
|
||||
* Clear published media metadata.
|
||||
*/
|
||||
void clearSMTCMetadata();
|
||||
};
|
||||
|
|
@ -155,6 +155,10 @@
|
|||
#define NS_MACWEBAPPUTILS_CID \
|
||||
{ 0xe9096367, 0xddd9, 0x45e4, { 0xb7, 0x62, 0x49, 0xc0, 0xc1, 0x8b, 0x71, 0x19 } }
|
||||
|
||||
// {7e3bd1b8-e2f4-4fbe-9f1c-d6f7b98a215e}
|
||||
#define NS_MAC_MEDIA_CONTROL_CID \
|
||||
{ 0x7e3bd1b8, 0xe2f4, 0x4fbe, { 0x9f, 0x1c, 0xd6, 0xf7, 0xb9, 0x8a, 0x21, 0x5e } }
|
||||
|
||||
//-----------------------------------------------------------
|
||||
//Printing
|
||||
//-----------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue