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.

DssiPlugin.cpp 67KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886
  1. /*
  2. * Carla DSSI Plugin
  3. * Copyright (C) 2011-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 GPL.txt file
  16. */
  17. #include "CarlaPluginInternal.hpp"
  18. #ifdef WANT_DSSI
  19. #include "CarlaLadspaUtils.hpp"
  20. #include "dssi/dssi.h"
  21. CARLA_BACKEND_START_NAMESPACE
  22. class DssiPlugin : public CarlaPlugin
  23. {
  24. public:
  25. DssiPlugin(CarlaEngine* const engine, const unsigned int id)
  26. : CarlaPlugin(engine, id),
  27. fHandle(nullptr),
  28. fHandle2(nullptr),
  29. fDescriptor(nullptr),
  30. fDssiDescriptor(nullptr),
  31. fAudioInBuffers(nullptr),
  32. fAudioOutBuffers(nullptr),
  33. fParamBuffers(nullptr)
  34. {
  35. carla_debug("DssiPlugin::DssiPlugin(%p, %i)", engine, id);
  36. carla_zeroMem(fMidiEvents, sizeof(snd_seq_event_t)*MAX_MIDI_EVENTS);
  37. kData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI);
  38. }
  39. ~DssiPlugin()
  40. {
  41. carla_debug("DssiPlugin::~DssiPlugin()");
  42. kData->singleMutex.lock();
  43. kData->masterMutex.lock();
  44. // close UI
  45. if (fHints & PLUGIN_HAS_GUI)
  46. {
  47. showGui(false);
  48. // Wait a bit first, then force kill
  49. if (kData->osc.thread.isRunning() && ! kData->osc.thread.stop(kData->engine->getOptions().oscUiTimeout))
  50. {
  51. carla_stderr("DSSI GUI thread still running, forcing termination now");
  52. kData->osc.thread.terminate();
  53. }
  54. }
  55. if (fDescriptor != nullptr)
  56. {
  57. if (fDescriptor->deactivate != nullptr && kData->activeBefore)
  58. {
  59. if (fHandle != nullptr)
  60. fDescriptor->deactivate(fHandle);
  61. if (fHandle2 != nullptr)
  62. fDescriptor->deactivate(fHandle2);
  63. }
  64. if (fDescriptor->cleanup != nullptr)
  65. {
  66. if (fHandle != nullptr)
  67. fDescriptor->cleanup(fHandle);
  68. if (fHandle2 != nullptr)
  69. fDescriptor->cleanup(fHandle2);
  70. }
  71. fHandle = nullptr;
  72. fHandle2 = nullptr;
  73. fDescriptor = nullptr;
  74. fDssiDescriptor = nullptr;
  75. }
  76. deleteBuffers();
  77. }
  78. // -------------------------------------------------------------------
  79. // Information (base)
  80. PluginType type() const
  81. {
  82. return PLUGIN_DSSI;
  83. }
  84. PluginCategory category()
  85. {
  86. if (fHints & PLUGIN_IS_SYNTH)
  87. return PLUGIN_CATEGORY_SYNTH;
  88. return getPluginCategoryFromName(fName);
  89. }
  90. long uniqueId() const
  91. {
  92. CARLA_ASSERT(fDescriptor != nullptr);
  93. return (fDescriptor != nullptr) ? static_cast<long>(fDescriptor->UniqueID) : 0;
  94. }
  95. // -------------------------------------------------------------------
  96. // Information (current data)
  97. int32_t chunkData(void** const dataPtr)
  98. {
  99. CARLA_ASSERT(fOptions & PLUGIN_OPTION_USE_CHUNKS);
  100. CARLA_ASSERT(fDssiDescriptor != nullptr);
  101. CARLA_ASSERT(fDssiDescriptor->get_custom_data != nullptr);
  102. CARLA_ASSERT(fHandle != nullptr);
  103. CARLA_ASSERT(fHandle2 == nullptr);
  104. CARLA_ASSERT(dataPtr != nullptr);
  105. unsigned long dataSize = 0;
  106. if (fDssiDescriptor->get_custom_data != nullptr && fDssiDescriptor->get_custom_data(fHandle, dataPtr, &dataSize))
  107. return (int32_t)dataSize;
  108. return 0;
  109. }
  110. // -------------------------------------------------------------------
  111. // Information (per-plugin data)
  112. unsigned int availableOptions()
  113. {
  114. CARLA_ASSERT(fDescriptor != nullptr);
  115. #ifdef __USE_GNU
  116. const bool isDssiVst = fFilename.contains("dssi-vst", true);
  117. const bool isZASX = fFilename.contains("zynaddsubfx", true);
  118. #else
  119. const bool isDssiVst = fFilename.contains("dssi-vst");
  120. const bool isZASX = fFilename.contains("zynaddsubfx");
  121. #endif
  122. unsigned int options = 0x0;
  123. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  124. //if ((kData->audioIns.count() == 1 || kData->audioOuts.count() == 0) || (kData->audioIns.count() == 0 || kData->audioOuts.count() == 1))
  125. // options |= PLUGIN_OPTION_FORCE_STEREO;
  126. if (isDssiVst)
  127. {
  128. if (fDescriptor != nullptr && fDssiDescriptor->get_custom_data != nullptr && fDssiDescriptor->set_custom_data != nullptr)
  129. options |= PLUGIN_OPTION_USE_CHUNKS;
  130. }
  131. else if (! isZASX)
  132. {
  133. options |= PLUGIN_OPTION_FIXED_BUFFER;
  134. }
  135. if (kData->extraHints & PLUGIN_HINT_HAS_MIDI_IN)
  136. {
  137. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  138. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  139. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  140. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  141. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  142. }
  143. return options;
  144. }
  145. float getParameterValue(const uint32_t parameterId)
  146. {
  147. CARLA_ASSERT(parameterId < kData->param.count);
  148. return fParamBuffers[parameterId];
  149. }
  150. void getLabel(char* const strBuf)
  151. {
  152. CARLA_ASSERT(fDescriptor != nullptr);
  153. if (fDescriptor != nullptr && fDescriptor->Label != nullptr)
  154. std::strncpy(strBuf, fDescriptor->Label, STR_MAX);
  155. else
  156. CarlaPlugin::getLabel(strBuf);
  157. }
  158. void getMaker(char* const strBuf)
  159. {
  160. CARLA_ASSERT(fDescriptor != nullptr);
  161. if (fDescriptor != nullptr && fDescriptor->Maker != nullptr)
  162. std::strncpy(strBuf, fDescriptor->Maker, STR_MAX);
  163. else
  164. CarlaPlugin::getMaker(strBuf);
  165. }
  166. void getCopyright(char* const strBuf)
  167. {
  168. CARLA_ASSERT(fDescriptor != nullptr);
  169. if (fDescriptor != nullptr && fDescriptor->Copyright != nullptr)
  170. std::strncpy(strBuf, fDescriptor->Copyright, STR_MAX);
  171. else
  172. CarlaPlugin::getCopyright(strBuf);
  173. }
  174. void getRealName(char* const strBuf)
  175. {
  176. CARLA_ASSERT(fDescriptor != nullptr);
  177. if (fDescriptor != nullptr && fDescriptor->Name != nullptr)
  178. std::strncpy(strBuf, fDescriptor->Name, STR_MAX);
  179. else
  180. CarlaPlugin::getRealName(strBuf);
  181. }
  182. void getParameterName(const uint32_t parameterId, char* const strBuf)
  183. {
  184. CARLA_ASSERT(fDescriptor != nullptr);
  185. CARLA_ASSERT(parameterId < kData->param.count);
  186. const int32_t rindex = kData->param.data[parameterId].rindex;
  187. if (fDescriptor != nullptr && rindex < static_cast<int32_t>(fDescriptor->PortCount))
  188. std::strncpy(strBuf, fDescriptor->PortNames[rindex], STR_MAX);
  189. else
  190. CarlaPlugin::getParameterName(parameterId, strBuf);
  191. }
  192. // -------------------------------------------------------------------
  193. // Set data (plugin-specific stuff)
  194. void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback)
  195. {
  196. CARLA_ASSERT(parameterId < kData->param.count);
  197. const float fixedValue = kData->param.fixValue(parameterId, value);
  198. fParamBuffers[parameterId] = fixedValue;
  199. CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
  200. }
  201. void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui)
  202. {
  203. carla_debug("DssiPlugin::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
  204. CARLA_ASSERT(fDescriptor != nullptr);
  205. CARLA_ASSERT(fHandle != nullptr);
  206. CARLA_ASSERT(type != nullptr);
  207. CARLA_ASSERT(key != nullptr);
  208. CARLA_ASSERT(value != nullptr);
  209. if (type == nullptr)
  210. return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is invalid", type, key, value, bool2str(sendGui));
  211. if (std::strcmp(type, CUSTOM_DATA_STRING) != 0)
  212. return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
  213. if (key == nullptr)
  214. return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - key is null", type, key, value, bool2str(sendGui));
  215. if (value == nullptr)
  216. return carla_stderr2("DssiPlugin::setCustomData(\"%s\", \"%s\", \"%s\", %s) - value is null", type, key, value, bool2str(sendGui));
  217. if (fDssiDescriptor->configure != nullptr)
  218. {
  219. fDssiDescriptor->configure(fHandle, key, value);
  220. if (fHandle2)
  221. fDssiDescriptor->configure(fHandle2, key, value);
  222. }
  223. if (sendGui && kData->osc.data.target != nullptr)
  224. osc_send_configure(&kData->osc.data, key, value);
  225. if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0)
  226. {
  227. const ScopedDisabler sd(this);
  228. reloadPrograms(false);
  229. }
  230. CarlaPlugin::setCustomData(type, key, value, sendGui);
  231. }
  232. void setChunkData(const char* const stringData)
  233. {
  234. CARLA_ASSERT(fOptions & PLUGIN_OPTION_USE_CHUNKS);
  235. CARLA_ASSERT(fDssiDescriptor != nullptr);
  236. CARLA_ASSERT(fDssiDescriptor->set_custom_data != nullptr);
  237. CARLA_ASSERT(fHandle != nullptr);
  238. CARLA_ASSERT(fHandle2 == nullptr);
  239. CARLA_ASSERT(stringData != nullptr);
  240. if (fDssiDescriptor->set_custom_data == nullptr)
  241. return;
  242. // FIXME
  243. fChunk = QByteArray::fromBase64(QByteArray(stringData));
  244. //fChunk.toBase64();
  245. const ScopedProcessLocker spl(this, true);
  246. fDssiDescriptor->set_custom_data(fHandle, fChunk.data(), (unsigned long)fChunk.size());
  247. }
  248. void setMidiProgram(int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback)
  249. {
  250. CARLA_ASSERT(fDssiDescriptor != nullptr);
  251. CARLA_ASSERT(fHandle != nullptr);
  252. CARLA_ASSERT(index >= -1 && index < static_cast<int32_t>(kData->midiprog.count));
  253. if (index < -1)
  254. index = -1;
  255. else if (index > static_cast<int32_t>(kData->midiprog.count))
  256. return;
  257. if (fDssiDescriptor != nullptr && fHandle != nullptr && index >= 0)
  258. {
  259. const uint32_t bank = kData->midiprog.data[index].bank;
  260. const uint32_t program = kData->midiprog.data[index].program;
  261. const ScopedProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
  262. fDssiDescriptor->select_program(fHandle, bank, program);
  263. if (fHandle2 != nullptr)
  264. fDssiDescriptor->select_program(fHandle2, bank, program);
  265. }
  266. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback);
  267. }
  268. // -------------------------------------------------------------------
  269. // Set gui stuff
  270. void showGui(const bool yesNo)
  271. {
  272. if (yesNo)
  273. {
  274. kData->osc.thread.start();
  275. }
  276. else
  277. {
  278. if (kData->osc.data.target != nullptr)
  279. {
  280. osc_send_hide(&kData->osc.data);
  281. osc_send_quit(&kData->osc.data);
  282. kData->osc.data.free();
  283. }
  284. if (kData->osc.thread.isRunning() && ! kData->osc.thread.stop(kData->engine->getOptions().oscUiTimeout))
  285. kData->osc.thread.terminate();
  286. }
  287. }
  288. // -------------------------------------------------------------------
  289. // Plugin state
  290. void reload()
  291. {
  292. carla_debug("DssiPlugin::reload() - start");
  293. CARLA_ASSERT(kData->engine != nullptr);
  294. CARLA_ASSERT(fDescriptor != nullptr);
  295. CARLA_ASSERT(fHandle != nullptr);
  296. const ProcessMode processMode(kData->engine->getProccessMode());
  297. // Safely disable plugin for reload
  298. const ScopedDisabler sd(this);
  299. deleteBuffers();
  300. const float sampleRate = (float)kData->engine->getSampleRate();
  301. const uint32_t portCount = static_cast<uint32_t>(fDescriptor->PortCount);
  302. uint32_t aIns, aOuts, mIns, params, j;
  303. aIns = aOuts = mIns = params = 0;
  304. bool forcedStereoIn, forcedStereoOut;
  305. forcedStereoIn = forcedStereoOut = false;
  306. bool needsCtrlIn, needsCtrlOut;
  307. needsCtrlIn = needsCtrlOut = false;
  308. if (portCount > 0)
  309. {
  310. CARLA_ASSERT(fDescriptor->PortDescriptors != nullptr);
  311. CARLA_ASSERT(fDescriptor->PortRangeHints != nullptr);
  312. CARLA_ASSERT(fDescriptor->PortNames != nullptr);
  313. for (uint32_t i=0; i < portCount; i++)
  314. {
  315. const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i];
  316. if (LADSPA_IS_PORT_AUDIO(portType))
  317. {
  318. if (LADSPA_IS_PORT_INPUT(portType))
  319. aIns += 1;
  320. else if (LADSPA_IS_PORT_OUTPUT(portType))
  321. aOuts += 1;
  322. }
  323. else if (LADSPA_IS_PORT_CONTROL(portType))
  324. params += 1;
  325. }
  326. }
  327. if ((fOptions & PLUGIN_OPTION_FORCE_STEREO) != 0 && (aIns == 1 || aOuts == 1))
  328. {
  329. if (fHandle2 == nullptr)
  330. fHandle2 = fDescriptor->instantiate(fDescriptor, (unsigned long)sampleRate);
  331. if (aIns == 1)
  332. {
  333. aIns = 2;
  334. forcedStereoIn = true;
  335. }
  336. if (aOuts == 1)
  337. {
  338. aOuts = 2;
  339. forcedStereoOut = true;
  340. }
  341. }
  342. if (fDssiDescriptor->run_synth != nullptr || fDssiDescriptor->run_multiple_synths != nullptr)
  343. {
  344. mIns = 1;
  345. needsCtrlIn = true;
  346. }
  347. if (aIns > 0)
  348. {
  349. kData->audioIn.createNew(aIns);
  350. fAudioInBuffers = new float*[aIns];
  351. for (uint32_t i=0; i < aIns; i++)
  352. fAudioInBuffers[i] = nullptr;
  353. }
  354. if (aOuts > 0)
  355. {
  356. kData->audioOut.createNew(aOuts);
  357. fAudioOutBuffers = new float*[aOuts];
  358. needsCtrlIn = true;
  359. for (uint32_t i=0; i < aOuts; i++)
  360. fAudioOutBuffers[i] = nullptr;
  361. }
  362. if (params > 0)
  363. {
  364. kData->param.createNew(params);
  365. fParamBuffers = new float[params];
  366. for (uint32_t i=0; i < params; i++)
  367. fParamBuffers[i] = 0.0f;
  368. }
  369. const uint portNameSize = kData->engine->maxPortNameSize();
  370. CarlaString portName;
  371. for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCtrl=0; i < portCount; i++)
  372. {
  373. const LADSPA_PortDescriptor portType = fDescriptor->PortDescriptors[i];
  374. const LADSPA_PortRangeHint portRangeHints = fDescriptor->PortRangeHints[i];
  375. CARLA_ASSERT(fDescriptor->PortNames[i] != nullptr);
  376. if (LADSPA_IS_PORT_AUDIO(portType))
  377. {
  378. portName.clear();
  379. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  380. {
  381. portName = fName;
  382. portName += ":";
  383. }
  384. portName += fDescriptor->PortNames[i];
  385. portName.truncate(portNameSize);
  386. if (LADSPA_IS_PORT_INPUT(portType))
  387. {
  388. j = iAudioIn++;
  389. kData->audioIn.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  390. kData->audioIn.ports[j].rindex = i;
  391. if (forcedStereoIn)
  392. {
  393. portName += "_2";
  394. kData->audioIn.ports[1].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, true);
  395. kData->audioIn.ports[1].rindex = i;
  396. }
  397. }
  398. else if (LADSPA_IS_PORT_OUTPUT(portType))
  399. {
  400. j = iAudioOut++;
  401. kData->audioOut.ports[j].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  402. kData->audioOut.ports[j].rindex = i;
  403. if (forcedStereoOut)
  404. {
  405. portName += "_2";
  406. kData->audioOut.ports[1].port = (CarlaEngineAudioPort*)kData->client->addPort(kEnginePortTypeAudio, portName, false);
  407. kData->audioOut.ports[1].rindex = i;
  408. }
  409. }
  410. else
  411. carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
  412. }
  413. else if (LADSPA_IS_PORT_CONTROL(portType))
  414. {
  415. j = iCtrl++;
  416. kData->param.data[j].index = j;
  417. kData->param.data[j].rindex = i;
  418. kData->param.data[j].hints = 0x0;
  419. kData->param.data[j].midiChannel = 0;
  420. kData->param.data[j].midiCC = -1;
  421. float min, max, def, step, stepSmall, stepLarge;
  422. // min value
  423. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  424. min = portRangeHints.LowerBound;
  425. else
  426. min = 0.0f;
  427. // max value
  428. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  429. max = portRangeHints.UpperBound;
  430. else
  431. max = 1.0f;
  432. if (min > max)
  433. max = min;
  434. else if (max < min)
  435. min = max;
  436. if (max - min == 0.0f)
  437. {
  438. carla_stderr2("WARNING - Broken plugin parameter '%s': max - min == 0.0f", fDescriptor->PortNames[i]);
  439. max = min + 0.1f;
  440. }
  441. // default value
  442. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  443. if (def < min)
  444. def = min;
  445. else if (def > max)
  446. def = max;
  447. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  448. {
  449. min *= sampleRate;
  450. max *= sampleRate;
  451. def *= sampleRate;
  452. kData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
  453. }
  454. if (LADSPA_IS_HINT_TOGGLED(portRangeHints.HintDescriptor))
  455. {
  456. step = max - min;
  457. stepSmall = step;
  458. stepLarge = step;
  459. kData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  460. }
  461. else if (LADSPA_IS_HINT_INTEGER(portRangeHints.HintDescriptor))
  462. {
  463. step = 1.0f;
  464. stepSmall = 1.0f;
  465. stepLarge = 10.0f;
  466. kData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  467. }
  468. else
  469. {
  470. float range = max - min;
  471. step = range/100.0f;
  472. stepSmall = range/1000.0f;
  473. stepLarge = range/10.0f;
  474. }
  475. if (LADSPA_IS_PORT_INPUT(portType))
  476. {
  477. kData->param.data[j].type = PARAMETER_INPUT;
  478. kData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  479. kData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  480. needsCtrlIn = true;
  481. // MIDI CC value
  482. if (fDssiDescriptor->get_midi_controller_for_port != nullptr)
  483. {
  484. int controller = fDssiDescriptor->get_midi_controller_for_port(fHandle, i);
  485. if (DSSI_CONTROLLER_IS_SET(controller) && DSSI_IS_CC(controller))
  486. {
  487. int16_t cc = DSSI_CC_NUMBER(controller);
  488. if (! MIDI_IS_CONTROL_BANK_SELECT(cc))
  489. kData->param.data[j].midiCC = cc;
  490. }
  491. }
  492. }
  493. else if (LADSPA_IS_PORT_OUTPUT(portType))
  494. {
  495. if (std::strcmp(fDescriptor->PortNames[i], "latency") == 0 || std::strcmp(fDescriptor->PortNames[i], "_latency") == 0)
  496. {
  497. min = 0.0f;
  498. max = sampleRate;
  499. def = 0.0f;
  500. step = 1.0f;
  501. stepSmall = 1.0f;
  502. stepLarge = 1.0f;
  503. kData->param.data[j].type = PARAMETER_LATENCY;
  504. kData->param.data[j].hints = 0;
  505. }
  506. else if (std::strcmp(fDescriptor->PortNames[i], "_sample-rate") == 0)
  507. {
  508. def = sampleRate;
  509. step = 1.0f;
  510. stepSmall = 1.0f;
  511. stepLarge = 1.0f;
  512. kData->param.data[j].type = PARAMETER_SAMPLE_RATE;
  513. kData->param.data[j].hints = 0;
  514. }
  515. else
  516. {
  517. kData->param.data[j].type = PARAMETER_OUTPUT;
  518. kData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  519. kData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
  520. needsCtrlOut = true;
  521. }
  522. }
  523. else
  524. {
  525. kData->param.data[j].type = PARAMETER_UNKNOWN;
  526. carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
  527. }
  528. // extra parameter hints
  529. if (LADSPA_IS_HINT_LOGARITHMIC(portRangeHints.HintDescriptor))
  530. kData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
  531. kData->param.ranges[j].min = min;
  532. kData->param.ranges[j].max = max;
  533. kData->param.ranges[j].def = def;
  534. kData->param.ranges[j].step = step;
  535. kData->param.ranges[j].stepSmall = stepSmall;
  536. kData->param.ranges[j].stepLarge = stepLarge;
  537. // Start parameters in their default values
  538. fParamBuffers[j] = def;
  539. fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]);
  540. if (fHandle2 != nullptr)
  541. fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]);
  542. }
  543. else
  544. {
  545. // Not Audio or Control
  546. carla_stderr2("ERROR - Got a broken Port (neither Audio or Control)");
  547. fDescriptor->connect_port(fHandle, i, nullptr);
  548. if (fHandle2 != nullptr)
  549. fDescriptor->connect_port(fHandle2, i, nullptr);
  550. }
  551. }
  552. if (needsCtrlIn)
  553. {
  554. portName.clear();
  555. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  556. {
  557. portName = fName;
  558. portName += ":";
  559. }
  560. portName += "event-in";
  561. portName.truncate(portNameSize);
  562. kData->event.portIn = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, true);
  563. }
  564. if (needsCtrlOut)
  565. {
  566. portName.clear();
  567. if (processMode == PROCESS_MODE_SINGLE_CLIENT)
  568. {
  569. portName = fName;
  570. portName += ":";
  571. }
  572. portName += "event-out";
  573. portName.truncate(portNameSize);
  574. kData->event.portOut = (CarlaEngineEventPort*)kData->client->addPort(kEnginePortTypeEvent, portName, false);
  575. }
  576. // plugin hints
  577. const bool hasGUI = (fHints & PLUGIN_HAS_GUI);
  578. #ifdef __USE_GNU
  579. const bool isDssiVst = fFilename.contains("dssi-vst", true);
  580. const bool isZASX = fFilename.contains("zynaddsubfx", true);
  581. #else
  582. const bool isDssiVst = fFilename.contains("dssi-vst");
  583. const bool isZASX = fFilename.contains("zynaddsubfx");
  584. #endif
  585. fHints = 0x0;
  586. if (hasGUI)
  587. fHints |= PLUGIN_HAS_GUI;
  588. if (mIns == 1 && aIns == 0 && aOuts > 0)
  589. fHints |= PLUGIN_IS_SYNTH;
  590. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  591. fHints |= PLUGIN_CAN_DRYWET;
  592. if (aOuts > 0)
  593. fHints |= PLUGIN_CAN_VOLUME;
  594. if (aOuts >= 2 && aOuts % 2 == 0)
  595. fHints |= PLUGIN_CAN_BALANCE;
  596. // extra plugin hints
  597. kData->extraHints = 0x0;
  598. if (mIns > 0)
  599. kData->extraHints |= PLUGIN_HINT_HAS_MIDI_IN;
  600. if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0))
  601. kData->extraHints |= PLUGIN_HINT_CAN_RUN_RACK;
  602. // plugin options
  603. fOptions = 0x0;
  604. fOptions |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  605. if (forcedStereoIn || forcedStereoOut)
  606. fOptions |= PLUGIN_OPTION_FORCE_STEREO;
  607. if (isDssiVst)
  608. {
  609. fOptions |= PLUGIN_OPTION_FIXED_BUFFER;
  610. if (kData->engine->getOptions().useDssiVstChunks && fDssiDescriptor->get_custom_data != nullptr && fDssiDescriptor->set_custom_data != nullptr)
  611. fOptions |= PLUGIN_OPTION_USE_CHUNKS;
  612. }
  613. else if (isZASX)
  614. {
  615. fOptions |= PLUGIN_OPTION_FIXED_BUFFER;
  616. }
  617. if (mIns > 0)
  618. {
  619. fOptions |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  620. fOptions |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  621. fOptions |= PLUGIN_OPTION_SEND_PITCHBEND;
  622. fOptions |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  623. }
  624. // check latency
  625. if (fHints & PLUGIN_CAN_DRYWET)
  626. {
  627. for (uint32_t i=0; i < kData->param.count; i++)
  628. {
  629. if (kData->param.data[i].type != PARAMETER_LATENCY)
  630. continue;
  631. // we need to pre-run the plugin so it can update its latency control-port
  632. float tmpIn[aIns][2];
  633. float tmpOut[aOuts][2];
  634. for (j=0; j < aIns; j++)
  635. {
  636. tmpIn[j][0] = 0.0f;
  637. tmpIn[j][1] = 0.0f;
  638. fDescriptor->connect_port(fHandle, kData->audioIn.ports[j].rindex, tmpIn[j]);
  639. }
  640. for (j=0; j < aOuts; j++)
  641. {
  642. tmpOut[j][0] = 0.0f;
  643. tmpOut[j][1] = 0.0f;
  644. fDescriptor->connect_port(fHandle, kData->audioOut.ports[j].rindex, tmpOut[j]);
  645. }
  646. if (fDescriptor->activate != nullptr)
  647. fDescriptor->activate(fHandle);
  648. fDescriptor->run(fHandle, 2);
  649. if (fDescriptor->deactivate != nullptr)
  650. fDescriptor->deactivate(fHandle);
  651. const uint32_t latency = (uint32_t)fParamBuffers[i];
  652. if (kData->latency != latency)
  653. {
  654. kData->latency = latency;
  655. kData->client->setLatency(latency);
  656. recreateLatencyBuffers();
  657. }
  658. break;
  659. }
  660. }
  661. bufferSizeChanged(kData->engine->getBufferSize());
  662. reloadPrograms(true);
  663. carla_debug("DssiPlugin::reload() - end");
  664. }
  665. void reloadPrograms(const bool init)
  666. {
  667. carla_debug("DssiPlugin::reloadPrograms(%s)", bool2str(init));
  668. uint32_t i, oldCount = kData->midiprog.count;
  669. const int32_t current = kData->midiprog.current;
  670. // Delete old programs
  671. kData->midiprog.clear();
  672. // Query new programs
  673. uint32_t count = 0;
  674. if (fDssiDescriptor->get_program != nullptr && fDssiDescriptor->select_program != nullptr)
  675. {
  676. while (fDssiDescriptor->get_program(fHandle, count))
  677. count++;
  678. }
  679. if (count > 0)
  680. {
  681. kData->midiprog.createNew(count);
  682. // Update data
  683. for (i=0; i < count; i++)
  684. {
  685. const DSSI_Program_Descriptor* const pdesc = fDssiDescriptor->get_program(fHandle, i);
  686. CARLA_ASSERT(pdesc != nullptr);
  687. CARLA_ASSERT(pdesc->Name != nullptr);
  688. kData->midiprog.data[i].bank = static_cast<uint32_t>(pdesc->Bank);
  689. kData->midiprog.data[i].program = static_cast<uint32_t>(pdesc->Program);
  690. kData->midiprog.data[i].name = carla_strdup(pdesc->Name);
  691. }
  692. }
  693. #ifndef BUILD_BRIDGE
  694. // Update OSC Names
  695. if (kData->engine->isOscControlRegistered())
  696. {
  697. kData->engine->osc_send_control_set_midi_program_count(fId, count);
  698. for (i=0; i < count; i++)
  699. kData->engine->osc_send_control_set_midi_program_data(fId, i, kData->midiprog.data[i].bank, kData->midiprog.data[i].program, kData->midiprog.data[i].name);
  700. }
  701. #endif
  702. if (init)
  703. {
  704. if (count > 0)
  705. setMidiProgram(0, false, false, false);
  706. }
  707. else
  708. {
  709. // Check if current program is invalid
  710. bool programChanged = false;
  711. if (count == oldCount+1)
  712. {
  713. // one midi program added, probably created by user
  714. kData->midiprog.current = oldCount;
  715. programChanged = true;
  716. }
  717. else if (current < 0 && count > 0)
  718. {
  719. // programs exist now, but not before
  720. kData->midiprog.current = 0;
  721. programChanged = true;
  722. }
  723. else if (current >= 0 && count == 0)
  724. {
  725. // programs existed before, but not anymore
  726. kData->midiprog.current = -1;
  727. programChanged = true;
  728. }
  729. else if (current >= static_cast<int32_t>(count))
  730. {
  731. // current midi program > count
  732. kData->midiprog.current = 0;
  733. programChanged = true;
  734. }
  735. else
  736. {
  737. // no change
  738. kData->midiprog.current = current;
  739. }
  740. if (programChanged)
  741. setMidiProgram(kData->midiprog.current, true, true, true);
  742. kData->engine->callback(CALLBACK_RELOAD_PROGRAMS, fId, 0, 0, 0.0f, nullptr);
  743. }
  744. }
  745. // -------------------------------------------------------------------
  746. // Plugin processing
  747. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames)
  748. {
  749. uint32_t i, k;
  750. // --------------------------------------------------------------------------------------------------------
  751. // Check if active
  752. if (! kData->active)
  753. {
  754. // disable any output sound
  755. for (i=0; i < kData->audioOut.count; i++)
  756. carla_zeroFloat(outBuffer[i], frames);
  757. if (kData->activeBefore)
  758. {
  759. if (fDescriptor->deactivate != nullptr)
  760. {
  761. fDescriptor->deactivate(fHandle);
  762. if (fHandle2 != nullptr)
  763. fDescriptor->deactivate(fHandle2);
  764. }
  765. }
  766. kData->activeBefore = kData->active;
  767. return;
  768. }
  769. unsigned long midiEventCount = 0;
  770. // --------------------------------------------------------------------------------------------------------
  771. // Check if not active before
  772. if (kData->needsReset || ! kData->activeBefore)
  773. {
  774. if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  775. {
  776. for (unsigned char j=0, l=MAX_MIDI_CHANNELS; j < MAX_MIDI_CHANNELS; j++)
  777. {
  778. carla_zeroStruct<snd_seq_event_t>(fMidiEvents[j]);
  779. carla_zeroStruct<snd_seq_event_t>(fMidiEvents[j+l]);
  780. fMidiEvents[j].type = SND_SEQ_EVENT_CONTROLLER;
  781. fMidiEvents[j].data.control.channel = j;
  782. fMidiEvents[j].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
  783. fMidiEvents[j+l].type = SND_SEQ_EVENT_CONTROLLER;
  784. fMidiEvents[j+l].data.control.channel = j;
  785. fMidiEvents[j+l].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
  786. }
  787. midiEventCount = MAX_MIDI_CHANNELS*2;
  788. }
  789. if (kData->latency > 0)
  790. {
  791. for (i=0; i < kData->audioIn.count; i++)
  792. carla_zeroFloat(kData->latencyBuffers[i], kData->latency);
  793. }
  794. if (kData->activeBefore)
  795. {
  796. if (fDescriptor->deactivate != nullptr)
  797. {
  798. fDescriptor->deactivate(fHandle);
  799. if (fHandle2 != nullptr)
  800. fDescriptor->deactivate(fHandle2);
  801. }
  802. }
  803. if (fDescriptor->activate != nullptr)
  804. {
  805. fDescriptor->activate(fHandle);
  806. if (fHandle2 != nullptr)
  807. fDescriptor->activate(fHandle2);
  808. }
  809. kData->needsReset = false;
  810. }
  811. // --------------------------------------------------------------------------------------------------------
  812. // Event Input and Processing
  813. if (kData->event.portIn != nullptr && kData->activeBefore)
  814. {
  815. // ----------------------------------------------------------------------------------------------------
  816. // MIDI Input (External)
  817. if (kData->extNotes.mutex.tryLock())
  818. {
  819. while (midiEventCount < MAX_MIDI_EVENTS && ! kData->extNotes.data.isEmpty())
  820. {
  821. const ExternalMidiNote& note = kData->extNotes.data.getFirst(true);
  822. CARLA_ASSERT(note.channel >= 0);
  823. carla_zeroStruct<snd_seq_event_t>(fMidiEvents[midiEventCount]);
  824. fMidiEvents[midiEventCount].type = (note.velo > 0) ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
  825. fMidiEvents[midiEventCount].data.note.channel = note.channel;
  826. fMidiEvents[midiEventCount].data.note.note = note.note;
  827. fMidiEvents[midiEventCount].data.note.velocity = note.velo;
  828. midiEventCount += 1;
  829. }
  830. kData->extNotes.mutex.unlock();
  831. } // End of MIDI Input (External)
  832. // ----------------------------------------------------------------------------------------------------
  833. // Event Input (System)
  834. bool allNotesOffSent = false;
  835. bool sampleAccurate = (fOptions & PLUGIN_OPTION_FIXED_BUFFER) == 0;
  836. uint32_t time, nEvents = kData->event.portIn->getEventCount();
  837. uint32_t startTime = 0;
  838. uint32_t timeOffset = 0;
  839. uint32_t nextBankId = 0;
  840. if (kData->midiprog.current >= 0 && kData->midiprog.count > 0)
  841. nextBankId = kData->midiprog.data[kData->midiprog.current].bank;
  842. for (i=0; i < nEvents; i++)
  843. {
  844. const EngineEvent& event = kData->event.portIn->getEvent(i);
  845. time = event.time;
  846. if (time >= frames)
  847. continue;
  848. CARLA_ASSERT_INT2(time >= timeOffset, time, timeOffset);
  849. if (time > timeOffset && sampleAccurate)
  850. {
  851. if (processSingle(inBuffer, outBuffer, time - timeOffset, timeOffset, midiEventCount))
  852. {
  853. midiEventCount = 0;
  854. timeOffset = time;
  855. if (kData->midiprog.current >= 0 && kData->midiprog.count > 0)
  856. nextBankId = kData->midiprog.data[kData->midiprog.current].bank;
  857. else
  858. nextBankId = 0;
  859. }
  860. else
  861. startTime += timeOffset;
  862. }
  863. // Control change
  864. switch (event.type)
  865. {
  866. case kEngineEventTypeNull:
  867. break;
  868. case kEngineEventTypeControl:
  869. {
  870. const EngineControlEvent& ctrlEvent = event.ctrl;
  871. switch (ctrlEvent.type)
  872. {
  873. case kEngineControlEventTypeNull:
  874. break;
  875. case kEngineControlEventTypeParameter:
  876. {
  877. // Control backend stuff
  878. if (event.channel == kData->ctrlChannel)
  879. {
  880. float value;
  881. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (fHints & PLUGIN_CAN_DRYWET) > 0)
  882. {
  883. value = ctrlEvent.value;
  884. setDryWet(value, false, false);
  885. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_DRYWET, 0, value);
  886. continue;
  887. }
  888. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (fHints & PLUGIN_CAN_VOLUME) > 0)
  889. {
  890. value = ctrlEvent.value*127.0f/100.0f;
  891. setVolume(value, false, false);
  892. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_VOLUME, 0, value);
  893. continue;
  894. }
  895. if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (fHints & PLUGIN_CAN_BALANCE) > 0)
  896. {
  897. float left, right;
  898. value = ctrlEvent.value/0.5f - 1.0f;
  899. if (value < 0.0f)
  900. {
  901. left = -1.0f;
  902. right = (value*2.0f)+1.0f;
  903. }
  904. else if (value > 0.0f)
  905. {
  906. left = (value*2.0f)-1.0f;
  907. right = 1.0f;
  908. }
  909. else
  910. {
  911. left = -1.0f;
  912. right = 1.0f;
  913. }
  914. setBalanceLeft(left, false, false);
  915. setBalanceRight(right, false, false);
  916. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  917. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  918. continue;
  919. }
  920. }
  921. // Control plugin parameters
  922. for (k=0; k < kData->param.count; k++)
  923. {
  924. if (kData->param.data[k].midiChannel != event.channel)
  925. continue;
  926. if (kData->param.data[k].midiCC != ctrlEvent.param)
  927. continue;
  928. if (kData->param.data[k].type != PARAMETER_INPUT)
  929. continue;
  930. if ((kData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
  931. continue;
  932. float value;
  933. if (kData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
  934. {
  935. value = (ctrlEvent.value < 0.5f) ? kData->param.ranges[k].min : kData->param.ranges[k].max;
  936. }
  937. else
  938. {
  939. value = kData->param.ranges[i].unnormalizeValue(ctrlEvent.value);
  940. if (kData->param.data[k].hints & PARAMETER_IS_INTEGER)
  941. value = std::rint(value);
  942. }
  943. setParameterValue(k, value, false, false, false);
  944. postponeRtEvent(kPluginPostRtEventParameterChange, static_cast<int32_t>(k), 0, value);
  945. }
  946. break;
  947. }
  948. case kEngineControlEventTypeMidiBank:
  949. if (event.channel == kData->ctrlChannel)
  950. nextBankId = ctrlEvent.param;
  951. break;
  952. case kEngineControlEventTypeMidiProgram:
  953. if (event.channel == kData->ctrlChannel)
  954. {
  955. const uint32_t nextProgramId = ctrlEvent.param;
  956. for (k=0; k < kData->midiprog.count; k++)
  957. {
  958. if (kData->midiprog.data[k].bank == nextBankId && kData->midiprog.data[k].program == nextProgramId)
  959. {
  960. setMidiProgram(k, false, false, false);
  961. postponeRtEvent(kPluginPostRtEventMidiProgramChange, k, 0, 0.0f);
  962. break;
  963. }
  964. }
  965. }
  966. break;
  967. case kEngineControlEventTypeAllSoundOff:
  968. if (event.channel == kData->ctrlChannel)
  969. {
  970. if (! allNotesOffSent)
  971. {
  972. sendMidiAllNotesOff();
  973. allNotesOffSent = true;
  974. }
  975. if (fDescriptor->deactivate != nullptr)
  976. {
  977. fDescriptor->deactivate(fHandle);
  978. if (fHandle2 != nullptr)
  979. fDescriptor->deactivate(fHandle2);
  980. }
  981. if (fDescriptor->activate != nullptr)
  982. {
  983. fDescriptor->activate(fHandle);
  984. if (fHandle2 != nullptr)
  985. fDescriptor->activate(fHandle2);
  986. }
  987. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 0.0f);
  988. postponeRtEvent(kPluginPostRtEventParameterChange, PARAMETER_ACTIVE, 0, 1.0f);
  989. }
  990. if (midiEventCount >= MAX_MIDI_EVENTS)
  991. continue;
  992. if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  993. {
  994. carla_zeroStruct<snd_seq_event_t>(fMidiEvents[midiEventCount]);
  995. fMidiEvents[midiEventCount].time.tick = sampleAccurate ? startTime : time;
  996. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER;
  997. fMidiEvents[midiEventCount].data.control.channel = event.channel;
  998. fMidiEvents[midiEventCount].data.control.param = MIDI_CONTROL_ALL_SOUND_OFF;
  999. midiEventCount += 1;
  1000. }
  1001. break;
  1002. case kEngineControlEventTypeAllNotesOff:
  1003. if (event.channel == kData->ctrlChannel)
  1004. {
  1005. if (! allNotesOffSent)
  1006. {
  1007. allNotesOffSent = true;
  1008. sendMidiAllNotesOff();
  1009. }
  1010. }
  1011. if (midiEventCount >= MAX_MIDI_EVENTS)
  1012. continue;
  1013. if (fOptions & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  1014. {
  1015. carla_zeroStruct<snd_seq_event_t>(fMidiEvents[midiEventCount]);
  1016. fMidiEvents[midiEventCount].time.tick = sampleAccurate ? startTime : time;
  1017. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER;
  1018. fMidiEvents[midiEventCount].data.control.channel = event.channel;
  1019. fMidiEvents[midiEventCount].data.control.param = MIDI_CONTROL_ALL_NOTES_OFF;
  1020. midiEventCount += 1;
  1021. }
  1022. break;
  1023. }
  1024. break;
  1025. }
  1026. case kEngineEventTypeMidi:
  1027. {
  1028. if (midiEventCount >= MAX_MIDI_EVENTS)
  1029. continue;
  1030. const EngineMidiEvent& midiEvent = event.midi;
  1031. uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent.data);
  1032. uint8_t channel = event.channel;
  1033. // Fix bad note-off (per DSSI spec)
  1034. if (MIDI_IS_STATUS_NOTE_ON(status) && midiEvent.data[2] == 0)
  1035. status -= 0x10;
  1036. carla_zeroStruct<snd_seq_event_t>(fMidiEvents[midiEventCount]);
  1037. fMidiEvents[midiEventCount].time.tick = sampleAccurate ? startTime : time;
  1038. if (MIDI_IS_STATUS_NOTE_OFF(status))
  1039. {
  1040. const uint8_t note = midiEvent.data[1];
  1041. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_NOTEOFF;
  1042. fMidiEvents[midiEventCount].data.note.channel = channel;
  1043. fMidiEvents[midiEventCount].data.note.note = note;
  1044. postponeRtEvent(kPluginPostRtEventNoteOff, channel, note, 0.0f);
  1045. }
  1046. else if (MIDI_IS_STATUS_NOTE_ON(status))
  1047. {
  1048. const uint8_t note = midiEvent.data[1];
  1049. const uint8_t velo = midiEvent.data[2];
  1050. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_NOTEON;
  1051. fMidiEvents[midiEventCount].data.note.channel = channel;
  1052. fMidiEvents[midiEventCount].data.note.note = note;
  1053. fMidiEvents[midiEventCount].data.note.velocity = velo;
  1054. postponeRtEvent(kPluginPostRtEventNoteOn, channel, note, velo);
  1055. }
  1056. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) != 0)
  1057. {
  1058. const uint8_t note = midiEvent.data[1];
  1059. const uint8_t pressure = midiEvent.data[2];
  1060. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_KEYPRESS;
  1061. fMidiEvents[midiEventCount].data.note.channel = channel;
  1062. fMidiEvents[midiEventCount].data.note.note = note;
  1063. fMidiEvents[midiEventCount].data.note.velocity = pressure;
  1064. }
  1065. else if (MIDI_IS_STATUS_CONTROL_CHANGE(status) && (fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0)
  1066. {
  1067. const uint8_t control = midiEvent.data[1];
  1068. const uint8_t value = midiEvent.data[2];
  1069. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CONTROLLER;
  1070. fMidiEvents[midiEventCount].data.control.channel = channel;
  1071. fMidiEvents[midiEventCount].data.control.param = control;
  1072. fMidiEvents[midiEventCount].data.control.value = value;
  1073. }
  1074. else if (MIDI_IS_STATUS_AFTERTOUCH(status) && (fOptions & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) != 0)
  1075. {
  1076. const uint8_t pressure = midiEvent.data[1];
  1077. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_CHANPRESS;
  1078. fMidiEvents[midiEventCount].data.control.channel = channel;
  1079. fMidiEvents[midiEventCount].data.control.value = pressure;
  1080. }
  1081. else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status) && (fOptions & PLUGIN_OPTION_SEND_PITCHBEND) != 0)
  1082. {
  1083. const uint8_t lsb = midiEvent.data[1];
  1084. const uint8_t msb = midiEvent.data[2];
  1085. fMidiEvents[midiEventCount].type = SND_SEQ_EVENT_PITCHBEND;
  1086. fMidiEvents[midiEventCount].data.control.channel = channel;
  1087. fMidiEvents[midiEventCount].data.control.value = ((msb << 7) | lsb) - 8192;
  1088. }
  1089. else
  1090. continue;
  1091. midiEventCount += 1;
  1092. break;
  1093. }
  1094. }
  1095. }
  1096. kData->postRtEvents.trySplice();
  1097. if (frames > timeOffset)
  1098. processSingle(inBuffer, outBuffer, frames - timeOffset, timeOffset, midiEventCount);
  1099. } // End of Event Input and Processing
  1100. // --------------------------------------------------------------------------------------------------------
  1101. // Plugin processing (no events)
  1102. else
  1103. {
  1104. processSingle(inBuffer, outBuffer, frames, 0, midiEventCount);
  1105. } // End of Plugin processing (no events)
  1106. // --------------------------------------------------------------------------------------------------------
  1107. // Special Parameters
  1108. #if 0
  1109. CARLA_PROCESS_CONTINUE_CHECK;
  1110. for (k=0; k < param.count; k++)
  1111. {
  1112. if (param.data[k].type == PARAMETER_LATENCY)
  1113. {
  1114. // TODO
  1115. }
  1116. }
  1117. CARLA_PROCESS_CONTINUE_CHECK;
  1118. #endif
  1119. CARLA_PROCESS_CONTINUE_CHECK;
  1120. // --------------------------------------------------------------------------------------------------------
  1121. // Control Output
  1122. if (kData->event.portOut != nullptr)
  1123. {
  1124. uint8_t channel;
  1125. uint16_t param;
  1126. float value;
  1127. for (k=0; k < kData->param.count; k++)
  1128. {
  1129. if (kData->param.data[k].type != PARAMETER_OUTPUT)
  1130. continue;
  1131. kData->param.ranges[k].fixValue(fParamBuffers[k]);
  1132. if (kData->param.data[k].midiCC > 0)
  1133. {
  1134. channel = kData->param.data[k].midiChannel;
  1135. param = static_cast<uint16_t>(kData->param.data[k].midiCC);
  1136. value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]);
  1137. kData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter, param, value);
  1138. }
  1139. }
  1140. } // End of Control Output
  1141. // --------------------------------------------------------------------------------------------------------
  1142. kData->activeBefore = kData->active;
  1143. }
  1144. bool processSingle(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t timeOffset, const unsigned long midiEventCount)
  1145. {
  1146. uint32_t i, k;
  1147. // --------------------------------------------------------------------------------------------------------
  1148. // Try lock, silence otherwise
  1149. if (kData->engine->isOffline())
  1150. {
  1151. kData->singleMutex.lock();
  1152. }
  1153. else if (! kData->singleMutex.tryLock())
  1154. {
  1155. for (i=0; i < kData->audioOut.count; i++)
  1156. {
  1157. for (k=0; k < frames; k++)
  1158. outBuffer[i][k+timeOffset] = 0.0f;
  1159. }
  1160. return false;
  1161. }
  1162. // --------------------------------------------------------------------------------------------------------
  1163. // Fill plugin buffers
  1164. for (i=0; i < kData->audioIn.count; i++)
  1165. carla_copyFloat(fAudioInBuffers[i], inBuffer[i]+timeOffset, frames);
  1166. for (i=0; i < kData->audioOut.count; i++)
  1167. carla_zeroFloat(fAudioOutBuffers[i], frames);
  1168. // --------------------------------------------------------------------------------------------------------
  1169. // Run plugin
  1170. if (fDssiDescriptor->run_synth != nullptr)
  1171. {
  1172. fDssiDescriptor->run_synth(fHandle, frames, fMidiEvents, midiEventCount);
  1173. if (fHandle2 != nullptr)
  1174. fDssiDescriptor->run_synth(fHandle2, frames, fMidiEvents, midiEventCount);
  1175. }
  1176. else if (fDssiDescriptor->run_multiple_synths != nullptr)
  1177. {
  1178. unsigned long instances = (fHandle2 != nullptr) ? 2 : 1;
  1179. LADSPA_Handle handlePtr[2] = { fHandle, fHandle2 };
  1180. snd_seq_event_t* midiEventsPtr[2] = { fMidiEvents, fMidiEvents };
  1181. unsigned long midiEventCountPtr[2] = { midiEventCount, midiEventCount };
  1182. fDssiDescriptor->run_multiple_synths(instances, handlePtr, frames, midiEventsPtr, midiEventCountPtr);
  1183. }
  1184. else
  1185. {
  1186. fDescriptor->run(fHandle, frames);
  1187. if (fHandle2 != nullptr)
  1188. fDescriptor->run(fHandle2, frames);
  1189. }
  1190. // --------------------------------------------------------------------------------------------------------
  1191. // Post-processing (dry/wet, volume and balance)
  1192. {
  1193. const bool doDryWet = (fHints & PLUGIN_CAN_DRYWET) > 0 && kData->postProc.dryWet != 1.0f;
  1194. const bool doBalance = (fHints & PLUGIN_CAN_BALANCE) > 0 && (kData->postProc.balanceLeft != -1.0f || kData->postProc.balanceRight != 1.0f);
  1195. float bufValue, oldBufLeft[doBalance ? frames : 1];
  1196. for (i=0; i < kData->audioOut.count; i++)
  1197. {
  1198. // Dry/Wet
  1199. if (doDryWet)
  1200. {
  1201. for (k=0; k < frames; k++)
  1202. {
  1203. // TODO
  1204. //if (k < kData->latency && kData->latency < frames)
  1205. // bufValue = (kData->audioIn.count == 1) ? kData->latencyBuffers[0][k] : kData->latencyBuffers[i][k];
  1206. //else
  1207. // bufValue = (kData->audioIn.count == 1) ? inBuffer[0][k-m_latency] : inBuffer[i][k-m_latency];
  1208. bufValue = fAudioInBuffers[(kData->audioIn.count == 1) ? 0 : i][k];
  1209. fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * kData->postProc.dryWet) + (bufValue * (1.0f - kData->postProc.dryWet));
  1210. }
  1211. }
  1212. // Balance
  1213. if (doBalance)
  1214. {
  1215. if (i % 2 == 0)
  1216. carla_copyFloat(oldBufLeft, fAudioOutBuffers[i], frames);
  1217. float balRangeL = (kData->postProc.balanceLeft + 1.0f)/2.0f;
  1218. float balRangeR = (kData->postProc.balanceRight + 1.0f)/2.0f;
  1219. for (k=0; k < frames; k++)
  1220. {
  1221. if (i % 2 == 0)
  1222. {
  1223. // left
  1224. fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  1225. fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
  1226. }
  1227. else
  1228. {
  1229. // right
  1230. fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
  1231. fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  1232. }
  1233. }
  1234. }
  1235. // Volume (and buffer copy)
  1236. {
  1237. for (k=0; k < frames; k++)
  1238. outBuffer[i][k+timeOffset] = fAudioOutBuffers[i][k] * kData->postProc.volume;
  1239. }
  1240. }
  1241. #if 0
  1242. // Latency, save values for next callback, TODO
  1243. if (kData->latency > 0 && kData->latency < frames)
  1244. {
  1245. for (i=0; i < kData->audioIn.count; i++)
  1246. carla_copyFloat(kData->latencyBuffers[i], inBuffer[i] + (frames - kData->latency), kData->latency);
  1247. }
  1248. #endif
  1249. } // End of Post-processing
  1250. // --------------------------------------------------------------------------------------------------------
  1251. kData->singleMutex.unlock();
  1252. return true;
  1253. }
  1254. void bufferSizeChanged(const uint32_t newBufferSize)
  1255. {
  1256. carla_debug("DssiPlugin::bufferSizeChanged(%i) - start", newBufferSize);
  1257. for (uint32_t i=0; i < kData->audioIn.count; i++)
  1258. {
  1259. if (fAudioInBuffers[i] != nullptr)
  1260. delete[] fAudioInBuffers[i];
  1261. fAudioInBuffers[i] = new float[newBufferSize];
  1262. }
  1263. for (uint32_t i=0; i < kData->audioOut.count; i++)
  1264. {
  1265. if (fAudioOutBuffers[i] != nullptr)
  1266. delete[] fAudioOutBuffers[i];
  1267. fAudioOutBuffers[i] = new float[newBufferSize];
  1268. }
  1269. if (fHandle2 == nullptr)
  1270. {
  1271. for (uint32_t i=0; i < kData->audioIn.count; i++)
  1272. {
  1273. CARLA_ASSERT(fAudioInBuffers[i] != nullptr);
  1274. fDescriptor->connect_port(fHandle, kData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
  1275. }
  1276. for (uint32_t i=0; i < kData->audioOut.count; i++)
  1277. {
  1278. CARLA_ASSERT(fAudioOutBuffers[i] != nullptr);
  1279. fDescriptor->connect_port(fHandle, kData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
  1280. }
  1281. }
  1282. else
  1283. {
  1284. if (kData->audioIn.count > 0)
  1285. {
  1286. CARLA_ASSERT(kData->audioIn.count == 2);
  1287. CARLA_ASSERT(fAudioInBuffers[0] != nullptr);
  1288. CARLA_ASSERT(fAudioInBuffers[1] != nullptr);
  1289. fDescriptor->connect_port(fHandle, kData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
  1290. fDescriptor->connect_port(fHandle2, kData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
  1291. }
  1292. if (kData->audioOut.count > 0)
  1293. {
  1294. CARLA_ASSERT(kData->audioOut.count == 2);
  1295. CARLA_ASSERT(fAudioOutBuffers[0] != nullptr);
  1296. CARLA_ASSERT(fAudioOutBuffers[1] != nullptr);
  1297. fDescriptor->connect_port(fHandle, kData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
  1298. fDescriptor->connect_port(fHandle2, kData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
  1299. }
  1300. }
  1301. carla_debug("DssiPlugin::bufferSizeChanged(%i) - start", newBufferSize);
  1302. }
  1303. // -------------------------------------------------------------------
  1304. // Post-poned events
  1305. void uiParameterChange(const uint32_t index, const float value)
  1306. {
  1307. CARLA_ASSERT(index < kData->param.count);
  1308. if (index >= kData->param.count)
  1309. return;
  1310. if (kData->osc.data.target == nullptr)
  1311. return;
  1312. osc_send_control(&kData->osc.data, kData->param.data[index].rindex, value);
  1313. }
  1314. void uiMidiProgramChange(const uint32_t index)
  1315. {
  1316. CARLA_ASSERT(index < kData->midiprog.count);
  1317. if (index >= kData->midiprog.count)
  1318. return;
  1319. if (kData->osc.data.target == nullptr)
  1320. return;
  1321. osc_send_program(&kData->osc.data, kData->midiprog.data[index].bank, kData->midiprog.data[index].program);
  1322. }
  1323. void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo)
  1324. {
  1325. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1326. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  1327. CARLA_ASSERT(velo > 0 && velo < MAX_MIDI_VALUE);
  1328. if (channel >= MAX_MIDI_CHANNELS)
  1329. return;
  1330. if (note >= MAX_MIDI_NOTE)
  1331. return;
  1332. if (velo >= MAX_MIDI_VALUE)
  1333. return;
  1334. if (kData->osc.data.target == nullptr)
  1335. return;
  1336. uint8_t midiData[4] = { 0 };
  1337. midiData[1] = MIDI_STATUS_NOTE_ON + channel;
  1338. midiData[2] = note;
  1339. midiData[3] = velo;
  1340. osc_send_midi(&kData->osc.data, midiData);
  1341. }
  1342. void uiNoteOff(const uint8_t channel, const uint8_t note)
  1343. {
  1344. CARLA_ASSERT(channel < MAX_MIDI_CHANNELS);
  1345. CARLA_ASSERT(note < MAX_MIDI_NOTE);
  1346. if (channel >= MAX_MIDI_CHANNELS)
  1347. return;
  1348. if (note >= MAX_MIDI_NOTE)
  1349. return;
  1350. if (kData->osc.data.target == nullptr)
  1351. return;
  1352. uint8_t midiData[4] = { 0 };
  1353. midiData[1] = MIDI_STATUS_NOTE_OFF + channel;
  1354. midiData[2] = note;
  1355. osc_send_midi(&kData->osc.data, midiData);
  1356. }
  1357. // -------------------------------------------------------------------
  1358. // Cleanup
  1359. void deleteBuffers()
  1360. {
  1361. carla_debug("DssiPlugin::deleteBuffers() - start");
  1362. if (fAudioInBuffers != nullptr)
  1363. {
  1364. for (uint32_t i=0; i < kData->audioIn.count; i++)
  1365. {
  1366. if (fAudioInBuffers[i] != nullptr)
  1367. {
  1368. delete[] fAudioInBuffers[i];
  1369. fAudioInBuffers[i] = nullptr;
  1370. }
  1371. }
  1372. delete[] fAudioInBuffers;
  1373. fAudioInBuffers = nullptr;
  1374. }
  1375. if (fAudioOutBuffers != nullptr)
  1376. {
  1377. for (uint32_t i=0; i < kData->audioOut.count; i++)
  1378. {
  1379. if (fAudioOutBuffers[i] != nullptr)
  1380. {
  1381. delete[] fAudioOutBuffers[i];
  1382. fAudioOutBuffers[i] = nullptr;
  1383. }
  1384. }
  1385. delete[] fAudioOutBuffers;
  1386. fAudioOutBuffers = nullptr;
  1387. }
  1388. if (fParamBuffers != nullptr)
  1389. {
  1390. delete[] fParamBuffers;
  1391. fParamBuffers = nullptr;
  1392. }
  1393. CarlaPlugin::deleteBuffers();
  1394. carla_debug("DssiPlugin::deleteBuffers() - end");
  1395. }
  1396. // -------------------------------------------------------------------
  1397. bool init(const char* const filename, const char* const name, const char* const label, const char* const guiFilename)
  1398. {
  1399. CARLA_ASSERT(kData->engine != nullptr);
  1400. CARLA_ASSERT(kData->client == nullptr);
  1401. CARLA_ASSERT(filename != nullptr);
  1402. CARLA_ASSERT(label != nullptr);
  1403. // ---------------------------------------------------------------
  1404. // open DLL
  1405. if (! libOpen(filename))
  1406. {
  1407. kData->engine->setLastError(libError(filename));
  1408. return false;
  1409. }
  1410. // ---------------------------------------------------------------
  1411. // get DLL main entry
  1412. const DSSI_Descriptor_Function descFn = (DSSI_Descriptor_Function)libSymbol("dssi_descriptor");
  1413. if (descFn == nullptr)
  1414. {
  1415. kData->engine->setLastError("Could not find the DSSI Descriptor in the plugin library");
  1416. return false;
  1417. }
  1418. // ---------------------------------------------------------------
  1419. // get descriptor that matches label
  1420. unsigned long i = 0;
  1421. while ((fDssiDescriptor = descFn(i++)) != nullptr)
  1422. {
  1423. fDescriptor = fDssiDescriptor->LADSPA_Plugin;
  1424. if (fDescriptor != nullptr && fDescriptor->Label != nullptr && std::strcmp(fDescriptor->Label, label) == 0)
  1425. break;
  1426. }
  1427. if (fDescriptor == nullptr || fDssiDescriptor == nullptr)
  1428. {
  1429. kData->engine->setLastError("Could not find the requested plugin label in the plugin library");
  1430. return false;
  1431. }
  1432. // ---------------------------------------------------------------
  1433. // get info
  1434. if (name != nullptr)
  1435. fName = kData->engine->getNewUniquePluginName(name);
  1436. else if (fDescriptor->Name != nullptr)
  1437. fName = kData->engine->getNewUniquePluginName(fDescriptor->Name);
  1438. else
  1439. fName = kData->engine->getNewUniquePluginName(fDescriptor->Label);
  1440. fFilename = filename;
  1441. // ---------------------------------------------------------------
  1442. // register client
  1443. kData->client = kData->engine->addClient(this);
  1444. if (kData->client == nullptr || ! kData->client->isOk())
  1445. {
  1446. kData->engine->setLastError("Failed to register plugin client");
  1447. return false;
  1448. }
  1449. // ---------------------------------------------------------------
  1450. // initialize plugin
  1451. fHandle = fDescriptor->instantiate(fDescriptor, (unsigned long)kData->engine->getSampleRate());
  1452. if (fHandle == nullptr)
  1453. {
  1454. kData->engine->setLastError("Plugin failed to initialize");
  1455. return false;
  1456. }
  1457. // ---------------------------------------------------------------
  1458. // gui stuff
  1459. if (guiFilename != nullptr)
  1460. {
  1461. kData->osc.thread.setOscData(guiFilename, fDescriptor->Label);
  1462. fHints |= PLUGIN_HAS_GUI;
  1463. }
  1464. return true;
  1465. }
  1466. private:
  1467. LADSPA_Handle fHandle;
  1468. LADSPA_Handle fHandle2;
  1469. const LADSPA_Descriptor* fDescriptor;
  1470. const DSSI_Descriptor* fDssiDescriptor;
  1471. float** fAudioInBuffers;
  1472. float** fAudioOutBuffers;
  1473. float* fParamBuffers;
  1474. snd_seq_event_t fMidiEvents[MAX_MIDI_EVENTS];
  1475. QByteArray fChunk;
  1476. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DssiPlugin)
  1477. };
  1478. CARLA_BACKEND_END_NAMESPACE
  1479. #else // WANT_DSSI
  1480. # warning Building without DSSI support
  1481. #endif
  1482. CARLA_BACKEND_START_NAMESPACE
  1483. CarlaPlugin* CarlaPlugin::newDSSI(const Initializer& init, const char* const guiFilename)
  1484. {
  1485. carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\"}, \"%s\")", init.engine, init.filename, init.name, init.label, guiFilename);
  1486. #ifdef WANT_DSSI
  1487. DssiPlugin* const plugin = new DssiPlugin(init.engine, init.id);
  1488. if (! plugin->init(init.filename, init.name, init.label, guiFilename))
  1489. {
  1490. delete plugin;
  1491. return nullptr;
  1492. }
  1493. plugin->reload();
  1494. if (init.engine->getProccessMode() == PROCESS_MODE_CONTINUOUS_RACK && ! CarlaPluginProtectedData::canRunInRack(plugin))
  1495. {
  1496. init.engine->setLastError("Carla's rack mode can only work with Mono or Stereo DSSI plugins, sorry!");
  1497. delete plugin;
  1498. return nullptr;
  1499. }
  1500. return plugin;
  1501. #else
  1502. init.engine->setLastError("DSSI support not available");
  1503. return nullptr;
  1504. #endif
  1505. }
  1506. CARLA_BACKEND_END_NAMESPACE