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.

249 lines
7.0KB

  1. /*
  2. * Carla Bridge Toolkit, Gtk version
  3. * Copyright (C) 2011-2014 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. #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
  20. # error Embed UI uses Qt
  21. #endif
  22. #include <gtk/gtk.h>
  23. #include <QtCore/QSettings>
  24. CARLA_BRIDGE_START_NAMESPACE
  25. // -------------------------------------------------------------------------
  26. #if defined(BRIDGE_GTK2)
  27. static const char* const appName = "Carla-Gtk2UIs";
  28. #elif defined(BRIDGE_GTK3)
  29. static const char* const appName = "Carla-Gtk3UIs";
  30. #else
  31. static const char* const appName = "Carla-UIs";
  32. #endif
  33. static int gargc = 0;
  34. static char** gargv = nullptr;
  35. // -------------------------------------------------------------------------
  36. class CarlaToolkitGtk : public CarlaBridgeToolkit
  37. {
  38. public:
  39. CarlaToolkitGtk(CarlaBridgeClient* const client, const char* const uiTitle)
  40. : CarlaBridgeToolkit(client, uiTitle),
  41. fNeedsShow(false),
  42. fWindow(nullptr),
  43. fLastX(0),
  44. fLastY(0),
  45. fLastWidth(0),
  46. fLastHeight(0)
  47. {
  48. carla_debug("CarlaToolkitGtk::CarlaToolkitGtk(%p, \"%s\")", client, uiTitle);
  49. }
  50. ~CarlaToolkitGtk() override
  51. {
  52. CARLA_ASSERT(fWindow == nullptr);
  53. carla_debug("CarlaToolkitGtk::~CarlaToolkitGtk()");
  54. }
  55. void init() override
  56. {
  57. CARLA_ASSERT(fWindow == nullptr);
  58. carla_debug("CarlaToolkitGtk::init()");
  59. gtk_init(&gargc, &gargv);
  60. fWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  61. gtk_window_resize(GTK_WINDOW(fWindow), 30, 30);
  62. gtk_widget_hide(fWindow);
  63. }
  64. void exec(const bool showGui) override
  65. {
  66. CARLA_ASSERT(kClient != nullptr);
  67. CARLA_ASSERT(fWindow != nullptr);
  68. carla_debug("CarlaToolkitGtk::exec(%s)", bool2str(showGui));
  69. GtkWidget* const widget((GtkWidget*)kClient->getWidget());
  70. gtk_container_add(GTK_CONTAINER(fWindow), widget);
  71. gtk_window_set_resizable(GTK_WINDOW(fWindow), kClient->isResizable());
  72. gtk_window_set_title(GTK_WINDOW(fWindow), kUiTitle);
  73. {
  74. QSettings settings("falkTX", appName);
  75. if (settings.contains(QString("%1/pos_x").arg(kUiTitle)))
  76. {
  77. gtk_window_get_position(GTK_WINDOW(fWindow), &fLastX, &fLastY);
  78. bool hasX, hasY;
  79. fLastX = settings.value(QString("%1/pos_x").arg(kUiTitle), fLastX).toInt(&hasX);
  80. fLastY = settings.value(QString("%1/pos_y").arg(kUiTitle), fLastY).toInt(&hasY);
  81. if (hasX && hasY)
  82. gtk_window_move(GTK_WINDOW(fWindow), fLastX, fLastY);
  83. if (kClient->isResizable())
  84. {
  85. gtk_window_get_size(GTK_WINDOW(fWindow), &fLastWidth, &fLastHeight);
  86. bool hasWidth, hasHeight;
  87. fLastWidth = settings.value(QString("%1/width").arg(kUiTitle), fLastWidth).toInt(&hasWidth);
  88. fLastHeight = settings.value(QString("%1/height").arg(kUiTitle), fLastHeight).toInt(&hasHeight);
  89. if (hasWidth && hasHeight)
  90. gtk_window_resize(GTK_WINDOW(fWindow), fLastWidth, fLastHeight);
  91. }
  92. }
  93. if (settings.value("Engine/UIsAlwaysOnTop", true).toBool())
  94. gtk_window_set_keep_above(GTK_WINDOW(fWindow), true);
  95. }
  96. if (showGui || fNeedsShow)
  97. {
  98. show();
  99. fNeedsShow = false;
  100. }
  101. g_timeout_add(30, gtk_ui_timeout, this);
  102. g_signal_connect(fWindow, "destroy", G_CALLBACK(gtk_ui_destroy), this);
  103. // First idle
  104. handleTimeout();
  105. // Main loop
  106. gtk_main();
  107. }
  108. void quit() override
  109. {
  110. carla_debug("CarlaToolkitGtk::quit()");
  111. if (fWindow != nullptr)
  112. {
  113. gtk_widget_destroy(fWindow);
  114. fWindow = nullptr;
  115. if (gtk_main_level() != 0)
  116. gtk_main_quit();
  117. }
  118. }
  119. void show() override
  120. {
  121. carla_debug("CarlaToolkitGtk::show()");
  122. fNeedsShow = true;
  123. if (fWindow != nullptr)
  124. gtk_widget_show_all(fWindow);
  125. }
  126. void hide() override
  127. {
  128. carla_debug("CarlaToolkitGtk::hide()");
  129. fNeedsShow = false;
  130. if (fWindow != nullptr)
  131. gtk_widget_hide(fWindow);
  132. }
  133. void resize(int width, int height) override
  134. {
  135. CARLA_ASSERT(fWindow != nullptr);
  136. carla_debug("CarlaToolkitGtk::resize(%i, %i)", width, height);
  137. if (fWindow != nullptr)
  138. gtk_window_resize(GTK_WINDOW(fWindow), width, height);
  139. }
  140. // ---------------------------------------------------------------------
  141. protected:
  142. bool fNeedsShow;
  143. GtkWidget* fWindow;
  144. gint fLastX;
  145. gint fLastY;
  146. gint fLastWidth;
  147. gint fLastHeight;
  148. void handleDestroy()
  149. {
  150. carla_debug("CarlaToolkitGtk::handleDestroy()");
  151. fWindow = nullptr;
  152. QSettings settings("falkTX", appName);
  153. settings.setValue(QString("%1/pos_x").arg(kUiTitle), fLastX);
  154. settings.setValue(QString("%1/pos_y").arg(kUiTitle), fLastY);
  155. settings.setValue(QString("%1/width").arg(kUiTitle), fLastWidth);
  156. settings.setValue(QString("%1/height").arg(kUiTitle), fLastHeight);
  157. }
  158. gboolean handleTimeout()
  159. {
  160. if (fWindow != nullptr)
  161. {
  162. gtk_window_get_position(GTK_WINDOW(fWindow), &fLastX, &fLastY);
  163. gtk_window_get_size(GTK_WINDOW(fWindow), &fLastWidth, &fLastHeight);
  164. }
  165. kClient->uiIdle();
  166. return kClient->oscIdle();
  167. }
  168. // ---------------------------------------------------------------------
  169. private:
  170. static void gtk_ui_destroy(GtkWidget*, gpointer data)
  171. {
  172. CARLA_ASSERT(data != nullptr);
  173. if (CarlaToolkitGtk* const _this_ = (CarlaToolkitGtk*)data)
  174. _this_->handleDestroy();
  175. gtk_main_quit();
  176. }
  177. static gboolean gtk_ui_timeout(gpointer data)
  178. {
  179. CARLA_ASSERT(data != nullptr);
  180. if (CarlaToolkitGtk* const _this_ = (CarlaToolkitGtk*)data)
  181. return _this_->handleTimeout();
  182. return false;
  183. }
  184. };
  185. // -------------------------------------------------------------------------
  186. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeClient* const client, const char* const uiTitle)
  187. {
  188. return new CarlaToolkitGtk(client, uiTitle);
  189. }
  190. CARLA_BRIDGE_END_NAMESPACE