Fix session-open after selecting new, template, then back
[ardour.git] / gtk2_ardour / lxvst_plugin_ui.cc
1 /*
2     Copyright (C) 2004 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include "gtkmm2ext/gui_thread.h"
21 #include "ardour/lxvst_plugin.h"
22 #include "ardour/linux_vst_support.h"
23 #include "lxvst_plugin_ui.h"
24 #include <gdk/gdkx.h>
25
26 #define LXVST_H_FIDDLE 40
27
28 using namespace std;
29 using namespace Gtk;
30 using namespace ARDOUR;
31 using namespace PBD;
32
33 LXVSTPluginUI::LXVSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<VSTPlugin> lxvp)
34         : VSTPluginUI (pi, lxvp)
35 {
36         vstfx_run_editor (_vst->state ());
37 }
38
39 LXVSTPluginUI::~LXVSTPluginUI ()
40 {
41         _resize_connection.disconnect();
42
43         // plugin destructor destroys the custom GUI, via the vstfx engine,
44         // and then our PluginUIWindow does the rest
45 }
46
47 void
48 LXVSTPluginUI::resize_callback ()
49 {
50         void* gtk_parent_window = _vst->state()->gtk_window_parent;
51
52         if (gtk_parent_window) {
53                 int width  = _vst->state()->width;
54                 int height = _vst->state()->height;
55 #ifndef NDEBUG
56                 printf ("LXVSTPluginUI::resize_callback %d x %d\n", width, height);
57 #endif
58                 _socket.set_size_request(
59                                 width  + _vst->state()->hoffset,
60                                 height + _vst->state()->voffset);
61
62                 ((Gtk::Window*) gtk_parent_window)->resize (width, height + LXVST_H_FIDDLE);
63                 if (_vst->state()->linux_plugin_ui_window) {
64                 }
65         }
66 }
67
68 int
69 LXVSTPluginUI::get_preferred_height ()
70 {
71         /* XXX: FIXME */
72
73         /* We have to return the required height of the plugin UI window +  a fiddle factor
74            because we can't know how big the preset menu bar is until the window is realised
75            and we can't realise it until we have told it how big we would like it to be
76            which we can't do until it is realised etc
77         */
78
79         // May not be 40 for all screen res etc
80         return VSTPluginUI::get_preferred_height () + LXVST_H_FIDDLE;
81 }
82
83 int
84 LXVSTPluginUI::package (Gtk::Window& win)
85 {
86         VSTPluginUI::package (win);
87         _vst->state()->gtk_window_parent = (void*) (&win);
88
89         /* Map the UI start and stop updating events to 'Map' events on the Window */
90
91         _vst->VSTSizeWindow.connect (_resize_connection, invalidator (*this), boost::bind (&LXVSTPluginUI::resize_callback, this), gui_context());
92         return 0;
93 }
94
95 void
96 LXVSTPluginUI::forward_key_event (GdkEventKey*)
97 {
98         std::cerr << "LXVSTPluginUI : keypress forwarding to linuxVSTs unsupported" << std::endl;
99 }
100
101 int
102 LXVSTPluginUI::get_XID ()
103 {
104         /* Wait for the lock to become free - otherwise
105            the window might be in the process of being
106            created and we get bad Window errors when trying
107            to embed it in the GTK UI
108         */
109
110         pthread_mutex_lock (&(_vst->state()->lock));
111
112         /* The Window may be scheduled for creation
113            but not actually created by the gui_event_loop yet -
114            spin here until it has been activated.  Possible
115            deadlock if the window never gets activated but
116            should not be called here if the window doesn't
117            exist or will never exist
118         */
119
120         while (!(_vst->state()->been_activated)) {
121                 Glib::usleep (1000);
122         }
123
124         int const id = _vst->state()->xid;
125
126         pthread_mutex_unlock (&(_vst->state()->lock));
127
128         /* Finally it might be safe to return the ID -
129            problems will arise if we return either a zero ID
130            and GTK tries to socket it or if we return an ID
131            which hasn't yet become real to the server
132         */
133
134         return id;
135 }
136
137 typedef int (*error_handler_t)( Display *, XErrorEvent *);
138 static Display *the_gtk_display;
139 static error_handler_t vstfx_error_handler;
140 static error_handler_t gtk_error_handler;
141
142 static int
143 gtk_xerror_handler (Display*, XErrorEvent*)
144 {
145         std::cerr << "** ERROR ** LXVSTPluginUI : Trapped an X Window System Error" << std::endl;
146
147         return 0;
148 }
149
150 void
151 gui_init (int* argc, char** argv[])
152 {
153         vstfx_error_handler = XSetErrorHandler (NULL);
154         gtk_init (argc, argv);
155         the_gtk_display = gdk_x11_display_get_xdisplay (gdk_display_get_default());
156         gtk_error_handler = XSetErrorHandler (gtk_xerror_handler);
157 }