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.

CarlaPluginNative.cpp 89KB

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