pay some attention to the special guest of the night: KDE window stacking
[ardour.git] / gtk2_ardour / linux_vst_gui_support.cc
index e5722b2be0b84888d3bd281f5e84816ced76cacc..b310227403bdceab2b724bd0015dba568c405076 100644 (file)
@@ -56,20 +56,19 @@ static VSTState * vstfx_first = NULL;
 
 const char magic[] = "VSTFX Plugin State v002";
 
-int  gui_thread_id = 0;
-static int gui_quit = 0;
+static volatile int gui_quit = 0;
 
 /*This will be our connection to X*/
 
-Display* LXVST_XDisplay = NULL;
+static Display* LXVST_XDisplay = NULL;
 
 /*The thread handle for the GUI event loop*/
 
-pthread_t LXVST_gui_event_thread;
+static pthread_t LXVST_gui_event_thread;
 
 /*Util functions to get the value of a property attached to an XWindow*/
 
-bool LXVST_xerror;
+static bool LXVST_xerror;
 
 int TempErrorHandler(Display *display, XErrorEvent *e)
 {
@@ -303,29 +302,6 @@ dispatch_x_events (XEvent* event, VSTState* vstfx)
        vstfx->eventProc((void*)event);
 }
 
-static void
-maybe_set_program (VSTState* vstfx)
-{
-       if (vstfx->want_program != -1) {
-               if (vstfx->vst_version >= 2) {
-                       vstfx->plugin->dispatcher (vstfx->plugin, 67 /* effBeginSetProgram */, 0, 0, NULL, 0);
-               }
-
-               vstfx->plugin->dispatcher (vstfx->plugin, effSetProgram, 0, vstfx->want_program, NULL, 0);
-
-               if (vstfx->vst_version >= 2) {
-                       vstfx->plugin->dispatcher (vstfx->plugin, 68 /* effEndSetProgram */, 0, 0, NULL, 0);
-               }
-
-               vstfx->want_program = -1;
-       }
-
-       if (vstfx->want_chunk == 1) {
-               vstfx->plugin->dispatcher (vstfx->plugin, 24 /* effSetChunk */, 1, vstfx->wanted_chunk_size, vstfx->wanted_chunk, 0);
-               vstfx->want_chunk = 0;
-       }
-}
-
 /** This is the main gui event loop for the plugin, we also need to pass
 any Xevents to all the UI callbacks plugins 'may' have registered on their
 windows, that is if they don't manage their own UIs **/
@@ -438,7 +414,7 @@ again:
                                        }
                                }
 
-                               maybe_set_program (vstfx);
+                               vststate_maybe_set_program (vstfx);
                                vstfx->want_program = -1;
                                vstfx->want_chunk = 0;
 
@@ -472,7 +448,7 @@ again:
                        clock1 = g_get_monotonic_time();
                }
 
-               if (may_sleep && elapsed_time_ms + 1 < LXVST_sched_timer_interval) {
+               if (!gui_quit && may_sleep && elapsed_time_ms + 1 < LXVST_sched_timer_interval) {
                        Glib::usleep(1000 * (LXVST_sched_timer_interval - elapsed_time_ms - 1));
                }
        }
@@ -488,6 +464,8 @@ normally started in globals.cc*/
 
 int vstfx_init (void* ptr)
 {
+       assert (gui_quit == 0);
+       pthread_mutex_init (&plugin_mutex, NULL);
 
        int thread_create_result;
 
@@ -525,7 +503,7 @@ int vstfx_init (void* ptr)
 
        /*Create the thread - use default attrs for now, don't think we need anything special*/
 
-       thread_create_result = pthread_create(&LXVST_gui_event_thread, NULL, gui_event_loop, NULL);
+       thread_create_result = pthread_create(&LXVST_gui_event_thread, &thread_attributes, gui_event_loop, NULL);
 
        if(thread_create_result!=0)
        {
@@ -534,6 +512,7 @@ int vstfx_init (void* ptr)
                vstfx_error ("** ERROR ** VSTFX: Failed starting GUI event thread");
 
                XCloseDisplay(LXVST_XDisplay);
+               gui_quit = 1;
 
                return -1;
        }
@@ -545,12 +524,19 @@ int vstfx_init (void* ptr)
 
 void vstfx_exit()
 {
+       if (gui_quit) {
+               return;
+       }
        gui_quit = 1;
 
        /*We need to pthread_join the gui_thread here so
        we know when it has stopped*/
 
+       // BEWARE: some Plugin GUIs can crash if the thread local storage is free()d
+       // after the shared library containing the destructor is already dl-closed.
+       // (e.g u-he LXVST GUI, crash in __nptl_deallocate_tsd) :(
        pthread_join(LXVST_gui_event_thread, NULL);
+       pthread_mutex_destroy (&plugin_mutex);
 }
 
 /*Adds a new plugin (VSTFX) instance to the linked list*/
@@ -686,7 +672,7 @@ vstfx_launch_editor (VSTState* vstfx)
                return 0;
 
        Window parent_window;
-       struct ERect* er;
+       struct ERect* er = NULL;
 
        int x_size = 1;
        int y_size = 1;
@@ -721,11 +707,15 @@ vstfx_launch_editor (VSTState* vstfx)
 
        vstfx->plugin->dispatcher (vstfx->plugin, effEditGetRect, 0, 0, &er, 0 );
 
-       x_size = er->right - er->left;
-       y_size = er->bottom - er->top;
+       if (er) {
+               // Don't crash is plugin does not implement effEditGetRect
+               // it'll result in 1x1 px window but that's not our problem :)
+               x_size = er->right - er->left;
+               y_size = er->bottom - er->top;
+       }
 
-       vstfx->width =  x_size;
-       vstfx->height =  y_size;
+       vstfx->width = x_size;
+       vstfx->height = y_size;
 
        XResizeWindow(LXVST_XDisplay, parent_window, x_size, y_size);