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.

370 lines
10KB

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