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

Annotation of /gigedit/trunk/src/gigedit/gigedit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1898 - (hide annotations) (download)
Sun May 10 09:35:56 2009 UTC (14 years, 11 months ago) by persson
File size: 9380 byte(s)
* Windows: look for translations using base directory of libgigedit
  dll
* virtual keyboard fixes: restore to grey when outside keyboard. Don't
  trigger multiple notes for each key when moving mouse.

1 schoenebeck 1225 /*
2 persson 1898 * Copyright (C) 2007-2009 Andreas Persson
3 schoenebeck 1225 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2, or (at
7     * your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20     #include "gigedit.h"
21    
22     #include <gtkmm/main.h>
23 schoenebeck 1654 #include <glibmm/main.h>
24 schoenebeck 1225 #include "mainwindow.h"
25    
26 schoenebeck 1396 #include "global.h"
27 schoenebeck 1225
28 persson 1456 namespace {
29 schoenebeck 1225
30 persson 1456 // 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 schoenebeck 1654 MainWindow* window;
44    
45 persson 1456 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 persson 1898 #ifdef WIN32
83     HINSTANCE gigedit_dll_handle = 0;
84     #endif
85    
86 persson 1456 void init_app() {
87 schoenebeck 1333 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 schoenebeck 1396
93     #if HAVE_GETTEXT
94 persson 1823
95     #ifdef WIN32
96     #if GLIB_CHECK_VERSION(2, 16, 0)
97     gchar* root =
98 persson 1898 g_win32_get_package_installation_directory_of_module(gigedit_dll_handle);
99 persson 1823 #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 schoenebeck 1333 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
111 persson 1823 #endif
112 schoenebeck 1333 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
113     textdomain(GETTEXT_PACKAGE);
114 schoenebeck 1396 #endif // HAVE_GETTEXT
115    
116 schoenebeck 1333 // 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 schoenebeck 1225 }
122    
123 persson 1456 void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
124 schoenebeck 1322 // the signals of the "GigEdit" class are actually just proxies, that
125     // is they simply forward the signals of the internal classes to the
126     // outer world
127     mainwindow->signal_file_structure_to_be_changed().connect(
128     gigedit->signal_file_structure_to_be_changed().make_slot()
129     );
130     mainwindow->signal_file_structure_changed().connect(
131     gigedit->signal_file_structure_changed().make_slot()
132     );
133     mainwindow->signal_samples_to_be_removed().connect(
134     gigedit->signal_samples_to_be_removed().make_slot()
135     );
136     mainwindow->signal_samples_removed().connect(
137     gigedit->signal_samples_removed().make_slot()
138     );
139     mainwindow->signal_region_to_be_changed().connect(
140     gigedit->signal_region_to_be_changed().make_slot()
141     );
142     mainwindow->signal_region_changed().connect(
143     gigedit->signal_region_changed().make_slot()
144     );
145     mainwindow->signal_dimreg_to_be_changed().connect(
146     gigedit->signal_dimreg_to_be_changed().make_slot()
147     );
148     mainwindow->signal_dimreg_changed().connect(
149     gigedit->signal_dimreg_changed().make_slot()
150     );
151 schoenebeck 1853 mainwindow->signal_sample_changed().connect(
152     gigedit->signal_sample_changed().make_slot()
153     );
154 schoenebeck 1322 mainwindow->signal_sample_ref_changed().connect(
155     gigedit->signal_sample_ref_changed().make_slot()
156     );
157 schoenebeck 1660 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 schoenebeck 1322 }
164    
165 schoenebeck 1654 } // namespace
166    
167     GigEdit::GigEdit() {
168     state = NULL;
169 schoenebeck 1225 }
170    
171 persson 1456 int GigEdit::run(int argc, char* argv[]) {
172     init_app();
173    
174     Gtk::Main kit(argc, argv);
175 schoenebeck 1225 MainWindow window;
176 persson 1456 connect_signals(this, &window);
177     if (argc >= 2) window.load_file(argv[1]);
178 schoenebeck 1225 kit.run(window);
179     return 0;
180     }
181    
182     int GigEdit::run(gig::Instrument* pInstrument) {
183 persson 1456 init_app();
184    
185     GigEditState state(this);
186 schoenebeck 1654 this->state = &state;
187 persson 1456 state.run(pInstrument);
188 schoenebeck 1654 this->state = NULL;
189 schoenebeck 1225 return 0;
190     }
191 schoenebeck 1322
192 schoenebeck 1654 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 schoenebeck 1339 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
205 schoenebeck 1322 return file_structure_to_be_changed_signal;
206     }
207    
208 schoenebeck 1339 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
209 schoenebeck 1322 return file_structure_changed_signal;
210     }
211    
212 schoenebeck 1339 sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
213 schoenebeck 1322 return samples_to_be_removed_signal;
214     }
215    
216 schoenebeck 1339 sigc::signal<void>& GigEdit::signal_samples_removed() {
217 schoenebeck 1322 return samples_removed_signal;
218     }
219    
220 schoenebeck 1339 sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
221 schoenebeck 1322 return region_to_be_changed_signal;
222     }
223    
224 schoenebeck 1339 sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
225 schoenebeck 1322 return region_changed_signal;
226     }
227    
228 schoenebeck 1339 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
229 schoenebeck 1322 return dimreg_to_be_changed_signal;
230     }
231    
232 schoenebeck 1339 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
233 schoenebeck 1322 return dimreg_changed_signal;
234     }
235    
236 schoenebeck 1853 sigc::signal<void, gig::Sample*>& GigEdit::signal_sample_changed() {
237     return sample_changed_signal;
238     }
239    
240 schoenebeck 1339 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
241 schoenebeck 1322 return sample_ref_changed_signal;
242     }
243 persson 1456
244 schoenebeck 1660 sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_hit() {
245     return keyboard_key_hit_signal;
246     }
247 persson 1456
248 schoenebeck 1660 sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_released() {
249     return keyboard_key_released_signal;
250     }
251    
252 persson 1456 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 persson 1898
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

  ViewVC Help
Powered by ViewVC