Collection of tools useful for audio production
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.

339 lines
8.3KB

  1. /*
  2. * Carla Bridge Toolkit, Qt version
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #include "carla_bridge_client.hpp"
  18. #include "carla_bridge_toolkit.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(! msgTimer);
  86. if (window)
  87. {
  88. window->close();
  89. delete window;
  90. }
  91. #ifdef BRIDGE_CONTAINER
  92. // TESTING
  93. if (embedContainer)
  94. {
  95. embedContainer->close();
  96. delete embedContainer;
  97. }
  98. #endif
  99. }
  100. void init()
  101. {
  102. qDebug("CarlaBridgeToolkitQt::init()");
  103. CARLA_ASSERT(! app);
  104. CARLA_ASSERT(! window);
  105. CARLA_ASSERT(! msgTimer);
  106. app = new QApplication(qargc, qargv);
  107. window = new QMainWindow(nullptr);
  108. window->resize(30, 30);
  109. window->hide();
  110. }
  111. void exec(const bool showGui)
  112. {
  113. qDebug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showGui));
  114. CARLA_ASSERT(app);
  115. CARLA_ASSERT(window);
  116. CARLA_ASSERT(client);
  117. #if defined(BRIDGE_QT4) || defined(BRIDGE_QT5)
  118. QWidget* const widget = (QWidget*)client->getWidget();
  119. window->setCentralWidget(widget);
  120. window->adjustSize();
  121. widget->setParent(window);
  122. widget->show();
  123. #endif
  124. if (! client->isResizable())
  125. {
  126. window->setFixedSize(window->width(), window->height());
  127. #ifdef Q_OS_WIN
  128. window->setWindowFlags(window->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
  129. #endif
  130. }
  131. window->setWindowTitle(uiTitle);
  132. if (settings.contains(QString("%1/pos_x").arg(uiTitle)))
  133. {
  134. bool hasX, hasY;
  135. int posX = settings.value(QString("%1/pos_x").arg(uiTitle), window->x()).toInt(&hasX);
  136. int posY = settings.value(QString("%1/pos_y").arg(uiTitle), window->y()).toInt(&hasY);
  137. if (hasX && hasY)
  138. window->move(posX, posY);
  139. if (client->isResizable())
  140. {
  141. bool hasWidth, hasHeight;
  142. int width = settings.value(QString("%1/width").arg(uiTitle), window->width()).toInt(&hasWidth);
  143. int height = settings.value(QString("%1/height").arg(uiTitle), window->height()).toInt(&hasHeight);
  144. if (hasWidth && hasHeight)
  145. window->resize(width, height);
  146. }
  147. }
  148. if (showGui)
  149. show();
  150. else
  151. client->sendOscUpdate();
  152. // Timer
  153. msgTimer = startTimer(50);
  154. // First idle
  155. handleTimeout();
  156. // Main loop
  157. app->exec();
  158. }
  159. void quit()
  160. {
  161. qDebug("CarlaBridgeToolkitQt::quit()");
  162. CARLA_ASSERT(app);
  163. if (msgTimer != 0)
  164. {
  165. killTimer(msgTimer);
  166. msgTimer = 0;
  167. }
  168. if (window)
  169. {
  170. settings.setValue(QString("%1/pos_x").arg(uiTitle), window->x());
  171. settings.setValue(QString("%1/pos_y").arg(uiTitle), window->y());
  172. settings.setValue(QString("%1/width").arg(uiTitle), window->width());
  173. settings.setValue(QString("%1/height").arg(uiTitle), window->height());
  174. settings.sync();
  175. window->close();
  176. delete window;
  177. window = nullptr;
  178. }
  179. if (app)
  180. {
  181. if (! app->closingDown())
  182. app->quit();
  183. delete app;
  184. app = nullptr;
  185. }
  186. }
  187. void show()
  188. {
  189. qDebug("CarlaBridgeToolkitQt::show()");
  190. CARLA_ASSERT(window);
  191. if (window)
  192. window->show();
  193. }
  194. void hide()
  195. {
  196. qDebug("CarlaBridgeToolkitQt::hide()");
  197. CARLA_ASSERT(window);
  198. if (window)
  199. window->hide();
  200. }
  201. void resize(const int width, const int height)
  202. {
  203. qDebug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height);
  204. CARLA_ASSERT(window);
  205. if (app->thread() != QThread::currentThread())
  206. {
  207. nextWidth = width;
  208. nextHeight = height;
  209. needsResize = true;
  210. return;
  211. }
  212. if (window)
  213. window->setFixedSize(width, height);
  214. #ifdef BRIDGE_CONTAINER
  215. if (embedContainer)
  216. embedContainer->setFixedSize(width, height);
  217. #endif
  218. }
  219. #ifdef BRIDGE_CONTAINER
  220. void* getContainerId()
  221. {
  222. qDebug("CarlaBridgeToolkitQt::getContainerId()");
  223. CARLA_ASSERT(window);
  224. if (! embedContainer)
  225. {
  226. embedContainer = new QEmbedContainer(window);
  227. window->setCentralWidget(embedContainer);
  228. window->adjustSize();
  229. embedContainer->setParent(window);
  230. embedContainer->show();
  231. }
  232. return (void*)embedContainer->winId();
  233. }
  234. #endif
  235. protected:
  236. QApplication* app;
  237. QMainWindow* window;
  238. QSettings settings;
  239. int msgTimer;
  240. bool needsResize;
  241. int nextWidth, nextHeight;
  242. #ifdef BRIDGE_CONTAINER
  243. QEmbedContainer* embedContainer;
  244. #endif
  245. void handleTimeout()
  246. {
  247. if (! client)
  248. return;
  249. if (needsResize)
  250. {
  251. client->toolkitResize(nextWidth, nextHeight);
  252. needsResize = false;
  253. }
  254. if (client->isOscControlRegistered() && ! client->oscIdle())
  255. {
  256. killTimer(msgTimer);
  257. msgTimer = 0;
  258. }
  259. }
  260. private:
  261. void timerEvent(QTimerEvent* const event)
  262. {
  263. if (event->timerId() == msgTimer)
  264. handleTimeout();
  265. QObject::timerEvent(event);
  266. }
  267. };
  268. // -------------------------------------------------------------------------
  269. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const uiTitle)
  270. {
  271. return new CarlaBridgeToolkitQt(client, uiTitle);
  272. }
  273. CARLA_BRIDGE_END_NAMESPACE