draconisplusplus/src/os/macos/NowPlayingBridge.mm
2024-06-05 19:04:53 -04:00

90 lines
2.3 KiB
Text

// NowPlayingBridge.mm
#import "NowPlayingBridge.h"
#import <Foundation/Foundation.h>
#import <dispatch/dispatch.h>
#import <objc/runtime.h>
typedef void (*MRMediaRemoteGetNowPlayingInfoFunction)(
dispatch_queue_t queue, void (^handler)(NSDictionary *information));
@implementation NowPlayingBridge
+ (NSDictionary *)currentPlayingMetadata {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast"
CFURLRef ref = (__bridge CFURLRef)
[NSURL fileURLWithPath:
@"/System/Library/PrivateFrameworks/MediaRemote.framework"];
#pragma clang diagnostic pop
CFBundleRef bundle = CFBundleCreate(kCFAllocatorDefault, ref);
if (!bundle) {
NSLog(@"Failed to load MediaRemote framework");
return nil;
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast"
MRMediaRemoteGetNowPlayingInfoFunction MRMediaRemoteGetNowPlayingInfo =
(MRMediaRemoteGetNowPlayingInfoFunction)CFBundleGetFunctionPointerForName(
bundle, CFSTR("MRMediaRemoteGetNowPlayingInfo"));
#pragma clang diagnostic pop
if (!MRMediaRemoteGetNowPlayingInfo) {
NSLog(@"Failed to get function pointer for MRMediaRemoteGetNowPlayingInfo");
CFRelease(bundle);
return nil;
}
__block NSDictionary *nowPlayingInfo = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
MRMediaRemoteGetNowPlayingInfo(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^(NSDictionary *information) {
nowPlayingInfo = [information copy];
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
CFRelease(bundle);
return nowPlayingInfo;
}
@end
extern "C" {
const char *getCurrentPlayingTitle() {
NSDictionary *metadata = [NowPlayingBridge currentPlayingMetadata];
if (metadata == nil) {
return nullptr;
}
NSString *title =
[metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoTitle"];
if (title) {
return strdup([title UTF8String]);
}
return nullptr;
}
const char *getCurrentPlayingArtist() {
NSDictionary *metadata = [NowPlayingBridge currentPlayingMetadata];
if (metadata == nil) {
return nullptr;
}
NSString *artist =
[metadata objectForKey:@"kMRMediaRemoteNowPlayingInfoArtist"];
if (artist) {
return strdup([artist UTF8String]);
}
return nullptr;
}
}