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.

351 lines
9.9KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012-2015 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. #include "CarlaNative.hpp"
  18. #include "CarlaMutex.hpp"
  19. #include "CarlaJuceUtils.hpp"
  20. #include "juce_audio_basics.h"
  21. #include "zita-jaaa/source/audio.cc"
  22. #include "zita-jaaa/source/rngen.cc"
  23. #include "zita-jaaa/source/spectwin.cc"
  24. #include "zita-jaaa/source/styles.cc"
  25. using juce::FloatVectorOperations;
  26. using juce::ScopedPointer;
  27. // -----------------------------------------------------------------------
  28. // Jaaa Plugin
  29. class JaaaPlugin : public NativePluginClass
  30. {
  31. public:
  32. enum Parameters {
  33. kParameterInput = 0,
  34. kParameterCount
  35. };
  36. JaaaPlugin(const NativeHostDescriptor* const host)
  37. : NativePluginClass(host),
  38. fJackClient(),
  39. fMutex(),
  40. xrm(),
  41. itcc(nullptr),
  42. driver(nullptr),
  43. display(nullptr),
  44. rootwin(nullptr),
  45. mainwin(nullptr),
  46. xhandler(nullptr),
  47. leakDetector_JaaaPlugin()
  48. {
  49. CARLA_SAFE_ASSERT(host != nullptr);
  50. int argc = 1;
  51. char* argv[] = { (char*)"jaaa" };
  52. xrm.init(&argc, argv, (char*)"jaaa", nullptr, 0);
  53. fParameters[kParameterInput] = 1.0f;
  54. }
  55. // -------------------------------------------------------------------
  56. // Plugin parameter calls
  57. uint32_t getParameterCount() const override
  58. {
  59. return kParameterCount;
  60. }
  61. const NativeParameter* getParameterInfo(const uint32_t index) const override
  62. {
  63. CARLA_SAFE_ASSERT_RETURN(index < kParameterCount, nullptr);
  64. static NativeParameter param;
  65. int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMABLE;
  66. // reset
  67. param.name = nullptr;
  68. param.unit = nullptr;
  69. param.ranges.def = 0.0f;
  70. param.ranges.min = 0.0f;
  71. param.ranges.max = 1.0f;
  72. param.ranges.step = 1.0f;
  73. param.ranges.stepSmall = 1.0f;
  74. param.ranges.stepLarge = 1.0f;
  75. param.scalePointCount = 0;
  76. param.scalePoints = nullptr;
  77. switch (index)
  78. {
  79. case kParameterInput:
  80. hints |= NATIVE_PARAMETER_IS_INTEGER;
  81. param.name = "Input";
  82. param.ranges.def = 1.0f;
  83. param.ranges.min = 1.0f;
  84. param.ranges.max = 8.0f;
  85. break;
  86. }
  87. param.hints = static_cast<NativeParameterHints>(hints);
  88. return &param;
  89. }
  90. float getParameterValue(const uint32_t index) const override
  91. {
  92. CARLA_SAFE_ASSERT_RETURN(index < kParameterCount, 0.0f);
  93. return fParameters[index];
  94. }
  95. // -------------------------------------------------------------------
  96. // Plugin state calls
  97. void setParameterValue(const uint32_t index, const float value) override
  98. {
  99. CARLA_SAFE_ASSERT_RETURN(index < kParameterCount,);
  100. fParameters[index] = value;
  101. }
  102. // -------------------------------------------------------------------
  103. // Plugin process calls
  104. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override
  105. {
  106. const CarlaMutexTryLocker cmtl(fMutex);
  107. if (itcc == nullptr || ! fJackClient.active || ! cmtl.wasLocked())
  108. {
  109. const int iframes(static_cast<int>(frames));
  110. for (int i=0; i<8; ++i)
  111. FloatVectorOperations::clear(outBuffer[i], iframes);
  112. return;
  113. }
  114. for (int i=0; i<8; ++i)
  115. fJackClient.portsAudioIn[i]->buffer = inBuffer[i];
  116. for (int i=0; i<8; ++i)
  117. fJackClient.portsAudioOut[i]->buffer = outBuffer[i];
  118. fJackClient.processCallback(frames, fJackClient.processPtr);
  119. }
  120. // -------------------------------------------------------------------
  121. // Plugin UI calls
  122. void uiShow(const bool show) override
  123. {
  124. const CarlaMutexLocker cml(fMutex);
  125. if (show)
  126. {
  127. if (itcc == nullptr)
  128. {
  129. carla_zeroStruct(fJackClient);
  130. gLastJackClient = &fJackClient;
  131. fJackClient.clientName = getUiName();
  132. fJackClient.bufferSize = getBufferSize();
  133. fJackClient.sampleRate = getSampleRate();
  134. itcc = new ITC_ctrl();
  135. driver = new Audio(itcc, getUiName());
  136. driver->init_jack(nullptr);
  137. display = new X_display(nullptr);
  138. if (display->dpy() == nullptr)
  139. {
  140. driver = nullptr;
  141. itcc = nullptr;
  142. return hostUiUnavailable();
  143. }
  144. init_styles(display, &xrm);
  145. rootwin = new X_rootwin(display);
  146. mainwin = new Spectwin(rootwin, &xrm, driver);
  147. xhandler = new X_handler(display, itcc, EV_X11);
  148. if (const uintptr_t winId = getUiParentId())
  149. XSetTransientForHint(display->dpy(), mainwin->win(), static_cast<Window>(winId));
  150. }
  151. xhandler->next_event();
  152. XFlush(display->dpy());
  153. }
  154. else
  155. {
  156. xhandler = nullptr;
  157. mainwin = nullptr;
  158. rootwin = nullptr;
  159. display = nullptr;
  160. driver = nullptr;
  161. itcc = nullptr;
  162. carla_zeroStruct(fJackClient);
  163. }
  164. }
  165. void uiIdle() override
  166. {
  167. if (itcc == nullptr)
  168. return;
  169. //for (int i=3; --i>=0;)
  170. {
  171. switch (itcc->get_event())
  172. {
  173. case EV_TRIG:
  174. mainwin->handle_trig();
  175. rootwin->handle_event();
  176. XFlush(display->dpy());
  177. break;
  178. case EV_MESG:
  179. mainwin->handle_mesg(itcc->get_message());
  180. rootwin->handle_event();
  181. XFlush(display->dpy());
  182. break;
  183. case EV_X11:
  184. rootwin->handle_event();
  185. xhandler->next_event();
  186. break;
  187. }
  188. }
  189. // check if parameters were updated
  190. if (mainwin->_input+1 != static_cast<int>(fParameters[kParameterInput]))
  191. {
  192. fParameters[kParameterInput] = mainwin->_input+1;
  193. uiParameterChanged(kParameterInput, fParameters[kParameterInput]);
  194. }
  195. // check if UI was closed
  196. if (! mainwin->running())
  197. {
  198. {
  199. const CarlaMutexLocker cml(fMutex);
  200. xhandler = nullptr;
  201. mainwin = nullptr;
  202. rootwin = nullptr;
  203. display = nullptr;
  204. driver = nullptr;
  205. itcc = nullptr;
  206. carla_zeroStruct(fJackClient);
  207. }
  208. uiClosed();
  209. return;
  210. }
  211. }
  212. void uiSetParameterValue(const uint32_t index, const float value) override
  213. {
  214. CARLA_SAFE_ASSERT_RETURN(index < kParameterCount,);
  215. const CarlaMutexLocker cml(fMutex);
  216. if (itcc == nullptr)
  217. return;
  218. switch (index)
  219. {
  220. case kParameterInput:
  221. mainwin->set_input(static_cast<int>(value)-1);
  222. break;
  223. }
  224. }
  225. // -------------------------------------------------------------------
  226. // Plugin dispatcher calls
  227. void bufferSizeChanged(const uint32_t bufferSize) override
  228. {
  229. fJackClient.bufferSize = bufferSize;
  230. }
  231. void sampleRateChanged(const double sampleRate) override
  232. {
  233. fJackClient.sampleRate = sampleRate;
  234. }
  235. // -------------------------------------------------------------------
  236. private:
  237. // Fake jack client
  238. jack_client_t fJackClient;
  239. // Mutex just in case
  240. CarlaMutex fMutex;
  241. // Zita stuff (core)
  242. X_resman xrm;
  243. ScopedPointer<ITC_ctrl> itcc;
  244. ScopedPointer<Audio> driver;
  245. ScopedPointer<X_display> display;
  246. ScopedPointer<X_rootwin> rootwin;
  247. ScopedPointer<Spectwin> mainwin;
  248. ScopedPointer<X_handler> xhandler;
  249. float fParameters[kParameterCount];
  250. PluginClassEND(JaaaPlugin)
  251. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JaaaPlugin)
  252. };
  253. // -----------------------------------------------------------------------
  254. static const NativePluginDescriptor jaaaDesc = {
  255. /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
  256. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
  257. |NATIVE_PLUGIN_HAS_UI
  258. |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS
  259. |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD
  260. |NATIVE_PLUGIN_USES_PARENT_ID),
  261. /* supports */ static_cast<NativePluginSupports>(0x0),
  262. /* audioIns */ 8,
  263. /* audioOuts */ 8,
  264. /* midiIns */ 0,
  265. /* midiOuts */ 0,
  266. /* paramIns */ JaaaPlugin::kParameterCount,
  267. /* paramOuts */ 0,
  268. /* name */ "Jaaa",
  269. /* label */ "jaaa",
  270. /* maker */ "Fons Adriaensen",
  271. /* copyright */ "GPL v2+",
  272. PluginDescriptorFILL(JaaaPlugin)
  273. };
  274. // -----------------------------------------------------------------------
  275. CARLA_EXPORT
  276. void carla_register_native_plugin_zita_jaaa();
  277. CARLA_EXPORT
  278. void carla_register_native_plugin_zita_jaaa()
  279. {
  280. carla_register_native_plugin(&jaaaDesc);
  281. }
  282. // -----------------------------------------------------------------------