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

NativePlugin.cpp 87KB

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