Collection of DPF-based plugins for packaging
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.

362 lines
9.3KB

  1. /*
  2. * DISTRHO ProM Plugin
  3. * Copyright (C) 2015-2021 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 Lesser General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * For a full copy of the license see the LICENSE file.
  15. */
  16. /* s/private/public/ as workaround old projectM versions */
  17. #define private public
  18. #include "libprojectM/projectM.hpp"
  19. #undef private
  20. #ifndef PROJECTM_DATA_DIR
  21. #include "libprojectM/projectM-opengl.h"
  22. #endif
  23. #include "DistrhoPluginProM.hpp"
  24. #include "DistrhoUIProM.hpp"
  25. #ifndef DISTRHO_OS_WINDOWS
  26. # include <dlfcn.h>
  27. #endif
  28. #ifdef DISTRHO_OS_WINDOWS
  29. static HINSTANCE hInstance = nullptr;
  30. DISTRHO_PLUGIN_EXPORT
  31. BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason, LPVOID)
  32. {
  33. if (reason == DLL_PROCESS_ATTACH)
  34. hInstance = hInst;
  35. return 1;
  36. }
  37. #endif
  38. START_NAMESPACE_DISTRHO
  39. // -----------------------------------------------------------------------
  40. static String getCurrentExecutableDataDir()
  41. {
  42. static String datadir;
  43. if (datadir.isNotEmpty())
  44. return datadir;
  45. #ifdef DISTRHO_OS_WINDOWS
  46. CHAR filename[MAX_PATH + 256];
  47. filename[0] = '\0';
  48. GetModuleFileName(hInstance, filename, sizeof(filename));
  49. datadir = String(filename);
  50. datadir.truncate(datadir.rfind('\\'));
  51. #else
  52. Dl_info info;
  53. dladdr((void*)getCurrentExecutableDataDir, &info);
  54. datadir = String(info.dli_fname);
  55. datadir.truncate(datadir.rfind('/'));
  56. # ifdef DISTRHO_OS_MAC
  57. if (datadir.endsWith("/MacOS"))
  58. {
  59. datadir.truncate(datadir.rfind('/'));
  60. datadir += "/Resources";
  61. }
  62. else
  63. # endif
  64. if (datadir.endsWith("/x86_64-linux"))
  65. {
  66. datadir.truncate(datadir.rfind('/'));
  67. datadir += "/Resources";
  68. }
  69. else
  70. #endif
  71. {
  72. datadir += "/resources";
  73. }
  74. return datadir;
  75. }
  76. // -----------------------------------------------------------------------
  77. DistrhoUIProM::DistrhoUIProM()
  78. : UI(512, 512),
  79. fPM(nullptr)
  80. #ifndef DGL_USE_OPENGL3
  81. , fResizeHandle(this)
  82. #endif
  83. {
  84. const double scaleFactor = getScaleFactor();
  85. if (d_isNotZero(scaleFactor))
  86. setSize(512*scaleFactor, 512*scaleFactor);
  87. setGeometryConstraints(256*scaleFactor, 256*scaleFactor, true);
  88. // no need to show resize handle if window is user-resizable
  89. #ifndef DGL_USE_OPENGL3
  90. // if (isResizable())
  91. // fResizeHandle.hide();
  92. #endif
  93. }
  94. DistrhoUIProM::~DistrhoUIProM()
  95. {
  96. if (fPM == nullptr)
  97. return;
  98. if (DistrhoPluginProM* const dspPtr = (DistrhoPluginProM*)getPluginInstancePointer())
  99. {
  100. const MutexLocker csm(dspPtr->fMutex);
  101. dspPtr->fPM = nullptr;
  102. }
  103. }
  104. // -----------------------------------------------------------------------
  105. // DSP Callbacks
  106. void DistrhoUIProM::parameterChanged(uint32_t, float)
  107. {
  108. }
  109. // -----------------------------------------------------------------------
  110. // UI Callbacks
  111. void DistrhoUIProM::uiIdle()
  112. {
  113. if (fPM == nullptr)
  114. return;
  115. repaint();
  116. if (DistrhoPluginProM* const dspPtr = (DistrhoPluginProM*)getPluginInstancePointer())
  117. {
  118. if (dspPtr->fPM != nullptr)
  119. return;
  120. const MutexLocker csm(dspPtr->fMutex);
  121. dspPtr->fPM = fPM;
  122. }
  123. }
  124. void DistrhoUIProM::uiReshape(uint width, uint height)
  125. {
  126. UI::uiReshape(width, height);
  127. if (fPM == nullptr)
  128. {
  129. #ifdef PROJECTM_DATA_DIR
  130. fPM = new projectM(PROJECTM_DATA_DIR "/config.inp");
  131. #else
  132. const String datadir(getCurrentExecutableDataDir());
  133. d_stdout("ProM datadir: '%s'", datadir.buffer());
  134. projectM::Settings settings;
  135. settings.presetURL = datadir + DISTRHO_OS_SEP_STR "presets";
  136. settings.titleFontURL = datadir + DISTRHO_OS_SEP_STR "fonts" DISTRHO_OS_SEP_STR "Vera.ttf";
  137. settings.menuFontURL = datadir + DISTRHO_OS_SEP_STR "fonts" DISTRHO_OS_SEP_STR "VeraMono.ttf";
  138. settings.datadir = datadir;
  139. fPM = new projectM(settings);
  140. #endif
  141. }
  142. fPM->projectM_resetGL(width, height);
  143. }
  144. // -----------------------------------------------------------------------
  145. // Widget Callbacks
  146. void DistrhoUIProM::onDisplay()
  147. {
  148. if (fPM == nullptr)
  149. return;
  150. fPM->renderFrame();
  151. }
  152. static projectMKeycode dgl2pmkey(const DGL_NAMESPACE::Key key) noexcept
  153. {
  154. switch (key)
  155. {
  156. case DGL_NAMESPACE::kKeyBackspace:
  157. return PROJECTM_K_BACKSPACE;
  158. case DGL_NAMESPACE::kKeyEscape:
  159. return PROJECTM_K_ESCAPE;
  160. case DGL_NAMESPACE::kKeyDelete:
  161. return PROJECTM_K_DELETE;
  162. case DGL_NAMESPACE::kKeyF1:
  163. return PROJECTM_K_F1;
  164. case DGL_NAMESPACE::kKeyF2:
  165. return PROJECTM_K_F2;
  166. case DGL_NAMESPACE::kKeyF3:
  167. return PROJECTM_K_F3;
  168. case DGL_NAMESPACE::kKeyF4:
  169. return PROJECTM_K_F4;
  170. case DGL_NAMESPACE::kKeyF5:
  171. return PROJECTM_K_F5;
  172. case DGL_NAMESPACE::kKeyF6:
  173. return PROJECTM_K_F6;
  174. case DGL_NAMESPACE::kKeyF7:
  175. return PROJECTM_K_F7;
  176. case DGL_NAMESPACE::kKeyF8:
  177. return PROJECTM_K_F8;
  178. case DGL_NAMESPACE::kKeyF9:
  179. return PROJECTM_K_F9;
  180. case DGL_NAMESPACE::kKeyF10:
  181. return PROJECTM_K_F10;
  182. case DGL_NAMESPACE::kKeyF11:
  183. return PROJECTM_K_F11;
  184. case DGL_NAMESPACE::kKeyF12:
  185. return PROJECTM_K_F12;
  186. case DGL_NAMESPACE::kKeyLeft:
  187. return PROJECTM_K_LEFT;
  188. case DGL_NAMESPACE::kKeyUp:
  189. return PROJECTM_K_UP;
  190. case DGL_NAMESPACE::kKeyRight:
  191. return PROJECTM_K_RIGHT;
  192. case DGL_NAMESPACE::kKeyDown:
  193. return PROJECTM_K_DOWN;
  194. case DGL_NAMESPACE::kKeyPageUp:
  195. return PROJECTM_K_PAGEUP;
  196. case DGL_NAMESPACE::kKeyPageDown:
  197. return PROJECTM_K_PAGEDOWN;
  198. case DGL_NAMESPACE::kKeyHome:
  199. return PROJECTM_K_HOME;
  200. case DGL_NAMESPACE::kKeyEnd:
  201. return PROJECTM_K_END;
  202. case DGL_NAMESPACE::kKeyInsert:
  203. return PROJECTM_K_INSERT;
  204. case DGL_NAMESPACE::kKeyShiftL:
  205. return PROJECTM_K_LSHIFT;
  206. case DGL_NAMESPACE::kKeyShiftR:
  207. return PROJECTM_K_RSHIFT;
  208. case DGL_NAMESPACE::kKeyControlL:
  209. return PROJECTM_K_LCTRL;
  210. case DGL_NAMESPACE::kKeyControlR:
  211. case DGL_NAMESPACE::kKeyAltL:
  212. case DGL_NAMESPACE::kKeyAltR:
  213. case DGL_NAMESPACE::kKeySuperL:
  214. case DGL_NAMESPACE::kKeySuperR:
  215. case DGL_NAMESPACE::kKeyMenu:
  216. case DGL_NAMESPACE::kKeyCapsLock:
  217. case DGL_NAMESPACE::kKeyScrollLock:
  218. case DGL_NAMESPACE::kKeyNumLock:
  219. case DGL_NAMESPACE::kKeyPrintScreen:
  220. case DGL_NAMESPACE::kKeyPause:
  221. break;
  222. }
  223. return PROJECTM_K_NONE;
  224. }
  225. bool DistrhoUIProM::onKeyboard(const KeyboardEvent& ev)
  226. {
  227. if (fPM == nullptr)
  228. return false;
  229. #ifdef HAVE_PROJECTM_TEXT_FUNCTIONS
  230. // special handling for text
  231. if (fPM->isTextInputActive(true) && !ev.press)
  232. {
  233. if (ev.key >= ' ' && ev.key <= 'z')
  234. {
  235. std::string key;
  236. key += static_cast<char>(ev.key);
  237. fPM->setSearchText(key);
  238. return true;
  239. }
  240. else if (ev.key == DGL_NAMESPACE::kKeyBackspace)
  241. {
  242. fPM->deleteSearchText();
  243. return true;
  244. }
  245. }
  246. #endif
  247. projectMKeycode pmKey = PROJECTM_K_NONE;
  248. if (ev.key >= kKeyF1)
  249. {
  250. pmKey = dgl2pmkey(static_cast<DGL_NAMESPACE::Key>(ev.key));
  251. }
  252. else if ((ev.key >= PROJECTM_K_0 && ev.key <= PROJECTM_K_9) ||
  253. (ev.key >= PROJECTM_K_A && ev.key <= PROJECTM_K_Z) ||
  254. (ev.key >= PROJECTM_K_a && ev.key <= PROJECTM_K_z))
  255. {
  256. pmKey = static_cast<projectMKeycode>(ev.key);
  257. if (ev.key >= PROJECTM_K_A && ev.key <= PROJECTM_K_Z && (ev.mod & DGL_NAMESPACE::kModifierShift))
  258. pmKey = static_cast<projectMKeycode>(pmKey + (PROJECTM_K_a - PROJECTM_K_A));
  259. }
  260. else
  261. {
  262. /* missing:
  263. * PROJECTM_K_CAPSLOCK
  264. */
  265. switch (ev.key)
  266. {
  267. case DGL_NAMESPACE::kKeyBackspace:
  268. pmKey = PROJECTM_K_BACKSPACE;
  269. break;
  270. case DGL_NAMESPACE::kKeyEscape:
  271. pmKey = PROJECTM_K_ESCAPE;
  272. break;
  273. case DGL_NAMESPACE::kKeyDelete:
  274. pmKey = PROJECTM_K_DELETE;
  275. break;
  276. case '\r':
  277. pmKey = PROJECTM_K_RETURN;
  278. break;
  279. #ifdef HAVE_PROJECTM_TEXT_FUNCTIONS
  280. case '/':
  281. pmKey = PROJECTM_K_SLASH;
  282. break;
  283. case '\\':
  284. pmKey = PROJECTM_K_BACKSLASH;
  285. break;
  286. #endif
  287. case '+':
  288. pmKey = PROJECTM_K_PLUS;
  289. break;
  290. case '-':
  291. pmKey = PROJECTM_K_MINUS;
  292. break;
  293. case '=':
  294. pmKey = PROJECTM_K_EQUALS;
  295. break;
  296. default:
  297. // d_stdout("Unhandled key %u %u %c", ev.keycode, ev.key, ev.key);
  298. break;
  299. }
  300. }
  301. if (pmKey == PROJECTM_K_NONE)
  302. return false;
  303. fPM->default_key_handler(ev.press ? PROJECTM_KEYUP : PROJECTM_KEYDOWN, pmKey);
  304. return true;
  305. }
  306. // -----------------------------------------------------------------------
  307. UI* createUI()
  308. {
  309. return new DistrhoUIProM();
  310. }
  311. // -----------------------------------------------------------------------
  312. END_NAMESPACE_DISTRHO