add old mediaremote way of getting playback data, as osascript way only works on sonoma and newer.
This commit is contained in:
parent
349058c32d
commit
bccf4c6100
|
@ -30,6 +30,14 @@ if(WIN32)
|
|||
list(APPEND LIBRARIES WindowsApp)
|
||||
target_link_options(PlayerLink PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
|
||||
elseif(APPLE)
|
||||
set(MEDIAREMOTE_FRAMEWORK_PATH "/System/Library/PrivateFrameworks")
|
||||
find_library(MEDIAREMOTE_LIBRARY MediaRemote PATHS ${MEDIAREMOTE_FRAMEWORK_PATH})
|
||||
if (MEDIAREMOTE_LIBRARY)
|
||||
message(STATUS "Found MediaRemote: ${MEDIAREMOTE_LIBRARY}")
|
||||
list(APPEND LIBRARIES ${MEDIAREMOTE_LIBRARY})
|
||||
else()
|
||||
message(FATAL_ERROR "MediaRemote framework not found.")
|
||||
endif()
|
||||
set_target_properties(PlayerLink PROPERTIES MACOSX_BUNDLE TRUE)
|
||||
set_source_files_properties(${CMAKE_SOURCE_DIR}/osx/icon.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
set_source_files_properties(${CMAKE_SOURCE_DIR}/osx/MediaRemote.js PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifdef __APPLE__
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoTitle;
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoAlbum;
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoArtist;
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoDuration;
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoElapsedTime;
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoArtworkData;
|
||||
FOUNDATION_EXPORT CFStringRef _Nullable kMRMediaRemoteNowPlayingInfoPlaybackRate;
|
||||
|
||||
typedef void (^ MRMediaRemoteGetNowPlayingInfoCompletion)(CFDictionaryRef _Nullable information);
|
||||
typedef void (^ MRMediaRemoteGetNowPlayingApplicationPIDCompletion)(int PID);
|
||||
|
||||
FOUNDATION_EXPORT void MRMediaRemoteGetNowPlayingApplicationPID(dispatch_queue_t _Nullable queue, MRMediaRemoteGetNowPlayingApplicationPIDCompletion _Nullable completion);
|
||||
FOUNDATION_EXPORT void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t _Nullable queue, MRMediaRemoteGetNowPlayingInfoCompletion _Nullable completion);
|
||||
#endif
|
|
@ -8,6 +8,7 @@
|
|||
#include <nlohmann-json/single_include/nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
|
||||
#include "../MediaRemote.hpp"
|
||||
#include "../backend.hpp"
|
||||
|
||||
void hideDockIcon(bool shouldHide) {
|
||||
|
@ -39,6 +40,8 @@ NSString* executeCommand(NSString* command, NSArray* arguments) {
|
|||
}
|
||||
|
||||
std::shared_ptr<MediaInfo> backend::getMediaInformation() {
|
||||
// apple decided to prevent apps not signed by them to use media remote, so we use an apple script instead. But that script only works on Sonoma or newer and the other one is arguably better, so keep the old method as well
|
||||
if (@available(macOS 15.0, *)) {
|
||||
static NSString *script = getFilePathFromBundle(@"MediaRemote", @"js");
|
||||
NSString *output = executeCommand(@"/usr/bin/osascript", @[ @"-l", @"JavaScript", script ]);
|
||||
nlohmann::json j = nlohmann::json::parse([output UTF8String]);
|
||||
|
@ -63,11 +66,72 @@ std::shared_ptr<MediaInfo> backend::getMediaInformation() {
|
|||
|
||||
double elapsedTimeNumber = j["elapsed"].get<double>();
|
||||
elapsedTimeMs = static_cast<int64_t>(elapsedTimeNumber * 1000);
|
||||
} catch (...) {}
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
return std::make_shared<MediaInfo>(paused, songTitle, songArtist, songAlbum, appName, "",
|
||||
return std::make_shared<MediaInfo>(paused, songTitle, songArtist, songAlbum, appName, "", durationMs,
|
||||
elapsedTimeMs);
|
||||
} else {
|
||||
__block NSString *appName = nil;
|
||||
__block NSDictionary *playingInfo = nil;
|
||||
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
|
||||
dispatch_group_enter(group);
|
||||
MRMediaRemoteGetNowPlayingApplicationPID(dispatch_get_main_queue(), ^(pid_t pid) {
|
||||
if (pid > 0) {
|
||||
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
|
||||
if (app)
|
||||
appName = [[app.bundleIdentifier copy] retain];
|
||||
}
|
||||
dispatch_group_leave(group);
|
||||
});
|
||||
|
||||
dispatch_group_enter(group);
|
||||
MRMediaRemoteGetNowPlayingInfo(dispatch_get_main_queue(), ^(CFDictionaryRef result) {
|
||||
if (result)
|
||||
playingInfo = [[(__bridge NSDictionary *)result copy] retain];
|
||||
dispatch_group_leave(group);
|
||||
});
|
||||
|
||||
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
||||
dispatch_release(group);
|
||||
if (appName == nil || playingInfo == nil)
|
||||
return nullptr;
|
||||
|
||||
bool paused = [playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoPlaybackRate] intValue] == 0;
|
||||
|
||||
NSString *title = playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoTitle];
|
||||
std::string songTitle = title ? [title UTF8String] : "";
|
||||
|
||||
NSString *album = playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoAlbum];
|
||||
std::string songAlbum = album ? [album UTF8String] : "";
|
||||
|
||||
NSString *artist = playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtist];
|
||||
std::string songArtist = artist ? [artist UTF8String] : "";
|
||||
|
||||
NSData *artworkData = playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoArtworkData];
|
||||
|
||||
std::string thumbnailData;
|
||||
if (artworkData)
|
||||
thumbnailData = std::string((const char *)[artworkData bytes], [artworkData length]);
|
||||
|
||||
NSNumber *elapsedTimeNumber = playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoElapsedTime];
|
||||
|
||||
NSNumber *durationNumber = playingInfo[(__bridge NSString *)kMRMediaRemoteNowPlayingInfoDuration];
|
||||
|
||||
int64_t elapsedTimeMs = elapsedTimeNumber ? static_cast<int64_t>([elapsedTimeNumber doubleValue] * 1000) : 0;
|
||||
|
||||
int64_t durationMs = durationNumber ? static_cast<int64_t>([durationNumber doubleValue] * 1000) : 0;
|
||||
|
||||
std::string appNameString = appName.UTF8String;
|
||||
|
||||
[appName release];
|
||||
[playingInfo release];
|
||||
return std::make_shared<MediaInfo>(paused, songTitle, songArtist, songAlbum, appNameString, thumbnailData,
|
||||
durationMs, elapsedTimeMs);
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path backend::getConfigDirectory() {
|
||||
std::filesystem::path configDirectoryPath = std::getenv("HOME");
|
||||
|
|
Loading…
Reference in New Issue