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.

CarlaNative.hpp 19KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. /*
  2. * Carla Native Plugin API (C++)
  3. * Copyright (C) 2012-2023 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_NATIVE_HPP_INCLUDED
  18. #define CARLA_NATIVE_HPP_INCLUDED
  19. #include "CarlaNative.h"
  20. #include "CarlaMIDI.h"
  21. #include "CarlaJuceUtils.hpp"
  22. /*!
  23. * @defgroup CarlaNativeAPI Carla Native API
  24. * @{
  25. */
  26. // --------------------------------------------------------------------------------------------------------------------
  27. // Native Plugin Class
  28. class NativePluginClass
  29. {
  30. public:
  31. NativePluginClass(const NativeHostDescriptor* const host)
  32. : pHost(host)
  33. {
  34. CARLA_SAFE_ASSERT(host != nullptr);
  35. }
  36. virtual ~NativePluginClass() {}
  37. protected:
  38. // -------------------------------------------------------------------
  39. // Host calls
  40. const NativeHostDescriptor* getHostHandle() const noexcept
  41. {
  42. return pHost;
  43. }
  44. const char* getResourceDir() const noexcept
  45. {
  46. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  47. return pHost->resourceDir;
  48. }
  49. const char* getUiName() const noexcept
  50. {
  51. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  52. return pHost->uiName;
  53. }
  54. uintptr_t getUiParentId() const noexcept
  55. {
  56. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  57. return pHost->uiParentId;
  58. }
  59. uint32_t getBufferSize() const
  60. {
  61. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  62. return pHost->get_buffer_size(pHost->handle);
  63. }
  64. double getSampleRate() const
  65. {
  66. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0.0);
  67. return pHost->get_sample_rate(pHost->handle);
  68. }
  69. bool isOffline() const
  70. {
  71. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, false);
  72. return pHost->is_offline(pHost->handle);
  73. }
  74. const NativeTimeInfo* getTimeInfo() const
  75. {
  76. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  77. return pHost->get_time_info(pHost->handle);
  78. }
  79. void writeMidiEvent(const NativeMidiEvent* const event) const
  80. {
  81. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  82. pHost->write_midi_event(pHost->handle, event);
  83. }
  84. void uiParameterChanged(const uint32_t index, const float value) const
  85. {
  86. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  87. pHost->ui_parameter_changed(pHost->handle, index, value);
  88. }
  89. void uiParameterTouch(const uint32_t index, const bool touch) const
  90. {
  91. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  92. pHost->dispatcher(pHost->handle,
  93. NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER,
  94. static_cast<int32_t>(index),
  95. touch ? 1 : 0,
  96. nullptr, 0.0f);
  97. }
  98. void uiMidiProgramChanged(const uint8_t channel, const uint32_t bank, const uint32_t program) const
  99. {
  100. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  101. pHost->ui_midi_program_changed(pHost->handle, channel, bank, program);
  102. }
  103. void uiCustomDataChanged(const char* const key, const char* const value) const
  104. {
  105. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  106. pHost->ui_custom_data_changed(pHost->handle, key, value);
  107. }
  108. void uiClosed() const
  109. {
  110. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  111. pHost->ui_closed(pHost->handle);
  112. }
  113. const char* uiOpenFile(const bool isDir, const char* const title, const char* const filter) const
  114. {
  115. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  116. return pHost->ui_open_file(pHost->handle, isDir, title, filter);
  117. }
  118. const char* uiSaveFile(const bool isDir, const char* const title, const char* const filter) const
  119. {
  120. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  121. return pHost->ui_save_file(pHost->handle, isDir, title, filter);
  122. }
  123. // -------------------------------------------------------------------
  124. // Host dispatcher calls
  125. void hostUpdateParameter(const int32_t index) const
  126. {
  127. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  128. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_PARAMETER, index, 0, nullptr, 0.0f);
  129. }
  130. void hostUpdateAllParameters() const
  131. {
  132. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  133. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_PARAMETER, -1, 0, nullptr, 0.0f);
  134. }
  135. void hostUpdateMidiProgram(const int32_t index, const intptr_t channel = 0) const
  136. {
  137. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  138. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM, index, channel, nullptr, 0.0f);
  139. }
  140. void hostUpdateAllMidiPrograms(const intptr_t channel = 0) const
  141. {
  142. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  143. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM, -1, channel, nullptr, 0.0f);
  144. }
  145. void hostReloadParameters() const
  146. {
  147. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  148. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_PARAMETERS, 0, 0, nullptr, 0.0f);
  149. }
  150. void hostReloadMidiPrograms() const
  151. {
  152. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  153. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS, 0, 0, nullptr, 0.0f);
  154. }
  155. void hostReloadAll() const
  156. {
  157. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  158. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_RELOAD_ALL, 0, 0, nullptr, 0.0f);
  159. }
  160. void hostUiUnavailable() const
  161. {
  162. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  163. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  164. }
  165. void hostGiveIdle() const
  166. {
  167. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  168. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f);
  169. }
  170. bool hostRequestIdle() const
  171. {
  172. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  173. return pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_REQUEST_IDLE, 0, 0, nullptr, 0.0f) == 1;
  174. }
  175. bool hostQueueDrawInlineDisplay()
  176. {
  177. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  178. return pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY, 0, 0, nullptr, 0.0f) == 1;
  179. }
  180. const char* hostGetFilePath(const char* const filetype) const
  181. {
  182. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  183. return (const char*)(uintptr_t)pHost->dispatcher(pHost->handle,
  184. NATIVE_HOST_OPCODE_GET_FILE_PATH,
  185. 0, 0,
  186. (void*)const_cast<char*>(filetype),
  187. 0.0f);
  188. }
  189. void hostSendPreviewBufferData(const char type, const uint32_t size, const void* const buffer)
  190. {
  191. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  192. pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_PREVIEW_BUFFER_DATA, type, size, const_cast<void*>(buffer), 0.0f);
  193. }
  194. // -------------------------------------------------------------------
  195. // Plugin parameter calls
  196. virtual uint32_t getParameterCount() const
  197. {
  198. return 0;
  199. }
  200. virtual const NativeParameter* getParameterInfo(const uint32_t index) const
  201. {
  202. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
  203. return nullptr;
  204. }
  205. virtual float getParameterValue(const uint32_t index) const
  206. {
  207. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
  208. return 0.0f;
  209. }
  210. // -------------------------------------------------------------------
  211. // Plugin midi-program calls
  212. virtual uint32_t getMidiProgramCount() const
  213. {
  214. return 0;
  215. }
  216. virtual const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
  217. {
  218. CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
  219. return nullptr;
  220. }
  221. // -------------------------------------------------------------------
  222. // Plugin state calls
  223. virtual void setParameterValue(const uint32_t index, const float value)
  224. {
  225. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  226. return;
  227. // unused
  228. (void)value;
  229. }
  230. virtual void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
  231. {
  232. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  233. return;
  234. // unused
  235. (void)bank; (void)program;
  236. }
  237. virtual void setCustomData(const char* const key, const char* const value)
  238. {
  239. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  240. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  241. }
  242. // -------------------------------------------------------------------
  243. // Plugin process calls
  244. virtual void activate() {}
  245. virtual void deactivate() {}
  246. virtual void process(const float* const* inBuffer, float** outBuffer, uint32_t frames,
  247. const NativeMidiEvent* midiEvents, uint32_t midiEventCount) = 0;
  248. // -------------------------------------------------------------------
  249. // Plugin UI calls
  250. virtual void uiShow(const bool show)
  251. {
  252. return;
  253. // unused
  254. (void)show;
  255. }
  256. virtual void uiIdle()
  257. {
  258. }
  259. virtual void uiSetParameterValue(const uint32_t index, const float value)
  260. {
  261. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  262. return;
  263. // unused
  264. (void)value;
  265. }
  266. virtual void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
  267. {
  268. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  269. return;
  270. // unused
  271. (void)bank; (void)program;
  272. }
  273. virtual void uiSetCustomData(const char* const key, const char* const value)
  274. {
  275. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  276. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  277. }
  278. // -------------------------------------------------------------------
  279. // Plugin state calls
  280. virtual char* getState() const
  281. {
  282. return nullptr;
  283. }
  284. virtual void setState(const char* const data)
  285. {
  286. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  287. }
  288. // -------------------------------------------------------------------
  289. // Plugin dispatcher calls
  290. virtual void bufferSizeChanged(const uint32_t bufferSize)
  291. {
  292. return;
  293. // unused
  294. (void)bufferSize;
  295. }
  296. virtual void sampleRateChanged(const double sampleRate)
  297. {
  298. return;
  299. // unused
  300. (void)sampleRate;
  301. }
  302. virtual void offlineChanged(const bool offline)
  303. {
  304. return;
  305. // unused
  306. (void)offline;
  307. }
  308. virtual void uiNameChanged(const char* const uiName)
  309. {
  310. CARLA_SAFE_ASSERT_RETURN(uiName != nullptr && uiName[0] != '\0',);
  311. }
  312. virtual bool uiMIDIEvent(uint8_t size, const uint8_t data[])
  313. {
  314. return false;
  315. // unused
  316. (void)size;
  317. (void)data;
  318. }
  319. virtual const NativeInlineDisplayImageSurface* renderInlineDisplay(const uint32_t width, const uint32_t height)
  320. {
  321. CARLA_SAFE_ASSERT_RETURN(width > 0 && height > 0, nullptr);
  322. return nullptr;
  323. }
  324. virtual void idle() {}
  325. // -------------------------------------------------------------------
  326. private:
  327. const NativeHostDescriptor* const pHost;
  328. // -------------------------------------------------------------------
  329. #ifndef DOXYGEN
  330. public:
  331. #define handlePtr ((NativePluginClass*)handle)
  332. static uint32_t _get_parameter_count(NativePluginHandle handle)
  333. {
  334. return handlePtr->getParameterCount();
  335. }
  336. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  337. {
  338. return handlePtr->getParameterInfo(index);
  339. }
  340. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  341. {
  342. return handlePtr->getParameterValue(index);
  343. }
  344. static uint32_t _get_midi_program_count(NativePluginHandle handle)
  345. {
  346. return handlePtr->getMidiProgramCount();
  347. }
  348. static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
  349. {
  350. return handlePtr->getMidiProgramInfo(index);
  351. }
  352. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  353. {
  354. handlePtr->setParameterValue(index, value);
  355. }
  356. static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  357. {
  358. handlePtr->setMidiProgram(channel, bank, program);
  359. }
  360. static void _set_custom_data(NativePluginHandle handle, const char* key, const char* value)
  361. {
  362. handlePtr->setCustomData(key, value);
  363. }
  364. static void _ui_show(NativePluginHandle handle, bool show)
  365. {
  366. handlePtr->uiShow(show);
  367. }
  368. static void _ui_idle(NativePluginHandle handle)
  369. {
  370. handlePtr->uiIdle();
  371. }
  372. static void _ui_set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  373. {
  374. handlePtr->uiSetParameterValue(index, value);
  375. }
  376. static void _ui_set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  377. {
  378. handlePtr->uiSetMidiProgram(channel, bank, program);
  379. }
  380. static void _ui_set_custom_data(NativePluginHandle handle, const char* key, const char* value)
  381. {
  382. handlePtr->uiSetCustomData(key, value);
  383. }
  384. static void _activate(NativePluginHandle handle)
  385. {
  386. handlePtr->activate();
  387. }
  388. static void _deactivate(NativePluginHandle handle)
  389. {
  390. handlePtr->deactivate();
  391. }
  392. // FIXME for v3.0, use const for the input buffer
  393. static void _process(NativePluginHandle handle,
  394. float** inBuffer, float** outBuffer, const uint32_t frames,
  395. const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  396. {
  397. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  398. }
  399. static char* _get_state(NativePluginHandle handle)
  400. {
  401. return handlePtr->getState();
  402. }
  403. static void _set_state(NativePluginHandle handle, const char* data)
  404. {
  405. handlePtr->setState(data);
  406. }
  407. static intptr_t _dispatcher(NativePluginHandle handle,
  408. NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  409. {
  410. switch(opcode)
  411. {
  412. case NATIVE_PLUGIN_OPCODE_NULL:
  413. return 0;
  414. case NATIVE_PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  415. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  416. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  417. return 0;
  418. case NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  419. CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0);
  420. handlePtr->sampleRateChanged(static_cast<double>(opt));
  421. return 0;
  422. case NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED:
  423. handlePtr->offlineChanged(value != 0);
  424. return 0;
  425. case NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED:
  426. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
  427. handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  428. return 0;
  429. case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE:
  430. return 0;
  431. case NATIVE_PLUGIN_OPCODE_IDLE:
  432. handlePtr->idle();
  433. return 0;
  434. case NATIVE_PLUGIN_OPCODE_UI_MIDI_EVENT:
  435. CARLA_SAFE_ASSERT_RETURN(index >= 0 && index < UINT8_MAX, 0);
  436. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
  437. return handlePtr->uiMIDIEvent(static_cast<uint8_t>(index),
  438. static_cast<uint8_t*>(ptr));
  439. case NATIVE_PLUGIN_OPCODE_HOST_USES_EMBED:
  440. case NATIVE_PLUGIN_OPCODE_HOST_OPTION:
  441. return 0;
  442. }
  443. return 0;
  444. // unused
  445. (void)index;
  446. }
  447. static const NativeInlineDisplayImageSurface* _render_inline_display(NativePluginHandle handle, uint32_t width, uint32_t height)
  448. {
  449. return handlePtr->renderInlineDisplay(width, height);
  450. }
  451. #undef handlePtr
  452. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginClass)
  453. #endif
  454. };
  455. /**@}*/
  456. // --------------------------------------------------------------------------------------------------------------------
  457. // -Weffc++ compat ext widget
  458. extern "C" {
  459. typedef struct _NativeInlineDisplayImageSurfaceCompat {
  460. unsigned char* data;
  461. int width, height, stride;
  462. size_t dataSize;
  463. _NativeInlineDisplayImageSurfaceCompat() noexcept
  464. : data(nullptr), width(0), height(0), stride(0), dataSize(0) {}
  465. } NativeInlineDisplayImageSurfaceCompat;
  466. }
  467. // --------------------------------------------------------------------------------------------------------------------
  468. #define PluginClassEND(ClassName) \
  469. public: \
  470. static NativePluginHandle _instantiate(const NativeHostDescriptor* host) \
  471. { \
  472. return (host != nullptr) ? new ClassName(host) : nullptr; \
  473. } \
  474. static void _cleanup(NativePluginHandle handle) \
  475. { \
  476. delete (ClassName*)handle; \
  477. }
  478. #define PluginDescriptorFILL(ClassName) \
  479. ClassName::_instantiate, \
  480. ClassName::_cleanup, \
  481. ClassName::_get_parameter_count, \
  482. ClassName::_get_parameter_info, \
  483. ClassName::_get_parameter_value, \
  484. ClassName::_get_midi_program_count, \
  485. ClassName::_get_midi_program_info, \
  486. ClassName::_set_parameter_value, \
  487. ClassName::_set_midi_program, \
  488. ClassName::_set_custom_data, \
  489. ClassName::_ui_show, \
  490. ClassName::_ui_idle, \
  491. ClassName::_ui_set_parameter_value, \
  492. ClassName::_ui_set_midi_program, \
  493. ClassName::_ui_set_custom_data, \
  494. ClassName::_activate, \
  495. ClassName::_deactivate, \
  496. ClassName::_process, \
  497. ClassName::_get_state, \
  498. ClassName::_set_state, \
  499. ClassName::_dispatcher, \
  500. ClassName::_render_inline_display, \
  501. 0, 0, nullptr, nullptr, 0, 0
  502. // --------------------------------------------------------------------------------------------------------------------
  503. #endif // CARLA_NATIVE_HPP_INCLUDED