comparison DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginCarla.cpp @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
comparison
equal deleted inserted replaced
2:cf2cb71d31dd 3:84e66ea83026
1 /*
2 * DISTRHO Plugin Framework (DPF)
3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with
6 * or without fee is hereby granted, provided that the above copyright notice and this
7 * permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "DistrhoPluginInternal.hpp"
18
19 #if DISTRHO_PLUGIN_HAS_UI
20 # include "DistrhoUIInternal.hpp"
21 #endif
22
23 #include "CarlaNative.hpp"
24
25 // TODO
26 #undef DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
27 #define DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST 0
28
29 // -----------------------------------------------------------------------
30
31 START_NAMESPACE_DISTRHO
32
33 #if ! DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
34 static constexpr const writeMidiFunc writeMidiCallback = nullptr;
35 #endif
36 #if ! DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
37 static constexpr const requestParameterValueChangeFunc requestParameterValueChangeCallback = nullptr;
38 #endif
39 // TODO
40 static constexpr const updateStateValueFunc updateStateValueCallback = nullptr;
41
42 #if DISTRHO_PLUGIN_HAS_UI
43 // -----------------------------------------------------------------------
44 // Carla UI
45
46 #if ! DISTRHO_PLUGIN_WANT_STATE
47 static const setStateFunc setStateCallback = nullptr;
48 #endif
49 #if ! DISTRHO_PLUGIN_IS_SYNTH
50 static const sendNoteFunc sendNoteCallback = nullptr;
51 #endif
52
53 class UICarla
54 {
55 public:
56 UICarla(const NativeHostDescriptor* const host, PluginExporter* const plugin)
57 : fHost(host),
58 fUI(this, 0, plugin->getSampleRate(),
59 editParameterCallback, setParameterCallback, setStateCallback, sendNoteCallback,
60 nullptr, // window size
61 nullptr, // TODO file request
62 nullptr, // bundle path
63 plugin->getInstancePointer())
64 {
65 fUI.setWindowTitle(host->uiName);
66
67 if (host->uiParentId != 0)
68 fUI.setWindowTransientWinId(host->uiParentId);
69 }
70
71 ~UICarla()
72 {
73 fUI.quit();
74 }
75
76 // ---------------------------------------------
77
78 void carla_show(const bool yesNo)
79 {
80 fUI.setWindowVisible(yesNo);
81 }
82
83 bool carla_idle()
84 {
85 return fUI.plugin_idle();
86 }
87
88 void carla_setParameterValue(const uint32_t index, const float value)
89 {
90 fUI.parameterChanged(index, value);
91 }
92
93 #if DISTRHO_PLUGIN_WANT_PROGRAMS
94 void carla_setMidiProgram(const uint32_t realProgram)
95 {
96 fUI.programLoaded(realProgram);
97 }
98 #endif
99
100 #if DISTRHO_PLUGIN_WANT_STATE
101 void carla_setCustomData(const char* const key, const char* const value)
102 {
103 fUI.stateChanged(key, value);
104 }
105 #endif
106
107 void carla_setUiTitle(const char* const uiTitle)
108 {
109 fUI.setWindowTitle(uiTitle);
110 }
111
112 // ---------------------------------------------
113
114 protected:
115 void handleEditParameter(const uint32_t, const bool)
116 {
117 // TODO
118 }
119
120 void handleSetParameterValue(const uint32_t rindex, const float value)
121 {
122 fHost->ui_parameter_changed(fHost->handle, rindex, value);
123 }
124
125 #if DISTRHO_PLUGIN_WANT_STATE
126 void handleSetState(const char* const key, const char* const value)
127 {
128 fHost->ui_custom_data_changed(fHost->handle, key, value);
129 }
130 #endif
131
132 #if DISTRHO_PLUGIN_IS_SYNTH
133 void handleSendNote(const uint8_t, const uint8_t, const uint8_t)
134 {
135 // TODO
136 }
137 #endif
138
139 // ---------------------------------------------
140
141 private:
142 // Plugin stuff
143 const NativeHostDescriptor* const fHost;
144
145 // UI
146 UIExporter fUI;
147
148 // ---------------------------------------------
149 // Callbacks
150
151 #define handlePtr ((UICarla*)ptr)
152
153 static void editParameterCallback(void* ptr, uint32_t index, bool started)
154 {
155 handlePtr->handleEditParameter(index, started);
156 }
157
158 static void setParameterCallback(void* ptr, uint32_t rindex, float value)
159 {
160 handlePtr->handleSetParameterValue(rindex, value);
161 }
162
163 #if DISTRHO_PLUGIN_WANT_STATE
164 static void setStateCallback(void* ptr, const char* key, const char* value)
165 {
166 handlePtr->handleSetState(key, value);
167 }
168 #endif
169
170 #if DISTRHO_PLUGIN_IS_SYNTH
171 static void sendNoteCallback(void* ptr, uint8_t channel, uint8_t note, uint8_t velocity)
172 {
173 handlePtr->handleSendNote(channel, note, velocity);
174 }
175 #endif
176
177 #undef handlePtr
178
179 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UICarla)
180 };
181 #endif // DISTRHO_PLUGIN_HAS_UI
182
183 // -----------------------------------------------------------------------
184 // Carla Plugin
185
186 class PluginCarla : public NativePluginClass
187 {
188 public:
189 PluginCarla(const NativeHostDescriptor* const host)
190 : NativePluginClass(host),
191 fPlugin(this, writeMidiCallback, requestParameterValueChangeCallback, updateStateValueCallback),
192 fScalePointsCache(nullptr)
193 {
194 #if DISTRHO_PLUGIN_HAS_UI
195 fUiPtr = nullptr;
196 #endif
197 }
198
199 ~PluginCarla() override
200 {
201 #if DISTRHO_PLUGIN_HAS_UI
202 if (fUiPtr != nullptr)
203 {
204 delete fUiPtr;
205 fUiPtr = nullptr;
206 }
207 #endif
208
209 if (fScalePointsCache != nullptr)
210 {
211 delete[] fScalePointsCache;
212 fScalePointsCache = nullptr;
213 }
214 }
215
216 protected:
217 // -------------------------------------------------------------------
218 // Plugin parameter calls
219
220 uint32_t getParameterCount() const override
221 {
222 return fPlugin.getParameterCount();
223 }
224
225 const NativeParameter* getParameterInfo(const uint32_t index) const override
226 {
227 CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
228
229 static NativeParameter param;
230
231 param.scalePointCount = 0;
232 param.scalePoints = nullptr;
233
234 {
235 int nativeParamHints = ::NATIVE_PARAMETER_IS_ENABLED;
236 const uint32_t paramHints = fPlugin.getParameterHints(index);
237
238 if (paramHints & kParameterIsAutomatable)
239 nativeParamHints |= ::NATIVE_PARAMETER_IS_AUTOMABLE;
240 if (paramHints & kParameterIsBoolean)
241 nativeParamHints |= ::NATIVE_PARAMETER_IS_BOOLEAN;
242 if (paramHints & kParameterIsInteger)
243 nativeParamHints |= ::NATIVE_PARAMETER_IS_INTEGER;
244 if (paramHints & kParameterIsLogarithmic)
245 nativeParamHints |= ::NATIVE_PARAMETER_IS_LOGARITHMIC;
246 if (paramHints & kParameterIsOutput)
247 nativeParamHints |= ::NATIVE_PARAMETER_IS_OUTPUT;
248
249 param.hints = static_cast<NativeParameterHints>(nativeParamHints);
250 }
251
252 param.name = fPlugin.getParameterName(index);
253 param.unit = fPlugin.getParameterUnit(index);
254
255 {
256 const ParameterRanges& ranges(fPlugin.getParameterRanges(index));
257
258 param.ranges.def = ranges.def;
259 param.ranges.min = ranges.min;
260 param.ranges.max = ranges.max;
261 }
262
263 {
264 const ParameterEnumerationValues& enumValues(fPlugin.getParameterEnumValues(index));
265
266 if (const uint32_t scalePointCount = enumValues.count)
267 {
268 NativeParameterScalePoint* const scalePoints = new NativeParameterScalePoint[scalePointCount];
269
270 for (uint32_t i=0; i<scalePointCount; ++i)
271 {
272 scalePoints[i].label = enumValues.values[i].label.buffer();
273 scalePoints[i].value = enumValues.values[i].value;
274 }
275
276 param.scalePoints = scalePoints;
277 param.scalePointCount = scalePointCount;
278
279 if (enumValues.restrictedMode)
280 param.hints = static_cast<NativeParameterHints>(param.hints|::NATIVE_PARAMETER_USES_SCALEPOINTS);
281 }
282 else if (fScalePointsCache != nullptr)
283 {
284 delete[] fScalePointsCache;
285 fScalePointsCache = nullptr;
286 }
287 }
288
289 return &param;
290 }
291
292 float getParameterValue(const uint32_t index) const override
293 {
294 CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
295
296 return fPlugin.getParameterValue(index);
297 }
298
299 // -------------------------------------------------------------------
300 // Plugin midi-program calls
301
302 #if DISTRHO_PLUGIN_WANT_PROGRAMS
303 uint32_t getMidiProgramCount() const override
304 {
305 return fPlugin.getProgramCount();
306 }
307
308 const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override
309 {
310 CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
311
312 static NativeMidiProgram midiProgram;
313
314 midiProgram.bank = index / 128;
315 midiProgram.program = index % 128;
316 midiProgram.name = fPlugin.getProgramName(index);
317
318 return &midiProgram;
319 }
320 #endif
321
322 // -------------------------------------------------------------------
323 // Plugin state calls
324
325 void setParameterValue(const uint32_t index, const float value) override
326 {
327 CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
328
329 fPlugin.setParameterValue(index, value);
330 }
331
332 #if DISTRHO_PLUGIN_WANT_PROGRAMS
333 void setMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
334 {
335 const uint32_t realProgram(bank * 128 + program);
336
337 CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);
338
339 fPlugin.loadProgram(realProgram);
340 }
341 #endif
342
343 #if DISTRHO_PLUGIN_WANT_STATE
344 void setCustomData(const char* const key, const char* const value) override
345 {
346 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
347 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
348
349 fPlugin.setState(key, value);
350 }
351 #endif
352
353 // -------------------------------------------------------------------
354 // Plugin process calls
355
356 void activate() override
357 {
358 fPlugin.activate();
359 }
360
361 void deactivate() override
362 {
363 fPlugin.deactivate();
364 }
365
366 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT
367 void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames,
368 const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
369 {
370 MidiEvent realMidiEvents[midiEventCount];
371
372 for (uint32_t i=0; i < midiEventCount; ++i)
373 {
374 const NativeMidiEvent& midiEvent(midiEvents[i]);
375 MidiEvent& realMidiEvent(realMidiEvents[i]);
376
377 realMidiEvent.frame = midiEvent.time;
378 realMidiEvent.size = midiEvent.size;
379
380 uint8_t j=0;
381 for (; j<midiEvent.size; ++j)
382 realMidiEvent.data[j] = midiEvent.data[j];
383 for (; j<midiEvent.size; ++j)
384 realMidiEvent.data[j] = midiEvent.data[j];
385
386 realMidiEvent.dataExt = nullptr;
387 }
388
389 fPlugin.run(const_cast<const float**>(inBuffer), outBuffer, frames, realMidiEvents, midiEventCount);
390 }
391 #else
392 void process(const float* const* const inBuffer, float** const outBuffer, const uint32_t frames,
393 const NativeMidiEvent* const, const uint32_t) override
394 {
395 fPlugin.run(const_cast<const float**>(inBuffer), outBuffer, frames);
396 }
397 #endif
398
399 // -------------------------------------------------------------------
400 // Plugin UI calls
401
402 #if DISTRHO_PLUGIN_HAS_UI
403 void uiShow(const bool show) override
404 {
405 if (show)
406 {
407 createUiIfNeeded();
408 CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
409
410 fUiPtr->carla_show(show);
411 }
412 else if (fUiPtr != nullptr)
413 {
414 delete fUiPtr;
415 fUiPtr = nullptr;
416 }
417 }
418
419 void uiIdle() override
420 {
421 CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
422
423 if (! fUiPtr->carla_idle())
424 {
425 uiClosed();
426
427 delete fUiPtr;
428 fUiPtr = nullptr;
429 }
430 }
431
432 void uiSetParameterValue(const uint32_t index, const float value) override
433 {
434 CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
435 CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
436
437 fUiPtr->carla_setParameterValue(index, value);
438 }
439
440 # if DISTRHO_PLUGIN_WANT_PROGRAMS
441 void uiSetMidiProgram(const uint8_t, const uint32_t bank, const uint32_t program) override
442 {
443 CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
444
445 const uint32_t realProgram(bank * 128 + program);
446
447 CARLA_SAFE_ASSERT_RETURN(realProgram < getMidiProgramCount(),);
448
449 fUiPtr->carla_setMidiProgram(realProgram);
450 }
451 # endif
452
453 # if DISTRHO_PLUGIN_WANT_STATE
454 void uiSetCustomData(const char* const key, const char* const value) override
455 {
456 CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
457 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
458 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
459
460 fUiPtr->carla_setCustomData(key, value);
461 }
462 # endif
463 #endif
464
465 // -------------------------------------------------------------------
466 // Plugin dispatcher calls
467
468 void bufferSizeChanged(const uint32_t bufferSize) override
469 {
470 fPlugin.setBufferSize(bufferSize, true);
471 }
472
473 void sampleRateChanged(const double sampleRate) override
474 {
475 fPlugin.setSampleRate(sampleRate, true);
476 }
477
478 #if DISTRHO_PLUGIN_HAS_UI
479 void uiNameChanged(const char* const uiName) override
480 {
481 CARLA_SAFE_ASSERT_RETURN(fUiPtr != nullptr,);
482
483 fUiPtr->carla_setUiTitle(uiName);
484 }
485 #endif
486
487 // -------------------------------------------------------------------
488
489 private:
490 PluginExporter fPlugin;
491 mutable NativeParameterScalePoint* fScalePointsCache;
492
493 #if DISTRHO_PLUGIN_HAS_UI
494 // UI
495 UICarla* fUiPtr;
496
497 void createUiIfNeeded()
498 {
499 if (fUiPtr == nullptr)
500 fUiPtr = new UICarla(getHostHandle(), &fPlugin);
501 }
502 #endif
503
504 #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT
505 static bool writeMidiCallback(void* ptr, const MidiEvent& midiEvent)
506 {
507 if (midiEvent.size > 4)
508 return;
509
510 const NativeMidiEvent event = {
511 midiEvent.frame, 0, midiEvent.size, midiEvent.data
512 };
513
514 return ((PluginCarla*)ptr)->fPlugin.writeMidiEvent(midiEvent);
515 }
516 #endif
517
518 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST
519 bool requestParameterValueChange(const uint32_t index, const float value)
520 {
521 // TODO implementation
522 return false;
523 }
524
525 static bool requestParameterValueChangeCallback(void* ptr, const uint32_t index, const float value)
526 {
527 return thisPtr->requestParameterValueChange(index, value);
528 }
529 #endif
530
531 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginCarla)
532
533 // -------------------------------------------------------------------
534
535 public:
536 static NativePluginHandle _instantiate(const NativeHostDescriptor* host)
537 {
538 d_nextBufferSize = host->get_buffer_size(host->handle);
539 d_nextSampleRate = host->get_sample_rate(host->handle);
540 return new PluginCarla(host);
541 }
542
543 static void _cleanup(NativePluginHandle handle)
544 {
545 delete (PluginCarla*)handle;
546 }
547 };
548
549 END_NAMESPACE_DISTRHO
550
551 // -----------------------------------------------------------------------