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.

386 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. // set window size
  137. setResizable(false);
  138. setSize(fUI->getWidth(), fUI->getHeight());
  139. }
  140. ~UIExporterWindow()
  141. {
  142. delete fUI;
  143. }
  144. UI* getUI() const noexcept
  145. {
  146. return fUI;
  147. }
  148. bool isReady() const noexcept
  149. {
  150. return fIsReady;
  151. }
  152. protected:
  153. #if DISTRHO_UI_USE_NTK
  154. void resize(int x, int y, int width, int height) override
  155. {
  156. UIWindow::resize(x, y, width, height);
  157. fIsReady = true;
  158. }
  159. #else
  160. void onReshape(uint width, uint height) override
  161. {
  162. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  163. // report size change to plugin UI
  164. // TESTING is this needed?
  165. //fUI->setSize(width, height);
  166. // custom window reshape
  167. fUI->d_uiReshape(width, height);
  168. fIsReady = true;
  169. }
  170. #endif
  171. private:
  172. UI* const fUI;
  173. bool fIsReady;
  174. };
  175. // -----------------------------------------------------------------------
  176. // UI exporter class
  177. class UIExporter
  178. {
  179. public:
  180. UIExporter(void* const ptr, const intptr_t winId,
  181. const editParamFunc editParamCall, const setParamFunc setParamCall, const setStateFunc setStateCall, const sendNoteFunc sendNoteCall, const setSizeFunc setSizeCall,
  182. void* const dspPtr = nullptr)
  183. : glApp(),
  184. glWindow(glApp, winId, dspPtr),
  185. fUI(glWindow.getUI()),
  186. fData((fUI != nullptr) ? fUI->pData : nullptr)
  187. {
  188. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  189. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  190. fData->ptr = ptr;
  191. fData->editParamCallbackFunc = editParamCall;
  192. fData->setParamCallbackFunc = setParamCall;
  193. fData->setStateCallbackFunc = setStateCall;
  194. fData->sendNoteCallbackFunc = sendNoteCall;
  195. fData->setSizeCallbackFunc = setSizeCall;
  196. }
  197. // -------------------------------------------------------------------
  198. uint getWidth() const noexcept
  199. {
  200. return glWindow.getWidth();
  201. }
  202. uint getHeight() const noexcept
  203. {
  204. return glWindow.getHeight();
  205. }
  206. bool isVisible() const noexcept
  207. {
  208. return glWindow.isVisible();
  209. }
  210. // -------------------------------------------------------------------
  211. uint32_t getParameterOffset() const noexcept
  212. {
  213. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr, 0);
  214. return fData->parameterOffset;
  215. }
  216. // -------------------------------------------------------------------
  217. void parameterChanged(const uint32_t index, const float value)
  218. {
  219. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  220. fUI->d_parameterChanged(index, value);
  221. }
  222. #if DISTRHO_PLUGIN_WANT_PROGRAMS
  223. void programChanged(const uint32_t index)
  224. {
  225. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  226. fUI->d_programChanged(index);
  227. }
  228. #endif
  229. #if DISTRHO_PLUGIN_WANT_STATE
  230. void stateChanged(const char* const key, const char* const value)
  231. {
  232. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  233. DISTRHO_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  234. DISTRHO_SAFE_ASSERT_RETURN(value != nullptr,);
  235. fUI->d_stateChanged(key, value);
  236. }
  237. #endif
  238. // -------------------------------------------------------------------
  239. void exec(IdleCallback* const cb)
  240. {
  241. DISTRHO_SAFE_ASSERT_RETURN(cb != nullptr,);
  242. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  243. glWindow.addIdleCallback(cb);
  244. glWindow.setVisible(true);
  245. glApp.exec();
  246. }
  247. void exec_idle()
  248. {
  249. if (glWindow.isReady())
  250. fUI->d_uiIdle();
  251. }
  252. bool idle()
  253. {
  254. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr, false);
  255. glApp.idle();
  256. if (glWindow.isReady())
  257. fUI->d_uiIdle();
  258. return ! glApp.isQuiting();
  259. }
  260. void quit()
  261. {
  262. glWindow.close();
  263. glApp.quit();
  264. }
  265. // -------------------------------------------------------------------
  266. void setWindowSize(const uint width, const uint height)
  267. {
  268. glWindow.setSize(width, height);
  269. }
  270. void setWindowTitle(const char* const uiTitle)
  271. {
  272. glWindow.setTitle(uiTitle);
  273. }
  274. void setWindowTransientWinId(const intptr_t winId)
  275. {
  276. glWindow.setTransientWinId(winId);
  277. }
  278. bool setWindowVisible(const bool yesNo)
  279. {
  280. glWindow.setVisible(yesNo);
  281. return ! glApp.isQuiting();
  282. }
  283. // -------------------------------------------------------------------
  284. void setSampleRate(const double sampleRate, const bool doCallback = false)
  285. {
  286. DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr,);
  287. DISTRHO_SAFE_ASSERT_RETURN(fUI != nullptr,);
  288. DISTRHO_SAFE_ASSERT(sampleRate > 0.0);
  289. if (fData->sampleRate == sampleRate)
  290. return;
  291. fData->sampleRate = sampleRate;
  292. if (doCallback)
  293. fUI->d_sampleRateChanged(sampleRate);
  294. }
  295. private:
  296. // -------------------------------------------------------------------
  297. // DGL Application and Window for this widget
  298. App glApp;
  299. UIExporterWindow glWindow;
  300. // -------------------------------------------------------------------
  301. // Widget and DistrhoUI data
  302. UI* const fUI;
  303. UI::PrivateData* const fData;
  304. DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UIExporter)
  305. };
  306. // -----------------------------------------------------------------------
  307. END_NAMESPACE_DISTRHO
  308. #endif // DISTRHO_UI_INTERNAL_HPP_INCLUDED