/[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 1339 by schoenebeck, Mon Sep 10 19:56:26 2007 UTC revision 1656 by schoenebeck, Sat Feb 2 08:18:19 2008 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2007 Andreas Persson   * Copyright (C) 2007, 2008 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 20  Line 20 
20  #include "gigedit.h"  #include "gigedit.h"
21    
22  #include <gtkmm/main.h>  #include <gtkmm/main.h>
23    #include <glibmm/main.h>
24  #include "mainwindow.h"  #include "mainwindow.h"
25    
26  #include <libintl.h>  #include "global.h"
 #include <config.h>  
27    
28  // the app has to work from a DLL as well, so we hard code argv  namespace {
 int argc = 1;  
 const char* argv_c[] = { "gigedit" };  
 char** argv = const_cast<char**>(argv_c);  
 //FIXME: Gtk only allows to instantiate one Gtk::Main object per process, so this might crash other Gtk applications, i.e. launched as plugins by LinuxSampler  
 Gtk::Main kit(argc, argv);  
29    
30  static void __init_app() {  // State for a gigedit thread.
31    //
32    // This class is only used when gigedit is run as a plugin and makes
33    // sure that there's only one Gtk::Main event loop. The event loop is
34    // started in a separate thread. The plugin thread just dispatches an
35    // event to the main loop to open a window and then goes to sleep
36    // until the window is closed.
37    //
38    class GigEditState : public sigc::trackable {
39    public:
40        GigEditState(GigEdit* parent) : parent(parent) { }
41        void run(gig::Instrument* pInstrument);
42    
43        MainWindow* window;
44    
45    private:
46    
47        // simple condition variable abstraction
48        class Cond {
49        private:
50            bool pred;
51            Glib::Mutex mutex;
52            Glib::Cond cond;
53        public:
54            Cond() : pred(false) { }
55            void signal() {
56                Glib::Mutex::Lock lock(mutex);
57                pred = true;
58                cond.signal();
59            }
60            void wait() {
61                Glib::Mutex::Lock lock(mutex);
62                while (!pred) cond.wait(mutex);
63            }
64        };
65    
66        static Glib::StaticMutex mutex;
67        static Glib::Dispatcher* dispatcher;
68        static GigEditState* current;
69    
70        static void main_loop_run(Cond* intialized);
71        static void open_window_static();
72    
73        GigEdit* parent;
74        Cond open;
75        Cond close;
76        gig::Instrument* instrument;
77    
78        void open_window();
79        void close_window();
80    };
81    
82    void init_app() {
83      static bool process_initialized = false;      static bool process_initialized = false;
84      if (!process_initialized) {      if (!process_initialized) {
85          std::cout << "Initializing 3rd party services needed by gigedit.\n"          std::cout << "Initializing 3rd party services needed by gigedit.\n"
86                    << std::flush;                    << std::flush;
87          setlocale(LC_ALL, "");          setlocale(LC_ALL, "");
88    
89    #if HAVE_GETTEXT
90          bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);          bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
91          bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");          bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
92          textdomain(GETTEXT_PACKAGE);          textdomain(GETTEXT_PACKAGE);
93    #endif // HAVE_GETTEXT
94    
95          // make sure thread_init() is called once and ONLY once per process          // make sure thread_init() is called once and ONLY once per process
96          if (!Glib::thread_supported()) Glib::thread_init();          if (!Glib::thread_supported()) Glib::thread_init();
97    
# Line 48  static void __init_app() { Line 99  static void __init_app() {
99      }      }
100  }  }
101    
102  static void __connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {  void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
103      // the signals of the "GigEdit" class are actually just proxies, that      // the signals of the "GigEdit" class are actually just proxies, that
104      // is they simply forward the signals of the internal classes to the      // is they simply forward the signals of the internal classes to the
105      // outer world      // outer world
# Line 81  static void __connect_signals(GigEdit* g Line 132  static void __connect_signals(GigEdit* g
132      );      );
133  }  }
134    
135  int GigEdit::run() {  } // namespace
136      __init_app();  
137      MainWindow window;  GigEdit::GigEdit() {
138      __connect_signals(this, &window);      state = NULL;
     kit.run(window);  
     return 0;  
139  }  }
140    
141  int GigEdit::run(const char* pFileName) {  int GigEdit::run(int argc, char* argv[]) {
142      __init_app();      init_app();
143    
144        Gtk::Main kit(argc, argv);
145      MainWindow window;      MainWindow window;
146      __connect_signals(this, &window);      connect_signals(this, &window);
147      if (pFileName) window.load_file(pFileName);      if (argc >= 2) window.load_file(argv[1]);
148      kit.run(window);      kit.run(window);
149      return 0;      return 0;
150  }  }
151    
152  int GigEdit::run(gig::Instrument* pInstrument) {  int GigEdit::run(gig::Instrument* pInstrument) {
153      __init_app();      init_app();
154      MainWindow window;  
155      __connect_signals(this, &window);      GigEditState state(this);
156      if (pInstrument) window.load_instrument(pInstrument);      this->state = &state;
157      kit.run(window);      state.run(pInstrument);
158        this->state = NULL;
159      return 0;      return 0;
160  }  }
161    
162    void GigEdit::on_note_on_event(int key, int velocity) {
163        if (!this->state) return;
164        GigEditState* state = (GigEditState*) this->state;
165        state->window->signal_note_on().emit(key, velocity);
166    }
167    
168    void GigEdit::on_note_off_event(int key, int velocity) {
169        if (!this->state) return;
170        GigEditState* state = (GigEditState*) this->state;
171        state->window->signal_note_off().emit(key, velocity);
172    }
173    
174  sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {  sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
175      return file_structure_to_be_changed_signal;      return file_structure_to_be_changed_signal;
176  }  }
# Line 142  sigc::signal<void, gig::DimensionRegion* Line 206  sigc::signal<void, gig::DimensionRegion*
206  sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {  sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
207      return sample_ref_changed_signal;      return sample_ref_changed_signal;
208  }  }
209    
210    
211    Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
212    Glib::Dispatcher* GigEditState::dispatcher = 0;
213    GigEditState* GigEditState::current = 0;
214    
215    void GigEditState::open_window_static() {
216        GigEditState* c = GigEditState::current;
217        c->open.signal();
218        c->open_window();
219    }
220    
221    void GigEditState::open_window() {
222        window = new MainWindow();
223    
224        connect_signals(parent, window);
225        if (instrument) window->load_instrument(instrument);
226    
227        window->signal_hide().connect(sigc::mem_fun(this,
228                                                    &GigEditState::close_window));
229        window->present();
230    }
231    
232    void GigEditState::close_window() {
233        delete window;
234        close.signal();
235    }
236    
237    void GigEditState::main_loop_run(Cond* initialized) {
238        int argc = 1;
239        const char* argv_c[] = { "gigedit" };
240        char** argv = const_cast<char**>(argv_c);
241        Gtk::Main main_loop(argc, argv);
242    
243        dispatcher = new Glib::Dispatcher();
244        dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
245        initialized->signal();
246    
247        main_loop.run();
248    }
249    
250    void GigEditState::run(gig::Instrument* pInstrument) {
251        mutex.lock(); // lock access to static variables
252    
253        static bool main_loop_started = false;
254        if (!main_loop_started) {
255            Cond initialized;
256            Glib::Thread::create(
257                sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
258                           &initialized),
259                false);
260            initialized.wait();
261            main_loop_started = true;
262        }
263        instrument = pInstrument;
264        current = this;
265        dispatcher->emit();
266        open.wait(); // wait until the GUI thread has read current
267        mutex.unlock();
268        close.wait(); // sleep until window is closed
269    }

Legend:
Removed from v.1339  
changed lines
  Added in v.1656

  ViewVC Help
Powered by ViewVC