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.

335 lines
8.2KB

  1. /*
  2. * Carla Bridge Toolkit, Qt version
  3. * Copyright (C) 2011-2013 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 GPL.txt file
  16. */
  17. #include "CarlaBridgeClient.hpp"
  18. #include "CarlaBridgeToolkit.hpp"
  19. #include <QtCore/QSettings>
  20. #include <QtCore/QThread>
  21. #include <QtCore/QTimerEvent>
  22. #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
  23. # include <QtWidgets/QApplication>
  24. # include <QtWidgets/QMainWindow>
  25. # ifdef Q_WS_X11
  26. # undef Q_WS_X11
  27. # endif
  28. #else
  29. # include <QtGui/QApplication>
  30. # include <QtGui/QMainWindow>
  31. # ifdef Q_WS_X11
  32. # include <QtGui/QX11EmbedContainer>
  33. # endif
  34. #endif
  35. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  36. # define BRIDGE_CONTAINER
  37. # ifdef Q_WS_X11
  38. typedef QX11EmbedContainer QEmbedContainer;
  39. # else
  40. typedef QWidget QEmbedContainer;
  41. # endif
  42. #endif
  43. CARLA_BRIDGE_START_NAMESPACE
  44. // -------------------------------------------------------------------------
  45. #if defined(BRIDGE_QT4)
  46. static const char* const appName = "Carla-Qt4UIs";
  47. #elif defined(BRIDGE_QT5)
  48. static const char* const appName = "Carla-Qt5UIs";
  49. #elif defined(BRIDGE_COCOA)
  50. static const char* const appName = "Carla-CocoaUIs";
  51. #elif defined(BRIDGE_HWND)
  52. static const char* const appName = "Carla-HWNDUIs";
  53. #elif defined(BRIDGE_X11)
  54. static const char* const appName = "Carla-X11UIs";
  55. #else
  56. static const char* const appName = "Carla-UIs";
  57. #endif
  58. static int qargc = 0;
  59. static char* qargv[0] = {};
  60. // -------------------------------------------------------------------------
  61. class CarlaBridgeToolkitQt: public CarlaBridgeToolkit,
  62. public QObject
  63. {
  64. public:
  65. CarlaBridgeToolkitQt(CarlaBridgeClient* const client, const char* const uiTitle)
  66. : CarlaBridgeToolkit(client, uiTitle),
  67. QObject(nullptr),
  68. settings("Cadence", appName)
  69. {
  70. qDebug("CarlaBridgeToolkitQt::CarlaBridgeToolkitQt(%p, \"%s\")", client, uiTitle);
  71. app = nullptr;
  72. window = nullptr;
  73. msgTimer = 0;
  74. needsResize = false;
  75. nextWidth = 0;
  76. nextHeight = 0;
  77. #ifdef BRIDGE_CONTAINER
  78. embedContainer = nullptr;
  79. #endif
  80. }
  81. ~CarlaBridgeToolkitQt()
  82. {
  83. qDebug("CarlaBridgeToolkitQt::~CarlaBridgeToolkitQt()");
  84. CARLA_ASSERT(! app);
  85. CARLA_ASSERT(! window);
  86. CARLA_ASSERT(! msgTimer);
  87. }
  88. void init()
  89. {
  90. qDebug("CarlaBridgeToolkitQt::init()");
  91. CARLA_ASSERT(! app);
  92. CARLA_ASSERT(! window);
  93. CARLA_ASSERT(! msgTimer);
  94. app = new QApplication(qargc, qargv);
  95. window = new QMainWindow(nullptr);
  96. window->resize(30, 30);
  97. window->hide();
  98. }
  99. void exec(const bool showGui)
  100. {
  101. qDebug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showGui));
  102. CARLA_ASSERT(app);
  103. CARLA_ASSERT(window);
  104. CARLA_ASSERT(kClient);
  105. #if defined(BRIDGE_QT4) || defined(BRIDGE_QT5)
  106. QWidget* const widget = (QWidget*)kClient->getWidget();
  107. window->setCentralWidget(widget);
  108. window->adjustSize();
  109. widget->setParent(window);
  110. widget->show();
  111. #endif
  112. if (! kClient->isResizable())
  113. {
  114. window->setFixedSize(window->width(), window->height());
  115. #ifdef Q_OS_WIN
  116. window->setWindowFlags(window->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
  117. #endif
  118. }
  119. window->setWindowTitle(kUiTitle);
  120. if (settings.contains(QString("%1/pos_x").arg(kUiTitle)))
  121. {
  122. bool hasX, hasY;
  123. int posX = settings.value(QString("%1/pos_x").arg(kUiTitle), window->x()).toInt(&hasX);
  124. int posY = settings.value(QString("%1/pos_y").arg(kUiTitle), window->y()).toInt(&hasY);
  125. if (hasX && hasY)
  126. window->move(posX, posY);
  127. if (kClient->isResizable())
  128. {
  129. bool hasWidth, hasHeight;
  130. int width = settings.value(QString("%1/width").arg(kUiTitle), window->width()).toInt(&hasWidth);
  131. int height = settings.value(QString("%1/height").arg(kUiTitle), window->height()).toInt(&hasHeight);
  132. if (hasWidth && hasHeight)
  133. window->resize(width, height);
  134. }
  135. }
  136. if (showGui)
  137. show();
  138. else
  139. kClient->sendOscUpdate();
  140. // Timer
  141. msgTimer = startTimer(50);
  142. // First idle
  143. handleTimeout();
  144. // Main loop
  145. app->exec();
  146. }
  147. void quit()
  148. {
  149. qDebug("CarlaBridgeToolkitQt::quit()");
  150. CARLA_ASSERT(app);
  151. if (msgTimer != 0)
  152. {
  153. killTimer(msgTimer);
  154. msgTimer = 0;
  155. }
  156. if (window)
  157. {
  158. settings.setValue(QString("%1/pos_x").arg(kUiTitle), window->x());
  159. settings.setValue(QString("%1/pos_y").arg(kUiTitle), window->y());
  160. settings.setValue(QString("%1/width").arg(kUiTitle), window->width());
  161. settings.setValue(QString("%1/height").arg(kUiTitle), window->height());
  162. settings.sync();
  163. window->close();
  164. delete window;
  165. window = nullptr;
  166. }
  167. #ifdef BRIDGE_CONTAINER
  168. if (embedContainer)
  169. {
  170. embedContainer->close();
  171. delete embedContainer;
  172. embedContainer = nullptr;
  173. }
  174. #endif
  175. if (app)
  176. {
  177. if (! app->closingDown())
  178. app->quit();
  179. delete app;
  180. app = nullptr;
  181. }
  182. }
  183. void show()
  184. {
  185. qDebug("CarlaBridgeToolkitQt::show()");
  186. CARLA_ASSERT(window);
  187. if (window)
  188. window->show();
  189. }
  190. void hide()
  191. {
  192. qDebug("CarlaBridgeToolkitQt::hide()");
  193. CARLA_ASSERT(window);
  194. if (window)
  195. window->hide();
  196. }
  197. void resize(const int width, const int height)
  198. {
  199. qDebug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height);
  200. CARLA_ASSERT(window);
  201. if (app->thread() != QThread::currentThread())
  202. {
  203. nextWidth = width;
  204. nextHeight = height;
  205. needsResize = true;
  206. return;
  207. }
  208. if (window)
  209. window->setFixedSize(width, height);
  210. #ifdef BRIDGE_CONTAINER
  211. if (embedContainer)
  212. embedContainer->setFixedSize(width, height);
  213. #endif
  214. }
  215. #ifdef BRIDGE_CONTAINER
  216. void* getContainerId()
  217. {
  218. qDebug("CarlaBridgeToolkitQt::getContainerId()");
  219. CARLA_ASSERT(window);
  220. if (! embedContainer)
  221. {
  222. embedContainer = new QEmbedContainer(window);
  223. window->setCentralWidget(embedContainer);
  224. window->adjustSize();
  225. embedContainer->setParent(window);
  226. embedContainer->show();
  227. }
  228. return (void*)embedContainer->winId();
  229. }
  230. #endif
  231. protected:
  232. QApplication* app;
  233. QMainWindow* window;
  234. QSettings settings;
  235. int msgTimer;
  236. bool needsResize;
  237. int nextWidth, nextHeight;
  238. #ifdef BRIDGE_CONTAINER
  239. QEmbedContainer* embedContainer;
  240. #endif
  241. void handleTimeout()
  242. {
  243. if (! kClient)
  244. return;
  245. if (needsResize)
  246. {
  247. kClient->toolkitResize(nextWidth, nextHeight);
  248. needsResize = false;
  249. }
  250. if (kClient->isOscControlRegistered() && ! kClient->oscIdle())
  251. {
  252. killTimer(msgTimer);
  253. msgTimer = 0;
  254. }
  255. }
  256. private:
  257. void timerEvent(QTimerEvent* const event)
  258. {
  259. if (event->timerId() == msgTimer)
  260. handleTimeout();
  261. QObject::timerEvent(event);
  262. }
  263. };
  264. // -------------------------------------------------------------------------
  265. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const uiTitle)
  266. {
  267. return new CarlaBridgeToolkitQt(client, uiTitle);
  268. }
  269. CARLA_BRIDGE_END_NAMESPACE