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.

362 lines
9.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 "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. #if 0
  96. {
  97. QSettings settings("falkTX", "Carla");
  98. if (settings.value("Main/UseProTheme", true).toBool())
  99. {
  100. CarlaStyle* const style(new CarlaStyle());
  101. app->setStyle(style);
  102. style->ready(app);
  103. QString color(settings.value("Main/ProThemeColor", "Black").toString());
  104. if (color == "System")
  105. pass(); //style->setColorScheme(CarlaStyle::COLOR_SYSTEM);
  106. else
  107. style->setColorScheme(CarlaStyle::COLOR_BLACK);
  108. }
  109. }
  110. #endif
  111. window = new QMainWindow(nullptr);
  112. window->resize(30, 30);
  113. window->hide();
  114. }
  115. void exec(const bool showGui) override
  116. {
  117. CARLA_ASSERT(app);
  118. CARLA_ASSERT(window);
  119. CARLA_ASSERT(kClient);
  120. carla_debug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showGui));
  121. #if defined(BRIDGE_QT4) || defined(BRIDGE_QT5)
  122. QWidget* const widget = (QWidget*)kClient->getWidget();
  123. window->setCentralWidget(widget);
  124. window->adjustSize();
  125. widget->setParent(window);
  126. widget->show();
  127. #endif
  128. if (! kClient->isResizable())
  129. {
  130. window->setFixedSize(window->width(), window->height());
  131. #ifdef Q_OS_WIN
  132. window->setWindowFlags(window->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
  133. #endif
  134. }
  135. window->setWindowTitle(kUiTitle);
  136. {
  137. QSettings settings("falkTX", appName);
  138. if (settings.contains(QString("%1/pos_x").arg(kUiTitle)))
  139. {
  140. bool hasX, hasY;
  141. int posX = settings.value(QString("%1/pos_x").arg(kUiTitle), window->x()).toInt(&hasX);
  142. int posY = settings.value(QString("%1/pos_y").arg(kUiTitle), window->y()).toInt(&hasY);
  143. if (hasX && hasY)
  144. window->move(posX, posY);
  145. if (kClient->isResizable())
  146. {
  147. bool hasWidth, hasHeight;
  148. int width = settings.value(QString("%1/width").arg(kUiTitle), window->width()).toInt(&hasWidth);
  149. int height = settings.value(QString("%1/height").arg(kUiTitle), window->height()).toInt(&hasHeight);
  150. if (hasWidth && hasHeight)
  151. window->resize(width, height);
  152. }
  153. }
  154. }
  155. if (showGui)
  156. show();
  157. else
  158. kClient->sendOscUpdate();
  159. // Timer
  160. msgTimer = startTimer(50);
  161. // First idle
  162. handleTimeout();
  163. // Main loop
  164. app->exec();
  165. }
  166. void quit() override
  167. {
  168. CARLA_ASSERT(app);
  169. carla_debug("CarlaBridgeToolkitQt::quit()");
  170. if (msgTimer != 0)
  171. {
  172. killTimer(msgTimer);
  173. msgTimer = 0;
  174. }
  175. if (window != nullptr)
  176. {
  177. QSettings settings("falkTX", appName);
  178. settings.setValue(QString("%1/pos_x").arg(kUiTitle), window->x());
  179. settings.setValue(QString("%1/pos_y").arg(kUiTitle), window->y());
  180. settings.setValue(QString("%1/width").arg(kUiTitle), window->width());
  181. settings.setValue(QString("%1/height").arg(kUiTitle), window->height());
  182. settings.sync();
  183. window->close();
  184. }
  185. #ifdef BRIDGE_CONTAINER
  186. if (embedContainer != nullptr)
  187. {
  188. embedContainer->close();
  189. delete embedContainer;
  190. embedContainer = nullptr;
  191. }
  192. #endif
  193. if (window != nullptr)
  194. {
  195. delete window;
  196. window = nullptr;
  197. }
  198. if (app)
  199. {
  200. if (! app->closingDown())
  201. app->quit();
  202. delete app;
  203. app = nullptr;
  204. }
  205. }
  206. void show() override
  207. {
  208. CARLA_ASSERT(window);
  209. carla_debug("CarlaBridgeToolkitQt::show()");
  210. if (window)
  211. window->show();
  212. }
  213. void hide() override
  214. {
  215. CARLA_ASSERT(window);
  216. carla_debug("CarlaBridgeToolkitQt::hide()");
  217. if (window)
  218. window->hide();
  219. }
  220. void resize(const int width, const int height) override
  221. {
  222. CARLA_ASSERT(window);
  223. carla_debug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height);
  224. if (app->thread() != QThread::currentThread())
  225. {
  226. nextWidth = width;
  227. nextHeight = height;
  228. needsResize = true;
  229. return;
  230. }
  231. if (window)
  232. window->setFixedSize(width, height);
  233. #ifdef BRIDGE_CONTAINER
  234. if (embedContainer)
  235. embedContainer->setFixedSize(width, height);
  236. #endif
  237. }
  238. #ifdef BRIDGE_CONTAINER
  239. void* getContainerId()
  240. {
  241. CARLA_ASSERT(window != nullptr);
  242. carla_debug("CarlaBridgeToolkitQt::getContainerId()");
  243. if (embedContainer == nullptr)
  244. {
  245. embedContainer = new QEmbedContainer(window);
  246. window->setCentralWidget(embedContainer);
  247. window->adjustSize();
  248. embedContainer->setParent(window);
  249. embedContainer->show();
  250. }
  251. return (void*)embedContainer->winId();
  252. }
  253. #endif
  254. protected:
  255. QApplication* app;
  256. QMainWindow* window;
  257. int msgTimer;
  258. bool needsResize;
  259. int nextWidth, nextHeight;
  260. #ifdef BRIDGE_CONTAINER
  261. QEmbedContainer* embedContainer;
  262. #endif
  263. void handleTimeout()
  264. {
  265. if (! kClient)
  266. return;
  267. if (needsResize)
  268. {
  269. kClient->toolkitResize(nextWidth, nextHeight);
  270. needsResize = false;
  271. }
  272. if (kClient->isOscControlRegistered() && ! kClient->oscIdle())
  273. {
  274. killTimer(msgTimer);
  275. msgTimer = 0;
  276. }
  277. }
  278. private:
  279. void timerEvent(QTimerEvent* const event)
  280. {
  281. if (event->timerId() == msgTimer)
  282. handleTimeout();
  283. QObject::timerEvent(event);
  284. }
  285. };
  286. // -------------------------------------------------------------------------
  287. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const uiTitle)
  288. {
  289. return new CarlaBridgeToolkitQt(client, uiTitle);
  290. }
  291. CARLA_BRIDGE_END_NAMESPACE