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.

360 lines
9.1KB

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