Media: support song detection on macOS

This commit is contained in:
李通洲
2022-09-19 20:05:23 +08:00
parent 85578c6807
commit bbdeb668d6
8 changed files with 80 additions and 13 deletions
+3 -1
View File
@@ -189,7 +189,6 @@ set(LIBFASTFETCH_SRC
src/detection/gtk.c
src/detection/terminalShell.c
src/detection/vulkan.c
src/detection/media.c
src/detection/datetime.c
src/detection/temps.c
src/detection/title.c
@@ -253,6 +252,7 @@ if(APPLE)
src/detection/terminalfont/terminalfont_apple.c
src/util/apple/cfdict_helpers.c
src/util/apple/osascript.m
src/detection/media/media_apple.m
)
elseif(ANDROID)
list(APPEND LIBFASTFETCH_SRC
@@ -264,6 +264,7 @@ elseif(ANDROID)
src/detection/memory/memory_linux.c
src/detection/displayserver/displayserver_android.c
src/detection/terminalfont/terminalfont_android.c
src/detection/media/media_linux.c
)
else()
list(APPEND LIBFASTFETCH_SRC
@@ -279,6 +280,7 @@ else()
src/detection/displayserver/linux/xlib.c
src/detection/displayserver/linux/wmde.c
src/detection/terminalfont/terminalfont_linux.c
src/detection/media/media_linux.c
)
endif()
@@ -13,6 +13,7 @@ typedef struct FFMediaResult
FFstrbuf artist;
FFstrbuf album;
FFstrbuf url;
const char* error;
} FFMediaResult;
const FFMediaResult* ffDetectMedia(FFinstance* instance);
+63
View File
@@ -0,0 +1,63 @@
#include "fastfetch.h"
#include "detection/media/media.h"
#include "common/library.h"
#include "util/apple/cfdict_helpers.h"
#import <pthread.h>
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t dispatcher, void(^callback)(_Nullable CFDictionaryRef info));
const char* getMedia(FFMediaResult* result)
{
ffStrbufInit(&result->busNameShort);
ffStrbufInit(&result->player);
ffStrbufInit(&result->song);
ffStrbufInit(&result->artist);
ffStrbufInit(&result->album);
ffStrbufInit(&result->url);
FFstrbuf fake;
ffStrbufInitA(&fake, 0);//MediaRemote is a macOS builtin framework thus its path should not change
FF_LIBRARY_LOAD(
MediaRemote,
fake,
"dlopen MediaRemote failed",
"/System/Library/PrivateFrameworks/MediaRemote.framework/MediaRemote",
1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(MediaRemote, MRMediaRemoteGetNowPlayingInfo);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ffMRMediaRemoteGetNowPlayingInfo(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(_Nullable CFDictionaryRef info) {
if(info != nil) {
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song);
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist);
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album);
}
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return NULL;
}
const FFMediaResult* ffDetectMedia(FFinstance* instance)
{
FF_UNUSED(instance)
static FFMediaResult result;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static bool init = false;
if(!init)
{
pthread_mutex_lock(&mutex);
if(!init)
{
result.error = getMedia(&result);
init = true;
}
pthread_mutex_unlock(&mutex);
}
return &result;
}
@@ -1,5 +1,5 @@
#include "fastfetch.h"
#include "detection/media.h"
#include "detection/media/media.h"
#include <string.h>
#include <pthread.h>
+1 -1
View File
@@ -1,6 +1,6 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "detection/media.h"
#include "detection/media/media.h"
#include <ctype.h>
+1 -1
View File
@@ -1,6 +1,6 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "detection/media.h"
#include "detection/media/media.h"
#include <ctype.h>
+7 -6
View File
@@ -1,6 +1,6 @@
#include "cfdict_helpers.h"
bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* result)
bool ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result)
{
CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key);
if(cf == NULL)
@@ -10,12 +10,13 @@ bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* r
{
CFStringRef cfStr = (CFStringRef)cf;
uint32_t length = (uint32_t)CFStringGetLength(cfStr);
ffStrbufEnsureFree(result, length + 1);
if(CFStringGetCString(cfStr, result->chars, length + 1, kCFStringEncodingASCII))
//CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string
ffStrbufEnsureFree(result, length * 2);
if(CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8))
{
result->length = length;
// CFStringGetCString ensures the buffer is NUL terminated
// https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
result->length = strnlen(result->chars, (uint32_t)result->allocated);
}
}
else if(CFGetTypeID(cf) == CFDataGetTypeID())
@@ -34,7 +35,7 @@ bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* r
return true;
}
bool ffCfDictGetBool(CFMutableDictionaryRef dict, CFStringRef key, bool* result)
bool ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result)
{
CFBooleanRef cf = (CFBooleanRef)CFDictionaryGetValue(dict, key);
if(cf == NULL || CFGetTypeID(cf) != CFBooleanGetTypeID())
@@ -44,7 +45,7 @@ bool ffCfDictGetBool(CFMutableDictionaryRef dict, CFStringRef key, bool* result)
return true;
}
bool ffCfDictGetInt(CFMutableDictionaryRef dict, CFStringRef key, int* result)
bool ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result)
{
CFNumberRef cf = (CFNumberRef)CFDictionaryGetValue(dict, key);
if (cf == NULL || CFGetTypeID(cf) != CFNumberGetTypeID())
+3 -3
View File
@@ -6,8 +6,8 @@
#include "fastfetch.h"
#include <CoreFoundation/CoreFoundation.h>
bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* result);
bool ffCfDictGetBool(CFMutableDictionaryRef dict, CFStringRef key, bool* result);
bool ffCfDictGetInt(CFMutableDictionaryRef dict, CFStringRef key, int* result);
bool ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
bool ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
bool ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result);
#endif