diff --git a/CMakeLists.txt b/CMakeLists.txt index b1b9be5..acf87cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ file(GLOB_RECURSE SOURCES "src/*.cpp") #enable objective c support on mac os, needed for wxwidgets and compile for both intel macs and apple sillicon macs if(APPLE) - list(APPEND SOURCES "src/backends/darwin.mm" ${CMAKE_SOURCE_DIR}/osx/icon.icns ${CMAKE_SOURCE_DIR}/osx/MediaRemote.scptd) + list(APPEND SOURCES "src/backends/darwin.mm" ${CMAKE_SOURCE_DIR}/osx/icon.icns ${CMAKE_SOURCE_DIR}/osx/MediaRemote.js) set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "" FORCE) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "" FORCE) project ("PlayerLink" LANGUAGES C CXX OBJCXX) @@ -32,7 +32,7 @@ if(WIN32) elseif(APPLE) 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.scptd PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") + set_source_files_properties(${CMAKE_SOURCE_DIR}/osx/MediaRemote.js PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") set_target_properties(PlayerLink PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/osx/Info.plist) elseif(UNIX AND NOT APPLE) list(APPEND LIBRARIES dbus) diff --git a/osx/MediaRemote.js b/osx/MediaRemote.js new file mode 100644 index 0000000..e5c9fa1 --- /dev/null +++ b/osx/MediaRemote.js @@ -0,0 +1,33 @@ +ObjC.import('Foundation'); +try { + const frameworkPath = '/System/Library/PrivateFrameworks/MediaRemote.framework'; + const framework = $.NSBundle.bundleWithPath($(frameworkPath)); + framework.load + + const MRNowPlayingRequest = $.NSClassFromString('MRNowPlayingRequest'); + + const playerPath = MRNowPlayingRequest.localNowPlayingPlayerPath; + const bundleID = ObjC.unwrap(playerPath.client.bundleIdentifier); + + const nowPlayingItem = MRNowPlayingRequest.localNowPlayingItem; + const info = nowPlayingItem.nowPlayingInfo; + + const title = info.valueForKey('kMRMediaRemoteNowPlayingInfoTitle'); + const album = info.valueForKey('kMRMediaRemoteNowPlayingInfoAlbum'); + const artist = info.valueForKey('kMRMediaRemoteNowPlayingInfoArtist'); + const duration = info.valueForKey('kMRMediaRemoteNowPlayingInfoDuration'); + const playbackStatus = info.valueForKey('kMRMediaRemoteNowPlayingInfoPlaybackRate'); + const elapsed = info.valueForKey('kMRMediaRemoteNowPlayingInfoElapsedTime'); + + JSON.stringify({ + title: ObjC.unwrap(title), + album: ObjC.unwrap(album), + artist: ObjC.unwrap(artist), + duration: ObjC.unwrap(duration), + playbackStatus: ObjC.unwrap(playbackStatus), + elapsed: ObjC.unwrap(elapsed), + player: ObjC.unwrap(bundleID) + }); +} catch (error) { + JSON.stringify({ player: 'none', error: error.toString() }); +} \ No newline at end of file diff --git a/osx/MediaRemote.scptd b/osx/MediaRemote.scptd deleted file mode 100644 index 02d8ad3..0000000 --- a/osx/MediaRemote.scptd +++ /dev/null @@ -1,30 +0,0 @@ -use framework "Foundation" -try - set MediaRemote to current application's NSBundle's bundleWithPath:"/System/Library/PrivateFrameworks/MediaRemote.framework/" - MediaRemote's load() - - set MRNowPlayingRequest to current application's NSClassFromString("MRNowPlayingRequest") - set bundleID to MRNowPlayingRequest's localNowPlayingPlayerPath()'s client()'s bundleIdentifier() - set info to MRNowPlayingRequest's localNowPlayingItem()'s nowPlayingInfo() - set title to info's valueForKey:"kMRMediaRemoteNowPlayingInfoTitle" - set album to info's valueForKey:"kMRMediaRemoteNowPlayingInfoAlbum" - set artist to info's valueForKey:"kMRMediaRemoteNowPlayingInfoArtist" - set duration to info's valueForKey:"kMRMediaRemoteNowPlayingInfoDuration" - set playbackStatus to info's valueForKey:"kMRMediaRemoteNowPlayingInfoPlaybackRate" - set elapsed to info's valueForKey:"kMRMediaRemoteNowPlayingInfoElapsedTime" - - set jsonString to "{" - set jsonString to jsonString & "\"title\": \"" & title & "\", " - set jsonString to jsonString & "\"album\": \"" & album & "\", " - set jsonString to jsonString & "\"artist\": \"" & artist & "\", " - set jsonString to jsonString & "\"duration\": \"" & duration & "\", " - set jsonString to jsonString & "\"playbackStatus\": \"" & playbackStatus & "\", " - set jsonString to jsonString & "\"elapsed\": \"" & elapsed & "\"," - set jsonString to jsonString & "\"player\": \"" & bundleID & "\"" - set jsonString to jsonString & "}" - return jsonString -on error - set jsonString to "{\"player\": \"none\"}" - return jsonString -end try - diff --git a/src/backends/darwin.mm b/src/backends/darwin.mm index 2ee2231..e55b9d4 100644 --- a/src/backends/darwin.mm +++ b/src/backends/darwin.mm @@ -39,15 +39,15 @@ NSString* executeCommand(NSString* command, NSArray* arguments) { } std::shared_ptr backend::getMediaInformation() { - static NSString* script = getFilePathFromBundle(@"MediaRemote", @"scptd"); - NSString* output = executeCommand(@"/usr/bin/osascript", @[script]); + static NSString* script = getFilePathFromBundle(@"MediaRemote", @"js"); + NSString* output = executeCommand(@"/usr/bin/osascript", @[@"-l", @"JavaScript", script]); nlohmann::json j = nlohmann::json::parse([output UTF8String]); std::string appName = j["player"].get(); if (appName == "none") return nullptr; - bool paused = j["playbackStatus"].get() == "0"; + bool paused = j["playbackStatus"].get() == 0; std::string songTitle = j["title"].get(); @@ -58,10 +58,10 @@ std::shared_ptr backend::getMediaInformation() { int64_t elapsedTimeMs = 0; int64_t durationMs = 0; try { - double durationNumber = std::stod(j["duration"].get()); + double durationNumber = j["duration"].get(); durationMs = static_cast(durationNumber * 1000); - double elapsedTimeNumber = std::stod(j["elapsed"].get()); + double elapsedTimeNumber = j["elapsed"].get(); elapsedTimeMs = static_cast(elapsedTimeNumber * 1000); } catch (...) {}