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