/[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 1322 by schoenebeck, Tue Sep 4 11:04:56 2007 UTC revision 1898 by persson, Sun May 10 09:35:56 2009 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2007 Andreas Persson   * Copyright (C) 2007-2009 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);  
29    
30  static void __init_app() {  // State for a gigedit thread.
31      setlocale(LC_ALL, "");  //
32      bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);  // This class is only used when gigedit is run as a plugin and makes
33      bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");  // sure that there's only one Gtk::Main event loop. The event loop is
34      textdomain(GETTEXT_PACKAGE);  // 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    #ifdef WIN32
83    HINSTANCE gigedit_dll_handle = 0;
84    #endif
85    
86    void init_app() {
87        static bool process_initialized = false;
88        if (!process_initialized) {
89            std::cout << "Initializing 3rd party services needed by gigedit.\n"
90                      << std::flush;
91            setlocale(LC_ALL, "");
92    
93    #if HAVE_GETTEXT
94    
95    #ifdef WIN32
96    #if GLIB_CHECK_VERSION(2, 16, 0)
97            gchar* root =
98                g_win32_get_package_installation_directory_of_module(gigedit_dll_handle);
99    #else
100            gchar* root =
101                g_win32_get_package_installation_directory(NULL, NULL);
102    #endif
103            gchar* temp = g_build_filename(root, "/share/locale", NULL);
104            g_free(root);
105            gchar* localedir = g_win32_locale_filename_from_utf8(temp);
106            g_free(temp);
107            bindtextdomain(GETTEXT_PACKAGE, localedir);
108            g_free(localedir);
109    #else
110            bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
111    #endif
112            bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
113            textdomain(GETTEXT_PACKAGE);
114    #endif // HAVE_GETTEXT
115    
116      Glib::thread_init();          // make sure thread_init() is called once and ONLY once per process
117            if (!Glib::thread_supported()) Glib::thread_init();
118    
119            process_initialized = true;
120        }
121  }  }
122    
123  static void __connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {  void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
124      // the signals of the "GigEdit" class are actually just proxies, that      // the signals of the "GigEdit" class are actually just proxies, that
125      // is they simply forward the signals of the internal classes to the      // is they simply forward the signals of the internal classes to the
126      // outer world      // outer world
# Line 67  static void __connect_signals(GigEdit* g Line 148  static void __connect_signals(GigEdit* g
148      mainwindow->signal_dimreg_changed().connect(      mainwindow->signal_dimreg_changed().connect(
149          gigedit->signal_dimreg_changed().make_slot()          gigedit->signal_dimreg_changed().make_slot()
150      );      );
151        mainwindow->signal_sample_changed().connect(
152            gigedit->signal_sample_changed().make_slot()
153        );
154      mainwindow->signal_sample_ref_changed().connect(      mainwindow->signal_sample_ref_changed().connect(
155          gigedit->signal_sample_ref_changed().make_slot()          gigedit->signal_sample_ref_changed().make_slot()
156      );      );
157        mainwindow->signal_keyboard_key_hit().connect(
158            gigedit->signal_keyboard_key_hit().make_slot()
159        );
160        mainwindow->signal_keyboard_key_released().connect(
161            gigedit->signal_keyboard_key_released().make_slot()
162        );
163  }  }
164    
165  int GigEdit::run() {  } // namespace
166      __init_app();  
167      Gtk::Main kit(argc, argv);  GigEdit::GigEdit() {
168      MainWindow window;      state = NULL;
     __connect_signals(this, &window);  
     kit.run(window);  
     return 0;  
169  }  }
170    
171  int GigEdit::run(const char* pFileName) {  int GigEdit::run(int argc, char* argv[]) {
172      __init_app();      init_app();
173    
174      Gtk::Main kit(argc, argv);      Gtk::Main kit(argc, argv);
175      MainWindow window;      MainWindow window;
176      __connect_signals(this, &window);      connect_signals(this, &window);
177      if (pFileName) window.load_file(pFileName);      if (argc >= 2) window.load_file(argv[1]);
178      kit.run(window);      kit.run(window);
179      return 0;      return 0;
180  }  }
181    
182  int GigEdit::run(gig::Instrument* pInstrument) {  int GigEdit::run(gig::Instrument* pInstrument) {
183      __init_app();      init_app();
184      Gtk::Main kit(argc, argv);  
185      MainWindow window;      GigEditState state(this);
186      __connect_signals(this, &window);      this->state = &state;
187      if (pInstrument) window.load_instrument(pInstrument);      state.run(pInstrument);
188      kit.run(window);      this->state = NULL;
189      return 0;      return 0;
190  }  }
191    
192  sigc::signal<void, gig::File*> GigEdit::signal_file_structure_to_be_changed() {  void GigEdit::on_note_on_event(int key, int velocity) {
193        if (!this->state) return;
194        GigEditState* state = (GigEditState*) this->state;
195        state->window->signal_note_on().emit(key, velocity);
196    }
197    
198    void GigEdit::on_note_off_event(int key, int velocity) {
199        if (!this->state) return;
200        GigEditState* state = (GigEditState*) this->state;
201        state->window->signal_note_off().emit(key, velocity);
202    }
203    
204    sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
205      return file_structure_to_be_changed_signal;      return file_structure_to_be_changed_signal;
206  }  }
207    
208  sigc::signal<void, gig::File*> GigEdit::signal_file_structure_changed() {  sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
209      return file_structure_changed_signal;      return file_structure_changed_signal;
210  }  }
211    
212  sigc::signal<void, std::list<gig::Sample*> > GigEdit::signal_samples_to_be_removed() {  sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
213      return samples_to_be_removed_signal;      return samples_to_be_removed_signal;
214  }  }
215    
216  sigc::signal<void> GigEdit::signal_samples_removed() {  sigc::signal<void>& GigEdit::signal_samples_removed() {
217      return samples_removed_signal;      return samples_removed_signal;
218  }  }
219    
220  sigc::signal<void, gig::Region*> GigEdit::signal_region_to_be_changed() {  sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
221      return region_to_be_changed_signal;      return region_to_be_changed_signal;
222  }  }
223    
224  sigc::signal<void, gig::Region*> GigEdit::signal_region_changed() {  sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
225      return region_changed_signal;      return region_changed_signal;
226  }  }
227    
228  sigc::signal<void, gig::DimensionRegion*> GigEdit::signal_dimreg_to_be_changed() {  sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
229      return dimreg_to_be_changed_signal;      return dimreg_to_be_changed_signal;
230  }  }
231    
232  sigc::signal<void, gig::DimensionRegion*> GigEdit::signal_dimreg_changed() {  sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
233      return dimreg_changed_signal;      return dimreg_changed_signal;
234  }  }
235    
236  sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/> GigEdit::signal_sample_ref_changed() {  sigc::signal<void, gig::Sample*>& GigEdit::signal_sample_changed() {
237        return sample_changed_signal;
238    }
239    
240    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
241      return sample_ref_changed_signal;      return sample_ref_changed_signal;
242  }  }
243    
244    sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_hit() {
245        return keyboard_key_hit_signal;
246    }
247    
248    sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_released() {
249        return keyboard_key_released_signal;
250    }
251    
252    Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
253    Glib::Dispatcher* GigEditState::dispatcher = 0;
254    GigEditState* GigEditState::current = 0;
255    
256    void GigEditState::open_window_static() {
257        GigEditState* c = GigEditState::current;
258        c->open.signal();
259        c->open_window();
260    }
261    
262    void GigEditState::open_window() {
263        window = new MainWindow();
264    
265        connect_signals(parent, window);
266        if (instrument) window->load_instrument(instrument);
267    
268        window->signal_hide().connect(sigc::mem_fun(this,
269                                                    &GigEditState::close_window));
270        window->present();
271    }
272    
273    void GigEditState::close_window() {
274        delete window;
275        close.signal();
276    }
277    
278    void GigEditState::main_loop_run(Cond* initialized) {
279        int argc = 1;
280        const char* argv_c[] = { "gigedit" };
281        char** argv = const_cast<char**>(argv_c);
282        Gtk::Main main_loop(argc, argv);
283    
284        dispatcher = new Glib::Dispatcher();
285        dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
286        initialized->signal();
287    
288        main_loop.run();
289    }
290    
291    void GigEditState::run(gig::Instrument* pInstrument) {
292        mutex.lock(); // lock access to static variables
293    
294        static bool main_loop_started = false;
295        if (!main_loop_started) {
296            Cond initialized;
297            Glib::Thread::create(
298                sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
299                           &initialized),
300                false);
301            initialized.wait();
302            main_loop_started = true;
303        }
304        instrument = pInstrument;
305        current = this;
306        dispatcher->emit();
307        open.wait(); // wait until the GUI thread has read current
308        mutex.unlock();
309        close.wait(); // sleep until window is closed
310    }
311    
312    #if defined(WIN32)
313    extern "C" {
314        BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
315        {
316            switch (reason) {
317            case DLL_PROCESS_ATTACH:
318                gigedit_dll_handle = instance;
319                break;
320            }
321            return TRUE;
322        }
323    }
324    #endif

Legend:
Removed from v.1322  
changed lines
  Added in v.1898

  ViewVC Help
Powered by ViewVC