RAM2118 commited on
Commit
ddb115b
·
verified ·
1 Parent(s): 915497a

Upload Source/Helper/HelperPluginHost.cpp

Browse files
Files changed (1) hide show
  1. Source/Helper/HelperPluginHost.cpp +2 -313
Source/Helper/HelperPluginHost.cpp CHANGED
@@ -1,314 +1,3 @@
 
 
1
  #include "HelperPluginHost.h"
2
- #include "Constants.h"
3
- #include <juce_audio_basics/juce_audio_basics.h>
4
- #include <pthread.h>
5
- #include <sched.h>
6
-
7
- // Custom window — X button hides instead of quitting
8
- class PluginGuiWindow : public juce::DocumentWindow
9
- {
10
- public:
11
- PluginGuiWindow(const juce::String& name)
12
- : DocumentWindow(name, juce::Colour(0xff1a1a2e), DocumentWindow::allButtons, true)
13
- {
14
- setUsingNativeTitleBar(true);
15
- }
16
-
17
- void closeButtonPressed() override
18
- {
19
- setVisible(false);
20
- }
21
- };
22
-
23
- HelperPluginHost::HelperPluginHost()
24
- {
25
- #if JUCE_PLUGINHOST_VST3
26
- formatManager.addFormat(new juce::VST3PluginFormat());
27
- #endif
28
- #if JUCE_PLUGINHOST_AU
29
- formatManager.addFormat(new juce::AudioUnitPluginFormat());
30
- #endif
31
- }
32
-
33
- HelperPluginHost::~HelperPluginHost()
34
- {
35
- stopProcessing();
36
- hideGui();
37
- unloadPlugin();
38
- }
39
-
40
- bool HelperPluginHost::loadPlugin(const juce::String& path, double sampleRate, int blockSize)
41
- {
42
- unloadPlugin();
43
-
44
- currentSampleRate = sampleRate;
45
- currentBlockSize = blockSize;
46
-
47
- juce::File pluginFile(path);
48
- if (!pluginFile.exists())
49
- return false;
50
-
51
- juce::OwnedArray<juce::PluginDescription> typesFound;
52
-
53
- for (int i = 0; i < formatManager.getNumFormats(); ++i)
54
- {
55
- auto* format = formatManager.getFormat(i);
56
- bool isVST3 = pluginFile.getFileExtension() == ".vst3";
57
- bool isAU = pluginFile.getFileExtension() == ".component";
58
-
59
- if (isVST3 && format->getName() != "VST3") continue;
60
- if (isAU && format->getName() != "AudioUnit") continue;
61
-
62
- format->findAllTypesForFile(typesFound, pluginFile.getFullPathName());
63
- if (typesFound.size() > 0)
64
- break;
65
- }
66
-
67
- if (typesFound.isEmpty())
68
- return false;
69
-
70
- juce::String errorMessage;
71
- plugin = formatManager.createPluginInstance(*typesFound[0], sampleRate, blockSize, errorMessage);
72
-
73
- if (plugin == nullptr)
74
- {
75
- DBG("HelperPluginHost: Failed to create plugin: " + errorMessage);
76
- return false;
77
- }
78
-
79
- plugin->enableAllBuses();
80
-
81
- auto layout = juce::AudioProcessor::BusesLayout();
82
- layout.inputBuses.add(juce::AudioChannelSet::stereo());
83
- layout.outputBuses.add(juce::AudioChannelSet::stereo());
84
-
85
- if (plugin->checkBusesLayoutSupported(layout))
86
- plugin->setBusesLayout(layout);
87
-
88
- plugin->prepareToPlay(sampleRate, blockSize);
89
-
90
- DBG("HelperPluginHost: Loaded " + getPluginName() + " (" + juce::String(getParameterCount()) + " params)");
91
- return true;
92
- }
93
-
94
- void HelperPluginHost::unloadPlugin()
95
- {
96
- hideGui();
97
- if (plugin)
98
- {
99
- plugin->releaseResources();
100
- plugin.reset();
101
- }
102
- }
103
-
104
- juce::String HelperPluginHost::getPluginName() const
105
- {
106
- return plugin ? plugin->getName() : juce::String();
107
- }
108
-
109
- int HelperPluginHost::getParameterCount() const
110
- {
111
- return plugin ? plugin->getParameters().size() : 0;
112
- }
113
-
114
- void HelperPluginHost::setSharedAudio(SharedAudioBuffer* shm, SharedSemaphore* inSem, SharedSemaphore* outSem)
115
- {
116
- sharedAudio = shm;
117
- inputSem = inSem;
118
- outputSem = outSem;
119
- }
120
-
121
- void HelperPluginHost::startProcessing()
122
- {
123
- if (processing.load()) return;
124
- processing.store(true);
125
- audioThread = std::thread([this]() { audioProcessingLoop(); });
126
- }
127
-
128
- void HelperPluginHost::stopProcessing()
129
- {
130
- processing.store(false);
131
- if (inputSem) inputSem->signal();
132
- if (audioThread.joinable())
133
- audioThread.join();
134
- }
135
-
136
- void HelperPluginHost::audioProcessingLoop()
137
- {
138
- struct sched_param param;
139
- param.sched_priority = sched_get_priority_max(SCHED_FIFO);
140
- pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
141
-
142
- while (processing.load())
143
- {
144
- if (!inputSem->wait(100))
145
- continue;
146
-
147
- if (!processing.load()) break;
148
- if (!plugin || !sharedAudio) continue;
149
-
150
- auto* header = sharedAudio->getHeader();
151
- int numChannels = header->numChannels.load();
152
- int blockSize = header->blockSize.load();
153
-
154
- juce::AudioBuffer<float> buffer(numChannels, blockSize);
155
- float* channelPtrs[2] = { buffer.getWritePointer(0),
156
- numChannels > 1 ? buffer.getWritePointer(1) : nullptr };
157
- sharedAudio->readInput(channelPtrs, numChannels, blockSize);
158
-
159
- juce::MidiBuffer midi;
160
- plugin->processBlock(buffer, midi);
161
-
162
- const float* constPtrs[2] = { buffer.getReadPointer(0),
163
- numChannels > 1 ? buffer.getReadPointer(1) : nullptr };
164
- sharedAudio->writeOutput(constPtrs, numChannels, blockSize);
165
-
166
- header->state.store(kStateOutputReady);
167
- outputSem->signal();
168
- }
169
- }
170
-
171
- // --- Parameters ---
172
-
173
- std::vector<HelperPluginHost::ParamInfo> HelperPluginHost::searchParams(const juce::String& keyword) const
174
- {
175
- std::vector<ParamInfo> results;
176
- if (!plugin) return results;
177
-
178
- auto& params = plugin->getParameters();
179
- auto keywordLower = keyword.toLowerCase();
180
-
181
- for (int i = 0; i < params.size(); ++i)
182
- {
183
- auto* param = params[i];
184
- auto name = param->getName(128);
185
-
186
- if (name.toLowerCase().contains(keywordLower))
187
- {
188
- ParamInfo info;
189
- info.index = i;
190
- info.name = name;
191
- info.value = param->getValue();
192
- info.displayText = param->getText(param->getValue(), 64);
193
-
194
- if (auto* hosted = dynamic_cast<juce::AudioPluginInstance::HostedParameter*>(param))
195
- info.id = hosted->getParameterID();
196
- else
197
- info.id = juce::String(i);
198
-
199
- results.push_back(info);
200
- if (results.size() >= PluginBridgeConstants::kMaxParamResults)
201
- break;
202
- }
203
- }
204
-
205
- return results;
206
- }
207
-
208
- std::vector<std::pair<int, float>> HelperPluginHost::getParams(const std::vector<int>& ids) const
209
- {
210
- std::vector<std::pair<int, float>> results;
211
- if (!plugin) return results;
212
-
213
- auto& params = plugin->getParameters();
214
- for (int idx : ids)
215
- {
216
- if (idx >= 0 && idx < params.size())
217
- results.push_back({idx, params[idx]->getValue()});
218
- }
219
- return results;
220
- }
221
-
222
- bool HelperPluginHost::setParams(const std::map<int, float>& values)
223
- {
224
- if (!plugin) return false;
225
-
226
- auto& params = plugin->getParameters();
227
- for (auto& [idx, val] : values)
228
- {
229
- if (idx >= 0 && idx < params.size())
230
- {
231
- auto* param = params[idx];
232
- param->beginChangeGesture();
233
- param->setValueNotifyingHost(juce::jlimit(0.0f, 1.0f, val));
234
- param->endChangeGesture();
235
- }
236
- }
237
- return true;
238
- }
239
-
240
- // --- GUI ---
241
-
242
- void HelperPluginHost::showGui()
243
- {
244
- if (!plugin || !plugin->hasEditor()) return;
245
-
246
- juce::MessageManager::callAsync([this]()
247
- {
248
- if (!plugin) return;
249
-
250
- if (guiWindow)
251
- {
252
- guiWindow->setVisible(true);
253
- return;
254
- }
255
-
256
- auto* editor = plugin->createEditor();
257
- if (!editor) return;
258
-
259
- guiWindow = std::make_unique<PluginGuiWindow>(plugin->getName());
260
- guiWindow->setContentOwned(editor, true);
261
- guiWindow->setResizable(true, true);
262
- guiWindow->setAlwaysOnTop(true);
263
- guiWindow->centreWithSize(editor->getWidth(), editor->getHeight());
264
- guiWindow->setVisible(true);
265
- });
266
- }
267
-
268
- void HelperPluginHost::hideGui()
269
- {
270
- if (guiWindow)
271
- {
272
- juce::MessageManager::callAsync([this]()
273
- {
274
- if (guiWindow)
275
- guiWindow->setVisible(false);
276
- });
277
- }
278
- }
279
-
280
- // --- State ---
281
-
282
- juce::String HelperPluginHost::getStateBase64() const
283
- {
284
- if (!plugin) return {};
285
-
286
- juce::MemoryBlock stateData;
287
- plugin->getStateInformation(stateData);
288
- return stateData.toBase64Encoding();
289
- }
290
-
291
- bool HelperPluginHost::setStateBase64(const juce::String& base64State)
292
- {
293
- if (!plugin) return false;
294
-
295
- juce::MemoryBlock stateData;
296
- if (!stateData.fromBase64Encoding(base64State))
297
- return false;
298
-
299
- plugin->setStateInformation(stateData.getData(), (int)stateData.getSize());
300
- return true;
301
- }
302
-
303
- void HelperPluginHost::configure(double sampleRate, int blockSize, int channels)
304
- {
305
- currentSampleRate = sampleRate;
306
- currentBlockSize = blockSize;
307
- currentChannels = channels;
308
-
309
- if (plugin)
310
- {
311
- plugin->releaseResources();
312
- plugin->prepareToPlay(sampleRate, blockSize);
313
- }
314
- }
 
1
+ // HelperPluginHost.cpp — implementation is fully in the header (header-only class)
2
+ // This file exists only to keep CMake happy as a compilation unit.
3
  #include "HelperPluginHost.h"