a reverb is a reverb is a reverb
[ardour.git] / gtk2_ardour / linux_vst_gui_support.cc
index e5722b2be0b84888d3bd281f5e84816ced76cacc..a2f637a26c6e5446f47337504dbe89bc14fd0996 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)
 {
@@ -472,7 +471,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 +487,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 +526,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 +535,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 +547,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 +695,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 +730,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);