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