diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp index b97bdb0d..20cea14d 100644 --- a/distrho/src/DistrhoPluginAU.cpp +++ b/distrho/src/DistrhoPluginAU.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho + * Copyright (C) 2012-2025 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this @@ -1153,6 +1153,8 @@ public: const CFStringRef keyRef = CFStringCreateWithCString(nullptr, fPlugin.getStateKey(i), kCFStringEncodingASCII); + DISTRHO_SAFE_ASSERT_CONTINUE(keyRef != nullptr); + CFArrayAppendValue(keysRef, keyRef); CFRelease(keyRef); } @@ -1647,29 +1649,42 @@ public: case 'DPFs': DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); - DISTRHO_SAFE_ASSERT_UINT_RETURN(inDataSize == sizeof(CFStringRef), inDataSize, kAudioUnitErr_InvalidPropertyValue); + DISTRHO_SAFE_ASSERT_UINT_RETURN(inDataSize == sizeof(CFDictionaryRef), inDataSize, kAudioUnitErr_InvalidPropertyValue); #if DISTRHO_PLUGIN_WANT_STATE - DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement < fStateCount, inElement, kAudioUnitErr_InvalidElement); + DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); { - const CFStringRef valueRef = *static_cast(inData); + const CFDictionaryRef dictRef = *static_cast(inData); + DISTRHO_SAFE_ASSERT_RETURN(CFGetTypeID(dictRef) == CFDictionaryGetTypeID(), + kAudioUnitErr_InvalidPropertyValue); + DISTRHO_SAFE_ASSERT_RETURN(CFDictionaryGetCount(dictRef) == 1, kAudioUnitErr_InvalidPropertyValue); + + CFStringRef keyRef = nullptr; + CFStringRef valueRef = nullptr; + CFDictionaryGetKeysAndValues(dictRef, + reinterpret_cast(&keyRef), + reinterpret_cast(&valueRef)); + DISTRHO_SAFE_ASSERT_RETURN(keyRef != nullptr && CFGetTypeID(keyRef) == CFStringGetTypeID(), + kAudioUnitErr_InvalidPropertyValue); DISTRHO_SAFE_ASSERT_RETURN(valueRef != nullptr && CFGetTypeID(valueRef) == CFStringGetTypeID(), kAudioUnitErr_InvalidPropertyValue); - const CFIndex valueLen = CFStringGetLength(valueRef); - char* const value = static_cast(std::malloc(valueLen + 1)); - DISTRHO_SAFE_ASSERT_RETURN(value != nullptr, kAudio_ParamError); - DISTRHO_SAFE_ASSERT_RETURN(CFStringGetCString(valueRef, value, valueLen + 1, kCFStringEncodingUTF8), + const CFIndex keyRefLen = CFStringGetLength(keyRef); + char* key = static_cast(std::malloc(keyRefLen + 1)); + DISTRHO_SAFE_ASSERT_RETURN(CFStringGetCString(keyRef, key, keyRefLen + 1, kCFStringEncodingASCII), kAudioUnitErr_InvalidPropertyValue); - const String& key(fPlugin.getStateKey(inElement)); + const CFIndex valueRefLen = CFStringGetLength(valueRef); + char* value = static_cast(std::malloc(valueRefLen + 1)); + DISTRHO_SAFE_ASSERT_RETURN(CFStringGetCString(valueRef, value, valueRefLen + 1, kCFStringEncodingUTF8), + kAudioUnitErr_InvalidPropertyValue); - // save this key as needed - if (fPlugin.wantStateKey(key)) - fStateMap[key] = value; + const String dkey(key); - fPlugin.setState(key, value); + // save this key as needed + if (fPlugin.wantStateKey(dkey)) + fStateMap[dkey] = value; - std::free(value); + fPlugin.setState(dkey, value); } return noErr; #else @@ -2561,12 +2576,12 @@ private: CFStringRef keyRef = CFStringCreateWithCString(nullptr, key, kCFStringEncodingASCII); CFStringRef valueRef = CFStringCreateWithCString(nullptr, value, kCFStringEncodingUTF8); - if (CFDictionaryRef dictRef = CFDictionaryCreate(nullptr, - reinterpret_cast(&keyRef), - reinterpret_cast(&valueRef), - 1, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks)) + if (const CFDictionaryRef dictRef = CFDictionaryCreate(nullptr, + reinterpret_cast(&keyRef), + reinterpret_cast(&valueRef), + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)) { CFArrayAppendValue(statesRef, dictRef); CFRelease(dictRef); diff --git a/distrho/src/DistrhoUIAU.mm b/distrho/src/DistrhoUIAU.mm index 1b3f77e5..fb3b1cdd 100644 --- a/distrho/src/DistrhoUIAU.mm +++ b/distrho/src/DistrhoUIAU.mm @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho + * Copyright (C) 2012-2025 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this @@ -125,6 +125,7 @@ public: CFRunLoopAddTimer(CFRunLoopGetCurrent(), fTimerRef, kCFRunLoopCommonModes); + // setup property listeners AudioUnitAddPropertyListener(fComponent, kAudioUnitProperty_SampleRate, auPropertyChangedCallback, this); AudioUnitAddPropertyListener(fComponent, 'DPFp', auPropertyChangedCallback, this); #if DISTRHO_PLUGIN_WANT_PROGRAMS @@ -322,15 +323,22 @@ private: #if DISTRHO_PLUGIN_WANT_STATE void setState(const char* const key, const char* const value) { - const std::vector::iterator it = std::find(fStateKeys.begin(), fStateKeys.end(), key); - DISTRHO_SAFE_ASSERT_RETURN(it != fStateKeys.end(),); - - if (const CFStringRef valueRef = CFStringCreateWithCString(nullptr, value, kCFStringEncodingUTF8)) + CFStringRef keyRef = CFStringCreateWithCString(nullptr, key, kCFStringEncodingASCII); + CFStringRef valueRef = CFStringCreateWithCString(nullptr, value, kCFStringEncodingUTF8); + + if (const CFDictionaryRef dictRef = CFDictionaryCreate(nullptr, + reinterpret_cast(&keyRef), + reinterpret_cast(&valueRef), + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)) { - const uint32_t index = it - fStateKeys.begin(); - AudioUnitSetProperty(fComponent, 'DPFs', kAudioUnitScope_Global, index, &valueRef, sizeof(CFStringRef)); - CFRelease(valueRef); + AudioUnitSetProperty(fComponent, 'DPFs', kAudioUnitScope_Global, 0, &dictRef, sizeof(dictRef)); + CFRelease(dictRef); } + + CFRelease(keyRef); + CFRelease(valueRef); } static void setStateCallback(void* const ptr, const char* const key, const char* const value)