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.

613 lines
17KB

  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. uint32_t getBufferSize() const noexcept
  57. {
  58. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0);
  59. return pHost->get_buffer_size(pHost->handle);
  60. }
  61. double getSampleRate() const noexcept
  62. {
  63. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, 0.0);
  64. return pHost->get_sample_rate(pHost->handle);
  65. }
  66. bool isOffline() const noexcept
  67. {
  68. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, false);
  69. return pHost->is_offline(pHost->handle);
  70. }
  71. const NativeTimeInfo* getTimeInfo() const noexcept
  72. {
  73. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  74. return pHost->get_time_info(pHost->handle);
  75. }
  76. void writeMidiEvent(const NativeMidiEvent* const event) const
  77. {
  78. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  79. pHost->write_midi_event(pHost->handle, event);
  80. }
  81. void uiParameterChanged(const uint32_t index, const float value) const
  82. {
  83. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  84. pHost->ui_parameter_changed(pHost->handle, index, value);
  85. }
  86. void uiMidiProgramChanged(const uint8_t channel, const uint32_t bank, const uint32_t program) const
  87. {
  88. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  89. pHost->ui_midi_program_changed(pHost->handle, channel, bank, program);
  90. }
  91. void uiCustomDataChanged(const char* const key, const char* const value) const
  92. {
  93. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  94. pHost->ui_custom_data_changed(pHost->handle, key, value);
  95. }
  96. void uiClosed() const
  97. {
  98. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  99. pHost->ui_closed(pHost->handle);
  100. }
  101. const char* uiOpenFile(const bool isDir, const char* const title, const char* const filter) const
  102. {
  103. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr);
  104. return pHost->ui_open_file(pHost->handle, isDir, title, filter);
  105. }
  106. const char* uiSaveFile(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_save_file(pHost->handle, isDir, title, filter);
  110. }
  111. // -------------------------------------------------------------------
  112. // Host dispatcher calls
  113. void hostSetVolume(const float value) const
  114. {
  115. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  116. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_VOLUME, 0, 0, nullptr, value);
  117. }
  118. void hostSetDryWet(const float value) const
  119. {
  120. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  121. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_DRYWET, 0, 0, nullptr, value);
  122. }
  123. void hostSetBalanceLeft(const float value) const
  124. {
  125. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  126. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_BALANCE_LEFT, 0, 0, nullptr, value);
  127. }
  128. void hostSetBalanceRight(const float value) const
  129. {
  130. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  131. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_BALANCE_RIGHT, 0, 0, nullptr, value);
  132. }
  133. void hostSetPanning(const float value) const
  134. {
  135. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  136. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_PANNING, 0, 0, nullptr, value);
  137. }
  138. intptr_t hostGetParameterMidiCC(const int32_t index) const
  139. {
  140. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, -1);
  141. return pHost->dispatcher(pHost->handle, HOST_OPCODE_GET_PARAMETER_MIDI_CC, index, 0, nullptr, 0.0f);
  142. }
  143. void hostSetParameterMidiCC(const int32_t index, const intptr_t value) const
  144. {
  145. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  146. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_PARAMETER_MIDI_CC, index, value, nullptr, 0.0f);
  147. }
  148. void hostSetProcessPrecision(const intptr_t value) const
  149. {
  150. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  151. pHost->dispatcher(pHost->handle, HOST_OPCODE_SET_PROCESS_PRECISION, 0, value, nullptr, 0.0f);
  152. }
  153. void hostUpdateParameter(const int32_t index) const
  154. {
  155. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  156. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_PARAMETER, index, 0, nullptr, 0.0f);
  157. }
  158. void hostUpdateAllParameters() const
  159. {
  160. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  161. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_PARAMETER, -1, 0, nullptr, 0.0f);
  162. }
  163. void hostUpdateMidiProgram(const int32_t index, const intptr_t channel = 0) const
  164. {
  165. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  166. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_MIDI_PROGRAM, index, channel, nullptr, 0.0f);
  167. }
  168. void hostUpdateAllMidiPrograms(const intptr_t channel = 0) const
  169. {
  170. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  171. pHost->dispatcher(pHost->handle, HOST_OPCODE_UPDATE_MIDI_PROGRAM, -1, channel, nullptr, 0.0f);
  172. }
  173. void hostReloadParameters() const
  174. {
  175. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  176. pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_PARAMETERS, 0, 0, nullptr, 0.0f);
  177. }
  178. void hostReloadMidiPrograms() const
  179. {
  180. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  181. pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_MIDI_PROGRAMS, 0, 0, nullptr, 0.0f);
  182. }
  183. void hostReloadAll() const
  184. {
  185. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  186. pHost->dispatcher(pHost->handle, HOST_OPCODE_RELOAD_ALL, 0, 0, nullptr, 0.0f);
  187. }
  188. void hostUiUnavailable() const
  189. {
  190. CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,);
  191. pHost->dispatcher(pHost->handle, HOST_OPCODE_UI_UNAVAILABLE, 0, 0, nullptr, 0.0f);
  192. }
  193. // -------------------------------------------------------------------
  194. // Plugin parameter calls
  195. virtual uint32_t getParameterCount() const
  196. {
  197. return 0;
  198. }
  199. virtual const NativeParameter* getParameterInfo(const uint32_t index) const
  200. {
  201. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
  202. return nullptr;
  203. }
  204. virtual float getParameterValue(const uint32_t index) const
  205. {
  206. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), 0.0f);
  207. return 0.0f;
  208. }
  209. virtual const char* getParameterText(const uint32_t index /*, const float value*/) const
  210. {
  211. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(), nullptr);
  212. return nullptr;
  213. }
  214. // -------------------------------------------------------------------
  215. // Plugin midi-program calls
  216. virtual uint32_t getMidiProgramCount() const
  217. {
  218. return 0;
  219. }
  220. virtual const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const
  221. {
  222. CARLA_SAFE_ASSERT_RETURN(index < getMidiProgramCount(), nullptr);
  223. return nullptr;
  224. }
  225. // -------------------------------------------------------------------
  226. // Plugin state calls
  227. virtual void setParameterValue(const uint32_t index, const float value)
  228. {
  229. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  230. return;
  231. // unused
  232. (void)value;
  233. }
  234. virtual void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
  235. {
  236. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  237. return;
  238. // unused
  239. (void)bank;
  240. (void)program;
  241. }
  242. virtual void setCustomData(const char* const key, const char* const value)
  243. {
  244. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  245. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  246. }
  247. // -------------------------------------------------------------------
  248. // Plugin process calls
  249. virtual void activate()
  250. {
  251. }
  252. virtual void deactivate()
  253. {
  254. }
  255. virtual void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) = 0;
  256. // -------------------------------------------------------------------
  257. // Plugin UI calls
  258. virtual void uiShow(const bool show)
  259. {
  260. return;
  261. // unused
  262. (void)show;
  263. }
  264. virtual void uiIdle()
  265. {
  266. }
  267. virtual void uiSetParameterValue(const uint32_t index, const float value)
  268. {
  269. CARLA_SAFE_ASSERT_RETURN(index < getParameterCount(),);
  270. return;
  271. // unused
  272. (void)value;
  273. }
  274. virtual void uiSetMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program)
  275. {
  276. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
  277. return;
  278. // unused
  279. (void)bank;
  280. (void)program;
  281. }
  282. virtual void uiSetCustomData(const char* const key, const char* const value)
  283. {
  284. CARLA_SAFE_ASSERT_RETURN(key != nullptr,);
  285. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  286. }
  287. // -------------------------------------------------------------------
  288. // Plugin state calls
  289. virtual char* getState() const
  290. {
  291. return nullptr;
  292. }
  293. virtual void setState(const char* const data)
  294. {
  295. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  296. }
  297. // -------------------------------------------------------------------
  298. // Plugin dispatcher calls
  299. virtual void bufferSizeChanged(const uint32_t bufferSize)
  300. {
  301. return;
  302. // unused
  303. (void)bufferSize;
  304. }
  305. virtual void sampleRateChanged(const double sampleRate)
  306. {
  307. return;
  308. // unused
  309. (void)sampleRate;
  310. }
  311. virtual void offlineChanged(const bool isOffline)
  312. {
  313. return;
  314. // unused
  315. (void)isOffline;
  316. }
  317. virtual void uiNameChanged(const char* const uiName)
  318. {
  319. return;
  320. // unused
  321. (void)uiName;
  322. }
  323. // -------------------------------------------------------------------
  324. private:
  325. const NativeHostDescriptor* const pHost;
  326. // -------------------------------------------------------------------
  327. #ifndef DOXYGEN
  328. public:
  329. #define handlePtr ((NativePluginClass*)handle)
  330. static uint32_t _get_parameter_count(NativePluginHandle handle)
  331. {
  332. return handlePtr->getParameterCount();
  333. }
  334. static const NativeParameter* _get_parameter_info(NativePluginHandle handle, uint32_t index)
  335. {
  336. return handlePtr->getParameterInfo(index);
  337. }
  338. static float _get_parameter_value(NativePluginHandle handle, uint32_t index)
  339. {
  340. return handlePtr->getParameterValue(index);
  341. }
  342. static const char* _get_parameter_text(NativePluginHandle handle, uint32_t index /*, float value*/)
  343. {
  344. return handlePtr->getParameterText(index /*, value*/);
  345. }
  346. static uint32_t _get_midi_program_count(NativePluginHandle handle)
  347. {
  348. return handlePtr->getMidiProgramCount();
  349. }
  350. static const NativeMidiProgram* _get_midi_program_info(NativePluginHandle handle, uint32_t index)
  351. {
  352. return handlePtr->getMidiProgramInfo(index);
  353. }
  354. static void _set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  355. {
  356. handlePtr->setParameterValue(index, value);
  357. }
  358. static void _set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  359. {
  360. handlePtr->setMidiProgram(channel, bank, program);
  361. }
  362. static void _set_custom_data(NativePluginHandle handle, const char* key, const char* value)
  363. {
  364. handlePtr->setCustomData(key, value);
  365. }
  366. static void _ui_show(NativePluginHandle handle, bool show)
  367. {
  368. handlePtr->uiShow(show);
  369. }
  370. static void _ui_idle(NativePluginHandle handle)
  371. {
  372. handlePtr->uiIdle();
  373. }
  374. static void _ui_set_parameter_value(NativePluginHandle handle, uint32_t index, float value)
  375. {
  376. handlePtr->uiSetParameterValue(index, value);
  377. }
  378. static void _ui_set_midi_program(NativePluginHandle handle, uint8_t channel, uint32_t bank, uint32_t program)
  379. {
  380. handlePtr->uiSetMidiProgram(channel, bank, program);
  381. }
  382. static void _ui_set_custom_data(NativePluginHandle handle, const char* key, const char* value)
  383. {
  384. handlePtr->uiSetCustomData(key, value);
  385. }
  386. static void _activate(NativePluginHandle handle)
  387. {
  388. handlePtr->activate();
  389. }
  390. static void _deactivate(NativePluginHandle handle)
  391. {
  392. handlePtr->deactivate();
  393. }
  394. static void _process(NativePluginHandle handle, float** inBuffer, float** outBuffer, const uint32_t frames, const NativeMidiEvent* midiEvents, uint32_t midiEventCount)
  395. {
  396. handlePtr->process(inBuffer, outBuffer, frames, midiEvents, midiEventCount);
  397. }
  398. static char* _get_state(NativePluginHandle handle)
  399. {
  400. return handlePtr->getState();
  401. }
  402. static void _set_state(NativePluginHandle handle, const char* data)
  403. {
  404. handlePtr->setState(data);
  405. }
  406. static intptr_t _dispatcher(NativePluginHandle handle, NativePluginDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt)
  407. {
  408. switch(opcode)
  409. {
  410. case PLUGIN_OPCODE_NULL:
  411. return 0;
  412. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  413. CARLA_SAFE_ASSERT_RETURN(value > 0, 0);
  414. handlePtr->bufferSizeChanged(static_cast<uint32_t>(value));
  415. return 0;
  416. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  417. CARLA_SAFE_ASSERT_RETURN(opt > 0.0f, 0);
  418. handlePtr->sampleRateChanged(static_cast<double>(opt));
  419. return 0;
  420. case PLUGIN_OPCODE_OFFLINE_CHANGED:
  421. handlePtr->offlineChanged(value != 0);
  422. return 0;
  423. case PLUGIN_OPCODE_UI_NAME_CHANGED:
  424. CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0);
  425. handlePtr->uiNameChanged(static_cast<const char*>(ptr));
  426. return 0;
  427. }
  428. return 0;
  429. // unused
  430. (void)index;
  431. }
  432. #undef handlePtr
  433. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginClass)
  434. #endif
  435. };
  436. /**@}*/
  437. // -----------------------------------------------------------------------
  438. #define PluginClassEND(ClassName) \
  439. public: \
  440. static NativePluginHandle _instantiate(const NativeHostDescriptor* host) \
  441. { \
  442. return (host != nullptr) ? new ClassName(host) : nullptr; \
  443. } \
  444. static void _cleanup(NativePluginHandle handle) \
  445. { \
  446. delete (ClassName*)handle; \
  447. }
  448. #define PluginDescriptorFILL(ClassName) \
  449. ClassName::_instantiate, \
  450. ClassName::_cleanup, \
  451. ClassName::_get_parameter_count, \
  452. ClassName::_get_parameter_info, \
  453. ClassName::_get_parameter_value, \
  454. ClassName::_get_parameter_text, \
  455. ClassName::_get_midi_program_count, \
  456. ClassName::_get_midi_program_info, \
  457. ClassName::_set_parameter_value, \
  458. ClassName::_set_midi_program, \
  459. ClassName::_set_custom_data, \
  460. ClassName::_ui_show, \
  461. ClassName::_ui_idle, \
  462. ClassName::_ui_set_parameter_value, \
  463. ClassName::_ui_set_midi_program, \
  464. ClassName::_ui_set_custom_data, \
  465. ClassName::_activate, \
  466. ClassName::_deactivate, \
  467. ClassName::_process, \
  468. ClassName::_get_state, \
  469. ClassName::_set_state, \
  470. ClassName::_dispatcher
  471. // -----------------------------------------------------------------------
  472. #endif // CARLA_NATIVE_HPP_INCLUDED