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

Contents of /gigedit/trunk/src/gigedit/gigedit.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1656 - (show annotations) (download)
Sat Feb 2 08:18:19 2008 UTC (16 years, 2 months ago) by schoenebeck
File size: 7804 byte(s)
* bugfix: key highlighting of active keys on the virtual keyboard is now
  working on multiple invocations from the sampler as well
* renamed misleading names regarding the gig format's "keyswitching"
  feature (the dimension is now displayed as "keyswitching" instead of
  "keyboard" in the dimregchooser widget and the two parameters for
  defining the actual keyswitching area on the keyboard in the instruments
  properties dialog are now called "Keyswitching range low/high" instead of
  "Dimension key range low/high")

1 /*
2 * Copyright (C) 2007, 2008 Andreas Persson
3 *
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 #include <glibmm/main.h>
24 #include "mainwindow.h"
25
26 #include "global.h"
27
28 namespace {
29
30 // 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 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 void init_app() {
83 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
89 #if HAVE_GETTEXT
90 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
91 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
92 textdomain(GETTEXT_PACKAGE);
93 #endif // HAVE_GETTEXT
94
95 // make sure thread_init() is called once and ONLY once per process
96 if (!Glib::thread_supported()) Glib::thread_init();
97
98 process_initialized = true;
99 }
100 }
101
102 void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
103 // the signals of the "GigEdit" class are actually just proxies, that
104 // is they simply forward the signals of the internal classes to the
105 // outer world
106 mainwindow->signal_file_structure_to_be_changed().connect(
107 gigedit->signal_file_structure_to_be_changed().make_slot()
108 );
109 mainwindow->signal_file_structure_changed().connect(
110 gigedit->signal_file_structure_changed().make_slot()
111 );
112 mainwindow->signal_samples_to_be_removed().connect(
113 gigedit->signal_samples_to_be_removed().make_slot()
114 );
115 mainwindow->signal_samples_removed().connect(
116 gigedit->signal_samples_removed().make_slot()
117 );
118 mainwindow->signal_region_to_be_changed().connect(
119 gigedit->signal_region_to_be_changed().make_slot()
120 );
121 mainwindow->signal_region_changed().connect(
122 gigedit->signal_region_changed().make_slot()
123 );
124 mainwindow->signal_dimreg_to_be_changed().connect(
125 gigedit->signal_dimreg_to_be_changed().make_slot()
126 );
127 mainwindow->signal_dimreg_changed().connect(
128 gigedit->signal_dimreg_changed().make_slot()
129 );
130 mainwindow->signal_sample_ref_changed().connect(
131 gigedit->signal_sample_ref_changed().make_slot()
132 );
133 }
134
135 } // namespace
136
137 GigEdit::GigEdit() {
138 state = NULL;
139 }
140
141 int GigEdit::run(int argc, char* argv[]) {
142 init_app();
143
144 Gtk::Main kit(argc, argv);
145 MainWindow window;
146 connect_signals(this, &window);
147 if (argc >= 2) window.load_file(argv[1]);
148 kit.run(window);
149 return 0;
150 }
151
152 int GigEdit::run(gig::Instrument* pInstrument) {
153 init_app();
154
155 GigEditState state(this);
156 this->state = &state;
157 state.run(pInstrument);
158 this->state = NULL;
159 return 0;
160 }
161
162 void GigEdit::on_note_on_event(int key, int velocity) {
163 if (!this->state) return;
164 GigEditState* state = (GigEditState*) this->state;
165 state->window->signal_note_on().emit(key, velocity);
166 }
167
168 void GigEdit::on_note_off_event(int key, int velocity) {
169 if (!this->state) return;
170 GigEditState* state = (GigEditState*) this->state;
171 state->window->signal_note_off().emit(key, velocity);
172 }
173
174 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
175 return file_structure_to_be_changed_signal;
176 }
177
178 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
179 return file_structure_changed_signal;
180 }
181
182 sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
183 return samples_to_be_removed_signal;
184 }
185
186 sigc::signal<void>& GigEdit::signal_samples_removed() {
187 return samples_removed_signal;
188 }
189
190 sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
191 return region_to_be_changed_signal;
192 }
193
194 sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
195 return region_changed_signal;
196 }
197
198 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
199 return dimreg_to_be_changed_signal;
200 }
201
202 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
203 return dimreg_changed_signal;
204 }
205
206 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
207 return sample_ref_changed_signal;
208 }
209
210
211 Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
212 Glib::Dispatcher* GigEditState::dispatcher = 0;
213 GigEditState* GigEditState::current = 0;
214
215 void GigEditState::open_window_static() {
216 GigEditState* c = GigEditState::current;
217 c->open.signal();
218 c->open_window();
219 }
220
221 void GigEditState::open_window() {
222 window = new MainWindow();
223
224 connect_signals(parent, window);
225 if (instrument) window->load_instrument(instrument);
226
227 window->signal_hide().connect(sigc::mem_fun(this,
228 &GigEditState::close_window));
229 window->present();
230 }
231
232 void GigEditState::close_window() {
233 delete window;
234 close.signal();
235 }
236
237 void GigEditState::main_loop_run(Cond* initialized) {
238 int argc = 1;
239 const char* argv_c[] = { "gigedit" };
240 char** argv = const_cast<char**>(argv_c);
241 Gtk::Main main_loop(argc, argv);
242
243 dispatcher = new Glib::Dispatcher();
244 dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
245 initialized->signal();
246
247 main_loop.run();
248 }
249
250 void GigEditState::run(gig::Instrument* pInstrument) {
251 mutex.lock(); // lock access to static variables
252
253 static bool main_loop_started = false;
254 if (!main_loop_started) {
255 Cond initialized;
256 Glib::Thread::create(
257 sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
258 &initialized),
259 false);
260 initialized.wait();
261 main_loop_started = true;
262 }
263 instrument = pInstrument;
264 current = this;
265 dispatcher->emit();
266 open.wait(); // wait until the GUI thread has read current
267 mutex.unlock();
268 close.wait(); // sleep until window is closed
269 }

  ViewVC Help
Powered by ViewVC