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-native-lv2.cpp 45KB

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