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 = KeyPress;
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()->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());
143 xev.xany.window = _vst->state()->xid;
145 if (!_vst->state()->eventProc) {
146 XSendEvent (xev.xany.display, xev.xany.window, TRUE, mask, &xev);
148 _vst->state()->eventProc (&xev);
153 LXVSTPluginUI::get_XID ()
155 /* Wait for the lock to become free - otherwise
156 the window might be in the process of being
157 created and we get bad Window errors when trying
158 to embed it in the GTK UI
161 pthread_mutex_lock (&(_vst->state()->lock));
163 /* The Window may be scheduled for creation
164 but not actually created by the gui_event_loop yet -
165 spin here until it has been activated. Possible
166 deadlock if the window never gets activated but
167 should not be called here if the window doesn't
168 exist or will never exist
171 while (!(_vst->state()->been_activated)) {
175 int const id = _vst->state()->xid;
177 pthread_mutex_unlock (&(_vst->state()->lock));
179 /* Finally it might be safe to return the ID -
180 problems will arise if we return either a zero ID
181 and GTK tries to socket it or if we return an ID
182 which hasn't yet become real to the server
188 typedef int (*error_handler_t)( Display *, XErrorEvent *);
189 static Display *the_gtk_display;
190 static error_handler_t vstfx_error_handler;
191 static error_handler_t gtk_error_handler;
194 gtk_xerror_handler (Display*, XErrorEvent*)
196 std::cerr << "** ERROR ** LXVSTPluginUI : Trapped an X Window System Error" << std::endl;
202 gui_init (int* argc, char** argv[])
204 vstfx_error_handler = XSetErrorHandler (NULL);
205 gtk_init (argc, argv);
206 the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default());
207 gtk_error_handler = XSetErrorHandler (gtk_xerror_handler);