/[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 1328 by schoenebeck, Fri Sep 7 21:18:31 2007 UTC revision 2332 by persson, Wed Mar 14 05:22:26 2012 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 19  Line 19 
19    
20  #include "gigedit.h"  #include "gigedit.h"
21    
22    #include <glibmm/dispatcher.h>
23    #include <glibmm/main.h>
24  #include <gtkmm/main.h>  #include <gtkmm/main.h>
25    
26  #include "mainwindow.h"  #include "mainwindow.h"
27    
28  #include <libintl.h>  #include "global.h"
29  #include <config.h>  
30    namespace {
31    
32  // the app has to work from a DLL as well, so we hard code argv  // State for a gigedit thread.
33  int argc = 1;  //
34  const char* argv_c[] = { "gigedit" };  // This class is only used when gigedit is run as a plugin and makes
35  char** argv = const_cast<char**>(argv_c);  // sure that there's only one Gtk::Main event loop. The event loop is
36    // started in a separate thread. The plugin thread just dispatches an
37  static void __init_app() {  // event to the main loop to open a window and then goes to sleep
38      setlocale(LC_ALL, "");  // until the window is closed.
39      bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);  //
40      bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");  class GigEditState : public sigc::trackable {
41      textdomain(GETTEXT_PACKAGE);  public:
42      // make sure thread_init() is called once and ONLY once per process      GigEditState(GigEdit* parent) : parent(parent) { }
43      if (!Glib::thread_supported()) Glib::thread_init();      void run(gig::Instrument* pInstrument);
44    
45        MainWindow* window;
46    
47    private:
48    
49        // simple condition variable abstraction
50        class Cond {
51        private:
52            bool pred;
53            Glib::Threads::Mutex mutex;
54            Glib::Threads::Cond cond;
55        public:
56            Cond() : pred(false) { }
57            void signal() {
58                Glib::Threads::Mutex::Lock lock(mutex);
59                pred = true;
60                cond.signal();
61            }
62            void wait() {
63                Glib::Threads::Mutex::Lock lock(mutex);
64                while (!pred) cond.wait(mutex);
65            }
66        };
67    
68    #ifdef OLD_THREADS
69        static Glib::StaticMutex mutex;
70    #else
71        static Glib::Threads::Mutex mutex;
72    #endif
73        static Glib::Dispatcher* dispatcher;
74        static GigEditState* current;
75    
76        static void main_loop_run(Cond* intialized);
77        static void open_window_static();
78    
79        GigEdit* parent;
80        Cond open;
81        Cond close;
82        gig::Instrument* instrument;
83    
84        void open_window();
85        void close_window();
86    };
87    
88    #ifdef WIN32
89    HINSTANCE gigedit_dll_handle = 0;
90    #endif
91    
92    void init_app() {
93        static bool process_initialized = false;
94        if (!process_initialized) {
95            std::cout << "Initializing 3rd party services needed by gigedit.\n"
96                      << std::flush;
97            setlocale(LC_ALL, "");
98    
99    #if HAVE_GETTEXT
100    
101    #ifdef WIN32
102    #if GLIB_CHECK_VERSION(2, 16, 0)
103            gchar* root =
104                g_win32_get_package_installation_directory_of_module(gigedit_dll_handle);
105    #else
106            gchar* root =
107                g_win32_get_package_installation_directory(NULL, NULL);
108    #endif
109            gchar* temp = g_build_filename(root, "/share/locale", NULL);
110            g_free(root);
111            gchar* localedir = g_win32_locale_filename_from_utf8(temp);
112            g_free(temp);
113            bindtextdomain(GETTEXT_PACKAGE, localedir);
114            g_free(localedir);
115    #else
116            bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
117    #endif
118            bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
119            textdomain(GETTEXT_PACKAGE);
120    #endif // HAVE_GETTEXT
121    
122    #ifdef OLD_THREADS
123            // make sure thread_init() is called once and ONLY once per process
124            if (!Glib::thread_supported()) Glib::thread_init();
125    #endif
126            process_initialized = true;
127        }
128  }  }
129    
130  static void __connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {  void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
131      // the signals of the "GigEdit" class are actually just proxies, that      // the signals of the "GigEdit" class are actually just proxies, that
132      // is they simply forward the signals of the internal classes to the      // is they simply forward the signals of the internal classes to the
133      // outer world      // outer world
# Line 67  static void __connect_signals(GigEdit* g Line 155  static void __connect_signals(GigEdit* g
155      mainwindow->signal_dimreg_changed().connect(      mainwindow->signal_dimreg_changed().connect(
156          gigedit->signal_dimreg_changed().make_slot()          gigedit->signal_dimreg_changed().make_slot()
157      );      );
158        mainwindow->signal_sample_changed().connect(
159            gigedit->signal_sample_changed().make_slot()
160        );
161      mainwindow->signal_sample_ref_changed().connect(      mainwindow->signal_sample_ref_changed().connect(
162          gigedit->signal_sample_ref_changed().make_slot()          gigedit->signal_sample_ref_changed().make_slot()
163      );      );
164        mainwindow->signal_keyboard_key_hit().connect(
165            gigedit->signal_keyboard_key_hit().make_slot()
166        );
167        mainwindow->signal_keyboard_key_released().connect(
168            gigedit->signal_keyboard_key_released().make_slot()
169        );
170  }  }
171    
172  int GigEdit::run() {  } // namespace
173      __init_app();  
174      Gtk::Main kit(argc, argv);  GigEdit::GigEdit() {
175      MainWindow window;      state = NULL;
     __connect_signals(this, &window);  
     kit.run(window);  
     return 0;  
176  }  }
177    
178  int GigEdit::run(const char* pFileName) {  int GigEdit::run(int argc, char* argv[]) {
179      __init_app();      init_app();
180    
181      Gtk::Main kit(argc, argv);      Gtk::Main kit(argc, argv);
182      MainWindow window;      MainWindow window;
183      __connect_signals(this, &window);      connect_signals(this, &window);
184      if (pFileName) window.load_file(pFileName);      if (argc >= 2) window.load_file(argv[1]);
185      kit.run(window);      kit.run(window);
186      return 0;      return 0;
187  }  }
188    
189  int GigEdit::run(gig::Instrument* pInstrument) {  int GigEdit::run(gig::Instrument* pInstrument) {
190      __init_app();      init_app();
191      Gtk::Main kit(argc, argv);  
192      MainWindow window;      GigEditState state(this);
193      __connect_signals(this, &window);      this->state = &state;
194      if (pInstrument) window.load_instrument(pInstrument);      state.run(pInstrument);
195      kit.run(window);      this->state = NULL;
196      return 0;      return 0;
197  }  }
198    
199  sigc::signal<void, gig::File*> GigEdit::signal_file_structure_to_be_changed() {  void GigEdit::on_note_on_event(int key, int velocity) {
200        if (!this->state) return;
201        GigEditState* state = (GigEditState*) this->state;
202        state->window->signal_note_on().emit(key, velocity);
203    }
204    
205    void GigEdit::on_note_off_event(int key, int velocity) {
206        if (!this->state) return;
207        GigEditState* state = (GigEditState*) this->state;
208        state->window->signal_note_off().emit(key, velocity);
209    }
210    
211    sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
212      return file_structure_to_be_changed_signal;      return file_structure_to_be_changed_signal;
213  }  }
214    
215  sigc::signal<void, gig::File*> GigEdit::signal_file_structure_changed() {  sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
216      return file_structure_changed_signal;      return file_structure_changed_signal;
217  }  }
218    
219  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() {
220      return samples_to_be_removed_signal;      return samples_to_be_removed_signal;
221  }  }
222    
223  sigc::signal<void> GigEdit::signal_samples_removed() {  sigc::signal<void>& GigEdit::signal_samples_removed() {
224      return samples_removed_signal;      return samples_removed_signal;
225  }  }
226    
227  sigc::signal<void, gig::Region*> GigEdit::signal_region_to_be_changed() {  sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
228      return region_to_be_changed_signal;      return region_to_be_changed_signal;
229  }  }
230    
231  sigc::signal<void, gig::Region*> GigEdit::signal_region_changed() {  sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
232      return region_changed_signal;      return region_changed_signal;
233  }  }
234    
235  sigc::signal<void, gig::DimensionRegion*> GigEdit::signal_dimreg_to_be_changed() {  sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
236      return dimreg_to_be_changed_signal;      return dimreg_to_be_changed_signal;
237  }  }
238    
239  sigc::signal<void, gig::DimensionRegion*> GigEdit::signal_dimreg_changed() {  sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
240      return dimreg_changed_signal;      return dimreg_changed_signal;
241  }  }
242    
243  sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/> GigEdit::signal_sample_ref_changed() {  sigc::signal<void, gig::Sample*>& GigEdit::signal_sample_changed() {
244        return sample_changed_signal;
245    }
246    
247    sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
248      return sample_ref_changed_signal;      return sample_ref_changed_signal;
249  }  }
250    
251    sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_hit() {
252        return keyboard_key_hit_signal;
253    }
254    
255    sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_released() {
256        return keyboard_key_released_signal;
257    }
258    
259    #ifdef OLD_THREADS
260    Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
261    #else
262    Glib::Threads::Mutex GigEditState::mutex;
263    #endif
264    Glib::Dispatcher* GigEditState::dispatcher = 0;
265    GigEditState* GigEditState::current = 0;
266    
267    void GigEditState::open_window_static() {
268        GigEditState* c = GigEditState::current;
269        c->open.signal();
270        c->open_window();
271    }
272    
273    void GigEditState::open_window() {
274        window = new MainWindow();
275    
276        connect_signals(parent, window);
277        if (instrument) window->load_instrument(instrument);
278    
279        window->signal_hide().connect(sigc::mem_fun(this,
280                                                    &GigEditState::close_window));
281        window->present();
282    }
283    
284    void GigEditState::close_window() {
285        delete window;
286        close.signal();
287    }
288    
289    void GigEditState::main_loop_run(Cond* initialized) {
290        int argc = 1;
291        const char* argv_c[] = { "gigedit" };
292        char** argv = const_cast<char**>(argv_c);
293        Gtk::Main main_loop(argc, argv);
294    
295        dispatcher = new Glib::Dispatcher();
296        dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
297        initialized->signal();
298    
299        main_loop.run();
300    }
301    
302    void GigEditState::run(gig::Instrument* pInstrument) {
303        mutex.lock(); // lock access to static variables
304    
305        static bool main_loop_started = false;
306        if (!main_loop_started) {
307            Cond initialized;
308    #ifdef OLD_THREADS
309            Glib::Thread::create(
310                sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
311                           &initialized),
312                false);
313    #else
314            Glib::Threads::Thread::create(
315                sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
316                           &initialized));
317    #endif
318            initialized.wait();
319            main_loop_started = true;
320        }
321        instrument = pInstrument;
322        current = this;
323        dispatcher->emit();
324        open.wait(); // wait until the GUI thread has read current
325        mutex.unlock();
326        close.wait(); // sleep until window is closed
327    }
328    
329    #if defined(WIN32)
330    extern "C" {
331        BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
332        {
333            switch (reason) {
334            case DLL_PROCESS_ATTACH:
335                gigedit_dll_handle = instance;
336                break;
337            }
338            return TRUE;
339        }
340    }
341    #endif

Legend:
Removed from v.1328  
changed lines
  Added in v.2332

  ViewVC Help
Powered by ViewVC