Skip to content

Commit 6f2748e

Browse files
Merge pull request #242 from CarterLi/master
Media: support song detection on macOS
2 parents fb3eb96 + bbdeb66 commit 6f2748e

File tree

8 files changed

+80
-13
lines changed

8 files changed

+80
-13
lines changed

CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,6 @@ set(LIBFASTFETCH_SRC
189189
src/detection/gtk.c
190190
src/detection/terminalShell.c
191191
src/detection/vulkan.c
192-
src/detection/media.c
193192
src/detection/datetime.c
194193
src/detection/temps.c
195194
src/detection/title.c
@@ -253,6 +252,7 @@ if(APPLE)
253252
src/detection/terminalfont/terminalfont_apple.c
254253
src/util/apple/cfdict_helpers.c
255254
src/util/apple/osascript.m
255+
src/detection/media/media_apple.m
256256
)
257257
elseif(ANDROID)
258258
list(APPEND LIBFASTFETCH_SRC
@@ -264,6 +264,7 @@ elseif(ANDROID)
264264
src/detection/memory/memory_linux.c
265265
src/detection/displayserver/displayserver_android.c
266266
src/detection/terminalfont/terminalfont_android.c
267+
src/detection/media/media_linux.c
267268
)
268269
else()
269270
list(APPEND LIBFASTFETCH_SRC
@@ -279,6 +280,7 @@ else()
279280
src/detection/displayserver/linux/xlib.c
280281
src/detection/displayserver/linux/wmde.c
281282
src/detection/terminalfont/terminalfont_linux.c
283+
src/detection/media/media_linux.c
282284
)
283285
endif()
284286

src/detection/media.h renamed to src/detection/media/media.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ typedef struct FFMediaResult
1313
FFstrbuf artist;
1414
FFstrbuf album;
1515
FFstrbuf url;
16+
const char* error;
1617
} FFMediaResult;
1718

1819
const FFMediaResult* ffDetectMedia(FFinstance* instance);

src/detection/media/media_apple.m

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#include "fastfetch.h"
2+
#include "detection/media/media.h"
3+
#include "common/library.h"
4+
#include "util/apple/cfdict_helpers.h"
5+
6+
#import <pthread.h>
7+
#import <Foundation/Foundation.h>
8+
#import <CoreFoundation/CoreFoundation.h>
9+
10+
void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t dispatcher, void(^callback)(_Nullable CFDictionaryRef info));
11+
12+
const char* getMedia(FFMediaResult* result)
13+
{
14+
ffStrbufInit(&result->busNameShort);
15+
ffStrbufInit(&result->player);
16+
ffStrbufInit(&result->song);
17+
ffStrbufInit(&result->artist);
18+
ffStrbufInit(&result->album);
19+
ffStrbufInit(&result->url);
20+
21+
FFstrbuf fake;
22+
ffStrbufInitA(&fake, 0);//MediaRemote is a macOS builtin framework thus its path should not change
23+
24+
FF_LIBRARY_LOAD(
25+
MediaRemote,
26+
fake,
27+
"dlopen MediaRemote failed",
28+
"/System/Library/PrivateFrameworks/MediaRemote.framework/MediaRemote",
29+
1);
30+
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(MediaRemote, MRMediaRemoteGetNowPlayingInfo);
31+
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
32+
ffMRMediaRemoteGetNowPlayingInfo(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^(_Nullable CFDictionaryRef info) {
33+
if(info != nil) {
34+
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song);
35+
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist);
36+
ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album);
37+
}
38+
dispatch_semaphore_signal(semaphore);
39+
});
40+
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
41+
return NULL;
42+
}
43+
44+
const FFMediaResult* ffDetectMedia(FFinstance* instance)
45+
{
46+
FF_UNUSED(instance)
47+
static FFMediaResult result;
48+
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
49+
static bool init = false;
50+
51+
if(!init)
52+
{
53+
pthread_mutex_lock(&mutex);
54+
if(!init)
55+
{
56+
result.error = getMedia(&result);
57+
init = true;
58+
}
59+
pthread_mutex_unlock(&mutex);
60+
}
61+
62+
return &result;
63+
}

