Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NativePlugin.cpp 88KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496
  1. /*
  2. * Carla Native Plugin
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  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.
  9. *
  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.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #include "CarlaEngine.hpp"
  19. #include "CarlaMathUtils.hpp"
  20. #include "CarlaNative.h"
  21. #include "juce_core.h"
  22. using juce::String;
  23. using juce::StringArray;
  24. // -----------------------------------------------------
  25. static LinkedList<const NativePluginDescriptor*> gPluginDescriptors;
  26. void carla_register_native_plugin(const NativePluginDescriptor* desc)
  27. {
  28. gPluginDescriptors.append(desc);
  29. }
  30. // -----------------------------------------------------
  31. CARLA_BACKEND_START_NAMESPACE
  32. // -----------------------------------------------------
  33. struct NativePluginMidiData {
  34. uint32_t count;
  35. uint32_t* indexes;
  36. CarlaEngineEventPort** ports;
  37. NativePluginMidiData() noexcept
  38. : count(0),
  39. indexes(nullptr),
  40. ports(nullptr) {}
  41. ~NativePluginMidiData() noexcept
  42. {
  43. CARLA_SAFE_ASSERT_INT(count == 0, count);
  44. CARLA_SAFE_ASSERT(indexes == nullptr);
  45. CARLA_SAFE_ASSERT(ports == nullptr);
  46. }
  47. void createNew(const uint32_t newCount)
  48. {
  49. CARLA_SAFE_ASSERT_INT(count == 0, count);
  50. CARLA_SAFE_ASSERT_RETURN(indexes == nullptr,);
  51. CARLA_SAFE_ASSERT_RETURN(ports == nullptr,);
  52. CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
  53. indexes = new uint32_t[newCount];
  54. ports = new CarlaEngineEventPort*[newCount];
  55. count = newCount;
  56. for (uint32_t i=0; i < newCount; ++i)
  57. indexes[i] = 0;
  58. for (uint32_t i=0; i < newCount; ++i)
  59. ports[i] = nullptr;
  60. }
  61. void clear() noexcept
  62. {
  63. if (ports != nullptr)
  64. {
  65. for (uint32_t i=0; i < count; ++i)
  66. {
  67. if (ports[i] != nullptr)
  68. {
  69. delete ports[i];
  70. ports[i] = nullptr;
  71. }
  72. }
  73. delete[] ports;
  74. ports = nullptr;
  75. }
  76. if (indexes != nullptr)
  77. {
  78. delete[] indexes;
  79. indexes = nullptr;
  80. }
  81. count = 0;
  82. }
  83. void initBuffers() const noexcept
  84. {
  85. for (uint32_t i=0; i < count; ++i)
  86. {
  87. if (ports[i] != nullptr)
  88. ports[i]->initBuffer();
  89. }
  90. }
  91. CARLA_DECLARE_NON_COPY_STRUCT(NativePluginMidiData)
  92. };
  93. // -----------------------------------------------------
  94. static const
  95. struct ScopedInitializer {
  96. ScopedInitializer()
  97. {
  98. carla_register_all_plugins();
  99. }
  100. ~ScopedInitializer()
  101. {
  102. gPluginDescriptors.clear();
  103. }
  104. } _si;
  105. // -----------------------------------------------------
  106. class NativePlugin : public CarlaPlugin
  107. {
  108. public:
  109. NativePlugin(CarlaEngine* const engine, const uint id)
  110. : CarlaPlugin(engine, id),
  111. fHandle(nullptr),
  112. fHandle2(nullptr),
  113. fHost(),
  114. fDescriptor(nullptr),
  115. fIsProcessing(false),
  116. fIsUiVisible(false),
  117. fAudioInBuffers(nullptr),
  118. fAudioOutBuffers(nullptr),
  119. fMidiEventCount(0),
  120. fMidiIn(),
  121. fMidiOut(),
  122. fTimeInfo(),
  123. leakDetector_NativePlugin()
  124. {
  125. carla_debug("NativePlugin::NativePlugin(%p, %i)", engine, id);
  126. carla_fill<int32_t>(fCurMidiProgs, 0, MAX_MIDI_CHANNELS);
  127. carla_zeroStruct<NativeMidiEvent>(fMidiEvents, kPluginMaxMidiEvents*2);
  128. carla_zeroStruct<NativeTimeInfo>(fTimeInfo);
  129. fHost.handle = this;
  130. fHost.resourceDir = carla_strdup(engine->getOptions().resourceDir);
  131. fHost.uiName = nullptr;
  132. fHost.uiParentId = engine->getOptions().frontendWinId;
  133. fHost.get_buffer_size = carla_host_get_buffer_size;
  134. fHost.get_sample_rate = carla_host_get_sample_rate;
  135. fHost.is_offline = carla_host_is_offline;
  136. fHost.get_time_info = carla_host_get_time_info;
  137. fHost.write_midi_event = carla_host_write_midi_event;
  138. fHost.ui_parameter_changed = carla_host_ui_parameter_changed;
  139. fHost.ui_custom_data_changed = carla_host_ui_custom_data_changed;
  140. fHost.ui_closed = carla_host_ui_closed;
  141. fHost.ui_open_file = carla_host_ui_open_file;
  142. fHost.ui_save_file = carla_host_ui_save_file;
  143. fHost.dispatcher = carla_host_dispatcher;
  144. }
  145. ~NativePlugin() override
  146. {
  147. carla_debug("NativePlugin::~NativePlugin()");
  148. // close UI
  149. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  150. {
  151. if (fIsUiVisible && fDescriptor != nullptr && fDescriptor->ui_show != nullptr && fHandle != nullptr)
  152. fDescriptor->ui_show(fHandle, false);
  153. pData->transientTryCounter = 0;
  154. }
  155. pData->singleMutex.lock();
  156. pData->masterMutex.lock();
  157. if (pData->client != nullptr && pData->client->isActive())
  158. pData->client->deactivate();
  159. CARLA_ASSERT(! fIsProcessing);
  160. if (pData->active)
  161. {
  162. deactivate();
  163. pData->active = false;
  164. }
  165. if (fDescriptor != nullptr)
  166. {
  167. if (fDescriptor->cleanup != nullptr)
  168. {
  169. if (fHandle != nullptr)
  170. fDescriptor->cleanup(fHandle);
  171. if (fHandle2 != nullptr)
  172. fDescriptor->cleanup(fHandle2);
  173. }
  174. fHandle = nullptr;
  175. fHandle2 = nullptr;
  176. fDescriptor = nullptr;
  177. }
  178. if (fHost.resourceDir != nullptr)
  179. {
  180. delete[] fHost.resourceDir;
  181. fHost.resourceDir = nullptr;
  182. }
  183. if (fHost.uiName != nullptr)
  184. {
  185. delete[] fHost.uiName;
  186. fHost.uiName = nullptr;
  187. }
  188. clearBuffers();
  189. }
  190. // -------------------------------------------------------------------
  191. // Information (base)
  192. PluginType getType() const noexcept override
  193. {
  194. return PLUGIN_INTERNAL;
  195. }
  196. PluginCategory getCategory() const noexcept override
  197. {
  198. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, PLUGIN_CATEGORY_NONE);
  199. return static_cast<PluginCategory>(fDescriptor->category);
  200. }
  201. // -------------------------------------------------------------------
  202. // Information (count)
  203. uint32_t getMidiInCount() const noexcept override
  204. {
  205. return fMidiIn.count;
  206. }
  207. uint32_t getMidiOutCount() const noexcept override
  208. {
  209. return fMidiOut.count;
  210. }
  211. uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
  212. {
  213. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0);
  214. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, 0);
  215. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0);
  216. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
  217. // FIXME - try
  218. if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  219. return param->scalePointCount;
  220. carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__);
  221. return 0;
  222. }
  223. // -------------------------------------------------------------------
  224. // Information (current data)
  225. // nothing
  226. // -------------------------------------------------------------------
  227. // Information (per-plugin data)
  228. uint getOptionsAvailable() const noexcept override
  229. {
  230. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0x0);
  231. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0);
  232. // FIXME - try
  233. const bool hasMidiProgs(fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_count(fHandle) > 0);
  234. uint options = 0x0;
  235. if (hasMidiProgs && (fDescriptor->supports & ::PLUGIN_SUPPORTS_PROGRAM_CHANGES) == 0)
  236. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  237. if (getMidiInCount() == 0 && (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS) == 0)
  238. options |= PLUGIN_OPTION_FIXED_BUFFERS;
  239. if (pData->engine->getProccessMode() != ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  240. {
  241. if (pData->options & PLUGIN_OPTION_FORCE_STEREO)
  242. options |= PLUGIN_OPTION_FORCE_STEREO;
  243. else if (pData->audioIn.count <= 1 && pData->audioOut.count <= 1 && (pData->audioIn.count != 0 || pData->audioOut.count != 0))
  244. options |= PLUGIN_OPTION_FORCE_STEREO;
  245. }
  246. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_CONTROL_CHANGES)
  247. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  248. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_CHANNEL_PRESSURE)
  249. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  250. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_NOTE_AFTERTOUCH)
  251. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  252. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_PITCHBEND)
  253. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  254. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_ALL_SOUND_OFF)
  255. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  256. return options;
  257. }
  258. float getParameterValue(const uint32_t parameterId) const noexcept override
  259. {
  260. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0.0f);
  261. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_value != nullptr, 0.0f);
  262. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0.0f);
  263. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  264. // FIXME - try
  265. return fDescriptor->get_parameter_value(fHandle, parameterId);
  266. }
  267. float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
  268. {
  269. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr, 0.0f);
  270. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr, 0.0f);
  271. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, 0.0f);
  272. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
  273. // FIXME - try
  274. if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  275. {
  276. CARLA_SAFE_ASSERT_RETURN(scalePointId < param->scalePointCount, 0.0f);
  277. const NativeParameterScalePoint* scalePoint(&param->scalePoints[scalePointId]);
  278. return scalePoint->value;
  279. }
  280. carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__);
  281. return 0.0f;
  282. }
  283. void getLabel(char* const strBuf) const noexcept override
  284. {
  285. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  286. if (fDescriptor->label != nullptr)
  287. {
  288. std::strncpy(strBuf, fDescriptor->label, STR_MAX);
  289. return;
  290. }
  291. CarlaPlugin::getLabel(strBuf);
  292. }
  293. void getMaker(char* const strBuf) const noexcept override
  294. {
  295. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  296. if (fDescriptor->maker != nullptr)
  297. {
  298. std::strncpy(strBuf, fDescriptor->maker, STR_MAX);
  299. return;
  300. }
  301. CarlaPlugin::getMaker(strBuf);
  302. }
  303. void getCopyright(char* const strBuf) const noexcept override
  304. {
  305. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  306. if (fDescriptor->copyright != nullptr)
  307. {
  308. std::strncpy(strBuf, fDescriptor->copyright, STR_MAX);
  309. return;
  310. }
  311. CarlaPlugin::getCopyright(strBuf);
  312. }
  313. void getRealName(char* const strBuf) const noexcept override
  314. {
  315. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  316. if (fDescriptor->name != nullptr)
  317. {
  318. std::strncpy(strBuf, fDescriptor->name, STR_MAX);
  319. return;
  320. }
  321. CarlaPlugin::getRealName(strBuf);
  322. }
  323. void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
  324. {
  325. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  326. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr,);
  327. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  328. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  329. // FIXME - try
  330. if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  331. {
  332. if (param->name != nullptr)
  333. {
  334. std::strncpy(strBuf, param->name, STR_MAX);
  335. return;
  336. }
  337. carla_safe_assert("param->name != nullptr", __FILE__, __LINE__);
  338. return CarlaPlugin::getParameterName(parameterId, strBuf);
  339. }
  340. carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__);
  341. CarlaPlugin::getParameterName(parameterId, strBuf);
  342. }
  343. void getParameterText(const uint32_t parameterId, char* const strBuf) const noexcept override
  344. {
  345. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  346. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_text != nullptr,);
  347. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_value != nullptr,);
  348. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  349. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  350. // FIXME - try
  351. if (const char* const text = fDescriptor->get_parameter_text(fHandle, parameterId /*, fDescriptor->get_parameter_value(fHandle, parameterId)*/))
  352. {
  353. std::strncpy(strBuf, text, STR_MAX);
  354. return;
  355. }
  356. carla_safe_assert("const char* const text = fDescriptor->get_parameter_text(fHandle, parameterId, value)", __FILE__, __LINE__);
  357. CarlaPlugin::getParameterText(parameterId, strBuf);
  358. }
  359. void getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
  360. {
  361. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  362. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr,);
  363. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  364. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  365. // FIXME - try
  366. if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  367. {
  368. if (param->unit != nullptr)
  369. {
  370. std::strncpy(strBuf, param->unit, STR_MAX);
  371. return;
  372. }
  373. return CarlaPlugin::getParameterUnit(parameterId, strBuf);
  374. }
  375. carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__);
  376. CarlaPlugin::getParameterUnit(parameterId, strBuf);
  377. }
  378. void getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
  379. {
  380. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  381. CARLA_SAFE_ASSERT_RETURN(fDescriptor->get_parameter_info != nullptr,);
  382. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  383. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  384. // FIXME - try
  385. if (const NativeParameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId))
  386. {
  387. CARLA_SAFE_ASSERT_RETURN(scalePointId < param->scalePointCount,);
  388. const NativeParameterScalePoint* scalePoint(&param->scalePoints[scalePointId]);
  389. if (scalePoint->label != nullptr)
  390. {
  391. std::strncpy(strBuf, scalePoint->label, STR_MAX);
  392. return;
  393. }
  394. carla_safe_assert("scalePoint->label != nullptr", __FILE__, __LINE__);
  395. return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
  396. }
  397. carla_safe_assert("const Parameter* const param = fDescriptor->get_parameter_info(fHandle, parameterId)", __FILE__, __LINE__);
  398. CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
  399. }
  400. // -------------------------------------------------------------------
  401. // Set data (state)
  402. void prepareForSave() override
  403. {
  404. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  405. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  406. if (pData->midiprog.count > 0 && fDescriptor->category == ::PLUGIN_CATEGORY_SYNTH)
  407. {
  408. char strBuf[STR_MAX+1];
  409. std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i",
  410. fCurMidiProgs[0], fCurMidiProgs[1], fCurMidiProgs[2], fCurMidiProgs[3],
  411. fCurMidiProgs[4], fCurMidiProgs[5], fCurMidiProgs[6], fCurMidiProgs[7],
  412. fCurMidiProgs[8], fCurMidiProgs[9], fCurMidiProgs[10], fCurMidiProgs[11],
  413. fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]);
  414. strBuf[STR_MAX] = '\0';
  415. CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING, "midiPrograms", strBuf, false);
  416. }
  417. if (fDescriptor == nullptr || fDescriptor->get_state == nullptr || (fDescriptor->hints & ::PLUGIN_USES_STATE) == 0)
  418. return;
  419. if (char* data = fDescriptor->get_state(fHandle))
  420. {
  421. CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_CHUNK, "State", data, false);
  422. std::free(data);
  423. }
  424. }
  425. // -------------------------------------------------------------------
  426. // Set data (internal stuff)
  427. void setName(const char* const newName) override
  428. {
  429. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  430. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  431. CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0',);
  432. char uiName[std::strlen(newName)+6+1];
  433. std::strcpy(uiName, newName);
  434. std::strcat(uiName, " (GUI)");
  435. if (fHost.uiName != nullptr)
  436. delete[] fHost.uiName;
  437. fHost.uiName = carla_strdup(uiName);
  438. if (fDescriptor->dispatcher != nullptr)
  439. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_UI_NAME_CHANGED, 0, 0, uiName, 0.0f);
  440. CarlaPlugin::setName(newName);
  441. }
  442. void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
  443. {
  444. if (channel >= 0 && channel < MAX_MIDI_CHANNELS && pData->midiprog.count > 0)
  445. pData->midiprog.current = fCurMidiProgs[channel];
  446. CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
  447. }
  448. // -------------------------------------------------------------------
  449. // Set data (plugin-specific stuff)
  450. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  451. {
  452. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  453. CARLA_SAFE_ASSERT_RETURN(fDescriptor->set_parameter_value != nullptr,);
  454. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  455. CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
  456. const float fixedValue(pData->param.getFixedValue(parameterId, value));
  457. // FIXME - try
  458. fDescriptor->set_parameter_value(fHandle, parameterId, fixedValue);
  459. if (fHandle2 != nullptr)
  460. fDescriptor->set_parameter_value(fHandle2, parameterId, fixedValue);
  461. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  462. }
  463. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
  464. {
  465. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  466. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  467. CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
  468. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  469. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  470. carla_debug("NativePlugin::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
  471. if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0 && std::strcmp(type, CUSTOM_DATA_TYPE_CHUNK) != 0)
  472. return carla_stderr2("NativePlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is invalid", type, key, value, bool2str(sendGui));
  473. if (std::strcmp(type, CUSTOM_DATA_TYPE_CHUNK) == 0)
  474. {
  475. if (fDescriptor->set_state != nullptr && (fDescriptor->hints & ::PLUGIN_USES_STATE) != 0)
  476. {
  477. const ScopedSingleProcessLocker spl(this, true);
  478. fDescriptor->set_state(fHandle, value);
  479. if (fHandle2 != nullptr)
  480. fDescriptor->set_state(fHandle2, value);
  481. }
  482. }
  483. else if (std::strcmp(key, "midiPrograms") == 0 && fDescriptor->set_midi_program != nullptr)
  484. {
  485. StringArray midiProgramList(StringArray::fromTokens(value, ":", ""));
  486. if (midiProgramList.size() == MAX_MIDI_CHANNELS)
  487. {
  488. uint8_t channel = 0;
  489. for (String *it=midiProgramList.begin(), *end=midiProgramList.end(); it != end; ++it)
  490. {
  491. const int index(it->getIntValue());
  492. if (index >= 0 && index < static_cast<int>(pData->midiprog.count))
  493. {
  494. const uint32_t bank = pData->midiprog.data[index].bank;
  495. const uint32_t program = pData->midiprog.data[index].program;
  496. fDescriptor->set_midi_program(fHandle, channel, bank, program);
  497. if (fHandle2 != nullptr)
  498. fDescriptor->set_midi_program(fHandle2, channel, bank, program);
  499. fCurMidiProgs[channel] = index;
  500. if (pData->ctrlChannel == static_cast<int32_t>(channel))
  501. {
  502. pData->midiprog.current = index;
  503. pData->engine->callback(ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED, pData->id, index, 0, 0.0f, nullptr);
  504. }
  505. }
  506. ++channel;
  507. }
  508. CARLA_SAFE_ASSERT(channel == MAX_MIDI_CHANNELS);
  509. }
  510. }
  511. else
  512. {
  513. if (fDescriptor->set_custom_data != nullptr)
  514. {
  515. fDescriptor->set_custom_data(fHandle, key, value);
  516. if (fHandle2 != nullptr)
  517. fDescriptor->set_custom_data(fHandle2, key, value);
  518. }
  519. if (sendGui && fIsUiVisible && fDescriptor->ui_set_custom_data != nullptr)
  520. fDescriptor->ui_set_custom_data(fHandle, key, value);
  521. }
  522. CarlaPlugin::setCustomData(type, key, value, sendGui);
  523. }
  524. void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  525. {
  526. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  527. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  528. CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
  529. // TODO, put into check below
  530. if ((pData->hints & PLUGIN_IS_SYNTH) != 0 && (pData->ctrlChannel < 0 || pData->ctrlChannel >= MAX_MIDI_CHANNELS))
  531. return CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  532. if (index >= 0)
  533. {
  534. const uint8_t channel = uint8_t((pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0);
  535. const uint32_t bank = pData->midiprog.data[index].bank;
  536. const uint32_t program = pData->midiprog.data[index].program;
  537. const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  538. try {
  539. fDescriptor->set_midi_program(fHandle, channel, bank, program);
  540. } catch(...) {}
  541. if (fHandle2 != nullptr)
  542. {
  543. try {
  544. fDescriptor->set_midi_program(fHandle2, channel, bank, program);
  545. } catch(...) {}
  546. }
  547. fCurMidiProgs[channel] = index;
  548. }
  549. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  550. }
  551. // -------------------------------------------------------------------
  552. // Set ui stuff
  553. void showCustomUI(const bool yesNo) override
  554. {
  555. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  556. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  557. if (fDescriptor->ui_show == nullptr)
  558. return;
  559. fDescriptor->ui_show(fHandle, yesNo);
  560. if (fIsUiVisible == yesNo)
  561. return;
  562. fIsUiVisible = yesNo;
  563. if (! yesNo)
  564. {
  565. pData->transientTryCounter = 0;
  566. return;
  567. }
  568. #ifndef BUILD_BRIDGE
  569. if ((fDescriptor->hints & ::PLUGIN_USES_PARENT_ID) == 0 && std::strstr(fDescriptor->label, "file") == nullptr)
  570. pData->tryTransient();
  571. #endif
  572. if (fDescriptor->ui_set_custom_data != nullptr)
  573. {
  574. for (LinkedList<CustomData>::Itenerator it = pData->custom.begin(); it.valid(); it.next())
  575. {
  576. const CustomData& cData(it.getValue());
  577. if (std::strcmp(cData.type, CUSTOM_DATA_TYPE_STRING) == 0 && std::strcmp(cData.key, "midiPrograms") != 0)
  578. fDescriptor->ui_set_custom_data(fHandle, cData.key, cData.value);
  579. }
  580. }
  581. if (fDescriptor->ui_set_midi_program != nullptr && pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  582. {
  583. const int32_t index = pData->midiprog.current;
  584. const uint8_t channel = uint8_t((pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS) ? pData->ctrlChannel : 0);
  585. const uint32_t bank = pData->midiprog.data[index].bank;
  586. const uint32_t program = pData->midiprog.data[index].program;
  587. fDescriptor->ui_set_midi_program(fHandle, channel, bank, program);
  588. }
  589. if (fDescriptor->ui_set_parameter_value != nullptr)
  590. {
  591. for (uint32_t i=0; i < pData->param.count; ++i)
  592. fDescriptor->ui_set_parameter_value(fHandle, i, fDescriptor->get_parameter_value(fHandle, i));
  593. }
  594. }
  595. void idle() override
  596. {
  597. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  598. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  599. if (fIsUiVisible && fDescriptor->ui_idle != nullptr)
  600. fDescriptor->ui_idle(fHandle);
  601. CarlaPlugin::idle();
  602. }
  603. // -------------------------------------------------------------------
  604. // Plugin state
  605. void reload() override
  606. {
  607. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  608. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  609. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  610. carla_debug("NativePlugin::reload() - start");
  611. const EngineProcessMode processMode(pData->engine->getProccessMode());
  612. // Safely disable plugin for reload
  613. const ScopedDisabler sd(this);
  614. if (pData->active)
  615. deactivate();
  616. clearBuffers();
  617. const float sampleRate((float)pData->engine->getSampleRate());
  618. uint32_t aIns, aOuts, mIns, mOuts, params, j;
  619. bool forcedStereoIn, forcedStereoOut;
  620. forcedStereoIn = forcedStereoOut = false;
  621. bool needsCtrlIn, needsCtrlOut;
  622. needsCtrlIn = needsCtrlOut = false;
  623. aIns = fDescriptor->audioIns;
  624. aOuts = fDescriptor->audioOuts;
  625. mIns = fDescriptor->midiIns;
  626. mOuts = fDescriptor->midiOuts;
  627. params = (fDescriptor->get_parameter_count != nullptr && fDescriptor->get_parameter_info != nullptr) ? fDescriptor->get_parameter_count(fHandle) : 0;
  628. if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1) && mIns <= 1 && mOuts <= 1)
  629. {
  630. if (fHandle2 == nullptr)
  631. fHandle2 = fDescriptor->instantiate(&fHost);
  632. if (fHandle2 != nullptr)
  633. {
  634. if (aIns == 1)
  635. {
  636. aIns = 2;
  637. forcedStereoIn = true;
  638. }
  639. if (aOuts == 1)
  640. {
  641. aOuts = 2;
  642. forcedStereoOut = true;
  643. }
  644. }
  645. }
  646. if (aIns > 0)
  647. {
  648. pData->audioIn.createNew(aIns);
  649. fAudioInBuffers = new float*[aIns];
  650. for (uint32_t i=0; i < aIns; ++i)
  651. fAudioInBuffers[i] = nullptr;
  652. }
  653. if (aOuts > 0)
  654. {
  655. pData->audioOut.createNew(aOuts);
  656. fAudioOutBuffers = new float*[aOuts];
  657. needsCtrlIn = true;
  658. for (uint32_t i=0; i < aOuts; ++i)
  659. fAudioOutBuffers[i] = nullptr;
  660. }
  661. if (mIns > 0)
  662. {
  663. fMidiIn.createNew(mIns);
  664. needsCtrlIn = (mIns == 1);
  665. }
  666. if (mOuts > 0)
  667. {
  668. fMidiOut.createNew(mOuts);
  669. needsCtrlOut = (mOuts == 1);
  670. }
  671. if (params > 0)
  672. {
  673. pData->param.createNew(params, true);
  674. }
  675. const uint portNameSize(pData->engine->getMaxPortNameSize());
  676. CarlaString portName;
  677. // Audio Ins
  678. for (j=0; j < aIns; ++j)
  679. {
  680. portName.clear();
  681. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  682. {
  683. portName = pData->name;
  684. portName += ":";
  685. }
  686. if (aIns > 1 && ! forcedStereoIn)
  687. {
  688. portName += "input_";
  689. portName += CarlaString(j+1);
  690. }
  691. else
  692. portName += "input";
  693. portName.truncate(portNameSize);
  694. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  695. pData->audioIn.ports[j].rindex = j;
  696. if (forcedStereoIn)
  697. {
  698. portName += "_2";
  699. pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true);
  700. pData->audioIn.ports[1].rindex = j;
  701. break;
  702. }
  703. }
  704. // Audio Outs
  705. for (j=0; j < aOuts; ++j)
  706. {
  707. portName.clear();
  708. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  709. {
  710. portName = pData->name;
  711. portName += ":";
  712. }
  713. if (aOuts > 1 && ! forcedStereoOut)
  714. {
  715. portName += "output_";
  716. portName += CarlaString(j+1);
  717. }
  718. else
  719. portName += "output";
  720. portName.truncate(portNameSize);
  721. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  722. pData->audioOut.ports[j].rindex = j;
  723. if (forcedStereoOut)
  724. {
  725. portName += "_2";
  726. pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false);
  727. pData->audioOut.ports[1].rindex = j;
  728. break;
  729. }
  730. }
  731. // MIDI Input (only if multiple)
  732. if (mIns > 1)
  733. {
  734. for (j=0; j < mIns; ++j)
  735. {
  736. portName.clear();
  737. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  738. {
  739. portName = pData->name;
  740. portName += ":";
  741. }
  742. portName += "midi-in_";
  743. portName += CarlaString(j+1);
  744. portName.truncate(portNameSize);
  745. fMidiIn.ports[j] = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  746. fMidiIn.indexes[j] = j;
  747. }
  748. }
  749. // MIDI Output (only if multiple)
  750. if (mOuts > 1)
  751. {
  752. for (j=0; j < mOuts; ++j)
  753. {
  754. portName.clear();
  755. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  756. {
  757. portName = pData->name;
  758. portName += ":";
  759. }
  760. portName += "midi-out_";
  761. portName += CarlaString(j+1);
  762. portName.truncate(portNameSize);
  763. fMidiOut.ports[j] = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  764. fMidiOut.indexes[j] = j;
  765. }
  766. }
  767. for (j=0; j < params; ++j)
  768. {
  769. const NativeParameter* const paramInfo(fDescriptor->get_parameter_info(fHandle, j));
  770. CARLA_SAFE_ASSERT_CONTINUE(paramInfo != nullptr);
  771. pData->param.data[j].type = PARAMETER_UNKNOWN;
  772. pData->param.data[j].index = static_cast<int32_t>(j);
  773. pData->param.data[j].rindex = static_cast<int32_t>(j);
  774. float min, max, def, step, stepSmall, stepLarge;
  775. // min value
  776. min = paramInfo->ranges.min;
  777. // max value
  778. max = paramInfo->ranges.max;
  779. if (min > max)
  780. max = min;
  781. else if (max < min)
  782. min = max;
  783. if (carla_compareFloats(min, max))
  784. {
  785. carla_stderr2("WARNING - Broken plugin parameter '%s': max == min", paramInfo->name);
  786. max = min + 0.1f;
  787. }
  788. // default value
  789. def = paramInfo->ranges.def;
  790. if (def < min)
  791. def = min;
  792. else if (def > max)
  793. def = max;
  794. if (paramInfo->hints & ::PARAMETER_USES_SAMPLE_RATE)
  795. {
  796. min *= sampleRate;
  797. max *= sampleRate;
  798. def *= sampleRate;
  799. pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  800. }
  801. if (paramInfo->hints & ::PARAMETER_IS_BOOLEAN)
  802. {
  803. step = max - min;
  804. stepSmall = step;
  805. stepLarge = step;
  806. pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  807. }
  808. else if (paramInfo->hints & ::PARAMETER_IS_INTEGER)
  809. {
  810. step = 1.0f;
  811. stepSmall = 1.0f;
  812. stepLarge = 10.0f;
  813. pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  814. }
  815. else
  816. {
  817. float range = max - min;
  818. step = range/100.0f;
  819. stepSmall = range/1000.0f;
  820. stepLarge = range/10.0f;
  821. }
  822. if (paramInfo->hints & ::PARAMETER_IS_OUTPUT)
  823. {
  824. pData->param.data[j].type = PARAMETER_OUTPUT;
  825. needsCtrlOut = true;
  826. }
  827. else
  828. {
  829. pData->param.data[j].type = PARAMETER_INPUT;
  830. needsCtrlIn = true;
  831. }
  832. // extra parameter hints
  833. if (paramInfo->hints & ::PARAMETER_IS_ENABLED)
  834. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  835. if (paramInfo->hints & ::PARAMETER_IS_AUTOMABLE)
  836. pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  837. if (paramInfo->hints & ::PARAMETER_IS_LOGARITHMIC)
  838. pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  839. if (paramInfo->hints & ::PARAMETER_USES_SCALEPOINTS)
  840. pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
  841. if (paramInfo->hints & ::PARAMETER_USES_CUSTOM_TEXT)
  842. pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
  843. pData->param.ranges[j].min = min;
  844. pData->param.ranges[j].max = max;
  845. pData->param.ranges[j].def = def;
  846. pData->param.ranges[j].step = step;
  847. pData->param.ranges[j].stepSmall = stepSmall;
  848. pData->param.ranges[j].stepLarge = stepLarge;
  849. }
  850. if (needsCtrlIn)
  851. {
  852. portName.clear();
  853. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  854. {
  855. portName = pData->name;
  856. portName += ":";
  857. }
  858. portName += "events-in";
  859. portName.truncate(portNameSize);
  860. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true);
  861. }
  862. if (needsCtrlOut)
  863. {
  864. portName.clear();
  865. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  866. {
  867. portName = pData->name;
  868. portName += ":";
  869. }
  870. portName += "events-out";
  871. portName.truncate(portNameSize);
  872. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false);
  873. }
  874. if (forcedStereoIn || forcedStereoOut)
  875. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  876. else
  877. pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
  878. // plugin hints
  879. pData->hints = 0x0;
  880. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  881. pData->hints |= PLUGIN_CAN_DRYWET;
  882. if (aOuts > 0)
  883. pData->hints |= PLUGIN_CAN_VOLUME;
  884. if (aOuts >= 2 && aOuts % 2 == 0)
  885. pData->hints |= PLUGIN_CAN_BALANCE;
  886. // native plugin hints
  887. if (fDescriptor->hints & ::PLUGIN_IS_RTSAFE)
  888. pData->hints |= PLUGIN_IS_RTSAFE;
  889. if (fDescriptor->hints & ::PLUGIN_IS_SYNTH)
  890. pData->hints |= PLUGIN_IS_SYNTH;
  891. if (fDescriptor->hints & ::PLUGIN_HAS_UI)
  892. pData->hints |= PLUGIN_HAS_CUSTOM_UI;
  893. if (fDescriptor->hints & ::PLUGIN_NEEDS_SINGLE_THREAD)
  894. pData->hints |= PLUGIN_NEEDS_SINGLE_THREAD;
  895. if (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS)
  896. pData->hints |= PLUGIN_NEEDS_FIXED_BUFFERS;
  897. // extra plugin hints
  898. pData->extraHints = 0x0;
  899. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && mIns <= 1 && mOuts <= 1)
  900. pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
  901. if (fDescriptor->hints & ::PLUGIN_USES_MULTI_PROGS)
  902. pData->extraHints |= PLUGIN_EXTRA_HINT_USES_MULTI_PROGS;
  903. bufferSizeChanged(pData->engine->getBufferSize());
  904. reloadPrograms(true);
  905. if (pData->active)
  906. activate();
  907. carla_debug("NativePlugin::reload() - end");
  908. }
  909. void reloadPrograms(const bool doInit) override
  910. {
  911. carla_debug("NativePlugin::reloadPrograms(%s)", bool2str(doInit));
  912. uint32_t i, oldCount = pData->midiprog.count;
  913. const int32_t current = pData->midiprog.current;
  914. // Delete old programs
  915. pData->midiprog.clear();
  916. // Query new programs
  917. uint32_t count = 0;
  918. if (fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_info != nullptr && fDescriptor->set_midi_program != nullptr)
  919. count = fDescriptor->get_midi_program_count(fHandle);
  920. if (count > 0)
  921. {
  922. pData->midiprog.createNew(count);
  923. // Update data
  924. for (i=0; i < count; ++i)
  925. {
  926. const NativeMidiProgram* const mpDesc(fDescriptor->get_midi_program_info(fHandle, i));
  927. CARLA_SAFE_ASSERT_CONTINUE(mpDesc != nullptr);
  928. pData->midiprog.data[i].bank = mpDesc->bank;
  929. pData->midiprog.data[i].program = mpDesc->program;
  930. pData->midiprog.data[i].name = carla_strdup(mpDesc->name);
  931. }
  932. }
  933. #ifndef BUILD_BRIDGE
  934. // Update OSC Names
  935. if (pData->engine->isOscControlRegistered())
  936. {
  937. pData->engine->oscSend_control_set_midi_program_count(pData->id, count);
  938. for (i=0; i < count; ++i)
  939. pData->engine->oscSend_control_set_midi_program_data(pData->id, i, pData->midiprog.data[i].bank, pData->midiprog.data[i].program, pData->midiprog.data[i].name);
  940. }
  941. #endif
  942. if (doInit)
  943. {
  944. if (count > 0)
  945. setMidiProgram(0, false, false, false);
  946. }
  947. else
  948. {
  949. // Check if current program is invalid
  950. bool programChanged = false;
  951. if (count == oldCount+1)
  952. {
  953. // one midi program added, probably created by user
  954. pData->midiprog.current = static_cast<int32_t>(oldCount);
  955. programChanged = true;
  956. }
  957. else if (current < 0 && count > 0)
  958. {
  959. // programs exist now, but not before
  960. pData->midiprog.current = 0;
  961. programChanged = true;
  962. }
  963. else if (current >= 0 && count == 0)
  964. {
  965. // programs existed before, but not anymore
  966. pData->midiprog.current = -1;
  967. programChanged = true;
  968. }
  969. else if (current >= static_cast<int32_t>(count))
  970. {
  971. // current midi program > count
  972. pData->midiprog.current = 0;
  973. programChanged = true;
  974. }
  975. else
  976. {
  977. // no change
  978. pData->midiprog.current = current;
  979. }
  980. if (programChanged)
  981. setMidiProgram(pData->midiprog.current, true, true, true);
  982. pData->engine->callback(ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0.0f, nullptr);
  983. }
  984. }
  985. // -------------------------------------------------------------------
  986. // Plugin processing
  987. void activate() noexcept override
  988. {
  989. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  990. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  991. if (fDescriptor->activate != nullptr)
  992. {
  993. try {
  994. fDescriptor->activate(fHandle);
  995. } catch(...) {}
  996. if (fHandle2 != nullptr)
  997. {
  998. try {
  999. fDescriptor->activate(fHandle2);
  1000. } catch(...) {}
  1001. }
  1002. }
  1003. }
  1004. void deactivate() noexcept override
  1005. {
  1006. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1007. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  1008. if (fDescriptor->deactivate != nullptr)
  1009. {
  1010. try {
  1011. fDescriptor->deactivate(fHandle);
  1012. } catch(...) {}
  1013. if (fHandle2 != nullptr)
  1014. {
  1015. try {
  1016. fDescriptor->deactivate(fHandle2);
  1017. } catch(...) {}
  1018. }
  1019. }
  1020. }
  1021. void process(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames) override
  1022. {
  1023. // --------------------------------------------------------------------------------------------------------
  1024. // Check if active
  1025. if (! pData->active)
  1026. {
  1027. // disable any output sound
  1028. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1029. FloatVectorOperations::clear(audioOut[i], static_cast<int>(frames));
  1030. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1031. FloatVectorOperations::clear(cvOut[i], static_cast<int>(frames));
  1032. return;
  1033. }
  1034. fMidiEventCount = 0;
  1035. carla_zeroStruct<NativeMidiEvent>(fMidiEvents, kPluginMaxMidiEvents*2);
  1036. // --------------------------------------------------------------------------------------------------------
  1037. // Check if needs reset
  1038. if (pData->needsReset)
  1039. {
  1040. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1041. {
  1042. fMidiEventCount = MAX_MIDI_CHANNELS*2;
  1043. for (uint8_t k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; ++k)
  1044. {
  1045. fMidiEvents[k].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT));
  1046. fMidiEvents[k].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  1047. fMidiEvents[k].data[2] = 0;
  1048. fMidiEvents[k].size = 3;
  1049. fMidiEvents[k+i].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT));
  1050. fMidiEvents[k+i].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  1051. fMidiEvents[k+i].data[2] = 0;
  1052. fMidiEvents[k+i].size = 3;
  1053. }
  1054. }
  1055. else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
  1056. {
  1057. fMidiEventCount = MAX_MIDI_NOTE;
  1058. for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k)
  1059. {
  1060. fMidiEvents[k].data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT));
  1061. fMidiEvents[k].data[1] = k;
  1062. fMidiEvents[k].data[2] = 0;
  1063. fMidiEvents[k].size = 3;
  1064. }
  1065. }
  1066. pData->needsReset = false;
  1067. }
  1068. // --------------------------------------------------------------------------------------------------------
  1069. // Set TimeInfo
  1070. const EngineTimeInfo& timeInfo(pData->engine->getTimeInfo());
  1071. fTimeInfo.playing = timeInfo.playing;
  1072. fTimeInfo.frame = timeInfo.frame;
  1073. fTimeInfo.usecs = timeInfo.usecs;
  1074. if (timeInfo.valid & EngineTimeInfo::kValidBBT)
  1075. {
  1076. fTimeInfo.bbt.valid = true;
  1077. fTimeInfo.bbt.bar = timeInfo.bbt.bar;
  1078. fTimeInfo.bbt.beat = timeInfo.bbt.beat;
  1079. fTimeInfo.bbt.tick = timeInfo.bbt.tick;
  1080. fTimeInfo.bbt.barStartTick = timeInfo.bbt.barStartTick;
  1081. fTimeInfo.bbt.beatsPerBar = timeInfo.bbt.beatsPerBar;
  1082. fTimeInfo.bbt.beatType = timeInfo.bbt.beatType;
  1083. fTimeInfo.bbt.ticksPerBeat = timeInfo.bbt.ticksPerBeat;
  1084. fTimeInfo.bbt.beatsPerMinute = timeInfo.bbt.beatsPerMinute;
  1085. }
  1086. else
  1087. fTimeInfo.bbt.valid = false;
  1088. // --------------------------------------------------------------------------------------------------------
  1089. // Event Input and Processing
  1090. if (pData->event.portIn != nullptr)
  1091. {
  1092. // ----------------------------------------------------------------------------------------------------
  1093. // MIDI Input (External)
  1094. if (pData->extNotes.mutex.tryLock())
  1095. {
  1096. ExternalMidiNote note = { 0, 0, 0 };
  1097. for (; fMidiEventCount < kPluginMaxMidiEvents*2 && ! pData->extNotes.data.isEmpty();)
  1098. {
  1099. note = pData->extNotes.data.getFirst(note, true);
  1100. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  1101. NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
  1102. nativeEvent.data[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
  1103. nativeEvent.data[1] = note.note;
  1104. nativeEvent.data[2] = note.velo;
  1105. nativeEvent.size = 3;
  1106. }
  1107. pData->extNotes.mutex.unlock();
  1108. } // End of MIDI Input (External)
  1109. // ----------------------------------------------------------------------------------------------------
  1110. // Event Input (System)
  1111. #ifndef BUILD_BRIDGE
  1112. bool allNotesOffSent = false;
  1113. #endif
  1114. bool sampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
  1115. uint32_t startTime = 0;
  1116. uint32_t timeOffset = 0;
  1117. uint32_t nextBankId;
  1118. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  1119. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  1120. else
  1121. nextBankId = 0;
  1122. for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
  1123. {
  1124. const EngineEvent& event(pData->event.portIn->getEvent(i));
  1125. if (event.time >= frames)
  1126. continue;
  1127. CARLA_ASSERT_INT2(event.time >= timeOffset, event.time, timeOffset);
  1128. if (event.time > timeOffset && sampleAccurate)
  1129. {
  1130. if (processSingle(audioIn, audioOut, cvIn, cvOut, event.time - timeOffset, timeOffset))
  1131. {
  1132. startTime = 0;
  1133. timeOffset = event.time;
  1134. if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
  1135. nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
  1136. else
  1137. nextBankId = 0;
  1138. if (fMidiEventCount > 0)
  1139. {
  1140. carla_zeroStruct<NativeMidiEvent>(fMidiEvents, fMidiEventCount);
  1141. fMidiEventCount = 0;
  1142. }
  1143. }
  1144. else
  1145. startTime += timeOffset;
  1146. }
  1147. // Control change
  1148. switch (event.type)
  1149. {
  1150. case kEngineEventTypeNull:
  1151. break;
  1152. case kEngineEventTypeControl: {
  1153. const EngineControlEvent& ctrlEvent = event.ctrl;
  1154. switch (ctrlEvent.type)
  1155. {
  1156. case kEngineControlEventTypeNull:
  1157. break;
  1158. case kEngineControlEventTypeParameter: {
  1159. #ifndef BUILD_BRIDGE
  1160. // Control backend stuff
  1161. if (event.channel == pData->ctrlChannel)
  1162. {
  1163. float value;
  1164. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) > 0)
  1165. {
  1166. value = ctrlEvent.value;
  1167. setDryWet(value, false, false);
  1168. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  1169. }
  1170. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) > 0)
  1171. {
  1172. value = ctrlEvent.value*127.0f/100.0f;
  1173. setVolume(value, false, false);
  1174. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  1175. }
  1176. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) > 0)
  1177. {
  1178. float left, right;
  1179. value = ctrlEvent.value/0.5f - 1.0f;
  1180. if (value < 0.0f)
  1181. {
  1182. left = -1.0f;
  1183. right = (value*2.0f)+1.0f;
  1184. }
  1185. else if (value > 0.0f)
  1186. {
  1187. left = (value*2.0f)-1.0f;
  1188. right = 1.0f;
  1189. }
  1190. else
  1191. {
  1192. left = -1.0f;
  1193. right = 1.0f;
  1194. }
  1195. setBalanceLeft(left, false, false);
  1196. setBalanceRight(right, false, false);
  1197. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  1198. pData->postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  1199. }
  1200. }
  1201. #endif
  1202. // Control plugin parameters
  1203. for (uint32_t k=0; k < pData->param.count; ++k)
  1204. {
  1205. if (pData->param.data[k].midiChannel != event.channel)
  1206. continue;
  1207. if (pData->param.data[k].midiCC != ctrlEvent.param)
  1208. continue;
  1209. if (pData->param.data[k].type != PARAMETER_INPUT)
  1210. continue;
  1211. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  1212. continue;
  1213. float value;
  1214. if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  1215. {
  1216. value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;
  1217. }
  1218. else
  1219. {
  1220. value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value);
  1221. if (pData->param.data[k].hints & PARAMETER_IS_INTEGER)
  1222. value = std::rint(value);
  1223. }
  1224. setParameterValue(k, value, false, false, false);
  1225. pData->postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  1226. }
  1227. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_CONTROL)
  1228. {
  1229. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1230. continue;
  1231. NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
  1232. carla_zeroStruct(nativeEvent);
  1233. nativeEvent.time = sampleAccurate ? startTime : event.time;
  1234. nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
  1235. nativeEvent.data[1] = uint8_t(ctrlEvent.param);
  1236. nativeEvent.data[2] = uint8_t(ctrlEvent.value*127.0f);
  1237. nativeEvent.size = 3;
  1238. }
  1239. break;
  1240. }
  1241. case kEngineControlEventTypeMidiBank:
  1242. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1243. nextBankId = ctrlEvent.param;
  1244. break;
  1245. case kEngineControlEventTypeMidiProgram:
  1246. if (event.channel < MAX_MIDI_CHANNELS && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  1247. {
  1248. const uint32_t nextProgramId(ctrlEvent.param);
  1249. for (uint32_t k=0; k < pData->midiprog.count; ++k)
  1250. {
  1251. if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
  1252. {
  1253. fDescriptor->set_midi_program(fHandle, event.channel, nextBankId, nextProgramId);
  1254. if (fHandle2 != nullptr)
  1255. fDescriptor->set_midi_program(fHandle2, event.channel, nextBankId, nextProgramId);
  1256. fCurMidiProgs[event.channel] = static_cast<int32_t>(k);
  1257. if (event.channel == pData->ctrlChannel)
  1258. pData->postponeRtEvent(kPluginPostRtEventMidiProgramChange, static_cast<int32_t>(k), 0, 0.0f);
  1259. break;
  1260. }
  1261. }
  1262. }
  1263. break;
  1264. case kEngineControlEventTypeAllSoundOff:
  1265. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1266. {
  1267. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1268. continue;
  1269. NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
  1270. carla_zeroStruct(nativeEvent);
  1271. nativeEvent.port = 0;
  1272. nativeEvent.time = sampleAccurate ? startTime : event.time;
  1273. nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
  1274. nativeEvent.data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
  1275. nativeEvent.data[2] = 0;
  1276. nativeEvent.size = 3;
  1277. }
  1278. break;
  1279. case kEngineControlEventTypeAllNotesOff:
  1280. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1281. {
  1282. #ifndef BUILD_BRIDGE
  1283. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  1284. {
  1285. allNotesOffSent = true;
  1286. sendMidiAllNotesOffToCallback();
  1287. }
  1288. #endif
  1289. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1290. continue;
  1291. NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
  1292. carla_zeroStruct(nativeEvent);
  1293. nativeEvent.time = sampleAccurate ? startTime : event.time;
  1294. nativeEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
  1295. nativeEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
  1296. nativeEvent.data[2] = 0;
  1297. nativeEvent.size = 3;
  1298. }
  1299. break;
  1300. }
  1301. break;
  1302. }
  1303. case kEngineEventTypeMidi: {
  1304. if (fMidiEventCount >= kPluginMaxMidiEvents*2)
  1305. continue;
  1306. const EngineMidiEvent& midiEvent(event.midi);
  1307. if (midiEvent.size > 4)
  1308. continue;
  1309. #ifdef CARLA_PROPER_CPP11_SUPPORT
  1310. static_assert(4 <= EngineMidiEvent::kDataSize, "Incorrect data");
  1311. #endif
  1312. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data));
  1313. if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
  1314. continue;
  1315. if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
  1316. continue;
  1317. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  1318. continue;
  1319. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
  1320. continue;
  1321. // Fix bad note-off
  1322. if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
  1323. status = MIDI_STATUS_NOTE_OFF;
  1324. NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
  1325. carla_zeroStruct(nativeEvent);
  1326. nativeEvent.port = midiEvent.port;
  1327. nativeEvent.time = sampleAccurate ? startTime : event.time;
  1328. nativeEvent.size = midiEvent.size;
  1329. nativeEvent.data[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT));
  1330. nativeEvent.data[1] = midiEvent.size >= 2 ? midiEvent.data[1] : 0;
  1331. nativeEvent.data[2] = midiEvent.size >= 3 ? midiEvent.data[2] : 0;
  1332. nativeEvent.data[3] = midiEvent.size == 4 ? midiEvent.data[3] : 0;
  1333. if (status == MIDI_STATUS_NOTE_ON)
  1334. pData->postponeRtEvent(kPluginPostRtEventNoteOn, event.channel, midiEvent.data[1], midiEvent.data[2]);
  1335. else if (status == MIDI_STATUS_NOTE_OFF)
  1336. pData->postponeRtEvent(kPluginPostRtEventNoteOff, event.channel, midiEvent.data[1], 0.0f);
  1337. } break;
  1338. } // switch (event.type)
  1339. }
  1340. pData->postRtEvents.trySplice();
  1341. if (frames > timeOffset)
  1342. processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset);
  1343. } // End of Event Input and Processing
  1344. // --------------------------------------------------------------------------------------------------------
  1345. // Plugin processing (no events)
  1346. else
  1347. {
  1348. processSingle(audioIn, audioOut, cvIn, cvOut, frames, 0);
  1349. } // End of Plugin processing (no events)
  1350. // --------------------------------------------------------------------------------------------------------
  1351. // Control and MIDI Output
  1352. if (fMidiOut.count > 0 || pData->event.portOut != nullptr)
  1353. {
  1354. #ifndef BUILD_BRIDGE
  1355. float value, curValue;
  1356. for (uint32_t k=0; k < pData->param.count; ++k)
  1357. {
  1358. if (pData->param.data[k].type != PARAMETER_OUTPUT)
  1359. continue;
  1360. curValue = fDescriptor->get_parameter_value(fHandle, k);
  1361. pData->param.ranges[k].fixValue(curValue);
  1362. if (pData->param.data[k].midiCC > 0)
  1363. {
  1364. value = pData->param.ranges[k].getNormalizedValue(curValue);
  1365. pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast<uint16_t>(pData->param.data[k].midiCC), value);
  1366. }
  1367. }
  1368. #endif
  1369. // reverse lookup MIDI events
  1370. for (uint32_t k = (kPluginMaxMidiEvents*2)-1; k >= fMidiEventCount; --k)
  1371. {
  1372. if (fMidiEvents[k].data[0] == 0)
  1373. break;
  1374. const uint8_t channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(fMidiEvents[k].data));
  1375. const uint8_t port = fMidiEvents[k].port;
  1376. if (pData->event.portOut != nullptr)
  1377. pData->event.portOut->writeMidiEvent(fMidiEvents[k].time, channel, port, fMidiEvents[k].size, fMidiEvents[k].data);
  1378. else if (port < fMidiOut.count)
  1379. fMidiOut.ports[port]->writeMidiEvent(fMidiEvents[k].time, channel, port, fMidiEvents[k].size, fMidiEvents[k].data);
  1380. }
  1381. } // End of Control and MIDI Output
  1382. }
  1383. bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames, const uint32_t timeOffset)
  1384. {
  1385. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  1386. if (pData->audioIn.count > 0)
  1387. {
  1388. CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
  1389. }
  1390. if (pData->audioOut.count > 0)
  1391. {
  1392. CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
  1393. }
  1394. if (pData->cvIn.count > 0)
  1395. {
  1396. CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
  1397. }
  1398. if (pData->cvOut.count > 0)
  1399. {
  1400. CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
  1401. }
  1402. // --------------------------------------------------------------------------------------------------------
  1403. // Try lock, silence otherwise
  1404. if (pData->engine->isOffline())
  1405. {
  1406. pData->singleMutex.lock();
  1407. }
  1408. else if (! pData->singleMutex.tryLock())
  1409. {
  1410. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1411. {
  1412. for (uint32_t k=0; k < frames; ++k)
  1413. audioOut[i][k+timeOffset] = 0.0f;
  1414. }
  1415. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1416. {
  1417. for (uint32_t k=0; k < frames; ++k)
  1418. cvOut[i][k+timeOffset] = 0.0f;
  1419. }
  1420. return false;
  1421. }
  1422. // --------------------------------------------------------------------------------------------------------
  1423. // Set audio buffers
  1424. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1425. FloatVectorOperations::copy(fAudioInBuffers[i], audioIn[i]+timeOffset, static_cast<int>(frames));
  1426. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1427. FloatVectorOperations::clear(fAudioOutBuffers[i], static_cast<int>(frames));
  1428. #if 0
  1429. // --------------------------------------------------------------------------------------------------------
  1430. // Set CV buffers
  1431. for (uint32_t i=0; i < pData->cvIn.count; ++i)
  1432. FloatVectorOperations::copy(fCvInBuffers[i], cvIn[i]+timeOffset, static_cast<int>(frames));
  1433. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1434. FloatVectorOperations::clear(fCvOutBuffers[i], static_cast<int>(frames));
  1435. #endif
  1436. // --------------------------------------------------------------------------------------------------------
  1437. // Run plugin
  1438. fIsProcessing = true;
  1439. if (fHandle2 == nullptr)
  1440. {
  1441. fDescriptor->process(fHandle, fAudioInBuffers, fAudioOutBuffers, frames, fMidiEvents, fMidiEventCount);
  1442. }
  1443. else
  1444. {
  1445. fDescriptor->process(fHandle,
  1446. (pData->audioIn.count > 0) ? &fAudioInBuffers[0] : nullptr,
  1447. (pData->audioOut.count > 0) ? &fAudioOutBuffers[0] : nullptr,
  1448. frames, fMidiEvents, fMidiEventCount);
  1449. fDescriptor->process(fHandle2,
  1450. (pData->audioIn.count > 0) ? &fAudioInBuffers[1] : nullptr,
  1451. (pData->audioOut.count > 0) ? &fAudioOutBuffers[1] : nullptr,
  1452. frames, fMidiEvents, fMidiEventCount);
  1453. }
  1454. fIsProcessing = false;
  1455. fTimeInfo.frame += frames;
  1456. #ifndef BUILD_BRIDGE
  1457. // --------------------------------------------------------------------------------------------------------
  1458. // Post-processing (dry/wet, volume and balance)
  1459. {
  1460. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && ! carla_compareFloats(pData->postProc.dryWet, 1.0f);
  1461. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_compareFloats(pData->postProc.balanceLeft, -1.0f) && carla_compareFloats(pData->postProc.balanceRight, 1.0f));
  1462. bool isPair;
  1463. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1464. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1465. {
  1466. // Dry/Wet
  1467. if (doDryWet)
  1468. {
  1469. for (uint32_t k=0; k < frames; ++k)
  1470. {
  1471. bufValue = fAudioInBuffers[(pData->audioIn.count == 1) ? 0 : i][k];
  1472. fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
  1473. }
  1474. }
  1475. // Balance
  1476. if (doBalance)
  1477. {
  1478. isPair = (i % 2 == 0);
  1479. if (isPair)
  1480. {
  1481. CARLA_ASSERT(i+1 < pData->audioOut.count);
  1482. FloatVectorOperations::copy(oldBufLeft, fAudioOutBuffers[i], static_cast<int>(frames));
  1483. }
  1484. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  1485. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  1486. for (uint32_t k=0; k < frames; ++k)
  1487. {
  1488. if (isPair)
  1489. {
  1490. // left
  1491. fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1492. fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
  1493. }
  1494. else
  1495. {
  1496. // right
  1497. fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
  1498. fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  1499. }
  1500. }
  1501. }
  1502. // Volume (and buffer copy)
  1503. {
  1504. for (uint32_t k=0; k < frames; ++k)
  1505. audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
  1506. }
  1507. }
  1508. } // End of Post-processing
  1509. #else
  1510. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1511. {
  1512. for (uint32_t k=0; k < frames; ++k)
  1513. audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
  1514. }
  1515. #endif
  1516. #if 0
  1517. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1518. {
  1519. for (uint32_t k=0; k < frames; ++k)
  1520. cvOut[i][k+timeOffset] = fCvOutBuffers[i][k];
  1521. }
  1522. #endif
  1523. // --------------------------------------------------------------------------------------------------------
  1524. pData->singleMutex.unlock();
  1525. return true;
  1526. }
  1527. void bufferSizeChanged(const uint32_t newBufferSize) override
  1528. {
  1529. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  1530. carla_debug("NativePlugin::bufferSizeChanged(%i)", newBufferSize);
  1531. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1532. {
  1533. if (fAudioInBuffers[i] != nullptr)
  1534. delete[] fAudioInBuffers[i];
  1535. fAudioInBuffers[i] = new float[newBufferSize];
  1536. }
  1537. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1538. {
  1539. if (fAudioOutBuffers[i] != nullptr)
  1540. delete[] fAudioOutBuffers[i];
  1541. fAudioOutBuffers[i] = new float[newBufferSize];
  1542. }
  1543. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  1544. {
  1545. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, static_cast<intptr_t>(newBufferSize), nullptr, 0.0f);
  1546. if (fHandle2 != nullptr)
  1547. fDescriptor->dispatcher(fHandle2, PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, static_cast<intptr_t>(newBufferSize), nullptr, 0.0f);
  1548. }
  1549. }
  1550. void sampleRateChanged(const double newSampleRate) override
  1551. {
  1552. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  1553. carla_debug("NativePlugin::sampleRateChanged(%g)", newSampleRate);
  1554. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  1555. {
  1556. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, float(newSampleRate));
  1557. if (fHandle2 != nullptr)
  1558. fDescriptor->dispatcher(fHandle2, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, float(newSampleRate));
  1559. }
  1560. }
  1561. void offlineModeChanged(const bool isOffline) override
  1562. {
  1563. if (fDescriptor != nullptr && fDescriptor->dispatcher != nullptr)
  1564. {
  1565. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_OFFLINE_CHANGED, 0, isOffline ? 1 : 0, nullptr, 0.0f);
  1566. if (fHandle2 != nullptr)
  1567. fDescriptor->dispatcher(fHandle2, PLUGIN_OPCODE_OFFLINE_CHANGED, 0, isOffline ? 1 : 0, nullptr, 0.0f);
  1568. }
  1569. }
  1570. // -------------------------------------------------------------------
  1571. // Plugin buffers
  1572. void initBuffers() const noexcept override
  1573. {
  1574. fMidiIn.initBuffers();
  1575. fMidiOut.initBuffers();
  1576. CarlaPlugin::initBuffers();
  1577. }
  1578. void clearBuffers() noexcept override
  1579. {
  1580. carla_debug("NativePlugin::clearBuffers() - start");
  1581. if (fAudioInBuffers != nullptr)
  1582. {
  1583. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  1584. {
  1585. if (fAudioInBuffers[i] != nullptr)
  1586. {
  1587. delete[] fAudioInBuffers[i];
  1588. fAudioInBuffers[i] = nullptr;
  1589. }
  1590. }
  1591. delete[] fAudioInBuffers;
  1592. fAudioInBuffers = nullptr;
  1593. }
  1594. if (fAudioOutBuffers != nullptr)
  1595. {
  1596. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1597. {
  1598. if (fAudioOutBuffers[i] != nullptr)
  1599. {
  1600. delete[] fAudioOutBuffers[i];
  1601. fAudioOutBuffers[i] = nullptr;
  1602. }
  1603. }
  1604. delete[] fAudioOutBuffers;
  1605. fAudioOutBuffers = nullptr;
  1606. }
  1607. fMidiIn.clear();
  1608. fMidiOut.clear();
  1609. CarlaPlugin::clearBuffers();
  1610. carla_debug("NativePlugin::clearBuffers() - end");
  1611. }
  1612. // -------------------------------------------------------------------
  1613. // Post-poned UI Stuff
  1614. void uiParameterChange(const uint32_t index, const float value) noexcept override
  1615. {
  1616. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1617. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  1618. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  1619. if (! fIsUiVisible)
  1620. return;
  1621. if (fDescriptor->ui_set_parameter_value != nullptr)
  1622. fDescriptor->ui_set_parameter_value(fHandle, index, value);
  1623. }
  1624. void uiMidiProgramChange(const uint32_t index) noexcept override
  1625. {
  1626. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1627. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  1628. CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
  1629. if (! fIsUiVisible)
  1630. return;
  1631. if (index >= pData->midiprog.count)
  1632. return;
  1633. if (fDescriptor->ui_set_midi_program != nullptr)
  1634. fDescriptor->ui_set_midi_program(fHandle, 0, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
  1635. }
  1636. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
  1637. {
  1638. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1639. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  1640. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1641. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1642. CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
  1643. if (! fIsUiVisible)
  1644. return;
  1645. // TODO
  1646. }
  1647. void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
  1648. {
  1649. CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
  1650. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
  1651. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  1652. CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
  1653. if (! fIsUiVisible)
  1654. return;
  1655. if (fDescriptor == nullptr || fHandle == nullptr)
  1656. return;
  1657. // TODO
  1658. }
  1659. // -------------------------------------------------------------------
  1660. protected:
  1661. uint32_t handleGetBufferSize() const noexcept
  1662. {
  1663. return pData->engine->getBufferSize();
  1664. }
  1665. double handleGetSampleRate() const noexcept
  1666. {
  1667. return pData->engine->getSampleRate();
  1668. }
  1669. bool handleIsOffline() const noexcept
  1670. {
  1671. return pData->engine->isOffline();
  1672. }
  1673. const NativeTimeInfo* handleGetTimeInfo() const noexcept
  1674. {
  1675. CARLA_SAFE_ASSERT_RETURN(fIsProcessing, nullptr);
  1676. return &fTimeInfo;
  1677. }
  1678. bool handleWriteMidiEvent(const NativeMidiEvent* const event)
  1679. {
  1680. CARLA_ASSERT(pData->enabled);
  1681. CARLA_ASSERT(fIsProcessing);
  1682. CARLA_ASSERT(fMidiOut.count > 0 || pData->event.portOut != nullptr);
  1683. CARLA_ASSERT(event != nullptr);
  1684. CARLA_ASSERT(event->data[0] != 0);
  1685. if (! pData->enabled)
  1686. return false;
  1687. if (fMidiOut.count == 0)
  1688. return false;
  1689. if (event == nullptr)
  1690. return false;
  1691. if (event->data[0] == 0)
  1692. return false;
  1693. if (! fIsProcessing)
  1694. {
  1695. carla_stderr2("NativePlugin::handleWriteMidiEvent(%p) - received MIDI out event outside audio thread, ignoring", event);
  1696. return false;
  1697. }
  1698. // reverse-find first free event, and put it there
  1699. for (uint32_t i=(kPluginMaxMidiEvents*2)-1; i > fMidiEventCount; --i)
  1700. {
  1701. if (fMidiEvents[i].data[0] == 0)
  1702. {
  1703. std::memcpy(&fMidiEvents[i], event, sizeof(NativeMidiEvent));
  1704. return true;
  1705. }
  1706. }
  1707. return false;
  1708. }
  1709. void handleUiParameterChanged(const uint32_t index, const float value)
  1710. {
  1711. setParameterValue(index, value, false, true, true);
  1712. }
  1713. void handleUiCustomDataChanged(const char* const key, const char* const value)
  1714. {
  1715. setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false);
  1716. }
  1717. void handleUiClosed()
  1718. {
  1719. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
  1720. fIsUiVisible = false;
  1721. }
  1722. const char* handleUiOpenFile(const bool isDir, const char* const title, const char* const filter)
  1723. {
  1724. return pData->engine->runFileCallback(FILE_CALLBACK_OPEN, isDir, title, filter);
  1725. }
  1726. const char* handleUiSaveFile(const bool isDir, const char* const title, const char* const filter)
  1727. {
  1728. return pData->engine->runFileCallback(FILE_CALLBACK_SAVE, isDir, title, filter);
  1729. }
  1730. intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
  1731. {
  1732. carla_debug("NativePlugin::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", opcode, index, value, ptr, opt);
  1733. intptr_t ret = 0;
  1734. switch (opcode)
  1735. {
  1736. case ::HOST_OPCODE_NULL:
  1737. break;
  1738. case ::HOST_OPCODE_UPDATE_PARAMETER:
  1739. // TODO
  1740. pData->engine->callback(ENGINE_CALLBACK_UPDATE, pData->id, -1, 0, 0.0f, nullptr);
  1741. break;
  1742. case ::HOST_OPCODE_UPDATE_MIDI_PROGRAM:
  1743. // TODO
  1744. pData->engine->callback(ENGINE_CALLBACK_UPDATE, pData->id, -1, 0, 0.0f, nullptr);
  1745. break;
  1746. case ::HOST_OPCODE_RELOAD_PARAMETERS:
  1747. reload(); // FIXME
  1748. pData->engine->callback(ENGINE_CALLBACK_RELOAD_PARAMETERS, pData->id, -1, 0, 0.0f, nullptr);
  1749. break;
  1750. case ::HOST_OPCODE_RELOAD_MIDI_PROGRAMS:
  1751. reloadPrograms(false);
  1752. pData->engine->callback(ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, -1, 0, 0.0f, nullptr);
  1753. break;
  1754. case ::HOST_OPCODE_RELOAD_ALL:
  1755. reload();
  1756. pData->engine->callback(ENGINE_CALLBACK_RELOAD_ALL, pData->id, -1, 0, 0.0f, nullptr);
  1757. break;
  1758. case ::HOST_OPCODE_UI_UNAVAILABLE:
  1759. pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0.0f, nullptr);
  1760. break;
  1761. }
  1762. return ret;
  1763. // unused for now
  1764. (void)index;
  1765. (void)value;
  1766. (void)ptr;
  1767. (void)opt;
  1768. }
  1769. // -------------------------------------------------------------------
  1770. public:
  1771. static size_t getPluginCount() noexcept
  1772. {
  1773. return gPluginDescriptors.count();
  1774. }
  1775. static const NativePluginDescriptor* getPluginDescriptor(const size_t index) noexcept
  1776. {
  1777. CARLA_SAFE_ASSERT_RETURN(index < gPluginDescriptors.count(), nullptr);
  1778. return gPluginDescriptors.getAt(index, nullptr);
  1779. }
  1780. // -------------------------------------------------------------------
  1781. void* getNativeHandle() const noexcept override
  1782. {
  1783. return fHandle;
  1784. }
  1785. const void* getNativeDescriptor() const noexcept override
  1786. {
  1787. return fDescriptor;
  1788. }
  1789. // -------------------------------------------------------------------
  1790. bool init(const char* const name, const char* const label)
  1791. {
  1792. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  1793. // ---------------------------------------------------------------
  1794. // first checks
  1795. if (pData->client != nullptr)
  1796. {
  1797. pData->engine->setLastError("Plugin client is already registered");
  1798. return false;
  1799. }
  1800. if (label == nullptr && label[0] != '\0')
  1801. {
  1802. pData->engine->setLastError("null label");
  1803. return false;
  1804. }
  1805. // ---------------------------------------------------------------
  1806. // get descriptor that matches label
  1807. for (LinkedList<const NativePluginDescriptor*>::Itenerator it = gPluginDescriptors.begin(); it.valid(); it.next())
  1808. {
  1809. fDescriptor = it.getValue();
  1810. CARLA_SAFE_ASSERT_BREAK(fDescriptor != nullptr);
  1811. carla_debug("Check vs \"%s\"", fDescriptor->label);
  1812. if (fDescriptor->label != nullptr && std::strcmp(fDescriptor->label, label) == 0)
  1813. break;
  1814. fDescriptor = nullptr;
  1815. }
  1816. if (fDescriptor == nullptr)
  1817. {
  1818. pData->engine->setLastError("Invalid internal plugin");
  1819. return false;
  1820. }
  1821. // ---------------------------------------------------------------
  1822. // set icon
  1823. if (std::strcmp(fDescriptor->label, "audiofile") == 0)
  1824. pData->iconName = carla_strdup_safe("file");
  1825. else if (std::strcmp(fDescriptor->label, "midifile") == 0)
  1826. pData->iconName = carla_strdup_safe("file");
  1827. // ---------------------------------------------------------------
  1828. // get info
  1829. if (name != nullptr && name[0] != '\0')
  1830. pData->name = pData->engine->getUniquePluginName(name);
  1831. else if (fDescriptor->name != nullptr && fDescriptor->name[0] != '\0')
  1832. pData->name = pData->engine->getUniquePluginName(fDescriptor->name);
  1833. else
  1834. pData->name = pData->engine->getUniquePluginName(label);
  1835. {
  1836. CARLA_ASSERT(fHost.uiName == nullptr);
  1837. char uiName[std::strlen(pData->name)+6+1];
  1838. std::strcpy(uiName, pData->name);
  1839. std::strcat(uiName, " (GUI)");
  1840. fHost.uiName = carla_strdup(uiName);
  1841. }
  1842. // ---------------------------------------------------------------
  1843. // register client
  1844. pData->client = pData->engine->addClient(this);
  1845. if (pData->client == nullptr || ! pData->client->isOk())
  1846. {
  1847. pData->engine->setLastError("Failed to register plugin client");
  1848. return false;
  1849. }
  1850. // ---------------------------------------------------------------
  1851. // initialize plugin
  1852. fHandle = fDescriptor->instantiate(&fHost);
  1853. if (fHandle == nullptr)
  1854. {
  1855. pData->engine->setLastError("Plugin failed to initialize");
  1856. return false;
  1857. }
  1858. // ---------------------------------------------------------------
  1859. // set default options
  1860. const bool hasMidiProgs(fDescriptor->get_midi_program_count != nullptr && fDescriptor->get_midi_program_count(fHandle) > 0);
  1861. pData->options = 0x0;
  1862. if (hasMidiProgs && (fDescriptor->supports & ::PLUGIN_SUPPORTS_PROGRAM_CHANGES) == 0)
  1863. pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  1864. if (getMidiInCount() > 0 || (fDescriptor->hints & ::PLUGIN_NEEDS_FIXED_BUFFERS) != 0)
  1865. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  1866. if (pData->engine->getOptions().forceStereo)
  1867. pData->options |= PLUGIN_OPTION_FORCE_STEREO;
  1868. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_CHANNEL_PRESSURE)
  1869. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  1870. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_NOTE_AFTERTOUCH)
  1871. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  1872. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_PITCHBEND)
  1873. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  1874. if (fDescriptor->supports & ::PLUGIN_SUPPORTS_ALL_SOUND_OFF)
  1875. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  1876. return true;
  1877. }
  1878. private:
  1879. NativePluginHandle fHandle;
  1880. NativePluginHandle fHandle2;
  1881. NativeHostDescriptor fHost;
  1882. const NativePluginDescriptor* fDescriptor;
  1883. bool fIsProcessing;
  1884. bool fIsUiVisible;
  1885. float** fAudioInBuffers;
  1886. float** fAudioOutBuffers;
  1887. uint32_t fMidiEventCount;
  1888. NativeMidiEvent fMidiEvents[kPluginMaxMidiEvents*2];
  1889. int32_t fCurMidiProgs[MAX_MIDI_CHANNELS];
  1890. NativePluginMidiData fMidiIn;
  1891. NativePluginMidiData fMidiOut;
  1892. NativeTimeInfo fTimeInfo;
  1893. // -------------------------------------------------------------------
  1894. #define handlePtr ((NativePlugin*)handle)
  1895. static uint32_t carla_host_get_buffer_size(NativeHostHandle handle) noexcept
  1896. {
  1897. return handlePtr->handleGetBufferSize();
  1898. }
  1899. static double carla_host_get_sample_rate(NativeHostHandle handle) noexcept
  1900. {
  1901. return handlePtr->handleGetSampleRate();
  1902. }
  1903. static bool carla_host_is_offline(NativeHostHandle handle) noexcept
  1904. {
  1905. return handlePtr->handleIsOffline();
  1906. }
  1907. static const NativeTimeInfo* carla_host_get_time_info(NativeHostHandle handle) noexcept
  1908. {
  1909. return handlePtr->handleGetTimeInfo();
  1910. }
  1911. static bool carla_host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event)
  1912. {
  1913. return handlePtr->handleWriteMidiEvent(event);
  1914. }
  1915. static void carla_host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value)
  1916. {
  1917. handlePtr->handleUiParameterChanged(index, value);
  1918. }
  1919. static void carla_host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value)
  1920. {
  1921. handlePtr->handleUiCustomDataChanged(key, value);
  1922. }
  1923. static void carla_host_ui_closed(NativeHostHandle handle)
  1924. {
  1925. handlePtr->handleUiClosed();
  1926. }
  1927. static const char* carla_host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
  1928. {
  1929. return handlePtr->handleUiOpenFile(isDir, title, filter);
  1930. }
  1931. static const char* carla_host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
  1932. {
  1933. return handlePtr->handleUiSaveFile(isDir, title, filter);
  1934. }
  1935. static intptr_t carla_host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  1936. {
  1937. return handlePtr->handleDispatcher(opcode, index, value, ptr, opt);
  1938. }
  1939. #undef handlePtr
  1940. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePlugin)
  1941. };
  1942. // -----------------------------------------------------------------------
  1943. std::size_t CarlaPlugin::getNativePluginCount() noexcept
  1944. {
  1945. return NativePlugin::getPluginCount();
  1946. }
  1947. const NativePluginDescriptor* CarlaPlugin::getNativePluginDescriptor(const std::size_t index) noexcept
  1948. {
  1949. return NativePlugin::getPluginDescriptor(index);
  1950. }
  1951. // -----------------------------------------------------------------------
  1952. CarlaPlugin* CarlaPlugin::newNative(const Initializer& init)
  1953. {
  1954. carla_debug("CarlaPlugin::newNative({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId);
  1955. NativePlugin* const plugin(new NativePlugin(init.engine, init.id));
  1956. if (! plugin->init(init.name, init.label))
  1957. {
  1958. delete plugin;
  1959. return nullptr;
  1960. }
  1961. plugin->reload();
  1962. bool canRun = true;
  1963. if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  1964. {
  1965. if (! plugin->canRunInRack())
  1966. {
  1967. init.engine->setLastError("Carla's rack mode can only work with Mono or Stereo Internal plugins, sorry!");
  1968. canRun = false;
  1969. }
  1970. else if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0)
  1971. {
  1972. init.engine->setLastError("Carla's rack mode cannot work with plugins that have CV ports, sorry!");
  1973. canRun = false;
  1974. }
  1975. }
  1976. else if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_PATCHBAY && (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0))
  1977. {
  1978. init.engine->setLastError("CV ports in patchbay mode is still TODO");
  1979. canRun = false;
  1980. }
  1981. if (! canRun)
  1982. {
  1983. delete plugin;
  1984. return nullptr;
  1985. }
  1986. return plugin;
  1987. }
  1988. // -----------------------------------------------------------------------
  1989. CARLA_BACKEND_END_NAMESPACE