2 Copyright (C) 2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "gtkmm2ext/gui_thread.h"
22 #include "ardour/lxvst_plugin.h"
23 #include "ardour/linux_vst_support.h"
24 #include "lxvst_plugin_ui.h"
26 #include <gdk/gdkx.h> /* must come later than glibmm/object.h */
28 #define LXVST_H_FIDDLE 40
32 using namespace ARDOUR;
35 LXVSTPluginUI::LXVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<VSTPlugin> lxvp)
36 : VSTPluginUI (pi, lxvp)
38 vstfx_run_editor (_vst->state ());
41 LXVSTPluginUI::~LXVSTPluginUI ()
43 _resize_connection.disconnect();
45 // plugin destructor destroys the custom GUI, via the vstfx engine,
46 // and then our PluginUIWindow does the rest
50 LXVSTPluginUI::resize_callback ()
52 void* gtk_parent_window = _vst->state()->gtk_window_parent;
54 if (gtk_parent_window) {
55 int width = _vst->state()->width;
56 int height = _vst->state()->height;
58 printf ("LXVSTPluginUI::resize_callback %d x %d\n", width, height);
60 _socket.set_size_request(
61 width + _vst->state()->hoffset,
62 height + _vst->state()->voffset);
64 ((Gtk::Window*) gtk_parent_window)->resize (width, height + LXVST_H_FIDDLE);
65 if (_vst->state()->linux_plugin_ui_window) {
71 LXVSTPluginUI::get_preferred_height ()
75 /* We have to return the required height of the plugin UI window + a fiddle factor
76 because we can't know how big the preset menu bar is until the window is realised
77 and we can't realise it until we have told it how big we would like it to be
78 which we can't do until it is realised etc
81 // May not be 40 for all screen res etc
82 return VSTPluginUI::get_preferred_height () + LXVST_H_FIDDLE;
86 LXVSTPluginUI::package (Gtk::Window& win)
88 VSTPluginUI::package (win);
89 _vst->state()->gtk_window_parent = (void*) (&win);
91 /* Map the UI start and stop updating events to 'Map' events on the Window */
93 _vst->VSTSizeWindow.connect (_resize_connection, invalidator (*this), boost::bind (&LXVSTPluginUI::resize_callback, this), gui_context());
98 LXVSTPluginUI::forward_key_event (GdkEventKey* gdk_key)
100 if (!_vst->state()->gtk_window_parent) {
104 Glib::RefPtr<Gdk::Window> gdk_window = ((Gtk::Window*) _vst->state()->gtk_window_parent)->get_window();
113 switch (gdk_key->type) {
115 xev.xany.type = KeyPress;
118 case GDK_KEY_RELEASE:
119 xev.xany.type = KeyRelease;
120 mask = KeyReleaseMask;
126 /* XXX relies on GDK using X11 definitions for these fields */
128 xev.xkey.state = gdk_key->state;
129 xev.xkey.keycode = gdk_key->hardware_keycode; /* see gdk/x11/gdkevents-x11.c:translate_key_event() */
135 xev.xkey.root = gdk_x11_get_default_root_xwindow();
136 xev.xkey.window = _vst->state()->linux_plugin_ui_window ? _vst->state()->linux_plugin_ui_window : _vst->state()->xid;
137 xev.xkey.subwindow = None;
138 xev.xkey.time = gdk_key->time;
140 xev.xany.serial = 0; /* we don't have one */
141 xev.xany.send_event = true; /* pretend we are using XSendEvent */
142 xev.xany.display = GDK_WINDOW_XDISPLAY (gdk_window->gobj());
144 if (_vst->state()->eventProc) {
145 _vst->state()->eventProc (&xev);
146 } else if (!dispatch_effeditkey (gdk_key)) {
147 XSendEvent (xev.xany.display, xev.xany.window, TRUE, mask, &xev);
152 LXVSTPluginUI::get_XID ()
154 /* Wait for the lock to become free - otherwise
155 the window might be in the process of being
156 created and we get bad Window errors when trying
157 to embed it in the GTK UI
160 pthread_mutex_lock (&(_vst->state()->lock));
162 /* The Window may be scheduled for creation
163 but not actually created by the gui_event_loop yet -
164 spin here until it has been activated. Possible
165 deadlock if the window never gets activated but
166 should not be called here if the window doesn't
167 exist or will never exist
170 while (!(_vst->state()->been_activated)) {
174 int const id = _vst->state()->xid;
176 pthread_mutex_unlock (&(_vst->state()->lock));
178 /* Finally it might be safe to return the ID -
179 problems will arise if we return either a zero ID
180 and GTK tries to socket it or if we return an ID
181 which hasn't yet become real to the server
187 typedef int (*error_handler_t)( Display *, XErrorEvent *);
188 static Display *the_gtk_display;
189 static error_handler_t vstfx_error_handler;
190 static error_handler_t gtk_error_handler;
193 gtk_xerror_handler (Display*, XErrorEvent*)
195 std::cerr << "** ERROR ** LXVSTPluginUI : Trapped an X Window System Error" << std::endl;
201 gui_init (int* argc, char** argv[])
203 vstfx_error_handler = XSetErrorHandler (NULL);
204 gtk_init (argc, argv);
205 the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default());
206 gtk_error_handler = XSetErrorHandler (gtk_xerror_handler);