DISTRHO Plugin Framework
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.

396 lines
10KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_UI_INTERNAL_HPP_INCLUDED
  17. #define DISTRHO_UI_INTERNAL_HPP_INCLUDED
  18. #include "../DistrhoUI.hpp"
  19. #if DISTRHO_UI_USE_NTK
  20. # include "../../dgl/ntk/NtkApp.hpp"
  21. # include "../../dgl/ntk/NtkWindow.hpp"
  22. typedef DGL::NtkApp App;
  23. typedef DGL::NtkWindow UIWindow;
  24. #else
  25. # include "../../dgl/App.hpp"
  26. # include "../../dgl/Window.hpp"
  27. typedef DGL::App App;
  28. typedef DGL::Window UIWindow;
  29. #endif
  30. using DGL::IdleCallback;
  31. START_NAMESPACE_DISTRHO
  32. // -----------------------------------------------------------------------
  33. // Static data, see DistrhoUI.cpp
  34. extern double d_lastUiSampleRate;
  35. extern void* d_lastUiDspPtr;
  36. extern UIWindow* d_lastUiWindow;
  37. // -----------------------------------------------------------------------
  38. // UI callbacks
  39. typedef void (*editParamFunc) (void* ptr, uint32_t rindex, bool started);
  40. typedef void (*setParamFunc) (void* ptr, uint32_t rindex, float value);
  41. typedef void (*setStateFunc) (void* ptr, const char* key, const char* value);
  42. typedef void (*sendNoteFunc) (void* ptr, uint8_t channel, uint8_t note, uint8_t velo);
  43. typedef void (*setSizeFunc) (void* ptr, uint width, uint height);
  44. // -----------------------------------------------------------------------
  45. // UI private data
  46. struct UI::PrivateData {
  47. // DSP
  48. double sampleRate;
  49. uint32_t parameterOffset;
  50. #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  51. void* dspPtr;
  52. #endif
  53. // Callbacks
  54. editParamFunc editParamCallbackFunc;
  55. setParamFunc setParamCallbackFunc;
  56. setStateFunc setStateCallbackFunc;
  57. sendNoteFunc sendNoteCallbackFunc;
  58. setSizeFunc setSizeCallbackFunc;
  59. void* ptr;
  60. PrivateData() noexcept
  61. : sampleRate(d_lastUiSampleRate),
  62. parameterOffset(0),
  63. #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
  64. dspPtr(d_lastUiDspPtr),
  65. #endif
  66. editParamCallbackFunc(nullptr),
  67. setParamCallbackFunc(nullptr),
  68. setStateCallbackFunc(nullptr),
  69. sendNoteCallbackFunc(nullptr),
  70. setSizeCallbackFunc(nullptr),
  71. ptr(nullptr)
  72. {
  73. DISTRHO_SAFE_ASSERT(sampleRate != 0.0);
  74. #if defined(DISTRHO_PLUGIN_TARGET_DSSI) || defined(DISTRHO_PLUGIN_TARGET_LV2)
  75. parameterOffset += DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS;
  76. # if DISTRHO_PLUGIN_WANT_LATENCY
  77. parameterOffset += 1;
  78. # endif
  79. #endif
  80. #ifdef DISTRHO_PLUGIN_TARGET_LV2
  81. # if (DISTRHO_PLUGIN_IS_SYNTH || DISTRHO_PLUGIN_WANT_TIMEPOS || DISTRHO_PLUGIN_WANT_STATE)
  82. parameterOffset += 1;
  83. # if DISTRHO_PLUGIN_WANT_STATE
  84. parameterOffset += 1;
  85. # endif
  86. # endif
  87. #endif
  88. }
  89. void editParamCallback(const uint32_t rindex, const bool started)
  90. {
  91. if (editParamCallbackFunc != nullptr)
  92. editParamCallbackFunc(ptr, rindex, started);
  93. }
  94. void setParamCallback(const uint32_t rindex, const float value)
  95. {
  96. if (setParamCallbackFunc != nullptr)
  97. setParamCallbackFunc(ptr, rindex, value);
  98. }
  99. void setStateCallback(const char* const key, const char* const value)
  100. {
  101. if (setStateCallbackFunc != nullptr)
  102. setStateCallbackFunc(ptr, key, value);
  103. }
  104. void sendNoteCallback(const uint8_t channel, const uint8_t note, const uint8_t velocity)
  105. {
  106. if (sendNoteCallbackFunc != nullptr)
  107. sendNoteCallbackFunc(ptr, channel, note, velocity);
  108. }
  109. void setSizeCallback(const uint width, const uint height)
  110. {
  111. if (setSizeCallbackFunc != nullptr)
  112. setSizeCallbackFunc(ptr, width, height);
  113. }
  114. };
  115. // -----------------------------------------------------------------------
  116. // Plugin Window, needed to take care of resize properly
  117. static inline
  118. UI* createUiWrapper(void* const dspPtr, UIWindow* const window)
  119. {
  120. d_lastUiDspPtr = dspPtr;
  121. d_lastUiWindow = window;
  122. UI* const ret = createUI();
  123. d_lastUiDspPtr = nullptr;
  124. d_lastUiWindow = nullptr;
  125. return ret;
  126. }
  127. class UIExporterWindow : public UIWindow
  128. {
  129. public:
  130. UIExporterWindow(App& app, const intptr_t winId, void* const dspPtr)
  131. : UIWindow(app, winId),
  132. fUI(createUiWrapper(dspPtr, this)),
  133. fIsReady(false)
  134. {
  135. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  136. #if ! DISTRHO_UI_USE_NTK
  137. const int width = fUI->d_getWidth();
  138. const int height = fUI->d_getHeight();
  139. // set widget size
  140. fUI->setSize(width, height);
  141. // set this window size
  142. setResizable(false);
  143. setSize(width, height);
  144. #endif
  145. }
  146. ~UIExporterWindow()
  147. {
  148. delete fUI;
  149. }
  150. UI* getUI() const noexcept
  151. {
  152. return fUI;
  153. }
  154. bool isReady() const noexcept
  155. {
  156. return fIsReady;
  157. }
  158. #if ! DISTRHO_UI_USE_NTK
  159. protected:
  160. void onReshape(int width, int height) override
  161. {
  162. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  163. // report size change to plugin UI
  164. fUI->setSize(width, height);
  165. // update openGL state
  166. fUI->d_uiReshape(width, height);
  167. fIsReady = true;
  168. }
  169. #endif
  170. private:
  171. UI* const fUI;
  172. bool fIsReady;
  173. };
  174. // -----------------------------------------------------------------------
  175. // UI exporter class
  176. class UIExporter
  177. {
  178. public:
  179. UIExporter(void* const ptr, const intptr_t winId,
  180. const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall,
  181. void* const dspPtr = nullptr)
  182. : glApp(),
  183. glWindow(glApp, winId, dspPtr),
  184. fUI(glWindow.getUI()),
  185. fData((fUI != nullptr) ? fUI->pData : nullptr)
  186. {
  187. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  188. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  189. fData->ptr = ptr;
  190. fData->editParamCallbackFunc = editParamCall;
  191. fData->setParamCallbackFunc = setParamCall;
  192. fData->setStateCallbackFunc = setStateCall;
  193. fData->sendNoteCallbackFunc = sendNoteCall;
  194. fData->setSizeCallbackFunc = setSizeCall;
  195. }
  196. // -------------------------------------------------------------------
  197. const char* getName() const noexcept
  198. {
  199. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, "");
  200. return fUI->d_getName();
  201. }
  202. uint getWidth() const noexcept
  203. {
  204. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 0);
  205. return fUI->d_getWidth();
  206. }
  207. uint getHeight() const noexcept
  208. {
  209. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, 0);
  210. return fUI->d_getHeight();
  211. }
  212. // -------------------------------------------------------------------
  213. uint32_t getParameterOffset() const noexcept
  214. {
  215. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  216. return fData->parameterOffset;
  217. }
  218. // -------------------------------------------------------------------
  219. void parameterChanged(const uint32_t index, const float value)
  220. {
  221. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  222. fUI->d_parameterChanged(index, value);
  223. }
  224. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  225. void programChanged(const uint32_t index)
  226. {
  227. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  228. fUI->d_programChanged(index);
  229. }
  230. #endif
  231. #if DISTRHO_PLUGIN_WANT_STATE
  232. void stateChanged(const char* const key, const char* const value)
  233. {
  234. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  235. DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  236. DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
  237. fUI->d_stateChanged(key, value);
  238. }
  239. #endif
  240. #if ! DISTRHO_UI_USE_NTK
  241. // -------------------------------------------------------------------
  242. void exec(IdleCallback* const cb)
  243. {
  244. DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
  245. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  246. glWindow.addIdleCallback(cb);
  247. glWindow.setVisible(true);
  248. glApp.exec();
  249. }
  250. void exec_idle()
  251. {
  252. if (glWindow.isReady())
  253. fUI->d_uiIdle();
  254. }
  255. bool idle()
  256. {
  257. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);
  258. glApp.idle();
  259. if (glWindow.isReady())
  260. fUI->d_uiIdle();
  261. return ! glApp.isQuiting();
  262. }
  263. bool isVisible() const noexcept
  264. {
  265. return glWindow.isVisible();
  266. }
  267. void quit()
  268. {
  269. glWindow.close();
  270. glApp.quit();
  271. }
  272. void setSize(const uint width, const uint height)
  273. {
  274. glWindow.setSize(width, height);
  275. }
  276. void setTitle(const char* const uiTitle)
  277. {
  278. glWindow.setTitle(uiTitle);
  279. }
  280. void setTransientWinId(const intptr_t winId)
  281. {
  282. glWindow.setTransientWinId(winId);
  283. }
  284. bool setVisible(const bool yesNo)
  285. {
  286. glWindow.setVisible(yesNo);
  287. return ! glApp.isQuiting();
  288. }
  289. #endif
  290. void setSampleRate(const double sampleRate, const bool doCallback = false)
  291. {
  292. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  293. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  294. DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
  295. if (fData->sampleRate == sampleRate)
  296. return;
  297. fData->sampleRate = sampleRate;
  298. if (doCallback)
  299. fUI->d_sampleRateChanged(sampleRate);
  300. }
  301. private:
  302. // -------------------------------------------------------------------
  303. // DGL Application and Window for this widget
  304. App glApp;
  305. UIExporterWindow glWindow;
  306. // -------------------------------------------------------------------
  307. // Widget and DistrhoUI data
  308. UI* const fUI;
  309. UI::PrivateData* const fData;
  310. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter)
  311. };
  312. // -----------------------------------------------------------------------
  313. END_NAMESPACE_DISTRHO
  314. #endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED