3 * Copyright (C) 2012-2022 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaPluginInternal.hpp"
19 #include "CarlaEngine.hpp"
21 #include "CarlaBackendUtils.hpp"
22 #include "CarlaMathUtils.hpp"
23 #include "CarlaNative.h"
25 #include "water/misc/Time.h"
26 #include "water/text/StringArray.h"
29 using water::StringArray
;
31 // -----------------------------------------------------------------------
32 // used in carla-base.cpp
34 std::size_t carla_getNativePluginCount() noexcept
;
35 const NativePluginDescriptor
* carla_getNativePluginDescriptor(const std::size_t index
) noexcept
;
37 // -----------------------------------------------------------------------
39 static LinkedList
<const NativePluginDescriptor
*> gPluginDescriptors
;
41 void carla_register_native_plugin(const NativePluginDescriptor
* desc
)
43 gPluginDescriptors
.append(desc
);
46 // -----------------------------------------------------------------------
49 class NativePluginInitializer
52 NativePluginInitializer() noexcept
55 ~NativePluginInitializer() noexcept
57 gPluginDescriptors
.clear();
60 void initIfNeeded() noexcept
68 carla_register_all_native_plugins();
69 } CARLA_SAFE_EXCEPTION("carla_register_all_native_plugins")
77 // -----------------------------------------------------------------------
79 std::size_t carla_getNativePluginCount() noexcept
81 sPluginInitializer
.initIfNeeded();
82 return gPluginDescriptors
.count();
85 const NativePluginDescriptor
* carla_getNativePluginDescriptor(const std::size_t index
) noexcept
87 sPluginInitializer
.initIfNeeded();
88 return gPluginDescriptors
.getAt(index
, nullptr);
91 // -----------------------------------------------------------------------
93 CARLA_BACKEND_START_NAMESPACE
95 // -------------------------------------------------------------------
98 static const CustomData kCustomDataFallback
= { nullptr, nullptr, nullptr };
99 static EngineEvent kNullEngineEvent
= {
100 kEngineEventTypeNull
, 0, 0, {{ kEngineControlEventTypeNull
, 0, -1, 0.0f
, true }}
103 // -----------------------------------------------------------------------
105 struct NativePluginMidiOutData
{
108 CarlaEngineEventPort
** ports
;
110 NativePluginMidiOutData() noexcept
115 ~NativePluginMidiOutData() noexcept
117 CARLA_SAFE_ASSERT_INT(count
== 0, count
);
118 CARLA_SAFE_ASSERT(indexes
== nullptr);
119 CARLA_SAFE_ASSERT(ports
== nullptr);
122 bool createNew(const uint32_t newCount
)
124 CARLA_SAFE_ASSERT_INT(count
== 0, count
);
125 CARLA_SAFE_ASSERT_RETURN(indexes
== nullptr, false);
126 CARLA_SAFE_ASSERT_RETURN(ports
== nullptr, false);
127 CARLA_SAFE_ASSERT_RETURN(newCount
> 0, false);
129 indexes
= new uint32_t[newCount
];
130 ports
= new CarlaEngineEventPort
*[newCount
];
133 carla_zeroStructs(indexes
, newCount
);
134 carla_zeroStructs(ports
, newCount
);
139 void clear() noexcept
141 if (ports
!= nullptr)
143 for (uint32_t i
=0; i
< count
; ++i
)
145 if (ports
[i
] != nullptr)
156 if (indexes
!= nullptr)
165 void initBuffers() const noexcept
167 for (uint32_t i
=0; i
< count
; ++i
)
169 if (ports
[i
] != nullptr)
170 ports
[i
]->initBuffer();
174 CARLA_DECLARE_NON_COPYABLE(NativePluginMidiOutData
)
177 struct NativePluginMidiInData
: NativePluginMidiOutData
{
178 struct MultiPortData
{
179 uint32_t cachedEventCount
;
183 MultiPortData
* multiportData
;
185 NativePluginMidiInData() noexcept
186 : NativePluginMidiOutData(),
187 multiportData(nullptr) {}
189 ~NativePluginMidiInData() noexcept
191 CARLA_SAFE_ASSERT(multiportData
== nullptr);
194 bool createNew(const uint32_t newCount
)
196 if (! NativePluginMidiOutData::createNew(newCount
))
199 multiportData
= new MultiPortData
[newCount
];
200 carla_zeroStructs(multiportData
, newCount
);
205 void clear() noexcept
207 if (multiportData
!= nullptr)
209 delete[] multiportData
;
210 multiportData
= nullptr;
213 NativePluginMidiOutData::clear();
216 void initBuffers(CarlaEngineEventPort
* const port
) const noexcept
220 CARLA_SAFE_ASSERT_RETURN(port
!= nullptr,);
222 carla_zeroStruct(multiportData
[0]);
223 multiportData
[0].cachedEventCount
= port
->getEventCount();
227 for (uint32_t i
=0; i
< count
; ++i
)
229 carla_zeroStruct(multiportData
[i
]);
231 if (ports
[i
] != nullptr)
233 ports
[i
]->initBuffer();
234 multiportData
[i
].cachedEventCount
= ports
[i
]->getEventCount();
239 CARLA_DECLARE_NON_COPYABLE(NativePluginMidiInData
)
242 // -----------------------------------------------------
244 class CarlaPluginNative
: public CarlaPlugin
247 CarlaPluginNative(CarlaEngine
* const engine
, const uint id
)
248 : CarlaPlugin(engine
, id
),
252 fDescriptor(nullptr),
253 fIsProcessing(false),
254 fIsOffline(engine
->isOffline()),
255 fIsUiAvailable(false),
258 fInlineDisplayNeedsRedraw(false),
259 fInlineDisplayLastRedrawTime(0),
260 fLastProjectFilename(),
261 fLastProjectFolder(),
262 fAudioAndCvInBuffers(nullptr),
263 fAudioAndCvOutBuffers(nullptr),
264 fMidiEventInCount(0),
265 fMidiEventOutCount(0),
266 fCurBufferSize(engine
->getBufferSize()),
267 fCurSampleRate(engine
->getSampleRate()),
272 carla_debug("CarlaPluginNative::CarlaPluginNative(%p, %i)", engine
, id
);
274 carla_fill(fCurMidiProgs
, 0, MAX_MIDI_CHANNELS
);
275 carla_zeroStructs(fMidiInEvents
, kPluginMaxMidiEvents
);
276 carla_zeroStructs(fMidiOutEvents
, kPluginMaxMidiEvents
);
277 carla_zeroStruct(fTimeInfo
);
280 fHost
.resourceDir
= carla_strdup(engine
->getOptions().resourceDir
);
281 fHost
.uiName
= nullptr;
282 fHost
.uiParentId
= engine
->getOptions().frontendWinId
;
284 fHost
.get_buffer_size
= carla_host_get_buffer_size
;
285 fHost
.get_sample_rate
= carla_host_get_sample_rate
;
286 fHost
.is_offline
= carla_host_is_offline
;
287 fHost
.get_time_info
= carla_host_get_time_info
;
288 fHost
.write_midi_event
= carla_host_write_midi_event
;
289 fHost
.ui_parameter_changed
= carla_host_ui_parameter_changed
;
290 fHost
.ui_custom_data_changed
= carla_host_ui_custom_data_changed
;
291 fHost
.ui_closed
= carla_host_ui_closed
;
292 fHost
.ui_open_file
= carla_host_ui_open_file
;
293 fHost
.ui_save_file
= carla_host_ui_save_file
;
294 fHost
.dispatcher
= carla_host_dispatcher
;
297 ~CarlaPluginNative() override
299 carla_debug("CarlaPluginNative::~CarlaPluginNative()");
301 fInlineDisplayNeedsRedraw
= false;
304 if (pData
->hints
& PLUGIN_HAS_CUSTOM_UI
)
306 if (fIsUiVisible
&& fDescriptor
!= nullptr && fDescriptor
->ui_show
!= nullptr && fHandle
!= nullptr)
307 fDescriptor
->ui_show(fHandle
, false);
310 pData
->transientTryCounter
= 0;
314 pData
->singleMutex
.lock();
315 pData
->masterMutex
.lock();
317 if (pData
->client
!= nullptr && pData
->client
->isActive())
318 pData
->client
->deactivate(true);
320 CARLA_ASSERT(! fIsProcessing
);
325 pData
->active
= false;
328 if (fDescriptor
!= nullptr)
330 if (fDescriptor
->cleanup
!= nullptr)
332 if (fHandle
!= nullptr)
333 fDescriptor
->cleanup(fHandle
);
334 if (fHandle2
!= nullptr)
335 fDescriptor
->cleanup(fHandle2
);
340 fDescriptor
= nullptr;
343 if (fHost
.resourceDir
!= nullptr)
345 delete[] fHost
.resourceDir
;
346 fHost
.resourceDir
= nullptr;
349 if (fHost
.uiName
!= nullptr)
351 std::free(const_cast<char*>(fHost
.uiName
));
352 fHost
.uiName
= nullptr;
358 // -------------------------------------------------------------------
359 // Information (base)
361 PluginType
getType() const noexcept override
363 return PLUGIN_INTERNAL
;
366 PluginCategory
getCategory() const noexcept override
368 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, PLUGIN_CATEGORY_NONE
);
370 return static_cast<PluginCategory
>(fDescriptor
->category
);
373 // -------------------------------------------------------------------
374 // Information (count)
376 uint32_t getMidiInCount() const noexcept override
378 return fMidiIn
.count
;
381 uint32_t getMidiOutCount() const noexcept override
383 return fMidiOut
.count
;
386 uint32_t getParameterScalePointCount(const uint32_t parameterId
) const noexcept override
388 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, 0);
389 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, 0);
390 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, 0);
391 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, 0);
394 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
395 return param
->scalePointCount
;
397 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
401 // -------------------------------------------------------------------
402 // Information (current data)
406 // -------------------------------------------------------------------
407 // Information (per-plugin data)
409 uint
getOptionsAvailable() const noexcept override
411 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, 0x0);
412 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, 0x0);
414 bool hasMidiProgs
= false;
416 if (fDescriptor
->get_midi_program_count
!= nullptr)
419 hasMidiProgs
= fDescriptor
->get_midi_program_count(fHandle
) > 0;
425 // can't disable fixed buffers if required by the plugin
426 if ((fDescriptor
->hints
& NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
) == 0x0)
427 options
|= PLUGIN_OPTION_FIXED_BUFFERS
;
429 // can't disable forced stereo if enabled in the engine, or using CV
430 if (pData
->engine
->getOptions().forceStereo
|| pData
->cvIn
.count
!= 0 || pData
->cvOut
.count
!= 0)
432 // if inputs or outputs are just 1, then yes we can force stereo
433 else if (pData
->audioIn
.count
== 1 || pData
->audioOut
.count
== 1 || fHandle2
!= nullptr)
434 options
|= PLUGIN_OPTION_FORCE_STEREO
;
436 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES
)
437 options
|= PLUGIN_OPTION_SEND_CONTROL_CHANGES
;
438 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_CHANNEL_PRESSURE
)
439 options
|= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
;
440 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_NOTE_AFTERTOUCH
)
441 options
|= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
;
442 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_PITCHBEND
)
443 options
|= PLUGIN_OPTION_SEND_PITCHBEND
;
444 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF
)
445 options
|= PLUGIN_OPTION_SEND_ALL_SOUND_OFF
;
447 if (fDescriptor
->midiIns
> 0)
448 options
|= PLUGIN_OPTION_SKIP_SENDING_NOTES
;
450 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_PROGRAM_CHANGES
)
451 options
|= PLUGIN_OPTION_SEND_PROGRAM_CHANGES
;
452 else if (hasMidiProgs
)
453 options
|= PLUGIN_OPTION_MAP_PROGRAM_CHANGES
;
458 float getParameterValue(const uint32_t parameterId
) const noexcept override
460 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, 0.0f
);
461 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_value
!= nullptr, 0.0f
);
462 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, 0.0f
);
463 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, 0.0f
);
466 return fDescriptor
->get_parameter_value(fHandle
, parameterId
);
469 float getParameterScalePointValue(const uint32_t parameterId
, const uint32_t scalePointId
) const noexcept override
471 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, 0.0f
);
472 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, 0.0f
);
473 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, 0.0f
);
474 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, 0.0f
);
477 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
479 CARLA_SAFE_ASSERT_RETURN(scalePointId
< param
->scalePointCount
, 0.0f
);
481 const NativeParameterScalePoint
* scalePoint(¶m
->scalePoints
[scalePointId
]);
482 return scalePoint
->value
;
485 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
489 bool getLabel(char* const strBuf
) const noexcept override
491 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
493 if (fDescriptor
->label
!= nullptr)
495 std::strncpy(strBuf
, fDescriptor
->label
, STR_MAX
);
499 return CarlaPlugin::getLabel(strBuf
);
502 bool getMaker(char* const strBuf
) const noexcept override
504 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
506 if (fDescriptor
->maker
!= nullptr)
508 std::strncpy(strBuf
, fDescriptor
->maker
, STR_MAX
);
512 return CarlaPlugin::getMaker(strBuf
);
515 bool getCopyright(char* const strBuf
) const noexcept override
517 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
519 if (fDescriptor
->copyright
!= nullptr)
521 std::strncpy(strBuf
, fDescriptor
->copyright
, STR_MAX
);
525 return CarlaPlugin::getCopyright(strBuf
);
528 bool getRealName(char* const strBuf
) const noexcept override
530 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
532 if (fDescriptor
->name
!= nullptr)
534 std::strncpy(strBuf
, fDescriptor
->name
, STR_MAX
);
538 return CarlaPlugin::getRealName(strBuf
);
541 bool getParameterName(const uint32_t parameterId
, char* const strBuf
) const noexcept override
543 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
544 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, false);
545 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
546 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
549 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
551 if (param
->name
!= nullptr)
553 std::strncpy(strBuf
, param
->name
, STR_MAX
);
557 carla_safe_assert("param->name != nullptr", __FILE__
, __LINE__
);
558 return CarlaPlugin::getParameterName(parameterId
, strBuf
);
561 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
562 return CarlaPlugin::getParameterName(parameterId
, strBuf
);
565 bool getParameterUnit(const uint32_t parameterId
, char* const strBuf
) const noexcept override
567 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
568 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, false);
569 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
570 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
573 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
575 if (param
->unit
!= nullptr)
577 std::strncpy(strBuf
, param
->unit
, STR_MAX
);
581 return CarlaPlugin::getParameterUnit(parameterId
, strBuf
);
584 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
585 return CarlaPlugin::getParameterUnit(parameterId
, strBuf
);
588 bool getParameterComment(const uint32_t parameterId
, char* const strBuf
) const noexcept override
590 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
591 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, false);
592 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
593 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
596 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
598 if (param
->comment
!= nullptr)
600 std::strncpy(strBuf
, param
->comment
, STR_MAX
);
604 return CarlaPlugin::getParameterComment(parameterId
, strBuf
);
607 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
608 return CarlaPlugin::getParameterComment(parameterId
, strBuf
);
611 bool getParameterGroupName(const uint32_t parameterId
, char* const strBuf
) const noexcept override
613 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
614 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, false);
615 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
616 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
619 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
621 if (param
->groupName
!= nullptr)
623 std::strncpy(strBuf
, param
->groupName
, STR_MAX
);
627 return CarlaPlugin::getParameterGroupName(parameterId
, strBuf
);
630 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
631 return CarlaPlugin::getParameterGroupName(parameterId
, strBuf
);
634 bool getParameterScalePointLabel(const uint32_t parameterId
, const uint32_t scalePointId
, char* const strBuf
) const noexcept override
636 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr, false);
637 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->get_parameter_info
!= nullptr, false);
638 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
639 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
642 if (const NativeParameter
* const param
= fDescriptor
->get_parameter_info(fHandle
, parameterId
))
644 CARLA_SAFE_ASSERT_RETURN(scalePointId
< param
->scalePointCount
, false);
646 const NativeParameterScalePoint
* scalePoint(¶m
->scalePoints
[scalePointId
]);
648 if (scalePoint
->label
!= nullptr)
650 std::strncpy(strBuf
, scalePoint
->label
, STR_MAX
);
654 carla_safe_assert("scalePoint->label != nullptr", __FILE__
, __LINE__
);
655 return CarlaPlugin::getParameterScalePointLabel(parameterId
, scalePointId
, strBuf
);
658 carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__
, __LINE__
);
659 return CarlaPlugin::getParameterScalePointLabel(parameterId
, scalePointId
, strBuf
);
662 // -------------------------------------------------------------------
665 void prepareForSave(bool) override
667 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
668 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
670 if (pData
->midiprog
.count
> 0 && fDescriptor
->category
== NATIVE_PLUGIN_CATEGORY_SYNTH
)
672 char strBuf
[STR_MAX
+1];
673 std::snprintf(strBuf
, STR_MAX
, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i",
674 fCurMidiProgs
[0], fCurMidiProgs
[1], fCurMidiProgs
[2], fCurMidiProgs
[3],
675 fCurMidiProgs
[4], fCurMidiProgs
[5], fCurMidiProgs
[6], fCurMidiProgs
[7],
676 fCurMidiProgs
[8], fCurMidiProgs
[9], fCurMidiProgs
[10], fCurMidiProgs
[11],
677 fCurMidiProgs
[12], fCurMidiProgs
[13], fCurMidiProgs
[14], fCurMidiProgs
[15]);
678 strBuf
[STR_MAX
] = '\0';
680 CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING
, "midiPrograms", strBuf
, false);
683 if (fDescriptor
== nullptr || fDescriptor
->get_state
== nullptr || (fDescriptor
->hints
& NATIVE_PLUGIN_USES_STATE
) == 0)
686 if (char* data
= fDescriptor
->get_state(fHandle
))
688 CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_CHUNK
, "State", data
, false);
693 // -------------------------------------------------------------------
694 // Set data (internal stuff)
696 void setName(const char* const newName
) override
698 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
699 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
700 CARLA_SAFE_ASSERT_RETURN(newName
!= nullptr && newName
[0] != '\0',);
702 CarlaPlugin::setName(newName
);
704 if (pData
->uiTitle
.isEmpty())
705 setWindowTitle(nullptr);
708 void setCtrlChannel(const int8_t channel
, const bool sendOsc
, const bool sendCallback
) noexcept override
710 if (channel
>= 0 && channel
< MAX_MIDI_CHANNELS
&& pData
->midiprog
.count
> 0)
711 pData
->midiprog
.current
= fCurMidiProgs
[channel
];
713 CarlaPlugin::setCtrlChannel(channel
, sendOsc
, sendCallback
);
716 void setWindowTitle(const char* const title
) noexcept
720 if (title
!= nullptr)
726 uiName
= pData
->name
;
730 std::free(const_cast<char*>(fHost
.uiName
));
731 fHost
.uiName
= uiName
.releaseBufferPointer();
733 if (fDescriptor
->dispatcher
!= nullptr && fIsUiVisible
)
736 fDescriptor
->dispatcher(fHandle
,
737 NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED
,
739 const_cast<char*>(fHost
.uiName
),
741 } CARLA_SAFE_EXCEPTION("set custom ui title");
746 // -------------------------------------------------------------------
747 // Set data (plugin-specific stuff)
749 void setParameterValue(const uint32_t parameterId
, const float value
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
) noexcept override
751 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
752 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->set_parameter_value
!= nullptr,);
753 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
754 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
756 const float fixedValue(pData
->param
.getFixedValue(parameterId
, value
));
759 fDescriptor
->set_parameter_value(fHandle
, parameterId
, fixedValue
);
761 if (fHandle2
!= nullptr)
762 fDescriptor
->set_parameter_value(fHandle2
, parameterId
, fixedValue
);
764 CarlaPlugin::setParameterValue(parameterId
, fixedValue
, sendGui
, sendOsc
, sendCallback
);
767 void setParameterValueRT(const uint32_t parameterId
, const float value
, const uint32_t frameOffset
, const bool sendCallbackLater
) noexcept override
769 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
770 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->set_parameter_value
!= nullptr,);
771 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
772 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
774 const float fixedValue(pData
->param
.getFixedValue(parameterId
, value
));
777 fDescriptor
->set_parameter_value(fHandle
, parameterId
, fixedValue
);
779 if (fHandle2
!= nullptr)
780 fDescriptor
->set_parameter_value(fHandle2
, parameterId
, fixedValue
);
782 CarlaPlugin::setParameterValueRT(parameterId
, fixedValue
, frameOffset
, sendCallbackLater
);
785 void setCustomData(const char* const type
, const char* const key
, const char* const value
, const bool sendGui
) override
787 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
788 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
789 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr && type
[0] != '\0',);
790 CARLA_SAFE_ASSERT_RETURN(key
!= nullptr && key
[0] != '\0',);
791 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr,);
792 carla_debug("CarlaPluginNative::setCustomData(\"%s\", \"%s\", ..., %s)", type
, key
, bool2str(sendGui
));
794 if (std::strcmp(type
, CUSTOM_DATA_TYPE_PROPERTY
) == 0)
795 return CarlaPlugin::setCustomData(type
, key
, value
, sendGui
);
797 if (std::strcmp(type
, CUSTOM_DATA_TYPE_PATH
) == 0)
799 CARLA_SAFE_ASSERT_RETURN(std::strcmp(key
, "file") == 0,);
800 CARLA_SAFE_ASSERT_RETURN(value
[0] != '\0',);
802 else if (std::strcmp(type
, CUSTOM_DATA_TYPE_STRING
) != 0 && std::strcmp(type
, CUSTOM_DATA_TYPE_CHUNK
) != 0)
804 return carla_stderr2("CarlaPluginNative::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is invalid",
805 type
, key
, value
, bool2str(sendGui
));
808 if (std::strcmp(type
, CUSTOM_DATA_TYPE_CHUNK
) == 0)
810 if (fDescriptor
->set_state
!= nullptr && (fDescriptor
->hints
& NATIVE_PLUGIN_USES_STATE
) != 0)
812 const ScopedSingleProcessLocker
spl(this, true);
814 fDescriptor
->set_state(fHandle
, value
);
816 if (fHandle2
!= nullptr)
817 fDescriptor
->set_state(fHandle2
, value
);
820 else if (std::strcmp(key
, "midiPrograms") == 0 && fDescriptor
->set_midi_program
!= nullptr)
822 StringArray
midiProgramList(StringArray::fromTokens(value
, ":", ""));
824 if (midiProgramList
.size() == MAX_MIDI_CHANNELS
)
827 for (String
*it
=midiProgramList
.begin(), *end
=midiProgramList
.end(); it
!= end
; ++it
)
829 const int index(it
->getIntValue());
831 if (index
>= 0 && index
< static_cast<int>(pData
->midiprog
.count
))
833 const uint32_t bank
= pData
->midiprog
.data
[index
].bank
;
834 const uint32_t program
= pData
->midiprog
.data
[index
].program
;
836 fDescriptor
->set_midi_program(fHandle
, channel
, bank
, program
);
838 if (fHandle2
!= nullptr)
839 fDescriptor
->set_midi_program(fHandle2
, channel
, bank
, program
);
841 fCurMidiProgs
[channel
] = index
;
843 if (pData
->ctrlChannel
== static_cast<int32_t>(channel
))
845 pData
->midiprog
.current
= index
;
846 pData
->engine
->callback(true, true,
847 ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED
,
850 0, 0, 0.0f
, nullptr);
856 CARLA_SAFE_ASSERT(channel
== MAX_MIDI_CHANNELS
);
861 if (fDescriptor
->set_custom_data
!= nullptr)
863 fDescriptor
->set_custom_data(fHandle
, key
, value
);
865 if (fHandle2
!= nullptr)
866 fDescriptor
->set_custom_data(fHandle2
, key
, value
);
869 if (sendGui
&& fIsUiVisible
&& fDescriptor
->ui_set_custom_data
!= nullptr)
870 fDescriptor
->ui_set_custom_data(fHandle
, key
, value
);
873 CarlaPlugin::setCustomData(type
, key
, value
, sendGui
);
876 void setMidiProgram(const int32_t index
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
, const bool doingInit
) noexcept override
878 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
879 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
880 CARLA_SAFE_ASSERT_RETURN(index
>= -1 && index
< static_cast<int32_t>(pData
->midiprog
.count
),);
881 CARLA_SAFE_ASSERT_RETURN(sendGui
|| sendOsc
|| sendCallback
|| doingInit
,);
883 // TODO, put into check below
884 if ((pData
->hints
& PLUGIN_IS_SYNTH
) != 0 && (pData
->ctrlChannel
< 0 || pData
->ctrlChannel
>= MAX_MIDI_CHANNELS
))
885 return CarlaPlugin::setMidiProgram(index
, sendGui
, sendOsc
, sendCallback
, doingInit
);
889 const uint8_t channel
= uint8_t((pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
) ? pData
->ctrlChannel
: 0);
890 const uint32_t bank
= pData
->midiprog
.data
[index
].bank
;
891 const uint32_t program
= pData
->midiprog
.data
[index
].program
;
893 const ScopedSingleProcessLocker
spl(this, (sendGui
|| sendOsc
|| sendCallback
));
896 fDescriptor
->set_midi_program(fHandle
, channel
, bank
, program
);
899 if (fHandle2
!= nullptr)
902 fDescriptor
->set_midi_program(fHandle2
, channel
, bank
, program
);
906 fCurMidiProgs
[channel
] = index
;
909 CarlaPlugin::setMidiProgram(index
, sendGui
, sendOsc
, sendCallback
, doingInit
);
912 // FIXME: this is never used
913 void setMidiProgramRT(const uint32_t index
, const bool sendCallbackLater
) noexcept override
915 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
916 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
917 CARLA_SAFE_ASSERT_RETURN(index
< pData
->midiprog
.count
,);
919 // TODO, put into check below
920 if ((pData
->hints
& PLUGIN_IS_SYNTH
) != 0 && (pData
->ctrlChannel
< 0 || pData
->ctrlChannel
>= MAX_MIDI_CHANNELS
))
921 return CarlaPlugin::setMidiProgramRT(index
, sendCallbackLater
);
923 const uint8_t channel
= uint8_t((pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
) ? pData
->ctrlChannel
: 0);
924 const uint32_t bank
= pData
->midiprog
.data
[index
].bank
;
925 const uint32_t program
= pData
->midiprog
.data
[index
].program
;
928 fDescriptor
->set_midi_program(fHandle
, channel
, bank
, program
);
931 if (fHandle2
!= nullptr)
934 fDescriptor
->set_midi_program(fHandle2
, channel
, bank
, program
);
938 fCurMidiProgs
[channel
] = static_cast<int32_t>(index
);
940 CarlaPlugin::setMidiProgramRT(index
, sendCallbackLater
);
943 // -------------------------------------------------------------------
946 void setCustomUITitle(const char* const title
) noexcept override
948 setWindowTitle(title
);
949 CarlaPlugin::setCustomUITitle(title
);
952 void showCustomUI(const bool yesNo
) override
954 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
955 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
957 if (fDescriptor
->ui_show
== nullptr)
960 fIsUiAvailable
= true;
962 fDescriptor
->ui_show(fHandle
, yesNo
);
964 // UI might not be available, see NATIVE_HOST_OPCODE_UI_UNAVAILABLE
965 if (yesNo
&& ! fIsUiAvailable
)
968 fIsUiVisible
= yesNo
;
973 pData
->transientTryCounter
= 0;
979 if ((fDescriptor
->hints
& NATIVE_PLUGIN_USES_PARENT_ID
) == 0 && std::strstr(fDescriptor
->label
, "file") == nullptr)
980 pData
->tryTransient();
983 if (fDescriptor
->ui_set_custom_data
!= nullptr)
985 for (LinkedList
<CustomData
>::Itenerator it
= pData
->custom
.begin2(); it
.valid(); it
.next())
987 const CustomData
& cData(it
.getValue(kCustomDataFallback
));
988 CARLA_SAFE_ASSERT_CONTINUE(cData
.isValid());
990 if (std::strcmp(cData
.type
, CUSTOM_DATA_TYPE_STRING
) == 0 && std::strcmp(cData
.key
, "midiPrograms") != 0)
991 fDescriptor
->ui_set_custom_data(fHandle
, cData
.key
, cData
.value
);
995 if (fDescriptor
->ui_set_midi_program
!= nullptr && pData
->midiprog
.current
>= 0 && pData
->midiprog
.count
> 0)
997 const int32_t index
= pData
->midiprog
.current
;
998 const uint8_t channel
= uint8_t((pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
) ? pData
->ctrlChannel
: 0);
999 const uint32_t bank
= pData
->midiprog
.data
[index
].bank
;
1000 const uint32_t program
= pData
->midiprog
.data
[index
].program
;
1002 fDescriptor
->ui_set_midi_program(fHandle
, channel
, bank
, program
);
1005 if (fDescriptor
->ui_set_parameter_value
!= nullptr)
1007 for (uint32_t i
=0; i
< pData
->param
.count
; ++i
)
1008 fDescriptor
->ui_set_parameter_value(fHandle
, i
, fDescriptor
->get_parameter_value(fHandle
, i
));
1012 void idle() override
1017 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_IDLE
, 0, 0, nullptr, 0.0f
);
1020 if (fInlineDisplayNeedsRedraw
)
1023 CARLA_SAFE_ASSERT(pData
->enabled
)
1024 CARLA_SAFE_ASSERT(!pData
->engine
->isAboutToClose());
1025 CARLA_SAFE_ASSERT(pData
->client
->isActive());
1027 if (pData
->enabled
&& !pData
->engine
->isAboutToClose() && pData
->client
->isActive())
1029 const int64_t timeNow
= water::Time::currentTimeMillis();
1031 if (timeNow
- fInlineDisplayLastRedrawTime
> (1000 / 30))
1033 fInlineDisplayNeedsRedraw
= false;
1034 fInlineDisplayLastRedrawTime
= timeNow
;
1035 pData
->engine
->callback(true, true,
1036 ENGINE_CALLBACK_INLINE_DISPLAY_REDRAW
,
1038 0, 0, 0, 0.0f
, nullptr);
1043 fInlineDisplayNeedsRedraw
= false;
1047 CarlaPlugin::idle();
1050 void uiIdle() override
1052 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
1053 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
1055 if (fIsUiVisible
&& fDescriptor
->ui_idle
!= nullptr)
1056 fDescriptor
->ui_idle(fHandle
);
1058 CarlaPlugin::uiIdle();
1061 // -------------------------------------------------------------------
1064 void reload() override
1066 CARLA_SAFE_ASSERT_RETURN(pData
->engine
!= nullptr,);
1067 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
1068 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
1069 carla_debug("CarlaPluginNative::reload() - start");
1071 const EngineProcessMode
processMode(pData
->engine
->getProccessMode());
1073 // Safely disable plugin for reload
1074 const ScopedDisabler
sd(this);
1081 uint32_t aIns
, aOuts
, cvIns
, cvOuts
, mIns
, mOuts
, j
;
1083 bool forcedStereoIn
, forcedStereoOut
;
1084 forcedStereoIn
= forcedStereoOut
= false;
1086 bool needsCtrlIn
, needsCtrlOut
;
1087 needsCtrlIn
= needsCtrlOut
= false;
1089 aIns
= fDescriptor
->audioIns
;
1090 aOuts
= fDescriptor
->audioOuts
;
1091 cvIns
= fDescriptor
->cvIns
;
1092 cvOuts
= fDescriptor
->cvOuts
;
1093 mIns
= fDescriptor
->midiIns
;
1094 mOuts
= fDescriptor
->midiOuts
;
1096 if ((pData
->options
& PLUGIN_OPTION_FORCE_STEREO
) != 0 && (aIns
== 1 || aOuts
== 1) && mIns
<= 1 && mOuts
<= 1)
1098 if (fHandle2
== nullptr)
1099 fHandle2
= fDescriptor
->instantiate(&fHost
);
1101 if (fHandle2
!= nullptr)
1106 forcedStereoIn
= true;
1112 forcedStereoOut
= true;
1119 pData
->audioIn
.createNew(aIns
);
1124 pData
->audioOut
.createNew(aOuts
);
1130 pData
->cvIn
.createNew(cvIns
);
1135 pData
->cvOut
.createNew(cvOuts
);
1138 if (const uint32_t acIns
= aIns
+ cvIns
)
1140 fAudioAndCvInBuffers
= new float*[acIns
];
1141 carla_zeroPointers(fAudioAndCvInBuffers
, acIns
);
1144 if (const uint32_t acOuts
= aOuts
+ cvOuts
)
1146 fAudioAndCvOutBuffers
= new float*[acOuts
];
1147 carla_zeroPointers(fAudioAndCvOutBuffers
, acOuts
);
1152 fMidiIn
.createNew(mIns
);
1153 needsCtrlIn
= (mIns
== 1);
1158 fMidiOut
.createNew(mOuts
);
1159 needsCtrlOut
= (mOuts
== 1);
1162 const uint
portNameSize(pData
->engine
->getMaxPortNameSize());
1163 CarlaString portName
;
1166 for (j
=0; j
< aIns
; ++j
)
1170 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1172 portName
= pData
->name
;
1176 if (fDescriptor
->get_buffer_port_name
!= nullptr)
1178 portName
+= fDescriptor
->get_buffer_port_name(fHandle
, forcedStereoIn
? 0 : j
, false);
1180 else if (aIns
> 1 && ! forcedStereoIn
)
1182 portName
+= "input_";
1183 portName
+= CarlaString(j
+1);
1186 portName
+= "input";
1188 portName
.truncate(portNameSize
);
1190 pData
->audioIn
.ports
[j
].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, true, j
);
1191 pData
->audioIn
.ports
[j
].rindex
= j
;
1196 pData
->audioIn
.ports
[1].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, true, 1);
1197 pData
->audioIn
.ports
[1].rindex
= j
;
1203 for (j
=0; j
< aOuts
; ++j
)
1207 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1209 portName
= pData
->name
;
1213 if (fDescriptor
->get_buffer_port_name
!= nullptr)
1215 portName
+= fDescriptor
->get_buffer_port_name(fHandle
, forcedStereoOut
? 0 : j
, true);
1217 else if (aOuts
> 1 && ! forcedStereoOut
)
1219 portName
+= "output_";
1220 portName
+= CarlaString(j
+1);
1223 portName
+= "output";
1225 portName
.truncate(portNameSize
);
1227 pData
->audioOut
.ports
[j
].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, false, j
);
1228 pData
->audioOut
.ports
[j
].rindex
= j
;
1230 if (forcedStereoOut
)
1233 pData
->audioOut
.ports
[1].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, false, 1);
1234 pData
->audioOut
.ports
[1].rindex
= j
;
1240 for (j
=0; j
< cvIns
; ++j
)
1244 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1246 portName
= pData
->name
;
1250 if (fDescriptor
->get_buffer_port_name
!= nullptr)
1252 portName
+= fDescriptor
->get_buffer_port_name(fHandle
, fDescriptor
->audioIns
+ j
, false);
1256 portName
+= "cv_input_";
1257 portName
+= CarlaString(j
+1);
1260 portName
+= "cv_input";
1262 portName
.truncate(portNameSize
);
1264 float min
= -1.0f
, max
= 1.0f
;
1265 if (fDescriptor
->get_buffer_port_range
!= nullptr)
1267 if (const NativePortRange
* const range
= fDescriptor
->get_buffer_port_range(fHandle
,
1268 fDescriptor
->audioIns
+ j
,
1271 min
= range
->minimum
;
1272 max
= range
->maximum
;
1276 pData
->cvIn
.ports
[j
].port
= (CarlaEngineCVPort
*)pData
->client
->addPort(kEnginePortTypeCV
, portName
, true, j
);
1277 pData
->cvIn
.ports
[j
].rindex
= j
;
1278 pData
->cvIn
.ports
[j
].port
->setRange(min
, max
);
1282 for (j
=0; j
< cvOuts
; ++j
)
1286 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1288 portName
= pData
->name
;
1292 if (fDescriptor
->get_buffer_port_name
!= nullptr)
1294 portName
+= fDescriptor
->get_buffer_port_name(fHandle
, fDescriptor
->audioOuts
+ j
, true);
1296 else if (cvOuts
> 1)
1298 portName
+= "cv_output_";
1299 portName
+= CarlaString(j
+1);
1302 portName
+= "cv_output";
1304 portName
.truncate(portNameSize
);
1306 float min
= -1.0f
, max
= 1.0f
;
1307 if (fDescriptor
->get_buffer_port_range
!= nullptr)
1309 if (const NativePortRange
* const range
= fDescriptor
->get_buffer_port_range(fHandle
,
1310 fDescriptor
->audioOuts
+ j
,
1313 min
= range
->minimum
;
1314 max
= range
->maximum
;
1318 pData
->cvOut
.ports
[j
].port
= (CarlaEngineCVPort
*)pData
->client
->addPort(kEnginePortTypeCV
, portName
, false, j
);
1319 pData
->cvOut
.ports
[j
].rindex
= j
;
1320 pData
->cvOut
.ports
[j
].port
->setRange(min
, max
);
1323 // MIDI Input (only if multiple)
1326 for (j
=0; j
< mIns
; ++j
)
1330 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1332 portName
= pData
->name
;
1336 portName
+= "midi-in_";
1337 portName
+= CarlaString(j
+1);
1338 portName
.truncate(portNameSize
);
1340 fMidiIn
.ports
[j
] = (CarlaEngineEventPort
*)pData
->client
->addPort(kEnginePortTypeEvent
, portName
, true, j
);
1341 fMidiIn
.indexes
[j
] = j
;
1344 pData
->event
.portIn
= fMidiIn
.ports
[0];
1347 // MIDI Output (only if multiple)
1350 for (j
=0; j
< mOuts
; ++j
)
1354 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1356 portName
= pData
->name
;
1360 portName
+= "midi-out_";
1361 portName
+= CarlaString(j
+1);
1362 portName
.truncate(portNameSize
);
1364 fMidiOut
.ports
[j
] = (CarlaEngineEventPort
*)pData
->client
->addPort(kEnginePortTypeEvent
, portName
, false, j
);
1365 fMidiOut
.indexes
[j
] = j
;
1368 pData
->event
.portOut
= fMidiOut
.ports
[0];
1371 reloadParameters(&needsCtrlIn
, &needsCtrlOut
);
1373 if (needsCtrlIn
|| mIns
== 1)
1377 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1379 portName
= pData
->name
;
1383 portName
+= "events-in";
1384 portName
.truncate(portNameSize
);
1386 pData
->event
.portIn
= (CarlaEngineEventPort
*)pData
->client
->addPort(kEnginePortTypeEvent
, portName
, true, 0);
1387 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1388 pData
->event
.cvSourcePorts
= pData
->client
->createCVSourcePorts();
1392 if (needsCtrlOut
|| mOuts
== 1)
1396 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1398 portName
= pData
->name
;
1402 portName
+= "events-out";
1403 portName
.truncate(portNameSize
);
1405 pData
->event
.portOut
= (CarlaEngineEventPort
*)pData
->client
->addPort(kEnginePortTypeEvent
, portName
, false, 0);
1408 if (forcedStereoIn
|| forcedStereoOut
)
1409 pData
->options
|= PLUGIN_OPTION_FORCE_STEREO
;
1411 pData
->options
&= ~PLUGIN_OPTION_FORCE_STEREO
;
1416 if (aOuts
> 0 && (aIns
== aOuts
|| aIns
== 1))
1417 pData
->hints
|= PLUGIN_CAN_DRYWET
;
1420 pData
->hints
|= PLUGIN_CAN_VOLUME
;
1422 if (aOuts
>= 2 && aOuts
% 2 == 0)
1423 pData
->hints
|= PLUGIN_CAN_BALANCE
;
1425 // native plugin hints
1426 if (fDescriptor
->hints
& NATIVE_PLUGIN_IS_RTSAFE
)
1427 pData
->hints
|= PLUGIN_IS_RTSAFE
;
1428 if (fDescriptor
->hints
& NATIVE_PLUGIN_IS_SYNTH
)
1429 pData
->hints
|= PLUGIN_IS_SYNTH
;
1430 if (fDescriptor
->hints
& NATIVE_PLUGIN_HAS_UI
)
1431 pData
->hints
|= PLUGIN_HAS_CUSTOM_UI
;
1432 if (fDescriptor
->hints
& NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
)
1433 pData
->hints
|= PLUGIN_NEEDS_FIXED_BUFFERS
;
1434 if (fDescriptor
->hints
& NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
)
1435 pData
->hints
|= PLUGIN_NEEDS_UI_MAIN_THREAD
;
1436 if (fDescriptor
->hints
& NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE
)
1437 pData
->hints
|= PLUGIN_HAS_CUSTOM_UI_USING_FILE_OPEN
;
1438 if (fDescriptor
->hints
& NATIVE_PLUGIN_USES_MULTI_PROGS
)
1439 pData
->hints
|= PLUGIN_USES_MULTI_PROGS
;
1440 if (fDescriptor
->hints
& NATIVE_PLUGIN_HAS_INLINE_DISPLAY
)
1441 pData
->hints
|= PLUGIN_HAS_INLINE_DISPLAY
;
1443 // extra plugin hints
1444 pData
->extraHints
= 0x0;
1446 bufferSizeChanged(pData
->engine
->getBufferSize());
1447 reloadPrograms(true);
1452 carla_debug("CarlaPluginNative::reload() - end");
1455 void reloadParameters(bool* const needsCtrlIn
, bool* const needsCtrlOut
)
1457 carla_debug("CarlaPluginNative::reloadParameters() - start");
1459 const float sampleRate
= static_cast<float>(pData
->engine
->getSampleRate());
1460 const uint32_t params
= (fDescriptor
->get_parameter_count
!= nullptr && fDescriptor
->get_parameter_info
!= nullptr)
1461 ? fDescriptor
->get_parameter_count(fHandle
)
1464 pData
->param
.clear();
1468 pData
->param
.createNew(params
, true);
1471 for (uint32_t j
=0; j
< params
; ++j
)
1473 const NativeParameter
* const paramInfo(fDescriptor
->get_parameter_info(fHandle
, j
));
1475 CARLA_SAFE_ASSERT_CONTINUE(paramInfo
!= nullptr);
1477 pData
->param
.data
[j
].type
= PARAMETER_UNKNOWN
;
1478 pData
->param
.data
[j
].index
= static_cast<int32_t>(j
);
1479 pData
->param
.data
[j
].rindex
= static_cast<int32_t>(j
);
1481 float min
, max
, def
, step
, stepSmall
, stepLarge
;
1484 min
= paramInfo
->ranges
.min
;
1487 max
= paramInfo
->ranges
.max
;
1492 if (carla_isEqual(min
, max
))
1494 carla_stderr2("WARNING - Broken plugin parameter '%s': max == min", paramInfo
->name
);
1499 def
= paramInfo
->ranges
.def
;
1506 if (paramInfo
->hints
& NATIVE_PARAMETER_USES_SAMPLE_RATE
)
1511 pData
->param
.data
[j
].hints
|= PARAMETER_USES_SAMPLERATE
;
1514 if (paramInfo
->hints
& NATIVE_PARAMETER_IS_BOOLEAN
)
1519 pData
->param
.data
[j
].hints
|= PARAMETER_IS_BOOLEAN
;
1521 else if (paramInfo
->hints
& NATIVE_PARAMETER_IS_INTEGER
)
1526 pData
->param
.data
[j
].hints
|= PARAMETER_IS_INTEGER
;
1530 float range
= max
- min
;
1531 step
= range
/100.0f
;
1532 stepSmall
= range
/1000.0f
;
1533 stepLarge
= range
/10.0f
;
1536 if (paramInfo
->hints
& NATIVE_PARAMETER_IS_OUTPUT
)
1538 pData
->param
.data
[j
].type
= PARAMETER_OUTPUT
;
1539 if (needsCtrlOut
!= nullptr)
1540 *needsCtrlOut
= true;
1544 pData
->param
.data
[j
].type
= PARAMETER_INPUT
;
1545 if (needsCtrlIn
!= nullptr)
1546 *needsCtrlIn
= true;
1549 // extra parameter hints
1550 if (paramInfo
->hints
& NATIVE_PARAMETER_IS_ENABLED
)
1552 pData
->param
.data
[j
].hints
|= PARAMETER_IS_ENABLED
;
1554 if (paramInfo
->hints
& NATIVE_PARAMETER_IS_AUTOMATABLE
)
1556 pData
->param
.data
[j
].hints
|= PARAMETER_IS_AUTOMATABLE
;
1557 pData
->param
.data
[j
].hints
|= PARAMETER_CAN_BE_CV_CONTROLLED
;
1561 if (paramInfo
->hints
& NATIVE_PARAMETER_IS_LOGARITHMIC
)
1562 pData
->param
.data
[j
].hints
|= PARAMETER_IS_LOGARITHMIC
;
1564 if (paramInfo
->hints
& NATIVE_PARAMETER_USES_SCALEPOINTS
)
1565 pData
->param
.data
[j
].hints
|= PARAMETER_USES_SCALEPOINTS
;
1567 pData
->param
.ranges
[j
].min
= min
;
1568 pData
->param
.ranges
[j
].max
= max
;
1569 pData
->param
.ranges
[j
].def
= def
;
1570 pData
->param
.ranges
[j
].step
= step
;
1571 pData
->param
.ranges
[j
].stepSmall
= stepSmall
;
1572 pData
->param
.ranges
[j
].stepLarge
= stepLarge
;
1575 carla_debug("CarlaPluginNative::reloadParameters() - end");
1578 void reloadPrograms(const bool doInit
) override
1580 carla_debug("CarlaPluginNative::reloadPrograms(%s)", bool2str(doInit
));
1581 uint32_t i
, oldCount
= pData
->midiprog
.count
;
1582 const int32_t current
= pData
->midiprog
.current
;
1584 // Delete old programs
1585 pData
->midiprog
.clear();
1587 // Query new programs
1589 if (fDescriptor
->get_midi_program_count
!= nullptr && fDescriptor
->get_midi_program_info
!= nullptr && fDescriptor
->set_midi_program
!= nullptr)
1590 count
= fDescriptor
->get_midi_program_count(fHandle
);
1594 pData
->midiprog
.createNew(count
);
1597 for (i
=0; i
< count
; ++i
)
1599 const NativeMidiProgram
* const mpDesc(fDescriptor
->get_midi_program_info(fHandle
, i
));
1600 CARLA_SAFE_ASSERT_CONTINUE(mpDesc
!= nullptr);
1602 pData
->midiprog
.data
[i
].bank
= mpDesc
->bank
;
1603 pData
->midiprog
.data
[i
].program
= mpDesc
->program
;
1604 pData
->midiprog
.data
[i
].name
= carla_strdup(mpDesc
->name
);
1611 setMidiProgram(0, false, false, false, true);
1615 // Check if current program is invalid
1616 bool programChanged
= false;
1618 if (count
== oldCount
+1)
1620 // one midi program added, probably created by user
1621 pData
->midiprog
.current
= static_cast<int32_t>(oldCount
);
1622 programChanged
= true;
1624 else if (current
< 0 && count
> 0)
1626 // programs exist now, but not before
1627 pData
->midiprog
.current
= 0;
1628 programChanged
= true;
1630 else if (current
>= 0 && count
== 0)
1632 // programs existed before, but not anymore
1633 pData
->midiprog
.current
= -1;
1634 programChanged
= true;
1636 else if (current
>= static_cast<int32_t>(count
))
1638 // current midi program > count
1639 pData
->midiprog
.current
= 0;
1640 programChanged
= true;
1645 pData
->midiprog
.current
= current
;
1649 setMidiProgram(pData
->midiprog
.current
, true, true, true, false);
1651 pData
->engine
->callback(true, true,
1652 ENGINE_CALLBACK_RELOAD_PROGRAMS
,
1654 0, 0, 0, 0.0f
, nullptr);
1658 // -------------------------------------------------------------------
1659 // Plugin processing
1661 void activate() noexcept override
1663 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
1664 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
1666 if (fDescriptor
->activate
!= nullptr)
1669 fDescriptor
->activate(fHandle
);
1672 if (fHandle2
!= nullptr)
1675 fDescriptor
->activate(fHandle2
);
1681 void deactivate() noexcept override
1683 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
1684 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
1686 if (fDescriptor
->deactivate
!= nullptr)
1689 fDescriptor
->deactivate(fHandle
);
1692 if (fHandle2
!= nullptr)
1695 fDescriptor
->deactivate(fHandle2
);
1701 EngineEvent
& findNextEvent()
1703 if (fMidiIn
.count
== 1)
1705 NativePluginMidiInData::MultiPortData
& multiportData(fMidiIn
.multiportData
[0]);
1707 if (multiportData
.usedIndex
== multiportData
.cachedEventCount
)
1709 const uint32_t eventCount
= pData
->event
.portIn
->getEventCount();
1710 CARLA_SAFE_ASSERT_INT2(eventCount
== multiportData
.cachedEventCount
,
1711 eventCount
, multiportData
.cachedEventCount
);
1712 return kNullEngineEvent
;
1715 return pData
->event
.portIn
->getEvent(multiportData
.usedIndex
++);
1718 uint32_t lowestSampleTime
= 9999999;
1719 uint32_t portMatching
= 0;
1722 // process events in order for multiple ports
1723 for (uint32_t m
=0; m
< fMidiIn
.count
; ++m
)
1725 CarlaEngineEventPort
* const eventPort(fMidiIn
.ports
[m
]);
1726 NativePluginMidiInData::MultiPortData
& multiportData(fMidiIn
.multiportData
[m
]);
1728 if (multiportData
.usedIndex
== multiportData
.cachedEventCount
)
1731 const EngineEvent
& event(eventPort
->getEventUnchecked(multiportData
.usedIndex
));
1733 if (event
.time
< lowestSampleTime
)
1735 lowestSampleTime
= event
.time
;
1743 CarlaEngineEventPort
* const eventPort(fMidiIn
.ports
[portMatching
]);
1744 NativePluginMidiInData::MultiPortData
& multiportData(fMidiIn
.multiportData
[portMatching
]);
1746 return eventPort
->getEvent(multiportData
.usedIndex
++);
1749 return kNullEngineEvent
;
1752 void process(const float* const* const audioIn
, float** const audioOut
,
1753 const float* const* const cvIn
, float** const cvOut
, const uint32_t frames
) override
1755 // --------------------------------------------------------------------------------------------------------
1758 if (! pData
->active
)
1760 // disable any output sound
1761 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1762 carla_zeroFloats(audioOut
[i
], frames
);
1763 for (uint32_t i
=0; i
< pData
->cvOut
.count
; ++i
)
1764 carla_zeroFloats(cvOut
[i
], frames
);
1768 fMidiEventInCount
= fMidiEventOutCount
= 0;
1769 carla_zeroStructs(fMidiInEvents
, kPluginMaxMidiEvents
);
1770 carla_zeroStructs(fMidiOutEvents
, kPluginMaxMidiEvents
);
1772 // --------------------------------------------------------------------------------------------------------
1773 // Check if needs reset
1775 if (pData
->needsReset
)
1777 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
1779 fMidiEventInCount
= MAX_MIDI_CHANNELS
*2;
1781 for (uint8_t k
=0, i
=MAX_MIDI_CHANNELS
; k
< MAX_MIDI_CHANNELS
; ++k
)
1783 fMidiInEvents
[k
].data
[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE
| (k
& MIDI_CHANNEL_BIT
));
1784 fMidiInEvents
[k
].data
[1] = MIDI_CONTROL_ALL_NOTES_OFF
;
1785 fMidiInEvents
[k
].data
[2] = 0;
1786 fMidiInEvents
[k
].size
= 3;
1788 fMidiInEvents
[k
+i
].data
[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE
| (k
& MIDI_CHANNEL_BIT
));
1789 fMidiInEvents
[k
+i
].data
[1] = MIDI_CONTROL_ALL_SOUND_OFF
;
1790 fMidiInEvents
[k
+i
].data
[2] = 0;
1791 fMidiInEvents
[k
+i
].size
= 3;
1794 else if (pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
)
1796 fMidiEventInCount
= MAX_MIDI_NOTE
;
1798 for (uint8_t k
=0; k
< MAX_MIDI_NOTE
; ++k
)
1800 fMidiInEvents
[k
].data
[0] = uint8_t(MIDI_STATUS_NOTE_OFF
| (pData
->ctrlChannel
& MIDI_CHANNEL_BIT
));
1801 fMidiInEvents
[k
].data
[1] = k
;
1802 fMidiInEvents
[k
].data
[2] = 0;
1803 fMidiInEvents
[k
].size
= 3;
1807 pData
->needsReset
= false;
1810 // --------------------------------------------------------------------------------------------------------
1813 const EngineTimeInfo
timeInfo(pData
->engine
->getTimeInfo());
1815 fTimeInfo
.playing
= timeInfo
.playing
;
1816 fTimeInfo
.frame
= timeInfo
.frame
;
1817 fTimeInfo
.usecs
= timeInfo
.usecs
;
1819 if (timeInfo
.bbt
.valid
)
1821 fTimeInfo
.bbt
.valid
= true;
1823 fTimeInfo
.bbt
.bar
= timeInfo
.bbt
.bar
;
1824 fTimeInfo
.bbt
.beat
= timeInfo
.bbt
.beat
;
1825 fTimeInfo
.bbt
.tick
= timeInfo
.bbt
.tick
;
1826 fTimeInfo
.bbt
.barStartTick
= timeInfo
.bbt
.barStartTick
;
1828 fTimeInfo
.bbt
.beatsPerBar
= timeInfo
.bbt
.beatsPerBar
;
1829 fTimeInfo
.bbt
.beatType
= timeInfo
.bbt
.beatType
;
1831 fTimeInfo
.bbt
.ticksPerBeat
= timeInfo
.bbt
.ticksPerBeat
;
1832 fTimeInfo
.bbt
.beatsPerMinute
= timeInfo
.bbt
.beatsPerMinute
;
1836 fTimeInfo
.bbt
.valid
= false;
1840 // This test code has proven to be quite useful
1841 // So I am leaving it behind, I might need it again..
1844 static int64_t last_frame
= timeInfo
.frame
;
1845 static int64_t last_dev_frame
= 0;
1846 static double last_val
= timeInfo
.bbt
.barStartTick
+ ((timeInfo
.bbt
.beat
-1) * timeInfo
.bbt
.ticksPerBeat
) + timeInfo
.bbt
.tick
;
1847 static double last_dev_val
= 0.0;
1849 int64_t cur_frame
= timeInfo
.frame
;
1850 int64_t cur_dev_frame
= cur_frame
- last_frame
;
1852 double cur_val
= timeInfo
.bbt
.barStartTick
+ ((timeInfo
.bbt
.beat
-1) * timeInfo
.bbt
.ticksPerBeat
) + timeInfo
.bbt
.tick
;
1853 double cur_dev_val
= cur_val
- last_val
;
1855 if (std::abs(last_dev_val
- cur_dev_val
) >= 0.0001 || last_dev_frame
!= cur_dev_frame
)
1857 carla_stdout("currently %u at %u => %f : DEV1: %li : DEV2: %f",
1866 last_dev_val
= cur_dev_val
;
1867 last_frame
= cur_frame
;
1868 last_dev_frame
= cur_dev_frame
;
1872 // --------------------------------------------------------------------------------------------------------
1873 // Event Input and Processing
1875 if (pData
->event
.portIn
!= nullptr)
1877 // ----------------------------------------------------------------------------------------------------
1878 // MIDI Input (External)
1880 if (pData
->extNotes
.mutex
.tryLock())
1882 ExternalMidiNote note
= { 0, 0, 0 };
1884 for (; fMidiEventInCount
< kPluginMaxMidiEvents
&& ! pData
->extNotes
.data
.isEmpty();)
1886 note
= pData
->extNotes
.data
.getFirst(note
, true);
1888 CARLA_SAFE_ASSERT_CONTINUE(note
.channel
>= 0 && note
.channel
< MAX_MIDI_CHANNELS
);
1890 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
1892 nativeEvent
.data
[0] = uint8_t((note
.velo
> 0 ? MIDI_STATUS_NOTE_ON
: MIDI_STATUS_NOTE_OFF
) | (note
.channel
& MIDI_CHANNEL_BIT
));
1893 nativeEvent
.data
[1] = note
.note
;
1894 nativeEvent
.data
[2] = note
.velo
;
1895 nativeEvent
.size
= 3;
1898 pData
->extNotes
.mutex
.unlock();
1900 } // End of MIDI Input (External)
1902 // ----------------------------------------------------------------------------------------------------
1903 // Event Input (System)
1905 #ifndef BUILD_BRIDGE
1906 bool allNotesOffSent
= false;
1908 const bool isSampleAccurate
= (pData
->options
& PLUGIN_OPTION_FIXED_BUFFERS
) == 0;
1910 uint32_t startTime
= 0;
1911 uint32_t timeOffset
= 0;
1912 uint32_t nextBankId
;
1914 if (pData
->midiprog
.current
>= 0 && pData
->midiprog
.count
> 0)
1915 nextBankId
= pData
->midiprog
.data
[pData
->midiprog
.current
].bank
;
1919 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1920 if (cvIn
!= nullptr && pData
->event
.cvSourcePorts
!= nullptr)
1921 pData
->event
.cvSourcePorts
->initPortBuffers(cvIn
+ pData
->cvIn
.count
, frames
, isSampleAccurate
, pData
->event
.portIn
);
1926 EngineEvent
& event(findNextEvent());
1928 if (event
.type
== kEngineEventTypeNull
)
1931 uint32_t eventTime
= event
.time
;
1932 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime
< frames
, eventTime
, frames
);
1934 if (eventTime
< timeOffset
)
1936 carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
1937 eventTime
, timeOffset
, pData
->name
);
1938 eventTime
= timeOffset
;
1941 if (isSampleAccurate
&& eventTime
> timeOffset
)
1943 if (processSingle(audioIn
, audioOut
, cvIn
, cvOut
, eventTime
- timeOffset
, timeOffset
))
1946 timeOffset
= eventTime
;
1948 if (pData
->midiprog
.current
>= 0 && pData
->midiprog
.count
> 0)
1949 nextBankId
= pData
->midiprog
.data
[pData
->midiprog
.current
].bank
;
1953 if (fMidiEventInCount
> 0)
1955 carla_zeroStructs(fMidiInEvents
, fMidiEventInCount
);
1956 fMidiEventInCount
= 0;
1959 if (fMidiEventOutCount
> 0)
1961 carla_zeroStructs(fMidiOutEvents
, fMidiEventOutCount
);
1962 fMidiEventOutCount
= 0;
1966 startTime
+= timeOffset
;
1972 case kEngineEventTypeNull
:
1975 case kEngineEventTypeControl
: {
1976 EngineControlEvent
& ctrlEvent(event
.ctrl
);
1978 switch (ctrlEvent
.type
)
1980 case kEngineControlEventTypeNull
:
1983 case kEngineControlEventTypeParameter
: {
1986 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1988 if (event
.channel
== kEngineEventNonMidiChannel
)
1990 const uint32_t k
= ctrlEvent
.param
;
1991 CARLA_SAFE_ASSERT_CONTINUE(k
< pData
->param
.count
);
1993 ctrlEvent
.handled
= true;
1994 value
= pData
->param
.getFinalUnnormalizedValue(k
, ctrlEvent
.normalizedValue
);
1995 setParameterValueRT(k
, value
, event
.time
, true);
1999 // Control backend stuff
2000 if (event
.channel
== pData
->ctrlChannel
)
2002 if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent
.param
) && (pData
->hints
& PLUGIN_CAN_DRYWET
) > 0)
2004 ctrlEvent
.handled
= true;
2005 value
= ctrlEvent
.normalizedValue
;
2006 setDryWetRT(value
, true);
2008 else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent
.param
) && (pData
->hints
& PLUGIN_CAN_VOLUME
) > 0)
2010 ctrlEvent
.handled
= true;
2011 value
= ctrlEvent
.normalizedValue
*127.0f
/100.0f
;
2012 setVolumeRT(value
, true);
2014 else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent
.param
) && (pData
->hints
& PLUGIN_CAN_BALANCE
) > 0)
2017 value
= ctrlEvent
.normalizedValue
/0.5f
- 1.0f
;
2022 right
= (value
*2.0f
)+1.0f
;
2024 else if (value
> 0.0f
)
2026 left
= (value
*2.0f
)-1.0f
;
2035 ctrlEvent
.handled
= true;
2036 setBalanceLeftRT(left
, true);
2037 setBalanceRightRT(right
, true);
2041 // Control plugin parameters
2042 for (uint32_t k
=0; k
< pData
->param
.count
; ++k
)
2044 if (pData
->param
.data
[k
].midiChannel
!= event
.channel
)
2046 if (pData
->param
.data
[k
].mappedControlIndex
!= ctrlEvent
.param
)
2048 if (pData
->param
.data
[k
].type
!= PARAMETER_INPUT
)
2050 if ((pData
->param
.data
[k
].hints
& PARAMETER_IS_AUTOMATABLE
) == 0)
2053 ctrlEvent
.handled
= true;
2054 value
= pData
->param
.getFinalUnnormalizedValue(k
, ctrlEvent
.normalizedValue
);
2055 setParameterValueRT(k
, value
, event
.time
, true);
2058 if ((pData
->options
& PLUGIN_OPTION_SEND_CONTROL_CHANGES
) != 0 && ctrlEvent
.param
< MAX_MIDI_VALUE
)
2060 if (fMidiEventInCount
>= kPluginMaxMidiEvents
)
2063 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
2064 carla_zeroStruct(nativeEvent
);
2066 nativeEvent
.time
= isSampleAccurate
? startTime
: eventTime
;
2067 nativeEvent
.data
[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE
| (event
.channel
& MIDI_CHANNEL_BIT
));
2068 nativeEvent
.data
[1] = uint8_t(ctrlEvent
.param
);
2069 nativeEvent
.data
[2] = uint8_t(ctrlEvent
.normalizedValue
*127.0f
+ 0.5f
);
2070 nativeEvent
.size
= 3;
2073 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2074 if (! ctrlEvent
.handled
)
2075 checkForMidiLearn(event
);
2078 } // case kEngineControlEventTypeParameter
2080 case kEngineControlEventTypeMidiBank
:
2081 if (pData
->options
& PLUGIN_OPTION_MAP_PROGRAM_CHANGES
)
2083 if (event
.channel
== pData
->ctrlChannel
)
2084 nextBankId
= ctrlEvent
.param
;
2086 else if (pData
->options
& PLUGIN_OPTION_SEND_PROGRAM_CHANGES
)
2088 if (fMidiEventInCount
>= kPluginMaxMidiEvents
)
2091 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
2092 carla_zeroStruct(nativeEvent
);
2094 nativeEvent
.time
= isSampleAccurate
? startTime
: eventTime
;
2095 nativeEvent
.data
[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE
| (event
.channel
& MIDI_CHANNEL_BIT
));
2096 nativeEvent
.data
[1] = MIDI_CONTROL_BANK_SELECT
;
2097 nativeEvent
.data
[2] = uint8_t(ctrlEvent
.param
);
2098 nativeEvent
.size
= 3;
2102 case kEngineControlEventTypeMidiProgram
:
2103 if (pData
->options
& PLUGIN_OPTION_MAP_PROGRAM_CHANGES
)
2105 if (event
.channel
< MAX_MIDI_CHANNELS
)
2107 const uint32_t nextProgramId(ctrlEvent
.param
);
2109 for (uint32_t k
=0; k
< pData
->midiprog
.count
; ++k
)
2111 if (pData
->midiprog
.data
[k
].bank
== nextBankId
&& pData
->midiprog
.data
[k
].program
== nextProgramId
)
2113 fDescriptor
->set_midi_program(fHandle
, event
.channel
, nextBankId
, nextProgramId
);
2115 if (fHandle2
!= nullptr)
2116 fDescriptor
->set_midi_program(fHandle2
, event
.channel
, nextBankId
, nextProgramId
);
2118 fCurMidiProgs
[event
.channel
] = static_cast<int32_t>(k
);
2120 if (event
.channel
== pData
->ctrlChannel
)
2122 pData
->postponeMidiProgramChangeRtEvent(true, k
);
2130 else if (pData
->options
& PLUGIN_OPTION_SEND_PROGRAM_CHANGES
)
2132 if (fMidiEventInCount
>= kPluginMaxMidiEvents
)
2135 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
2136 carla_zeroStruct(nativeEvent
);
2138 nativeEvent
.time
= isSampleAccurate
? startTime
: eventTime
;
2139 nativeEvent
.data
[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE
| (event
.channel
& MIDI_CHANNEL_BIT
));
2140 nativeEvent
.data
[1] = uint8_t(ctrlEvent
.param
);
2141 nativeEvent
.size
= 2;
2145 case kEngineControlEventTypeAllSoundOff
:
2146 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
2148 if (fMidiEventInCount
>= kPluginMaxMidiEvents
)
2151 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
2152 carla_zeroStruct(nativeEvent
);
2154 nativeEvent
.time
= isSampleAccurate
? startTime
: eventTime
;
2155 nativeEvent
.data
[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE
| (event
.channel
& MIDI_CHANNEL_BIT
));
2156 nativeEvent
.data
[1] = MIDI_CONTROL_ALL_SOUND_OFF
;
2157 nativeEvent
.data
[2] = 0;
2158 nativeEvent
.size
= 3;
2162 case kEngineControlEventTypeAllNotesOff
:
2163 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
2165 #ifndef BUILD_BRIDGE
2166 if (event
.channel
== pData
->ctrlChannel
&& ! allNotesOffSent
)
2168 allNotesOffSent
= true;
2169 postponeRtAllNotesOff();
2173 if (fMidiEventInCount
>= kPluginMaxMidiEvents
)
2176 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
2177 carla_zeroStruct(nativeEvent
);
2179 nativeEvent
.time
= isSampleAccurate
? startTime
: eventTime
;
2180 nativeEvent
.data
[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE
| (event
.channel
& MIDI_CHANNEL_BIT
));
2181 nativeEvent
.data
[1] = MIDI_CONTROL_ALL_NOTES_OFF
;
2182 nativeEvent
.data
[2] = 0;
2183 nativeEvent
.size
= 3;
2190 case kEngineEventTypeMidi
: {
2191 if (fMidiEventInCount
>= kPluginMaxMidiEvents
)
2194 const EngineMidiEvent
& midiEvent(event
.midi
);
2196 if (midiEvent
.size
> 4)
2198 #ifdef CARLA_PROPER_CPP11_SUPPORT
2199 static_assert(4 <= EngineMidiEvent::kDataSize
, "Incorrect data");
2202 uint8_t status
= uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent
.data
));
2204 if ((status
== MIDI_STATUS_NOTE_OFF
|| status
== MIDI_STATUS_NOTE_ON
) && (pData
->options
& PLUGIN_OPTION_SKIP_SENDING_NOTES
))
2206 if (status
== MIDI_STATUS_CHANNEL_PRESSURE
&& (pData
->options
& PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
) == 0)
2208 if (status
== MIDI_STATUS_CONTROL_CHANGE
&& (pData
->options
& PLUGIN_OPTION_SEND_CONTROL_CHANGES
) == 0)
2210 if (status
== MIDI_STATUS_POLYPHONIC_AFTERTOUCH
&& (pData
->options
& PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
) == 0)
2212 if (status
== MIDI_STATUS_PITCH_WHEEL_CONTROL
&& (pData
->options
& PLUGIN_OPTION_SEND_PITCHBEND
) == 0)
2216 if (status
== MIDI_STATUS_NOTE_ON
&& midiEvent
.data
[2] == 0)
2217 status
= MIDI_STATUS_NOTE_OFF
;
2219 NativeMidiEvent
& nativeEvent(fMidiInEvents
[fMidiEventInCount
++]);
2220 carla_zeroStruct(nativeEvent
);
2222 nativeEvent
.port
= midiEvent
.port
;
2223 nativeEvent
.time
= isSampleAccurate
? startTime
: eventTime
;
2224 nativeEvent
.size
= midiEvent
.size
;
2226 nativeEvent
.data
[0] = uint8_t(status
| (event
.channel
& MIDI_CHANNEL_BIT
));
2227 nativeEvent
.data
[1] = midiEvent
.size
>= 2 ? midiEvent
.data
[1] : 0;
2228 nativeEvent
.data
[2] = midiEvent
.size
>= 3 ? midiEvent
.data
[2] : 0;
2229 nativeEvent
.data
[3] = midiEvent
.size
== 4 ? midiEvent
.data
[3] : 0;
2231 if (status
== MIDI_STATUS_NOTE_ON
)
2233 pData
->postponeNoteOnRtEvent(true, event
.channel
, midiEvent
.data
[1], midiEvent
.data
[2]);
2235 else if (status
== MIDI_STATUS_NOTE_OFF
)
2237 pData
->postponeNoteOffRtEvent(true, event
.channel
, midiEvent
.data
[1]);
2240 } // switch (event.type)
2243 pData
->postRtEvents
.trySplice();
2245 if (frames
> timeOffset
)
2246 processSingle(audioIn
, audioOut
, cvIn
, cvOut
, frames
- timeOffset
, timeOffset
);
2248 } // End of Event Input and Processing
2250 // --------------------------------------------------------------------------------------------------------
2251 // Plugin processing (no events)
2255 processSingle(audioIn
, audioOut
, cvIn
, cvOut
, frames
, 0);
2257 } // End of Plugin processing (no events)
2259 #ifndef BUILD_BRIDGE
2260 // --------------------------------------------------------------------------------------------------------
2263 if (pData
->event
.portOut
!= nullptr)
2265 float value
, curValue
;
2267 for (uint32_t k
=0; k
< pData
->param
.count
; ++k
)
2269 if (pData
->param
.data
[k
].type
!= PARAMETER_OUTPUT
)
2272 curValue
= fDescriptor
->get_parameter_value(fHandle
, k
);
2273 pData
->param
.ranges
[k
].fixValue(curValue
);
2275 if (pData
->param
.data
[k
].mappedControlIndex
> 0)
2277 value
= pData
->param
.ranges
[k
].getNormalizedValue(curValue
);
2278 pData
->event
.portOut
->writeControlEvent(0,
2279 pData
->param
.data
[k
].midiChannel
,
2280 kEngineControlEventTypeParameter
,
2281 static_cast<uint16_t>(pData
->param
.data
[k
].mappedControlIndex
),
2286 } // End of Control Output
2290 bool processSingle(const float* const* const audioIn
, float** const audioOut
,
2291 const float* const* const cvIn
, float** const cvOut
,
2292 const uint32_t frames
, const uint32_t timeOffset
)
2294 CARLA_SAFE_ASSERT_RETURN(frames
> 0, false);
2296 if (pData
->audioIn
.count
> 0) {
2297 CARLA_SAFE_ASSERT_RETURN(audioIn
!= nullptr, false);
2299 if (pData
->audioOut
.count
> 0) {
2300 CARLA_SAFE_ASSERT_RETURN(audioOut
!= nullptr, false);
2302 if (pData
->cvIn
.count
> 0) {
2303 CARLA_SAFE_ASSERT_RETURN(cvIn
!= nullptr, false);
2305 if (pData
->cvOut
.count
> 0) {
2306 CARLA_SAFE_ASSERT_RETURN(cvOut
!= nullptr, false);
2309 // --------------------------------------------------------------------------------------------------------
2310 // Try lock, silence otherwise
2314 pData
->singleMutex
.lock();
2316 else if (! pData
->singleMutex
.tryLock())
2318 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
2320 for (uint32_t k
=0; k
< frames
; ++k
)
2321 audioOut
[i
][k
+timeOffset
] = 0.0f
;
2323 for (uint32_t i
=0; i
< pData
->cvOut
.count
; ++i
)
2325 for (uint32_t k
=0; k
< frames
; ++k
)
2326 cvOut
[i
][k
+timeOffset
] = 0.0f
;
2332 // --------------------------------------------------------------------------------------------------------
2333 // Set audio buffers
2336 for (uint32_t i
=0; i
< pData
->audioIn
.count
; ++i
)
2337 carla_copyFloats(fAudioAndCvInBuffers
[i
], audioIn
[i
]+timeOffset
, frames
);
2338 for (uint32_t i
=0; i
< pData
->cvIn
.count
; ++i
)
2339 carla_copyFloats(fAudioAndCvInBuffers
[pData
->audioIn
.count
+i
], cvIn
[i
]+timeOffset
, frames
);
2341 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
2342 carla_zeroFloats(fAudioAndCvOutBuffers
[i
], frames
);
2343 for (uint32_t i
=0; i
< pData
->cvOut
.count
; ++i
)
2344 carla_zeroFloats(fAudioAndCvOutBuffers
[pData
->audioOut
.count
+i
], frames
);
2347 // --------------------------------------------------------------------------------------------------------
2350 fIsProcessing
= true;
2352 if (fHandle2
== nullptr)
2354 fDescriptor
->process(fHandle
,
2355 fAudioAndCvInBuffers
, fAudioAndCvOutBuffers
, frames
,
2356 fMidiInEvents
, fMidiEventInCount
);
2360 fDescriptor
->process(fHandle
,
2361 (fAudioAndCvInBuffers
!= nullptr) ? &fAudioAndCvInBuffers
[0] : nullptr,
2362 (fAudioAndCvOutBuffers
!= nullptr) ? &fAudioAndCvOutBuffers
[0] : nullptr,
2363 frames
, fMidiInEvents
, fMidiEventInCount
);
2365 fDescriptor
->process(fHandle2
,
2366 (fAudioAndCvInBuffers
!= nullptr) ? &fAudioAndCvInBuffers
[1] : nullptr,
2367 (fAudioAndCvOutBuffers
!= nullptr) ? &fAudioAndCvOutBuffers
[1] : nullptr,
2368 frames
, fMidiInEvents
, fMidiEventInCount
);
2371 fIsProcessing
= false;
2373 if (fTimeInfo
.playing
)
2374 fTimeInfo
.frame
+= frames
;
2377 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2378 // --------------------------------------------------------------------------------------------------------
2379 // Post-processing (dry/wet, volume and balance)
2382 const bool doDryWet
= (pData
->hints
& PLUGIN_CAN_DRYWET
) != 0 && carla_isNotEqual(pData
->postProc
.dryWet
, 1.0f
);
2383 const bool doBalance
= (pData
->hints
& PLUGIN_CAN_BALANCE
) != 0 && ! (carla_isEqual(pData
->postProc
.balanceLeft
, -1.0f
) && carla_isEqual(pData
->postProc
.balanceRight
, 1.0f
));
2387 float* const oldBufLeft
= pData
->postProc
.extraBuffer
;
2389 for (; i
< pData
->audioOut
.count
; ++i
)
2394 for (uint32_t k
=0; k
< frames
; ++k
)
2396 bufValue
= fAudioAndCvInBuffers
[(pData
->audioIn
.count
== 1) ? 0 : i
][k
];
2397 fAudioAndCvOutBuffers
[i
][k
] = (fAudioAndCvOutBuffers
[i
][k
] * pData
->postProc
.dryWet
) + (bufValue
* (1.0f
- pData
->postProc
.dryWet
));
2404 isPair
= (i
% 2 == 0);
2408 CARLA_ASSERT(i
+1 < pData
->audioOut
.count
);
2409 carla_copyFloats(oldBufLeft
, fAudioAndCvOutBuffers
[i
], frames
);
2412 float balRangeL
= (pData
->postProc
.balanceLeft
+ 1.0f
)/2.0f
;
2413 float balRangeR
= (pData
->postProc
.balanceRight
+ 1.0f
)/2.0f
;
2415 for (uint32_t k
=0; k
< frames
; ++k
)
2420 fAudioAndCvOutBuffers
[i
][k
] = oldBufLeft
[k
] * (1.0f
- balRangeL
);
2421 fAudioAndCvOutBuffers
[i
][k
] += fAudioAndCvOutBuffers
[i
+1][k
] * (1.0f
- balRangeR
);
2426 fAudioAndCvOutBuffers
[i
][k
] = fAudioAndCvOutBuffers
[i
][k
] * balRangeR
;
2427 fAudioAndCvOutBuffers
[i
][k
] += oldBufLeft
[k
] * balRangeL
;
2432 // Volume (and buffer copy)
2434 for (uint32_t k
=0; k
< frames
; ++k
)
2435 audioOut
[i
][k
+timeOffset
] = fAudioAndCvOutBuffers
[i
][k
] * pData
->postProc
.volume
;
2439 } // End of Post-processing
2441 for (; i
< pData
->audioOut
.count
; ++i
)
2443 for (uint32_t k
=0; k
< frames
; ++k
)
2444 audioOut
[i
][k
+timeOffset
] = fAudioAndCvOutBuffers
[i
][k
];
2448 for (; i
< pData
->cvOut
.count
; ++i
)
2450 for (uint32_t k
=0; k
< frames
; ++k
)
2451 cvOut
[i
][k
+timeOffset
] = fAudioAndCvOutBuffers
[pData
->audioOut
.count
+i
][k
];
2454 // --------------------------------------------------------------------------------------------------------
2457 if (pData
->event
.portOut
!= nullptr)
2459 for (uint32_t k
= 0; k
< fMidiEventOutCount
; ++k
)
2461 const uint8_t channel
= uint8_t(MIDI_GET_CHANNEL_FROM_DATA(fMidiOutEvents
[k
].data
));
2462 const uint8_t port
= fMidiOutEvents
[k
].port
;
2464 if (fMidiOut
.count
> 1 && port
< fMidiOut
.count
)
2465 fMidiOut
.ports
[port
]->writeMidiEvent(fMidiOutEvents
[k
].time
+timeOffset
, channel
, fMidiOutEvents
[k
].size
, fMidiOutEvents
[k
].data
);
2467 pData
->event
.portOut
->writeMidiEvent(fMidiOutEvents
[k
].time
+timeOffset
, channel
, fMidiOutEvents
[k
].size
, fMidiOutEvents
[k
].data
);
2471 // --------------------------------------------------------------------------------------------------------
2473 pData
->singleMutex
.unlock();
2477 void bufferSizeChanged(const uint32_t newBufferSize
) override
2479 CARLA_ASSERT_INT(newBufferSize
> 0, newBufferSize
);
2480 carla_debug("CarlaPluginNative::bufferSizeChanged(%i)", newBufferSize
);
2482 for (uint32_t i
=0; i
< (pData
->audioIn
.count
+pData
->cvIn
.count
); ++i
)
2484 if (fAudioAndCvInBuffers
[i
] != nullptr)
2485 delete[] fAudioAndCvInBuffers
[i
];
2486 fAudioAndCvInBuffers
[i
] = new float[newBufferSize
];
2489 for (uint32_t i
=0; i
< (pData
->audioOut
.count
+pData
->cvOut
.count
); ++i
)
2491 if (fAudioAndCvOutBuffers
[i
] != nullptr)
2492 delete[] fAudioAndCvOutBuffers
[i
];
2493 fAudioAndCvOutBuffers
[i
] = new float[newBufferSize
];
2496 if (fCurBufferSize
!= newBufferSize
)
2498 fCurBufferSize
= newBufferSize
;
2500 if (fDescriptor
!= nullptr && fDescriptor
->dispatcher
!= nullptr)
2502 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED
, 0, static_cast<intptr_t>(newBufferSize
), nullptr, 0.0f
);
2504 if (fHandle2
!= nullptr)
2505 fDescriptor
->dispatcher(fHandle2
, NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED
, 0, static_cast<intptr_t>(newBufferSize
), nullptr, 0.0f
);
2509 CarlaPlugin::bufferSizeChanged(newBufferSize
);
2512 void sampleRateChanged(const double newSampleRate
) override
2514 CARLA_ASSERT_INT(newSampleRate
> 0.0, newSampleRate
);
2515 carla_debug("CarlaPluginNative::sampleRateChanged(%g)", newSampleRate
);
2517 if (carla_isEqual(fCurSampleRate
, newSampleRate
))
2520 fCurSampleRate
= newSampleRate
;
2522 if (fDescriptor
!= nullptr && fDescriptor
->dispatcher
!= nullptr)
2524 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED
, 0, 0, nullptr, float(newSampleRate
));
2526 if (fHandle2
!= nullptr)
2527 fDescriptor
->dispatcher(fHandle2
, NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED
, 0, 0, nullptr, float(newSampleRate
));
2531 void offlineModeChanged(const bool isOffline
) override
2533 if (fIsOffline
== isOffline
)
2536 fIsOffline
= isOffline
;
2538 if (fDescriptor
!= nullptr && fDescriptor
->dispatcher
!= nullptr)
2540 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED
, 0, isOffline
? 1 : 0, nullptr, 0.0f
);
2542 if (fHandle2
!= nullptr)
2543 fDescriptor
->dispatcher(fHandle2
, NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED
, 0, isOffline
? 1 : 0, nullptr, 0.0f
);
2547 // -------------------------------------------------------------------
2550 void initBuffers() const noexcept override
2552 CarlaPlugin::initBuffers();
2554 fMidiIn
.initBuffers(pData
->event
.portIn
);
2555 fMidiOut
.initBuffers();
2558 void clearBuffers() noexcept override
2560 carla_debug("CarlaPluginNative::clearBuffers() - start");
2562 if (fAudioAndCvInBuffers
!= nullptr)
2564 for (uint32_t i
=0; i
< (pData
->audioIn
.count
+pData
->cvIn
.count
); ++i
)
2566 if (fAudioAndCvInBuffers
[i
] != nullptr)
2568 delete[] fAudioAndCvInBuffers
[i
];
2569 fAudioAndCvInBuffers
[i
] = nullptr;
2573 delete[] fAudioAndCvInBuffers
;
2574 fAudioAndCvInBuffers
= nullptr;
2577 if (fAudioAndCvOutBuffers
!= nullptr)
2579 for (uint32_t i
=0; i
< (pData
->audioOut
.count
+pData
->cvOut
.count
); ++i
)
2581 if (fAudioAndCvOutBuffers
[i
] != nullptr)
2583 delete[] fAudioAndCvOutBuffers
[i
];
2584 fAudioAndCvOutBuffers
[i
] = nullptr;
2588 delete[] fAudioAndCvOutBuffers
;
2589 fAudioAndCvOutBuffers
= nullptr;
2592 if (fMidiIn
.count
> 1)
2593 pData
->event
.portIn
= nullptr;
2595 if (fMidiOut
.count
> 1)
2596 pData
->event
.portOut
= nullptr;
2601 CarlaPlugin::clearBuffers();
2603 carla_debug("CarlaPluginNative::clearBuffers() - end");
2606 // -------------------------------------------------------------------
2607 // Post-poned UI Stuff
2609 void uiParameterChange(const uint32_t index
, const float value
) noexcept override
2611 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
2612 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
2613 CARLA_SAFE_ASSERT_RETURN(index
< pData
->param
.count
,);
2618 if (fDescriptor
->ui_set_parameter_value
!= nullptr)
2619 fDescriptor
->ui_set_parameter_value(fHandle
, index
, value
);
2622 void uiMidiProgramChange(const uint32_t index
) noexcept override
2624 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
2625 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
2626 CARLA_SAFE_ASSERT_RETURN(index
< pData
->midiprog
.count
,);
2630 if (index
>= pData
->midiprog
.count
)
2633 if (fDescriptor
->ui_set_midi_program
!= nullptr)
2634 fDescriptor
->ui_set_midi_program(fHandle
, 0, pData
->midiprog
.data
[index
].bank
, pData
->midiprog
.data
[index
].program
);
2637 void uiNoteOn(const uint8_t channel
, const uint8_t note
, const uint8_t velo
) noexcept override
2639 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
2640 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
2641 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
2642 CARLA_SAFE_ASSERT_RETURN(note
< MAX_MIDI_NOTE
,);
2643 CARLA_SAFE_ASSERT_RETURN(velo
> 0 && velo
< MAX_MIDI_VALUE
,);
2648 if (fDescriptor
->dispatcher
!= nullptr)
2651 uint8_t(MIDI_STATUS_NOTE_ON
| (channel
& MIDI_CHANNEL_BIT
)),
2655 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_UI_MIDI_EVENT
,
2662 void uiNoteOff(const uint8_t channel
, const uint8_t note
) noexcept override
2664 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
2665 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
2666 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
,);
2667 CARLA_SAFE_ASSERT_RETURN(note
< MAX_MIDI_NOTE
,);
2671 if (fDescriptor
== nullptr || fHandle
== nullptr)
2674 if (fDescriptor
->dispatcher
!= nullptr)
2677 uint8_t(MIDI_STATUS_NOTE_OFF
| (channel
& MIDI_CHANNEL_BIT
)),
2681 fDescriptor
->dispatcher(fHandle
, NATIVE_PLUGIN_OPCODE_UI_MIDI_EVENT
,
2688 // -------------------------------------------------------------------
2690 const NativeInlineDisplayImageSurface
* renderInlineDisplay(const uint32_t width
, const uint32_t height
) const
2692 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->hints
& NATIVE_PLUGIN_HAS_INLINE_DISPLAY
, nullptr);
2693 CARLA_SAFE_ASSERT_RETURN(fDescriptor
->render_inline_display
, nullptr);
2694 CARLA_SAFE_ASSERT_RETURN(width
> 0, nullptr);
2695 CARLA_SAFE_ASSERT_RETURN(height
> 0, nullptr);
2697 return fDescriptor
->render_inline_display(fHandle
, width
, height
);
2700 // -------------------------------------------------------------------
2703 const NativeTimeInfo
* handleGetTimeInfo() const noexcept
2705 CARLA_SAFE_ASSERT_RETURN(fIsProcessing
, nullptr);
2710 bool handleWriteMidiEvent(const NativeMidiEvent
* const event
)
2712 CARLA_SAFE_ASSERT_RETURN(pData
->enabled
, false);
2713 CARLA_SAFE_ASSERT_RETURN(fIsProcessing
, false);
2714 CARLA_SAFE_ASSERT_RETURN(fMidiOut
.count
> 0 || pData
->event
.portOut
!= nullptr, false);
2715 CARLA_SAFE_ASSERT_RETURN(event
!= nullptr, false);
2716 CARLA_SAFE_ASSERT_RETURN(event
->data
[0] != 0, false);
2718 if (fMidiEventOutCount
== kPluginMaxMidiEvents
)
2720 carla_stdout("CarlaPluginNative::handleWriteMidiEvent(%p) - buffer full", event
);
2724 std::memcpy(&fMidiOutEvents
[fMidiEventOutCount
++], event
, sizeof(NativeMidiEvent
));
2728 void handleUiParameterChanged(const uint32_t index
, const float value
)
2730 setParameterValue(index
, value
, false, true, true);
2733 void handleUiCustomDataChanged(const char* const key
, const char* const value
)
2735 setCustomData(CUSTOM_DATA_TYPE_STRING
, key
, value
, false);
2738 void handleUiClosed()
2740 pData
->engine
->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED
, pData
->id
, 0, 0, 0, 0.0f
, nullptr);
2741 fIsUiVisible
= false;
2744 const char* handleUiOpenFile(const bool isDir
, const char* const title
, const char* const filter
)
2746 return pData
->engine
->runFileCallback(FILE_CALLBACK_OPEN
, isDir
, title
, filter
);
2749 const char* handleUiSaveFile(const bool isDir
, const char* const title
, const char* const filter
)
2751 return pData
->engine
->runFileCallback(FILE_CALLBACK_SAVE
, isDir
, title
, filter
);
2754 intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode
,
2755 const int32_t index
, const intptr_t value
, void* const ptr
, const float opt
)
2758 if (opcode
!= NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY
&& opcode
!= NATIVE_HOST_OPCODE_REQUEST_IDLE
) {
2759 carla_debug("CarlaPluginNative::handleDispatcher(%i, %i, " P_INTPTR
", %p, %f)",
2760 opcode
, index
, value
, ptr
, static_cast<double>(opt
));
2766 case NATIVE_HOST_OPCODE_NULL
:
2769 case NATIVE_HOST_OPCODE_UPDATE_PARAMETER
:
2771 pData
->engine
->callback(true, true, ENGINE_CALLBACK_UPDATE
, pData
->id
, -1, 0, 0, 0.0f
, nullptr);
2774 case NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM
:
2776 pData
->engine
->callback(true, true, ENGINE_CALLBACK_UPDATE
, pData
->id
, -1, 0, 0, 0.0f
, nullptr);
2779 case NATIVE_HOST_OPCODE_RELOAD_PARAMETERS
:
2780 reloadParameters(nullptr, nullptr);
2781 pData
->engine
->callback(true, true, ENGINE_CALLBACK_RELOAD_PARAMETERS
, pData
->id
, -1, 0, 0, 0.0f
, nullptr);
2784 case NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS
:
2785 reloadPrograms(false);
2786 pData
->engine
->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS
, pData
->id
, -1, 0, 0, 0.0f
, nullptr);
2789 case NATIVE_HOST_OPCODE_RELOAD_ALL
:
2791 pData
->engine
->callback(true, true, ENGINE_CALLBACK_RELOAD_ALL
, pData
->id
, -1, 0, 0, 0.0f
, nullptr);
2794 case NATIVE_HOST_OPCODE_UI_UNAVAILABLE
:
2795 pData
->engine
->callback(true, true, ENGINE_CALLBACK_UI_STATE_CHANGED
, pData
->id
, -1, 0, 0, 0.0f
, nullptr);
2796 fIsUiAvailable
= false;
2799 case NATIVE_HOST_OPCODE_HOST_IDLE
:
2800 pData
->engine
->callback(true, false, ENGINE_CALLBACK_IDLE
, 0, 0, 0, 0, 0.0f
, nullptr);
2803 case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN
:
2806 case NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY
:
2807 switch (pData
->engine
->getProccessMode())
2809 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
:
2810 case ENGINE_PROCESS_MODE_PATCHBAY
:
2811 fInlineDisplayNeedsRedraw
= true;
2818 case NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER
:
2819 CARLA_SAFE_ASSERT_RETURN(index
>= 0, 0);
2820 pData
->engine
->touchPluginParameter(pData
->id
, static_cast<uint32_t>(index
), value
!= 0);
2823 case NATIVE_HOST_OPCODE_REQUEST_IDLE
:
2827 case NATIVE_HOST_OPCODE_GET_FILE_PATH
:
2828 CARLA_SAFE_ASSERT_RETURN(ptr
!= nullptr, 0);
2830 const EngineOptions
& opts(pData
->engine
->getOptions());
2831 const char* const filetype
= (const char*)ptr
;
2832 const char* ret
= nullptr;
2834 if (std::strcmp(filetype
, "carla") == 0)
2836 ret
= pData
->engine
->getCurrentProjectFilename();
2838 if (fLastProjectFilename
!= ret
)
2840 fLastProjectFilename
= ret
;
2843 const size_t r
= fLastProjectFilename
.rfind(CARLA_OS_SEP
, &found
);
2846 fLastProjectFolder
= ret
;
2847 fLastProjectFolder
[r
] = '\0';
2851 fLastProjectFolder
.clear();
2855 ret
= fLastProjectFolder
.buffer();
2858 else if (std::strcmp(filetype
, "audio") == 0)
2859 ret
= opts
.pathAudio
;
2860 else if (std::strcmp(filetype
, "midi") == 0)
2861 ret
= opts
.pathMIDI
;
2863 return static_cast<intptr_t>((uintptr_t)ret
);
2867 case NATIVE_HOST_OPCODE_UI_RESIZE
:
2868 case NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA
:
2879 // -------------------------------------------------------------------
2882 void* getNativeHandle() const noexcept override
2887 const void* getNativeDescriptor() const noexcept override
2892 // -------------------------------------------------------------------
2894 bool init(const CarlaPluginPtr plugin
,
2895 const char* const name
, const char* const label
, const uint options
)
2897 CARLA_SAFE_ASSERT_RETURN(pData
->engine
!= nullptr, false);
2899 // ---------------------------------------------------------------
2902 if (pData
->client
!= nullptr)
2904 pData
->engine
->setLastError("Plugin client is already registered");
2908 if (label
== nullptr || label
[0] == '\0')
2910 pData
->engine
->setLastError("null label");
2914 // ---------------------------------------------------------------
2915 // get descriptor that matches label
2917 sPluginInitializer
.initIfNeeded();
2919 for (LinkedList
<const NativePluginDescriptor
*>::Itenerator it
= gPluginDescriptors
.begin2(); it
.valid(); it
.next())
2921 fDescriptor
= it
.getValue(nullptr);
2922 CARLA_SAFE_ASSERT_BREAK(fDescriptor
!= nullptr);
2924 carla_debug("Check vs \"%s\"", fDescriptor
->label
);
2926 if (fDescriptor
->label
!= nullptr && std::strcmp(fDescriptor
->label
, label
) == 0)
2929 fDescriptor
= nullptr;
2932 if (fDescriptor
== nullptr)
2934 pData
->engine
->setLastError("Invalid internal plugin");
2938 // ---------------------------------------------------------------
2941 /**/ if (std::strcmp(fDescriptor
->label
, "audiofile") == 0)
2942 pData
->iconName
= carla_strdup_safe("file");
2943 else if (std::strcmp(fDescriptor
->label
, "midifile") == 0)
2944 pData
->iconName
= carla_strdup_safe("file");
2946 else if (std::strcmp(fDescriptor
->label
, "3bandeq") == 0)
2947 pData
->iconName
= carla_strdup_safe("distrho");
2948 else if (std::strcmp(fDescriptor
->label
, "3bandsplitter") == 0)
2949 pData
->iconName
= carla_strdup_safe("distrho");
2950 else if (std::strcmp(fDescriptor
->label
, "kars") == 0)
2951 pData
->iconName
= carla_strdup_safe("distrho");
2952 else if (std::strcmp(fDescriptor
->label
, "nekobi") == 0)
2953 pData
->iconName
= carla_strdup_safe("distrho");
2954 else if (std::strcmp(fDescriptor
->label
, "pingpongpan") == 0)
2955 pData
->iconName
= carla_strdup_safe("distrho");
2957 // ---------------------------------------------------------------
2960 if (name
!= nullptr && name
[0] != '\0')
2961 pData
->name
= pData
->engine
->getUniquePluginName(name
);
2962 else if (fDescriptor
->name
!= nullptr && fDescriptor
->name
[0] != '\0')
2963 pData
->name
= pData
->engine
->getUniquePluginName(fDescriptor
->name
);
2965 pData
->name
= pData
->engine
->getUniquePluginName(label
);
2968 CARLA_ASSERT(fHost
.uiName
== nullptr);
2972 if (pData
->uiTitle
.isNotEmpty())
2974 uiName
= pData
->uiTitle
;
2978 uiName
= pData
->name
;
2982 fHost
.uiName
= uiName
.releaseBufferPointer();
2985 // ---------------------------------------------------------------
2988 pData
->client
= pData
->engine
->addClient(plugin
);
2990 if (pData
->client
== nullptr || ! pData
->client
->isOk())
2992 pData
->engine
->setLastError("Failed to register plugin client");
2996 // ---------------------------------------------------------------
2997 // initialize plugin
2999 fHandle
= fDescriptor
->instantiate(&fHost
);
3001 if (fHandle
== nullptr)
3003 pData
->engine
->setLastError("Plugin failed to initialize");
3007 // ---------------------------------------------------------------
3010 bool hasMidiProgs
= false;
3012 if (fDescriptor
->get_midi_program_count
!= nullptr)
3015 hasMidiProgs
= fDescriptor
->get_midi_program_count(fHandle
) > 0;
3019 pData
->options
= 0x0;
3021 if (fDescriptor
->hints
& NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
)
3022 pData
->options
|= PLUGIN_OPTION_FIXED_BUFFERS
;
3023 else if (options
& PLUGIN_OPTION_FIXED_BUFFERS
)
3024 pData
->options
|= PLUGIN_OPTION_FIXED_BUFFERS
;
3026 if (pData
->engine
->getOptions().forceStereo
)
3027 pData
->options
|= PLUGIN_OPTION_FORCE_STEREO
;
3028 else if (options
& PLUGIN_OPTION_FORCE_STEREO
)
3029 pData
->options
|= PLUGIN_OPTION_FORCE_STEREO
;
3031 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES
)
3032 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_CONTROL_CHANGES
))
3033 pData
->options
|= PLUGIN_OPTION_SEND_CONTROL_CHANGES
;
3035 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_CHANNEL_PRESSURE
)
3036 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
))
3037 pData
->options
|= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
;
3039 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_NOTE_AFTERTOUCH
)
3040 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
))
3041 pData
->options
|= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
;
3043 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_PITCHBEND
)
3044 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_PITCHBEND
))
3045 pData
->options
|= PLUGIN_OPTION_SEND_PITCHBEND
;
3047 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF
)
3048 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_ALL_SOUND_OFF
))
3049 pData
->options
|= PLUGIN_OPTION_SEND_ALL_SOUND_OFF
;
3051 if (fDescriptor
->midiIns
> 0)
3052 if (isPluginOptionInverseEnabled(options
, PLUGIN_OPTION_SKIP_SENDING_NOTES
))
3053 pData
->options
|= PLUGIN_OPTION_SKIP_SENDING_NOTES
;
3055 if (fDescriptor
->supports
& NATIVE_PLUGIN_SUPPORTS_PROGRAM_CHANGES
)
3057 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_PROGRAM_CHANGES
))
3058 pData
->options
|= PLUGIN_OPTION_SEND_PROGRAM_CHANGES
;
3060 // makes no sense for a plugin to set program changes supported, but it has no midi programs
3061 CARLA_SAFE_ASSERT(! hasMidiProgs
);
3063 else if (hasMidiProgs
)
3065 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_MAP_PROGRAM_CHANGES
))
3066 pData
->options
|= PLUGIN_OPTION_MAP_PROGRAM_CHANGES
;
3074 NativePluginHandle fHandle
;
3075 NativePluginHandle fHandle2
;
3076 NativeHostDescriptor fHost
;
3077 const NativePluginDescriptor
* fDescriptor
;
3081 bool fIsUiAvailable
;
3083 volatile bool fNeedsIdle
;
3085 bool fInlineDisplayNeedsRedraw
;
3086 int64_t fInlineDisplayLastRedrawTime
;
3088 CarlaString fLastProjectFilename
;
3089 CarlaString fLastProjectFolder
;
3091 float** fAudioAndCvInBuffers
;
3092 float** fAudioAndCvOutBuffers
;
3093 uint32_t fMidiEventInCount
;
3094 uint32_t fMidiEventOutCount
;
3095 NativeMidiEvent fMidiInEvents
[kPluginMaxMidiEvents
];
3096 NativeMidiEvent fMidiOutEvents
[kPluginMaxMidiEvents
];
3098 int32_t fCurMidiProgs
[MAX_MIDI_CHANNELS
];
3099 uint32_t fCurBufferSize
;
3100 double fCurSampleRate
;
3102 NativePluginMidiInData fMidiIn
;
3103 NativePluginMidiOutData fMidiOut
;
3105 NativeTimeInfo fTimeInfo
;
3107 // -------------------------------------------------------------------
3109 #define handlePtr ((CarlaPluginNative*)handle)
3111 static uint32_t carla_host_get_buffer_size(NativeHostHandle handle
) noexcept
3113 return handlePtr
->fCurBufferSize
;
3116 static double carla_host_get_sample_rate(NativeHostHandle handle
) noexcept
3118 return handlePtr
->fCurSampleRate
;
3121 static bool carla_host_is_offline(NativeHostHandle handle
) noexcept
3123 return handlePtr
->fIsOffline
;
3126 static const NativeTimeInfo
* carla_host_get_time_info(NativeHostHandle handle
) noexcept
3128 return handlePtr
->handleGetTimeInfo();
3131 static bool carla_host_write_midi_event(NativeHostHandle handle
, const NativeMidiEvent
* event
)
3133 return handlePtr
->handleWriteMidiEvent(event
);
3136 static void carla_host_ui_parameter_changed(NativeHostHandle handle
, uint32_t index
, float value
)
3138 handlePtr
->handleUiParameterChanged(index
, value
);
3141 static void carla_host_ui_custom_data_changed(NativeHostHandle handle
, const char* key
, const char* value
)
3143 handlePtr
->handleUiCustomDataChanged(key
, value
);
3146 static void carla_host_ui_closed(NativeHostHandle handle
)
3148 handlePtr
->handleUiClosed();
3151 static const char* carla_host_ui_open_file(NativeHostHandle handle
, bool isDir
, const char* title
, const char* filter
)
3153 return handlePtr
->handleUiOpenFile(isDir
, title
, filter
);
3156 static const char* carla_host_ui_save_file(NativeHostHandle handle
, bool isDir
, const char* title
, const char* filter
)
3158 return handlePtr
->handleUiSaveFile(isDir
, title
, filter
);
3161 static intptr_t carla_host_dispatcher(NativeHostHandle handle
, NativeHostDispatcherOpcode opcode
, int32_t index
, intptr_t value
, void* ptr
, float opt
)
3163 return handlePtr
->handleDispatcher(opcode
, index
, value
, ptr
, opt
);
3168 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginNative
)
3171 // -----------------------------------------------------------------------
3173 CarlaPluginPtr
CarlaPlugin::newNative(const Initializer
& init
)
3175 carla_debug("CarlaPlugin::newNative({%p, \"%s\", \"%s\", \"%s\", " P_INT64
"})",
3176 init
.engine
, init
.filename
, init
.name
, init
.label
, init
.uniqueId
);
3178 std::shared_ptr
<CarlaPluginNative
> plugin(new CarlaPluginNative(init
.engine
, init
.id
));
3180 if (! plugin
->init(plugin
, init
.name
, init
.label
, init
.options
))
3186 // used in CarlaStandalone.cpp
3187 const void* carla_render_inline_display_internal(const CarlaPluginPtr
& plugin
, uint32_t width
, uint32_t height
);
3189 const void* carla_render_inline_display_internal(const CarlaPluginPtr
& plugin
, uint32_t width
, uint32_t height
)
3191 const std::shared_ptr
<CarlaPluginNative
>& nativePlugin((const std::shared_ptr
<CarlaPluginNative
>&)plugin
);
3193 return nativePlugin
->renderInlineDisplay(width
, height
);
3196 // -----------------------------------------------------------------------
3198 CARLA_BACKEND_END_NAMESPACE