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.

244 lines
6.9KB

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