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.

carla-lv2.cpp 53KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586
  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #define CARLA_NATIVE_PLUGIN_LV2
  18. #include "carla-base.cpp"
  19. #include "CarlaLv2Utils.hpp"
  20. #include "CarlaMathUtils.hpp"
  21. #include "CarlaString.hpp"
  22. #include "juce_audio_basics.h"
  23. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  24. # include "juce_gui_basics.h"
  25. #else
  26. namespace juce {
  27. # include "juce_events/messages/juce_Initialisation.h"
  28. } // namespace juce
  29. #endif
  30. using juce::FloatVectorOperations;
  31. using juce::ScopedJuceInitialiser_GUI;
  32. using juce::SharedResourcePointer;
  33. // -----------------------------------------------------------------------
  34. // -Weffc++ compat ext widget
  35. extern "C" {
  36. typedef struct _LV2_External_UI_Widget_Compat {
  37. void (*run )(struct _LV2_External_UI_Widget_Compat*);
  38. void (*show)(struct _LV2_External_UI_Widget_Compat*);
  39. void (*hide)(struct _LV2_External_UI_Widget_Compat*);
  40. _LV2_External_UI_Widget_Compat()
  41. : run(nullptr), show(nullptr), hide(nullptr) {}
  42. } LV2_External_UI_Widget_Compat;
  43. }
  44. // -----------------------------------------------------------------------
  45. // LV2 descriptor functions
  46. #if defined(__clang__)
  47. # pragma clang diagnostic push
  48. # pragma clang diagnostic ignored "-Weffc++"
  49. #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  50. # pragma GCC diagnostic push
  51. # pragma GCC diagnostic ignored "-Weffc++"
  52. #endif
  53. class NativePlugin : public LV2_External_UI_Widget_Compat
  54. {
  55. #if defined(__clang__)
  56. # pragma clang diagnostic pop
  57. #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
  58. # pragma GCC diagnostic pop
  59. #endif
  60. public:
  61. static const uint32_t kMaxMidiEvents = 512;
  62. NativePlugin(const NativePluginDescriptor* const desc, const double sampleRate, const char* const bundlePath, const LV2_Feature* const* features)
  63. : fHandle(nullptr),
  64. fHost(),
  65. fDescriptor(desc),
  66. #ifdef CARLA_PROPER_CPP11_SUPPORT
  67. fProgramDesc({0, 0, nullptr}),
  68. #endif
  69. fMidiEventCount(0),
  70. fTimeInfo(),
  71. fLastTimeSpeed(0.0),
  72. fIsProcessing(false),
  73. fBufferSize(0),
  74. fSampleRate(sampleRate),
  75. fUridMap(nullptr),
  76. fURIs(),
  77. fUI(),
  78. fPorts(),
  79. sJuceInitialiser(),
  80. leakDetector_NativePlugin()
  81. {
  82. run = extui_run;
  83. show = extui_show;
  84. hide = extui_hide;
  85. CarlaString resourceDir(bundlePath);
  86. #ifdef CARLA_OS_WIN
  87. resourceDir += "\\resources\\";
  88. #else
  89. resourceDir += "/resources/";
  90. #endif
  91. fHost.handle = this;
  92. fHost.resourceDir = resourceDir.dup();
  93. fHost.uiName = nullptr;
  94. fHost.uiParentId = 0;
  95. fHost.get_buffer_size = host_get_buffer_size;
  96. fHost.get_sample_rate = host_get_sample_rate;
  97. fHost.is_offline = host_is_offline;
  98. fHost.get_time_info = host_get_time_info;
  99. fHost.write_midi_event = host_write_midi_event;
  100. fHost.ui_parameter_changed = host_ui_parameter_changed;
  101. fHost.ui_custom_data_changed = host_ui_custom_data_changed;
  102. fHost.ui_closed = host_ui_closed;
  103. fHost.ui_open_file = host_ui_open_file;
  104. fHost.ui_save_file = host_ui_save_file;
  105. fHost.dispatcher = host_dispatcher;
  106. const LV2_Options_Option* options = nullptr;
  107. const LV2_URID_Map* uridMap = nullptr;
  108. const LV2_URID_Unmap* uridUnmap = nullptr;
  109. for (int i=0; features[i] != nullptr; ++i)
  110. {
  111. if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
  112. options = (const LV2_Options_Option*)features[i]->data;
  113. else if (std::strcmp(features[i]->URI, LV2_URID__map) == 0)
  114. uridMap = (const LV2_URID_Map*)features[i]->data;
  115. else if (std::strcmp(features[i]->URI, LV2_URID__unmap) == 0)
  116. uridUnmap = (const LV2_URID_Unmap*)features[i]->data;
  117. }
  118. if (options == nullptr || uridMap == nullptr)
  119. {
  120. carla_stderr("Host doesn't provides option or urid-map features");
  121. return;
  122. }
  123. for (int i=0; options[i].key != 0; ++i)
  124. {
  125. if (uridUnmap != nullptr)
  126. {
  127. carla_debug("Host option %i:\"%s\"", i, uridUnmap->unmap(uridUnmap->handle, options[i].key));
  128. }
  129. if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
  130. {
  131. if (options[i].type == uridMap->map(uridMap->handle, LV2_ATOM__Int))
  132. {
  133. const int value(*(const int*)options[i].value);
  134. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  135. fBufferSize = static_cast<uint32_t>(value);
  136. }
  137. else
  138. carla_stderr("Host provides maxBlockLength but has wrong value type");
  139. break;
  140. }
  141. }
  142. fUridMap = uridMap;
  143. if (fDescriptor->midiIns > 0)
  144. fUI.portOffset += desc->midiIns;
  145. else if (fDescriptor->hints & PLUGIN_USES_TIME)
  146. fUI.portOffset += 1;
  147. fUI.portOffset += desc->midiOuts;
  148. fUI.portOffset += 1; // freewheel
  149. fUI.portOffset += desc->audioIns;
  150. fUI.portOffset += desc->audioOuts;
  151. }
  152. ~NativePlugin()
  153. {
  154. CARLA_ASSERT(fHandle == nullptr);
  155. if (fHost.resourceDir != nullptr)
  156. {
  157. delete[] fHost.resourceDir;
  158. fHost.resourceDir = nullptr;
  159. }
  160. }
  161. bool init()
  162. {
  163. if (fDescriptor->instantiate == nullptr || fDescriptor->process == nullptr)
  164. {
  165. carla_stderr("Plugin is missing something...");
  166. return false;
  167. }
  168. if (fBufferSize == 0)
  169. {
  170. carla_stderr("Host is missing bufferSize feature");
  171. //return false;
  172. // as testing, continue for now
  173. fBufferSize = 1024;
  174. }
  175. fHandle = fDescriptor->instantiate(&fHost);
  176. CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
  177. carla_zeroStruct<NativeMidiEvent>(fMidiEvents, kMaxMidiEvents*2);
  178. carla_zeroStruct<NativeTimeInfo>(fTimeInfo);
  179. fPorts.init(fDescriptor, fHandle);
  180. fURIs.map(fUridMap);
  181. return true;
  182. }
  183. // -------------------------------------------------------------------
  184. // LV2 functions
  185. void lv2_connect_port(const uint32_t port, void* const dataLocation)
  186. {
  187. fPorts.connectPort(fDescriptor, port, dataLocation);
  188. }
  189. void lv2_activate()
  190. {
  191. if (fDescriptor->activate != nullptr)
  192. fDescriptor->activate(fHandle);
  193. carla_zeroStruct<NativeTimeInfo>(fTimeInfo);
  194. }
  195. void lv2_deactivate()
  196. {
  197. if (fDescriptor->deactivate != nullptr)
  198. fDescriptor->deactivate(fHandle);
  199. }
  200. void lv2_cleanup()
  201. {
  202. if (fDescriptor->cleanup != nullptr)
  203. fDescriptor->cleanup(fHandle);
  204. fHandle = nullptr;
  205. }
  206. void lv2_run(const uint32_t frames)
  207. {
  208. if (frames == 0)
  209. {
  210. updateParameterOutputs();
  211. return;
  212. }
  213. // Check for updated parameters
  214. float curValue;
  215. for (uint32_t i=0; i < fPorts.paramCount; ++i)
  216. {
  217. CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr)
  218. curValue = *fPorts.paramsPtr[i];
  219. if ((! carla_compareFloats(fPorts.paramsLast[i], curValue)) && (fDescriptor->get_parameter_info(fHandle, i)->hints & PARAMETER_IS_OUTPUT) == 0)
  220. {
  221. fPorts.paramsLast[i] = curValue;
  222. fDescriptor->set_parameter_value(fHandle, i, curValue);
  223. }
  224. }
  225. if (fDescriptor->midiIns > 0 || (fDescriptor->hints & PLUGIN_USES_TIME) != 0)
  226. {
  227. fMidiEventCount = 0;
  228. carla_zeroStruct<NativeMidiEvent>(fMidiEvents, kMaxMidiEvents*2);
  229. LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[0], iter)
  230. {
  231. const LV2_Atom_Event* const event((const LV2_Atom_Event*)iter);
  232. if (event == nullptr)
  233. continue;
  234. if (event->body.size > 4)
  235. continue;
  236. if (event->time.frames >= frames)
  237. break;
  238. if (event->body.type == fURIs.midiEvent)
  239. {
  240. if (fMidiEventCount >= kMaxMidiEvents*2)
  241. continue;
  242. const uint8_t* const data((const uint8_t*)(event + 1));
  243. fMidiEvents[fMidiEventCount].port = 0;
  244. fMidiEvents[fMidiEventCount].time = (uint32_t)event->time.frames;
  245. fMidiEvents[fMidiEventCount].size = (uint8_t)event->body.size;
  246. for (uint32_t i=0; i < event->body.size; ++i)
  247. fMidiEvents[fMidiEventCount].data[i] = data[i];
  248. fMidiEventCount += 1;
  249. continue;
  250. }
  251. if (event->body.type == fURIs.atomBlank)
  252. {
  253. const LV2_Atom_Object* const obj((const LV2_Atom_Object*)&event->body);
  254. if (obj->body.otype != fURIs.timePos)
  255. continue;
  256. LV2_Atom* bar = nullptr;
  257. LV2_Atom* barBeat = nullptr;
  258. LV2_Atom* beat = nullptr;
  259. LV2_Atom* beatUnit = nullptr;
  260. LV2_Atom* beatsPerBar = nullptr;
  261. LV2_Atom* beatsPerMinute = nullptr;
  262. LV2_Atom* ticksPerBeat = nullptr;
  263. LV2_Atom* frame = nullptr;
  264. LV2_Atom* speed = nullptr;
  265. lv2_atom_object_get(obj,
  266. fURIs.timeBar, &bar,
  267. fURIs.timeBarBeat, &barBeat,
  268. fURIs.timeBeat, &beat,
  269. fURIs.timeBeatUnit, &beatUnit,
  270. fURIs.timeBeatsPerBar, &beatsPerBar,
  271. fURIs.timeBeatsPerMinute, &beatsPerMinute,
  272. fURIs.timeTicksPerBeat, &ticksPerBeat,
  273. fURIs.timeFrame, &frame,
  274. fURIs.timeSpeed, &speed,
  275. nullptr);
  276. if (bar != nullptr)
  277. {
  278. /**/ if (bar->type == fURIs.atomDouble)
  279. fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Double*)bar)->body + 1.0);
  280. else if (bar->type == fURIs.atomFloat)
  281. fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Float*)bar)->body + 1.0f);
  282. else if (bar->type == fURIs.atomInt)
  283. fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Int*)bar)->body + 1);
  284. else if (bar->type == fURIs.atomLong)
  285. fTimeInfo.bbt.bar = static_cast<int32_t>(((LV2_Atom_Long*)bar)->body + 1);
  286. else
  287. carla_stderr("Unknown lv2 bar value type");
  288. }
  289. if (ticksPerBeat != nullptr)
  290. {
  291. /**/ if (ticksPerBeat->type == fURIs.atomDouble)
  292. fTimeInfo.bbt.ticksPerBeat = ((LV2_Atom_Double*)ticksPerBeat)->body;
  293. else if (ticksPerBeat->type == fURIs.atomFloat)
  294. fTimeInfo.bbt.ticksPerBeat = static_cast<double>(((LV2_Atom_Float*)ticksPerBeat)->body);
  295. else if (ticksPerBeat->type == fURIs.atomInt)
  296. fTimeInfo.bbt.ticksPerBeat = static_cast<double>(((LV2_Atom_Int*)ticksPerBeat)->body);
  297. else if (ticksPerBeat->type == fURIs.atomLong)
  298. fTimeInfo.bbt.ticksPerBeat = static_cast<double>(((LV2_Atom_Long*)ticksPerBeat)->body);
  299. else
  300. carla_stderr("Unknown lv2 ticksPerBeat value type");
  301. }
  302. if (barBeat != nullptr)
  303. {
  304. double barBeatValue = 0.0;
  305. /**/ if (barBeat->type == fURIs.atomDouble)
  306. barBeatValue = ((LV2_Atom_Double*)barBeat)->body;
  307. else if (barBeat->type == fURIs.atomFloat)
  308. barBeatValue = static_cast<double>(((LV2_Atom_Float*)barBeat)->body);
  309. else if (barBeat->type == fURIs.atomInt)
  310. barBeatValue = static_cast<double>(((LV2_Atom_Int*)barBeat)->body);
  311. else if (barBeat->type == fURIs.atomLong)
  312. barBeatValue = static_cast<double>(((LV2_Atom_Long*)barBeat)->body);
  313. else
  314. carla_stderr("Unknown lv2 barBeat value type");
  315. const double rest = std::fmod(barBeatValue, 1.0);
  316. fTimeInfo.bbt.beat = static_cast<int32_t>(barBeatValue-rest+1.0);
  317. fTimeInfo.bbt.tick = static_cast<int32_t>(rest*fTimeInfo.bbt.ticksPerBeat+0.5);
  318. }
  319. // barBeat includes beat
  320. else if (beat != nullptr)
  321. {
  322. /**/ if (beat->type == fURIs.atomDouble)
  323. fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Double*)beat)->body + 1.0);
  324. else if (beat->type == fURIs.atomFloat)
  325. fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Float*)beat)->body + 1.0f);
  326. else if (beat->type == fURIs.atomInt)
  327. fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Int*)beat)->body + 1);
  328. else if (beat->type == fURIs.atomLong)
  329. fTimeInfo.bbt.beat = static_cast<int32_t>(((LV2_Atom_Long*)beat)->body + 1);
  330. else
  331. carla_stderr("Unknown lv2 beat value type");
  332. }
  333. if (beatUnit != nullptr)
  334. {
  335. /**/ if (beatUnit->type == fURIs.atomDouble)
  336. fTimeInfo.bbt.beatType = static_cast<float>(((LV2_Atom_Double*)beatUnit)->body);
  337. else if (beatUnit->type == fURIs.atomFloat)
  338. fTimeInfo.bbt.beatType = ((LV2_Atom_Float*)beatUnit)->body;
  339. else if (beatUnit->type == fURIs.atomInt)
  340. fTimeInfo.bbt.beatType = static_cast<float>(((LV2_Atom_Int*)beatUnit)->body);
  341. else if (beatUnit->type == fURIs.atomLong)
  342. fTimeInfo.bbt.beatType = static_cast<float>(((LV2_Atom_Long*)beatUnit)->body);
  343. else
  344. carla_stderr("Unknown lv2 beatUnit value type");
  345. }
  346. if (beatsPerBar != nullptr)
  347. {
  348. /**/ if (beatsPerBar->type == fURIs.atomDouble)
  349. fTimeInfo.bbt.beatsPerBar = static_cast<float>(((LV2_Atom_Double*)beatsPerBar)->body);
  350. else if (beatsPerBar->type == fURIs.atomFloat)
  351. fTimeInfo.bbt.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
  352. else if (beatsPerBar->type == fURIs.atomInt)
  353. fTimeInfo.bbt.beatsPerBar = static_cast<float>(((LV2_Atom_Int*)beatsPerBar)->body);
  354. else if (beatsPerBar->type == fURIs.atomLong)
  355. fTimeInfo.bbt.beatsPerBar = static_cast<float>(((LV2_Atom_Long*)beatsPerBar)->body);
  356. else
  357. carla_stderr("Unknown lv2 beatsPerBar value type");
  358. }
  359. if (beatsPerMinute != nullptr)
  360. {
  361. /**/ if (beatsPerMinute->type == fURIs.atomDouble)
  362. fTimeInfo.bbt.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
  363. else if (beatsPerMinute->type == fURIs.atomFloat)
  364. fTimeInfo.bbt.beatsPerMinute = static_cast<double>(((LV2_Atom_Float*)beatsPerMinute)->body);
  365. else if (beatsPerMinute->type == fURIs.atomInt)
  366. fTimeInfo.bbt.beatsPerMinute = static_cast<double>(((LV2_Atom_Int*)beatsPerMinute)->body);
  367. else if (beatsPerMinute->type == fURIs.atomLong)
  368. fTimeInfo.bbt.beatsPerMinute = static_cast<double>(((LV2_Atom_Long*)beatsPerMinute)->body);
  369. else
  370. carla_stderr("Unknown lv2 beatsPerMinute value type");
  371. }
  372. fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*fTimeInfo.bbt.beatsPerBar*(fTimeInfo.bbt.bar-1);
  373. if (frame != nullptr && frame->type == fURIs.atomLong)
  374. fTimeInfo.frame = static_cast<uint64_t>(((LV2_Atom_Long*)frame)->body);
  375. if (speed != nullptr && speed->type == fURIs.atomFloat)
  376. {
  377. fLastTimeSpeed = ((LV2_Atom_Float*)speed)->body;
  378. fTimeInfo.playing = carla_compareFloats(fLastTimeSpeed, 1.0);
  379. }
  380. fTimeInfo.bbt.valid = (beatsPerMinute != nullptr && beatsPerBar != nullptr && beatUnit != nullptr);
  381. continue;
  382. }
  383. }
  384. for (uint32_t i=1; i < fDescriptor->midiIns; ++i)
  385. {
  386. LV2_ATOM_SEQUENCE_FOREACH(fPorts.eventsIn[i], iter)
  387. {
  388. const LV2_Atom_Event* const event((const LV2_Atom_Event*)iter);
  389. if (event == nullptr)
  390. continue;
  391. if (event->body.type != fURIs.midiEvent)
  392. continue;
  393. if (event->body.size > 4)
  394. continue;
  395. if (event->time.frames >= frames)
  396. break;
  397. if (fMidiEventCount >= kMaxMidiEvents*2)
  398. break;
  399. const uint8_t* const data((const uint8_t*)(event + 1));
  400. fMidiEvents[fMidiEventCount].port = (uint8_t)i;
  401. fMidiEvents[fMidiEventCount].size = (uint8_t)event->body.size;
  402. fMidiEvents[fMidiEventCount].time = (uint32_t)event->time.frames;
  403. for (uint32_t j=0; j < event->body.size; ++j)
  404. fMidiEvents[fMidiEventCount].data[j] = data[j];
  405. fMidiEventCount += 1;
  406. }
  407. }
  408. }
  409. fIsProcessing = true;
  410. fDescriptor->process(fHandle, fPorts.audioIns, fPorts.audioOuts, frames, fMidiEvents, fMidiEventCount);
  411. fIsProcessing = false;
  412. // update timePos for next callback
  413. if (! carla_compareFloats(fLastTimeSpeed, 0.0))
  414. {
  415. const double newFrames = fLastTimeSpeed*frames;
  416. fTimeInfo.frame += static_cast<uint64_t>(newFrames);
  417. if (fTimeInfo.bbt.valid)
  418. {
  419. const double samplesPerBeat = 60.0 / fTimeInfo.bbt.beatsPerMinute * fSampleRate;
  420. const double ticksPerSample = fTimeInfo.bbt.ticksPerBeat / samplesPerBeat;
  421. double newTickPos = double(fTimeInfo.bbt.tick) + ticksPerSample*newFrames;
  422. double newBeatPos = double(fTimeInfo.bbt.beat)-1.0;
  423. double newBarPos = double(fTimeInfo.bbt.bar)-1.0;
  424. for (; newTickPos >= fTimeInfo.bbt.ticksPerBeat;)
  425. {
  426. ++newBeatPos;
  427. newTickPos -= fTimeInfo.bbt.ticksPerBeat;
  428. }
  429. for (; newBeatPos >= fTimeInfo.bbt.beatsPerBar;)
  430. {
  431. ++newBarPos;
  432. newBeatPos -= fTimeInfo.bbt.beatsPerBar;
  433. }
  434. fTimeInfo.bbt.bar = static_cast<int32_t>(newBarPos+1.0);
  435. fTimeInfo.bbt.beat = static_cast<int32_t>(newBeatPos+1.0);
  436. fTimeInfo.bbt.tick = static_cast<int32_t>(newTickPos);
  437. fTimeInfo.bbt.barStartTick = fTimeInfo.bbt.ticksPerBeat*fTimeInfo.bbt.beatsPerBar*(fTimeInfo.bbt.bar-1);
  438. }
  439. }
  440. // TODO - midi out
  441. updateParameterOutputs();
  442. }
  443. // -------------------------------------------------------------------
  444. uint32_t lv2_get_options(LV2_Options_Option* const /*options*/) const
  445. {
  446. // currently unused
  447. return LV2_OPTIONS_SUCCESS;
  448. }
  449. uint32_t lv2_set_options(const LV2_Options_Option* const options)
  450. {
  451. for (int i=0; options[i].key != 0; ++i)
  452. {
  453. if (options[i].key == fUridMap->map(fUridMap->handle, LV2_BUF_SIZE__maxBlockLength))
  454. {
  455. if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Int))
  456. {
  457. const int value(*(const int*)options[i].value);
  458. CARLA_SAFE_ASSERT_CONTINUE(value > 0);
  459. fBufferSize = static_cast<uint32_t>(value);
  460. if (fDescriptor->dispatcher != nullptr)
  461. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_BUFFER_SIZE_CHANGED, 0, value, nullptr, 0.0f);
  462. }
  463. else
  464. carla_stderr("Host changed maxBlockLength but with wrong value type");
  465. }
  466. else if (options[i].key == fUridMap->map(fUridMap->handle, LV2_CORE__sampleRate))
  467. {
  468. if (options[i].type == fUridMap->map(fUridMap->handle, LV2_ATOM__Double))
  469. {
  470. const double value(*(const double*)options[i].value);
  471. CARLA_SAFE_ASSERT_CONTINUE(value > 0.0);
  472. fSampleRate = value;
  473. if (fDescriptor->dispatcher != nullptr)
  474. fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, (float)fSampleRate);
  475. }
  476. else
  477. carla_stderr("Host changed sampleRate but with wrong value type");
  478. }
  479. }
  480. return LV2_OPTIONS_SUCCESS;
  481. }
  482. const LV2_Program_Descriptor* lv2_get_program(const uint32_t index)
  483. {
  484. if (fDescriptor->category == PLUGIN_CATEGORY_SYNTH)
  485. return nullptr;
  486. if (fDescriptor->get_midi_program_count == nullptr)
  487. return nullptr;
  488. if (fDescriptor->get_midi_program_info == nullptr)
  489. return nullptr;
  490. if (index >= fDescriptor->get_midi_program_count(fHandle))
  491. return nullptr;
  492. const NativeMidiProgram* const midiProg(fDescriptor->get_midi_program_info(fHandle, index));
  493. if (midiProg == nullptr)
  494. return nullptr;
  495. fProgramDesc.bank = midiProg->bank;
  496. fProgramDesc.program = midiProg->program;
  497. fProgramDesc.name = midiProg->name;
  498. return &fProgramDesc;
  499. }
  500. void lv2_select_program(uint32_t bank, uint32_t program)
  501. {
  502. if (fDescriptor->category == PLUGIN_CATEGORY_SYNTH)
  503. return;
  504. if (fDescriptor->set_midi_program == nullptr)
  505. return;
  506. fDescriptor->set_midi_program(fHandle, 0, bank, program);
  507. }
  508. LV2_State_Status lv2_save(const LV2_State_Store_Function store, const LV2_State_Handle handle, const uint32_t /*flags*/, const LV2_Feature* const* const /*features*/) const
  509. {
  510. if ((fDescriptor->hints & PLUGIN_USES_STATE) == 0 || fDescriptor->get_state == nullptr)
  511. return LV2_STATE_ERR_NO_FEATURE;
  512. if (char* const state = fDescriptor->get_state(fHandle))
  513. {
  514. store(handle, fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/chunk"), state, std::strlen(state), fURIs.atomString, LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE);
  515. std::free(state);
  516. return LV2_STATE_SUCCESS;
  517. }
  518. return LV2_STATE_ERR_UNKNOWN;
  519. }
  520. LV2_State_Status lv2_restore(const LV2_State_Retrieve_Function retrieve, const LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* const /*features*/) const
  521. {
  522. if ((fDescriptor->hints & PLUGIN_USES_STATE) == 0 || fDescriptor->set_state == nullptr)
  523. return LV2_STATE_ERR_NO_FEATURE;
  524. size_t size = 0;
  525. uint32_t type = 0;
  526. const void* data = retrieve(handle, fUridMap->map(fUridMap->handle, "http://kxstudio.sf.net/ns/carla/chunk"), &size, &type, &flags);
  527. if (size == 0)
  528. return LV2_STATE_ERR_UNKNOWN;
  529. if (type == 0)
  530. return LV2_STATE_ERR_UNKNOWN;
  531. if (data == nullptr)
  532. return LV2_STATE_ERR_UNKNOWN;
  533. if (type != fURIs.atomString)
  534. return LV2_STATE_ERR_BAD_TYPE;
  535. fDescriptor->set_state(fHandle, (const char*)data);
  536. return LV2_STATE_SUCCESS;
  537. }
  538. // -------------------------------------------------------------------
  539. void lv2ui_instantiate(LV2UI_Write_Function writeFunction, LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
  540. {
  541. fUI.writeFunction = writeFunction;
  542. fUI.controller = controller;
  543. // ---------------------------------------------------------------
  544. // see if the host supports external-ui
  545. for (int i=0; features[i] != nullptr; ++i)
  546. {
  547. if (std::strcmp(features[i]->URI, LV2_EXTERNAL_UI__Host) == 0 ||
  548. std::strcmp(features[i]->URI, LV2_EXTERNAL_UI_DEPRECATED_URI) == 0)
  549. {
  550. fUI.host = (const LV2_External_UI_Host*)features[i]->data;
  551. break;
  552. }
  553. }
  554. if (fUI.host != nullptr)
  555. {
  556. fHost.uiName = carla_strdup(fUI.host->plugin_human_id);
  557. *widget = this;
  558. return;
  559. }
  560. // ---------------------------------------------------------------
  561. // no external-ui support, use showInterface
  562. for (int i=0; features[i] != nullptr; ++i)
  563. {
  564. if (std::strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
  565. {
  566. const LV2_Options_Option* const options((const LV2_Options_Option*)features[i]->data);
  567. for (int j=0; options[j].key != 0; ++j)
  568. {
  569. if (options[j].key == fUridMap->map(fUridMap->handle, LV2_UI__windowTitle))
  570. {
  571. fHost.uiName = carla_strdup((const char*)options[j].value);
  572. break;
  573. }
  574. }
  575. break;
  576. }
  577. }
  578. if (fHost.uiName == nullptr)
  579. fHost.uiName = carla_strdup(fDescriptor->name);
  580. *widget = nullptr;
  581. }
  582. void lv2ui_port_event(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer) const
  583. {
  584. if (format != 0 || bufferSize != sizeof(float) || buffer == nullptr)
  585. return;
  586. if (portIndex >= fUI.portOffset || ! fUI.isVisible)
  587. return;
  588. if (fDescriptor->ui_set_parameter_value == nullptr)
  589. return;
  590. const float value(*(const float*)buffer);
  591. fDescriptor->ui_set_parameter_value(fHandle, portIndex-fUI.portOffset, value);
  592. }
  593. void lv2ui_cleanup()
  594. {
  595. fUI.host = nullptr;
  596. fUI.writeFunction = nullptr;
  597. fUI.controller = nullptr;
  598. if (fHost.uiName != nullptr)
  599. {
  600. delete[] fHost.uiName;
  601. fHost.uiName = nullptr;
  602. }
  603. if (! fUI.isVisible)
  604. return;
  605. if (fDescriptor->ui_show != nullptr)
  606. fDescriptor->ui_show(fHandle, false);
  607. fUI.isVisible = false;
  608. }
  609. // -------------------------------------------------------------------
  610. void lv2ui_select_program(uint32_t bank, uint32_t program) const
  611. {
  612. if (fDescriptor->category == PLUGIN_CATEGORY_SYNTH)
  613. return;
  614. if (fDescriptor->ui_set_midi_program == nullptr)
  615. return;
  616. fDescriptor->ui_set_midi_program(fHandle, 0, bank, program);
  617. }
  618. // -------------------------------------------------------------------
  619. int lv2ui_idle() const
  620. {
  621. if (! fUI.isVisible)
  622. return 1;
  623. if (fDescriptor->ui_idle != nullptr)
  624. fDescriptor->ui_idle(fHandle);
  625. return 0;
  626. }
  627. int lv2ui_show()
  628. {
  629. handleUiShow();
  630. return 0;
  631. }
  632. int lv2ui_hide()
  633. {
  634. handleUiHide();
  635. return 0;
  636. }
  637. // -------------------------------------------------------------------
  638. protected:
  639. void handleUiRun() const
  640. {
  641. if (fDescriptor->ui_idle != nullptr)
  642. fDescriptor->ui_idle(fHandle);
  643. }
  644. void handleUiShow()
  645. {
  646. if (fDescriptor->ui_show != nullptr)
  647. fDescriptor->ui_show(fHandle, true);
  648. fUI.isVisible = true;
  649. }
  650. void handleUiHide()
  651. {
  652. if (fDescriptor->ui_show != nullptr)
  653. fDescriptor->ui_show(fHandle, false);
  654. fUI.isVisible = false;
  655. }
  656. // -------------------------------------------------------------------
  657. uint32_t handleGetBufferSize() const
  658. {
  659. return fBufferSize;
  660. }
  661. double handleGetSampleRate() const
  662. {
  663. return fSampleRate;
  664. }
  665. bool handleIsOffline() const
  666. {
  667. CARLA_SAFE_ASSERT_RETURN(fIsProcessing, false);
  668. return (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f);
  669. }
  670. const NativeTimeInfo* handleGetTimeInfo() const
  671. {
  672. CARLA_SAFE_ASSERT_RETURN(fIsProcessing, nullptr);
  673. return &fTimeInfo;
  674. }
  675. bool handleWriteMidiEvent(const NativeMidiEvent* const event)
  676. {
  677. CARLA_SAFE_ASSERT_RETURN(fIsProcessing, false);
  678. CARLA_SAFE_ASSERT_RETURN(fDescriptor->midiOuts > 0, false);
  679. CARLA_SAFE_ASSERT_RETURN(event != nullptr, false);
  680. CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false);
  681. // reverse-find first free event, and put it there
  682. for (uint32_t i=(kMaxMidiEvents*2)-1; i > fMidiEventCount; --i)
  683. {
  684. if (fMidiEvents[i].data[0] == 0)
  685. {
  686. std::memcpy(&fMidiEvents[i], event, sizeof(NativeMidiEvent));
  687. return true;
  688. }
  689. }
  690. return false;
  691. }
  692. void handleUiParameterChanged(const uint32_t index, const float value) const
  693. {
  694. if (fUI.writeFunction != nullptr && fUI.controller != nullptr)
  695. fUI.writeFunction(fUI.controller, index+fUI.portOffset, sizeof(float), 0, &value);
  696. }
  697. void handleUiCustomDataChanged(const char* const /*key*/, const char* const /*value*/) const
  698. {
  699. //storeCustomData(key, value);
  700. }
  701. void handleUiClosed()
  702. {
  703. if (fUI.host != nullptr && fUI.host->ui_closed != nullptr && fUI.controller != nullptr)
  704. fUI.host->ui_closed(fUI.controller);
  705. fUI.host = nullptr;
  706. fUI.writeFunction = nullptr;
  707. fUI.controller = nullptr;
  708. fUI.isVisible = false;
  709. }
  710. const char* handleUiOpenFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
  711. {
  712. // TODO
  713. return nullptr;
  714. }
  715. const char* handleUiSaveFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const
  716. {
  717. // TODO
  718. return nullptr;
  719. }
  720. intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
  721. {
  722. carla_debug("NativePlugin::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", opcode, index, value, ptr, opt);
  723. intptr_t ret = 0;
  724. switch (opcode)
  725. {
  726. case HOST_OPCODE_NULL:
  727. case HOST_OPCODE_UPDATE_PARAMETER:
  728. case HOST_OPCODE_UPDATE_MIDI_PROGRAM:
  729. case HOST_OPCODE_RELOAD_PARAMETERS:
  730. case HOST_OPCODE_RELOAD_MIDI_PROGRAMS:
  731. case HOST_OPCODE_RELOAD_ALL:
  732. // nothing
  733. break;
  734. case HOST_OPCODE_UI_UNAVAILABLE:
  735. handleUiClosed();
  736. break;
  737. }
  738. return ret;
  739. // unused for now
  740. (void)index;
  741. (void)value;
  742. (void)ptr;
  743. (void)opt;
  744. }
  745. void updateParameterOutputs()
  746. {
  747. for (uint32_t i=0; i < fPorts.paramCount; ++i)
  748. {
  749. if (fDescriptor->get_parameter_info(fHandle, i)->hints & PARAMETER_IS_OUTPUT)
  750. {
  751. fPorts.paramsLast[i] = fDescriptor->get_parameter_value(fHandle, i);
  752. if (fPorts.paramsPtr[i] != nullptr)
  753. *fPorts.paramsPtr[i] = fPorts.paramsLast[i];
  754. }
  755. }
  756. }
  757. // -------------------------------------------------------------------
  758. private:
  759. // Native data
  760. NativePluginHandle fHandle;
  761. NativeHostDescriptor fHost;
  762. const NativePluginDescriptor* const fDescriptor;
  763. LV2_Program_Descriptor fProgramDesc;
  764. uint32_t fMidiEventCount;
  765. NativeMidiEvent fMidiEvents[kMaxMidiEvents*2];
  766. NativeTimeInfo fTimeInfo;
  767. double fLastTimeSpeed;
  768. bool fIsProcessing;
  769. // Lv2 host data
  770. uint32_t fBufferSize;
  771. double fSampleRate;
  772. const LV2_URID_Map* fUridMap;
  773. struct URIDs {
  774. LV2_URID atomBlank;
  775. LV2_URID atomDouble;
  776. LV2_URID atomFloat;
  777. LV2_URID atomInt;
  778. LV2_URID atomLong;
  779. LV2_URID atomSequence;
  780. LV2_URID atomString;
  781. LV2_URID midiEvent;
  782. LV2_URID timePos;
  783. LV2_URID timeBar;
  784. LV2_URID timeBeat;
  785. LV2_URID timeBarBeat;
  786. LV2_URID timeBeatsPerBar;
  787. LV2_URID timeBeatsPerMinute;
  788. LV2_URID timeBeatUnit;
  789. LV2_URID timeFrame;
  790. LV2_URID timeSpeed;
  791. LV2_URID timeTicksPerBeat;
  792. URIDs()
  793. : atomBlank(0),
  794. atomDouble(0),
  795. atomFloat(0),
  796. atomInt(0),
  797. atomLong(0),
  798. atomSequence(0),
  799. atomString(0),
  800. midiEvent(0),
  801. timePos(0),
  802. timeBar(0),
  803. timeBeat(0),
  804. timeBarBeat(0),
  805. timeBeatsPerBar(0),
  806. timeBeatsPerMinute(0),
  807. timeBeatUnit(0),
  808. timeFrame(0),
  809. timeSpeed(0),
  810. timeTicksPerBeat(0) {}
  811. void map(const LV2_URID_Map* const uridMap)
  812. {
  813. atomBlank = uridMap->map(uridMap->handle, LV2_ATOM__Blank);
  814. atomDouble = uridMap->map(uridMap->handle, LV2_ATOM__Double);
  815. atomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float);
  816. atomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int);
  817. atomLong = uridMap->map(uridMap->handle, LV2_ATOM__Long);
  818. atomSequence = uridMap->map(uridMap->handle, LV2_ATOM__Sequence);
  819. atomString = uridMap->map(uridMap->handle, LV2_ATOM__String);
  820. midiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
  821. timePos = uridMap->map(uridMap->handle, LV2_TIME__Position);
  822. timeBar = uridMap->map(uridMap->handle, LV2_TIME__bar);
  823. timeBeat = uridMap->map(uridMap->handle, LV2_TIME__beat);
  824. timeBarBeat = uridMap->map(uridMap->handle, LV2_TIME__barBeat);
  825. timeBeatUnit = uridMap->map(uridMap->handle, LV2_TIME__beatUnit);
  826. timeFrame = uridMap->map(uridMap->handle, LV2_TIME__frame);
  827. timeSpeed = uridMap->map(uridMap->handle, LV2_TIME__speed);
  828. timeBeatsPerBar = uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar);
  829. timeBeatsPerMinute = uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute);
  830. timeTicksPerBeat = uridMap->map(uridMap->handle, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat);
  831. }
  832. } fURIs;
  833. struct UI {
  834. const LV2_External_UI_Host* host;
  835. LV2UI_Write_Function writeFunction;
  836. LV2UI_Controller controller;
  837. uint32_t portOffset;
  838. bool isVisible;
  839. UI()
  840. : host(nullptr),
  841. writeFunction(nullptr),
  842. controller(nullptr),
  843. portOffset(0),
  844. isVisible(false) {}
  845. } fUI;
  846. struct Ports {
  847. LV2_Atom_Sequence** eventsIn;
  848. LV2_Atom_Sequence** midiOuts;
  849. float** audioIns;
  850. float** audioOuts;
  851. float* freewheel;
  852. uint32_t paramCount;
  853. float* paramsLast;
  854. float** paramsPtr;
  855. Ports()
  856. : eventsIn(nullptr),
  857. midiOuts(nullptr),
  858. audioIns(nullptr),
  859. audioOuts(nullptr),
  860. freewheel(nullptr),
  861. paramCount(0),
  862. paramsLast(nullptr),
  863. paramsPtr(nullptr) {}
  864. ~Ports()
  865. {
  866. if (eventsIn != nullptr)
  867. {
  868. delete[] eventsIn;
  869. eventsIn = nullptr;
  870. }
  871. if (midiOuts != nullptr)
  872. {
  873. delete[] midiOuts;
  874. midiOuts = nullptr;
  875. }
  876. if (audioIns != nullptr)
  877. {
  878. delete[] audioIns;
  879. audioIns = nullptr;
  880. }
  881. if (audioOuts != nullptr)
  882. {
  883. delete[] audioOuts;
  884. audioOuts = nullptr;
  885. }
  886. if (paramsLast != nullptr)
  887. {
  888. delete[] paramsLast;
  889. paramsLast = nullptr;
  890. }
  891. if (paramsPtr != nullptr)
  892. {
  893. delete[] paramsPtr;
  894. paramsPtr = nullptr;
  895. }
  896. }
  897. void init(const NativePluginDescriptor* const desc, NativePluginHandle handle)
  898. {
  899. CARLA_SAFE_ASSERT_RETURN(desc != nullptr && handle != nullptr,)
  900. if (desc->midiIns > 0)
  901. {
  902. eventsIn = new LV2_Atom_Sequence*[desc->midiIns];
  903. for (uint32_t i=0; i < desc->midiIns; ++i)
  904. eventsIn[i] = nullptr;
  905. }
  906. else if (desc->hints & PLUGIN_USES_TIME)
  907. {
  908. eventsIn = new LV2_Atom_Sequence*[1];
  909. eventsIn[0] = nullptr;
  910. }
  911. if (desc->midiOuts > 0)
  912. {
  913. midiOuts = new LV2_Atom_Sequence*[desc->midiOuts];
  914. for (uint32_t i=0; i < desc->midiOuts; ++i)
  915. midiOuts[i] = nullptr;
  916. }
  917. if (desc->audioIns > 0)
  918. {
  919. audioIns = new float*[desc->audioIns];
  920. for (uint32_t i=0; i < desc->audioIns; ++i)
  921. audioIns[i] = nullptr;
  922. }
  923. if (desc->audioOuts > 0)
  924. {
  925. audioOuts = new float*[desc->audioOuts];
  926. for (uint32_t i=0; i < desc->audioOuts; ++i)
  927. audioOuts[i] = nullptr;
  928. }
  929. if (desc->get_parameter_count != nullptr && desc->get_parameter_info != nullptr && desc->get_parameter_value != nullptr && desc->set_parameter_value != nullptr)
  930. {
  931. paramCount = desc->get_parameter_count(handle);
  932. if (paramCount > 0)
  933. {
  934. paramsLast = new float[paramCount];
  935. paramsPtr = new float*[paramCount];
  936. for (uint32_t i=0; i < paramCount; ++i)
  937. {
  938. paramsLast[i] = desc->get_parameter_value(handle, i);
  939. paramsPtr[i] = nullptr;
  940. }
  941. }
  942. }
  943. }
  944. void connectPort(const NativePluginDescriptor* const desc, const uint32_t port, void* const dataLocation)
  945. {
  946. uint32_t index = 0;
  947. if (desc->midiIns > 0 || (desc->hints & PLUGIN_USES_TIME) != 0)
  948. {
  949. if (port == index++)
  950. {
  951. eventsIn[0] = (LV2_Atom_Sequence*)dataLocation;
  952. return;
  953. }
  954. }
  955. for (uint32_t i=1; i < desc->midiIns; ++i)
  956. {
  957. if (port == index++)
  958. {
  959. eventsIn[i] = (LV2_Atom_Sequence*)dataLocation;
  960. return;
  961. }
  962. }
  963. for (uint32_t i=0; i < desc->midiOuts; ++i)
  964. {
  965. if (port == index++)
  966. {
  967. midiOuts[i] = (LV2_Atom_Sequence*)dataLocation;
  968. return;
  969. }
  970. }
  971. if (port == index++)
  972. {
  973. freewheel = (float*)dataLocation;
  974. return;
  975. }
  976. for (uint32_t i=0; i < desc->audioIns; ++i)
  977. {
  978. if (port == index++)
  979. {
  980. audioIns[i] = (float*)dataLocation;
  981. return;
  982. }
  983. }
  984. for (uint32_t i=0; i < desc->audioOuts; ++i)
  985. {
  986. if (port == index++)
  987. {
  988. audioOuts[i] = (float*)dataLocation;
  989. return;
  990. }
  991. }
  992. for (uint32_t i=0; i < paramCount; ++i)
  993. {
  994. if (port == index++)
  995. {
  996. paramsPtr[i] = (float*)dataLocation;
  997. return;
  998. }
  999. }
  1000. }
  1001. CARLA_DECLARE_NON_COPY_STRUCT(Ports);
  1002. } fPorts;
  1003. SharedResourcePointer<ScopedJuceInitialiser_GUI> sJuceInitialiser;
  1004. // -------------------------------------------------------------------
  1005. #define handlePtr ((NativePlugin*)self)
  1006. static void extui_run(LV2_External_UI_Widget_Compat* self)
  1007. {
  1008. handlePtr->handleUiRun();
  1009. }
  1010. static void extui_show(LV2_External_UI_Widget_Compat* self)
  1011. {
  1012. handlePtr->handleUiShow();
  1013. }
  1014. static void extui_hide(LV2_External_UI_Widget_Compat* self)
  1015. {
  1016. handlePtr->handleUiHide();
  1017. }
  1018. #undef handlePtr
  1019. // -------------------------------------------------------------------
  1020. #define handlePtr ((NativePlugin*)handle)
  1021. static uint32_t host_get_buffer_size(NativeHostHandle handle)
  1022. {
  1023. return handlePtr->handleGetBufferSize();
  1024. }
  1025. static double host_get_sample_rate(NativeHostHandle handle)
  1026. {
  1027. return handlePtr->handleGetSampleRate();
  1028. }
  1029. static bool host_is_offline(NativeHostHandle handle)
  1030. {
  1031. return handlePtr->handleIsOffline();
  1032. }
  1033. static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle)
  1034. {
  1035. return handlePtr->handleGetTimeInfo();
  1036. }
  1037. static bool host_write_midi_event(NativeHostHandle handle, const NativeMidiEvent* event)
  1038. {
  1039. return handlePtr->handleWriteMidiEvent(event);
  1040. }
  1041. static void host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value)
  1042. {
  1043. handlePtr->handleUiParameterChanged(index, value);
  1044. }
  1045. static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value)
  1046. {
  1047. handlePtr->handleUiCustomDataChanged(key, value);
  1048. }
  1049. static void host_ui_closed(NativeHostHandle handle)
  1050. {
  1051. handlePtr->handleUiClosed();
  1052. }
  1053. static const char* host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
  1054. {
  1055. return handlePtr->handleUiOpenFile(isDir, title, filter);
  1056. }
  1057. static const char* host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter)
  1058. {
  1059. return handlePtr->handleUiSaveFile(isDir, title, filter);
  1060. }
  1061. static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  1062. {
  1063. return handlePtr->handleDispatcher(opcode, index, value, ptr, opt);
  1064. }
  1065. #undef handlePtr
  1066. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePlugin)
  1067. };
  1068. // -----------------------------------------------------------------------
  1069. // LV2 plugin descriptor functions
  1070. static LV2_Handle lv2_instantiate(const LV2_Descriptor* lv2Descriptor, double sampleRate, const char* bundlePath, const LV2_Feature* const* features)
  1071. {
  1072. carla_debug("lv2_instantiate(%p, %g, %s, %p)", lv2Descriptor, sampleRate, bundlePath, features);
  1073. const NativePluginDescriptor* pluginDesc = nullptr;
  1074. const char* pluginLabel = nullptr;
  1075. if (std::strncmp(lv2Descriptor->URI, "http://kxstudio.sf.net/carla/plugins/", 37) == 0)
  1076. pluginLabel = lv2Descriptor->URI+37;
  1077. if (pluginLabel == nullptr)
  1078. {
  1079. carla_stderr("Failed to find carla native plugin with URI \"%s\"", lv2Descriptor->URI);
  1080. return nullptr;
  1081. }
  1082. carla_debug("lv2_instantiate() - looking up label \"%s\"", pluginLabel);
  1083. PluginListManager& plm(PluginListManager::getInstance());
  1084. for (LinkedList<const NativePluginDescriptor*>::Itenerator it = plm.descs.begin(); it.valid(); it.next())
  1085. {
  1086. const NativePluginDescriptor* const& tmpDesc(it.getValue());
  1087. if (std::strcmp(tmpDesc->label, pluginLabel) == 0)
  1088. {
  1089. pluginDesc = tmpDesc;
  1090. break;
  1091. }
  1092. }
  1093. if (pluginDesc == nullptr)
  1094. {
  1095. carla_stderr("Failed to find carla native plugin with label \"%s\"", pluginLabel);
  1096. return nullptr;
  1097. }
  1098. NativePlugin* const plugin(new NativePlugin(pluginDesc, sampleRate, bundlePath, features));
  1099. if (! plugin->init())
  1100. {
  1101. carla_stderr("Failed to init plugin");
  1102. delete plugin;
  1103. return nullptr;
  1104. }
  1105. return (LV2_Handle)plugin;
  1106. }
  1107. #define instancePtr ((NativePlugin*)instance)
  1108. static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation)
  1109. {
  1110. instancePtr->lv2_connect_port(port, dataLocation);
  1111. }
  1112. static void lv2_activate(LV2_Handle instance)
  1113. {
  1114. carla_debug("lv2_activate(%p)", instance);
  1115. instancePtr->lv2_activate();
  1116. }
  1117. static void lv2_run(LV2_Handle instance, uint32_t sampleCount)
  1118. {
  1119. instancePtr->lv2_run(sampleCount);
  1120. }
  1121. static void lv2_deactivate(LV2_Handle instance)
  1122. {
  1123. carla_debug("lv2_deactivate(%p)", instance);
  1124. instancePtr->lv2_deactivate();
  1125. }
  1126. static void lv2_cleanup(LV2_Handle instance)
  1127. {
  1128. carla_debug("lv2_cleanup(%p)", instance);
  1129. instancePtr->lv2_cleanup();
  1130. delete instancePtr;
  1131. }
  1132. static uint32_t lv2_get_options(LV2_Handle instance, LV2_Options_Option* options)
  1133. {
  1134. carla_debug("lv2_get_options(%p, %p)", instance, options);
  1135. return instancePtr->lv2_get_options(options);
  1136. }
  1137. static uint32_t lv2_set_options(LV2_Handle instance, const LV2_Options_Option* options)
  1138. {
  1139. carla_debug("lv2_set_options(%p, %p)", instance, options);
  1140. return instancePtr->lv2_set_options(options);
  1141. }
  1142. static const LV2_Program_Descriptor* lv2_get_program(LV2_Handle instance, uint32_t index)
  1143. {
  1144. carla_debug("lv2_get_program(%p, %i)", instance, index);
  1145. return instancePtr->lv2_get_program(index);
  1146. }
  1147. static void lv2_select_program(LV2_Handle instance, uint32_t bank, uint32_t program)
  1148. {
  1149. carla_debug("lv2_select_program(%p, %i, %i)", instance, bank, program);
  1150. return instancePtr->lv2_select_program(bank, program);
  1151. }
  1152. static LV2_State_Status lv2_save(LV2_Handle instance, LV2_State_Store_Function store, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features)
  1153. {
  1154. carla_debug("lv2_save(%p, %p, %p, %i, %p)", instance, store, handle, flags, features);
  1155. return instancePtr->lv2_save(store, handle, flags, features);
  1156. }
  1157. static LV2_State_Status lv2_restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, LV2_State_Handle handle, uint32_t flags, const LV2_Feature* const* features)
  1158. {
  1159. carla_debug("lv2_restore(%p, %p, %p, %i, %p)", instance, retrieve, handle, flags, features);
  1160. return instancePtr->lv2_restore(retrieve, handle, flags, features);
  1161. }
  1162. static const void* lv2_extension_data(const char* uri)
  1163. {
  1164. carla_debug("lv2_extension_data(\"%s\")", uri);
  1165. static const LV2_Options_Interface options = { lv2_get_options, lv2_set_options };
  1166. static const LV2_Programs_Interface programs = { lv2_get_program, lv2_select_program };
  1167. static const LV2_State_Interface state = { lv2_save, lv2_restore };
  1168. if (std::strcmp(uri, LV2_OPTIONS__interface) == 0)
  1169. return &options;
  1170. if (std::strcmp(uri, LV2_PROGRAMS__Interface) == 0)
  1171. return &programs;
  1172. if (std::strcmp(uri, LV2_STATE__interface) == 0)
  1173. return &state;
  1174. return nullptr;
  1175. }
  1176. #undef instancePtr
  1177. // -----------------------------------------------------------------------
  1178. // LV2 UI descriptor functions
  1179. static LV2UI_Handle lv2ui_instantiate(const LV2UI_Descriptor*, const char*, const char*, LV2UI_Write_Function writeFunction,
  1180. LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
  1181. {
  1182. carla_debug("lv2ui_instantiate(..., %p, %p, %p)", writeFunction, controller, widget, features);
  1183. NativePlugin* plugin = nullptr;
  1184. for (int i=0; features[i] != nullptr; ++i)
  1185. {
  1186. if (std::strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI) == 0)
  1187. {
  1188. plugin = (NativePlugin*)features[i]->data;
  1189. break;
  1190. }
  1191. }
  1192. if (plugin == nullptr)
  1193. {
  1194. carla_stderr("Host doesn't support instance-access, cannot show UI");
  1195. return nullptr;
  1196. }
  1197. plugin->lv2ui_instantiate(writeFunction, controller, widget, features);
  1198. return (LV2UI_Handle)plugin;
  1199. }
  1200. #define uiPtr ((NativePlugin*)ui)
  1201. static void lv2ui_port_event(LV2UI_Handle ui, uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
  1202. {
  1203. carla_debug("lv2ui_port_event(%p, %i, %i, %i, %p)", ui, portIndex, bufferSize, format, buffer);
  1204. uiPtr->lv2ui_port_event(portIndex, bufferSize, format, buffer);
  1205. }
  1206. static void lv2ui_cleanup(LV2UI_Handle ui)
  1207. {
  1208. carla_debug("lv2ui_cleanup(%p)", ui);
  1209. uiPtr->lv2ui_cleanup();
  1210. }
  1211. static void lv2ui_select_program(LV2UI_Handle ui, uint32_t bank, uint32_t program)
  1212. {
  1213. carla_debug("lv2ui_select_program(%p, %i, %i)", ui, bank, program);
  1214. uiPtr->lv2ui_select_program(bank, program);
  1215. }
  1216. static int lv2ui_idle(LV2UI_Handle ui)
  1217. {
  1218. return uiPtr->lv2ui_idle();
  1219. }
  1220. static int lv2ui_show(LV2UI_Handle ui)
  1221. {
  1222. carla_debug("lv2ui_show(%p)", ui);
  1223. return uiPtr->lv2ui_show();
  1224. }
  1225. static int lv2ui_hide(LV2UI_Handle ui)
  1226. {
  1227. carla_debug("lv2ui_hide(%p)", ui);
  1228. return uiPtr->lv2ui_hide();
  1229. }
  1230. static const void* lv2ui_extension_data(const char* uri)
  1231. {
  1232. carla_stdout("lv2ui_extension_data(\"%s\")", uri);
  1233. static const LV2UI_Idle_Interface uiidle = { lv2ui_idle };
  1234. static const LV2UI_Show_Interface uishow = { lv2ui_show, lv2ui_hide };
  1235. static const LV2_Programs_UI_Interface uiprograms = { lv2ui_select_program };
  1236. if (std::strcmp(uri, LV2_UI__idleInterface) == 0)
  1237. return &uiidle;
  1238. if (std::strcmp(uri, LV2_UI__showInterface) == 0)
  1239. return &uishow;
  1240. if (std::strcmp(uri, LV2_PROGRAMS__UIInterface) == 0)
  1241. return &uiprograms;
  1242. return nullptr;
  1243. }
  1244. #undef uiPtr
  1245. // -----------------------------------------------------------------------
  1246. // Startup code
  1247. CARLA_EXPORT
  1248. const LV2_Descriptor* lv2_descriptor(uint32_t index)
  1249. {
  1250. carla_debug("lv2_descriptor(%i)", index);
  1251. PluginListManager& plm(PluginListManager::getInstance());
  1252. if (index >= plm.descs.count())
  1253. {
  1254. carla_debug("lv2_descriptor(%i) - out of bounds", index);
  1255. return nullptr;
  1256. }
  1257. if (index < plm.lv2Descs.count())
  1258. {
  1259. carla_debug("lv2_descriptor(%i) - found previously allocated", index);
  1260. return plm.lv2Descs.getAt(index, nullptr);
  1261. }
  1262. const NativePluginDescriptor* const pluginDesc(plm.descs.getAt(index, nullptr));
  1263. CARLA_SAFE_ASSERT_RETURN(pluginDesc != nullptr, nullptr);
  1264. CarlaString tmpURI;
  1265. tmpURI = "http://kxstudio.sf.net/carla/plugins/";
  1266. tmpURI += pluginDesc->label;
  1267. carla_debug("lv2_descriptor(%i) - not found, allocating new with uri \"%s\"", index, (const char*)tmpURI);
  1268. const LV2_Descriptor lv2DescTmp = {
  1269. /* URI */ carla_strdup(tmpURI),
  1270. /* instantiate */ lv2_instantiate,
  1271. /* connect_port */ lv2_connect_port,
  1272. /* activate */ lv2_activate,
  1273. /* run */ lv2_run,
  1274. /* deactivate */ lv2_deactivate,
  1275. /* cleanup */ lv2_cleanup,
  1276. /* extension_data */ lv2_extension_data
  1277. };
  1278. LV2_Descriptor* const lv2Desc(new LV2_Descriptor);
  1279. std::memcpy(lv2Desc, &lv2DescTmp, sizeof(LV2_Descriptor));
  1280. plm.lv2Descs.append(lv2Desc);
  1281. return lv2Desc;
  1282. }
  1283. CARLA_EXPORT
  1284. const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index)
  1285. {
  1286. carla_debug("lv2ui_descriptor(%i)", index);
  1287. static const LV2UI_Descriptor lv2UiDesc = {
  1288. /* URI */ "http://kxstudio.sf.net/carla/ui",
  1289. /* instantiate */ lv2ui_instantiate,
  1290. /* cleanup */ lv2ui_cleanup,
  1291. /* port_event */ lv2ui_port_event,
  1292. /* extension_data */ lv2ui_extension_data
  1293. };
  1294. return (index == 0) ? &lv2UiDesc : nullptr;
  1295. }
  1296. // -----------------------------------------------------------------------