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:
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);