Skip to content

Commit b110f54

Browse files
committed
0.24.1
1 parent e7db7e0 commit b110f54

File tree

12 files changed

+140
-69
lines changed

12 files changed

+140
-69
lines changed

CMakePresets.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
"deprecated": true
3535
},
3636
"cacheVariables": {
37-
"CMAKE_OSX_DEPLOYMENT_TARGET": "12.0",
3837
"CMAKE_OSX_ARCHITECTURES": "arm64;x86_64",
3938
"CODESIGN_IDENTITY": "$penv{CODESIGN_IDENT}",
4039
"CODESIGN_TEAM": "$penv{CODESIGN_TEAM}"
@@ -50,7 +49,8 @@
5049
"generator": "Xcode",
5150
"cacheVariables": {
5251
"CMAKE_COMPILE_WARNING_AS_ERROR": false,
53-
"ENABLE_CCACHE": true
52+
"CMAKE_OSX_DEPLOYMENT_TARGET": "12.0",
53+
"ENABLE_CCACHE": false
5454
}
5555
},
5656
{

lib/atkaudio/src/atkaudio/DeviceIo/DeviceIo.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ struct atk::DeviceIo::Impl : public juce::Timer
1717

1818
~Impl()
1919
{
20+
// Follow the same clean pattern as regular PluginHost
2021
auto* window = this->mainWindow;
2122
auto* manager = this->deviceManager;
22-
auto lambda = [window, manager]()
23+
auto lambda = [window, manager]
2324
{
2425
delete window;
2526
delete manager;
@@ -43,12 +44,22 @@ struct atk::DeviceIo::Impl : public juce::Timer
4344

4445
void setVisible(bool visible)
4546
{
46-
if (!mainWindow->isOnDesktop())
47-
mainWindow->addToDesktop();
47+
auto doUi = [this, visible]
48+
{
49+
if (visible && !mainWindow->isOnDesktop())
50+
{
51+
mainWindow->addToDesktop();
52+
mainWindow->toFront(true);
53+
}
54+
mainWindow->setVisible(visible);
55+
if (visible && mainWindow->isMinimised())
56+
mainWindow->setMinimised(false);
57+
};
4858

49-
mainWindow->setVisible(visible);
50-
if (visible && mainWindow->isMinimised())
51-
mainWindow->setMinimised(false);
59+
if (juce::MessageManager::getInstance()->isThisTheMessageThread())
60+
doUi();
61+
else
62+
juce::MessageManager::callAsync(doUi);
5263
}
5364

5465
void getState(std::string& s)

lib/atkaudio/src/atkaudio/DeviceIo/DeviceIoApp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ class AudioAppMainWindow final : public DocumentWindow
126126
setVisible(false);
127127
}
128128

129+
~AudioAppMainWindow() override
130+
{
131+
// Note: setVisible(false) is handled by atk::destroy() force-hide before this destructor runs
132+
}
133+
129134
void closeButtonPressed() override
130135
{
131136
setVisible(false);

lib/atkaudio/src/atkaudio/PluginHost/PluginHost.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@ struct atk::PluginHost::Impl : public juce::Timer
6464

6565
void process(float** buffer, int newNumChannels, int newNumSamples, double newSampleRate)
6666
{
67-
if (!buffer || this->numChannels != newNumChannels || this->numSamples < newNumSamples
68-
|| this->sampleRate != newSampleRate || isFirstRun.load(std::memory_order_acquire))
67+
if (!buffer
68+
|| this->numChannels != newNumChannels
69+
|| this->numSamples < newNumSamples
70+
|| this->sampleRate != newSampleRate
71+
|| isFirstRun.load(std::memory_order_acquire))
6972
{
7073
isFirstRun.store(false, std::memory_order_release);
7174
this->numChannels = newNumChannels;
@@ -93,12 +96,22 @@ struct atk::PluginHost::Impl : public juce::Timer
9396

9497
void setVisible(bool visible)
9598
{
96-
if (!mainWindow->isOnDesktop())
97-
mainWindow->addToDesktop();
98-
99-
mainWindow->setVisible(visible);
100-
if (visible && mainWindow->isMinimised())
101-
mainWindow->setMinimised(false);
99+
auto doUi = [this, visible]
100+
{
101+
if (visible && !mainWindow->isOnDesktop())
102+
{
103+
mainWindow->addToDesktop();
104+
mainWindow->toFront(true);
105+
}
106+
mainWindow->setVisible(visible);
107+
if (visible && mainWindow->isMinimised())
108+
mainWindow->setMinimised(false);
109+
};
110+
111+
if (juce::MessageManager::getInstance()->isThisTheMessageThread())
112+
doUi();
113+
else
114+
juce::MessageManager::callAsync(doUi);
102115
}
103116

104117
// some plugins dont export state if audio is not playing

lib/atkaudio/src/atkaudio/PluginHost/StandaloneFilterWindow.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ class StandalonePluginHolder2
6868

6969
auto audioInputRequired = (inChannels > 0);
7070

71-
if (audioInputRequired && RuntimePermissions::isRequired(RuntimePermissions::recordAudio)
71+
if (audioInputRequired
72+
&& RuntimePermissions::isRequired(RuntimePermissions::recordAudio)
7273
&& !RuntimePermissions::isGranted(RuntimePermissions::recordAudio))
7374
RuntimePermissions::request(
7475
RuntimePermissions::recordAudio,
@@ -185,7 +186,8 @@ class StandalonePluginHolder2
185186
{
186187
stateFileChooser =
187188
std::make_unique<FileChooser>(TRANS("Save current state"), getLastFile(), getFilePatterns(fileSuffix));
188-
auto flags = FileBrowserComponent::saveMode | FileBrowserComponent::canSelectFiles
189+
auto flags = FileBrowserComponent::saveMode
190+
| FileBrowserComponent::canSelectFiles
189191
| FileBrowserComponent::warnAboutOverwriting;
190192

191193
stateFileChooser->launchAsync(
@@ -650,6 +652,8 @@ class StandaloneFilterWindow
650652

651653
~StandaloneFilterWindow() override
652654
{
655+
// Note: setVisible(false) is handled by atk::destroy() force-hide before this destructor runs
656+
653657
#if (!JUCE_IOS) && (!JUCE_ANDROID)
654658
if (auto* props = pluginHolder->settings.get())
655659
{

lib/atkaudio/src/atkaudio/PluginHost2/ObsOutput.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class ObsOutputAudioProcessor : public juce::AudioProcessor
3333

3434
obs_source_set_audio_active(privateSource, true);
3535
obs_source_set_enabled(privateSource, true);
36+
obs_source_release(sceneSource);
3637
}
3738
}
3839

lib/atkaudio/src/atkaudio/PluginHost2/PluginHost2.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ struct atk::PluginHost2::Impl : public juce::Timer
1313

1414
~Impl()
1515
{
16+
// Follow the same clean pattern as regular PluginHost
1617
auto* window = this->mainHostWindow.release();
1718
auto lambda = [window] { delete window; };
1819
juce::MessageManager::callAsync(lambda);
@@ -24,12 +25,20 @@ struct atk::PluginHost2::Impl : public juce::Timer
2425

2526
void setVisible(bool visible)
2627
{
27-
if (!mainHostWindow->isOnDesktop() && visible)
28+
auto doUi = [this, visible]
2829
{
29-
mainHostWindow->addToDesktop();
30-
mainHostWindow->toFront(true);
31-
}
32-
mainHostWindow->setVisible(visible);
30+
if (visible && !mainHostWindow->isOnDesktop())
31+
{
32+
mainHostWindow->addToDesktop();
33+
mainHostWindow->toFront(true);
34+
}
35+
mainHostWindow->setVisible(visible);
36+
};
37+
38+
if (juce::MessageManager::getInstance()->isThisTheMessageThread())
39+
doUi();
40+
else
41+
juce::MessageManager::callAsync(doUi);
3342
}
3443

3544
void getState(std::string& s)
@@ -111,7 +120,6 @@ struct atk::PluginHost2::Impl : public juce::Timer
111120

112121
private:
113122
std::unique_ptr<MainHostWindow> mainHostWindow;
114-
std::unique_ptr<juce::AudioDeviceManager> deviceManager;
115123

116124
juce::AudioBuffer<float> outputData{MAX_AUDIO_CHANNELS, AUDIO_OUTPUT_FRAMES};
117125
uint64_t hostTimeNs;

lib/atkaudio/src/atkaudio/PluginHost2/Plugins/GainPlugin.h

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class GainPlugin final
1818
using namespace juce;
1919
apvts = std::make_unique<AudioProcessorValueTreeState>(*this, nullptr, "state", createParameterLayout());
2020
gainValue = apvts->getRawParameterValue("gain");
21+
gain2Value = apvts->getRawParameterValue("gain2");
2122
midiEnabled = apvts->getRawParameterValue("midi");
2223
midiChannel = apvts->getRawParameterValue("ch");
2324
midiCc = apvts->getRawParameterValue("cc");
@@ -56,7 +57,8 @@ class GainPlugin final
5657
void prepareToPlay(double sampleRate, int samplesPerBlock) override
5758
{
5859
juce::ignoreUnused(sampleRate, samplesPerBlock);
59-
gainValueSmoothed.reset(sampleRate, 0.05f); // Smooth the gain value with a time constant of 50ms
60+
gainValueSmoothed.reset(sampleRate, 0.05f); // Smooth the gain value with a time constant of 50ms
61+
gain2ValueSmoothed.reset(sampleRate, 0.05f); // Smooth the gain2 value with a time constant of 50ms
6062
}
6163

6264
void releaseResources() override
@@ -66,6 +68,8 @@ class GainPlugin final
6668
void processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiBuffer) override
6769
{
6870
auto gain = gainValue->load(std::memory_order_acquire);
71+
auto gain2Db = gain2Value->load(std::memory_order_acquire);
72+
auto gain2Linear = juce::Decibels::decibelsToGain(gain2Db);
6973

7074
if (midiEnabled->load(std::memory_order_acquire) > 0.5f)
7175
{
@@ -89,10 +93,15 @@ class GainPlugin final
8993
for (int channel = 0; channel < buffer.getNumChannels(); ++channel)
9094
{
9195
gainValueSmoothed.setTargetValue(gain);
96+
gain2ValueSmoothed.setTargetValue(gain2Linear);
9297
auto* readPtr = buffer.getReadPointer(channel);
9398
auto* writePtr = buffer.getWritePointer(channel);
9499
for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
95-
writePtr[sample] = readPtr[sample] * gainValueSmoothed.getNextValue();
100+
{
101+
auto currentGain = gainValueSmoothed.getNextValue();
102+
auto currentGain2 = gain2ValueSmoothed.getNextValue();
103+
writePtr[sample] = readPtr[sample] * currentGain * currentGain2;
104+
}
96105
}
97106

98107
if (midiLearn->load(std::memory_order_acquire) > 0.5f)
@@ -218,17 +227,25 @@ class GainPlugin final
218227

219228
params.push_back(std::make_unique<AudioParameterBool>(ParameterID{"learn", 1}, "Learn", false));
220229

230+
// Gain2 parameter with -30 to +30 dB range
231+
auto gain2Range = NormalisableRange<float>(-30.0f, 30.0f, 0.1f, 1.0f);
232+
params.push_back(
233+
std::make_unique<AudioParameterFloat>(ParameterID{"gain2", 1}, "Gainsborough", gain2Range, 0.0f)
234+
);
235+
221236
return {params.begin(), params.end()};
222237
}
223238

224239
std::unique_ptr<juce::AudioProcessorValueTreeState> apvts;
225240
std::atomic<float>* gainValue = nullptr;
241+
std::atomic<float>* gain2Value = nullptr;
226242
std::atomic<float>* midiEnabled = nullptr;
227243
std::atomic<float>* midiChannel = nullptr;
228244
std::atomic<float>* midiCc = nullptr;
229245
std::atomic<float>* midiLearn = nullptr;
230246

231247
juce::LinearSmoothedValue<float> gainValueSmoothed;
248+
juce::LinearSmoothedValue<float> gain2ValueSmoothed;
232249

233250
juce::RangedAudioParameter* gainParam = nullptr;
234251
juce::RangedAudioParameter* channelParam = nullptr;

lib/atkaudio/src/atkaudio/PluginHost2/Plugins/MidiGainPlugin.h

Whitespace-only changes.

lib/atkaudio/src/atkaudio/PluginHost2/UI/MainHostWindow.cpp

Lines changed: 7 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ MainHostWindow::MainHostWindow()
334334

335335
restoreWindowStateFromString(getAppProperties().getUserSettings()->getValue("mainWindowPos"));
336336

337-
setVisible(false);
337+
setVisible(true);
338338

339339
InternalPluginFormat internalFormat;
340340
internalTypes = internalFormat.getAllTypes();
@@ -409,48 +409,15 @@ struct AsyncQuitRetrier final : private Timer
409409

410410
void MainHostWindow::tryToQuitApplication()
411411
{
412-
if (graphHolder->closeAnyOpenPluginWindows())
413-
{
414-
// Really important thing to note here: if the last call just deleted any plugin windows,
415-
// we won't exit immediately - instead we'll use our AsyncQuitRetrier to let the message
416-
// loop run for another brief moment, then try again. This will give any plugins a chance
417-
// to flush any GUI events that may have been in transit before the app forces them to
418-
// be unloaded
419-
new AsyncQuitRetrier();
420-
return;
421-
}
422-
423-
if (ModalComponentManager::getInstance()->cancelAllModalComponents())
424-
{
425-
new AsyncQuitRetrier();
426-
return;
427-
}
428-
412+
// In plugin context, we don't quit the host application (OBS).
413+
// Instead, attempt to close plugin windows and hide our window.
429414
if (graphHolder != nullptr)
430-
{
431-
auto releaseAndQuit = [this]
432-
{
433-
// Some plug-ins do not want [NSApp stop] to be called
434-
// before the plug-ins are not deallocated.
435-
graphHolder->releaseGraph();
436-
};
437-
438-
SafePointer<MainHostWindow> parent{this};
439-
graphHolder->graph->saveIfNeededAndUserAgreesAsync(
440-
[parent, releaseAndQuit](FileBasedDocument::SaveResult r)
441-
{
442-
if (parent == nullptr)
443-
return;
415+
(void)graphHolder->closeAnyOpenPluginWindows();
444416

445-
if (r == FileBasedDocument::savedOk)
446-
releaseAndQuit();
447-
}
448-
);
417+
if (ModalComponentManager::getInstance() != nullptr)
418+
(void)ModalComponentManager::getInstance()->cancelAllModalComponents();
449419

450-
return;
451-
}
452-
453-
JUCEApplication::quit();
420+
setVisible(false);
454421
}
455422

456423
void MainHostWindow::changeListenerCallback(ChangeBroadcaster* changed)

0 commit comments

Comments
 (0)