From c23ea4d63c95a215aa03f1b9103e0c734010a877 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Fri, 7 Aug 2026 03:16:26 +0000
Subject: [PATCH 14/38] codec (Apple): dlopen VideoToolbox instead of linking
 it directly

VideoToolbox doesn't exist pre-10.7; resolve VTCopyVideoEncoderList and
VTIsHardwareDecodeSupported via dlopen/dlsym with RTLD_NOLOAD so the
binary degrades to reporting no codecs instead of failing to link.

Ported from https://github.com/macos-powerpc/powerpc-ports/blob/main/sysutils/fastfetch/files/0012-Misc-fixes-for-legacy-systems.patch
---
 src/detection/codec/codec_apple.c | 54 ++++++++++++++++++++++++++++---
 1 file changed, 49 insertions(+), 5 deletions(-)

diff --git a/src/detection/codec/codec_apple.c b/src/detection/codec/codec_apple.c
index 2cf2a48b2..dd51f981b 100644
--- a/src/detection/codec/codec_apple.c
+++ b/src/detection/codec/codec_apple.c
@@ -1,12 +1,46 @@
 #include "codec.h"
-
-#include <VideoToolbox/VideoToolbox.h>
 #include "common/apple/cf_helpers.h"
 
+#include <dlfcn.h>
+#include <stdint.h>
+#include <AvailabilityMacros.h>
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+    #include <VideoToolbox/VideoToolbox.h>
+#else
+    /* CoreMedia is not available; define the type and constants manually.
+     * CMVideoCodecType is FourCharCode which is uint32_t. */
+    typedef uint32_t CMVideoCodecType;
+#endif
+
+/* Use plain uint32_t in the typedefs so they compile even without CoreMedia. */
+typedef int  (*VTCopyVideoEncoderList_fn)(void*, CFArrayRef*);
+typedef int  (*VTIsHardwareDecodeSupported_fn)(uint32_t);
+
+static VTCopyVideoEncoderList_fn      pVTCopyVideoEncoderList      = nullptr;
+static VTIsHardwareDecodeSupported_fn pVTIsHardwareDecodeSupported = nullptr;
+
 #ifdef MAC_OS_VERSION_11_0
 [[clang::weak_import]] VT_EXPORT void VTRegisterSupplementalVideoDecoderIfAvailable(CMVideoCodecType codecType);
 #endif
 
+static void ffCodecLoadSymbols(void) {
+    static bool loaded = false;
+    if (loaded) return;
+    loaded = true;
+    /* RTLD_LAZY | RTLD_NOLOAD: only succeed if the framework is already present */
+    void* vt = dlopen(
+        "/System/Library/Frameworks/VideoToolbox.framework/VideoToolbox",
+        RTLD_LAZY | RTLD_NOLOAD);
+    if (!vt) {
+        return;
+    }
+    pVTCopyVideoEncoderList      = (VTCopyVideoEncoderList_fn)
+        dlsym(vt, "VTCopyVideoEncoderList");
+    pVTIsHardwareDecodeSupported = (VTIsHardwareDecodeSupported_fn)
+        dlsym(vt, "VTIsHardwareDecodeSupported");
+}
+
 static const struct {
     CMVideoCodecType codec;
     FFCodecType type;
@@ -45,8 +79,11 @@
 }
 
 static FFCodecType ffCodecDetectEncoders(void) {
+    if (!pVTCopyVideoEncoderList)
+        return FF_CODEC_TYPE_NONE;
+
     FF_CFTYPE_AUTO_RELEASE CFArrayRef encoderList = nullptr;
-    if (VTCopyVideoEncoderList(nullptr, &encoderList) != noErr || !encoderList) {
+    if (pVTCopyVideoEncoderList(nullptr, &encoderList) != 0 || !encoderList) {
         return FF_CODEC_TYPE_NONE;
     }
 
@@ -66,7 +103,10 @@
     return types;
 }
 
-static FFCodecType ffCodecDetectDecoders() {
+static FFCodecType ffCodecDetectDecoders(void) {
+    if (!pVTIsHardwareDecodeSupported)
+        return FF_CODEC_TYPE_NONE;
+
     FFCodecType types = FF_CODEC_TYPE_NONE;
     for (uint32_t i = 0; i < ARRAY_SIZE(FF_CODEC_CODECS); ++i) {
         auto codec = FF_CODEC_CODECS[i];
@@ -79,7 +119,7 @@
             VTRegisterSupplementalVideoDecoderIfAvailable(codec.codec);
         }
 #endif
-        bool supported = VTIsHardwareDecodeSupported(codec.codec);
+        bool supported = pVTIsHardwareDecodeSupported((uint32_t) codec.codec);
         if (!supported) {
             continue;
         }
@@ -91,6 +131,8 @@
 }
 
 const char* ffDetectCodecNative(FFCodecOptions* options, FFlist* result /* list of FFCodecResult */) {
+    ffCodecLoadSymbols();
+
     FFCodecType decoders = options->showType & FF_CODEC_SHOW_TYPE_DECODER ? ffCodecDetectDecoders() : FF_CODEC_TYPE_NONE;
     FFCodecType encoders = options->showType & FF_CODEC_SHOW_TYPE_ENCODER ? ffCodecDetectEncoders() : FF_CODEC_TYPE_NONE;
 
