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.

287 lines
7.6KB

  1. /*
  2. * Carla Bridge UI
  3. * Copyright (C) 2011-2017 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 doc/GPL.txt file.
  16. */
  17. #include "CarlaBridgeFormat.hpp"
  18. #include "CarlaBridgeToolkit.hpp"
  19. #include "CarlaStyle.hpp"
  20. #include <QtCore/QTimerEvent>
  21. #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
  22. # include <QtWidgets/QApplication>
  23. # include <QtWidgets/QMainWindow>
  24. #else
  25. # include <QtGui/QApplication>
  26. # include <QtGui/QMainWindow>
  27. # ifdef HAVE_X11
  28. # define USE_CUSTOM_X11_METHODS
  29. # include <QtGui/QX11Info>
  30. # include <X11/Xlib.h>
  31. # endif
  32. #endif
  33. CARLA_BRIDGE_UI_START_NAMESPACE
  34. // -------------------------------------------------------------------------
  35. static int qargc = 0;
  36. static char* qargv[0] = {};
  37. // -------------------------------------------------------------------------
  38. class CarlaBridgeToolkitQt: public QObject,
  39. public CarlaBridgeToolkit
  40. {
  41. #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) && defined(__clang_major__) && __clang_major__ >= 4
  42. # pragma clang diagnostic push
  43. # pragma clang diagnostic ignored "-Winconsistent-missing-override"
  44. #endif
  45. Q_OBJECT
  46. #if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) && defined(__clang_major__) && __clang_major__ >= 4
  47. # pragma clang diagnostic pop
  48. #endif
  49. public:
  50. CarlaBridgeToolkitQt(CarlaBridgeFormat* const format)
  51. : QObject(nullptr),
  52. CarlaBridgeToolkit(format),
  53. fApp(nullptr),
  54. fWindow(nullptr),
  55. fMsgTimer(0),
  56. fNeedsShow(false)
  57. {
  58. carla_debug("CarlaBridgeToolkitQt::CarlaBridgeToolkitQt(%p)", format);
  59. }
  60. ~CarlaBridgeToolkitQt() override
  61. {
  62. CARLA_SAFE_ASSERT(fApp == nullptr);
  63. CARLA_SAFE_ASSERT(fWindow == nullptr);
  64. CARLA_SAFE_ASSERT(fMsgTimer == 0);
  65. carla_debug("CarlaBridgeToolkitQt::~CarlaBridgeToolkitQt()");
  66. }
  67. bool init(const int /*argc*/, const char** /*argv[]*/) override
  68. {
  69. CARLA_SAFE_ASSERT_RETURN(fApp == nullptr, false);
  70. CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr, false);
  71. CARLA_SAFE_ASSERT_RETURN(fMsgTimer == 0, false);
  72. carla_debug("CarlaBridgeToolkitQt::init()");
  73. fApp = new QApplication(qargc, qargv);
  74. fWindow = new QMainWindow(nullptr);
  75. fWindow->resize(30, 30);
  76. fWindow->hide();
  77. return true;
  78. }
  79. void exec(const bool showUI) override
  80. {
  81. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  82. CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,);
  83. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  84. carla_debug("CarlaBridgeToolkitQt::exec(%s)", bool2str(showUI));
  85. const CarlaBridgeFormat::Options& options(fPlugin->getOptions());
  86. QWidget* const widget((QWidget*)fPlugin->getWidget());
  87. fWindow->setCentralWidget(widget);
  88. fWindow->adjustSize();
  89. widget->setParent(fWindow);
  90. widget->show();
  91. if (! options.isResizable)
  92. {
  93. fWindow->setFixedSize(fWindow->width(), fWindow->height());
  94. #ifdef CARLA_OS_WIN
  95. fWindow->setWindowFlags(fWindow->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
  96. #endif
  97. }
  98. fWindow->setWindowIcon(QIcon::fromTheme("carla", QIcon(":/scalable/carla.svg")));
  99. fWindow->setWindowTitle(options.windowTitle.buffer());
  100. #ifdef USE_CUSTOM_X11_METHODS
  101. if (options.transientWindowId != 0)
  102. {
  103. XSetTransientForHint(QX11Info::display(),
  104. static_cast< ::Window>(fWindow->winId()),
  105. static_cast< ::Window>(options.transientWindowId));
  106. }
  107. #endif
  108. if (showUI || fNeedsShow)
  109. {
  110. show();
  111. fNeedsShow = false;
  112. }
  113. fMsgTimer = startTimer(30);
  114. // First idle
  115. handleTimeout();
  116. // Main loop
  117. fApp->exec();
  118. }
  119. void quit() override
  120. {
  121. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  122. CARLA_SAFE_ASSERT_RETURN(fApp != nullptr,);
  123. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  124. carla_debug("CarlaBridgeToolkitQt::quit()");
  125. if (fMsgTimer != 0)
  126. {
  127. killTimer(fMsgTimer);
  128. fMsgTimer = 0;
  129. }
  130. if (fWindow != nullptr)
  131. {
  132. fWindow->close();
  133. delete fWindow;
  134. fWindow = nullptr;
  135. }
  136. if (fApp != nullptr)
  137. {
  138. if (! fApp->closingDown())
  139. fApp->quit();
  140. delete fApp;
  141. fApp = nullptr;
  142. }
  143. }
  144. void show() override
  145. {
  146. carla_debug("CarlaBridgeToolkitQt::show()");
  147. fNeedsShow = true;
  148. if (fWindow != nullptr)
  149. fWindow->show();
  150. }
  151. void focus() override
  152. {
  153. carla_debug("CarlaBridgeToolkitQt::focus()");
  154. }
  155. void hide() override
  156. {
  157. carla_debug("CarlaBridgeToolkitQt::hide()");
  158. fNeedsShow = false;
  159. if (fWindow != nullptr)
  160. fWindow->hide();
  161. }
  162. void setSize(const uint width, const uint height) override
  163. {
  164. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  165. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  166. CARLA_SAFE_ASSERT_RETURN(width > 0,);
  167. CARLA_SAFE_ASSERT_RETURN(height > 0,);
  168. carla_debug("CarlaBridgeToolkitQt::resize(%i, %i)", width, height);
  169. if (fPlugin->getOptions().isResizable)
  170. fWindow->resize(static_cast<int>(width), static_cast<int>(height));
  171. else
  172. fWindow->setFixedSize(static_cast<int>(width), static_cast<int>(height));
  173. }
  174. void setTitle(const char* const title) override
  175. {
  176. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  177. CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0',);
  178. carla_debug("CarlaBridgeToolkitQt::setTitle(\"%s\")", title);
  179. fWindow->setWindowTitle(title);
  180. }
  181. protected:
  182. QApplication* fApp;
  183. QMainWindow* fWindow;
  184. int fMsgTimer;
  185. bool fNeedsShow;
  186. void handleTimeout()
  187. {
  188. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  189. if (fPlugin->isPipeRunning())
  190. fPlugin->idlePipe();
  191. fPlugin->idleUI();
  192. }
  193. private:
  194. void timerEvent(QTimerEvent* const ev) override
  195. {
  196. if (ev->timerId() == fMsgTimer)
  197. handleTimeout();
  198. QObject::timerEvent(ev);
  199. }
  200. #ifndef MOC_PARSING
  201. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitQt)
  202. #endif
  203. };
  204. #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
  205. # include "CarlaBridgeToolkitQt5.moc"
  206. #else
  207. # include "CarlaBridgeToolkitQt4.moc"
  208. #endif
  209. // -------------------------------------------------------------------------
  210. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeFormat* const format)
  211. {
  212. return new CarlaBridgeToolkitQt(format);
  213. }
  214. // -------------------------------------------------------------------------
  215. CARLA_BRIDGE_UI_END_NAMESPACE
  216. // -------------------------------------------------------------------------
  217. // missing declaration
  218. int qInitResources();
  219. int qCleanupResources();
  220. #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
  221. # include "resources.qt5.cpp"
  222. #else
  223. # include "resources.qt4.cpp"
  224. #endif
  225. // -------------------------------------------------------------------------