/[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 1396 by schoenebeck, Wed Oct 10 15:48:54 2007 UTC revision 1456 by persson, Sun Oct 21 15:32:36 2007 UTC
# Line 24  Line 24 
24    
25  #include "global.h"  #include "global.h"
26    
27  // 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);  
28    
29  static void __init_app() {  // State for a gigedit thread.
30    //
31    // This class is only used when gigedit is run as a plugin and makes
32    // sure that there's only one Gtk::Main event loop. The event loop is
33    // started in a separate thread. The plugin thread just dispatches an
34    // event to the main loop to open a window and then goes to sleep
35    // until the window is closed.
36    //
37    class GigEditState : public sigc::trackable {
38    public:
39        GigEditState(GigEdit* parent) : parent(parent) { }
40        void run(gig::Instrument* pInstrument);
41    
42    private:
43    
44        // simple condition variable abstraction
45        class Cond {
46        private:
47            bool pred;
48            Glib::Mutex mutex;
49            Glib::Cond cond;
50        public:
51            Cond() : pred(false) { }
52            void signal() {
53                Glib::Mutex::Lock lock(mutex);
54                pred = true;
55                cond.signal();
56            }
57            void wait() {
58                Glib::Mutex::Lock lock(mutex);
59                while (!pred) cond.wait(mutex);
60            }
61        };
62    
63        static Glib::StaticMutex mutex;
64        static Glib::Dispatcher* dispatcher;
65        static GigEditState* current;
66    
67        static void main_loop_run(Cond* intialized);
68        static void open_window_static();
69    
70        GigEdit* parent;
71        Cond open;
72        Cond close;
73        gig::Instrument* instrument;
74        MainWindow* window;
75    
76        void open_window();
77        void close_window();
78    };
79    
80    void init_app() {
81      static bool process_initialized = false;      static bool process_initialized = false;
82      if (!process_initialized) {      if (!process_initialized) {
83          std::cout << "Initializing 3rd party services needed by gigedit.\n"          std::cout << "Initializing 3rd party services needed by gigedit.\n"
# Line 51  static void __init_app() { Line 97  static void __init_app() {
97      }      }
98  }  }
99    
100  static void __connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {  void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
101      // the signals of the "GigEdit" class are actually just proxies, that      // the signals of the "GigEdit" class are actually just proxies, that
102      // is they simply forward the signals of the internal classes to the      // is they simply forward the signals of the internal classes to the
103      // outer world      // outer world
# Line 84  static void __connect_signals(GigEdit* g Line 130  static void __connect_signals(GigEdit* g
130      );      );
131  }  }
132    
 int GigEdit::run() {  
     __init_app();  
     MainWindow window;  
     __connect_signals(this, &window);  
     kit.run(window);  
     return 0;  
133  }  }
134    
135  int GigEdit::run(const char* pFileName) {  
136      __init_app();  int GigEdit::run(int argc, char* argv[]) {
137        init_app();
138    
139        Gtk::Main kit(argc, argv);
140      MainWindow window;      MainWindow window;
141      __connect_signals(this, &window);      connect_signals(this, &window);
142      if (pFileName) window.load_file(pFileName);      if (argc >= 2) window.load_file(argv[1]);
143      kit.run(window);      kit.run(window);
144      return 0;      return 0;
145  }  }
146    
147  int GigEdit::run(gig::Instrument* pInstrument) {  int GigEdit::run(gig::Instrument* pInstrument) {
148      __init_app();      init_app();
149      MainWindow window;  
150      __connect_signals(this, &window);      GigEditState state(this);
151      if (pInstrument) window.load_instrument(pInstrument);      state.run(pInstrument);
     kit.run(window);  
152      return 0;      return 0;
153  }  }
154    
# Line 145  sigc::signal<void, gig::DimensionRegion* Line 187  sigc::signal<void, gig::DimensionRegion*
187  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() {
188      return sample_ref_changed_signal;      return sample_ref_changed_signal;
189  }  }
190    
191    
192    Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
193    Glib::Dispatcher* GigEditState::dispatcher = 0;
194    GigEditState* GigEditState::current = 0;
195    
196    void GigEditState::open_window_static() {
197        GigEditState* c = GigEditState::current;
198        c->open.signal();
199        c->open_window();
200    }
201    
202    void GigEditState::open_window() {
203        window = new MainWindow();
204    
205        connect_signals(parent, window);
206        if (instrument) window->load_instrument(instrument);
207    
208        window->signal_hide().connect(sigc::mem_fun(this,
209                                                    &GigEditState::close_window));
210        window->present();
211    }
212    
213    void GigEditState::close_window() {
214        delete window;
215        close.signal();
216    }
217    
218    void GigEditState::main_loop_run(Cond* initialized) {
219        int argc = 1;
220        const char* argv_c[] = { "gigedit" };
221        char** argv = const_cast<char**>(argv_c);
222        Gtk::Main main_loop(argc, argv);
223    
224        dispatcher = new Glib::Dispatcher();
225        dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
226        initialized->signal();
227    
228        main_loop.run();
229    }
230    
231    void GigEditState::run(gig::Instrument* pInstrument) {
232        mutex.lock(); // lock access to static variables
233    
234        static bool main_loop_started = false;
235        if (!main_loop_started) {
236            Cond initialized;
237            Glib::Thread::create(
238                sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
239                           &initialized),
240                false);
241            initialized.wait();
242            main_loop_started = true;
243        }
244        instrument = pInstrument;
245        current = this;
246        dispatcher->emit();
247        open.wait(); // wait until the GUI thread has read current
248        mutex.unlock();
249        close.wait(); // sleep until window is closed
250    }

Legend:
Removed from v.1396  
changed lines
  Added in v.1456

  ViewVC Help
Powered by ViewVC