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.

CarlaBridgeUI-LV2.cpp 41KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. /*
  2. * Carla Bridge UI, LV2 version
  3. * Copyright (C) 2011-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the GPL.txt file
  16. */
  17. #include "CarlaBridgeClient.hpp"
  18. #include "CarlaLv2Utils.hpp"
  19. #include "CarlaMIDI.h"
  20. #include "RtList.hpp"
  21. #include <QtCore/QDir>
  22. extern "C" {
  23. #include "rtmempool/rtmempool-lv2.h"
  24. }
  25. // -----------------------------------------------------
  26. // Our LV2 World class object
  27. Lv2WorldClass gLv2World;
  28. // -----------------------------------------------------
  29. CARLA_BRIDGE_START_NAMESPACE
  30. #if 0
  31. }
  32. #endif
  33. static uint32_t gBufferSize = 1024;
  34. static double gSampleRate = 44100.0;
  35. // static max values
  36. const unsigned int MAX_EVENT_BUFFER = 8192; // 0x2000
  37. // LV2 URI Map Ids
  38. const uint32_t CARLA_URI_MAP_ID_NULL = 0;
  39. const uint32_t CARLA_URI_MAP_ID_ATOM_BLANK = 1;
  40. const uint32_t CARLA_URI_MAP_ID_ATOM_BOOL = 2;
  41. const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 3;
  42. const uint32_t CARLA_URI_MAP_ID_ATOM_DOUBLE = 4;
  43. const uint32_t CARLA_URI_MAP_ID_ATOM_FLOAT = 5;
  44. const uint32_t CARLA_URI_MAP_ID_ATOM_INT = 6;
  45. const uint32_t CARLA_URI_MAP_ID_ATOM_LITERAL = 7;
  46. const uint32_t CARLA_URI_MAP_ID_ATOM_LONG = 8;
  47. const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 9;
  48. const uint32_t CARLA_URI_MAP_ID_ATOM_PROPERTY = 10;
  49. const uint32_t CARLA_URI_MAP_ID_ATOM_RESOURCE = 11;
  50. const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 12;
  51. const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 13;
  52. const uint32_t CARLA_URI_MAP_ID_ATOM_TUPLE = 14;
  53. const uint32_t CARLA_URI_MAP_ID_ATOM_URI = 15;
  54. const uint32_t CARLA_URI_MAP_ID_ATOM_URID = 16;
  55. const uint32_t CARLA_URI_MAP_ID_ATOM_VECTOR = 17;
  56. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 18;
  57. const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 19;
  58. const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 20;
  59. const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 21;
  60. const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 22;
  61. const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 23;
  62. const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 24;
  63. const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 25;
  64. const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 26;
  65. const uint32_t CARLA_URI_MAP_ID_TIME_POSITION = 27; // base type
  66. const uint32_t CARLA_URI_MAP_ID_TIME_BAR = 28; // values
  67. const uint32_t CARLA_URI_MAP_ID_TIME_BAR_BEAT = 29;
  68. const uint32_t CARLA_URI_MAP_ID_TIME_BEAT = 30;
  69. const uint32_t CARLA_URI_MAP_ID_TIME_BEAT_UNIT = 31;
  70. const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR = 32;
  71. const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE = 33;
  72. const uint32_t CARLA_URI_MAP_ID_TIME_FRAME = 34;
  73. const uint32_t CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND = 35;
  74. const uint32_t CARLA_URI_MAP_ID_TIME_SPEED = 36;
  75. const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 37;
  76. const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 38;
  77. const uint32_t CARLA_URI_MAP_ID_COUNT = 39;
  78. // LV2 Feature Ids
  79. const uint32_t kFeatureIdLogs = 0;
  80. const uint32_t kFeatureIdOptions = 1;
  81. const uint32_t kFeatureIdPrograms = 2;
  82. const uint32_t kFeatureIdStateMakePath = 3;
  83. const uint32_t kFeatureIdStateMapPath = 4;
  84. const uint32_t kFeatureIdUriMap = 5;
  85. const uint32_t kFeatureIdUridMap = 6;
  86. const uint32_t kFeatureIdUridUnmap = 7;
  87. const uint32_t kFeatureIdUiIdle = 8;
  88. const uint32_t kFeatureIdUiFixedSize = 9;
  89. const uint32_t kFeatureIdUiMakeResident = 10;
  90. const uint32_t kFeatureIdUiNoUserResize = 11;
  91. const uint32_t kFeatureIdUiParent = 12;
  92. const uint32_t kFeatureIdUiPortMap = 13;
  93. const uint32_t kFeatureIdUiPortSubscribe = 14;
  94. const uint32_t kFeatureIdUiResize = 15;
  95. const uint32_t kFeatureIdUiTouch = 16;
  96. const uint32_t kFeatureCount = 17;
  97. // -------------------------------------------------------------------------
  98. struct Lv2PluginOptions {
  99. int maxBufferSize;
  100. int minBufferSize;
  101. int sequenceSize;
  102. double sampleRate;
  103. LV2_Options_Option optMaxBlockLenth;
  104. LV2_Options_Option optMinBlockLenth;
  105. LV2_Options_Option optSequenceSize;
  106. LV2_Options_Option optSampleRate;
  107. LV2_Options_Option optNull;
  108. LV2_Options_Option* opts[5];
  109. Lv2PluginOptions()
  110. : maxBufferSize(0),
  111. minBufferSize(0),
  112. sequenceSize(MAX_EVENT_BUFFER),
  113. sampleRate(0.0)
  114. {
  115. optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE;
  116. optMaxBlockLenth.subject = 0;
  117. optMaxBlockLenth.key = CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  118. optMaxBlockLenth.size = sizeof(int);
  119. optMaxBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
  120. optMaxBlockLenth.value = &maxBufferSize;
  121. optMinBlockLenth.context = LV2_OPTIONS_INSTANCE;
  122. optMinBlockLenth.subject = 0;
  123. optMinBlockLenth.key = CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  124. optMinBlockLenth.size = sizeof(int);
  125. optMinBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
  126. optMinBlockLenth.value = &minBufferSize;
  127. optSequenceSize.context = LV2_OPTIONS_INSTANCE;
  128. optSequenceSize.subject = 0;
  129. optSequenceSize.key = CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  130. optSequenceSize.size = sizeof(int);
  131. optSequenceSize.type = CARLA_URI_MAP_ID_ATOM_INT;
  132. optSequenceSize.value = &sequenceSize;
  133. optSampleRate.context = LV2_OPTIONS_INSTANCE;
  134. optSampleRate.subject = 0;
  135. optSampleRate.key = CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  136. optSampleRate.size = sizeof(double);
  137. optSampleRate.type = CARLA_URI_MAP_ID_ATOM_DOUBLE;
  138. optSampleRate.value = &sampleRate;
  139. optNull.context = LV2_OPTIONS_INSTANCE;
  140. optNull.subject = 0;
  141. optNull.key = CARLA_URI_MAP_ID_NULL;
  142. optNull.size = 0;
  143. optNull.type = CARLA_URI_MAP_ID_NULL;
  144. optNull.value = nullptr;
  145. opts[0] = &optMinBlockLenth;
  146. opts[1] = &optMaxBlockLenth;
  147. opts[2] = &optSequenceSize;
  148. opts[3] = &optSampleRate;
  149. opts[4] = &optNull;
  150. }
  151. CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(Lv2PluginOptions)
  152. };
  153. // -------------------------------------------------------------------------
  154. class CarlaLv2Client : public CarlaBridgeClient
  155. {
  156. public:
  157. CarlaLv2Client(const char* const uiTitle)
  158. : CarlaBridgeClient(uiTitle),
  159. fHandle(nullptr),
  160. fWidget(nullptr),
  161. #ifdef CARLA_PROPER_CPP11_SUPPORT
  162. fFeatures{nullptr},
  163. #endif
  164. fDescriptor(nullptr),
  165. fRdfDescriptor(nullptr),
  166. fRdfUiDescriptor(nullptr),
  167. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  168. fIsResizable(false)
  169. #else
  170. fIsResizable(true)
  171. #endif
  172. {
  173. #ifndef CARLA_PROPER_CPP11_SUPPORT
  174. carla_fill<LV2_Feature*>(fFeatures, kFeatureCount+1, nullptr);
  175. #endif
  176. for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; ++i)
  177. fCustomURIDs.append(nullptr);
  178. // ---------------------------------------------------------------
  179. // initialize options
  180. fOptions.minBufferSize = gBufferSize;
  181. fOptions.maxBufferSize = gBufferSize;
  182. fOptions.sampleRate = gSampleRate;
  183. // ---------------------------------------------------------------
  184. // initialize features (part 1)
  185. LV2_Log_Log* const logFt = new LV2_Log_Log;
  186. logFt->handle = this;
  187. logFt->printf = carla_lv2_log_printf;
  188. logFt->vprintf = carla_lv2_log_vprintf;
  189. LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
  190. stateMakePathFt->handle = this;
  191. stateMakePathFt->path = carla_lv2_state_make_path;
  192. LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
  193. stateMapPathFt->handle = this;
  194. stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path;
  195. stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path;
  196. LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
  197. programsFt->handle = this;
  198. programsFt->program_changed = carla_lv2_program_changed;
  199. LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
  200. uriMapFt->callback_data = this;
  201. uriMapFt->uri_to_id = carla_lv2_uri_to_id;
  202. LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
  203. uridMapFt->handle = this;
  204. uridMapFt->map = carla_lv2_urid_map;
  205. LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
  206. uridUnmapFt->handle = this;
  207. uridUnmapFt->unmap = carla_lv2_urid_unmap;
  208. LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
  209. uiPortMapFt->handle = this;
  210. uiPortMapFt->port_index = carla_lv2_ui_port_map;
  211. LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
  212. uiResizeFt->handle = this;
  213. uiResizeFt->ui_resize = carla_lv2_ui_resize;
  214. // ---------------------------------------------------------------
  215. // initialize features (part 2)
  216. for (uint32_t i=0; i < kFeatureCount; ++i)
  217. fFeatures[i] = new LV2_Feature;
  218. fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
  219. fFeatures[kFeatureIdLogs]->data = logFt;
  220. fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
  221. fFeatures[kFeatureIdOptions]->data = fOptions.opts;
  222. fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
  223. fFeatures[kFeatureIdPrograms]->data = programsFt;
  224. fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
  225. fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
  226. fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
  227. fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
  228. fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
  229. fFeatures[kFeatureIdUriMap]->data = uriMapFt;
  230. fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
  231. fFeatures[kFeatureIdUridMap]->data = uridMapFt;
  232. fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
  233. fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
  234. fFeatures[kFeatureIdUiIdle]->URI = LV2_UI__idle;
  235. fFeatures[kFeatureIdUiIdle]->data = nullptr;
  236. fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
  237. fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
  238. fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
  239. fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
  240. fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
  241. fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
  242. fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
  243. fFeatures[kFeatureIdUiParent]->data = nullptr;
  244. fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
  245. fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
  246. fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
  247. fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
  248. fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
  249. fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
  250. fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
  251. fFeatures[kFeatureIdUiTouch]->data = nullptr;
  252. }
  253. ~CarlaLv2Client() override
  254. {
  255. if (fRdfDescriptor != nullptr)
  256. delete fRdfDescriptor;
  257. delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
  258. delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
  259. delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
  260. delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
  261. delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
  262. delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
  263. delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
  264. delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
  265. delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
  266. for (uint32_t i=0; i < kFeatureCount; ++i)
  267. {
  268. if (fFeatures[i] != nullptr)
  269. {
  270. delete fFeatures[i];
  271. fFeatures[i] = nullptr;
  272. }
  273. }
  274. for (NonRtList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
  275. {
  276. const char*& uri(*it);
  277. if (uri != nullptr)
  278. {
  279. delete[] uri;
  280. uri = nullptr;
  281. }
  282. }
  283. fCustomURIDs.clear();
  284. }
  285. // ---------------------------------------------------------------------
  286. // ui initialization
  287. bool uiInit(const char* pluginURI, const char* uiURI) override
  288. {
  289. // -----------------------------------------------------------------
  290. // init
  291. CarlaBridgeClient::uiInit(pluginURI, uiURI);
  292. // -----------------------------------------------------------------
  293. // get plugin from lv2_rdf (lilv)
  294. gLv2World.init();
  295. fRdfDescriptor = lv2_rdf_new(pluginURI);
  296. if (fRdfDescriptor == nullptr)
  297. return false;
  298. // -----------------------------------------------------------------
  299. // find requested UI
  300. for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
  301. {
  302. if (std::strcmp(fRdfDescriptor->UIs[i].URI, uiURI) == 0)
  303. {
  304. fRdfUiDescriptor = &fRdfDescriptor->UIs[i];
  305. break;
  306. }
  307. }
  308. if (fRdfUiDescriptor == nullptr)
  309. return false;
  310. // -----------------------------------------------------------------
  311. // open DLL
  312. if (! uiLibOpen(fRdfUiDescriptor->Binary))
  313. return false;
  314. // -----------------------------------------------------------------
  315. // get DLL main entry
  316. const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)uiLibSymbol("lv2ui_descriptor");
  317. if (ui_descFn == nullptr)
  318. return false;
  319. // -----------------------------------------------------------
  320. // get descriptor that matches URI
  321. uint32_t i = 0;
  322. while ((fDescriptor = ui_descFn(i++)))
  323. {
  324. if (std::strcmp(fDescriptor->URI, uiURI) == 0)
  325. break;
  326. }
  327. if (fDescriptor == nullptr)
  328. return false;
  329. // -----------------------------------------------------------
  330. // initialize UI
  331. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  332. fFeatures[kFeatureIdUiParent]->data = getContainerId();
  333. #endif
  334. fHandle = fDescriptor->instantiate(fDescriptor, pluginURI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures);
  335. if (fHandle == nullptr)
  336. return false;
  337. // -----------------------------------------------------------
  338. // check if not resizable
  339. for (uint32_t i=0; i < fRdfUiDescriptor->FeatureCount && fIsResizable; ++i)
  340. {
  341. if (std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__fixedSize) == 0 || std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
  342. {
  343. fIsResizable = false;
  344. break;
  345. }
  346. }
  347. // -----------------------------------------------------------
  348. // check for known extensions
  349. if (fDescriptor->extension_data != nullptr)
  350. {
  351. for (uint32_t i=0; i < fRdfUiDescriptor->ExtensionCount; ++i)
  352. {
  353. if (std::strcmp(fRdfUiDescriptor->Extensions[i], LV2_PROGRAMS__UIInterface) == 0)
  354. {
  355. fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
  356. fExt.idle = (const LV2UI_Idle_Interface*)fDescriptor->extension_data(LV2_UI__idleInterface);
  357. fExt.programs = (const LV2_Programs_UI_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__UIInterface);
  358. // check if invalid
  359. if (fExt.idle != nullptr && fExt.idle->idle == nullptr)
  360. fExt.idle = nullptr;
  361. if (fExt.programs != nullptr && fExt.programs->select_program == nullptr)
  362. fExt.programs = nullptr;
  363. }
  364. }
  365. }
  366. return true;
  367. }
  368. void uiIdle() override
  369. {
  370. if (fHandle != nullptr && fExt.idle != nullptr)
  371. fExt.idle->idle(fHandle);
  372. }
  373. void uiClose() override
  374. {
  375. CarlaBridgeClient::uiClose();
  376. if (fHandle && fDescriptor && fDescriptor->cleanup)
  377. fDescriptor->cleanup(fHandle);
  378. uiLibClose();
  379. }
  380. // ---------------------------------------------------------------------
  381. // ui management
  382. void* getWidget() const override
  383. {
  384. return fWidget;
  385. }
  386. bool isResizable() const override
  387. {
  388. return fIsResizable;
  389. }
  390. bool needsReparent() const override
  391. {
  392. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  393. return true;
  394. #else
  395. return false;
  396. #endif
  397. }
  398. // ---------------------------------------------------------------------
  399. // ui processing
  400. void setParameter(const int32_t rindex, const float value) override
  401. {
  402. CARLA_ASSERT(fHandle != nullptr && fDescriptor != nullptr);
  403. if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
  404. fDescriptor->port_event(fHandle, rindex, sizeof(float), 0, &value);
  405. }
  406. void setProgram(const uint32_t) override
  407. {
  408. }
  409. void setMidiProgram(const uint32_t bank, const uint32_t program) override
  410. {
  411. CARLA_ASSERT(fHandle != nullptr);
  412. if (fHandle != nullptr && fExt.programs != nullptr)
  413. fExt.programs->select_program(fHandle, bank, program);
  414. }
  415. void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
  416. {
  417. CARLA_ASSERT(fHandle != nullptr && fDescriptor != nullptr);
  418. if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
  419. {
  420. LV2_Atom_MidiEvent midiEv;
  421. midiEv.event.time.frames = 0;
  422. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  423. midiEv.event.body.size = 3;
  424. midiEv.data[0] = MIDI_STATUS_NOTE_ON + channel;
  425. midiEv.data[1] = note;
  426. midiEv.data[2] = velo;
  427. fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  428. }
  429. }
  430. void noteOff(const uint8_t channel, const uint8_t note) override
  431. {
  432. CARLA_ASSERT(fHandle != nullptr && fDescriptor != nullptr);
  433. if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
  434. {
  435. LV2_Atom_MidiEvent midiEv;
  436. midiEv.event.time.frames = 0;
  437. midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
  438. midiEv.event.body.size = 3;
  439. midiEv.data[0] = MIDI_STATUS_NOTE_OFF + channel;
  440. midiEv.data[1] = note;
  441. midiEv.data[2] = 0;
  442. fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
  443. }
  444. }
  445. // ---------------------------------------------------------------------
  446. LV2_URID getCustomURID(const char* const uri)
  447. {
  448. CARLA_ASSERT(uri != nullptr);
  449. carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri);
  450. if (uri == nullptr)
  451. return CARLA_URI_MAP_ID_NULL;
  452. for (size_t i=0; i < fCustomURIDs.count(); ++i)
  453. {
  454. const char*& thisUri(fCustomURIDs.getAt(i));
  455. if (thisUri != nullptr && std::strcmp(thisUri, uri) == 0)
  456. return i;
  457. }
  458. fCustomURIDs.append(carla_strdup(uri));
  459. const LV2_URID urid(fCustomURIDs.count()-1);
  460. if (isOscControlRegistered())
  461. sendOscLv2UridMap(urid, uri);
  462. return urid;
  463. }
  464. const char* getCustomURIString(const LV2_URID urid)
  465. {
  466. CARLA_ASSERT(urid != CARLA_URI_MAP_ID_NULL);
  467. CARLA_ASSERT_INT2(urid < fCustomURIDs.count(), urid, fCustomURIDs.count());
  468. carla_debug("CarlaLv2Client::getCustomURIString(%i)", urid);
  469. if (urid == CARLA_URI_MAP_ID_NULL)
  470. return nullptr;
  471. if (urid < fCustomURIDs.count())
  472. return fCustomURIDs.getAt(urid);
  473. return nullptr;
  474. }
  475. // ---------------------------------------------------------------------
  476. void handleProgramChanged(const int32_t /*index*/)
  477. {
  478. if (isOscControlRegistered())
  479. sendOscConfigure("reloadprograms", "");
  480. }
  481. uint32_t handleUiPortMap(const char* const symbol)
  482. {
  483. CARLA_ASSERT(symbol != nullptr);
  484. if (symbol == nullptr)
  485. return LV2UI_INVALID_PORT_INDEX;
  486. for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
  487. {
  488. if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
  489. return i;
  490. }
  491. return LV2UI_INVALID_PORT_INDEX;
  492. }
  493. int handleUiResize(const int width, const int height)
  494. {
  495. CARLA_ASSERT(width > 0);
  496. CARLA_ASSERT(height > 0);
  497. if (width <= 0 || height <= 0)
  498. return 1;
  499. toolkitResize(width, height);
  500. return 0;
  501. }
  502. void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
  503. {
  504. if (format == 0)
  505. {
  506. CARLA_ASSERT(buffer != nullptr);
  507. CARLA_ASSERT(bufferSize == sizeof(float));
  508. if (bufferSize != sizeof(float))
  509. return;
  510. if (buffer == nullptr || bufferSize != sizeof(float))
  511. return;
  512. const float value(*(const float*)buffer);
  513. if (isOscControlRegistered())
  514. sendOscControl(portIndex, value);
  515. }
  516. else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  517. {
  518. CARLA_ASSERT(bufferSize != 0);
  519. CARLA_ASSERT(buffer != nullptr);
  520. if (bufferSize == 0 || buffer == nullptr)
  521. return;
  522. if (isOscControlRegistered())
  523. sendOscLv2AtomTransfer(portIndex, QByteArray((const char*)buffer, bufferSize).toBase64().constData());
  524. }
  525. else
  526. {
  527. carla_stdout("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format", portIndex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
  528. }
  529. }
  530. // ---------------------------------------------------------------------
  531. void handleAtomTransfer(const uint32_t portIndex, const LV2_Atom* const atom)
  532. {
  533. CARLA_ASSERT(atom != nullptr);
  534. carla_debug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom);
  535. if (atom != nullptr && fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
  536. fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
  537. }
  538. void handleUridMap(const LV2_URID urid, const char* const uri)
  539. {
  540. CARLA_ASSERT(urid != CARLA_URI_MAP_ID_NULL);
  541. CARLA_ASSERT(uri != nullptr);
  542. carla_debug("CarlaLv2Client::handleUridMap(%i, \"%s\")", urid, uri);
  543. // TODO
  544. }
  545. private:
  546. LV2UI_Handle fHandle;
  547. LV2UI_Widget fWidget;
  548. LV2_Feature* fFeatures[kFeatureCount+1];
  549. const LV2UI_Descriptor* fDescriptor;
  550. const LV2_RDF_Descriptor* fRdfDescriptor;
  551. const LV2_RDF_UI* fRdfUiDescriptor;
  552. Lv2PluginOptions fOptions;
  553. bool fIsResizable;
  554. NonRtList<const char*> fCustomURIDs;
  555. struct Extensions {
  556. const LV2_Options_Interface* options;
  557. const LV2UI_Idle_Interface* idle;
  558. const LV2_Programs_UI_Interface* programs;
  559. Extensions()
  560. : options(nullptr),
  561. idle(nullptr),
  562. programs(nullptr) {}
  563. } fExt;
  564. // -------------------------------------------------------------------
  565. // Logs Feature
  566. static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
  567. {
  568. CARLA_ASSERT(handle != nullptr);
  569. CARLA_ASSERT(type > CARLA_URI_MAP_ID_NULL);
  570. #ifndef DEBUG
  571. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  572. return 0;
  573. #endif
  574. va_list args;
  575. va_start(args, fmt);
  576. const int ret = carla_lv2_log_vprintf(handle, type, fmt, args);
  577. va_end(args);
  578. return ret;
  579. }
  580. static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
  581. {
  582. CARLA_ASSERT(handle != nullptr);
  583. CARLA_ASSERT(type > CARLA_URI_MAP_ID_NULL);
  584. #ifndef DEBUG
  585. if (type == CARLA_URI_MAP_ID_LOG_TRACE)
  586. return 0;
  587. #endif
  588. int ret = 0;
  589. switch (type)
  590. {
  591. case CARLA_URI_MAP_ID_LOG_ERROR:
  592. #ifndef CARLA_OS_WIN
  593. std::fprintf(stderr, "\x1b[31m");
  594. #endif
  595. ret = std::vfprintf(stderr, fmt, ap);
  596. #ifndef CARLA_OS_WIN
  597. std::fprintf(stderr, "\x1b[0m");
  598. #endif
  599. break;
  600. case CARLA_URI_MAP_ID_LOG_NOTE:
  601. ret = std::vfprintf(stdout, fmt, ap);
  602. break;
  603. case CARLA_URI_MAP_ID_LOG_TRACE:
  604. #ifdef DEBUG
  605. # ifndef CARLA_OS_WIN
  606. std::fprintf(stdout, "\x1b[30;1m");
  607. # endif
  608. ret = std::vfprintf(stdout, fmt, ap);
  609. # ifndef CARLA_OS_WIN
  610. std::fprintf(stdout, "\x1b[0m");
  611. # endif
  612. #endif
  613. break;
  614. case CARLA_URI_MAP_ID_LOG_WARNING:
  615. ret = std::vfprintf(stderr, fmt, ap);
  616. break;
  617. default:
  618. break;
  619. }
  620. return ret;
  621. }
  622. // -------------------------------------------------------------------
  623. // Programs Feature
  624. static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
  625. {
  626. carla_debug("CarlaLv2Client::carla_lv2_program_changed(%p, %i)", handle, index);
  627. CARLA_ASSERT(handle != nullptr);
  628. if (handle == nullptr)
  629. return;
  630. ((CarlaLv2Client*)handle)->handleProgramChanged(index);
  631. }
  632. // -------------------------------------------------------------------
  633. // State Feature
  634. static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
  635. {
  636. carla_debug("CarlaLv2Client::carla_lv2_state_make_path(%p, \"%s\")", handle, path);
  637. CARLA_ASSERT(handle != nullptr);
  638. CARLA_ASSERT(path != nullptr);
  639. if (path == nullptr)
  640. return nullptr;
  641. QDir dir;
  642. dir.mkpath(path);
  643. return strdup(path);
  644. }
  645. static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path)
  646. {
  647. carla_debug("CarlaLv2Client::carla_lv2_state_map_abstract_path(%p, \"%s\")", handle, absolute_path);
  648. CARLA_ASSERT(handle != nullptr);
  649. CARLA_ASSERT(absolute_path != nullptr);
  650. if (absolute_path == nullptr)
  651. return nullptr;
  652. QDir dir(absolute_path);
  653. return strdup(dir.canonicalPath().toUtf8().constData());
  654. }
  655. static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path)
  656. {
  657. carla_debug("CarlaLv2Client::carla_lv2_state_map_absolute_path(%p, \"%s\")", handle, abstract_path);
  658. CARLA_ASSERT(handle != nullptr);
  659. CARLA_ASSERT(abstract_path != nullptr);
  660. if (abstract_path == nullptr)
  661. return nullptr;
  662. QDir dir(abstract_path);
  663. return strdup(dir.absolutePath().toUtf8().constData());
  664. }
  665. // -------------------------------------------------------------------
  666. // URI-Map Feature
  667. static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
  668. {
  669. carla_debug("CarlaLv2Client::carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
  670. return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
  671. // unused
  672. (void)map;
  673. }
  674. // -------------------------------------------------------------------
  675. // URID Feature
  676. static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
  677. {
  678. CARLA_ASSERT(handle != nullptr);
  679. CARLA_ASSERT(uri != nullptr);
  680. carla_debug("CarlaLv2Client::carla_lv2_urid_map(%p, \"%s\")", handle, uri);
  681. if (uri == nullptr)
  682. return CARLA_URI_MAP_ID_NULL;
  683. // Atom types
  684. if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
  685. return CARLA_URI_MAP_ID_ATOM_BLANK;
  686. if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
  687. return CARLA_URI_MAP_ID_ATOM_BOOL;
  688. if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
  689. return CARLA_URI_MAP_ID_ATOM_CHUNK;
  690. if (std::strcmp(uri, LV2_ATOM__Double) == 0)
  691. return CARLA_URI_MAP_ID_ATOM_DOUBLE;
  692. if (std::strcmp(uri, LV2_ATOM__Float) == 0)
  693. return CARLA_URI_MAP_ID_ATOM_FLOAT;
  694. if (std::strcmp(uri, LV2_ATOM__Int) == 0)
  695. return CARLA_URI_MAP_ID_ATOM_INT;
  696. if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
  697. return CARLA_URI_MAP_ID_ATOM_LITERAL;
  698. if (std::strcmp(uri, LV2_ATOM__Long) == 0)
  699. return CARLA_URI_MAP_ID_ATOM_LONG;
  700. if (std::strcmp(uri, LV2_ATOM__Path) == 0)
  701. return CARLA_URI_MAP_ID_ATOM_PATH;
  702. if (std::strcmp(uri, LV2_ATOM__Property) == 0)
  703. return CARLA_URI_MAP_ID_ATOM_PROPERTY;
  704. if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
  705. return CARLA_URI_MAP_ID_ATOM_RESOURCE;
  706. if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
  707. return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
  708. if (std::strcmp(uri, LV2_ATOM__String) == 0)
  709. return CARLA_URI_MAP_ID_ATOM_STRING;
  710. if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
  711. return CARLA_URI_MAP_ID_ATOM_TUPLE;
  712. if (std::strcmp(uri, LV2_ATOM__URI) == 0)
  713. return CARLA_URI_MAP_ID_ATOM_URI;
  714. if (std::strcmp(uri, LV2_ATOM__URID) == 0)
  715. return CARLA_URI_MAP_ID_ATOM_URID;
  716. if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
  717. return CARLA_URI_MAP_ID_ATOM_VECTOR;
  718. if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
  719. return CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM;
  720. if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
  721. return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT;
  722. // BufSize types
  723. if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
  724. return CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
  725. if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
  726. return CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
  727. if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
  728. return CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
  729. // Log types
  730. if (std::strcmp(uri, LV2_LOG__Error) == 0)
  731. return CARLA_URI_MAP_ID_LOG_ERROR;
  732. if (std::strcmp(uri, LV2_LOG__Note) == 0)
  733. return CARLA_URI_MAP_ID_LOG_NOTE;
  734. if (std::strcmp(uri, LV2_LOG__Trace) == 0)
  735. return CARLA_URI_MAP_ID_LOG_TRACE;
  736. if (std::strcmp(uri, LV2_LOG__Warning) == 0)
  737. return CARLA_URI_MAP_ID_LOG_WARNING;
  738. // Time types
  739. if (std::strcmp(uri, LV2_TIME__Position) == 0)
  740. return CARLA_URI_MAP_ID_TIME_POSITION;
  741. if (std::strcmp(uri, LV2_TIME__bar) == 0)
  742. return CARLA_URI_MAP_ID_TIME_BAR;
  743. if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
  744. return CARLA_URI_MAP_ID_TIME_BAR_BEAT;
  745. if (std::strcmp(uri, LV2_TIME__beat) == 0)
  746. return CARLA_URI_MAP_ID_TIME_BEAT;
  747. if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
  748. return CARLA_URI_MAP_ID_TIME_BEAT_UNIT;
  749. if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
  750. return CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR;
  751. if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
  752. return CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE;
  753. if (std::strcmp(uri, LV2_TIME__frame) == 0)
  754. return CARLA_URI_MAP_ID_TIME_FRAME;
  755. if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
  756. return CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND;
  757. if (std::strcmp(uri, LV2_TIME__speed) == 0)
  758. return CARLA_URI_MAP_ID_TIME_SPEED;
  759. // Others
  760. if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
  761. return CARLA_URI_MAP_ID_MIDI_EVENT;
  762. if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
  763. return CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
  764. if (handle == nullptr)
  765. return CARLA_URI_MAP_ID_NULL;
  766. // Custom types
  767. return ((CarlaLv2Client*)handle)->getCustomURID(uri);
  768. }
  769. static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
  770. {
  771. carla_debug("CarlaLv2Client::carla_lv2_urid_unmap(%p, %i)", handle, urid);
  772. CARLA_ASSERT(handle != nullptr);
  773. CARLA_ASSERT(urid > CARLA_URI_MAP_ID_NULL);
  774. if (urid == CARLA_URI_MAP_ID_NULL)
  775. return nullptr;
  776. // Atom types
  777. if (urid == CARLA_URI_MAP_ID_ATOM_BLANK)
  778. return LV2_ATOM__Blank;
  779. if (urid == CARLA_URI_MAP_ID_ATOM_BOOL)
  780. return LV2_ATOM__Bool;
  781. if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK)
  782. return LV2_ATOM__Chunk;
  783. if (urid == CARLA_URI_MAP_ID_ATOM_DOUBLE)
  784. return LV2_ATOM__Double;
  785. if (urid == CARLA_URI_MAP_ID_ATOM_FLOAT)
  786. return LV2_ATOM__Float;
  787. if (urid == CARLA_URI_MAP_ID_ATOM_INT)
  788. return LV2_ATOM__Int;
  789. if (urid == CARLA_URI_MAP_ID_ATOM_LITERAL)
  790. return LV2_ATOM__Literal;
  791. if (urid == CARLA_URI_MAP_ID_ATOM_LONG)
  792. return LV2_ATOM__Long;
  793. if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
  794. return LV2_ATOM__Path;
  795. if (urid == CARLA_URI_MAP_ID_ATOM_PROPERTY)
  796. return LV2_ATOM__Property;
  797. if (urid == CARLA_URI_MAP_ID_ATOM_RESOURCE)
  798. return LV2_ATOM__Resource;
  799. if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
  800. return LV2_ATOM__Sequence;
  801. if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
  802. return LV2_ATOM__String;
  803. if (urid == CARLA_URI_MAP_ID_ATOM_TUPLE)
  804. return LV2_ATOM__Tuple;
  805. if (urid == CARLA_URI_MAP_ID_ATOM_URI)
  806. return LV2_ATOM__URI;
  807. if (urid == CARLA_URI_MAP_ID_ATOM_URID)
  808. return LV2_ATOM__URID;
  809. if (urid == CARLA_URI_MAP_ID_ATOM_VECTOR)
  810. return LV2_ATOM__Vector;
  811. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM)
  812. return LV2_ATOM__atomTransfer;
  813. if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
  814. return LV2_ATOM__eventTransfer;
  815. // BufSize types
  816. if (urid == CARLA_URI_MAP_ID_BUF_MAX_LENGTH)
  817. return LV2_BUF_SIZE__maxBlockLength;
  818. if (urid == CARLA_URI_MAP_ID_BUF_MIN_LENGTH)
  819. return LV2_BUF_SIZE__minBlockLength;
  820. if (urid == CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE)
  821. return LV2_BUF_SIZE__sequenceSize;
  822. // Log types
  823. if (urid == CARLA_URI_MAP_ID_LOG_ERROR)
  824. return LV2_LOG__Error;
  825. if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
  826. return LV2_LOG__Note;
  827. if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
  828. return LV2_LOG__Trace;
  829. if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
  830. return LV2_LOG__Warning;
  831. // Time types
  832. if (urid == CARLA_URI_MAP_ID_TIME_POSITION)
  833. return LV2_TIME__Position;
  834. if (urid == CARLA_URI_MAP_ID_TIME_BAR)
  835. return LV2_TIME__bar;
  836. if (urid == CARLA_URI_MAP_ID_TIME_BAR_BEAT)
  837. return LV2_TIME__barBeat;
  838. if (urid == CARLA_URI_MAP_ID_TIME_BEAT)
  839. return LV2_TIME__beat;
  840. if (urid == CARLA_URI_MAP_ID_TIME_BEAT_UNIT)
  841. return LV2_TIME__beatUnit;
  842. if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR)
  843. return LV2_TIME__beatsPerBar;
  844. if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE)
  845. return LV2_TIME__beatsPerMinute;
  846. if (urid == CARLA_URI_MAP_ID_TIME_FRAME)
  847. return LV2_TIME__frame;
  848. if (urid == CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND)
  849. return LV2_TIME__framesPerSecond;
  850. if (urid == CARLA_URI_MAP_ID_TIME_SPEED)
  851. return LV2_TIME__speed;
  852. // Others
  853. if (urid == CARLA_URI_MAP_ID_MIDI_EVENT)
  854. return LV2_MIDI__MidiEvent;
  855. if (urid == CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE)
  856. return LV2_PARAMETERS__sampleRate;
  857. if (handle == nullptr)
  858. return nullptr;
  859. // Custom types
  860. return ((CarlaLv2Client*)handle)->getCustomURIString(urid);
  861. }
  862. // -------------------------------------------------------------------
  863. // UI Port-Map Feature
  864. static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
  865. {
  866. carla_debug("CarlaLv2Client::carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
  867. CARLA_ASSERT(handle);
  868. if (handle == nullptr)
  869. return LV2UI_INVALID_PORT_INDEX;
  870. return ((CarlaLv2Client*)handle)->handleUiPortMap(symbol);
  871. }
  872. // -------------------------------------------------------------------
  873. // UI Resize Feature
  874. static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
  875. {
  876. carla_debug("CarlaLv2Client::carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
  877. CARLA_ASSERT(handle != nullptr);
  878. if (handle == nullptr)
  879. return 1;
  880. return ((CarlaLv2Client*)handle)->handleUiResize(width, height);
  881. }
  882. // -------------------------------------------------------------------
  883. // UI Extension
  884. static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
  885. {
  886. CARLA_ASSERT(controller != nullptr);
  887. carla_debug("CarlaLv2Client::carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
  888. if (controller == nullptr)
  889. return;
  890. ((CarlaLv2Client*)controller)->handleUiWrite(port_index, buffer_size, format, buffer);
  891. }
  892. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client)
  893. };
  894. #define lv2ClientPtr ((CarlaLv2Client*)kClient)
  895. int CarlaBridgeOsc::handleMsgLv2AtomTransfer(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  896. {
  897. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
  898. carla_debug("CarlaBridgeOsc::handleMsgLv2AtomTransfer()");
  899. if (kClient == nullptr)
  900. return 1;
  901. const int32_t portIndex = argv[0]->i;
  902. const char* const atomBuf = (const char*)&argv[1]->s;
  903. if (portIndex < 0)
  904. return 0;
  905. QByteArray chunk;
  906. chunk = QByteArray::fromBase64(atomBuf);
  907. LV2_Atom* const atom = (LV2_Atom*)chunk.constData();
  908. lv2ClientPtr->handleAtomTransfer(portIndex, atom);
  909. return 0;
  910. }
  911. int CarlaBridgeOsc::handleMsgLv2UridMap(CARLA_BRIDGE_OSC_HANDLE_ARGS)
  912. {
  913. CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
  914. carla_debug("CarlaBridgeOsc::handleMsgLv2UridMap()");
  915. if (kClient == nullptr)
  916. return 1;
  917. const int32_t urid = argv[0]->i;
  918. const char* const uri = (const char*)&argv[1]->s;
  919. if (urid <= 0)
  920. return 0;
  921. lv2ClientPtr->handleUridMap(urid, uri);
  922. return 0;
  923. }
  924. #undef lv2ClientPtr
  925. CARLA_BRIDGE_END_NAMESPACE
  926. int main(int argc, char* argv[])
  927. {
  928. CARLA_BRIDGE_USE_NAMESPACE
  929. if (argc != 5)
  930. {
  931. carla_stderr("usage: %s <osc-url|\"null\"> <plugin-uri> <ui-uri> <ui-title>", argv[0]);
  932. return 1;
  933. }
  934. const char* oscUrl = argv[1];
  935. const char* pluginURI = argv[2];
  936. const char* uiURI = argv[3];
  937. const char* uiTitle = argv[4];
  938. const bool useOsc(std::strcmp(oscUrl, "null") != 0);
  939. // try to get sampleRate value
  940. if (const char* const sampleRateStr = getenv("CARLA_SAMPLE_RATE"))
  941. gSampleRate = atof(sampleRateStr);
  942. // Init LV2 client
  943. CarlaLv2Client client(uiTitle);
  944. // Init OSC
  945. if (useOsc)
  946. client.oscInit(oscUrl);
  947. // Load UI
  948. int ret;
  949. if (client.uiInit(pluginURI, uiURI))
  950. {
  951. client.toolkitExec(!useOsc);
  952. ret = 0;
  953. }
  954. else
  955. {
  956. carla_stderr("Failed to load LV2 UI");
  957. ret = 1;
  958. }
  959. // Close OSC
  960. if (useOsc)
  961. client.oscClose();
  962. // Close LV2 client
  963. client.uiClose();
  964. return ret;
  965. }