mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-08 14:10:11 +01:00
Media (macOS): don't spawn child process
This commit is contained in:
@@ -110,106 +110,9 @@ static const char* getMediaByMediaRemote(FFMediaResult* result, bool saveCover)
|
||||
return error;
|
||||
}
|
||||
|
||||
#if !FF_MODULE_DISABLE_MEDIA
|
||||
// Called from the Perl helper process through `DynaLoader::dl_install_xsub`. That mechanism installs a
|
||||
// plain C function as an XSUB, so Perl calls it with the `CV*` in the first parameter slot and no Perl
|
||||
// argument ever reaches a parameter — a `bool saveCover` parameter read as a pointer and was always
|
||||
// truthy. The flag has to travel in the environment instead; see `getMediaByAuthorizedProcess`.
|
||||
[[gnu::visibility("default"), gnu::used]] int ffPrintMediaByMediaRemote(void) {
|
||||
const char* saveCoverEnv = getenv("FF_MEDIA_REMOTE_SAVE_COVER");
|
||||
bool saveCover = saveCoverEnv && saveCoverEnv[0] == '1';
|
||||
|
||||
FFMediaResult media = {
|
||||
.status = ffStrbufCreate(),
|
||||
.song = ffStrbufCreate(),
|
||||
.artist = ffStrbufCreate(),
|
||||
.album = ffStrbufCreate(),
|
||||
.playerId = ffStrbufCreate(),
|
||||
.player = ffStrbufCreate(),
|
||||
.cover = ffStrbufCreate(),
|
||||
};
|
||||
if (getMediaByMediaRemote(&media, saveCover) != nullptr) {
|
||||
return 1;
|
||||
}
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppend(&media.status, &media.song);
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppend(&media.status, &media.artist);
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppend(&media.status, &media.album);
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppend(&media.status, &media.playerId);
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppend(&media.status, &media.player);
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
if (saveCover) {
|
||||
ffStrbufAppend(&media.status, &media.cover);
|
||||
}
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppendUInt(&media.status, media.position);
|
||||
ffStrbufAppendC(&media.status, '\n');
|
||||
ffStrbufAppendUInt(&media.status, media.length);
|
||||
write(STDOUT_FILENO, media.status.chars, media.status.length);
|
||||
ffStrbufDestroy(&media.status);
|
||||
ffStrbufDestroy(&media.song);
|
||||
ffStrbufDestroy(&media.artist);
|
||||
ffStrbufDestroy(&media.album);
|
||||
ffStrbufDestroy(&media.playerId);
|
||||
ffStrbufDestroy(&media.player);
|
||||
ffStrbufDestroy(&media.cover);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* getMediaByAuthorizedProcess(FFMediaResult* result, bool saveCover) {
|
||||
// #1737
|
||||
// `DynaLoader::dl_install_xsub` hands the C function the `CV*` as its first parameter, so the flag
|
||||
// cannot be passed as a Perl argument — `ffPrintMediaByMediaRemote` reads it from the environment,
|
||||
// which the child process inherits.
|
||||
FF_STRBUF_AUTO_DESTROY script = ffStrbufCreateF("$ENV{'FF_MEDIA_REMOTE_SAVE_COVER'}='%c';\
|
||||
require DynaLoader;\
|
||||
my $so = DynaLoader::dl_load_file('%s', 0);\
|
||||
my $sym = DynaLoader::dl_find_symbol($so, 'ffPrintMediaByMediaRemote');\
|
||||
DynaLoader::dl_install_xsub('fn', $sym, __FILE__);\
|
||||
exit(fn())",
|
||||
saveCover ? '1' : '0',
|
||||
instance.state.platform.exePath.chars);
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
|
||||
const char* error = ffProcessAppendStdOut(
|
||||
&buffer,
|
||||
(char* const[]) { "/usr/bin/perl", // Must be signed by Apple. Homebrew version doesn't work
|
||||
"-e",
|
||||
script.chars,
|
||||
nil });
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
if (buffer.length == 0) {
|
||||
return "No media found";
|
||||
}
|
||||
|
||||
// status\ntitle\nartist\nalbum\nbundleName\nappName\ncoverPath\nelapsedTimeMS\ndurationMS
|
||||
FFstrbuf* const strList[] = { &result->status, &result->song, &result->artist, &result->album, &result->playerId, &result->player, &result->cover };
|
||||
char* line = nullptr;
|
||||
size_t len = 0;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(strList) && ffStrbufGetline(&line, &len, &buffer); ++i) {
|
||||
ffStrbufSetS(strList[i], line);
|
||||
}
|
||||
uint32_t* const numList[] = { &result->position, &result->length };
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(numList) && ffStrbufGetline(&line, &len, &buffer); ++i) {
|
||||
*numList[i] = (uint32_t) strtoul(line, nullptr, 10);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ffDetectMediaImpl(FFMediaResult* media, bool saveCover) {
|
||||
const char* error;
|
||||
if (@available(macOS 15.4, *)) {
|
||||
error = getMediaByAuthorizedProcess(media, saveCover);
|
||||
} else {
|
||||
error = getMediaByMediaRemote(media, saveCover);
|
||||
}
|
||||
const char* error = getMediaByMediaRemote(media, saveCover);
|
||||
|
||||
if (error) {
|
||||
ffStrbufAppendS(&media->error, error);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user