resolve gtk + VST threading issues
authorRobin Gareus <robin@gareus.org>
Sat, 22 Feb 2014 01:44:34 +0000 (02:44 +0100)
committerRobin Gareus <robin@gareus.org>
Sat, 22 Feb 2014 02:11:48 +0000 (03:11 +0100)
while (gtk_events_pending()) gtk_main_iteration(); never returns
as long as there's a idle call registered somewhere (and it's not
called from an idle callback itself)

gtk2_ardour/ardour_ui.cc
gtk2_ardour/editor_audio_import.cc
libs/ardour/session_vst.cc
libs/fst/fst.c
libs/fst/fst.h
libs/fst/vstwin.c

index 9781bd01d9d53911d22b89a42ec38c19b859bc34..cb1c22a8d081277181e65fbae20de1814e01f607 100644 (file)
 #include "ardour/session_utils.h"
 #include "ardour/slave.h"
 
+#ifdef WINDOWS_VST_SUPPORT
+#include <fst.h>
+#endif
+
 #include "timecode/time.h"
 
 typedef uint64_t microseconds_t;
@@ -1008,6 +1012,9 @@ If you still wish to quit, please use the\n\n\
 
        halt_connection.disconnect ();
        AudioEngine::instance()->stop ();
+#ifdef WINDOWS_VST_SUPPORT
+       fst_stop_threading();
+#endif
        quit ();
 }
 
@@ -2916,7 +2923,13 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name,
                _session->set_clean ();
        }
 
+#ifdef WINDOWS_VST_SUPPORT
+       fst_stop_threading();
+#endif
        flush_pending ();
+#ifdef WINDOWS_VST_SUPPORT
+       fst_start_threading();
+#endif
        retval = 0;
 
   out:
@@ -3343,10 +3356,6 @@ ARDOUR_UI::add_route (Gtk::Window* float_window)
 
        PBD::ScopedConnection idle_connection;
 
-       if (count > 8) {
-               ARDOUR::GUIIdle.connect (idle_connection, MISSING_INVALIDATOR, boost::bind (&Gtkmm2ext::UI::flush_pending, this), gui_context());
-       }
-
        string template_path = add_route_dialog->track_template();
 
        if (!template_path.empty()) {
index a19a62b337290233fbd48da8c1b9aeed937b2b71..da70df5c15a71c2e3ead386b9e43a85fb728f997 100644 (file)
@@ -632,7 +632,7 @@ Editor::embed_sndfiles (vector<string> paths, bool multifile,
                                goto out;
                        }
 
-                       ARDOUR_UI::instance()->flush_pending ();
+                       gtk_main_iteration();
                }
        }
 
index 461934b5f4e31392681d8049c5b26e07d9bf3a58..61805be2cd789b9a2ed3534da4c6170c29cc9a5b 100644 (file)
@@ -28,6 +28,9 @@
 #include "ardour/windows_vst_plugin.h"
 #include "ardour/vestige/aeffectx.h"
 #include "ardour/vst_types.h"
+#ifdef WINDOWS_VST_SUPPORT
+#include <fst.h>
+#endif
 
 #include "i18n.h"
 
@@ -100,26 +103,9 @@ intptr_t Session::vst_callback (
 
        case audioMasterIdle:
                SHOW_CALLBACK ("amc: audioMasterIdle\n");
-               // call application idle routine (this will
-               // call effEditIdle for all open editors too)
-
-#if 0 // TODO -> emit to GUI OR better delegete to fst/fst
-
-               // This allows the main GUI window to update if needed.
-               // Some plugins take over the GUI event loop
-               // which causes the main GUI to freeze while the plugin GUI continues to run. This code
-               // prevents the main GUI from being frozen.
-
-               do {
-#ifdef GDK_WINDOWING_X11
-                       gtk_main_iteration_do(false);
-#else
-                       gtk_main_iteration()
-#endif
-               } while (gtk_events_pending());
+#ifdef WINDOWS_VST_SUPPORT
+               fst_audio_master_idle();
 #endif
-               printf("audioMasterIdle\n");
-
                if (effect) {
                        effect->dispatcher(effect, effEditIdle, 0, 0, NULL, 0.0f);
                }
index 433354e1f1ada38aa04a899a1e5d5f401442eac3..3ceee5278fe79fa355b5a3fe3462c6440bdaa7cb 100644 (file)
@@ -15,7 +15,7 @@ fst_error (const char *fmt, ...)
        va_end (ap);
 }
 
