/[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 1853 - (hide annotations) (download)
Sun Mar 1 22:26:36 2009 UTC (15 years, 1 month ago) by schoenebeck
File size: 9031 byte(s)
* bugfix: inform the sampler when new file(s) has been imported on save
  operation (#82)

1 schoenebeck 1225 /*
2 schoenebeck 1654 * Copyright (C) 2007, 2008 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     void init_app() {
83 schoenebeck 1333 static bool process_initialized = false;
84     if (!process_initialized) {
85     std::cout << "Initializing 3rd party services needed by gigedit.\n"
86     << std::flush;
87     setlocale(LC_ALL, "");
88 schoenebeck 1396
89     #if HAVE_GETTEXT
90 persson 1823
91     #ifdef WIN32
92     #if GLIB_CHECK_VERSION(2, 16, 0)
93     gchar* root =
94     g_win32_get_package_installation_directory_of_module(NULL);
95     #else
96     gchar* root =
97     g_win32_get_package_installation_directory(NULL, NULL);
98     #endif
99     gchar* temp = g_build_filename(root, "/share/locale", NULL);
100     g_free(root);
101     gchar* localedir = g_win32_locale_filename_from_utf8(temp);
102     g_free(temp);
103     bindtextdomain(GETTEXT_PACKAGE, localedir);
104     g_free(localedir);
105     #else
106 schoenebeck 1333 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
107 persson 1823 #endif
108 schoenebeck 1333 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
109     textdomain(GETTEXT_PACKAGE);
110 schoenebeck 1396 #endif // HAVE_GETTEXT
111    
112 schoenebeck 1333 // make sure thread_init() is called once and ONLY once per process
113     if (!Glib::thread_supported()) Glib::thread_init();
114    
115     process_initialized = true;
116     }
117 schoenebeck 1225 }
118    
119 persson 1456 void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
120 schoenebeck 1322 // the signals of the "GigEdit" class are actually just proxies, that
121     // is they simply forward the signals of the internal classes to the
122     // outer world
123     mainwindow->signal_file_structure_to_be_changed().connect(
124     gigedit->signal_file_structure_to_be_changed().make_slot()
125     );
126     mainwindow->signal_file_structure_changed().connect(
127     gigedit->signal_file_structure_changed().make_slot()
128     );
129     mainwindow->signal_samples_to_be_removed().connect(
130     gigedit->signal_samples_to_be_removed().make_slot()
131     );
132     mainwindow->signal_samples_removed().connect(
133     gigedit->signal_samples_removed().make_slot()
134     );
135     mainwindow->signal_region_to_be_changed().connect(
136     gigedit->signal_region_to_be_changed().make_slot()
137     );
138     mainwindow->signal_region_changed().connect(
139     gigedit->signal_region_changed().make_slot()
140     );
141     mainwindow->signal_dimreg_to_be_changed().connect(
142     gigedit->signal_dimreg_to_be_changed().make_slot()
143     );
144     mainwindow->signal_dimreg_changed().connect(
145     gigedit->signal_dimreg_changed().make_slot()
146     );
147 schoenebeck 1853 mainwindow->signal_sample_changed().connect(
148     gigedit->signal_sample_changed().make_slot()
149     );
150 schoenebeck 1322 mainwindow->signal_sample_ref_changed().connect(
151     gigedit->signal_sample_ref_changed().make_slot()
152     );
153 schoenebeck 1660 mainwindow->signal_keyboard_key_hit().connect(
154     gigedit->signal_keyboard_key_hit().make_slot()
155     );
156     mainwindow->signal_keyboard_key_released().connect(
157     gigedit->signal_keyboard_key_released().make_slot()
158     );
159 schoenebeck 1322 }
160    
161 schoenebeck 1654 } // namespace
162    
163     GigEdit::GigEdit() {
164     state = NULL;
165 schoenebeck 1225 }
166    
167 persson 1456 int GigEdit::run(int argc, char* argv[]) {
168     init_app();
169    
170     Gtk::Main kit(argc, argv);
171 schoenebeck 1225 MainWindow window;
172 persson 1456 connect_signals(this, &window);
173     if (argc >= 2) window.load_file(argv[1]);
174 schoenebeck 1225 kit.run(window);
175     return 0;
176     }
177    
178     int GigEdit::run(gig::Instrument* pInstrument) {
179 persson 1456 init_app();
180    
181     GigEditState state(this);
182 schoenebeck 1654 this->state = &state;
183 persson 1456 state.run(pInstrument);
184 schoenebeck 1654 this->state = NULL;
185 schoenebeck 1225 return 0;
186     }
187 schoenebeck 1322
188 schoenebeck 1654 void GigEdit::on_note_on_event(int key, int velocity) {
189     if (!this->state) return;
190     GigEditState* state = (GigEditState*) this->state;
191     state->window->signal_note_on().emit(key, velocity);
192     }
193    
194     void GigEdit::on_note_off_event(int key, int velocity) {
195     if (!this->state) return;
196     GigEditState* state = (GigEditState*) this->state;
197     state->window->signal_note_off().emit(key, velocity);
198     }
199    
200 schoenebeck 1339 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
201 schoenebeck 1322 return file_structure_to_be_changed_signal;
202     }
203    
204 schoenebeck 1339 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
205 schoenebeck 1322 return file_structure_changed_signal;
206     }
207    
208 schoenebeck 1339 sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
209 schoenebeck 1322 return samples_to_be_removed_signal;
210     }
211    
212 schoenebeck 1339 sigc::signal<void>& GigEdit::signal_samples_removed() {
213 schoenebeck 1322 return samples_removed_signal;
214     }
215    
216 schoenebeck 1339 sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
217 schoenebeck 1322 return region_to_be_changed_signal;
218     }
219    
220 schoenebeck 1339 sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
221 schoenebeck 1322 return region_changed_signal;
222     }
223    
224 schoenebeck 1339 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
225 schoenebeck 1322 return dimreg_to_be_changed_signal;
226     }
227    
228 schoenebeck 1339 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
229 schoenebeck 1322 return dimreg_changed_signal;
230     }
231    
232 schoenebeck 1853 sigc::signal<void, gig::Sample*>& GigEdit::signal_sample_changed() {
233     return sample_changed_signal;
234     }
235    
236 schoenebeck 1339 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
237 schoenebeck 1322 return sample_ref_changed_signal;
238     }
239 persson 1456
240 schoenebeck 1660 sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_hit() {
241     return keyboard_key_hit_signal;
242     }
243 persson 1456
244 schoenebeck 1660 sigc::signal<void, int/*key*/, int/*velocity*/>& GigEdit::signal_keyboard_key_released() {
245     return keyboard_key_released_signal;
246     }
247    
248 persson 1456 Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
249     Glib::Dispatcher* GigEditState::dispatcher = 0;
250     GigEditState* GigEditState::current = 0;
251    
252     void GigEditState::open_window_static() {
253     GigEditState* c = GigEditState::current;
254     c->open.signal();
255     c->open_window();
256     }
257    
258     void GigEditState::open_window() {
259     window = new MainWindow();
260    
261     connect_signals(parent, window);
262     if (instrument) window->load_instrument(instrument);
263    
264     window->signal_hide().connect(sigc::mem_fun(this,
265     &GigEditState::close_window));
266     window->present();
267     }
268    
269     void GigEditState::close_window() {
270     delete window;
271     close.signal();
272     }
273    
274     void GigEditState::main_loop_run(Cond* initialized) {
275     int argc = 1;
276     const char* argv_c[] = { "gigedit" };
277     char** argv = const_cast<char**>(argv_c);
278     Gtk::Main main_loop(argc, argv);
279    
280     dispatcher = new Glib::Dispatcher();
281     dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
282     initialized->signal();
283    
284     main_loop.run();
285     }
286    
287     void GigEditState::run(gig::Instrument* pInstrument) {
288     mutex.lock(); // lock access to static variables
289    
290     static bool main_loop_started = false;
291     if (!main_loop_started) {
292     Cond initialized;
293     Glib::Thread::create(
294     sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
295     &initialized),
296     false);
297     initialized.wait();
298     main_loop_started = true;
299     }
300     instrument = pInstrument;
301     current = this;
302     dispatcher->emit();
303     open.wait(); // wait until the GUI thread has read current
304     mutex.unlock();
305     close.wait(); // sleep until window is closed
306     }

  ViewVC Help
Powered by ViewVC