Phase 4: Medien-Widget mit dreistufiger Kaskade
Adapter für alles inklusive Browser, AppleScript für Spotify und Musik, Medientasten als letzte Reserve. Die Reihenfolge ist keine Vorliebe, sondern Absicherung: Apple hat die Now-Playing-Schnittstelle in macOS 15.4 schon einmal zugemacht. Fällt der Adapter aus, verliert das Widget seine Anzeige — aber nicht seine Funktion. Deshalb bleiben die Transporttasten auch dann bedienbar, wenn gar keine Metadaten da sind. Der Fortschritt zählt zwischen den Ereignissen selbst hoch. Spike B hatte gezeigt, dass elapsedTime nicht laufend nachgeliefert wird: ein Scrubber, der stur den letzten Wert anzeigt, steht still, während der Titel läuft. Gerechnet wird aus asOf und playbackRate, begrenzt auf die Titellänge — sonst zeigt die Anzeige nach dem Ende weiter steigende Zahlen. Teilmeldungen (diff = true) ergänzen den Stand, statt ihn zu ersetzen. Eine Meldung mit nur der Position würde sonst Titel, Interpret und Cover löschen. In AnyDecodable wird Bool vor Double geprüft. Andernfalls wird "playing": true zu 1 und die Wiedergabe gilt für immer als angehalten. Play/Pause schaltet sofort um, statt auf das nächste Ereignis zu warten. Ein Knopf, der eine halbe Sekunde später reagiert, fühlt sich kaputt an; das echte Ereignis korrigiert den Stand ohnehin. Der Adapter liegt als Quellcode unter Vendor/ (BSD-3, Stand in ONYX-VERSION.txt) und wird beim Bauen kompiliert, statt als fertige Binary eingecheckt zu werden. Er wird bewusst nicht gelinkt: geladen wird er von /usr/bin/perl, im eigenen Prozess greift Apples Entitlement-Prüfung. 124 Tests grün.
This commit is contained in:
163
Vendor/mediaremote-adapter/src/private/MediaRemote.h
vendored
Normal file
163
Vendor/mediaremote-adapter/src/private/MediaRemote.h
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
// clang-format off
|
||||
|
||||
#ifndef MEDIAREMOTE_PRIVATE_H_
|
||||
#define MEDIAREMOTE_PRIVATE_H_
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#pragma mark Notifications
|
||||
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoDidChangeNotification;
|
||||
extern NSString *kMRMediaRemoteNowPlayingPlaybackQueueDidChangeNotification;
|
||||
extern NSString *kMRMediaRemotePickableRoutesDidChangeNotification;
|
||||
extern NSString *kMRMediaRemoteNowPlayingApplicationDidChangeNotification;
|
||||
extern NSString *kMRMediaRemoteNowPlayingApplicationIsPlayingDidChangeNotification;
|
||||
extern NSString *kMRMediaRemoteRouteStatusDidChangeNotification;
|
||||
|
||||
#pragma mark Keys
|
||||
|
||||
extern NSString *kMRMediaRemoteNowPlayingApplicationPIDUserInfoKey;
|
||||
extern NSString *kMRMediaRemoteNowPlayingApplicationIsPlayingUserInfoKey;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoAlbum;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoArtist;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoArtworkData;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoArtworkMIMEType;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoChapterNumber;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoComposer;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoDuration;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoElapsedTime;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoGenre;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoIsAdvertisement;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoIsBanned;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoIsInWishList;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoIsLiked;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoIsMusicApp;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoPlaybackRate;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoProhibitsSkip;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoQueueIndex;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoRadioStationIdentifier;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoRepeatMode;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoShuffleMode;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoStartTime;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoSupportsFastForward15Seconds;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoSupportsIsBanned;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoSupportsIsLiked;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoSupportsRewind15Seconds;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTimestamp;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTitle;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTotalChapterCount;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTotalDiscCount;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTotalQueueCount;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTotalTrackCount;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoTrackNumber;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoUniqueIdentifier;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoContentItemIdentifier;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoRadioStationHash;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoMediaType;
|
||||
extern NSString *kMRMediaRemoteNowPlayingInfoServiceIdentifier;
|
||||
extern NSString *kMRMediaRemoteOptionMediaType;
|
||||
extern NSString *kMRMediaRemoteOptionSourceID;
|
||||
extern NSString *kMRMediaRemoteOptionTrackID;
|
||||
extern NSString *kMRMediaRemoteOptionStationID;
|
||||
extern NSString *kMRMediaRemoteOptionStationHash;
|
||||
extern NSString *kMRMediaRemoteRouteDescriptionUserInfoKey;
|
||||
extern NSString *kMRMediaRemoteRouteStatusUserInfoKey;
|
||||
|
||||
#pragma mark API
|
||||
|
||||
typedef enum {
|
||||
/*
|
||||
* Use nil for userInfo.
|
||||
*/
|
||||
kMRPlay = 0,
|
||||
kMRPause = 1,
|
||||
kMRTogglePlayPause = 2,
|
||||
kMRStop = 3,
|
||||
kMRNextTrack = 4,
|
||||
kMRPreviousTrack = 5,
|
||||
kMRToggleShuffle = 6,
|
||||
kMRToggleRepeat = 7,
|
||||
kMRStartForwardSeek = 8,
|
||||
kMREndForwardSeek = 9,
|
||||
kMRStartBackwardSeek = 10,
|
||||
kMREndBackwardSeek = 11,
|
||||
kMRGoBackFifteenSeconds = 12,
|
||||
kMRSkipFifteenSeconds = 13,
|
||||
|
||||
/*
|
||||
* Use a NSDictionary for userInfo, which contains three keys:
|
||||
* kMRMediaRemoteOptionTrackID
|
||||
* kMRMediaRemoteOptionStationID
|
||||
* kMRMediaRemoteOptionStationHash
|
||||
*/
|
||||
kMRLikeTrack = 0x6A,
|
||||
kMRBanTrack = 0x6B,
|
||||
kMRAddTrackToWishList = 0x6C,
|
||||
kMRRemoveTrackFromWishList = 0x6D
|
||||
} MRCommand;
|
||||
|
||||
extern CFStringRef MRMediaRemoteSendCommand;
|
||||
typedef bool (*MRMediaRemoteSendCommand_t)(MRCommand command, id userInfo);
|
||||
|
||||
extern CFStringRef MRMediaRemoteSetPlaybackSpeed;
|
||||
extern CFStringRef MRMediaRemoteSetElapsedTime;
|
||||
extern CFStringRef MRMediaRemoteSetShuffleMode;
|
||||
extern CFStringRef MRMediaRemoteSetRepeatMode;
|
||||
typedef void (*MRMediaRemoteSetPlaybackSpeed_t)(int speed);
|
||||
typedef void (*MRMediaRemoteSetElapsedTime_t)(double elapsedTime);
|
||||
typedef void (*MRMediaRemoteSetShuffleMode_t)(int mode);
|
||||
typedef void (*MRMediaRemoteSetRepeatMode_t)(int mode);
|
||||
|
||||
extern CFStringRef MRMediaRemoteRegisterForNowPlayingNotifications;
|
||||
extern CFStringRef MRMediaRemoteUnregisterForNowPlayingNotifications;
|
||||
extern CFStringRef MRMediaRemoteGetNowPlayingApplicationPID;
|
||||
extern CFStringRef MRMediaRemoteGetNowPlayingClient;
|
||||
extern CFStringRef MRMediaRemoteGetNowPlayingInfo;
|
||||
extern CFStringRef MRMediaRemoteGetNowPlayingApplicationIsPlaying;
|
||||
|
||||
typedef void (*MRMediaRemoteRegisterForNowPlayingNotifications_t)(dispatch_queue_t queue);
|
||||
typedef void (*MRMediaRemoteUnregisterForNowPlayingNotifications_t)();
|
||||
|
||||
typedef void (^MRMediaRemoteGetNowPlayingInfoCompletion_t)(NSDictionary *information);
|
||||
typedef void (^MRMediaRemoteGetNowPlayingApplicationPIDCompletion_t)(int PID);
|
||||
typedef void (^MRMediaRemoteGetNowPlayingClientCompletion_t)(id clientObj);
|
||||
typedef void (^MRMediaRemoteGetNowPlayingApplicationIsPlayingCompletion_t)(bool isPlaying);
|
||||
|
||||
typedef void (*MRMediaRemoteGetNowPlayingApplicationPID_t)(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingApplicationPIDCompletion_t completion);
|
||||
typedef void (*MRMediaRemoteGetNowPlayingClient_t)(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingClientCompletion_t completion);
|
||||
typedef void (*MRMediaRemoteGetNowPlayingInfo_t)(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingInfoCompletion_t completion);
|
||||
typedef void (*MRMediaRemoteGetNowPlayingApplicationIsPlaying_t)(dispatch_queue_t queue, MRMediaRemoteGetNowPlayingApplicationIsPlayingCompletion_t completion);
|
||||
|
||||
#pragma mark Miscellaneous
|
||||
|
||||
extern NSString *kMRNowPlayingClientUserInfoKey;
|
||||
|
||||
// Accessed with the kMRNowPlayingClientUserInfoKey
|
||||
// on the userInfo dictionary of an NSNotification.
|
||||
@interface MRClient : NSObject {}
|
||||
-(NSString *)parentApplicationBundleIdentifier;
|
||||
-(NSString *)bundleIdentifier;
|
||||
-(NSString *)displayName;
|
||||
@end
|
||||
|
||||
@interface MediaRemote : NSObject
|
||||
// Commands
|
||||
@property(readonly) MRMediaRemoteSendCommand_t sendCommand;
|
||||
// Other controls
|
||||
@property(readonly) MRMediaRemoteSetPlaybackSpeed_t setPlaybackSpeed;
|
||||
@property(readonly) MRMediaRemoteSetElapsedTime_t setElapsedTime;
|
||||
@property(readonly) MRMediaRemoteSetShuffleMode_t setShuffleMode;
|
||||
@property(readonly) MRMediaRemoteSetRepeatMode_t setRepeatMode;
|
||||
// Observers
|
||||
@property(readonly) MRMediaRemoteRegisterForNowPlayingNotifications_t registerForNowPlayingNotifications;
|
||||
@property(readonly) MRMediaRemoteUnregisterForNowPlayingNotifications_t unregisterForNowPlayingNotifications;
|
||||
// Metadata
|
||||
@property(readonly) MRMediaRemoteGetNowPlayingApplicationPID_t getNowPlayingApplicationPID;
|
||||
@property(readonly) MRMediaRemoteGetNowPlayingClient_t getNowPlayingClient;
|
||||
@property(readonly) MRMediaRemoteGetNowPlayingInfo_t getNowPlayingInfo;
|
||||
@property(readonly) MRMediaRemoteGetNowPlayingApplicationIsPlaying_t getNowPlayingApplicationIsPlaying;
|
||||
// Constructor
|
||||
-(id)init;
|
||||
@end
|
||||
|
||||
#endif /* MEDIAREMOTE_PRIVATE_H_ */
|
||||
Reference in New Issue
Block a user