-void
+static void
 default_fst_error_callback (const char *desc)
 {
        fprintf(stderr, "%s\n", desc);
index e3cba8d3d548c0d5aae5b22bf51fa153e7c4be3f..10ccda4d41d7a0bbd0e5360fea234095954d7487 100644 (file)
@@ -48,6 +48,9 @@ extern void fst_move_window_into_view (VSTState *);
 extern VSTInfo *fst_get_info (char *dllpathname);
 extern void fst_free_info (VSTInfo *info);
 extern void fst_event_loop_remove_plugin (VSTState* fst);
+extern void fst_start_threading(void);
+extern void fst_stop_threading(void);
+extern void fst_audio_master_idle(void);
 
 #ifdef __cplusplus
 }
index 37ea86dc19796cd02450bab765496bfdaa3864e2..75bf2372da8dbf82f3b4f7ebbb2e4ce0bb2697f5 100644 (file)
@@ -16,6 +16,7 @@ static UINT_PTR idle_timer_id   = 0;
 #include <wine/exception.h>
 #include <pthread.h>
 static int gui_quit = 0;
+static unsigned int idle_id = 0;
 
 #endif
 
@@ -249,12 +250,14 @@ fst_handle_new (void)
 #ifndef PLATFORM_WINDOWS /* linux + wine */
 static gboolean
 g_idle_call (gpointer ignored) {
+       if (gui_quit) return FALSE;
        MSG msg;
        if (PeekMessageA (&msg, NULL, 0, 0, 1)) {
                TranslateMessage (&msg);
                DispatchMessageA (&msg);
        }
        idle_hands(NULL, 0, 0, 0);
+       g_main_context_iteration(NULL, FALSE);
        return gui_quit ? FALSE : TRUE;
 }
 #endif
@@ -311,12 +314,31 @@ fst_init (void* possible_hmodule)
                fst_error ("Error in fst_init(): (class registration failed");
                return -1;
        }
+       return 0;
+}
+
+void
+fst_start_threading(void)
+{
 #ifndef PLATFORM_WINDOWS /* linux + wine */
-       gui_quit = 0;
-       g_idle_add (g_idle_call, NULL); // XXX too early ?
-       //g_timeout_add(40, g_idle_call, NULL);
+       if (idle_id == 0) {
+               gui_quit = 0;
+               idle_id = g_idle_add (g_idle_call, NULL);
+       }
+#endif
+}
+
+void
+fst_stop_threading(void) {
+#ifndef PLATFORM_WINDOWS /* linux + wine */
+       if (idle_id != 0) {
+               gui_quit = 1;
+               PostQuitMessage (0);
+               g_main_context_iteration(NULL, FALSE);
+               //g_source_remove(idle_id);
+               idle_id = 0;
+       }
 #endif
-       return 0;
 }
 
 void
@@ -333,8 +355,10 @@ fst_exit (void)
                KillTimer(NULL, idle_timer_id);
        }
 #else /* linux + wine */
-       gui_quit = 1;
-       PostQuitMessage (0);
+       if (idle_id) {
+               gui_quit = 1;
+               PostQuitMessage (0);
+       }
 #endif
 
        host_initialized = FALSE;
@@ -562,6 +586,10 @@ fst_instantiate (VSTHandle* fhandle, audioMasterCallback amc, void* userptr)
        return fst;
 }
 
+void fst_audio_master_idle(void) {
+       while(g_main_context_iteration(NULL, FALSE)) ;
+}
+
 void
 fst_close (VSTState* fst)
 {