/[svn]/gigedit/trunk/src/gigedit/gigedit.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/gigedit/gigedit.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2470 by persson, Sun Sep 15 13:31:04 2013 UTC revision 3489 by persson, Sun Mar 3 09:08:20 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2007-2009 Andreas Persson   * Copyright (C) 2007-2019 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include "compat.h"
21  #include "gigedit.h"  #include "gigedit.h"
22    
23    #ifdef GLIB_THREADS
24    #ifndef OLD_THREADS
25    #include <glibmm/threads.h>
26    #endif
27    #else
28    #include <thread>
29    #include <mutex>
30    #include <condition_variable>
31    #endif
32    #if GTKMM_MAJOR_VERSION < 3
33    #include <gdkmm/region.h>
34    #endif
35  #include <glibmm/dispatcher.h>  #include <glibmm/dispatcher.h>
36  #include <glibmm/main.h>  #include <glibmm/main.h>
37    #include <glibmm/miscutils.h>
38  #include <gtkmm/main.h>  #include <gtkmm/main.h>
39    
40    #if defined(WIN32) || defined(__APPLE__)
41    #include <gtkmm/icontheme.h>
42    #endif
43    
44    #if defined(__APPLE__)
45    # include <CoreFoundation/CoreFoundation.h>
46    # include "MacHelper.h"
47    #endif
48    
49  #include "mainwindow.h"  #include "mainwindow.h"
50    
51  #include "global.h"  #include "global.h"
# Line 30  Line 53 
53  #ifdef __APPLE__  #ifdef __APPLE__
54  #include <dlfcn.h>  #include <dlfcn.h>
55  #include <glibmm/fileutils.h>  #include <glibmm/fileutils.h>
56  #include <glibmm/miscutils.h>  #endif
57    
58    //TODO: (hopefully) just a temporary nasty hack for launching gigedit on the main thread on Mac (see comments below in this file for details)
59    #if defined(__APPLE__) && HAVE_LINUXSAMPLER // the following global external variables are defined in LinuxSampler's global_private.cpp ...
60    extern bool g_mainThreadCallbackSupported;
61    extern void (*g_mainThreadCallback)(void* info);
62    extern void* g_mainThreadCallbackInfo;
63    extern bool g_fireMainThreadCallback;
64  #endif  #endif
65    
66  namespace {  namespace {
# Line 45  namespace { Line 75  namespace {
75  //  //
76  class GigEditState : public sigc::trackable {  class GigEditState : public sigc::trackable {
77  public:  public:
78      GigEditState(GigEdit* parent) : parent(parent) { }      GigEditState(GigEdit* parent) :
79            window(0), parent(parent), instrument(0) { }
80      void run(gig::Instrument* pInstrument);      void run(gig::Instrument* pInstrument);
81    
82      MainWindow* window;      MainWindow* window;
# Line 56  private: Line 87  private:
87      class Cond {      class Cond {
88      private:      private:
89          bool pred;          bool pred;
90    #ifdef GLIB_THREADS
91          Glib::Threads::Mutex mutex;          Glib::Threads::Mutex mutex;
92          Glib::Threads::Cond cond;          Glib::Threads::Cond cond;
93    #else
94            std::mutex mutex;
95            std::condition_variable cond;
96    #endif        
97      public:      public:
98          Cond() : pred(false) { }          Cond() : pred(false) { }
99          void signal() {          void signal() {
100    #ifdef GLIB_THREADS
101              Glib::Threads::Mutex::Lock lock(mutex);              Glib::Threads::Mutex::Lock lock(mutex);
102              pred = true;              pred = true;
103              cond.signal();              cond.signal();
104    #else
105                std::lock_guard<std::mutex> lock(mutex);
106                pred = true;
107                cond.notify_one();
108    #endif
109          }          }
110          void wait() {          void wait() {
111    #ifdef GLIB_THREADS
112              Glib::Threads::Mutex::Lock lock(mutex);              Glib::Threads::Mutex::Lock lock(mutex);
113              while (!pred) cond.wait(mutex);              while (!pred) cond.wait(mutex);
114    #else
115                std::unique_lock<std::mutex> lock(mutex);
116                while (!pred) cond.wait(lock);
117    #endif      
118          }          }
119      };      };
120    
121  #ifdef OLD_THREADS  #ifdef OLD_THREADS
122      static Glib::StaticMutex mutex;      static Glib::StaticMutex mutex;
123  #else  #elif defined(GLIB_THREADS)
124      static Glib::Threads::Mutex mutex;      static Glib::Threads::Mutex mutex;
125    #else
126        static std::mutex mutex;
127  #endif  #endif
128      static Glib::Dispatcher* dispatcher;      static Glib::Dispatcher* dispatcher;
129      static GigEditState* current;      static GigEditState* current;
# Line 85  private: Line 134  private:
134      GigEdit* parent;      GigEdit* parent;
135      Cond open;      Cond open;
136      Cond close;      Cond close;
137        Cond initialized;
138      gig::Instrument* instrument;      gig::Instrument* instrument;
139    
140      void open_window();      void open_window();
141      void close_window();      void close_window();
142    #if defined(__APPLE__)
143        static void runInCFMainLoop(void* info);
144    #endif
145  };  };
146    
147  #ifdef WIN32  #ifdef WIN32
148  HINSTANCE gigedit_dll_handle = 0;  HINSTANCE gigedit_dll_handle = 0;
149    std::string gigedit_datadir;
150    bool gigedit_installdir_is_parent = false;
151  #endif  #endif
152    
153  #ifdef __APPLE__  #ifdef __APPLE__
154  std::string gigedit_localedir;  std::string gigedit_localedir;
155    std::string gigedit_datadir;
156  #endif  #endif
157    
158  void init_app() {  void init_app() {
# Line 111  void init_app() { Line 167  void init_app() {
167          // under the same dir as the gigedit dylib is installed in.          // under the same dir as the gigedit dylib is installed in.
168          Dl_info info;          Dl_info info;
169          if (dladdr((void*)&init_app, &info)) {          if (dladdr((void*)&init_app, &info)) {
170    #ifdef CONFIG_FORCE_GTK_LIBDIR
171                std::string libdir = CONFIG_FORCE_GTK_LIBDIR;
172    #else
173              std::string libdir = Glib::path_get_dirname(info.dli_fname);              std::string libdir = Glib::path_get_dirname(info.dli_fname);
174    #endif
175    
176                // newer pango versions don't use modules
177    #if PANGO_VERSION_MAJOR == 1 && PANGO_VERSION_MINOR < 38
178              if (Glib::getenv("PANGO_SYSCONFDIR") == "" &&              if (Glib::getenv("PANGO_SYSCONFDIR") == "" &&
179                  Glib::file_test(Glib::build_filename(libdir,                  Glib::file_test(Glib::build_filename(libdir,
180                                                       "pango/pango.modules"),                                                       "pango/pango.modules"),
181                                  Glib::FILE_TEST_EXISTS)) {                                  Glib::FILE_TEST_EXISTS)) {
182                  Glib::setenv("PANGO_SYSCONFDIR", libdir, true);                  Glib::setenv("PANGO_SYSCONFDIR", libdir, true);
183              }              }
184    #endif
185              if (Glib::getenv("GDK_PIXBUF_MODULE_FILE") == "") {              if (Glib::getenv("GDK_PIXBUF_MODULE_FILE") == "") {
186                  std::string module_file =                  std::string module_file =
187                      Glib::build_filename(libdir,                      Glib::build_filename(libdir,
188                                           "gtk-2.0/gdk-pixbuf.loaders");                                           "gdk-pixbuf-2.0/2.10.0/loaders.cache");
189                  if (Glib::file_test(module_file, Glib::FILE_TEST_EXISTS)) {                  if (Glib::file_test(module_file, Glib::FILE_TEST_EXISTS)) {
190                      Glib::setenv("GDK_PIXBUF_MODULE_FILE", module_file, true);                      Glib::setenv("GDK_PIXBUF_MODULE_FILE", module_file, true);
191                  }                  }
192              }              }
193  #if HAVE_GETTEXT              std::string datadir = Glib::build_filename(
194              std::string localedir = Glib::build_filename(libdir, "locale");                  Glib::path_get_dirname(libdir), "share");
195              if (Glib::file_test(localedir, Glib::FILE_TEST_EXISTS)) {  
196                  gigedit_localedir = localedir;              if (Glib::file_test(datadir, Glib::FILE_TEST_EXISTS)) {
197                    gigedit_datadir = datadir;
198    
199                    std::string localedir = Glib::build_filename(datadir, "locale");
200                    if (Glib::file_test(localedir, Glib::FILE_TEST_EXISTS)) {
201                        gigedit_localedir = localedir;
202                    }
203                    std::string schemadir =
204                        Glib::build_filename(gigedit_datadir, "glib-2.0/schemas");
205                    if (Glib::file_test(schemadir, Glib::FILE_TEST_EXISTS)) {
206                        Glib::setenv("GSETTINGS_SCHEMA_DIR", schemadir);
207                    }
208                }
209      //FIXME: for some reason AC GETTEXT check fails on the Mac cross compiler?
210      //#if HAVE_GETTEXT
211                if (!gigedit_localedir.empty()) {
212                  bindtextdomain(GETTEXT_PACKAGE, gigedit_localedir.c_str());                  bindtextdomain(GETTEXT_PACKAGE, gigedit_localedir.c_str());
213              } else {              } else {
214                  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);                  bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
215              }              }
216  #endif    //#endif
217          }          }
218    
219          // The gtk file dialog stores its recent files state in          // The gtk file dialog stores its recent files state in
# Line 143  void init_app() { Line 221  void init_app() {
221          g_mkdir_with_parents(          g_mkdir_with_parents(
222              Glib::build_filename(Glib::get_home_dir(),              Glib::build_filename(Glib::get_home_dir(),
223                                   ".local/share").c_str(), 0777);                                   ".local/share").c_str(), 0777);
224  #endif  #endif // __APPLE__
   
 #if HAVE_GETTEXT  
225    
226  #ifdef WIN32  #ifdef WIN32
227  #if GLIB_CHECK_VERSION(2, 16, 0)          // Find the data directory: the linuxsampler installer puts
228            // the binaries in sub directories "32" and "64", so the share
229            // directory is located in the parent of the directory of the
230            // binaries.
231    
232      #if GLIB_CHECK_VERSION(2, 16, 0)
233          gchar* root =          gchar* root =
234              g_win32_get_package_installation_directory_of_module(gigedit_dll_handle);              g_win32_get_package_installation_directory_of_module(gigedit_dll_handle);
235  #else    #else
236          gchar* root =          gchar* root =
237              g_win32_get_package_installation_directory(NULL, NULL);              g_win32_get_package_installation_directory(NULL, NULL);
238  #endif    #endif
239          gchar* temp = g_build_filename(root, "/share/locale", NULL);          std::string installdir(root);
240          g_free(root);          g_free(root);
241          gchar* localedir = g_win32_locale_filename_from_utf8(temp);          std::string basename = Glib::path_get_basename(installdir);
242          g_free(temp);          if (basename == "32" || basename == "64") {
243                installdir = Glib::path_get_dirname(installdir);
244                gigedit_installdir_is_parent = true;
245            }
246            gigedit_datadir = Glib::build_filename(installdir, "share");
247    
248            // the file dialogs need glib-2.0/schemas/gschemas.compiled
249            if (gigedit_installdir_is_parent) {
250                Glib::setenv("GSETTINGS_SCHEMA_DIR",
251                             Glib::build_filename(gigedit_datadir,
252                                                  "glib-2.0/schemas"));
253            }
254    #endif
255    
256    //FIXME: for some reason AC GETTEXT check fails on the Mac cross compiler?
257    #if (HAVE_GETTEXT || defined(__APPLE__))
258      #ifdef WIN32
259            std::string temp = Glib::build_filename(gigedit_datadir, "locale");
260            gchar* localedir = g_win32_locale_filename_from_utf8(temp.c_str());
261          bindtextdomain(GETTEXT_PACKAGE, localedir);          bindtextdomain(GETTEXT_PACKAGE, localedir);
262          g_free(localedir);          g_free(localedir);
263  #elif !defined(__APPLE__)    #elif !defined(__APPLE__)
264          bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);          bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
265  #endif    #endif
266          bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");          bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
267          textdomain(GETTEXT_PACKAGE);          textdomain(GETTEXT_PACKAGE);
268  #endif // HAVE_GETTEXT  #endif // HAVE_GETTEXT
# Line 176  void init_app() { Line 275  void init_app() {
275      }      }
276  }  }
277    
278    
279    #if GTKMM_MAJOR_VERSION >= 3
280    
281    /**
282     * This is required since GTK 3, because those GTK super heros came up with
283     * the clever idea to simply disable things like icons and keyboard shortcuts
284     * for menus and for buttons by default for all users, all devices and all
285     * apps. Yey! Seriously, I have no idea what came on their mind to find that
286     * was a good idea!
287     */
288    void enforceGtk3Settings() {
289    
290        // got no behavior change on those 2 settings, so ignoring them for now,
291        // actually I though I could use them to show the mnemonics in the GTK 3
292        // menus again, but it seems that was entirely removed from around GTK 3.10.
293        //g_object_set(gtk_settings_get_default(), "gtk-auto-mnemonics", false, NULL);
294        //g_object_set(gtk_settings_get_default(), "gtk-can-change-accels", true, NULL);
295    
296        // bring back keyboard accelerators with GTK 3
297        g_object_set(gtk_settings_get_default(), "gtk-enable-accels", true, NULL);
298        g_object_set(gtk_settings_get_default(), "gtk-enable-mnemonics", true, NULL);
299    
300        // bring back icons with GTK 3
301        g_object_set(gtk_settings_get_default(), "gtk-menu-images", true, NULL);
302        g_object_set(gtk_settings_get_default(), "gtk-button-images", true, NULL);
303    
304        // who knows ... one day those GTK "masterminds" decide to disable tooltips by default as well
305        g_object_set(gtk_settings_get_default(), "gtk-enable-tooltips", true, NULL);
306    }
307    
308    #endif // GTKM 3
309    
310    
311    void init_app_after_gtk_init() {
312    #if GTKMM_MAJOR_VERSION >= 3
313        enforceGtk3Settings();
314    #endif
315        
316    //FIXME: for some reason AC GETTEXT check fails on the Mac cross compiler?
317    #if (/*HAVE_GETTEXT &&*/ defined(__APPLE__))
318        // Gtk::Main binds the gtk locale to a possible non-existent
319        // directory. If we have bundled gtk locale files, we rebind here,
320        // after the Gtk::Main constructor.
321        if (!gigedit_localedir.empty()) {
322    #if GTKMM_MAJOR_VERSION < 3
323            bindtextdomain("gtk20", gigedit_localedir.c_str());
324    #else
325            bindtextdomain("gtk30", gigedit_localedir.c_str());
326    #endif
327        }
328    #endif
329    
330    #ifdef WIN32
331        if (gigedit_installdir_is_parent) {
332            std::string icon_dir = Glib::build_filename(gigedit_datadir, "icons");
333            Gtk::IconTheme::get_default()->append_search_path(icon_dir);
334        }
335    #endif
336    #ifdef __APPLE__
337        if (!gigedit_datadir.empty()) {
338            std::string icon_dir = Glib::build_filename(gigedit_datadir, "icons");
339            Gtk::IconTheme::get_default()->append_search_path(icon_dir);
340        }
341    #endif    
342    }
343    
344  void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {  void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
345      // the signals of the "GigEdit" class are actually just proxies, that      // the signals of the "GigEdit" class are actually just proxies, that
346      // is they simply forward the signals of the internal classes to the      // is they simply forward the signals of the internal classes to the
# Line 216  void connect_signals(GigEdit* gigedit, M Line 381  void connect_signals(GigEdit* gigedit, M
381      mainwindow->signal_keyboard_key_released().connect(      mainwindow->signal_keyboard_key_released().connect(
382          gigedit->signal_keyboard_key_released().make_slot()          gigedit->signal_keyboard_key_released().make_slot()
383      );      );
384        mainwindow->signal_switch_sampler_instrument().connect(
385            gigedit->signal_switch_sampler_instrument().make_slot()
386        );
387        mainwindow->signal_script_to_be_changed.connect(
388            gigedit->signal_script_to_be_changed.make_slot()
389        );
390        mainwindow->signal_script_changed.connect(
391            gigedit->signal_script_changed.make_slot()
392        );
393  }  }
394    
395  } // namespace  } // namespace
# Line 227  GigEdit::GigEdit() { Line 401  GigEdit::GigEdit() {
401  int GigEdit::run(int argc, char* argv[]) {  int GigEdit::run(int argc, char* argv[]) {
402      init_app();      init_app();
403    
404    #if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION < 89 || (GTKMM_MINOR_VERSION == 89 && GTKMM_MICRO_VERSION < 4))) // GTKMM < 3.89.4
405      Gtk::Main kit(argc, argv);      Gtk::Main kit(argc, argv);
406    #else
407  #ifdef __APPLE__      Glib::RefPtr<Gtk::Application> app =
408      // Gtk::Main binds the gtk locale to a possible non-existent          Gtk::Application::create("org.linuxsampler.gigedit");
     // directory. If we have bundled gtk locale files, we rebind here,  
     // after the Gtk::Main constructor.  
     if (!gigedit_localedir.empty()) {  
         bindtextdomain("gtk20", gigedit_localedir.c_str());  
     }  
409  #endif  #endif
410        init_app_after_gtk_init();
411    
412      MainWindow window;      MainWindow window;
413      connect_signals(this, &window);      connect_signals(this, &window);
414      if (argc >= 2) window.load_file(argv[1]);      if (argc >= 2) window.load_file(argv[1]);
415    #if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION < 89 || (GTKMM_MINOR_VERSION == 89 && GTKMM_MICRO_VERSION < 4))) // GTKMM < 3.89.4
416      kit.run(window);      kit.run(window);
417    #else
418        app->run(window, argc, argv);
419    #endif
420        
421      return 0;      return 0;
422  }  }
423    
# Line 257  int GigEdit::run(gig::Instrument* pInstr Line 433  int GigEdit::run(gig::Instrument* pInstr
433    
434  void GigEdit::on_note_on_event(int key, int velocity) {  void GigEdit::on_note_on_event(int key, int velocity) {
435      if (!this->state) return;      if (!this->state) return;
436      GigEditState* state = (GigEditState*) this->state;      GigEditState* state = static_cast<GigEditState*>(this->state);
437      state->window->signal_note_on().emit(key, velocity);      state->window->signal_note_on().emit(key, velocity);
438  }  }
439    
440  void GigEdit::on_note_off_event(int key, int velocity) {  void GigEdit::on_note_off_event(int key, int velocity) {
441      if (!this->state) return;      if (!this->state) return;
442      GigEditState* state = (GigEditState*) this->state;      GigEditState* state = static_cast<GigEditState*>(this->state);
443      state->window->signal_note_off().emit(key, velocity);      state->window->signal_note_off().emit(key, velocity);
444  }  }
445    
# Line 315  sigc::signal<void, int/*key*/, int/*velo Line 491  sigc::signal<void, int/*key*/, int/*velo
491      return keyboard_key_released_signal;      return keyboard_key_released_signal;
492  }  }
493    
494    sigc::signal<void, gig::Instrument*>& GigEdit::signal_switch_sampler_instrument() {
495        return switch_sampler_instrument_signal;
496    }
497    
498  #ifdef OLD_THREADS  #ifdef OLD_THREADS
499  Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;  Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
500  #else  #elif defined(GLIB_THREADS)
501  Glib::Threads::Mutex GigEditState::mutex;  Glib::Threads::Mutex GigEditState::mutex;
502    #else
503    std::mutex GigEditState::mutex;
504  #endif  #endif
505  Glib::Dispatcher* GigEditState::dispatcher = 0;  Glib::Dispatcher* GigEditState::dispatcher = 0;
506  GigEditState* GigEditState::current = 0;  GigEditState* GigEditState::current = 0;
# Line 335  void GigEditState::open_window() { Line 517  void GigEditState::open_window() {
517      connect_signals(parent, window);      connect_signals(parent, window);
518      if (instrument) window->load_instrument(instrument);      if (instrument) window->load_instrument(instrument);
519    
520      window->signal_hide().connect(sigc::mem_fun(this,      window->signal_hide().connect(sigc::mem_fun(*this,
521                                                  &GigEditState::close_window));                                                  &GigEditState::close_window));
522      window->present();      window->present();
523  }  }
# Line 345  void GigEditState::close_window() { Line 527  void GigEditState::close_window() {
527      close.signal();      close.signal();
528  }  }
529    
530    #if defined(WIN32) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
531    // make sure stack is 16-byte aligned for SSE instructions
532    __attribute__((force_align_arg_pointer))
533    #endif
534  void GigEditState::main_loop_run(Cond* initialized) {  void GigEditState::main_loop_run(Cond* initialized) {
535      int argc = 1;      int argc = 1;
536      const char* argv_c[] = { "gigedit" };      const char* argv_c[] = { "gigedit" };
537      char** argv = const_cast<char**>(argv_c);      char** argv = const_cast<char**>(argv_c);
538    #if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION < 89 || (GTKMM_MINOR_VERSION == 89 && GTKMM_MICRO_VERSION < 4))) // GTKMM < 3.89.4
539      Gtk::Main main_loop(argc, argv);      Gtk::Main main_loop(argc, argv);
 #ifdef __APPLE__  
     if (!gigedit_localedir.empty()) {  
         bindtextdomain("gtk20", gigedit_localedir.c_str());  
     }  
540  #endif  #endif
541        init_app_after_gtk_init();
542    
543      dispatcher = new Glib::Dispatcher();      dispatcher = new Glib::Dispatcher();
544      dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));      dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
545      initialized->signal();      initialized->signal();
546    
547    #if GTKMM_MAJOR_VERSION < 3 || (GTKMM_MAJOR_VERSION == 3 && (GTKMM_MINOR_VERSION < 89 || (GTKMM_MINOR_VERSION == 89 && GTKMM_MICRO_VERSION < 4))) // GTKMM < 3.89.4
548      main_loop.run();      main_loop.run();
549    #else
550        Gtk::Main::run();
551    #endif
552  }  }
553    
554    #if defined(__APPLE__)
555    
556    void GigEditState::runInCFMainLoop(void* info) {
557        printf("runInCFMainLoop() entered\n"); fflush(stdout);
558        GigEditState* state = static_cast<GigEditState*>(info);
559        state->main_loop_run(
560            &state->initialized
561        );
562        printf("runInCFMainLoop() left\n"); fflush(stdout);
563    }
564    
565    #endif // __APPLE__
566    
567  void GigEditState::run(gig::Instrument* pInstrument) {  void GigEditState::run(gig::Instrument* pInstrument) {
568      mutex.lock(); // lock access to static variables      mutex.lock(); // lock access to static variables
569    
570      static bool main_loop_started = false;      static bool main_loop_started = false;
571        instrument = pInstrument;
572      if (!main_loop_started) {      if (!main_loop_started) {
573          Cond initialized;  #if defined(__APPLE__) && HAVE_LINUXSAMPLER
574  #ifdef OLD_THREADS          // spawn GUI on main thread :
575            //     On OS X the Gtk GUI can only be launched on a process's "main"
576            //     thread. When trying to launch the Gtk GUI on any other thread,
577            //     there will only be a white box, because the GUI would not receive
578            //     any events, since it would listen to the wrong system event loop.
579            //     So far we haven't investigated whether there is any kind of
580            //     circumvention to allow doing that also on other OS X threads.
581            {
582                // In case the sampler was launched as standalone sampler (not as
583                // plugin), use the following global callback variable hack ...
584                if (g_mainThreadCallbackSupported) {
585                    printf("Setting callback ...\n"); fflush(stdout);
586                    g_mainThreadCallback = runInCFMainLoop;
587                    g_mainThreadCallbackInfo = this;
588                    g_fireMainThreadCallback = true;
589                    printf("Callback variables set.\n"); fflush(stdout);
590                } else { // Sampler was launched as (i.e. AU / VST) plugin ...
591                    // When the sampler was launched as plugin, we have no idea
592                    // whether any sampler thread is the process's "main" thread.
593                    // So that's why we are trying to use Apple's API for trying to
594                    // launch our callback function on the process's main thread.
595                    // However this will only work, if the plugin host application
596                    // established a CF event loop, that is if the application is
597                    // using Cocoa for its GUI. For other host applications the
598                    // callback will never be executed and thus gigedit would not
599                    // popup.
600                    
601                    // should be pretty much the same as the Objective-C solution below with macHelperRunCFuncOnMainThread()
602                    /*CFRunLoopSourceContext sourceContext = CFRunLoopSourceContext();
603                    sourceContext.info = this;
604                    sourceContext.perform = runInCFMainLoop;
605                    printf("CFRunLoopSourceCreate\n"); fflush(stdout);
606                    CFRunLoopSourceRef source = CFRunLoopSourceCreate(
607                        kCFAllocatorDefault, // allocator
608                        1, // priority
609                        &sourceContext
610                    );
611                    printf("CFRunLoopAddSource\n"); fflush(stdout);
612                    CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopDefaultMode);
613                    CFRelease(source);*/
614                    
615                    // use Apple's Objective-C API to call our callback function
616                    // 'runInCFMainLoop()' on the process's "main" thread
617                    macHelperRunCFuncOnMainThread(runInCFMainLoop, this);
618                }
619            }
620    #else
621      #ifdef OLD_THREADS
622          Glib::Thread::create(          Glib::Thread::create(
623              sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),              sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
624                         &initialized),                         &initialized),
625              false);              false);
626  #else    #elif defined(GLIB_THREADS)
627          Glib::Threads::Thread::create(          Glib::Threads::Thread::create(
628              sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),              sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
629                         &initialized));                         &initialized));
630      #else
631            new std::thread([this]() { main_loop_run(&initialized); });
632      #endif
633  #endif  #endif
634            printf("Waiting for GUI being initialized (on main thread) ....\n"); fflush(stdout);
635          initialized.wait();          initialized.wait();
636            printf("GUI is now initialized. Everything done.\n"); fflush(stdout);
637          main_loop_started = true;          main_loop_started = true;
638      }      }
     instrument = pInstrument;  
639      current = this;      current = this;
640      dispatcher->emit();      dispatcher->emit();
641      open.wait(); // wait until the GUI thread has read current      open.wait(); // wait until the GUI thread has read current

Legend:
Removed from v.2470  
changed lines
  Added in v.3489

  ViewVC Help
Powered by ViewVC