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.

564 lines
16KB

  1. /*
  2. * Carla Native Plugin API (C++)
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #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. {
  38. }
  39. protected:
  40. // -------------------------------------------------------------------
  41. // Host calls
  42. const NativeHostDescriptor* getHostHandle() const noexcept
  43. {
  44. return pHost;
  45. }
  46. const char* getResourceDir() const noexcept
  47. {
  48. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  49. return pHost->resourceDir;
  50. }
  51. const char* getUiName() const noexcept
  52. {
  53. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  54. return pHost->uiName;
  55. }
  56. uintptr_t getUiParentId() const noexcept
  57. {
  58. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  59. return pHost->uiParentId;
  60. }
  61. uint32_t getBufferSize() const
  62. {
  63. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  64. return pHost->get_buffer_size(pHost->handle);
  65. }
  66. double getSampleRate() const
  67. {
  68. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0.0);
  69. return pHost->get_sample_rate(pHost->handle);
  70. }
  71. bool isOffline() const
  72. {
  73. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, false);
  74. return pHost->is_offline(pHost->handle);
  75. }
  76. const NativeTimeInfo* getTimeInfo() const
  77. {
  78. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  79. return pHost->get_time_info(pHost->handle);
  80. }
  81. void writeMidiEvent(const NativeMidiEvent* const event) const
  82. {
  83. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  84. pHost->write_midi_event(pHost->handle, event);
  85. }
  86. void uiParameterChanged(const uint32_t index, const float value) const
  87. {
  88. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  89. pHost->ui_parameter_changed(pHost->handle, index, value);
  90. }
  91. void uiMidiProgramChanged(const uint8_t channel, const uint32_t bank, const uint32_t program) const
  92. {
  93. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  94. pHost->ui_midi_program_changed(pHost->handle, channel, bank, program);
  95. }
  96. void uiCustomDataChanged(const char* const key, const char* const value) const
  97. {
  98. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  99. pHost->ui_custom_data_changed(pHost->handle, key, value);
  100. }
  101. void uiClosed() const
  102. {
  103. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  104. pHost->ui_closed(pHost->handle);
  105. }
  106. const char* uiOpenFile(const bool isDir, const char* const title, const char* const filter) const
  107. {
  108. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  109. return pHost->ui_open_file(pHost->handle, isDir, title, filter);
  110. }
  111. const char* uiSaveFile(const bool isDir, const char* const title, const char* const filter) const
  112. {
  113. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  114. return pHost->ui_save_file(pHost->handle, isDir, title, filter);
  115. }
  116. // -------------------------------------------------------------------
  117. // Host dispatcher calls
  118. void hostUpdateParameter(const int32_t index) const
  119. {
  120. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  121. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_PARAMETER, index, 0, nullptr, 0.0f);
  122. }
  123. void hostUpdateAllParameters() const
  124. {
  125. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  126. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_PARAMETER, -1, 0, nullptr, 0.0f);
  127. }
  128. void hostUpdateMidiProgram(const int32_t index, const intptr_t channel = 0) const
  129. {
  130. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  131. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_MIDI_PROGRAM, index, channel, nullptr, 0.0f);
  132. }
  133. void hostUpdateAllMidiPrograms(const intptr_t channel = 0) const
  134. {
  135. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  136. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_MIDI_PROGRAM, -1, channel, nullptr, 0.0f);
  137. }
  138. void hostReloadParameters() const
  139. {
  140. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  141. pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_PARAMETERS, 0, 0, nullptr, 0.0f);
  142. }
  143. void hostReloadMidiPrograms() const
  144. {
  145. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  146. pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_MIDI_PROGRAMS, 0, 0, nullptr, 0.0f);
  147. }
  148. void hostReloadAll() const
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  151. pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_ALL, 0, 0, nullptr, 0.0f);
  152. }
  153. void hostUiUnavailable() const
  154. {
  155. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  156. pHost->dispatcher(pHost->handle, HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  157. }
  158. // -------------------------------------------------------------------
  159. // Plugin parameter calls
  160. virtual uint32_t getParameterCount() const
  161. {
  162. return 0;
  163. }
  164. virtual const NativeParameter* getParameterInfo(const uint32_t index) const
  165. {
  166. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
  167. return nullptr;
  168. }
  169. virtual float getParameterValue(const uint32_t index) const
  170. {
  171. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
  172. return 0.0f;
  173. }
  174. virtual const char* getParameterText(const uint32_t index /*, const float value*/) const
  175. {
  176. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
  177. return nullptr;
  178. }
  179. // -------------------------------------------------------------------
  180. // Plugin midi-program calls
  181. virtual uint32_t getMidiProgramCount() const
  182. {
  183. return 0;
  184. }
  185. virtual const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
  186. {
  187. CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
  188. return nullptr;
  189. }
  190. // -------------------------------------------------------------------
  191. // Plugin state calls
  192. virtual void setParameterValue(const uint32_t index, const float value)
  193. {
  194. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  195. return;
  196. // unused
  197. (void)value;
  198. }
  199. virtual void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
  200. {
  201. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  202. return;
  203. // unused
  204. (void)bank;
  205. (void)program;
  206. }
  207. virtual void setCustomData(const char* const key, const char* const value)
  208. {
  209. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  210. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  211. }
  212. // -------------------------------------------------------------------
  213. // Plugin process calls
  214. virtual void activate()
  215. {
  216. }
  217. virtual void deactivate()
  218. {
  219. }
  220. virtual void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) = 0;
  221. // -------------------------------------------------------------------
  222. // Plugin UI calls
  223. virtual void uiShow(const bool show)
  224. {
  225. return;
  226. // unused
  227. (void)show;
  228. }
  229. virtual void uiIdle()
  230. {
  231. }
  232. virtual void uiSetParameterValue(const uint32_t index, const float value)
  233. {
  234. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  235. return;
  236. // unused
  237. (void)value;
  238. }
  239. virtual void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
  240. {
  241. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  242. return;
  243. // unused
  244. (void)bank;
  245. (void)program;
  246. }
  247. virtual void uiSetCustomData(const char* const key, const char* const value)
  248. {
  249. CARLA_SAFE_ASSERT_RETURN(key != nullptr,);
  250. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  251. }
  252. // -------------------------------------------------------------------
  253. // Plugin state calls
  254. virtual char* getState() const
  255. {
  256. return nullptr;
  257. }
  258. virtual void setState(const char* const data)
  259. {
  260. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  261. }
  262. // -------------------------------------------------------------------
  263. // Plugin dispatcher calls
  264. virtual void bufferSizeChanged(const uint32_t bufferSize)
  265. {
  266. return;
  267. // unused
  268. (void)bufferSize;
  269. }
  270. virtual void sampleRateChanged(const double sampleRate)
  271. {
  272. return;
  273. // unused
  274. (void)sampleRate;
  275. }
  276. virtual void offlineChanged(const bool isOffline)
  277. {
  278. return;
  279. // unused
  280. (void)isOffline;
  281. }
  282. virtual void uiNameChanged(const char* const uiName)
  283. {
  284. return;
  285. // unused
  286. (void)uiName;
  287. }
  288. // -------------------------------------------------------------------
  289. private:
  290. const NativeHostDescriptor* const pHost;
  291. // -------------------------------------------------------------------
  292. #ifndef DOXYGEN
  293. public:
  294. #define handlePtr ((NativePluginClass*)handle)
  295. static uint32_t _get_parameter_count(NativePluginHandle handle)
  296. {
  297. return handlePtr->getParameterCount();
  298. }
  299. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  300. {
  301. return handlePtr->getParameterInfo(index);
  302. }
  303. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  304. {
  305. return handlePtr->getParameterValue(index);
  306. }
  307. static const char* _get_parameter_text(NativePluginHandle handle, uint32_t index /*, float value*/)
  308. {
  309. return handlePtr->getParameterText(index /*, value*/);
  310. }
  311. static uint32_t _get_midi_program_count(NativePluginHandle handle)
  312. {
  313. return handlePtr->getMidiProgramCount();
  314. }
  315. static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
  316. {
  317. return handlePtr->getMidiProgramInfo(index);
  318. }
  319. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  320. {
  321. handlePtr->setParameterValue(index, value);
  322. }
  323. static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  324. {
  325. handlePtr->setMidiProgram(channel, bank, program);
  326. }
  327. static void _set_custom_data(NativePluginHandle handle, const char* key, const char* value)
  328. {
  329. handlePtr->setCustomData(key, value);
  330. }
  331. static void _ui_show(NativePluginHandle handle, bool show)
  332. {
  333. handlePtr->uiShow(show);
  334. }
  335. static void _ui_idle(NativePluginHandle handle)
  336. {
  337. handlePtr->uiIdle();
  338. }
  339. static void _ui_set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  340. {
  341. handlePtr->uiSetParameterValue(index, value);
  342. }
  343. static void _ui_set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  344. {
  345. handlePtr->uiSetMidiProgram(channel, bank, program);
  346. }
  347. static void _ui_set_custom_data(NativePluginHandle handle, const char* key, const char* value)
  348. {
  349. handlePtr->uiSetCustomData(key, value);
  350. }
  351. static void _activate(NativePluginHandle handle)
  352. {
  353. handlePtr->activate();
  354. }
  355. static void _deactivate(NativePluginHandle handle)
  356. {
  357. handlePtr->deactivate();
  358. }
  359. static void _process(NativePluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  360. {
  361. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  362. }
  363. static char* _get_state(NativePluginHandle handle)
  364. {
  365. return handlePtr->getState();
  366. }
  367. static void _set_state(NativePluginHandle handle, const char* data)
  368. {
  369. handlePtr->setState(data);
  370. }
  371. static intptr_t _dispatcher(NativePluginHandle handle, NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  372. {
  373. switch(opcode)
  374. {
  375. case PLUGIN_OPCODE_NULL:
  376. return 0;
  377. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  378. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  379. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  380. return 0;
  381. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  382. CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0);
  383. handlePtr->sampleRateChanged(static_cast<double>(opt));
  384. return 0;
  385. case PLUGIN_OPCODE_OFFLINE_CHANGED:
  386. handlePtr->offlineChanged(value != 0);
  387. return 0;
  388. case PLUGIN_OPCODE_UI_NAME_CHANGED:
  389. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
  390. handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  391. return 0;
  392. }
  393. return 0;
  394. // unused
  395. (void)index;
  396. }
  397. #undef handlePtr
  398. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginClass)
  399. #endif
  400. };
  401. /**@}*/
  402. // -----------------------------------------------------------------------
  403. #define PluginClassEND(ClassName) \
  404. public: \
  405. static NativePluginHandle _instantiate(const NativeHostDescriptor* host) \
  406. { \
  407. return (host != nullptr) ? new ClassName(host) : nullptr; \
  408. } \
  409. static void _cleanup(NativePluginHandle handle) \
  410. { \
  411. delete (ClassName*)handle; \
  412. }
  413. #define PluginDescriptorFILL(ClassName) \
  414. ClassName::_instantiate, \
  415. ClassName::_cleanup, \
  416. ClassName::_get_parameter_count, \
  417. ClassName::_get_parameter_info, \
  418. ClassName::_get_parameter_value, \
  419. ClassName::_get_parameter_text, \
  420. ClassName::_get_midi_program_count, \
  421. ClassName::_get_midi_program_info, \
  422. ClassName::_set_parameter_value, \
  423. ClassName::_set_midi_program, \
  424. ClassName::_set_custom_data, \
  425. ClassName::_ui_show, \
  426. ClassName::_ui_idle, \
  427. ClassName::_ui_set_parameter_value, \
  428. ClassName::_ui_set_midi_program, \
  429. ClassName::_ui_set_custom_data, \
  430. ClassName::_activate, \
  431. ClassName::_deactivate, \
  432. ClassName::_process, \
  433. ClassName::_get_state, \
  434. ClassName::_set_state, \
  435. ClassName::_dispatcher
  436. // -----------------------------------------------------------------------
  437. #endif // CARLA_NATIVE_HPP_INCLUDED