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.

CarlaBridgeToolkitGtk.cpp 17KB

11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
3 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * Carla Bridge UI
  3. * Copyright (C) 2011-2021 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 "CarlaLibUtils.hpp"
  20. #ifdef HAVE_X11
  21. # include <X11/Xlib.h>
  22. #endif
  23. struct GtkHandle;
  24. enum GtkWidgetType {
  25. GTK_WINDOW_TOPLEVEL
  26. };
  27. typedef ulong (*gsym_signal_connect_data)(void* instance,
  28. const char* detailed_signal,
  29. void (*c_handler)(GtkHandle*, void* data),
  30. void* data,
  31. void* destroy_data,
  32. int connect_flags);
  33. typedef uint (*gsym_timeout_add)(uint interval, int (*function)(void* user_data), void* data);
  34. typedef void (*gtksym_init)(int* argc, char*** argv);
  35. typedef void (*gtksym_main)(void);
  36. typedef uint (*gtksym_main_level)(void);
  37. typedef void (*gtksym_main_quit)(void);
  38. typedef void (*gtksym_container_add)(GtkHandle* container, GtkHandle* widget);
  39. typedef void (*gtksym_widget_destroy)(GtkHandle* widget);
  40. typedef void (*gtksym_widget_hide)(GtkHandle* widget);
  41. typedef void (*gtksym_widget_show_all)(GtkHandle* widget);
  42. typedef GtkHandle* (*gtksym_window_new)(GtkWidgetType type);
  43. typedef void (*gtksym_window_get_position)(GtkHandle* window, int* root_x, int* root_y);
  44. typedef void (*gtksym_window_get_size)(GtkHandle* window, int* width, int* height);
  45. typedef void (*gtksym_window_resize)(GtkHandle* window, int width, int height);
  46. typedef void (*gtksym_window_set_resizable)(GtkHandle* window, int resizable);
  47. typedef void (*gtksym_window_set_title)(GtkHandle* window, const char* title);
  48. #ifdef HAVE_X11
  49. typedef GtkHandle* (*gtksym_widget_get_window)(GtkHandle* widget);
  50. # ifdef BRIDGE_GTK3
  51. typedef GtkHandle* (*gdksym_window_get_display)(GtkHandle* window);
  52. typedef Display* (*gdksym_x11_display_get_xdisplay)(GtkHandle* display);
  53. typedef Window (*gdksym_x11_window_get_xid)(GtkHandle* window);
  54. # else
  55. typedef Display* (*gdksym_x11_drawable_get_xdisplay)(GtkHandle* drawable);
  56. typedef XID (*gdksym_x11_drawable_get_xid)(GtkHandle* drawable);
  57. # endif
  58. #endif
  59. CARLA_BRIDGE_UI_START_NAMESPACE
  60. // -------------------------------------------------------------------------
  61. struct GtkLoader {
  62. lib_t lib;
  63. #ifdef CARLA_OS_WIN
  64. lib_t glib;
  65. lib_t golib;
  66. #endif
  67. gsym_timeout_add timeout_add;
  68. gsym_signal_connect_data signal_connect_data;
  69. gtksym_init init;
  70. gtksym_main main;
  71. gtksym_main_level main_level;
  72. gtksym_main_quit main_quit;
  73. gtksym_container_add container_add;
  74. gtksym_widget_destroy widget_destroy;
  75. gtksym_widget_hide widget_hide;
  76. gtksym_widget_show_all widget_show_all;
  77. gtksym_window_new window_new;
  78. gtksym_window_get_position window_get_position;
  79. gtksym_window_get_size window_get_size;
  80. gtksym_window_resize window_resize;
  81. gtksym_window_set_resizable window_set_resizable;
  82. gtksym_window_set_title window_set_title;
  83. bool ok;
  84. #ifdef HAVE_X11
  85. gtksym_widget_get_window widget_get_window;
  86. # ifdef BRIDGE_GTK3
  87. gdksym_window_get_display window_get_display;
  88. gdksym_x11_display_get_xdisplay x11_display_get_xdisplay;
  89. gdksym_x11_window_get_xid x11_window_get_xid;
  90. # else
  91. gdksym_x11_drawable_get_xdisplay x11_drawable_get_xdisplay;
  92. gdksym_x11_drawable_get_xid x11_drawable_get_xid;
  93. # endif
  94. #endif
  95. GtkLoader()
  96. : lib(nullptr),
  97. #ifdef CARLA_OS_WIN
  98. glib(nullptr),
  99. golib(nullptr),
  100. #endif
  101. timeout_add(nullptr),
  102. signal_connect_data(nullptr),
  103. init(nullptr),
  104. main(nullptr),
  105. main_level(nullptr),
  106. main_quit(nullptr),
  107. container_add(nullptr),
  108. widget_destroy(nullptr),
  109. widget_hide(nullptr),
  110. widget_show_all(nullptr),
  111. window_new(nullptr),
  112. window_get_position(nullptr),
  113. window_get_size(nullptr),
  114. window_resize(nullptr),
  115. window_set_resizable(nullptr),
  116. window_set_title(nullptr),
  117. ok(false)
  118. #ifdef HAVE_X11
  119. , widget_get_window(nullptr),
  120. # ifdef BRIDGE_GTK3
  121. window_get_display(nullptr),
  122. x11_display_get_xdisplay(nullptr),
  123. x11_window_get_xid(nullptr)
  124. # else
  125. x11_drawable_get_xdisplay(nullptr),
  126. x11_drawable_get_xid(nullptr)
  127. # endif
  128. #endif
  129. {
  130. const char* filename;
  131. const char* const filenames[] = {
  132. #ifdef BRIDGE_GTK3
  133. # if defined(CARLA_OS_MAC)
  134. "libgtk-3.0.dylib",
  135. # elif defined(CARLA_OS_WIN)
  136. "libgtk-3-0.dll",
  137. # else
  138. "libgtk-3.so.0",
  139. # endif
  140. #else
  141. # if defined(CARLA_OS_MAC)
  142. "libgtk-quartz-2.0.dylib",
  143. "libgtk-x11-2.0.dylib",
  144. "/opt/homebrew/opt/gtk+/lib/libgtk-quartz-2.0.0.dylib",
  145. "/opt/local/lib/libgtk-quartz-2.0.dylib",
  146. "/opt/local/lib/libgtk-x11-2.0.dylib",
  147. # elif defined(CARLA_OS_WIN)
  148. "libgtk-win32-2.0-0.dll",
  149. # ifdef CARLA_OS_WIN64
  150. "C:\\msys64\\mingw64\\bin\\libgtk-win32-2.0-0.dll",
  151. # else
  152. "C:\\msys64\\mingw32\\bin\\libgtk-win32-2.0-0.dll",
  153. # endif
  154. # else
  155. "libgtk-x11-2.0.so.0",
  156. # endif
  157. #endif
  158. };
  159. for (size_t i=0; i<sizeof(filenames)/sizeof(filenames[0]); ++i)
  160. {
  161. filename = filenames[i];
  162. if ((lib = lib_open(filename, true)) != nullptr)
  163. break;
  164. }
  165. if (lib == nullptr)
  166. {
  167. fprintf(stderr, "Failed to load Gtk, reason:\n%s\n", lib_error(filename));
  168. return;
  169. }
  170. else
  171. {
  172. fprintf(stdout, "%s loaded successfully!\n", filename);
  173. }
  174. #ifdef CARLA_OS_WIN
  175. const char* gfilename;
  176. const char* const gfilenames[] = {
  177. "libglib-2.0-0.dll",
  178. # ifdef CARLA_OS_WIN64
  179. "C:\\msys64\\mingw64\\bin\\libglib-2.0-0.dll",
  180. # else
  181. "C:\\msys64\\mingw32\\bin\\libglib-2.0-0.dll",
  182. # endif
  183. };
  184. for (size_t i=0; i<sizeof(gfilenames)/sizeof(gfilenames[0]); ++i)
  185. {
  186. gfilename = gfilenames[i];
  187. if ((glib = lib_open(gfilename, true)) != nullptr)
  188. break;
  189. }
  190. if (glib == nullptr)
  191. {
  192. fprintf(stderr, "Failed to load glib, reason:\n%s\n", lib_error(gfilename));
  193. return;
  194. }
  195. else
  196. {
  197. fprintf(stdout, "%s loaded successfully!\n", gfilename);
  198. }
  199. const char* gofilename;
  200. const char* const gofilenames[] = {
  201. "libgobject-2.0-0.dll",
  202. # ifdef CARLA_OS_WIN64
  203. "C:\\msys64\\mingw64\\bin\\libgobject-2.0-0.dll",
  204. # else
  205. "C:\\msys64\\mingw32\\bin\\libgobject-2.0-0.dll",
  206. # endif
  207. };
  208. for (size_t i=0; i<sizeof(gofilenames)/sizeof(gofilenames[0]); ++i)
  209. {
  210. gofilename = gofilenames[i];
  211. if ((golib = lib_open(gofilename, true)) != nullptr)
  212. break;
  213. }
  214. if (golib == nullptr)
  215. {
  216. fprintf(stderr, "Failed to load gobject, reason:\n%s\n", lib_error(gofilename));
  217. return;
  218. }
  219. else
  220. {
  221. fprintf(stdout, "%s loaded successfully!\n", gofilename);
  222. }
  223. #define G_LIB_SYMBOL(NAME) \
  224. NAME = lib_symbol<gsym_##NAME>(glib, "g_" #NAME); \
  225. CARLA_SAFE_ASSERT_RETURN(NAME != nullptr,);
  226. #define GO_LIB_SYMBOL(NAME) \
  227. NAME = lib_symbol<gsym_##NAME>(golib, "g_" #NAME); \
  228. CARLA_SAFE_ASSERT_RETURN(NAME != nullptr,);
  229. #else
  230. #define G_LIB_SYMBOL(NAME) \
  231. NAME = lib_symbol<gsym_##NAME>(lib, "g_" #NAME); \
  232. CARLA_SAFE_ASSERT_RETURN(NAME != nullptr,);
  233. #define GO_LIB_SYMBOL G_LIB_SYMBOL
  234. #endif
  235. #define GTK_LIB_SYMBOL(NAME) \
  236. NAME = lib_symbol<gtksym_##NAME>(lib, "gtk_" #NAME); \
  237. CARLA_SAFE_ASSERT_RETURN(NAME != nullptr,);
  238. #define GDK_LIB_SYMBOL(NAME) \
  239. NAME = lib_symbol<gdksym_##NAME>(lib, "gdk_" #NAME); \
  240. CARLA_SAFE_ASSERT(NAME != nullptr);
  241. G_LIB_SYMBOL(timeout_add)
  242. GO_LIB_SYMBOL(signal_connect_data)
  243. GTK_LIB_SYMBOL(init)
  244. GTK_LIB_SYMBOL(main)
  245. GTK_LIB_SYMBOL(main_level)
  246. GTK_LIB_SYMBOL(main_quit)
  247. GTK_LIB_SYMBOL(container_add)
  248. GTK_LIB_SYMBOL(widget_destroy)
  249. GTK_LIB_SYMBOL(widget_hide)
  250. GTK_LIB_SYMBOL(widget_show_all)
  251. GTK_LIB_SYMBOL(window_new)
  252. GTK_LIB_SYMBOL(window_get_position)
  253. GTK_LIB_SYMBOL(window_get_size)
  254. GTK_LIB_SYMBOL(window_resize)
  255. GTK_LIB_SYMBOL(window_set_resizable)
  256. GTK_LIB_SYMBOL(window_set_title)
  257. ok = true;
  258. #ifdef HAVE_X11
  259. GTK_LIB_SYMBOL(widget_get_window)
  260. # ifdef BRIDGE_GTK3
  261. GDK_LIB_SYMBOL(window_get_display)
  262. GDK_LIB_SYMBOL(x11_display_get_xdisplay)
  263. GDK_LIB_SYMBOL(x11_window_get_xid)
  264. # else
  265. GDK_LIB_SYMBOL(x11_drawable_get_xdisplay)
  266. GDK_LIB_SYMBOL(x11_drawable_get_xid)
  267. # endif
  268. #endif
  269. #undef G_LIB_SYMBOL
  270. #undef GO_LIB_SYMBOL
  271. #undef GDK_LIB_SYMBOL
  272. #undef GTK_LIB_SYMBOL
  273. }
  274. ~GtkLoader()
  275. {
  276. if (lib != nullptr)
  277. lib_close(lib);
  278. #ifdef CARLA_OS_WIN
  279. if (golib != nullptr)
  280. lib_close(golib);
  281. if (glib != nullptr)
  282. lib_close(glib);
  283. #endif
  284. }
  285. void main_quit_if_needed()
  286. {
  287. if (main_level() != 0)
  288. main_quit();
  289. }
  290. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(GtkLoader)
  291. };
  292. // -------------------------------------------------------------------------
  293. static const bool gHideShowTesting = std::getenv("CARLA_UI_TESTING") != nullptr;
  294. // -------------------------------------------------------------------------
  295. class CarlaBridgeToolkitGtk : public CarlaBridgeToolkit
  296. {
  297. public:
  298. CarlaBridgeToolkitGtk(CarlaBridgeFormat* const format)
  299. : CarlaBridgeToolkit(format),
  300. gtk(),
  301. fNeedsShow(false),
  302. fWindow(nullptr),
  303. fLastX(0),
  304. fLastY(0),
  305. fLastWidth(0),
  306. fLastHeight(0)
  307. {
  308. carla_debug("CarlaBridgeToolkitGtk::CarlaBridgeToolkitGtk(%p)", format);
  309. }
  310. ~CarlaBridgeToolkitGtk() override
  311. {
  312. CARLA_SAFE_ASSERT(fWindow == nullptr);
  313. carla_debug("CarlaBridgeToolkitGtk::~CarlaBridgeToolkitGtk()");
  314. }
  315. bool init(const int /*argc*/, const char** /*argv[]*/) override
  316. {
  317. CARLA_SAFE_ASSERT_RETURN(fWindow == nullptr, false);
  318. carla_debug("CarlaBridgeToolkitGtk::init()");
  319. if (! gtk.ok)
  320. return false;
  321. static int gargc = 0;
  322. static char** gargv = nullptr;
  323. gtk.init(&gargc, &gargv);
  324. fWindow = gtk.window_new(GTK_WINDOW_TOPLEVEL);
  325. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr, false);
  326. gtk.window_resize(fWindow, 30, 30);
  327. gtk.widget_hide(fWindow);
  328. return true;
  329. }
  330. void exec(const bool showUI) override
  331. {
  332. CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);
  333. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  334. carla_debug("CarlaBridgeToolkitGtk::exec(%s)", bool2str(showUI));
  335. const CarlaBridgeFormat::Options& options(fPlugin->getOptions());
  336. GtkHandle* const widget((GtkHandle*)fPlugin->getWidget());
  337. CARLA_SAFE_ASSERT_RETURN(widget != nullptr,);
  338. gtk.container_add(fWindow, widget);
  339. gtk.window_set_resizable(fWindow, options.isResizable);
  340. gtk.window_set_title(fWindow, options.windowTitle.buffer());
  341. if (showUI || fNeedsShow)
  342. {
  343. show();
  344. fNeedsShow = false;
  345. }
  346. gtk.timeout_add(30, gtk_ui_timeout, this);
  347. gtk.signal_connect_data(fWindow, "destroy", gtk_ui_destroy, this, nullptr, 0);
  348. gtk.signal_connect_data(fWindow, "realize", gtk_ui_realize, this, nullptr, 0);
  349. // First idle
  350. handleTimeout();
  351. // Main loop
  352. gtk.main();
  353. }
  354. void quit() override
  355. {
  356. carla_debug("CarlaBridgeToolkitGtk::quit()");
  357. if (fWindow != nullptr)
  358. {
  359. gtk.widget_destroy(fWindow);
  360. fWindow = nullptr;
  361. gtk.main_quit_if_needed();
  362. }
  363. }
  364. void show() override
  365. {
  366. carla_debug("CarlaBridgeToolkitGtk::show()");
  367. fNeedsShow = true;
  368. if (fWindow != nullptr)
  369. gtk.widget_show_all(fWindow);
  370. }
  371. void focus() override
  372. {
  373. carla_debug("CarlaBridgeToolkitGtk::focus()");
  374. }
  375. void hide() override
  376. {
  377. carla_debug("CarlaBridgeToolkitGtk::hide()");
  378. fNeedsShow = false;
  379. if (fWindow != nullptr)
  380. gtk.widget_hide(fWindow);
  381. }
  382. void setChildWindow(void* const) override {}
  383. void setSize(const uint width, const uint height) override
  384. {
  385. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  386. carla_debug("CarlaBridgeToolkitGtk::resize(%i, %i)", width, height);
  387. gtk.window_resize(fWindow, static_cast<int>(width), static_cast<int>(height));
  388. }
  389. void setTitle(const char* const title) override
  390. {
  391. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  392. carla_debug("CarlaBridgeToolkitGtk::setTitle(\"%s\")", title);
  393. gtk.window_set_title(fWindow, title);
  394. }
  395. // ---------------------------------------------------------------------
  396. protected:
  397. GtkLoader gtk;
  398. bool fNeedsShow;
  399. GtkHandle* fWindow;
  400. int fLastX;
  401. int fLastY;
  402. int fLastWidth;
  403. int fLastHeight;
  404. void handleDestroy()
  405. {
  406. carla_debug("CarlaBridgeToolkitGtk::handleDestroy()");
  407. fWindow = nullptr;
  408. gtk.main_quit_if_needed();
  409. }
  410. void handleRealize()
  411. {
  412. carla_debug("CarlaBridgeToolkitGtk::handleRealize()");
  413. #ifdef HAVE_X11
  414. const CarlaBridgeFormat::Options& options(fPlugin->getOptions());
  415. if (options.transientWindowId != 0)
  416. setTransient(options.transientWindowId);
  417. #endif
  418. }
  419. int handleTimeout()
  420. {
  421. if (fWindow != nullptr)
  422. {
  423. gtk.window_get_position(fWindow, &fLastX, &fLastY);
  424. gtk.window_get_size(fWindow, &fLastWidth, &fLastHeight);
  425. }
  426. if (fPlugin->isPipeRunning())
  427. fPlugin->idlePipe();
  428. fPlugin->idleUI();
  429. if (gHideShowTesting)
  430. {
  431. static int counter = 0;
  432. ++counter;
  433. if (counter == 100)
  434. {
  435. hide();
  436. }
  437. else if (counter == 200)
  438. {
  439. show();
  440. counter = 0;
  441. }
  442. }
  443. return 1;
  444. }
  445. #ifdef HAVE_X11
  446. void setTransient(const uintptr_t winId)
  447. {
  448. CARLA_SAFE_ASSERT_RETURN(fWindow != nullptr,);
  449. carla_debug("CarlaBridgeToolkitGtk::setTransient(0x" P_UINTPTR ")", winId);
  450. if (gtk.widget_get_window == nullptr)
  451. return;
  452. # ifdef BRIDGE_GTK3
  453. if (gtk.window_get_display == nullptr)
  454. return;
  455. if (gtk.x11_display_get_xdisplay == nullptr)
  456. return;
  457. if (gtk.x11_window_get_xid == nullptr)
  458. return;
  459. # else
  460. if (gtk.x11_drawable_get_xdisplay == nullptr)
  461. return;
  462. if (gtk.x11_drawable_get_xid == nullptr)
  463. return;
  464. # endif
  465. GtkHandle* const gdkWindow = gtk.widget_get_window(fWindow);
  466. CARLA_SAFE_ASSERT_RETURN(gdkWindow != nullptr,);
  467. # ifdef BRIDGE_GTK3
  468. GtkHandle* const gdkDisplay = gtk.window_get_display(gdkWindow);
  469. CARLA_SAFE_ASSERT_RETURN(gdkDisplay != nullptr,);
  470. ::Display* const display = gtk.x11_display_get_xdisplay(gdkDisplay);
  471. CARLA_SAFE_ASSERT_RETURN(display != nullptr,);
  472. const ::XID xid = gtk.x11_window_get_xid(gdkWindow);
  473. CARLA_SAFE_ASSERT_RETURN(xid != 0,);
  474. # else
  475. ::Display* const display = gtk.x11_drawable_get_xdisplay((GtkHandle*)gdkWindow);
  476. CARLA_SAFE_ASSERT_RETURN(display != nullptr,);
  477. const ::XID xid = gtk.x11_drawable_get_xid((GtkHandle*)gdkWindow);
  478. CARLA_SAFE_ASSERT_RETURN(xid != 0,);
  479. # endif
  480. XSetTransientForHint(display, xid, static_cast< ::Window>(winId));
  481. }
  482. #endif
  483. // ---------------------------------------------------------------------
  484. private:
  485. static void gtk_ui_destroy(GtkHandle*, void* data)
  486. {
  487. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  488. ((CarlaBridgeToolkitGtk*)data)->handleDestroy();
  489. }
  490. static void gtk_ui_realize(GtkHandle*, void* data)
  491. {
  492. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  493. ((CarlaBridgeToolkitGtk*)data)->handleRealize();
  494. }
  495. static int gtk_ui_timeout(void* data)
  496. {
  497. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  498. return ((CarlaBridgeToolkitGtk*)data)->handleTimeout();
  499. }
  500. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaBridgeToolkitGtk)
  501. };
  502. // -------------------------------------------------------------------------
  503. CarlaBridgeToolkit* CarlaBridgeToolkit::createNew(CarlaBridgeFormat* const format)
  504. {
  505. return new CarlaBridgeToolkitGtk(format);
  506. }
  507. // -------------------------------------------------------------------------
  508. CARLA_BRIDGE_UI_END_NAMESPACE