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.

4385 lines
155KB

  1. // SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. /* TODO list
  4. * noexcept safe calls
  5. * paramId vs index
  6. */
  7. #include "CarlaPluginInternal.hpp"
  8. #include "CarlaEngine.hpp"
  9. #include "CarlaBackendUtils.hpp"
  10. #include "CarlaVst3Utils.hpp"
  11. #include "CarlaPluginUI.hpp"
  12. #ifdef CARLA_OS_MAC
  13. # include "CarlaMacUtils.hpp"
  14. # import <Foundation/Foundation.h>
  15. #endif
  16. #include "water/files/File.h"
  17. #include "water/misc/Time.h"
  18. #if defined(V3_VIEW_PLATFORM_TYPE_NATIVE) && defined(_POSIX_VERSION)
  19. # ifdef CARLA_OS_LINUX
  20. # define CARLA_VST3_POSIX_EPOLL
  21. # include <sys/epoll.h>
  22. # else
  23. # include <sys/event.h>
  24. # include <sys/types.h>
  25. # endif
  26. #endif
  27. #include <atomic>
  28. #include <unordered_map>
  29. CARLA_BACKEND_START_NAMESPACE
  30. // --------------------------------------------------------------------------------------------------------------------
  31. static inline
  32. size_t strlen_utf16(const int16_t* const str)
  33. {
  34. size_t i = 0;
  35. while (str[i] != 0)
  36. ++i;
  37. return i;
  38. }
  39. // --------------------------------------------------------------------------------------------------------------------
  40. static inline
  41. void strncpy_utf8(char* const dst, const int16_t* const src, const size_t length)
  42. {
  43. CARLA_SAFE_ASSERT_RETURN(length > 0,);
  44. if (const size_t len = std::min(strlen_utf16(src), length-1U))
  45. {
  46. for (size_t i=0; i<len; ++i)
  47. {
  48. // skip non-ascii chars, unsupported
  49. if (src[i] >= 0x80)
  50. continue;
  51. dst[i] = static_cast<char>(src[i]);
  52. }
  53. dst[len] = 0;
  54. }
  55. else
  56. {
  57. dst[0] = 0;
  58. }
  59. }
  60. // --------------------------------------------------------------------------------------------------------------------
  61. struct v3HostCallback {
  62. virtual ~v3HostCallback() {}
  63. // v3_component_handler
  64. virtual v3_result v3BeginEdit(v3_param_id) = 0;
  65. virtual v3_result v3PerformEdit(v3_param_id, double) = 0;
  66. virtual v3_result v3EndEdit(v3_param_id) = 0;
  67. virtual v3_result v3RestartComponent(int32_t) = 0;
  68. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  69. // v3_plugin_frame
  70. virtual v3_result v3ResizeView(struct v3_plugin_view**, struct v3_view_rect*) = 0;
  71. #endif
  72. };
  73. // --------------------------------------------------------------------------------------------------------------------
  74. struct v3_var {
  75. char type;
  76. uint32_t size;
  77. union {
  78. int64_t i;
  79. double f;
  80. int16_t* s;
  81. void* b;
  82. } value;
  83. };
  84. static void v3_var_cleanup(v3_var& var)
  85. {
  86. switch (var.type)
  87. {
  88. case 's':
  89. std::free(var.value.s);
  90. break;
  91. case 'b':
  92. std::free(var.value.b);
  93. break;
  94. }
  95. carla_zeroStruct(var);
  96. }
  97. struct carla_v3_attribute_list : v3_attribute_list_cpp {
  98. // std::atomic<int> refcounter;
  99. std::unordered_map<std::string, v3_var> vars;
  100. carla_v3_attribute_list()
  101. // : refcounter(1)
  102. {
  103. query_interface = v3_query_interface_static<v3_attribute_list_iid>;
  104. ref = v3_ref_static;
  105. unref = v3_unref_static;
  106. attrlist.set_int = set_int;
  107. attrlist.get_int = get_int;
  108. attrlist.set_float = set_float;
  109. attrlist.get_float = get_float;
  110. attrlist.set_string = set_string;
  111. attrlist.get_string = get_string;
  112. attrlist.set_binary = set_binary;
  113. attrlist.get_binary = get_binary;
  114. }
  115. ~carla_v3_attribute_list()
  116. {
  117. for (std::unordered_map<std::string, v3_var>::iterator it = vars.begin(); it != vars.end(); ++it)
  118. v3_var_cleanup(it->second);
  119. }
  120. v3_result add(const char* const id, const v3_var& var)
  121. {
  122. const std::string sid(id);
  123. for (std::unordered_map<std::string, v3_var>::iterator it = vars.begin(); it != vars.end(); ++it)
  124. {
  125. if (it->first == sid)
  126. {
  127. v3_var_cleanup(it->second);
  128. break;
  129. }
  130. }
  131. vars[sid] = var;
  132. return V3_OK;
  133. }
  134. bool get(const char* const id, v3_var& var)
  135. {
  136. const std::string sid(id);
  137. for (std::unordered_map<std::string, v3_var>::iterator it = vars.begin(); it != vars.end(); ++it)
  138. {
  139. if (it->first == sid)
  140. {
  141. var = it->second;
  142. return true;
  143. }
  144. }
  145. return false;
  146. }
  147. private:
  148. static v3_result V3_API set_int(void* const self, const char* const id, const int64_t value)
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  151. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  152. v3_var var = {};
  153. var.type = 'i';
  154. var.value.i = value;
  155. return attrlist->add(id, var);
  156. }
  157. static v3_result V3_API get_int(void* const self, const char* const id, int64_t* const value)
  158. {
  159. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  160. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  161. v3_var var = {};
  162. if (attrlist->get(id, var))
  163. {
  164. *value = var.value.i;
  165. return V3_OK;
  166. }
  167. return V3_INVALID_ARG;
  168. }
  169. static v3_result V3_API set_float(void* const self, const char* const id, const double value)
  170. {
  171. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  172. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  173. v3_var var = {};
  174. var.type = 'f';
  175. var.value.f = value;
  176. return attrlist->add(id, var);
  177. }
  178. static v3_result V3_API get_float(void* const self, const char* const id, double* const value)
  179. {
  180. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  181. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  182. v3_var var = {};
  183. if (attrlist->get(id, var))
  184. {
  185. *value = var.value.f;
  186. return V3_OK;
  187. }
  188. return V3_INVALID_ARG;
  189. }
  190. static v3_result V3_API set_string(void* const self, const char* const id, const int16_t* const string)
  191. {
  192. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  193. CARLA_SAFE_ASSERT_RETURN(string != nullptr, V3_INVALID_ARG);
  194. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  195. const size_t size = sizeof(int16_t) * (strlen_utf16(string) + 1);
  196. int16_t* const s = static_cast<int16_t*>(std::malloc(size));
  197. CARLA_SAFE_ASSERT_RETURN(s != nullptr, V3_NOMEM);
  198. std::memcpy(s, string, size);
  199. v3_var var = {};
  200. var.type = 's';
  201. var.size = size;
  202. var.value.s = s;
  203. return attrlist->add(id, var);
  204. }
  205. static v3_result V3_API get_string(void* const self, const char* const id,
  206. int16_t* const string, const uint32_t size)
  207. {
  208. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  209. CARLA_SAFE_ASSERT_RETURN(string != nullptr, V3_INVALID_ARG);
  210. CARLA_SAFE_ASSERT_RETURN(size != 0, V3_INVALID_ARG);
  211. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  212. v3_var var = {};
  213. if (attrlist->get(id, var))
  214. {
  215. CARLA_SAFE_ASSERT_UINT2_RETURN(var.size >= size, var.size, size, V3_INVALID_ARG);
  216. std::memcpy(string, var.value.s, size);
  217. return V3_OK;
  218. }
  219. return V3_INVALID_ARG;
  220. }
  221. static v3_result V3_API set_binary(void* const self, const char* const id,
  222. const void* const data, const uint32_t size)
  223. {
  224. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  225. CARLA_SAFE_ASSERT_RETURN(data != nullptr, V3_INVALID_ARG);
  226. CARLA_SAFE_ASSERT_RETURN(size != 0, V3_INVALID_ARG);
  227. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  228. void* const b = std::malloc(size);
  229. CARLA_SAFE_ASSERT_RETURN(b != nullptr, V3_NOMEM);
  230. std::memcpy(b, data, size);
  231. v3_var var = {};
  232. var.type = 'b';
  233. var.size = size;
  234. var.value.b = b;
  235. return attrlist->add(id, var);
  236. }
  237. static v3_result V3_API get_binary(void* const self, const char* const id,
  238. const void** const data, uint32_t* const size)
  239. {
  240. CARLA_SAFE_ASSERT_RETURN(id != nullptr, V3_INVALID_ARG);
  241. carla_v3_attribute_list* const attrlist = *static_cast<carla_v3_attribute_list**>(self);
  242. v3_var var = {};
  243. if (attrlist->get(id, var))
  244. {
  245. *data = var.value.b;
  246. *size = var.size;
  247. return V3_OK;
  248. }
  249. return V3_INVALID_ARG;
  250. }
  251. CARLA_DECLARE_NON_COPYABLE(carla_v3_attribute_list)
  252. CARLA_PREVENT_HEAP_ALLOCATION
  253. };
  254. struct carla_v3_message : v3_message_cpp {
  255. std::atomic<int> refcounter;
  256. carla_v3_attribute_list attrlist;
  257. carla_v3_attribute_list* attrlistptr;
  258. const char* msgId;
  259. carla_v3_message()
  260. : refcounter(1),
  261. attrlistptr(&attrlist),
  262. msgId(nullptr)
  263. {
  264. query_interface = v3_query_interface<carla_v3_message, v3_message_iid>;
  265. ref = v3_ref<carla_v3_message>;
  266. unref = v3_unref<carla_v3_message>;
  267. msg.get_message_id = get_message_id;
  268. msg.set_message_id = set_message_id;
  269. msg.get_attributes = get_attributes;
  270. }
  271. ~carla_v3_message()
  272. {
  273. delete[] msgId;
  274. }
  275. private:
  276. static const char* V3_API get_message_id(void* const self)
  277. {
  278. carla_v3_message* const msg = *static_cast<carla_v3_message**>(self);
  279. return msg->msgId;
  280. }
  281. static void V3_API set_message_id(void* const self, const char* const id)
  282. {
  283. carla_v3_message* const msg = *static_cast<carla_v3_message**>(self);
  284. delete[] msg->msgId;
  285. msg->msgId = id != nullptr ? carla_strdup(id) : nullptr;
  286. }
  287. static v3_attribute_list** V3_API get_attributes(void* const self)
  288. {
  289. carla_v3_message* const msg = *static_cast<carla_v3_message**>(self);
  290. return (v3_attribute_list**)&msg->attrlistptr;
  291. }
  292. CARLA_DECLARE_NON_COPYABLE(carla_v3_message)
  293. };
  294. // --------------------------------------------------------------------------------------------------------------------
  295. struct carla_v3_bstream : v3_bstream_cpp {
  296. // to be filled by class producer
  297. void* buffer;
  298. int64_t size;
  299. bool canRead, canWrite;
  300. // used by class consumer
  301. int64_t readPos;
  302. carla_v3_bstream()
  303. : buffer(nullptr),
  304. size(0),
  305. canRead(false),
  306. canWrite(false),
  307. readPos(0)
  308. {
  309. query_interface = v3_query_interface_static<v3_bstream_iid>;
  310. ref = v3_ref_static;
  311. unref = v3_unref_static;
  312. stream.read = read;
  313. stream.write = write;
  314. stream.seek = seek;
  315. stream.tell = tell;
  316. }
  317. private:
  318. static v3_result V3_API read(void* const self, void* const buffer, int32_t num_bytes, int32_t* const bytes_read)
  319. {
  320. carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self);
  321. CARLA_SAFE_ASSERT_RETURN(buffer != nullptr, V3_INVALID_ARG);
  322. CARLA_SAFE_ASSERT_RETURN(num_bytes > 0, V3_INVALID_ARG);
  323. CARLA_SAFE_ASSERT_RETURN(stream->canRead, V3_INVALID_ARG);
  324. if (stream->readPos + num_bytes > stream->size)
  325. num_bytes = stream->size - stream->readPos;
  326. std::memcpy(buffer, static_cast<uint8_t*>(stream->buffer) + stream->readPos, num_bytes);
  327. stream->readPos += num_bytes;
  328. // this is nasty, some plugins do not care about incomplete reads!
  329. if (bytes_read != nullptr)
  330. *bytes_read = num_bytes;
  331. return V3_OK;
  332. }
  333. static v3_result V3_API write(void* const self,
  334. void* const buffer, const int32_t num_bytes, int32_t* const bytes_read)
  335. {
  336. carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self);
  337. CARLA_SAFE_ASSERT_RETURN(buffer != nullptr, V3_INVALID_ARG);
  338. CARLA_SAFE_ASSERT_RETURN(num_bytes > 0, V3_INVALID_ARG);
  339. CARLA_SAFE_ASSERT_RETURN(stream->canWrite, V3_INVALID_ARG);
  340. void* const newbuffer = std::realloc(stream->buffer, stream->size + num_bytes);
  341. CARLA_SAFE_ASSERT_RETURN(newbuffer != nullptr, V3_NOMEM);
  342. std::memcpy(static_cast<uint8_t*>(newbuffer) + stream->size, buffer, num_bytes);
  343. stream->buffer = newbuffer;
  344. stream->size += num_bytes;
  345. // this is nasty, some plugins do not care about incomplete writes!
  346. if (bytes_read != nullptr)
  347. *bytes_read = num_bytes;
  348. return V3_OK;
  349. }
  350. static v3_result V3_API seek(void* const self, const int64_t pos, const int32_t seek_mode, int64_t* const result)
  351. {
  352. carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self);
  353. CARLA_SAFE_ASSERT_RETURN(stream->canRead, V3_INVALID_ARG);
  354. switch (seek_mode)
  355. {
  356. case V3_SEEK_SET:
  357. CARLA_SAFE_ASSERT_INT2_RETURN(pos <= stream->size, pos, stream->size, V3_INVALID_ARG);
  358. stream->readPos = pos;
  359. break;
  360. case V3_SEEK_CUR:
  361. CARLA_SAFE_ASSERT_INT2_RETURN(stream->readPos + pos <= stream->size, pos, stream->size, V3_INVALID_ARG);
  362. stream->readPos = stream->readPos + pos;
  363. break;
  364. case V3_SEEK_END:
  365. CARLA_SAFE_ASSERT_INT2_RETURN(pos <= stream->size, pos, stream->size, V3_INVALID_ARG);
  366. stream->readPos = stream->size - pos;
  367. break;
  368. default:
  369. return V3_INVALID_ARG;
  370. }
  371. if (result != nullptr)
  372. *result = stream->readPos;
  373. return V3_OK;
  374. }
  375. static v3_result V3_API tell(void* const self, int64_t* const pos)
  376. {
  377. carla_v3_bstream* const stream = *static_cast<carla_v3_bstream**>(self);
  378. CARLA_SAFE_ASSERT_RETURN(pos != nullptr, V3_INVALID_ARG);
  379. CARLA_SAFE_ASSERT_RETURN(stream->canRead, V3_INVALID_ARG);
  380. *pos = stream->readPos;
  381. return V3_OK;
  382. }
  383. CARLA_DECLARE_NON_COPYABLE(carla_v3_bstream)
  384. CARLA_PREVENT_HEAP_ALLOCATION
  385. };
  386. // --------------------------------------------------------------------------------------------------------------------
  387. struct carla_v3_host_application : v3_host_application_cpp {
  388. carla_v3_host_application()
  389. {
  390. query_interface = v3_query_interface_static<v3_host_application_iid>;
  391. ref = v3_ref_static;
  392. unref = v3_unref_static;
  393. app.get_name = get_name;
  394. app.create_instance = create_instance;
  395. }
  396. private:
  397. static v3_result V3_API get_name(void*, v3_str_128 name)
  398. {
  399. static const char hostname[] = "Carla\0";
  400. for (size_t i=0; i<sizeof(hostname); ++i)
  401. name[i] = hostname[i];
  402. return V3_OK;
  403. }
  404. static v3_result V3_API create_instance(void*, v3_tuid cid, v3_tuid iid, void** const obj)
  405. {
  406. if (v3_tuid_match(cid, v3_message_iid) && (v3_tuid_match(iid, v3_message_iid) ||
  407. v3_tuid_match(iid, v3_funknown_iid)))
  408. {
  409. *obj = v3_create_class_ptr<carla_v3_message>();
  410. return V3_OK;
  411. }
  412. carla_stdout("TODO carla_create_instance %s", tuid2str(cid));
  413. return V3_NOT_IMPLEMENTED;
  414. }
  415. CARLA_DECLARE_NON_COPYABLE(carla_v3_host_application)
  416. CARLA_PREVENT_HEAP_ALLOCATION
  417. };
  418. // --------------------------------------------------------------------------------------------------------------------
  419. struct carla_v3_input_param_value_queue : v3_param_value_queue_cpp {
  420. const v3_param_id paramId;
  421. int8_t numUsed;
  422. struct Point {
  423. int32_t offset;
  424. float value;
  425. } points[32];
  426. carla_v3_input_param_value_queue(const v3_param_id pId)
  427. : paramId(pId),
  428. numUsed(0)
  429. {
  430. query_interface = v3_query_interface_static<v3_param_value_queue_iid>;
  431. ref = v3_ref_static;
  432. unref = v3_unref_static;
  433. queue.get_param_id = get_param_id;
  434. queue.get_point_count = get_point_count;
  435. queue.get_point = get_point;
  436. queue.add_point = add_point;
  437. }
  438. private:
  439. static v3_param_id V3_API get_param_id(void* self)
  440. {
  441. carla_v3_input_param_value_queue* const me = *static_cast<carla_v3_input_param_value_queue**>(self);
  442. return me->paramId;
  443. }
  444. static int32_t V3_API get_point_count(void* self)
  445. {
  446. carla_v3_input_param_value_queue* const me = *static_cast<carla_v3_input_param_value_queue**>(self);
  447. return me->numUsed;
  448. }
  449. static v3_result V3_API get_point(void* const self,
  450. const int32_t idx, int32_t* const sample_offset, double* const value)
  451. {
  452. carla_v3_input_param_value_queue* const me = *static_cast<carla_v3_input_param_value_queue**>(self);
  453. CARLA_SAFE_ASSERT_INT2_RETURN(idx < me->numUsed, idx, me->numUsed, V3_INVALID_ARG);
  454. *sample_offset = me->points[idx].offset;
  455. *value = me->points[idx].value;
  456. return V3_OK;
  457. }
  458. static v3_result V3_API add_point(void*, int32_t, double, int32_t*)
  459. {
  460. // there is nothing here for input parameters, plugins are not meant to call this!
  461. return V3_NOT_IMPLEMENTED;
  462. }
  463. CARLA_DECLARE_NON_COPYABLE(carla_v3_input_param_value_queue)
  464. };
  465. struct carla_v3_input_param_changes : v3_param_changes_cpp {
  466. const uint32_t paramCount;
  467. struct UpdatedParam {
  468. bool updated;
  469. float value;
  470. }* const updatedParams;
  471. carla_v3_input_param_value_queue** const queue;
  472. // data given to plugins
  473. v3_param_value_queue*** pluginExposedQueue;
  474. int32_t pluginExposedCount;
  475. carla_v3_input_param_changes(const PluginParameterData& paramData)
  476. : paramCount(paramData.count),
  477. updatedParams(new UpdatedParam[paramData.count]),
  478. queue(new carla_v3_input_param_value_queue*[paramData.count]),
  479. pluginExposedQueue(new v3_param_value_queue**[paramData.count]),
  480. pluginExposedCount(0)
  481. {
  482. query_interface = v3_query_interface_static<v3_param_changes_iid>;
  483. ref = v3_ref_static;
  484. unref = v3_unref_static;
  485. changes.get_param_count = get_param_count;
  486. changes.get_param_data = get_param_data;
  487. changes.add_param_data = add_param_data;
  488. CARLA_ASSERT(paramCount != 0);
  489. carla_zeroStructs(updatedParams, paramCount);
  490. for (uint32_t i=0; i<paramCount; ++i)
  491. queue[i] = new carla_v3_input_param_value_queue(static_cast<v3_param_id>(paramData.data[i].rindex));
  492. }
  493. ~carla_v3_input_param_changes()
  494. {
  495. for (uint32_t i=0; i<paramCount; ++i)
  496. delete queue[i];
  497. delete[] updatedParams;
  498. delete[] pluginExposedQueue;
  499. delete[] queue;
  500. }
  501. // called during start of process, gathering all parameter update requests so far
  502. void init()
  503. {
  504. for (uint32_t i=0; i<paramCount; ++i)
  505. {
  506. if (updatedParams[i].updated)
  507. {
  508. queue[i]->numUsed = 1;
  509. queue[i]->points[0].offset = 0;
  510. queue[i]->points[0].value = updatedParams[i].value;
  511. }
  512. else
  513. {
  514. queue[i]->numUsed = 0;
  515. }
  516. }
  517. }
  518. // called just before plugin processing, creating local queue
  519. void prepare()
  520. {
  521. int32_t count = 0;
  522. for (uint32_t i=0; i<paramCount; ++i)
  523. {
  524. if (queue[i]->numUsed)
  525. pluginExposedQueue[count++] = (v3_param_value_queue**)&queue[i];
  526. }
  527. pluginExposedCount = count;
  528. }
  529. // called when a parameter is set from non-rt thread
  530. void setParamValue(const uint32_t index, const float value) noexcept
  531. {
  532. updatedParams[index].value = value;
  533. updatedParams[index].updated = true;
  534. }
  535. // called as response to MIDI CC
  536. void setParamValueRT(const uint32_t index, const int32_t offset, const float value) noexcept
  537. {
  538. static constexpr const int8_t kQueuePointSize = sizeof(queue[0]->points)/sizeof(queue[0]->points[0]);
  539. if (queue[index]->numUsed < kQueuePointSize)
  540. {
  541. // still has space, add in queue
  542. carla_v3_input_param_value_queue::Point& point(queue[index]->points[queue[index]->numUsed++]);
  543. point.offset = offset;
  544. point.value = value;
  545. }
  546. else
  547. {
  548. // points are full, replace last one
  549. carla_v3_input_param_value_queue::Point& point(queue[index]->points[queue[index]->numUsed - 1]);
  550. point.offset = offset;
  551. point.value = value;
  552. }
  553. }
  554. private:
  555. static int32_t V3_API get_param_count(void* const self)
  556. {
  557. carla_v3_input_param_changes* const me = *static_cast<carla_v3_input_param_changes**>(self);
  558. return me->pluginExposedCount;
  559. }
  560. static v3_param_value_queue** V3_API get_param_data(void* const self, const int32_t index)
  561. {
  562. carla_v3_input_param_changes* const me = *static_cast<carla_v3_input_param_changes**>(self);
  563. return me->pluginExposedQueue[index];
  564. }
  565. static v3_param_value_queue** V3_API add_param_data(void*, const v3_param_id*, int32_t*)
  566. {
  567. // there is nothing here for input parameters, plugins are not meant to call this!
  568. return nullptr;
  569. }
  570. CARLA_DECLARE_NON_COPYABLE(carla_v3_input_param_changes)
  571. };
  572. // --------------------------------------------------------------------------------------------------------------------
  573. struct carla_v3_output_param_value_queue : v3_param_value_queue_cpp {
  574. const v3_param_id paramId;
  575. bool used;
  576. int32_t offset;
  577. double value;
  578. carla_v3_output_param_value_queue(const v3_param_id pId)
  579. : paramId(pId),
  580. used(false),
  581. offset(0),
  582. value(0.0)
  583. {
  584. query_interface = v3_query_interface_static<v3_param_value_queue_iid>;
  585. ref = v3_ref_static;
  586. unref = v3_unref_static;
  587. queue.get_param_id = get_param_id;
  588. queue.get_point_count = get_point_count;
  589. queue.get_point = get_point;
  590. queue.add_point = add_point;
  591. }
  592. void init()
  593. {
  594. used = false;
  595. offset = 0;
  596. value = 0.0;
  597. }
  598. private:
  599. static v3_param_id V3_API get_param_id(void* self)
  600. {
  601. carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
  602. return me->paramId;
  603. }
  604. static int32_t V3_API get_point_count(void* self)
  605. {
  606. carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
  607. return me->used ? 1 : 0;
  608. }
  609. static v3_result V3_API get_point(void* const self,
  610. const int32_t index, int32_t* const sample_offset, double* const value)
  611. {
  612. carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
  613. CARLA_SAFE_ASSERT_RETURN(me->used, V3_INVALID_ARG);
  614. CARLA_SAFE_ASSERT_INT_RETURN(index == 0, index, V3_INVALID_ARG);
  615. *sample_offset = me->offset;
  616. *value = me->value;
  617. return V3_OK;
  618. }
  619. static v3_result V3_API add_point(void* const self,
  620. const int32_t sample_offset, const double value, int32_t* const index)
  621. {
  622. carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
  623. CARLA_SAFE_ASSERT_INT_RETURN(sample_offset >= 0, sample_offset, V3_INVALID_ARG);
  624. CARLA_SAFE_ASSERT_RETURN(value >= 0 && value <= 1, V3_INVALID_ARG);
  625. CARLA_SAFE_ASSERT_RETURN(index != nullptr, V3_INVALID_ARG);
  626. me->offset = sample_offset;
  627. me->value = value;
  628. *index = 0;
  629. return V3_OK;
  630. }
  631. CARLA_DECLARE_NON_COPYABLE(carla_v3_output_param_value_queue)
  632. };
  633. struct carla_v3_output_param_changes : v3_param_changes_cpp {
  634. const uint32_t numParameters;
  635. int32_t numParametersUsed;
  636. bool* const parametersUsed;
  637. carla_v3_output_param_value_queue** const queue;
  638. std::unordered_map<v3_param_id, int32_t> paramIds;
  639. carla_v3_output_param_changes(const PluginParameterData& paramData)
  640. : numParameters(paramData.count),
  641. numParametersUsed(0),
  642. parametersUsed(new bool[paramData.count]),
  643. queue(new carla_v3_output_param_value_queue*[paramData.count])
  644. {
  645. query_interface = v3_query_interface_static<v3_param_changes_iid>;
  646. ref = v3_ref_static;
  647. unref = v3_unref_static;
  648. changes.get_param_count = get_param_count;
  649. changes.get_param_data = get_param_data;
  650. changes.add_param_data = add_param_data;
  651. carla_zeroStructs(parametersUsed, numParameters);
  652. for (uint32_t i=0; i<numParameters; ++i)
  653. {
  654. const v3_param_id paramId = paramData.data[i].rindex;
  655. queue[i] = new carla_v3_output_param_value_queue(paramId);
  656. paramIds[paramId] = i;
  657. }
  658. }
  659. ~carla_v3_output_param_changes()
  660. {
  661. for (uint32_t i=0; i<numParameters; ++i)
  662. delete queue[i];
  663. delete[] parametersUsed;
  664. delete[] queue;
  665. }
  666. void prepare()
  667. {
  668. numParametersUsed = 0;
  669. carla_zeroStructs(parametersUsed, numParameters);
  670. }
  671. private:
  672. static int32_t V3_API get_param_count(void*)
  673. {
  674. // there is nothing here for output parameters, plugins are not meant to call this!
  675. return 0;
  676. }
  677. static v3_param_value_queue** V3_API get_param_data(void*, int32_t)
  678. {
  679. // there is nothing here for output parameters, plugins are not meant to call this!
  680. return nullptr;
  681. }
  682. static v3_param_value_queue** V3_API add_param_data(void* const self,
  683. const v3_param_id* const paramIdPtr,
  684. int32_t* const index)
  685. {
  686. carla_v3_output_param_changes* const me = *static_cast<carla_v3_output_param_changes**>(self);
  687. CARLA_SAFE_ASSERT_RETURN(paramIdPtr != nullptr, nullptr);
  688. const v3_param_id paramId = *paramIdPtr;
  689. if (me->paramIds.find(paramId) == me->paramIds.end())
  690. return nullptr;
  691. const int32_t paramIndex = me->paramIds[paramId];
  692. CARLA_SAFE_ASSERT_RETURN(!me->parametersUsed[paramIndex], nullptr);
  693. *index = me->numParametersUsed++;
  694. me->parametersUsed[paramIndex] = true;
  695. me->queue[paramIndex]->init();
  696. return (v3_param_value_queue**)&me->queue[paramIndex];
  697. }
  698. CARLA_DECLARE_NON_COPYABLE(carla_v3_output_param_changes)
  699. };
  700. // --------------------------------------------------------------------------------------------------------------------
  701. struct carla_v3_input_event_list : v3_event_list_cpp {
  702. v3_event* const events;
  703. uint16_t numEvents;
  704. carla_v3_input_event_list()
  705. : events(new v3_event[kPluginMaxMidiEvents]),
  706. numEvents(0)
  707. {
  708. query_interface = v3_query_interface_static<v3_event_list_iid>;
  709. ref = v3_ref_static;
  710. unref = v3_unref_static;
  711. list.get_event_count = get_event_count;
  712. list.get_event = get_event;
  713. list.add_event = add_event;
  714. }
  715. ~carla_v3_input_event_list()
  716. {
  717. delete[] events;
  718. }
  719. private:
  720. static uint32_t V3_API get_event_count(void* const self)
  721. {
  722. const carla_v3_input_event_list* const me = *static_cast<const carla_v3_input_event_list**>(self);
  723. return me->numEvents;
  724. }
  725. static v3_result V3_API get_event(void* const self, const int32_t index, v3_event* const event)
  726. {
  727. const carla_v3_input_event_list* const me = *static_cast<const carla_v3_input_event_list**>(self);
  728. CARLA_SAFE_ASSERT_RETURN(index < static_cast<int32_t>(me->numEvents), V3_INVALID_ARG);
  729. std::memcpy(event, &me->events[index], sizeof(v3_event));
  730. return V3_OK;
  731. }
  732. static v3_result V3_API add_event(void*, v3_event*)
  733. {
  734. // there is nothing here for input events, plugins are not meant to call this!
  735. return V3_NOT_IMPLEMENTED;
  736. }
  737. CARLA_DECLARE_NON_COPYABLE(carla_v3_input_event_list)
  738. };
  739. // --------------------------------------------------------------------------------------------------------------------
  740. struct carla_v3_output_event_list : v3_event_list_cpp {
  741. v3_event* const events;
  742. uint16_t numEvents;
  743. carla_v3_output_event_list()
  744. : events(new v3_event[kPluginMaxMidiEvents]),
  745. numEvents(0)
  746. {
  747. query_interface = v3_query_interface_static<v3_event_list_iid>;
  748. ref = v3_ref_static;
  749. unref = v3_unref_static;
  750. list.get_event_count = get_event_count;
  751. list.get_event = get_event;
  752. list.add_event = add_event;
  753. }
  754. ~carla_v3_output_event_list()
  755. {
  756. delete[] events;
  757. }
  758. private:
  759. static uint32_t V3_API get_event_count(void*)
  760. {
  761. carla_debug("TODO %s", __PRETTY_FUNCTION__);
  762. // there is nothing here for output events, plugins are not meant to call this!
  763. return 0;
  764. }
  765. static v3_result V3_API get_event(void*, int32_t, v3_event*)
  766. {
  767. carla_debug("TODO %s", __PRETTY_FUNCTION__);
  768. // there is nothing here for output events, plugins are not meant to call this!
  769. return V3_NOT_IMPLEMENTED;
  770. }
  771. static v3_result V3_API add_event(void* const self, v3_event* const event)
  772. {
  773. carla_v3_output_event_list* const me = *static_cast<carla_v3_output_event_list**>(self);
  774. if (me->numEvents >= kPluginMaxMidiEvents)
  775. return V3_NOMEM;
  776. std::memcpy(&me->events[me->numEvents++], event, sizeof(v3_event));
  777. return V3_OK;
  778. }
  779. CARLA_DECLARE_NON_COPYABLE(carla_v3_output_event_list)
  780. };
  781. // --------------------------------------------------------------------------------------------------------------------
  782. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  783. struct HostTimer {
  784. v3_timer_handler** handler;
  785. uint64_t periodInMs;
  786. uint64_t lastCallTimeInMs;
  787. };
  788. static constexpr const HostTimer kTimerFallback = { nullptr, 0, 0 };
  789. static /* */ HostTimer kTimerFallbackNC = { nullptr, 0, 0 };
  790. #ifdef _POSIX_VERSION
  791. struct HostPosixFileDescriptor {
  792. v3_event_handler** handler;
  793. int hostfd;
  794. int pluginfd;
  795. };
  796. static constexpr const HostPosixFileDescriptor kPosixFileDescriptorFallback = { nullptr, -1, -1 };
  797. static /* */ HostPosixFileDescriptor kPosixFileDescriptorFallbackNC = { nullptr, -1, -1 };
  798. #endif
  799. struct carla_v3_run_loop : v3_run_loop_cpp {
  800. LinkedList<HostTimer> timers;
  801. #ifdef _POSIX_VERSION
  802. LinkedList<HostPosixFileDescriptor> posixfds;
  803. #endif
  804. carla_v3_run_loop()
  805. {
  806. query_interface = v3_query_interface_static<v3_run_loop_iid>;
  807. ref = v3_ref_static;
  808. unref = v3_unref_static;
  809. loop.register_event_handler = register_event_handler;
  810. loop.unregister_event_handler = unregister_event_handler;
  811. loop.register_timer = register_timer;
  812. loop.unregister_timer = unregister_timer;
  813. }
  814. private:
  815. static v3_result V3_API register_event_handler(void* const self, v3_event_handler** const handler, const int fd)
  816. {
  817. #ifdef _POSIX_VERSION
  818. carla_v3_run_loop* const loop = *static_cast<carla_v3_run_loop**>(self);
  819. #ifdef CARLA_VST3_POSIX_EPOLL
  820. const int hostfd = ::epoll_create1(0);
  821. #else
  822. const int hostfd = ::kqueue();
  823. #endif
  824. CARLA_SAFE_ASSERT_RETURN(hostfd >= 0, V3_INTERNAL_ERR);
  825. #ifdef CARLA_VST3_POSIX_EPOLL
  826. struct ::epoll_event ev = {};
  827. ev.events = EPOLLIN|EPOLLOUT;
  828. ev.data.fd = fd;
  829. if (::epoll_ctl(hostfd, EPOLL_CTL_ADD, fd, &ev) < 0)
  830. {
  831. ::close(hostfd);
  832. return V3_INTERNAL_ERR;
  833. }
  834. #endif
  835. const HostPosixFileDescriptor posixfd = { handler, hostfd, fd };
  836. return loop->posixfds.append(posixfd) ? V3_OK : V3_NOMEM;
  837. #else
  838. return V3_NOT_IMPLEMENTED;
  839. // unused
  840. (void)self; (void)handler; (void)fd;
  841. #endif
  842. }
  843. static v3_result V3_API unregister_event_handler(void* const self, v3_event_handler** const handler)
  844. {
  845. #ifdef _POSIX_VERSION
  846. carla_v3_run_loop* const loop = *static_cast<carla_v3_run_loop**>(self);
  847. for (LinkedList<HostPosixFileDescriptor>::Itenerator it = loop->posixfds.begin2(); it.valid(); it.next())
  848. {
  849. const HostPosixFileDescriptor& posixfd(it.getValue(kPosixFileDescriptorFallback));
  850. if (posixfd.handler == handler)
  851. {
  852. #ifdef CARLA_VST3_POSIX_EPOLL
  853. ::epoll_ctl(posixfd.hostfd, EPOLL_CTL_DEL, posixfd.pluginfd, nullptr);
  854. #endif
  855. ::close(posixfd.hostfd);
  856. loop->posixfds.remove(it);
  857. return V3_OK;
  858. }
  859. }
  860. return V3_INVALID_ARG;
  861. #else
  862. return V3_NOT_IMPLEMENTED;
  863. // unused
  864. (void)self; (void)handler;
  865. #endif
  866. }
  867. static v3_result V3_API register_timer(void* const self, v3_timer_handler** const handler, const uint64_t ms)
  868. {
  869. carla_v3_run_loop* const loop = *static_cast<carla_v3_run_loop**>(self);
  870. const HostTimer timer = { handler, ms, 0 };
  871. return loop->timers.append(timer) ? V3_OK : V3_NOMEM;
  872. }
  873. static v3_result V3_API unregister_timer(void* const self, v3_timer_handler** const handler)
  874. {
  875. carla_v3_run_loop* const loop = *static_cast<carla_v3_run_loop**>(self);
  876. for (LinkedList<HostTimer>::Itenerator it = loop->timers.begin2(); it.valid(); it.next())
  877. {
  878. const HostTimer& timer(it.getValue(kTimerFallback));
  879. if (timer.handler == handler)
  880. {
  881. loop->timers.remove(it);
  882. return V3_OK;
  883. }
  884. }
  885. return V3_INVALID_ARG;
  886. }
  887. CARLA_DECLARE_NON_COPYABLE(carla_v3_run_loop)
  888. CARLA_PREVENT_HEAP_ALLOCATION
  889. };
  890. #endif // V3_VIEW_PLATFORM_TYPE_NATIVE
  891. // --------------------------------------------------------------------------------------------------------------------
  892. struct carla_v3_component_handler : v3_component_handler_cpp {
  893. v3HostCallback* const callback;
  894. carla_v3_component_handler(v3HostCallback* const cb)
  895. : callback(cb)
  896. {
  897. query_interface = carla_query_interface;
  898. ref = v3_ref_static;
  899. unref = v3_unref_static;
  900. comp.begin_edit = begin_edit;
  901. comp.perform_edit = perform_edit;
  902. comp.end_edit = end_edit;
  903. comp.restart_component = restart_component;
  904. }
  905. private:
  906. static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface)
  907. {
  908. if (v3_query_interface_static<v3_component_handler_iid>(self, iid, iface) == V3_OK)
  909. return V3_OK;
  910. // TODO
  911. if (v3_tuid_match(iid, v3_component_handler2_iid))
  912. {
  913. *iface = nullptr;
  914. return V3_NO_INTERFACE;
  915. }
  916. *iface = nullptr;
  917. carla_stdout("TODO carla_v3_component_handler::query_interface %s", tuid2str(iid));
  918. return V3_NO_INTERFACE;
  919. }
  920. static v3_result V3_API begin_edit(void* const self, const v3_param_id paramId)
  921. {
  922. carla_v3_component_handler* const comp = *static_cast<carla_v3_component_handler**>(self);
  923. return comp->callback->v3BeginEdit(paramId);
  924. }
  925. static v3_result V3_API perform_edit(void* const self, const v3_param_id paramId, const double value)
  926. {
  927. carla_v3_component_handler* const comp = *static_cast<carla_v3_component_handler**>(self);
  928. return comp->callback->v3PerformEdit(paramId, value);
  929. }
  930. static v3_result V3_API end_edit(void* const self, const v3_param_id paramId)
  931. {
  932. carla_v3_component_handler* const comp = *static_cast<carla_v3_component_handler**>(self);
  933. return comp->callback->v3EndEdit(paramId);
  934. }
  935. static v3_result V3_API restart_component(void* const self, const int32_t flags)
  936. {
  937. carla_v3_component_handler* const comp = *static_cast<carla_v3_component_handler**>(self);
  938. return comp->callback->v3RestartComponent(flags);
  939. }
  940. CARLA_DECLARE_NON_COPYABLE(carla_v3_component_handler)
  941. CARLA_PREVENT_HEAP_ALLOCATION
  942. };
  943. // --------------------------------------------------------------------------------------------------------------------
  944. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  945. struct carla_v3_plugin_frame : v3_plugin_frame_cpp {
  946. v3HostCallback* const callback;
  947. carla_v3_run_loop loop;
  948. carla_v3_run_loop* loopPtr;
  949. carla_v3_plugin_frame(v3HostCallback* const cb)
  950. : callback(cb),
  951. loopPtr(&loop)
  952. {
  953. query_interface = carla_query_interface;
  954. ref = v3_ref_static;
  955. unref = v3_unref_static;
  956. frame.resize_view = resize_view;
  957. }
  958. private:
  959. static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface)
  960. {
  961. if (v3_query_interface_static<v3_plugin_frame_iid>(self, iid, iface) == V3_OK)
  962. return V3_OK;
  963. carla_v3_plugin_frame* const frame = *static_cast<carla_v3_plugin_frame**>(self);
  964. if (v3_tuid_match(iid, v3_run_loop_iid))
  965. {
  966. *iface = &frame->loopPtr;
  967. return V3_OK;
  968. }
  969. *iface = nullptr;
  970. return V3_NO_INTERFACE;
  971. }
  972. static v3_result V3_API resize_view(void* const self,
  973. struct v3_plugin_view** const view, struct v3_view_rect* const rect)
  974. {
  975. const carla_v3_plugin_frame* const me = *static_cast<const carla_v3_plugin_frame**>(self);
  976. return me->callback->v3ResizeView(view, rect);
  977. }
  978. CARLA_DECLARE_NON_COPYABLE(carla_v3_plugin_frame)
  979. CARLA_PREVENT_HEAP_ALLOCATION
  980. };
  981. #endif
  982. // --------------------------------------------------------------------------------------------------------------------
  983. class CarlaPluginVST3 : public CarlaPlugin,
  984. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  985. private CarlaPluginUI::Callback,
  986. #endif
  987. private v3HostCallback
  988. {
  989. public:
  990. CarlaPluginVST3(CarlaEngine* const engine, const uint id)
  991. : CarlaPlugin(engine, id),
  992. kEngineHasIdleOnMainThread(engine->hasIdleOnMainThread()),
  993. fFirstActive(true),
  994. fAudioAndCvOutBuffers(nullptr),
  995. fLastKnownLatency(0),
  996. fRestartFlags(0),
  997. fLastChunk(nullptr),
  998. fLastTimeInfo(),
  999. fV3TimeContext(),
  1000. fV3Application(),
  1001. fV3ApplicationPtr(&fV3Application),
  1002. fComponentHandler(this),
  1003. fComponentHandlerPtr(&fComponentHandler),
  1004. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1005. fPluginFrame(this),
  1006. fPluginFramePtr(&fPluginFrame),
  1007. #endif
  1008. fV3ClassInfo(),
  1009. fV3(),
  1010. fEvents()
  1011. {
  1012. carla_debug("CarlaPluginVST3::CarlaPluginVST3(%p, %i)", engine, id);
  1013. carla_zeroStruct(fV3TimeContext);
  1014. }
  1015. ~CarlaPluginVST3() override
  1016. {
  1017. carla_debug("CarlaPluginVST3::~CarlaPluginVST3()");
  1018. runIdleCallbacksAsNeeded(false);
  1019. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1020. fPluginFrame.loop.timers.clear();
  1021. #ifdef _POSIX_VERSION
  1022. fPluginFrame.loop.posixfds.clear();
  1023. #endif
  1024. // close UI
  1025. if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
  1026. {
  1027. if (! fUI.isEmbed)
  1028. showCustomUI(false);
  1029. if (fUI.isAttached)
  1030. {
  1031. fUI.isAttached = false;
  1032. v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr);
  1033. v3_cpp_obj(fV3.view)->removed(fV3.view);
  1034. }
  1035. }
  1036. if (fV3.view != nullptr)
  1037. {
  1038. v3_cpp_obj_unref(fV3.view);
  1039. fV3.view = nullptr;
  1040. }
  1041. #endif
  1042. pData->singleMutex.lock();
  1043. pData->masterMutex.lock();
  1044. if (pData->client != nullptr && pData->client->isActive())
  1045. pData->client->deactivate(true);
  1046. if (pData->active)
  1047. {
  1048. deactivate();
  1049. pData->active = false;
  1050. }
  1051. if (fLastChunk != nullptr)
  1052. {
  1053. std::free(fLastChunk);
  1054. fLastChunk = nullptr;
  1055. }
  1056. clearBuffers();
  1057. fV3.exit();
  1058. }
  1059. // ----------------------------------------------------------------------------------------------------------------
  1060. // Information (base)
  1061. PluginType getType() const noexcept override
  1062. {
  1063. return PLUGIN_VST3;
  1064. }
  1065. PluginCategory getCategory() const noexcept override
  1066. {
  1067. return getPluginCategoryFromV3SubCategories(fV3ClassInfo.v2.sub_categories);
  1068. }
  1069. uint32_t getLatencyInFrames() const noexcept override
  1070. {
  1071. return fLastKnownLatency;
  1072. }
  1073. // ----------------------------------------------------------------------------------------------------------------
  1074. // Information (count)
  1075. /* TODO
  1076. uint32_t getMidiInCount() const noexcept override
  1077. {
  1078. }
  1079. uint32_t getMidiOutCount() const noexcept override
  1080. {
  1081. }
  1082. uint32_t getParameterScalePointCount(const uint32_t paramIndex) const noexcept override
  1083. {
  1084. }
  1085. */
  1086. // ----------------------------------------------------------------------------------------------------------------
  1087. // Information (current data)
  1088. uint getAudioPortHints(const bool isOutput, const uint32_t portIndex) const noexcept override
  1089. {
  1090. uint hints = 0x0;
  1091. if (isOutput)
  1092. {
  1093. const uint32_t numOutputs = static_cast<uint32_t>(fBuses.numOutputs);
  1094. for (uint32_t b=0, i=0; b < numOutputs; ++b, i += fBuses.outputs[b].num_channels)
  1095. {
  1096. if (i != portIndex)
  1097. continue;
  1098. if (fBuses.outputInfo[i].bus_type == V3_AUX)
  1099. hints |= AUDIO_PORT_IS_SIDECHAIN;
  1100. }
  1101. }
  1102. else
  1103. {
  1104. const uint32_t numInputs = static_cast<uint32_t>(fBuses.numInputs);
  1105. for (uint32_t b=0, i=0; b < numInputs; ++b, i += fBuses.inputs[b].num_channels)
  1106. {
  1107. if (i != portIndex)
  1108. continue;
  1109. if (fBuses.inputInfo[i].bus_type == V3_AUX)
  1110. hints |= AUDIO_PORT_IS_SIDECHAIN;
  1111. }
  1112. }
  1113. return hints;
  1114. }
  1115. std::size_t getChunkData(void** const dataPtr) noexcept override
  1116. {
  1117. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS, 0);
  1118. CARLA_SAFE_ASSERT_RETURN(fV3.component != nullptr, 0);
  1119. CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr, 0);
  1120. std::free(fLastChunk);
  1121. carla_v3_bstream stream;
  1122. carla_v3_bstream* const streamPtr = &stream;
  1123. v3_bstream** const v3stream = (v3_bstream**)&streamPtr;
  1124. stream.canWrite = true;
  1125. if (v3_cpp_obj(fV3.component)->get_state(fV3.component, v3stream) == V3_OK)
  1126. {
  1127. *dataPtr = fLastChunk = stream.buffer;
  1128. runIdleCallbacksAsNeeded(false);
  1129. return stream.size;
  1130. }
  1131. *dataPtr = fLastChunk = nullptr;
  1132. runIdleCallbacksAsNeeded(false);
  1133. return 0;
  1134. }
  1135. // ----------------------------------------------------------------------------------------------------------------
  1136. // Information (per-plugin data)
  1137. uint getOptionsAvailable() const noexcept override
  1138. {
  1139. uint options = 0x0;
  1140. // can't disable fixed buffers if using latency
  1141. if (fLastKnownLatency == 0)
  1142. options |= PLUGIN_OPTION_FIXED_BUFFERS;
  1143. /* TODO
  1144. if (numPrograms > 1)
  1145. options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  1146. */
  1147. options |= PLUGIN_OPTION_USE_CHUNKS;
  1148. if (hasMidiInput())
  1149. {
  1150. options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  1151. options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  1152. options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  1153. options |= PLUGIN_OPTION_SEND_PITCHBEND;
  1154. options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  1155. options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
  1156. }
  1157. return options;
  1158. }
  1159. float getParameterValue(const uint32_t paramIndex) const noexcept override
  1160. {
  1161. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr, 0.0f);
  1162. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count, 0.0f);
  1163. // FIXME use pending RT value?
  1164. const v3_param_id paramId = pData->param.data[paramIndex].rindex;
  1165. const double normalized = v3_cpp_obj(fV3.controller)->get_parameter_normalised(fV3.controller, paramId);
  1166. return static_cast<float>(
  1167. v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller, paramId, normalized));
  1168. }
  1169. /* TODO
  1170. float getParameterScalePointValue(uint32_t paramIndex, uint32_t scalePointId) const noexcept override
  1171. {
  1172. }
  1173. */
  1174. bool getLabel(char* const strBuf) const noexcept override
  1175. {
  1176. std::strncpy(strBuf, fV3ClassInfo.v1.name, STR_MAX);
  1177. return true;
  1178. }
  1179. bool getMaker(char* const strBuf) const noexcept override
  1180. {
  1181. std::strncpy(strBuf, fV3ClassInfo.v2.vendor, STR_MAX);
  1182. return true;
  1183. }
  1184. bool getCopyright(char* const strBuf) const noexcept override
  1185. {
  1186. return getMaker(strBuf);
  1187. }
  1188. bool getRealName(char* const strBuf) const noexcept override
  1189. {
  1190. std::strncpy(strBuf, fV3ClassInfo.v1.name, STR_MAX);
  1191. return true;
  1192. }
  1193. bool getParameterName(const uint32_t paramIndex, char* const strBuf) const noexcept override
  1194. {
  1195. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr, 0.0f);
  1196. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count, false);
  1197. v3_param_info paramInfo = {};
  1198. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(fV3.controller)->get_parameter_info(fV3.controller,
  1199. static_cast<int32_t>(paramIndex),
  1200. &paramInfo) == V3_OK, false);
  1201. strncpy_utf8(strBuf, paramInfo.title, STR_MAX);
  1202. return true;
  1203. }
  1204. bool getParameterSymbol(const uint32_t paramIndex, char* strBuf) const noexcept override
  1205. {
  1206. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count, false);
  1207. std::snprintf(strBuf, STR_MAX, "%d", pData->param.data[paramIndex].rindex);
  1208. return true;
  1209. }
  1210. bool getParameterText(const uint32_t paramIndex, char* const strBuf) noexcept override
  1211. {
  1212. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr, false);
  1213. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count, false);
  1214. const v3_param_id paramId = pData->param.data[paramIndex].rindex;
  1215. const double normalized = v3_cpp_obj(fV3.controller)->get_parameter_normalised(fV3.controller, paramId);
  1216. v3_str_128 paramText;
  1217. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(fV3.controller)->get_parameter_string_for_value(fV3.controller,
  1218. paramId,
  1219. normalized,
  1220. paramText) == V3_OK, false);
  1221. if (paramText[0] != '\0')
  1222. strncpy_utf8(strBuf, paramText, STR_MAX);
  1223. else
  1224. std::snprintf(strBuf, STR_MAX, "%.12g",
  1225. v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller, paramId, normalized));
  1226. return true;
  1227. }
  1228. bool getParameterUnit(const uint32_t paramIndex, char* const strBuf) const noexcept override
  1229. {
  1230. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr, false);
  1231. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count, false);
  1232. v3_param_info paramInfo = {};
  1233. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(fV3.controller)->get_parameter_info(fV3.controller,
  1234. static_cast<int32_t>(paramIndex),
  1235. &paramInfo) == V3_OK, false);
  1236. strncpy_utf8(strBuf, paramInfo.units, STR_MAX);
  1237. return true;
  1238. }
  1239. /* TODO
  1240. bool getParameterGroupName(const uint32_t paramIndex, char* const strBuf) const noexcept override
  1241. {
  1242. }
  1243. bool getParameterScalePointLabel(const uint32_t paramIndex,
  1244. const uint32_t scalePointId, char* const strBuf) const noexcept override
  1245. {
  1246. }
  1247. */
  1248. // ----------------------------------------------------------------------------------------------------------------
  1249. // Set data (state)
  1250. /* TODO
  1251. void prepareForSave(const bool temporary) override
  1252. {
  1253. // component to edit controller state or vice-versa here
  1254. }
  1255. */
  1256. // ----------------------------------------------------------------------------------------------------------------
  1257. // Set data (internal stuff)
  1258. /* TODO
  1259. void setName(const char* newName) override
  1260. {
  1261. }
  1262. */
  1263. // ----------------------------------------------------------------------------------------------------------------
  1264. // Set data (plugin-specific stuff)
  1265. void setParameterValue(const uint32_t paramIndex, const float value,
  1266. const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
  1267. {
  1268. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr,);
  1269. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count,);
  1270. CARLA_SAFE_ASSERT_RETURN(fEvents.paramInputs != nullptr,);
  1271. const v3_param_id paramId = pData->param.data[paramIndex].rindex;
  1272. const float fixedValue = pData->param.getFixedValue(paramIndex, value);
  1273. const double normalized = v3_cpp_obj(fV3.controller)->plain_parameter_to_normalised(fV3.controller,
  1274. paramId,
  1275. fixedValue);
  1276. // report value to component (next process call)
  1277. fEvents.paramInputs->setParamValue(paramIndex, static_cast<float>(normalized));
  1278. // report value to edit controller
  1279. v3_cpp_obj(fV3.controller)->set_parameter_normalised(fV3.controller, paramId, normalized);
  1280. CarlaPlugin::setParameterValue(paramIndex, fixedValue, sendGui, sendOsc, sendCallback);
  1281. }
  1282. void setParameterValueRT(const uint32_t paramIndex, const float value, const uint32_t frameOffset,
  1283. const bool sendCallbackLater) noexcept override
  1284. {
  1285. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr,);
  1286. CARLA_SAFE_ASSERT_RETURN(paramIndex < pData->param.count,);
  1287. CARLA_SAFE_ASSERT_RETURN(fEvents.paramInputs != nullptr,);
  1288. const v3_param_id paramId = pData->param.data[paramIndex].rindex;
  1289. const float fixedValue = pData->param.getFixedValue(paramIndex, value);
  1290. const double normalized = v3_cpp_obj(fV3.controller)->plain_parameter_to_normalised(fV3.controller,
  1291. paramId,
  1292. fixedValue);
  1293. // report value to component (next process call)
  1294. fEvents.paramInputs->setParamValueRT(paramIndex, frameOffset, static_cast<float>(normalized));
  1295. CarlaPlugin::setParameterValueRT(paramIndex, fixedValue, frameOffset, sendCallbackLater);
  1296. }
  1297. void setChunkData(const void* data, std::size_t dataSize) override
  1298. {
  1299. CARLA_SAFE_ASSERT_RETURN(pData->options & PLUGIN_OPTION_USE_CHUNKS,);
  1300. CARLA_SAFE_ASSERT_RETURN(fV3.component != nullptr,);
  1301. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr,);
  1302. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  1303. CARLA_SAFE_ASSERT_RETURN(dataSize > 0,);
  1304. carla_v3_bstream stream;
  1305. carla_v3_bstream* const streamPtr = &stream;
  1306. v3_bstream** const v3stream = (v3_bstream**)&streamPtr;
  1307. stream.buffer = const_cast<void*>(data);
  1308. stream.size = dataSize;
  1309. stream.canRead = true;
  1310. if (v3_cpp_obj(fV3.component)->set_state(fV3.component, v3stream) == V3_OK)
  1311. {
  1312. v3_cpp_obj(fV3.controller)->set_state(fV3.controller, v3stream);
  1313. pData->updateParameterValues(this, true, true, false);
  1314. }
  1315. runIdleCallbacksAsNeeded(false);
  1316. }
  1317. // ----------------------------------------------------------------------------------------------------------------
  1318. // Set ui stuff
  1319. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1320. void setCustomUITitle(const char* const title) noexcept override
  1321. {
  1322. if (fUI.window != nullptr)
  1323. {
  1324. try {
  1325. fUI.window->setTitle(title);
  1326. } CARLA_SAFE_EXCEPTION("set custom ui title");
  1327. }
  1328. CarlaPlugin::setCustomUITitle(title);
  1329. }
  1330. void showCustomUI(const bool yesNo) override
  1331. {
  1332. if (fUI.isVisible == yesNo)
  1333. return;
  1334. CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr,);
  1335. if (yesNo)
  1336. {
  1337. CarlaString uiTitle;
  1338. if (pData->uiTitle.isNotEmpty())
  1339. {
  1340. uiTitle = pData->uiTitle;
  1341. }
  1342. else
  1343. {
  1344. uiTitle = pData->name;
  1345. uiTitle += " (GUI)";
  1346. }
  1347. if (fUI.window == nullptr)
  1348. {
  1349. const EngineOptions& opts(pData->engine->getOptions());
  1350. const bool isStandalone = opts.pluginsAreStandalone;
  1351. const bool isResizable = v3_cpp_obj(fV3.view)->can_resize(fV3.view) == V3_TRUE;
  1352. #if defined(CARLA_OS_MAC)
  1353. fUI.window = CarlaPluginUI::newCocoa(this, opts.frontendWinId, isStandalone, isResizable);
  1354. #elif defined(CARLA_OS_WIN)
  1355. fUI.window = CarlaPluginUI::newWindows(this, opts.frontendWinId, isStandalone, isResizable);
  1356. #elif defined(HAVE_X11)
  1357. fUI.window = CarlaPluginUI::newX11(this, opts.frontendWinId, isStandalone, isResizable, false);
  1358. #else
  1359. pData->engine->callback(true, true,
  1360. ENGINE_CALLBACK_UI_STATE_CHANGED,
  1361. pData->id,
  1362. -1,
  1363. 0, 0, 0.0f,
  1364. "Unsupported UI type");
  1365. return;
  1366. #endif
  1367. fUI.window->setTitle(uiTitle.buffer());
  1368. #ifndef CARLA_OS_MAC
  1369. if (carla_isNotZero(opts.uiScale))
  1370. {
  1371. // TODO inform plugin of what UI scale we use
  1372. }
  1373. #endif
  1374. v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fPluginFramePtr);
  1375. if (v3_cpp_obj(fV3.view)->attached(fV3.view, fUI.window->getPtr(),
  1376. V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_OK)
  1377. {
  1378. v3_view_rect rect = {};
  1379. if (v3_cpp_obj(fV3.view)->get_size(fV3.view, &rect) == V3_OK)
  1380. {
  1381. const int32_t width = rect.right - rect.left;
  1382. const int32_t height = rect.bottom - rect.top;
  1383. carla_stdout("view attached ok, size %i %i", width, height);
  1384. CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height);
  1385. if (width > 1 && height > 1)
  1386. {
  1387. fUI.isResizingFromInit = true;
  1388. fUI.width = width;
  1389. fUI.height = height;
  1390. fUI.window->setSize(static_cast<uint>(width), static_cast<uint>(height), true, true);
  1391. }
  1392. }
  1393. else
  1394. {
  1395. carla_stdout("view attached ok, size failed");
  1396. }
  1397. if (isResizable)
  1398. {
  1399. carla_zeroStruct(rect);
  1400. if (v3_cpp_obj(fV3.view)->check_size_constraint(fV3.view, &rect) == V3_OK)
  1401. {
  1402. const int32_t width = rect.right - rect.left;
  1403. const int32_t height = rect.bottom - rect.top;
  1404. carla_stdout("size constraint ok %i %i", width, height);
  1405. CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height);
  1406. if (width > 1 && height > 1)
  1407. fUI.window->setMinimumSize(static_cast<uint>(width), static_cast<uint>(height));
  1408. else if (fUI.width > 1 && fUI.height > 1)
  1409. fUI.window->setMinimumSize(fUI.width, fUI.height);
  1410. }
  1411. else
  1412. {
  1413. carla_stdout("view attached ok, size constraint failed");
  1414. }
  1415. }
  1416. }
  1417. else
  1418. {
  1419. v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr);
  1420. delete fUI.window;
  1421. fUI.window = nullptr;
  1422. carla_stderr2("Plugin refused to open its own UI");
  1423. return pData->engine->callback(true, true,
  1424. ENGINE_CALLBACK_UI_STATE_CHANGED,
  1425. pData->id,
  1426. -1,
  1427. 0, 0, 0.0f,
  1428. "Plugin refused to open its own UI");
  1429. }
  1430. }
  1431. fUI.window->show();
  1432. fUI.isVisible = true;
  1433. }
  1434. else
  1435. {
  1436. fUI.isVisible = false;
  1437. if (fUI.window != nullptr)
  1438. fUI.window->hide();
  1439. if (fUI.isEmbed)
  1440. {
  1441. fUI.isAttached = false;
  1442. fUI.isEmbed = false;
  1443. v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr);
  1444. v3_cpp_obj(fV3.view)->removed(fV3.view);
  1445. }
  1446. }
  1447. runIdleCallbacksAsNeeded(true);
  1448. }
  1449. void* embedCustomUI(void* const ptr) override
  1450. {
  1451. CARLA_SAFE_ASSERT_RETURN(fUI.window == nullptr, nullptr);
  1452. CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr, nullptr);
  1453. v3_cpp_obj(fV3.view)->set_frame(fV3.view, (v3_plugin_frame**)&fPluginFramePtr);
  1454. #ifndef CARLA_OS_MAC
  1455. const EngineOptions& opts(pData->engine->getOptions());
  1456. if (carla_isNotZero(opts.uiScale))
  1457. {
  1458. // TODO
  1459. }
  1460. #endif
  1461. if (v3_cpp_obj(fV3.view)->attached(fV3.view, ptr, V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_OK)
  1462. {
  1463. fUI.isAttached = true;
  1464. fUI.isEmbed = true;
  1465. fUI.isVisible = true;
  1466. v3_view_rect rect = {};
  1467. if (v3_cpp_obj(fV3.view)->get_size(fV3.view, &rect) == V3_OK)
  1468. {
  1469. const int32_t width = rect.right - rect.left;
  1470. const int32_t height = rect.bottom - rect.top;
  1471. carla_stdout("view attached ok, size %i %i", width, height);
  1472. CARLA_SAFE_ASSERT_INT2(width > 1 && height > 1, width, height);
  1473. if (width > 1 && height > 1)
  1474. {
  1475. fUI.isResizingFromInit = true;
  1476. fUI.width = width;
  1477. fUI.height = height;
  1478. pData->engine->callback(true, true,
  1479. ENGINE_CALLBACK_EMBED_UI_RESIZED,
  1480. pData->id, width, height,
  1481. 0, 0.0f, nullptr);
  1482. }
  1483. }
  1484. else
  1485. {
  1486. carla_stdout("view attached ok, size failed");
  1487. }
  1488. }
  1489. else
  1490. {
  1491. fUI.isVisible = false;
  1492. v3_cpp_obj(fV3.view)->set_frame(fV3.view, nullptr);
  1493. carla_stderr2("Plugin refused to open its own UI");
  1494. pData->engine->callback(true, true,
  1495. ENGINE_CALLBACK_UI_STATE_CHANGED,
  1496. pData->id,
  1497. -1,
  1498. 0, 0, 0.0f,
  1499. "Plugin refused to open its own UI");
  1500. }
  1501. return nullptr;
  1502. }
  1503. #endif // V3_VIEW_PLATFORM_TYPE_NATIVE
  1504. void runIdleCallbacksAsNeeded(const bool isIdleCallback)
  1505. {
  1506. int32_t flags = fRestartFlags;
  1507. if (isIdleCallback)
  1508. {
  1509. }
  1510. fRestartFlags = flags;
  1511. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1512. #ifdef _POSIX_VERSION
  1513. LinkedList<HostPosixFileDescriptor>& posixfds(fPluginFrame.loop.posixfds);
  1514. if (posixfds.isNotEmpty())
  1515. {
  1516. for (LinkedList<HostPosixFileDescriptor>::Itenerator it = posixfds.begin2(); it.valid(); it.next())
  1517. {
  1518. HostPosixFileDescriptor& posixfd(it.getValue(kPosixFileDescriptorFallbackNC));
  1519. #ifdef CARLA_VST3_POSIX_EPOLL
  1520. struct ::epoll_event event;
  1521. #else
  1522. const int16_t filter = EVFILT_WRITE;
  1523. struct ::kevent kev = {}, event;
  1524. struct ::timespec timeout = {};
  1525. EV_SET(&kev, posixfd.pluginfd, filter, EV_ADD|EV_ENABLE, 0, 0, nullptr);
  1526. #endif
  1527. for (int i=0; i<50; ++i)
  1528. {
  1529. #ifdef CARLA_VST3_POSIX_EPOLL
  1530. switch (::epoll_wait(posixfd.hostfd, &event, 1, 0))
  1531. #else
  1532. switch (::kevent(posixfd.hostfd, &kev, 1, &event, 1, &timeout))
  1533. #endif
  1534. {
  1535. case 1:
  1536. v3_cpp_obj(posixfd.handler)->on_fd_is_set(posixfd.handler, posixfd.pluginfd);
  1537. break;
  1538. case -1:
  1539. // fall through
  1540. case 0:
  1541. i = 50;
  1542. break;
  1543. default:
  1544. carla_safe_exception("posix fd received abnormal value", __FILE__, __LINE__);
  1545. i = 50;
  1546. break;
  1547. }
  1548. }
  1549. }
  1550. }
  1551. #endif // _POSIX_VERSION
  1552. LinkedList<HostTimer>& timers(fPluginFrame.loop.timers);
  1553. if (timers.isNotEmpty())
  1554. {
  1555. for (LinkedList<HostTimer>::Itenerator it = timers.begin2(); it.valid(); it.next())
  1556. {
  1557. HostTimer& timer(it.getValue(kTimerFallbackNC));
  1558. const uint32_t currentTimeInMs = water::Time::getMillisecondCounter();
  1559. if (currentTimeInMs > timer.lastCallTimeInMs + timer.periodInMs)
  1560. {
  1561. timer.lastCallTimeInMs = currentTimeInMs;
  1562. v3_cpp_obj(timer.handler)->on_timer(timer.handler);
  1563. }
  1564. }
  1565. }
  1566. #endif // V3_VIEW_PLATFORM_TYPE_NATIVE
  1567. }
  1568. void idle() override
  1569. {
  1570. if (kEngineHasIdleOnMainThread)
  1571. runIdleCallbacksAsNeeded(true);
  1572. CarlaPlugin::idle();
  1573. }
  1574. void uiIdle() override
  1575. {
  1576. if (!kEngineHasIdleOnMainThread)
  1577. runIdleCallbacksAsNeeded(true);
  1578. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1579. if (fUI.window != nullptr)
  1580. fUI.window->idle();
  1581. if (fUI.isResizingFromHost)
  1582. {
  1583. fUI.isResizingFromHost = false;
  1584. // if (!fUI.isResizingFromPlugin && !fUI.isResizingFromInit)
  1585. {
  1586. carla_stdout("Host resize stopped");
  1587. // v3_view_rect rect = { 0, 0, static_cast<int32_t>(fUI.width), static_cast<int32_t>(fUI.height) };
  1588. // v3_cpp_obj(fV3.view)->on_size(fV3.view, &rect);
  1589. }
  1590. }
  1591. if (fUI.isResizingFromPlugin)
  1592. {
  1593. fUI.isResizingFromPlugin = false;
  1594. carla_stdout("Plugin resize stopped");
  1595. }
  1596. #endif
  1597. CarlaPlugin::uiIdle();
  1598. }
  1599. // ----------------------------------------------------------------------------------------------------------------
  1600. // Plugin state
  1601. void reload() override
  1602. {
  1603. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
  1604. CARLA_SAFE_ASSERT_RETURN(fV3.component != nullptr,);
  1605. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr,);
  1606. CARLA_SAFE_ASSERT_RETURN(fV3.processor != nullptr,);
  1607. carla_debug("CarlaPluginVST3::reload() - start");
  1608. // Safely disable plugin for reload
  1609. const ScopedDisabler sd(this);
  1610. if (pData->active)
  1611. deactivate();
  1612. clearBuffers();
  1613. const int32_t numAudioInputBuses = v3_cpp_obj(fV3.component)->get_bus_count(fV3.component, V3_AUDIO, V3_INPUT);
  1614. const int32_t numAudioOutputBuses = v3_cpp_obj(fV3.component)->get_bus_count(fV3.component, V3_AUDIO, V3_OUTPUT);
  1615. const int32_t numEventInputBuses = v3_cpp_obj(fV3.component)->get_bus_count(fV3.component, V3_EVENT, V3_INPUT);
  1616. const int32_t numEventOutputBuses = v3_cpp_obj(fV3.component)->get_bus_count(fV3.component, V3_EVENT, V3_OUTPUT);
  1617. const int32_t numParameters = v3_cpp_obj(fV3.controller)->get_parameter_count(fV3.controller);
  1618. CARLA_SAFE_ASSERT(numAudioInputBuses >= 0);
  1619. CARLA_SAFE_ASSERT(numAudioOutputBuses >= 0);
  1620. CARLA_SAFE_ASSERT(numEventInputBuses >= 0);
  1621. CARLA_SAFE_ASSERT(numEventOutputBuses >= 0);
  1622. CARLA_SAFE_ASSERT(numParameters >= 0);
  1623. uint32_t aIns, aOuts, cvIns, cvOuts;
  1624. aIns = aOuts = cvIns = cvOuts = 0;
  1625. bool needsCtrlIn, needsCtrlOut;
  1626. needsCtrlIn = needsCtrlOut = false;
  1627. fBuses.createNew(numAudioInputBuses, numAudioOutputBuses);
  1628. for (int32_t b=0; b<numAudioInputBuses; ++b)
  1629. {
  1630. carla_zeroStruct(fBuses.inputs[b]);
  1631. carla_zeroStruct(fBuses.inputInfo[b]);
  1632. fBuses.inputInfo[b].offset = aIns + cvIns;
  1633. v3_bus_info busInfo = {};
  1634. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component,
  1635. V3_AUDIO, V3_INPUT, b, &busInfo) == V3_OK);
  1636. const int32_t numChannels = busInfo.channel_count;
  1637. CARLA_SAFE_ASSERT_BREAK(numChannels >= 0);
  1638. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->activate_bus(fV3.component,
  1639. V3_AUDIO, V3_INPUT, b, true) == V3_OK);
  1640. fBuses.inputs[b].num_channels = numChannels;
  1641. fBuses.inputInfo[b].bus_type = busInfo.bus_type;
  1642. fBuses.inputInfo[b].flags = busInfo.flags;
  1643. if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
  1644. cvIns += static_cast<uint32_t>(numChannels);
  1645. else
  1646. aIns += static_cast<uint32_t>(numChannels);
  1647. }
  1648. for (int32_t b=0; b<numAudioOutputBuses; ++b)
  1649. {
  1650. carla_zeroStruct(fBuses.outputs[b]);
  1651. carla_zeroStruct(fBuses.outputInfo[b]);
  1652. fBuses.outputInfo[b].offset = aOuts + cvOuts;
  1653. v3_bus_info busInfo = {};
  1654. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component,
  1655. V3_AUDIO, V3_OUTPUT, b, &busInfo) == V3_OK);
  1656. const int32_t numChannels = busInfo.channel_count;
  1657. CARLA_SAFE_ASSERT_BREAK(numChannels >= 0);
  1658. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->activate_bus(fV3.component,
  1659. V3_AUDIO, V3_OUTPUT, b, true) == V3_OK);
  1660. fBuses.outputs[b].num_channels = numChannels;
  1661. fBuses.outputInfo[b].bus_type = busInfo.bus_type;
  1662. fBuses.outputInfo[b].flags = busInfo.flags;
  1663. if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
  1664. cvOuts += static_cast<uint32_t>(numChannels);
  1665. else
  1666. aOuts += static_cast<uint32_t>(numChannels);
  1667. }
  1668. if (aIns > 0)
  1669. {
  1670. pData->audioIn.createNew(aIns);
  1671. }
  1672. if (aOuts > 0)
  1673. {
  1674. pData->audioOut.createNew(aOuts);
  1675. needsCtrlIn = true;
  1676. }
  1677. if (cvIns > 0)
  1678. pData->cvIn.createNew(cvIns);
  1679. if (cvOuts > 0)
  1680. pData->cvOut.createNew(cvOuts);
  1681. if (numEventInputBuses > 0)
  1682. needsCtrlIn = true;
  1683. if (numEventOutputBuses > 0)
  1684. needsCtrlOut = true;
  1685. if (numParameters > 0)
  1686. {
  1687. pData->param.createNew(numParameters, false);
  1688. needsCtrlIn = true;
  1689. }
  1690. if (aOuts + cvOuts > 0)
  1691. {
  1692. fAudioAndCvOutBuffers = new float*[aOuts + cvOuts];
  1693. for (uint32_t i=0; i < aOuts + cvOuts; ++i)
  1694. fAudioAndCvOutBuffers[i] = nullptr;
  1695. }
  1696. const EngineProcessMode processMode = pData->engine->getProccessMode();
  1697. const uint portNameSize = pData->engine->getMaxPortNameSize();
  1698. CarlaString portName;
  1699. // Audio Ins
  1700. for (uint32_t j=0; j < aIns; ++j)
  1701. {
  1702. portName.clear();
  1703. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1704. {
  1705. portName = pData->name;
  1706. portName += ":";
  1707. }
  1708. if (aIns > 1)
  1709. {
  1710. portName += "input_";
  1711. portName += CarlaString(j+1);
  1712. }
  1713. else
  1714. portName += "input";
  1715. portName.truncate(portNameSize);
  1716. pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio,
  1717. portName, true, j);
  1718. pData->audioIn.ports[j].rindex = j;
  1719. }
  1720. // Audio Outs
  1721. for (uint32_t j=0; j < aOuts; ++j)
  1722. {
  1723. portName.clear();
  1724. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1725. {
  1726. portName = pData->name;
  1727. portName += ":";
  1728. }
  1729. if (aOuts > 1)
  1730. {
  1731. portName += "output_";
  1732. portName += CarlaString(j+1);
  1733. }
  1734. else
  1735. portName += "output";
  1736. portName.truncate(portNameSize);
  1737. pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio,
  1738. portName, false, j);
  1739. pData->audioOut.ports[j].rindex = j;
  1740. }
  1741. // CV Ins
  1742. for (uint32_t j=0; j < cvIns; ++j)
  1743. {
  1744. portName.clear();
  1745. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1746. {
  1747. portName = pData->name;
  1748. portName += ":";
  1749. }
  1750. if (cvIns > 1)
  1751. {
  1752. portName += "cv_input_";
  1753. portName += CarlaString(j+1);
  1754. }
  1755. else
  1756. portName += "cv_input";
  1757. portName.truncate(portNameSize);
  1758. pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV,
  1759. portName, true, j);
  1760. pData->cvIn.ports[j].rindex = j;
  1761. }
  1762. // CV Outs
  1763. for (uint32_t j=0; j < cvOuts; ++j)
  1764. {
  1765. portName.clear();
  1766. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1767. {
  1768. portName = pData->name;
  1769. portName += ":";
  1770. }
  1771. if (cvOuts > 1)
  1772. {
  1773. portName += "cv_output_";
  1774. portName += CarlaString(j+1);
  1775. }
  1776. else
  1777. portName += "cv_output";
  1778. portName.truncate(portNameSize);
  1779. pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV,
  1780. portName, false, j);
  1781. pData->cvOut.ports[j].rindex = j;
  1782. }
  1783. for (int32_t j=0; j < numParameters; ++j)
  1784. {
  1785. v3_param_info paramInfo = {};
  1786. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.controller)->get_parameter_info(fV3.controller,
  1787. j, &paramInfo) == V3_OK);
  1788. char strBuf[200];
  1789. strncpy_utf8(strBuf, paramInfo.title, 128);
  1790. const v3_param_id paramId = paramInfo.param_id;
  1791. pData->param.data[j].index = static_cast<uint32_t>(j);
  1792. pData->param.data[j].rindex = paramId;
  1793. if (paramInfo.flags & (V3_PARAM_IS_BYPASS|V3_PARAM_IS_HIDDEN|V3_PARAM_PROGRAM_CHANGE))
  1794. continue;
  1795. double min, max, def, step, stepSmall, stepLarge;
  1796. min = v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller, paramId, 0.0);
  1797. max = v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller, paramId, 1.0);
  1798. def = v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller, paramId,
  1799. paramInfo.default_normalised_value);
  1800. if (min >= max)
  1801. max = min + 0.1;
  1802. if (def < min)
  1803. def = min;
  1804. else if (def > max)
  1805. def = max;
  1806. if (paramInfo.flags & V3_PARAM_READ_ONLY)
  1807. pData->param.data[j].type = PARAMETER_OUTPUT;
  1808. else
  1809. pData->param.data[j].type = PARAMETER_INPUT;
  1810. if (paramInfo.step_count == 1)
  1811. {
  1812. step = max - min;
  1813. stepSmall = step;
  1814. stepLarge = step;
  1815. pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
  1816. }
  1817. /*
  1818. else if (paramInfo.step_count != 0 && (paramInfo.flags & V3_PARAM_IS_LIST) != 0x0)
  1819. {
  1820. step = 1.0;
  1821. stepSmall = 1.0;
  1822. stepLarge = std::min(max - min, 10.0);
  1823. pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
  1824. }
  1825. */
  1826. else
  1827. {
  1828. float range = max - min;
  1829. step = range/100.0;
  1830. stepSmall = range/1000.0;
  1831. stepLarge = range/10.0;
  1832. }
  1833. pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
  1834. pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;
  1835. if (paramInfo.flags & V3_PARAM_CAN_AUTOMATE)
  1836. {
  1837. pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
  1838. if ((paramInfo.flags & V3_PARAM_IS_LIST) == 0x0)
  1839. pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED;
  1840. }
  1841. pData->param.ranges[j].min = min;
  1842. pData->param.ranges[j].max = max;
  1843. pData->param.ranges[j].def = def;
  1844. pData->param.ranges[j].step = step;
  1845. pData->param.ranges[j].stepSmall = stepSmall;
  1846. pData->param.ranges[j].stepLarge = stepLarge;
  1847. }
  1848. if (numParameters > 0)
  1849. {
  1850. fEvents.paramInputs = new carla_v3_input_param_changes(pData->param);
  1851. fEvents.paramOutputs = new carla_v3_output_param_changes(pData->param);
  1852. }
  1853. if (needsCtrlIn)
  1854. {
  1855. portName.clear();
  1856. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1857. {
  1858. portName = pData->name;
  1859. portName += ":";
  1860. }
  1861. portName += "events-in";
  1862. portName.truncate(portNameSize);
  1863. pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent,
  1864. portName, true, 0);
  1865. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  1866. pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
  1867. #endif
  1868. fEvents.eventInputs = new carla_v3_input_event_list;
  1869. }
  1870. if (needsCtrlOut)
  1871. {
  1872. portName.clear();
  1873. if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  1874. {
  1875. portName = pData->name;
  1876. portName += ":";
  1877. }
  1878. portName += "events-out";
  1879. portName.truncate(portNameSize);
  1880. pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent,
  1881. portName, false, 0);
  1882. fEvents.eventOutputs = new carla_v3_output_event_list;
  1883. }
  1884. // plugin hints
  1885. const PluginCategory v3category = getPluginCategoryFromV3SubCategories(fV3ClassInfo.v2.sub_categories);
  1886. pData->hints = 0x0;
  1887. if (v3category == PLUGIN_CATEGORY_SYNTH)
  1888. pData->hints |= PLUGIN_IS_SYNTH;
  1889. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1890. if (fV3.view != nullptr &&
  1891. v3_cpp_obj(fV3.view)->is_platform_type_supported(fV3.view, V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_TRUE)
  1892. {
  1893. pData->hints |= PLUGIN_HAS_CUSTOM_UI;
  1894. pData->hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
  1895. pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
  1896. }
  1897. #endif
  1898. if (aOuts > 0 && (aIns == aOuts || aIns == 1))
  1899. pData->hints |= PLUGIN_CAN_DRYWET;
  1900. if (aOuts > 0)
  1901. pData->hints |= PLUGIN_CAN_VOLUME;
  1902. if (aOuts >= 2 && aOuts % 2 == 0)
  1903. pData->hints |= PLUGIN_CAN_BALANCE;
  1904. // extra plugin hints
  1905. pData->extraHints = 0x0;
  1906. if (numEventInputBuses > 0)
  1907. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
  1908. if (numEventOutputBuses > 0)
  1909. pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;
  1910. // check initial latency
  1911. if ((fLastKnownLatency = v3_cpp_obj(fV3.processor)->get_latency_samples(fV3.processor)) != 0)
  1912. {
  1913. pData->client->setLatency(fLastKnownLatency);
  1914. #ifndef BUILD_BRIDGE
  1915. pData->latency.recreateBuffers(std::max(aIns+cvIns, aOuts+cvOuts), fLastKnownLatency);
  1916. #endif
  1917. }
  1918. // initial audio setup
  1919. v3_process_setup setup = {
  1920. pData->engine->isOffline() ? V3_OFFLINE : V3_REALTIME,
  1921. V3_SAMPLE_32,
  1922. static_cast<int32_t>(pData->engine->getBufferSize()),
  1923. pData->engine->getSampleRate()
  1924. };
  1925. v3_cpp_obj(fV3.processor)->setup_processing(fV3.processor, &setup);
  1926. // activate all buses
  1927. for (int32_t j=0; j<numAudioInputBuses; ++j)
  1928. {
  1929. v3_bus_info busInfo = {};
  1930. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component,
  1931. V3_AUDIO, V3_INPUT, j, &busInfo) == V3_OK);
  1932. if ((busInfo.flags & V3_DEFAULT_ACTIVE) == 0x0) {
  1933. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->activate_bus(fV3.component,
  1934. V3_AUDIO, V3_INPUT, j, true) == V3_OK);
  1935. }
  1936. }
  1937. for (int32_t j=0; j<numAudioOutputBuses; ++j)
  1938. {
  1939. v3_bus_info busInfo = {};
  1940. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->get_bus_info(fV3.component,
  1941. V3_AUDIO, V3_OUTPUT, j, &busInfo) == V3_OK);
  1942. if ((busInfo.flags & V3_DEFAULT_ACTIVE) == 0x0) {
  1943. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(fV3.component)->activate_bus(fV3.component,
  1944. V3_AUDIO, V3_OUTPUT, j, true) == V3_OK);
  1945. }
  1946. }
  1947. if (fEvents.paramInputs != nullptr && fV3.midiMapping != nullptr)
  1948. fMidiControllerAssignments.init(fV3.midiMapping, numEventInputBuses);
  1949. bufferSizeChanged(pData->engine->getBufferSize());
  1950. reloadPrograms(true);
  1951. if (pData->active)
  1952. activate();
  1953. else
  1954. runIdleCallbacksAsNeeded(false);
  1955. carla_debug("CarlaPluginVST3::reload() - end");
  1956. }
  1957. // ----------------------------------------------------------------------------------------------------------------
  1958. // Plugin processing
  1959. void activate() noexcept override
  1960. {
  1961. CARLA_SAFE_ASSERT_RETURN(fV3.component != nullptr,);
  1962. CARLA_SAFE_ASSERT_RETURN(fV3.processor != nullptr,);
  1963. try {
  1964. v3_cpp_obj(fV3.component)->set_active(fV3.component, true);
  1965. } CARLA_SAFE_EXCEPTION("set_active on");
  1966. try {
  1967. v3_cpp_obj(fV3.processor)->set_processing(fV3.processor, true);
  1968. } CARLA_SAFE_EXCEPTION("set_processing on");
  1969. fFirstActive = true;
  1970. runIdleCallbacksAsNeeded(false);
  1971. }
  1972. void deactivate() noexcept override
  1973. {
  1974. CARLA_SAFE_ASSERT_RETURN(fV3.component != nullptr,);
  1975. CARLA_SAFE_ASSERT_RETURN(fV3.processor != nullptr,);
  1976. try {
  1977. v3_cpp_obj(fV3.processor)->set_processing(fV3.processor, false);
  1978. } CARLA_SAFE_EXCEPTION("set_processing off");
  1979. try {
  1980. v3_cpp_obj(fV3.component)->set_active(fV3.component, false);
  1981. } CARLA_SAFE_EXCEPTION("set_active off");
  1982. runIdleCallbacksAsNeeded(false);
  1983. }
  1984. void process(const float* const* const audioIn, float** const audioOut,
  1985. const float* const* const cvIn, float** const cvOut, const uint32_t frames) override
  1986. {
  1987. // ------------------------------------------------------------------------------------------------------------
  1988. // Check if active
  1989. if (! pData->active)
  1990. {
  1991. // disable any output sound
  1992. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  1993. carla_zeroFloats(audioOut[i], frames);
  1994. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  1995. carla_zeroFloats(cvOut[i], frames);
  1996. return;
  1997. }
  1998. fEvents.init();
  1999. // ------------------------------------------------------------------------------------------------------------
  2000. // Check if needs reset
  2001. if (pData->needsReset)
  2002. {
  2003. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  2004. {
  2005. for (uint8_t c=0; c<MAX_MIDI_CHANNELS; ++c)
  2006. {
  2007. v3_param_id paramId;
  2008. if (fMidiControllerAssignments.get(0, c, MIDI_CONTROL_ALL_NOTES_OFF, paramId))
  2009. {
  2010. // TODO create mapping between paramId -> index
  2011. uint32_t index = UINT32_MAX;
  2012. for (uint32_t i=0; i < pData->param.count; ++i)
  2013. {
  2014. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2015. {
  2016. index = i;
  2017. break;
  2018. }
  2019. }
  2020. if (index == UINT32_MAX)
  2021. break;
  2022. fEvents.paramInputs->setParamValueRT(index, 0, 0.f);
  2023. }
  2024. }
  2025. }
  2026. else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS && fEvents.eventInputs != nullptr)
  2027. {
  2028. fEvents.eventInputs->numEvents = MAX_MIDI_NOTE;
  2029. for (uint8_t i=0; i < MAX_MIDI_NOTE; ++i)
  2030. {
  2031. v3_event& event(fEvents.eventInputs->events[i]);
  2032. carla_zeroStruct(event);
  2033. event.type = V3_EVENT_NOTE_OFF;
  2034. event.note_off.channel = (pData->ctrlChannel & MIDI_CHANNEL_BIT);
  2035. event.note_off.pitch = i;
  2036. }
  2037. }
  2038. pData->needsReset = false;
  2039. }
  2040. // ------------------------------------------------------------------------------------------------------------
  2041. // Set TimeInfo
  2042. const EngineTimeInfo timeInfo(pData->engine->getTimeInfo());
  2043. fV3TimeContext.state = V3_PROCESS_CTX_PROJECT_TIME_VALID | V3_PROCESS_CTX_CONT_TIME_VALID;
  2044. fV3TimeContext.sample_rate = pData->engine->getSampleRate();
  2045. fV3TimeContext.project_time_in_samples = fV3TimeContext.continuous_time_in_samples
  2046. = static_cast<int64_t>(timeInfo.frame);
  2047. if (fFirstActive || ! fLastTimeInfo.compareIgnoringRollingFrames(timeInfo, frames))
  2048. fLastTimeInfo = timeInfo;
  2049. if (timeInfo.playing)
  2050. fV3TimeContext.state |= V3_PROCESS_CTX_PLAYING;
  2051. if (timeInfo.usecs != 0)
  2052. {
  2053. fV3TimeContext.system_time_ns = static_cast<int64_t>(timeInfo.usecs / 1000);
  2054. fV3TimeContext.state |= V3_PROCESS_CTX_SYSTEM_TIME_VALID;
  2055. }
  2056. if (timeInfo.bbt.valid)
  2057. {
  2058. CARLA_SAFE_ASSERT_INT(timeInfo.bbt.bar > 0, timeInfo.bbt.bar);
  2059. CARLA_SAFE_ASSERT_INT(timeInfo.bbt.beat > 0, timeInfo.bbt.beat);
  2060. const double ppqBar = static_cast<double>(timeInfo.bbt.beatsPerBar) * (timeInfo.bbt.bar - 1);
  2061. // const double ppqBeat = static_cast<double>(timeInfo.bbt.beat - 1);
  2062. // const double ppqTick = timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat;
  2063. // PPQ Pos
  2064. fV3TimeContext.project_time_quarters = static_cast<double>(timeInfo.frame) / (fV3TimeContext.sample_rate * 60 / timeInfo.bbt.beatsPerMinute);
  2065. // fTimeInfo.project_time_quarters = ppqBar + ppqBeat + ppqTick;
  2066. fV3TimeContext.state |= V3_PROCESS_CTX_PROJECT_TIME_VALID;
  2067. // Tempo
  2068. fV3TimeContext.bpm = timeInfo.bbt.beatsPerMinute;
  2069. fV3TimeContext.state |= V3_PROCESS_CTX_TEMPO_VALID;
  2070. // Bars
  2071. fV3TimeContext.bar_position_quarters = ppqBar;
  2072. fV3TimeContext.state |= V3_PROCESS_CTX_BAR_POSITION_VALID;
  2073. // Time Signature
  2074. fV3TimeContext.time_sig_numerator = static_cast<int32_t>(timeInfo.bbt.beatsPerBar + 0.5f);
  2075. fV3TimeContext.time_sig_denom = static_cast<int32_t>(timeInfo.bbt.beatType + 0.5f);
  2076. fV3TimeContext.state |= V3_PROCESS_CTX_TIME_SIG_VALID;
  2077. }
  2078. else
  2079. {
  2080. // Tempo
  2081. fV3TimeContext.bpm = 120.0;
  2082. fV3TimeContext.state |= V3_PROCESS_CTX_TEMPO_VALID;
  2083. // Time Signature
  2084. fV3TimeContext.time_sig_numerator = 4;
  2085. fV3TimeContext.time_sig_denom = 4;
  2086. fV3TimeContext.state |= V3_PROCESS_CTX_TIME_SIG_VALID;
  2087. // Missing info
  2088. fV3TimeContext.project_time_quarters = 0.0;
  2089. fV3TimeContext.bar_position_quarters = 0.0;
  2090. }
  2091. // ------------------------------------------------------------------------------------------------------------
  2092. // Event Input and Processing
  2093. if (pData->event.portIn != nullptr && fEvents.eventInputs != nullptr)
  2094. {
  2095. // --------------------------------------------------------------------------------------------------------
  2096. // MIDI Input (External)
  2097. if (pData->extNotes.mutex.tryLock())
  2098. {
  2099. ExternalMidiNote note = { 0, 0, 0 };
  2100. uint16_t numEvents = fEvents.eventInputs->numEvents;
  2101. for (; numEvents < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();)
  2102. {
  2103. note = pData->extNotes.data.getFirst(note, true);
  2104. CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
  2105. v3_event& event(fEvents.eventInputs->events[numEvents++]);
  2106. carla_zeroStruct(event);
  2107. if (note.velo > 0)
  2108. {
  2109. event.type = V3_EVENT_NOTE_ON;
  2110. event.note_on.channel = (note.channel & MIDI_CHANNEL_BIT);
  2111. event.note_on.pitch = note.note;
  2112. event.note_on.velocity = static_cast<float>(note.velo) / 127.f;
  2113. }
  2114. else
  2115. {
  2116. event.type = V3_EVENT_NOTE_OFF;
  2117. event.note_off.channel = (note.channel & MIDI_CHANNEL_BIT);
  2118. event.note_off.pitch = note.note;
  2119. }
  2120. }
  2121. pData->extNotes.mutex.unlock();
  2122. fEvents.eventInputs->numEvents = numEvents;
  2123. } // End of MIDI Input (External)
  2124. // --------------------------------------------------------------------------------------------------------
  2125. // Event Input (System)
  2126. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2127. bool allNotesOffSent = false;
  2128. #endif
  2129. bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
  2130. uint32_t startTime = 0;
  2131. uint32_t timeOffset = 0;
  2132. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2133. if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
  2134. pData->event.cvSourcePorts->initPortBuffers(cvIn, frames, isSampleAccurate, pData->event.portIn);
  2135. #endif
  2136. for (uint32_t i=0, numEvents = pData->event.portIn->getEventCount(); i < numEvents; ++i)
  2137. {
  2138. EngineEvent& event(pData->event.portIn->getEvent(i));
  2139. uint32_t eventTime = event.time;
  2140. CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
  2141. if (eventTime < timeOffset)
  2142. {
  2143. carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
  2144. eventTime, timeOffset, pData->name);
  2145. eventTime = timeOffset;
  2146. }
  2147. if (isSampleAccurate && eventTime > timeOffset)
  2148. {
  2149. if (processSingle(audioIn, audioOut, cvIn, cvOut, eventTime - timeOffset, timeOffset))
  2150. {
  2151. startTime = 0;
  2152. timeOffset = eventTime;
  2153. // TODO
  2154. }
  2155. else
  2156. {
  2157. startTime += timeOffset;
  2158. }
  2159. }
  2160. switch (event.type)
  2161. {
  2162. case kEngineEventTypeNull:
  2163. break;
  2164. case kEngineEventTypeControl: {
  2165. EngineControlEvent& ctrlEvent(event.ctrl);
  2166. switch (ctrlEvent.type)
  2167. {
  2168. case kEngineControlEventTypeNull:
  2169. break;
  2170. case kEngineControlEventTypeParameter: {
  2171. float value;
  2172. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2173. // non-midi
  2174. if (event.channel == kEngineEventNonMidiChannel)
  2175. {
  2176. const uint32_t k = ctrlEvent.param;
  2177. CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
  2178. ctrlEvent.handled = true;
  2179. value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
  2180. setParameterValueRT(k, value, event.time, true);
  2181. continue;
  2182. }
  2183. // Control backend stuff
  2184. if (event.channel == pData->ctrlChannel)
  2185. {
  2186. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
  2187. {
  2188. ctrlEvent.handled = true;
  2189. value = ctrlEvent.normalizedValue;
  2190. setDryWetRT(value, true);
  2191. }
  2192. else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
  2193. {
  2194. ctrlEvent.handled = true;
  2195. value = ctrlEvent.normalizedValue*127.0f/100.0f;
  2196. setVolumeRT(value, true);
  2197. }
  2198. else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
  2199. {
  2200. float left, right;
  2201. value = ctrlEvent.normalizedValue/0.5f - 1.0f;
  2202. if (value < 0.0f)
  2203. {
  2204. left = -1.0f;
  2205. right = (value*2.0f)+1.0f;
  2206. }
  2207. else if (value > 0.0f)
  2208. {
  2209. left = (value*2.0f)-1.0f;
  2210. right = 1.0f;
  2211. }
  2212. else
  2213. {
  2214. left = -1.0f;
  2215. right = 1.0f;
  2216. }
  2217. ctrlEvent.handled = true;
  2218. setBalanceLeftRT(left, true);
  2219. setBalanceRightRT(right, true);
  2220. }
  2221. }
  2222. #endif
  2223. // Control plugin parameters
  2224. uint32_t k;
  2225. for (k=0; k < pData->param.count; ++k)
  2226. {
  2227. if (pData->param.data[k].midiChannel != event.channel)
  2228. continue;
  2229. if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
  2230. continue;
  2231. if (pData->param.data[k].type != PARAMETER_INPUT)
  2232. continue;
  2233. if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMATABLE) == 0)
  2234. continue;
  2235. ctrlEvent.handled = true;
  2236. value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
  2237. setParameterValueRT(k, value, event.time, true);
  2238. }
  2239. if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
  2240. {
  2241. v3_param_id paramId;
  2242. if (fMidiControllerAssignments.get(0, event.channel, ctrlEvent.param, paramId))
  2243. {
  2244. // TODO create mapping between paramId -> index
  2245. uint32_t index = UINT32_MAX;
  2246. for (uint32_t i=0; i < pData->param.count; ++i)
  2247. {
  2248. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2249. {
  2250. index = i;
  2251. break;
  2252. }
  2253. }
  2254. if (index == UINT32_MAX)
  2255. break;
  2256. fEvents.paramInputs->setParamValueRT(index, event.time, ctrlEvent.normalizedValue);
  2257. }
  2258. }
  2259. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2260. if (! ctrlEvent.handled)
  2261. checkForMidiLearn(event);
  2262. #endif
  2263. break;
  2264. } // case kEngineControlEventTypeParameter
  2265. case kEngineControlEventTypeMidiBank:
  2266. break;
  2267. case kEngineControlEventTypeMidiProgram:
  2268. if (event.channel == pData->ctrlChannel && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
  2269. {
  2270. if (ctrlEvent.param < pData->prog.count)
  2271. {
  2272. setProgramRT(ctrlEvent.param, true);
  2273. break;
  2274. }
  2275. }
  2276. break;
  2277. case kEngineControlEventTypeAllSoundOff:
  2278. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  2279. {
  2280. v3_param_id paramId;
  2281. if (fMidiControllerAssignments.get(0, event.channel, MIDI_CONTROL_ALL_SOUND_OFF, paramId))
  2282. {
  2283. // TODO create mapping between paramId -> index
  2284. uint32_t index = UINT32_MAX;
  2285. for (uint32_t i=0; i < pData->param.count; ++i)
  2286. {
  2287. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2288. {
  2289. index = i;
  2290. break;
  2291. }
  2292. }
  2293. if (index == UINT32_MAX)
  2294. break;
  2295. fEvents.paramInputs->setParamValueRT(index, event.time, 0.f);
  2296. }
  2297. }
  2298. break;
  2299. case kEngineControlEventTypeAllNotesOff:
  2300. if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
  2301. {
  2302. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2303. if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
  2304. {
  2305. allNotesOffSent = true;
  2306. postponeRtAllNotesOff();
  2307. }
  2308. #endif
  2309. v3_param_id paramId;
  2310. if (fMidiControllerAssignments.get(0, event.channel, MIDI_CONTROL_ALL_NOTES_OFF, paramId))
  2311. {
  2312. // TODO create mapping between paramId -> index
  2313. uint32_t index = UINT32_MAX;
  2314. for (uint32_t i=0; i < pData->param.count; ++i)
  2315. {
  2316. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2317. {
  2318. index = i;
  2319. break;
  2320. }
  2321. }
  2322. if (index == UINT32_MAX)
  2323. break;
  2324. fEvents.paramInputs->setParamValueRT(index, event.time, 0.f);
  2325. }
  2326. }
  2327. break;
  2328. } // switch (ctrlEvent.type)
  2329. break;
  2330. } // case kEngineEventTypeControl
  2331. case kEngineEventTypeMidi: {
  2332. const EngineMidiEvent& midiEvent(event.midi);
  2333. if (midiEvent.size > 3)
  2334. continue;
  2335. #ifdef CARLA_PROPER_CPP11_SUPPORT
  2336. static_assert(3 <= EngineMidiEvent::kDataSize, "Incorrect data");
  2337. #endif
  2338. uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data));
  2339. if ((status == MIDI_STATUS_NOTE_OFF || status == MIDI_STATUS_NOTE_ON) && (pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES))
  2340. continue;
  2341. if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
  2342. continue;
  2343. if (status == MIDI_STATUS_CONTROL_CHANGE && ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0 || fEvents.paramInputs == nullptr || fV3.midiMapping == nullptr))
  2344. continue;
  2345. if (status == MIDI_STATUS_CHANNEL_PRESSURE && ((pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0 || fEvents.paramInputs == nullptr || fV3.midiMapping == nullptr))
  2346. continue;
  2347. if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && ((pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0 || fEvents.paramInputs == nullptr || fV3.midiMapping == nullptr))
  2348. continue;
  2349. // Fix bad note-off
  2350. if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
  2351. status = MIDI_STATUS_NOTE_OFF;
  2352. switch (status)
  2353. {
  2354. case MIDI_STATUS_NOTE_OFF:
  2355. if (fEvents.eventInputs->numEvents < kPluginMaxMidiEvents)
  2356. {
  2357. const uint8_t note = midiEvent.data[1];
  2358. v3_event& v3event(fEvents.eventInputs->events[fEvents.eventInputs->numEvents++]);
  2359. carla_zeroStruct(v3event);
  2360. v3event.type = V3_EVENT_NOTE_OFF;
  2361. v3event.note_off.channel = event.channel & MIDI_CHANNEL_BIT;
  2362. v3event.note_off.pitch = note;
  2363. pData->postponeNoteOffRtEvent(true, event.channel, note);
  2364. }
  2365. break;
  2366. case MIDI_STATUS_NOTE_ON:
  2367. if (fEvents.eventInputs->numEvents < kPluginMaxMidiEvents)
  2368. {
  2369. const uint8_t note = midiEvent.data[1];
  2370. const uint8_t velo = midiEvent.data[2];
  2371. v3_event& v3event(fEvents.eventInputs->events[fEvents.eventInputs->numEvents++]);
  2372. carla_zeroStruct(v3event);
  2373. v3event.type = V3_EVENT_NOTE_ON;
  2374. v3event.note_on.channel = event.channel & MIDI_CHANNEL_BIT;
  2375. v3event.note_on.pitch = note;
  2376. v3event.note_on.velocity = static_cast<float>(velo) / 127.f;
  2377. pData->postponeNoteOnRtEvent(true, event.channel, note, velo);
  2378. }
  2379. break;
  2380. case MIDI_STATUS_POLYPHONIC_AFTERTOUCH:
  2381. if (fEvents.eventInputs->numEvents < kPluginMaxMidiEvents)
  2382. {
  2383. const uint8_t note = midiEvent.data[1];
  2384. const uint8_t pressure = midiEvent.data[2];
  2385. v3_event& v3event(fEvents.eventInputs->events[fEvents.eventInputs->numEvents++]);
  2386. carla_zeroStruct(v3event);
  2387. v3event.type = V3_EVENT_POLY_PRESSURE;
  2388. v3event.poly_pressure.channel = event.channel;
  2389. v3event.poly_pressure.pitch = note;
  2390. v3event.poly_pressure.pressure = static_cast<float>(pressure) / 127.f;
  2391. }
  2392. break;
  2393. case MIDI_STATUS_CONTROL_CHANGE:
  2394. {
  2395. const uint8_t control = midiEvent.data[1];
  2396. const uint8_t value = midiEvent.data[2];
  2397. v3_param_id paramId;
  2398. if (fMidiControllerAssignments.get(midiEvent.port, event.channel, control, paramId))
  2399. {
  2400. // TODO create mapping between paramId -> index
  2401. uint32_t index = UINT32_MAX;
  2402. for (uint32_t i=0; i < pData->param.count; ++i)
  2403. {
  2404. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2405. {
  2406. index = i;
  2407. break;
  2408. }
  2409. }
  2410. if (index == UINT32_MAX)
  2411. break;
  2412. fEvents.paramInputs->setParamValueRT(index,
  2413. event.time,
  2414. static_cast<float>(value) / 127.f);
  2415. }
  2416. }
  2417. break;
  2418. case MIDI_STATUS_CHANNEL_PRESSURE:
  2419. {
  2420. const uint8_t pressure = midiEvent.data[1];
  2421. v3_param_id paramId;
  2422. if (fMidiControllerAssignments.get(midiEvent.port, event.channel, 128, paramId))
  2423. {
  2424. // TODO create mapping between paramId -> index
  2425. uint32_t index = UINT32_MAX;
  2426. for (uint32_t i=0; i < pData->param.count; ++i)
  2427. {
  2428. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2429. {
  2430. index = i;
  2431. break;
  2432. }
  2433. }
  2434. if (index == UINT32_MAX)
  2435. break;
  2436. fEvents.paramInputs->setParamValueRT(index,
  2437. event.time,
  2438. static_cast<float>(pressure) / 127.f);
  2439. }
  2440. }
  2441. break;
  2442. case MIDI_STATUS_PITCH_WHEEL_CONTROL:
  2443. {
  2444. const uint16_t pitchbend = (midiEvent.data[2] << 7) | midiEvent.data[1];
  2445. v3_param_id paramId;
  2446. if (fMidiControllerAssignments.get(midiEvent.port, event.channel, 129, paramId))
  2447. {
  2448. // TODO create mapping between paramId -> index
  2449. uint32_t index = UINT32_MAX;
  2450. for (uint32_t i=0; i < pData->param.count; ++i)
  2451. {
  2452. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  2453. {
  2454. index = i;
  2455. break;
  2456. }
  2457. }
  2458. if (index == UINT32_MAX)
  2459. break;
  2460. fEvents.paramInputs->setParamValueRT(index,
  2461. event.time,
  2462. static_cast<float>(pitchbend) / 16384.f);
  2463. }
  2464. }
  2465. break;
  2466. } // switch (status)
  2467. } break;
  2468. } // switch (event.type)
  2469. }
  2470. pData->postRtEvents.trySplice();
  2471. if (frames > timeOffset)
  2472. processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset);
  2473. } // End of Event Input and Processing
  2474. // ------------------------------------------------------------------------------------------------------------
  2475. // Plugin processing (no events)
  2476. else
  2477. {
  2478. processSingle(audioIn, audioOut, cvIn, cvOut, frames, 0);
  2479. } // End of Plugin processing (no events)
  2480. fFirstActive = false;
  2481. // ------------------------------------------------------------------------------------------------------------
  2482. }
  2483. bool processSingle(const float* const* const inBuffer, float** const outBuffer,
  2484. const float* const* const cvIn, float** const cvOut,
  2485. const uint32_t frames, const uint32_t timeOffset)
  2486. {
  2487. CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
  2488. if (pData->audioIn.count > 0)
  2489. {
  2490. CARLA_SAFE_ASSERT_RETURN(inBuffer != nullptr, false);
  2491. }
  2492. if (pData->audioOut.count > 0)
  2493. {
  2494. CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false);
  2495. CARLA_SAFE_ASSERT_RETURN(fAudioAndCvOutBuffers != nullptr, false);
  2496. }
  2497. // ------------------------------------------------------------------------------------------------------------
  2498. // Try lock, silence otherwise
  2499. #ifndef STOAT_TEST_BUILD
  2500. if (pData->engine->isOffline())
  2501. {
  2502. pData->singleMutex.lock();
  2503. }
  2504. else
  2505. #endif
  2506. if (! pData->singleMutex.tryLock())
  2507. {
  2508. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  2509. {
  2510. for (uint32_t k=0; k < frames; ++k)
  2511. outBuffer[i][k+timeOffset] = 0.0f;
  2512. }
  2513. for (uint32_t i=0; i < pData->cvOut.count; ++i)
  2514. {
  2515. for (uint32_t k=0; k < frames; ++k)
  2516. cvOut[i][k+timeOffset] = 0.0f;
  2517. }
  2518. return false;
  2519. }
  2520. // ------------------------------------------------------------------------------------------------------------
  2521. // Set audio buffers
  2522. float* bufferAudioIn[96]; // std::max(1u, pData->audioIn.count + pData->cvIn.count)
  2523. float* bufferAudioOut[96]; // std::max(1u, pData->audioOut.count + pData->cvOut.count)
  2524. for (uint32_t i=0; i < pData->audioIn.count; ++i)
  2525. bufferAudioIn[i] = const_cast<float*>(inBuffer[i]+timeOffset);
  2526. for (uint32_t i=0, j=pData->audioIn.count; i < pData->cvIn.count; ++i, ++j)
  2527. bufferAudioIn[j] = const_cast<float*>(cvIn[i]+timeOffset);
  2528. for (uint32_t i=0; i < pData->audioOut.count + pData->cvOut.count; ++i)
  2529. {
  2530. bufferAudioOut[i] = fAudioAndCvOutBuffers[i]+timeOffset;
  2531. carla_zeroFloats(bufferAudioOut[i], frames);
  2532. }
  2533. // ------------------------------------------------------------------------------------------------------------
  2534. // Set MIDI events
  2535. // TODO
  2536. // ------------------------------------------------------------------------------------------------------------
  2537. // Run plugin
  2538. fEvents.prepare();
  2539. for (int32_t b = 0, j = 0; b < fBuses.numInputs; ++b)
  2540. {
  2541. fBuses.inputs[b].channel_buffers_32 = const_cast<float**>(bufferAudioIn + j);
  2542. j += fBuses.inputs[b].num_channels;
  2543. }
  2544. for (int32_t b = 0, j = 0; b < fBuses.numOutputs; ++b)
  2545. {
  2546. fBuses.outputs[b].channel_buffers_32 = bufferAudioOut + j;
  2547. j += fBuses.outputs[b].num_channels;
  2548. }
  2549. v3_process_data processData = {
  2550. pData->engine->isOffline() ? V3_OFFLINE : V3_REALTIME,
  2551. V3_SAMPLE_32,
  2552. static_cast<int32_t>(frames),
  2553. fBuses.numInputs,
  2554. fBuses.numOutputs,
  2555. fBuses.inputs,
  2556. fBuses.outputs,
  2557. fEvents.paramInputs != nullptr ? (v3_param_changes**)&fEvents.paramInputs : nullptr,
  2558. fEvents.paramOutputs != nullptr ? (v3_param_changes**)&fEvents.paramOutputs : nullptr,
  2559. fEvents.eventInputs != nullptr ? (v3_event_list**)&fEvents.eventInputs : nullptr,
  2560. fEvents.eventOutputs != nullptr ? (v3_event_list**)&fEvents.eventOutputs : nullptr,
  2561. &fV3TimeContext
  2562. };
  2563. try {
  2564. v3_cpp_obj(fV3.processor)->process(fV3.processor, &processData);
  2565. } CARLA_SAFE_EXCEPTION("process");
  2566. // ------------------------------------------------------------------------------------------------------------
  2567. // Handle MIDI output
  2568. int32_t minPortOutOffset = 0;
  2569. if (fEvents.eventOutputs != nullptr)
  2570. {
  2571. uint8_t midiData[3], midiSize;
  2572. for (uint32_t i=0; i < fEvents.eventOutputs->numEvents; ++i)
  2573. {
  2574. v3_event& v3event(fEvents.eventOutputs->events[i]);
  2575. if (v3event.bus_index != 0)
  2576. continue;
  2577. switch (v3event.type)
  2578. {
  2579. case V3_EVENT_NOTE_OFF:
  2580. midiData[0] = MIDI_STATUS_NOTE_OFF | (v3event.note_off.channel & MIDI_CHANNEL_BIT);
  2581. midiData[1] = v3event.note_off.pitch;
  2582. midiData[2] = carla_fixedValue<uint8_t>(0,
  2583. MAX_MIDI_VALUE - 1,
  2584. v3event.note_off.velocity * MAX_MIDI_VALUE);
  2585. midiSize = 3;
  2586. break;
  2587. case V3_EVENT_NOTE_ON:
  2588. midiData[0] = MIDI_STATUS_NOTE_ON | (v3event.note_on.channel & MIDI_CHANNEL_BIT);
  2589. midiData[1] = v3event.note_on.pitch;
  2590. midiData[2] = carla_fixedValue<uint8_t>(0,
  2591. MAX_MIDI_VALUE - 1,
  2592. v3event.note_on.velocity * MAX_MIDI_VALUE);
  2593. midiSize = 3;
  2594. break;
  2595. case V3_EVENT_POLY_PRESSURE:
  2596. midiData[0] = MIDI_STATUS_POLYPHONIC_AFTERTOUCH | (v3event.poly_pressure.channel & MIDI_CHANNEL_BIT);
  2597. midiData[1] = v3event.poly_pressure.pitch;
  2598. midiData[2] = carla_fixedValue<uint8_t>(0,
  2599. MAX_MIDI_VALUE - 1,
  2600. v3event.poly_pressure.pressure * MAX_MIDI_VALUE);
  2601. midiSize = 3;
  2602. break;
  2603. case V3_EVENT_LEGACY_MIDI_CC_OUT:
  2604. midiData[0] = MIDI_STATUS_CONTROL_CHANGE | (v3event.midi_cc_out.channel & MIDI_CHANNEL_BIT);
  2605. midiData[1] = v3event.midi_cc_out.cc_number;
  2606. midiData[2] = v3event.midi_cc_out.value;
  2607. midiSize = 3;
  2608. break;
  2609. default:
  2610. continue;
  2611. }
  2612. if (! pData->event.portOut->writeMidiEvent(static_cast<uint32_t>(v3event.sample_offset) + timeOffset,
  2613. midiSize,
  2614. midiData))
  2615. break;
  2616. minPortOutOffset = v3event.sample_offset;
  2617. }
  2618. }
  2619. // ------------------------------------------------------------------------------------------------------------
  2620. // Handle parameter outputs
  2621. if (fEvents.paramOutputs != nullptr && fEvents.paramOutputs->numParametersUsed != 0)
  2622. {
  2623. uint8_t channel;
  2624. uint16_t param;
  2625. for (uint32_t i=0; i < pData->param.count; ++i)
  2626. {
  2627. if (fEvents.paramOutputs->parametersUsed[i])
  2628. {
  2629. carla_v3_output_param_value_queue* const queue = fEvents.paramOutputs->queue[i];
  2630. const v3_param_id paramId = pData->param.data[i].rindex;
  2631. const float value = v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller,
  2632. paramId,
  2633. queue->value);
  2634. pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(i), value);
  2635. if (pData->param.data[i].type == PARAMETER_OUTPUT && pData->param.data[i].mappedControlIndex > 0)
  2636. {
  2637. channel = pData->param.data[i].midiChannel;
  2638. param = static_cast<uint16_t>(pData->param.data[i].mappedControlIndex);
  2639. pData->event.portOut->writeControlEvent(std::max(minPortOutOffset, queue->offset) + timeOffset,
  2640. channel,
  2641. kEngineControlEventTypeParameter,
  2642. param,
  2643. -1,
  2644. queue->value);
  2645. }
  2646. }
  2647. }
  2648. }
  2649. pData->postRtEvents.trySplice();
  2650. fEvents.init();
  2651. #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
  2652. // ------------------------------------------------------------------------------------------------------------
  2653. // Post-processing (dry/wet, volume and balance)
  2654. {
  2655. const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0
  2656. && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
  2657. const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0
  2658. && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f)
  2659. && carla_isEqual(pData->postProc.balanceRight, 1.0f));
  2660. const bool isMono = (pData->audioIn.count == 1);
  2661. bool isPair;
  2662. float bufValue;
  2663. float* const oldBufLeft = pData->postProc.extraBuffer;
  2664. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  2665. {
  2666. // Dry/Wet
  2667. if (doDryWet)
  2668. {
  2669. const uint32_t c = isMono ? 0 : i;
  2670. for (uint32_t k=0; k < frames; ++k)
  2671. {
  2672. bufValue = inBuffer[c][k+timeOffset];
  2673. fAudioAndCvOutBuffers[i][k] = (fAudioAndCvOutBuffers[i][k] * pData->postProc.dryWet)
  2674. + (bufValue * (1.0f - pData->postProc.dryWet));
  2675. }
  2676. }
  2677. // Balance
  2678. if (doBalance)
  2679. {
  2680. isPair = (i % 2 == 0);
  2681. if (isPair)
  2682. {
  2683. CARLA_ASSERT(i+1 < pData->audioOut.count);
  2684. carla_copyFloats(oldBufLeft, fAudioAndCvOutBuffers[i], frames);
  2685. }
  2686. float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
  2687. float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
  2688. for (uint32_t k=0; k < frames; ++k)
  2689. {
  2690. if (isPair)
  2691. {
  2692. // left
  2693. fAudioAndCvOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
  2694. fAudioAndCvOutBuffers[i][k] += fAudioAndCvOutBuffers[i+1][k] * (1.0f - balRangeR);
  2695. }
  2696. else
  2697. {
  2698. // right
  2699. fAudioAndCvOutBuffers[i][k] = fAudioAndCvOutBuffers[i][k] * balRangeR;
  2700. fAudioAndCvOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
  2701. }
  2702. }
  2703. }
  2704. // Volume (and buffer copy)
  2705. {
  2706. for (uint32_t k=0; k < frames; ++k)
  2707. outBuffer[i][k+timeOffset] = fAudioAndCvOutBuffers[i][k] * pData->postProc.volume;
  2708. }
  2709. }
  2710. for (uint32_t i=0, j=pData->audioOut.count; i < pData->cvOut.count; ++i, ++j)
  2711. carla_copyFloats(cvOut[i] + timeOffset, fAudioAndCvOutBuffers[j] + timeOffset, frames);
  2712. } // End of Post-processing
  2713. #else // BUILD_BRIDGE_ALTERNATIVE_ARCH
  2714. for (uint32_t i=0; i < pData->audioOut.count; ++i)
  2715. carla_copyFloats(outBuffer[i] + timeOffset, fAudioAndCvOutBuffers[i] + timeOffset, frames);
  2716. for (uint32_t i=0, j=pData->audioOut.count; i < pData->cvOut.count; ++i, ++j)
  2717. carla_copyFloats(cvOut[i] + timeOffset, fAudioAndCvOutBuffers[j] + timeOffset, frames);
  2718. #endif
  2719. // ------------------------------------------------------------------------------------------------------------
  2720. pData->singleMutex.unlock();
  2721. return true;
  2722. }
  2723. void bufferSizeChanged(const uint32_t newBufferSize) override
  2724. {
  2725. CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
  2726. carla_debug("CarlaPluginVST3::bufferSizeChanged(%i)", newBufferSize);
  2727. if (pData->active)
  2728. deactivate();
  2729. for (uint32_t i=0; i < pData->audioOut.count + pData->cvOut.count; ++i)
  2730. {
  2731. if (fAudioAndCvOutBuffers[i] != nullptr)
  2732. delete[] fAudioAndCvOutBuffers[i];
  2733. fAudioAndCvOutBuffers[i] = new float[newBufferSize];
  2734. }
  2735. v3_process_setup setup = {
  2736. pData->engine->isOffline() ? V3_OFFLINE : V3_REALTIME,
  2737. V3_SAMPLE_32,
  2738. static_cast<int32_t>(newBufferSize),
  2739. pData->engine->getSampleRate()
  2740. };
  2741. v3_cpp_obj(fV3.processor)->setup_processing(fV3.processor, &setup);
  2742. if (pData->active)
  2743. activate();
  2744. CarlaPlugin::bufferSizeChanged(newBufferSize);
  2745. }
  2746. void sampleRateChanged(const double newSampleRate) override
  2747. {
  2748. CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
  2749. carla_debug("CarlaPluginVST3::sampleRateChanged(%g)", newSampleRate);
  2750. if (pData->active)
  2751. deactivate();
  2752. v3_process_setup setup = {
  2753. pData->engine->isOffline() ? V3_OFFLINE : V3_REALTIME,
  2754. V3_SAMPLE_32,
  2755. static_cast<int32_t>(pData->engine->getBufferSize()),
  2756. newSampleRate
  2757. };
  2758. v3_cpp_obj(fV3.processor)->setup_processing(fV3.processor, &setup);
  2759. if (pData->active)
  2760. activate();
  2761. }
  2762. void offlineModeChanged(const bool isOffline) override
  2763. {
  2764. carla_debug("CarlaPluginVST3::offlineModeChanged(%d)", isOffline);
  2765. if (pData->active)
  2766. deactivate();
  2767. v3_process_setup setup = {
  2768. isOffline ? V3_OFFLINE : V3_REALTIME,
  2769. V3_SAMPLE_32,
  2770. static_cast<int32_t>(pData->engine->getBufferSize()),
  2771. pData->engine->getSampleRate()
  2772. };
  2773. v3_cpp_obj(fV3.processor)->setup_processing(fV3.processor, &setup);
  2774. if (pData->active)
  2775. activate();
  2776. }
  2777. // ----------------------------------------------------------------------------------------------------------------
  2778. // Plugin buffers
  2779. void clearBuffers() noexcept override
  2780. {
  2781. carla_debug("CarlaPluginVST3::clearBuffers() - start");
  2782. if (fAudioAndCvOutBuffers != nullptr)
  2783. {
  2784. for (uint32_t i=0; i < pData->audioOut.count + pData->cvOut.count; ++i)
  2785. {
  2786. if (fAudioAndCvOutBuffers[i] != nullptr)
  2787. {
  2788. delete[] fAudioAndCvOutBuffers[i];
  2789. fAudioAndCvOutBuffers[i] = nullptr;
  2790. }
  2791. }
  2792. delete[] fAudioAndCvOutBuffers;
  2793. fAudioAndCvOutBuffers = nullptr;
  2794. }
  2795. CarlaPlugin::clearBuffers();
  2796. carla_debug("CarlaPluginVST3::clearBuffers() - end");
  2797. }
  2798. // ----------------------------------------------------------------------------------------------------------------
  2799. // Post-poned UI Stuff
  2800. void uiParameterChange(const uint32_t index, const float value) noexcept override
  2801. {
  2802. CARLA_SAFE_ASSERT_RETURN(fV3.controller != nullptr,);
  2803. CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
  2804. const v3_param_id paramId = pData->param.data[index].rindex;
  2805. const double normalized = v3_cpp_obj(fV3.controller)->plain_parameter_to_normalised(fV3.controller,
  2806. paramId, value);
  2807. v3_cpp_obj(fV3.controller)->set_parameter_normalised(fV3.controller, paramId, normalized);
  2808. }
  2809. // ----------------------------------------------------------------------------------------------------------------
  2810. bool hasMidiInput() const noexcept
  2811. {
  2812. return pData->extraHints & PLUGIN_EXTRA_HINT_HAS_MIDI_IN ||
  2813. std::strstr(fV3ClassInfo.v2.sub_categories, "Instrument") != nullptr ||
  2814. v3_cpp_obj(fV3.component)->get_bus_count(fV3.component, V3_EVENT, V3_INPUT) > 0;
  2815. }
  2816. // ----------------------------------------------------------------------------------------------------------------
  2817. const void* getNativeDescriptor() const noexcept override
  2818. {
  2819. return fV3.component;
  2820. }
  2821. const void* getExtraStuff() const noexcept override
  2822. {
  2823. return fV3.controller;
  2824. }
  2825. // ----------------------------------------------------------------------------------------------------------------
  2826. bool init(const CarlaPluginPtr plugin,
  2827. const char* const filename,
  2828. const char* name,
  2829. const char* /*const label*/,
  2830. const uint options)
  2831. {
  2832. CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
  2833. // ------------------------------------------------------------------------------------------------------------
  2834. // first checks
  2835. if (pData->client != nullptr)
  2836. {
  2837. pData->engine->setLastError("Plugin client is already registered");
  2838. return false;
  2839. }
  2840. if (filename == nullptr || filename[0] == '\0')
  2841. {
  2842. pData->engine->setLastError("null filename");
  2843. return false;
  2844. }
  2845. V3_ENTRYFN v3_entry;
  2846. V3_EXITFN v3_exit;
  2847. V3_GETFN v3_get;
  2848. // filename is full path to binary
  2849. if (water::File(filename).existsAsFile())
  2850. {
  2851. if (! pData->libOpen(filename))
  2852. {
  2853. pData->engine->setLastError(pData->libError(filename));
  2854. return false;
  2855. }
  2856. v3_entry = pData->libSymbol<V3_ENTRYFN>(V3_ENTRYFNNAME);
  2857. v3_exit = pData->libSymbol<V3_EXITFN>(V3_EXITFNNAME);
  2858. v3_get = pData->libSymbol<V3_GETFN>(V3_GETFNNAME);
  2859. }
  2860. // assume filename is a vst3 bundle
  2861. else
  2862. {
  2863. #ifdef CARLA_OS_MAC
  2864. if (! fMacBundleLoader.load(filename))
  2865. {
  2866. pData->engine->setLastError("Failed to load VST3 bundle executable");
  2867. return false;
  2868. }
  2869. v3_entry = fMacBundleLoader.getSymbol<V3_ENTRYFN>(CFSTR(V3_ENTRYFNNAME));
  2870. v3_exit = fMacBundleLoader.getSymbol<V3_EXITFN>(CFSTR(V3_EXITFNNAME));
  2871. v3_get = fMacBundleLoader.getSymbol<V3_GETFN>(CFSTR(V3_GETFNNAME));
  2872. #else
  2873. water::String binaryfilename = filename;
  2874. if (!binaryfilename.endsWithChar(CARLA_OS_SEP))
  2875. binaryfilename += CARLA_OS_SEP_STR;
  2876. binaryfilename += "Contents" CARLA_OS_SEP_STR V3_CONTENT_DIR CARLA_OS_SEP_STR;
  2877. binaryfilename += water::File(filename).getFileNameWithoutExtension();
  2878. #ifdef CARLA_OS_WIN
  2879. binaryfilename += ".vst3";
  2880. #else
  2881. binaryfilename += ".so";
  2882. #endif
  2883. if (! water::File(binaryfilename.toRawUTF8()).existsAsFile())
  2884. {
  2885. pData->engine->setLastError("Failed to find a suitable VST3 bundle binary");
  2886. return false;
  2887. }
  2888. if (! pData->libOpen(binaryfilename.toRawUTF8()))
  2889. {
  2890. pData->engine->setLastError(pData->libError(binaryfilename.toRawUTF8()));
  2891. return false;
  2892. }
  2893. v3_entry = pData->libSymbol<V3_ENTRYFN>(V3_ENTRYFNNAME);
  2894. v3_exit = pData->libSymbol<V3_EXITFN>(V3_EXITFNNAME);
  2895. v3_get = pData->libSymbol<V3_GETFN>(V3_GETFNNAME);
  2896. #endif
  2897. }
  2898. // ------------------------------------------------------------------------------------------------------------
  2899. // ensure entry and exit points are available
  2900. if (v3_entry == nullptr || v3_exit == nullptr || v3_get == nullptr)
  2901. {
  2902. pData->engine->setLastError("Not a VST3 plugin");
  2903. return false;
  2904. }
  2905. // ------------------------------------------------------------------------------------------------------------
  2906. // call entry point
  2907. #if defined(CARLA_OS_MAC)
  2908. v3_entry(pData->lib == nullptr ? fMacBundleLoader.getRef() : nullptr);
  2909. #elif defined(CARLA_OS_WIN)
  2910. v3_entry();
  2911. #else
  2912. v3_entry(pData->lib);
  2913. #endif
  2914. // ------------------------------------------------------------------------------------------------------------
  2915. // fetch initial factory
  2916. v3_plugin_factory** const factory = v3_get();
  2917. if (factory == nullptr)
  2918. {
  2919. pData->engine->setLastError("VST3 factory failed to create a valid instance");
  2920. return false;
  2921. }
  2922. // ------------------------------------------------------------------------------------------------------------
  2923. // initialize and find requested plugin
  2924. fV3.exitfn = v3_exit;
  2925. fV3.factory1 = factory;
  2926. v3_funknown** const hostContext = (v3_funknown**)&fV3ApplicationPtr;
  2927. if (! fV3.queryFactories(hostContext))
  2928. {
  2929. pData->engine->setLastError("VST3 plugin failed to properly create factories");
  2930. return false;
  2931. }
  2932. if (! fV3.findPlugin(fV3ClassInfo))
  2933. {
  2934. pData->engine->setLastError("Failed to find the requested plugin in the VST3 bundle");
  2935. return false;
  2936. }
  2937. if (! fV3.initializePlugin(fV3ClassInfo.v1.class_id,
  2938. hostContext,
  2939. (v3_component_handler**)&fComponentHandlerPtr))
  2940. {
  2941. pData->engine->setLastError("VST3 plugin failed to initialize");
  2942. return false;
  2943. }
  2944. // ------------------------------------------------------------------------------------------------------------
  2945. // do some basic safety checks
  2946. if (v3_cpp_obj(fV3.processor)->can_process_sample_size(fV3.processor, V3_SAMPLE_32) != V3_OK)
  2947. {
  2948. pData->engine->setLastError("VST3 plugin does not support 32bit audio, cannot continue");
  2949. return false;
  2950. }
  2951. // ------------------------------------------------------------------------------------------------------------
  2952. // get info
  2953. if (name != nullptr && name[0] != '\0')
  2954. {
  2955. pData->name = pData->engine->getUniquePluginName(name);
  2956. }
  2957. else
  2958. {
  2959. if (fV3ClassInfo.v1.name[0] != '\0')
  2960. pData->name = pData->engine->getUniquePluginName(fV3ClassInfo.v1.name);
  2961. else if (const char* const shortname = std::strrchr(filename, CARLA_OS_SEP))
  2962. pData->name = pData->engine->getUniquePluginName(shortname+1);
  2963. else
  2964. pData->name = pData->engine->getUniquePluginName("unknown");
  2965. }
  2966. pData->filename = carla_strdup(filename);
  2967. // ------------------------------------------------------------------------------------------------------------
  2968. // register client
  2969. pData->client = pData->engine->addClient(plugin);
  2970. if (pData->client == nullptr || ! pData->client->isOk())
  2971. {
  2972. pData->engine->setLastError("Failed to register plugin client");
  2973. return false;
  2974. }
  2975. // ------------------------------------------------------------------------------------------------------------
  2976. // set default options
  2977. pData->options = 0x0;
  2978. if (fLastKnownLatency != 0 /*|| hasMidiOutput()*/ || isPluginOptionEnabled(options, PLUGIN_OPTION_FIXED_BUFFERS))
  2979. pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
  2980. if (isPluginOptionEnabled(options, PLUGIN_OPTION_USE_CHUNKS))
  2981. pData->options |= PLUGIN_OPTION_USE_CHUNKS;
  2982. if (hasMidiInput())
  2983. {
  2984. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
  2985. pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
  2986. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
  2987. pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
  2988. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
  2989. pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
  2990. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
  2991. pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
  2992. if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
  2993. pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
  2994. if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
  2995. pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
  2996. }
  2997. /*
  2998. if (numPrograms > 1 && isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
  2999. pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
  3000. */
  3001. // ------------------------------------------------------------------------------------------------------------
  3002. return true;
  3003. }
  3004. protected:
  3005. v3_result v3BeginEdit(const v3_param_id paramId) override
  3006. {
  3007. for (uint32_t i=0; i < pData->param.count; ++i)
  3008. {
  3009. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  3010. {
  3011. pData->engine->touchPluginParameter(pData->id, i, true);
  3012. return V3_OK;
  3013. }
  3014. }
  3015. return V3_INVALID_ARG;
  3016. }
  3017. v3_result v3PerformEdit(const v3_param_id paramId, const double value) override
  3018. {
  3019. CARLA_SAFE_ASSERT_RETURN(fEvents.paramInputs != nullptr, V3_INTERNAL_ERR);
  3020. for (uint32_t i=0; i < pData->param.count; ++i)
  3021. {
  3022. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  3023. {
  3024. // report value to component (next process call)
  3025. fEvents.paramInputs->setParamValue(i, static_cast<float>(value));
  3026. const double plain = v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller,
  3027. paramId,
  3028. value);
  3029. const float fixedValue = pData->param.getFixedValue(i, plain);
  3030. CarlaPlugin::setParameterValue(i, fixedValue, false, true, true);
  3031. return V3_OK;
  3032. }
  3033. }
  3034. return V3_INVALID_ARG;
  3035. }
  3036. v3_result v3EndEdit(const v3_param_id paramId) override
  3037. {
  3038. for (uint32_t i=0; i < pData->param.count; ++i)
  3039. {
  3040. if (static_cast<v3_param_id>(pData->param.data[i].rindex) == paramId)
  3041. {
  3042. pData->engine->touchPluginParameter(pData->id, i, false);
  3043. return V3_OK;
  3044. }
  3045. }
  3046. return V3_INVALID_ARG;
  3047. }
  3048. v3_result v3RestartComponent(const int32_t flags) override
  3049. {
  3050. fRestartFlags |= flags;
  3051. return V3_OK;
  3052. }
  3053. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3054. v3_result v3ResizeView(struct v3_plugin_view** const view, struct v3_view_rect* const rect) override
  3055. {
  3056. CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr, V3_INVALID_ARG);
  3057. CARLA_SAFE_ASSERT_RETURN(fV3.view == view, V3_INVALID_ARG);
  3058. const int32_t width = rect->right - rect->left;
  3059. const int32_t height = rect->bottom - rect->top;
  3060. CARLA_SAFE_ASSERT_INT_RETURN(width > 0, width, V3_INVALID_ARG);
  3061. CARLA_SAFE_ASSERT_INT_RETURN(height > 0, height, V3_INVALID_ARG);
  3062. carla_stdout("v3ResizeView %d %d", width, height);
  3063. fUI.isResizingFromPlugin = true;
  3064. fUI.width = width;
  3065. fUI.height = height;
  3066. if (fUI.isEmbed)
  3067. {
  3068. pData->engine->callback(true, true,
  3069. ENGINE_CALLBACK_EMBED_UI_RESIZED,
  3070. pData->id,
  3071. width, height,
  3072. 0, 0.0f, nullptr);
  3073. }
  3074. else
  3075. {
  3076. CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr, V3_NOT_INITIALIZED);
  3077. fUI.window->setSize(static_cast<uint>(width), static_cast<uint>(height), true, false);
  3078. }
  3079. return V3_OK;
  3080. }
  3081. void handlePluginUIClosed() override
  3082. {
  3083. // CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
  3084. carla_debug("CarlaPluginVST3::handlePluginUIClosed()");
  3085. fUI.isResizingFromHost = fUI.isResizingFromInit = false;
  3086. fUI.isResizingFromPlugin = false;
  3087. showCustomUI(false);
  3088. pData->engine->callback(true, true,
  3089. ENGINE_CALLBACK_UI_STATE_CHANGED,
  3090. pData->id,
  3091. 0,
  3092. 0, 0, 0.0f, nullptr);
  3093. }
  3094. void handlePluginUIResized(const uint width, const uint height) override
  3095. {
  3096. CARLA_SAFE_ASSERT_RETURN(fV3.view != nullptr,);
  3097. CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
  3098. carla_stdout("CarlaPluginVST3::handlePluginUIResized(%u, %u | vs %u %u) %s %s %s",
  3099. width, height,
  3100. fUI.width, fUI.height,
  3101. bool2str(fUI.isResizingFromPlugin),
  3102. bool2str(fUI.isResizingFromInit),
  3103. bool2str(fUI.isResizingFromHost));
  3104. if (fUI.isResizingFromInit)
  3105. {
  3106. CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.width == width, fUI.width, width,);
  3107. CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.height == height, fUI.height, height,);
  3108. fUI.isResizingFromInit = false;
  3109. return;
  3110. }
  3111. if (fUI.isResizingFromPlugin)
  3112. {
  3113. CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.width == width, fUI.width, width,);
  3114. CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.height == height, fUI.height, height,);
  3115. fUI.isResizingFromPlugin = false;
  3116. return;
  3117. }
  3118. if (fUI.isResizingFromHost)
  3119. {
  3120. CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.width == width, fUI.width, width,);
  3121. CARLA_SAFE_ASSERT_UINT2_RETURN(fUI.height == height, fUI.height, height,);
  3122. fUI.isResizingFromHost = false;
  3123. return;
  3124. }
  3125. if (fUI.width != width || fUI.height != height)
  3126. {
  3127. v3_view_rect rect = { 0, 0, static_cast<int32_t>(width), static_cast<int32_t>(height) };
  3128. if (v3_cpp_obj(fV3.view)->check_size_constraint(fV3.view, &rect) == V3_OK)
  3129. {
  3130. const uint width2 = rect.right - rect.left;
  3131. const uint height2 = rect.bottom - rect.top;
  3132. if (width2 != width || height2 != height)
  3133. {
  3134. fUI.isResizingFromHost = true;
  3135. fUI.width = width2;
  3136. fUI.height = height2;
  3137. fUI.window->setSize(width2, height2, true, false);
  3138. }
  3139. else
  3140. {
  3141. v3_cpp_obj(fV3.view)->on_size(fV3.view, &rect);
  3142. }
  3143. }
  3144. }
  3145. }
  3146. #endif // V3_VIEW_PLATFORM_TYPE_NATIVE
  3147. private:
  3148. #ifdef CARLA_OS_MAC
  3149. BundleLoader fMacBundleLoader;
  3150. #endif
  3151. const bool kEngineHasIdleOnMainThread;
  3152. bool fFirstActive; // first process() call after activate()
  3153. float** fAudioAndCvOutBuffers;
  3154. uint32_t fLastKnownLatency;
  3155. int32_t fRestartFlags;
  3156. void* fLastChunk;
  3157. EngineTimeInfo fLastTimeInfo;
  3158. v3_process_context fV3TimeContext;
  3159. carla_v3_host_application fV3Application;
  3160. carla_v3_host_application* const fV3ApplicationPtr;
  3161. carla_v3_component_handler fComponentHandler;
  3162. carla_v3_component_handler* const fComponentHandlerPtr;
  3163. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3164. carla_v3_plugin_frame fPluginFrame;
  3165. carla_v3_plugin_frame* const fPluginFramePtr;
  3166. #endif
  3167. // v3_class_info_2 is ABI compatible with v3_class_info
  3168. union ClassInfo {
  3169. v3_class_info v1;
  3170. v3_class_info_2 v2;
  3171. } fV3ClassInfo;
  3172. struct PluginPointers {
  3173. V3_EXITFN exitfn;
  3174. v3_plugin_factory** factory1;
  3175. v3_plugin_factory_2** factory2;
  3176. v3_plugin_factory_3** factory3;
  3177. v3_component** component;
  3178. v3_edit_controller** controller;
  3179. v3_audio_processor** processor;
  3180. v3_connection_point** connComponent;
  3181. v3_connection_point** connController;
  3182. v3_midi_mapping** midiMapping;
  3183. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3184. v3_plugin_view** view;
  3185. #endif
  3186. bool shouldTerminateComponent;
  3187. bool shouldTerminateController;
  3188. PluginPointers()
  3189. : exitfn(nullptr),
  3190. factory1(nullptr),
  3191. factory2(nullptr),
  3192. factory3(nullptr),
  3193. component(nullptr),
  3194. controller(nullptr),
  3195. processor(nullptr),
  3196. connComponent(nullptr),
  3197. connController(nullptr),
  3198. midiMapping(nullptr),
  3199. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3200. view(nullptr),
  3201. #endif
  3202. shouldTerminateComponent(false),
  3203. shouldTerminateController(false) {}
  3204. ~PluginPointers()
  3205. {
  3206. // must have been cleaned up by now
  3207. CARLA_SAFE_ASSERT(exitfn == nullptr);
  3208. }
  3209. // must have exitfn and factory1 set
  3210. bool queryFactories(v3_funknown** const hostContext)
  3211. {
  3212. // query 2nd factory
  3213. if (v3_cpp_obj_query_interface(factory1, v3_plugin_factory_2_iid, &factory2) == V3_OK)
  3214. {
  3215. CARLA_SAFE_ASSERT_RETURN(factory2 != nullptr, exit());
  3216. }
  3217. else
  3218. {
  3219. CARLA_SAFE_ASSERT(factory2 == nullptr);
  3220. factory2 = nullptr;
  3221. }
  3222. // query 3rd factory
  3223. if (factory2 != nullptr && v3_cpp_obj_query_interface(factory2, v3_plugin_factory_3_iid, &factory3) == V3_OK)
  3224. {
  3225. CARLA_SAFE_ASSERT_RETURN(factory3 != nullptr, exit());
  3226. }
  3227. else
  3228. {
  3229. CARLA_SAFE_ASSERT(factory3 == nullptr);
  3230. factory3 = nullptr;
  3231. }
  3232. // set host context (application) if 3rd factory provided
  3233. if (factory3 != nullptr)
  3234. v3_cpp_obj(factory3)->set_host_context(factory3, hostContext);
  3235. return true;
  3236. }
  3237. // must have all possible factories and exitfn set
  3238. bool findPlugin(ClassInfo& classInfo)
  3239. {
  3240. // get factory info
  3241. v3_factory_info factoryInfo = {};
  3242. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(factory1)->get_factory_info(factory1, &factoryInfo) == V3_OK, exit());
  3243. // get num classes
  3244. const int32_t numClasses = v3_cpp_obj(factory1)->num_classes(factory1);
  3245. CARLA_SAFE_ASSERT_RETURN(numClasses > 0, exit());
  3246. // go through all relevant classes
  3247. for (int32_t i=0; i<numClasses; ++i)
  3248. {
  3249. carla_zeroStruct(classInfo);
  3250. if (factory2 != nullptr)
  3251. v3_cpp_obj(factory2)->get_class_info_2(factory2, i, &classInfo.v2);
  3252. else
  3253. v3_cpp_obj(factory1)->get_class_info(factory1, i, &classInfo.v1);
  3254. // safety check
  3255. CARLA_SAFE_ASSERT_CONTINUE(classInfo.v1.cardinality == 0x7FFFFFFF);
  3256. // only check for audio plugins
  3257. if (std::strcmp(classInfo.v1.category, "Audio Module Class") != 0)
  3258. continue;
  3259. // FIXME multi-plugin bundle
  3260. break;
  3261. }
  3262. return true;
  3263. }
  3264. bool initializePlugin(const v3_tuid uid,
  3265. v3_funknown** const hostContext,
  3266. v3_component_handler** const handler)
  3267. {
  3268. // create instance
  3269. void* instance = nullptr;
  3270. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(factory1)->create_instance(factory1, uid, v3_component_iid,
  3271. &instance) == V3_OK,
  3272. exit());
  3273. CARLA_SAFE_ASSERT_RETURN(instance != nullptr, exit());
  3274. component = static_cast<v3_component**>(instance);
  3275. // initialize instance
  3276. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj_initialize(component, hostContext) == V3_OK, exit());
  3277. shouldTerminateComponent = true;
  3278. // create edit controller
  3279. if (v3_cpp_obj_query_interface(component, v3_edit_controller_iid, &controller) != V3_OK)
  3280. controller = nullptr;
  3281. // if we cannot cast from component, try to create edit controller from factory
  3282. if (controller == nullptr)
  3283. {
  3284. v3_tuid cuid = {};
  3285. if (v3_cpp_obj(component)->get_controller_class_id(component, cuid) == V3_OK)
  3286. {
  3287. instance = nullptr;
  3288. if (v3_cpp_obj(factory1)->create_instance(factory1, cuid,
  3289. v3_edit_controller_iid, &instance) == V3_OK)
  3290. controller = static_cast<v3_edit_controller**>(instance);
  3291. }
  3292. CARLA_SAFE_ASSERT_RETURN(controller != nullptr, exit());
  3293. // component is separate from controller, needs its dedicated initialize and terminate
  3294. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj_initialize(controller, hostContext) == V3_OK, exit());
  3295. shouldTerminateController = true;
  3296. }
  3297. v3_cpp_obj(controller)->set_component_handler(controller, handler);
  3298. // create processor
  3299. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj_query_interface(component, v3_audio_processor_iid,
  3300. &processor) == V3_OK, exit());
  3301. CARLA_SAFE_ASSERT_RETURN(processor != nullptr, exit());
  3302. // connect component to controller
  3303. if (v3_cpp_obj_query_interface(component, v3_connection_point_iid, &connComponent) != V3_OK)
  3304. connComponent = nullptr;
  3305. if (v3_cpp_obj_query_interface(controller, v3_connection_point_iid, &connController) != V3_OK)
  3306. connController = nullptr;
  3307. if (connComponent != nullptr && connController != nullptr)
  3308. {
  3309. v3_cpp_obj(connComponent)->connect(connComponent, connController);
  3310. v3_cpp_obj(connController)->connect(connController, connComponent);
  3311. }
  3312. // get midi mapping interface
  3313. if (v3_cpp_obj_query_interface(component, v3_midi_mapping_iid, &midiMapping) != V3_OK)
  3314. {
  3315. midiMapping = nullptr;
  3316. if (v3_cpp_obj_query_interface(controller, v3_midi_mapping_iid, &midiMapping) != V3_OK)
  3317. midiMapping = nullptr;
  3318. }
  3319. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3320. // create view
  3321. view = v3_cpp_obj(controller)->create_view(controller, "editor");
  3322. #endif
  3323. return true;
  3324. }
  3325. bool exit()
  3326. {
  3327. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3328. // must be deleted by now
  3329. CARLA_SAFE_ASSERT(view == nullptr);
  3330. #endif
  3331. if (midiMapping != nullptr)
  3332. {
  3333. v3_cpp_obj_unref(midiMapping);
  3334. midiMapping = nullptr;
  3335. }
  3336. if (connComponent != nullptr && connController != nullptr)
  3337. {
  3338. v3_cpp_obj(connComponent)->disconnect(connComponent, connController);
  3339. v3_cpp_obj(connController)->disconnect(connController, connComponent);
  3340. }
  3341. if (connComponent != nullptr)
  3342. {
  3343. v3_cpp_obj_unref(connComponent);
  3344. connComponent = nullptr;
  3345. }
  3346. if (connController != nullptr)
  3347. {
  3348. v3_cpp_obj_unref(connController);
  3349. connController = nullptr;
  3350. }
  3351. if (processor != nullptr)
  3352. {
  3353. v3_cpp_obj_unref(processor);
  3354. processor = nullptr;
  3355. }
  3356. if (controller != nullptr)
  3357. {
  3358. if (shouldTerminateController)
  3359. {
  3360. v3_cpp_obj_terminate(controller);
  3361. shouldTerminateController = false;
  3362. }
  3363. v3_cpp_obj_unref(controller);
  3364. controller = nullptr;
  3365. }
  3366. if (component != nullptr)
  3367. {
  3368. if (shouldTerminateComponent)
  3369. {
  3370. v3_cpp_obj_terminate(component);
  3371. shouldTerminateComponent = false;
  3372. }
  3373. v3_cpp_obj_unref(component);
  3374. component = nullptr;
  3375. }
  3376. if (factory3 != nullptr)
  3377. {
  3378. v3_cpp_obj_unref(factory3);
  3379. factory3 = nullptr;
  3380. }
  3381. if (factory2 != nullptr)
  3382. {
  3383. v3_cpp_obj_unref(factory2);
  3384. factory2 = nullptr;
  3385. }
  3386. if (factory1 != nullptr)
  3387. {
  3388. v3_cpp_obj_unref(factory1);
  3389. factory1 = nullptr;
  3390. }
  3391. if (exitfn != nullptr)
  3392. {
  3393. exitfn();
  3394. exitfn = nullptr;
  3395. }
  3396. // return false so it can be used as error/fail condition
  3397. return false;
  3398. }
  3399. CARLA_DECLARE_NON_COPYABLE(PluginPointers)
  3400. } fV3;
  3401. struct Buses {
  3402. int32_t numInputs;
  3403. int32_t numOutputs;
  3404. v3_audio_bus_buffers* inputs;
  3405. v3_audio_bus_buffers* outputs;
  3406. v3_bus_mini_info* inputInfo;
  3407. v3_bus_mini_info* outputInfo;
  3408. Buses()
  3409. : numInputs(0),
  3410. numOutputs(0),
  3411. inputs(nullptr),
  3412. outputs(nullptr),
  3413. inputInfo(nullptr),
  3414. outputInfo(nullptr) {}
  3415. ~Buses()
  3416. {
  3417. delete[] inputs;
  3418. delete[] outputs;
  3419. delete[] inputInfo;
  3420. delete[] outputInfo;
  3421. }
  3422. void createNew(const int32_t numAudioInputBuses, const int32_t numAudioOutputBuses)
  3423. {
  3424. delete[] inputs;
  3425. delete[] outputs;
  3426. delete[] inputInfo;
  3427. delete[] outputInfo;
  3428. numInputs = numAudioInputBuses;
  3429. numOutputs = numAudioOutputBuses;
  3430. if (numAudioInputBuses > 0)
  3431. {
  3432. inputs = new v3_audio_bus_buffers[numAudioInputBuses];
  3433. inputInfo = new v3_bus_mini_info[numAudioInputBuses];
  3434. }
  3435. else
  3436. {
  3437. inputs = nullptr;
  3438. inputInfo = nullptr;
  3439. }
  3440. if (numAudioOutputBuses > 0)
  3441. {
  3442. outputs = new v3_audio_bus_buffers[numAudioOutputBuses];
  3443. outputInfo = new v3_bus_mini_info[numAudioOutputBuses];
  3444. }
  3445. else
  3446. {
  3447. outputs = nullptr;
  3448. outputInfo = nullptr;
  3449. }
  3450. }
  3451. CARLA_DECLARE_NON_COPYABLE(Buses)
  3452. } fBuses;
  3453. struct Events {
  3454. carla_v3_input_param_changes* paramInputs;
  3455. carla_v3_output_param_changes* paramOutputs;
  3456. carla_v3_input_event_list* eventInputs;
  3457. carla_v3_output_event_list* eventOutputs;
  3458. Events() noexcept
  3459. : paramInputs(nullptr),
  3460. paramOutputs(nullptr),
  3461. eventInputs(nullptr),
  3462. eventOutputs(nullptr) {}
  3463. ~Events()
  3464. {
  3465. delete paramInputs;
  3466. delete paramOutputs;
  3467. delete eventInputs;
  3468. delete eventOutputs;
  3469. }
  3470. void init()
  3471. {
  3472. if (paramInputs != nullptr)
  3473. paramInputs->init();
  3474. if (eventInputs != nullptr)
  3475. eventInputs->numEvents = 0;
  3476. if (eventOutputs != nullptr)
  3477. eventOutputs->numEvents = 0;
  3478. }
  3479. void prepare()
  3480. {
  3481. if (paramInputs != nullptr)
  3482. paramInputs->prepare();
  3483. if (paramOutputs != nullptr)
  3484. paramOutputs->prepare();
  3485. }
  3486. CARLA_DECLARE_NON_COPYABLE(Events)
  3487. } fEvents;
  3488. struct MidiControllerAssignments {
  3489. v3_param_id* mappings;
  3490. bool* used;
  3491. MidiControllerAssignments() noexcept
  3492. : mappings(nullptr),
  3493. used(nullptr) {}
  3494. ~MidiControllerAssignments() noexcept
  3495. {
  3496. clear();
  3497. }
  3498. void init(v3_midi_mapping** const midiMapping, const uint32_t numPorts)
  3499. {
  3500. clear();
  3501. if (numPorts == 0)
  3502. return;
  3503. const uint32_t dataPoints = numPorts * MAX_MIDI_CHANNELS * 130;
  3504. mappings = new v3_param_id[dataPoints];
  3505. used = new bool[dataPoints];
  3506. carla_zeroStructs(mappings, dataPoints);
  3507. carla_zeroStructs(used, dataPoints);
  3508. v3_param_id paramId;
  3509. for (uint32_t p=0; p<numPorts; ++p)
  3510. {
  3511. for (uint8_t ch=0; ch<MAX_MIDI_CHANNELS; ++ch)
  3512. {
  3513. for (uint16_t cc=0; cc<130; ++cc)
  3514. {
  3515. if (v3_cpp_obj(midiMapping)->get_midi_controller_assignment(midiMapping, p,
  3516. ch, cc, &paramId) == V3_OK)
  3517. {
  3518. const uint32_t index = p * (130 + MAX_MIDI_CHANNELS) + cc * MAX_MIDI_CHANNELS + ch;
  3519. mappings[index] = paramId;
  3520. used[index] = true;
  3521. }
  3522. }
  3523. }
  3524. }
  3525. }
  3526. void clear() noexcept
  3527. {
  3528. delete[] mappings;
  3529. delete[] used;
  3530. mappings = nullptr;
  3531. used = nullptr;
  3532. }
  3533. bool get(const uint8_t port, const uint8_t channel, const uint8_t cc, v3_param_id& paramId) noexcept
  3534. {
  3535. CARLA_SAFE_ASSERT_UINT_RETURN(channel < MAX_MIDI_CHANNELS, channel, false);
  3536. CARLA_SAFE_ASSERT_UINT_RETURN(cc < 130, cc, false);
  3537. if (used == nullptr)
  3538. return false;
  3539. const uint32_t index = port * (130 + MAX_MIDI_CHANNELS) + cc * MAX_MIDI_CHANNELS + channel;
  3540. if (used[index])
  3541. {
  3542. paramId = mappings[index];
  3543. return true;
  3544. }
  3545. return false;
  3546. }
  3547. } fMidiControllerAssignments;
  3548. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  3549. struct UI {
  3550. bool isAttached;
  3551. bool isEmbed;
  3552. bool isResizingFromHost;
  3553. bool isResizingFromInit;
  3554. bool isResizingFromPlugin;
  3555. bool isVisible;
  3556. uint32_t width, height;
  3557. CarlaPluginUI* window;
  3558. UI() noexcept
  3559. : isAttached(false),
  3560. isEmbed(false),
  3561. isResizingFromHost(false),
  3562. isResizingFromInit(false),
  3563. isResizingFromPlugin(false),
  3564. isVisible(false),
  3565. width(0),
  3566. height(0),
  3567. window(nullptr) {}
  3568. ~UI()
  3569. {
  3570. CARLA_ASSERT(isEmbed || ! isVisible);
  3571. if (window != nullptr)
  3572. {
  3573. delete window;
  3574. window = nullptr;
  3575. }
  3576. }
  3577. CARLA_DECLARE_NON_COPYABLE(UI)
  3578. } fUI;
  3579. #endif
  3580. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginVST3)
  3581. };
  3582. // --------------------------------------------------------------------------------------------------------------------
  3583. CarlaPluginPtr CarlaPlugin::newVST3(const Initializer& init)
  3584. {
  3585. carla_debug("CarlaPlugin::newVST3({%p, \"%s\", \"%s\", \"%s\"})",
  3586. init.engine, init.filename, init.name, init.label);
  3587. std::shared_ptr<CarlaPluginVST3> plugin(new CarlaPluginVST3(init.engine, init.id));
  3588. if (! plugin->init(plugin, init.filename, init.name, init.label, init.options))
  3589. return nullptr;
  3590. return plugin;
  3591. }
  3592. // -------------------------------------------------------------------------------------------------------------------
  3593. CARLA_BACKEND_END_NAMESPACE