src/detection/media.c renamed to src/detection/media/media_linux.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "fastfetch.h"
2-
#include "detection/media.h"
2+
#include "detection/media/media.h"
33

44
#include <string.h>
55
#include <pthread.h>

src/modules/player.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "fastfetch.h"
22
#include "common/printing.h"
3-
#include "detection/media.h"
3+
#include "detection/media/media.h"
44

55
#include <ctype.h>
66

src/modules/song.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "fastfetch.h"
22
#include "common/printing.h"
3-
#include "detection/media.h"
3+
#include "detection/media/media.h"
44

55
#include <ctype.h>
66

src/util/apple/cfdict_helpers.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include "cfdict_helpers.h"
22

3-
bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* result)
3+
bool ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result)
44
{
55
CFTypeRef cf = (CFTypeRef)CFDictionaryGetValue(dict, key);
66
if(cf == NULL)
@@ -10,12 +10,13 @@ bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* r
1010
{
1111
CFStringRef cfStr = (CFStringRef)cf;
1212
uint32_t length = (uint32_t)CFStringGetLength(cfStr);
13-
ffStrbufEnsureFree(result, length + 1);
14-
if(CFStringGetCString(cfStr, result->chars, length + 1, kCFStringEncodingASCII))
13+
//CFString stores UTF16 characters, therefore may require larger buffer to convert to UTF8 string
14+
ffStrbufEnsureFree(result, length * 2);
15+
if(CFStringGetCString(cfStr, result->chars, result->allocated, kCFStringEncodingUTF8))
1516
{
16-
result->length = length;
1717
// CFStringGetCString ensures the buffer is NUL terminated
1818
// https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
19+
result->length = strnlen(result->chars, (uint32_t)result->allocated);
1920
}
2021
}
2122
else if(CFGetTypeID(cf) == CFDataGetTypeID())
@@ -34,7 +35,7 @@ bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* r
3435
return true;
3536
}
3637

37-
bool ffCfDictGetBool(CFMutableDictionaryRef dict, CFStringRef key, bool* result)
38+
bool ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result)
3839
{
3940
CFBooleanRef cf = (CFBooleanRef)CFDictionaryGetValue(dict, key);
4041
if(cf == NULL || CFGetTypeID(cf) != CFBooleanGetTypeID())
@@ -44,7 +45,7 @@ bool ffCfDictGetBool(CFMutableDictionaryRef dict, CFStringRef key, bool* result)
4445
return true;
4546
}
4647

47-
bool ffCfDictGetInt(CFMutableDictionaryRef dict, CFStringRef key, int* result)
48+
bool ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result)
4849
{
4950
CFNumberRef cf = (CFNumberRef)CFDictionaryGetValue(dict, key);
5051
if (cf == NULL || CFGetTypeID(cf) != CFNumberGetTypeID())

src/util/apple/cfdict_helpers.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#include "fastfetch.h"
77
#include <CoreFoundation/CoreFoundation.h>
88

9-
bool ffCfDictGetString(CFMutableDictionaryRef dict, CFStringRef key, FFstrbuf* result);
10-
bool ffCfDictGetBool(CFMutableDictionaryRef dict, CFStringRef key, bool* result);
11-
bool ffCfDictGetInt(CFMutableDictionaryRef dict, CFStringRef key, int* result);
9+
bool ffCfDictGetString(CFDictionaryRef dict, CFStringRef key, FFstrbuf* result);
10+
bool ffCfDictGetBool(CFDictionaryRef dict, CFStringRef key, bool* result);
11+
bool ffCfDictGetInt(CFDictionaryRef dict, CFStringRef key, int* result);
1212

1313
#endif

0 commit comments

Comments
 (0)