DPF

DISTRHO Plugin Framework
Log | Files | Refs | Submodules | README | LICENSE

commit bff2d396592c1249d7b1c96ef1e9f0f7a3e7c088
parent 94f4e33aa6b24dbaa33a38dd12442fd5bea1721d
Author: falkTX <falktx@falktx.com>
Date:   Mon, 26 Feb 2024 00:07:56 +0100

Implement programs for AU

Signed-off-by: falkTX <falktx@falktx.com>

Diffstat:
Mdistrho/src/DistrhoPluginAU.cpp | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mdistrho/src/DistrhoPluginExport.cpp | 11++++++++---
Mdistrho/src/DistrhoUIAU.mm | 5+++++
3 files changed, 136 insertions(+), 20 deletions(-)

diff --git a/distrho/src/DistrhoPluginAU.cpp b/distrho/src/DistrhoPluginAU.cpp @@ -247,16 +247,15 @@ public: , fMidiEventCount(0) #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS - , fCurrentProgram(0) + , fCurrentProgram(-1) + , fLastFactoryProgram(0) + , fProgramCount(fPlugin.getProgramCount()) + , fFactoryPresetsData(nullptr) #endif #if DISTRHO_PLUGIN_WANT_STATE , fStateCount(fPlugin.getStateCount()) #endif - { - fCurrentPreset.presetName = CFSTR("Default"); - fCurrentPreset.presetNumber = 0; - if (fParameterCount != 0) { fLastParameterValues = new float[fParameterCount]; @@ -280,6 +279,33 @@ public: std::memset(&fMidiOutputPackets, 0, sizeof(fMidiOutputPackets)); #endif + #if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fProgramCount != 0) + { + fFactoryPresetsData = new AUPreset[fProgramCount]; + std::memset(fFactoryPresetsData, 0, sizeof(AUPreset) * fProgramCount); + + for (uint32_t i=0; i<fProgramCount; ++i) + { + fFactoryPresetsData[i].presetNumber = i; + fFactoryPresetsData[i].presetName = CFStringCreateWithCString(nullptr, + fPlugin.getProgramName(i), + kCFStringEncodingUTF8); + } + } + else + { + fFactoryPresetsData = new AUPreset; + std::memset(fFactoryPresetsData, 0, sizeof(AUPreset)); + + fFactoryPresetsData->presetNumber = 0; + fFactoryPresetsData->presetName = CFSTR("Default"); + } + #endif + + fUserPresetData.presetNumber = -1; + fUserPresetData.presetName = CFSTR(""); + #if DISTRHO_PLUGIN_WANT_STATE for (uint32_t i=0; i<fStateCount; ++i) { @@ -298,8 +324,14 @@ public: ~PluginAU() { - CFRelease(fCurrentPreset.presetName); delete[] fLastParameterValues; + CFRelease(fUserPresetData.presetName); + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + for (uint32_t i=0; i<fProgramCount; ++i) + CFRelease(fFactoryPresetsData[i].presetName); + delete[] fFactoryPresetsData; + #endif } OSStatus auInitialize() @@ -451,6 +483,17 @@ public: outWritable = true; return noErr; + case kAudioUnitProperty_FactoryPresets: + DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); + DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); + #if DISTRHO_PLUGIN_WANT_PROGRAMS + outDataSize = sizeof(CFArrayRef); + outWritable = false; + return noErr; + #else + return kAudioUnitErr_InvalidProperty; + #endif + case kAudioUnitProperty_HostCallbacks: DISTRHO_SAFE_ASSERT_UINT_RETURN(inScope == kAudioUnitScope_Global, inScope, kAudioUnitErr_InvalidScope); DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); @@ -795,6 +838,19 @@ public: // TODO break; + #if DISTRHO_PLUGIN_WANT_PROGRAMS + case kAudioUnitProperty_FactoryPresets: + if (const CFMutableArrayRef presetsRef = CFArrayCreateMutable(nullptr, fProgramCount, nullptr)) + { + for (uint32_t i=0; i<fProgramCount; ++i) + CFArrayAppendValue(presetsRef, &fFactoryPresetsData[i]); + + *static_cast<CFArrayRef*>(outData) = presetsRef; + return noErr; + } + return kAudio_ParamError; + #endif + #if DISTRHO_PLUGIN_WANT_TIMEPOS case kAudioUnitProperty_HostCallbacks: std::memcpy(outData, &fHostCallbackInfo, sizeof(HostCallbackInfo)); @@ -806,7 +862,16 @@ public: return noErr; case kAudioUnitProperty_PresentPreset: - std::memcpy(outData, &fCurrentPreset, sizeof(AUPreset)); + #if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fCurrentProgram >= 0) + { + std::memcpy(outData, &fFactoryPresetsData[fCurrentProgram], sizeof(AUPreset)); + } + else + #endif + { + std::memcpy(outData, &fUserPresetData, sizeof(AUPreset)); + } return noErr; #if DISTRHO_PLUGIN_HAS_UI @@ -865,7 +930,7 @@ public: #if DISTRHO_PLUGIN_WANT_PROGRAMS case 'DPFo': - *static_cast<uint32_t*>(outData) = fCurrentProgram; + *static_cast<uint32_t*>(outData) = fLastFactoryProgram; return noErr; #endif @@ -1136,8 +1201,30 @@ public: DISTRHO_SAFE_ASSERT_UINT_RETURN(inElement == 0, inElement, kAudioUnitErr_InvalidElement); DISTRHO_SAFE_ASSERT_UINT_RETURN(inDataSize == sizeof(AUPreset), inDataSize, kAudioUnitErr_InvalidPropertyValue); { - CFRelease(fCurrentPreset.presetName); - std::memcpy(&fCurrentPreset, inData, sizeof(AUPreset)); + const int32_t presetNumber = static_cast<const AUPreset*>(inData)->presetNumber; + + #if DISTRHO_PLUGIN_WANT_PROGRAMS + if (presetNumber >= 0) + { + if (fCurrentProgram != presetNumber) + { + fCurrentProgram = presetNumber; + fLastFactoryProgram = presetNumber; + fPlugin.loadProgram(fLastFactoryProgram); + notifyListeners('DPFo', kAudioUnitScope_Global, 0); + } + } + else + { + fCurrentProgram = presetNumber; + CFRelease(fUserPresetData.presetName); + std::memcpy(&fUserPresetData, inData, sizeof(AUPreset)); + } + #else + DISTRHO_SAFE_ASSERT_INT_RETURN(presetNumber < 0, presetNumber, kAudioUnitErr_InvalidPropertyValue); + CFRelease(fUserPresetData.presetName); + std::memcpy(&fUserPresetData, inData, sizeof(AUPreset)); + #endif } return noErr; @@ -1573,7 +1660,6 @@ private: const AudioUnit fComponent; // AUv2 related fields - AUPreset fCurrentPreset; OSStatus fLastRenderError; PropertyListeners fPropertyListeners; Float64 fSampleRateForInput; @@ -1601,8 +1687,12 @@ private: #endif #if DISTRHO_PLUGIN_WANT_PROGRAMS - uint32_t fCurrentProgram; + int32_t fCurrentProgram; + uint32_t fLastFactoryProgram; + uint32_t fProgramCount; + AUPreset* fFactoryPresetsData; #endif + AUPreset fUserPresetData; #if DISTRHO_PLUGIN_WANT_STATE const uint32_t fStateCount; @@ -1818,7 +1908,16 @@ private: CFRelease(num); } - CFDictionarySetValue(clsInfo, CFSTR(kAUPresetNameKey), fCurrentPreset.presetName); + #if DISTRHO_PLUGIN_WANT_PROGRAMS + if (fCurrentProgram >= 0) + { + CFDictionarySetValue(clsInfo, CFSTR(kAUPresetNameKey), fFactoryPresetsData[fCurrentProgram].presetName); + } + else + #endif + { + CFDictionarySetValue(clsInfo, CFSTR(kAUPresetNameKey), fUserPresetData.presetName); + } if (const CFMutableDictionaryRef data = CFDictionaryCreateMutable(nullptr, 0, @@ -1949,12 +2048,19 @@ private: if (CFDictionaryGetValueIfPresent(data, CFSTR("program"), reinterpret_cast<const void**>(&programRef)) && CFGetTypeID(programRef) == CFNumberGetTypeID()) { - SInt32 program = 0; - if (CFNumberGetValue(programRef, kCFNumberSInt32Type, &program) && program >= 0) + SInt32 program = -1; + if (CFNumberGetValue(programRef, kCFNumberSInt32Type, &program)) { fCurrentProgram = program; - fPlugin.loadProgram(fCurrentProgram); - notifyListeners('DPFo', kAudioUnitScope_Global, 0); + + if (program >= 0) + { + fLastFactoryProgram = program; + fPlugin.loadProgram(fLastFactoryProgram); + notifyListeners('DPFo', kAudioUnitScope_Global, 0); + } + + notifyListeners(kAudioUnitProperty_PresentPreset, kAudioUnitScope_Global, 0); } } #endif diff --git a/distrho/src/DistrhoPluginExport.cpp b/distrho/src/DistrhoPluginExport.cpp @@ -67,8 +67,11 @@ void generate_au_plist(const PluginExporter& plugin, outputFile << " <string>" << majorVersion << "." << minorVersion << "." << microVersion << "</string>\n"; outputFile << " <key>CFBundleVersion</key>\n"; outputFile << " <string>" << majorVersion << "." << minorVersion << "." << microVersion << "</string>\n"; - outputFile << " <key>NSHumanReadableCopyright</key>\n"; - outputFile << " <string>" << license << "</string>\n"; + if (license != nullptr && license[0] != '\0') + { + outputFile << " <key>NSHumanReadableCopyright</key>\n"; + outputFile << " <string>" << license << "</string>\n"; + } outputFile << " <key>NSHighResolutionCapable</key>\n"; outputFile << " <true/>\n"; outputFile << " <key>AudioComponents</key>\n"; @@ -122,8 +125,10 @@ int main(int argc, char* argv[]) String license(plugin.getLicense()); + if (license.isEmpty()) + {} // License as URL, use as-is - if (license.contains("://")) + else if (license.contains("://")) {} // License contains quotes, use as-is else if (license.contains('"')) diff --git a/distrho/src/DistrhoUIAU.mm b/distrho/src/DistrhoUIAU.mm @@ -474,6 +474,11 @@ END_NAMESPACE_DISTRHO dataSize = sizeof(Float64); AudioUnitGetProperty(component, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, 0, &sampleRate, &dataSize); + #if defined(DISTRHO_UI_DEFAULT_WIDTH) && defined(DISTRHO_UI_DEFAULT_HEIGHT) + const double scaleFactor = [NSScreen mainScreen].backingScaleFactor; + inPreferredSize = NSMakeSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor); + #endif + // create view view = [[[COCOA_VIEW_CLASS_NAME alloc] initWithPreferredSize:inPreferredSize] autorelease]; view->ui = new DPF_UI_AU(component, view, sampleRate, instancePointer);