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.

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