/[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 1456 - (show annotations) (download)
Sun Oct 21 15:32:36 2007 UTC (16 years, 5 months ago) by persson
File size: 7264 byte(s)
* multiple editor windows can now be opened by the plugin
* bugfix: gigedit didn't start on windows 2000
* standard gtk command line parameters is now handled

1 /*
2 * Copyright (C) 2007 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 "mainwindow.h"
24
25 #include "global.h"
26
27 namespace {
28
29 // State for a gigedit thread.
30 //
31 // This class is only used when gigedit is run as a plugin and makes
32 // sure that there's only one Gtk::Main event loop. The event loop is
33 // started in a separate thread. The plugin thread just dispatches an
34 // event to the main loop to open a window and then goes to sleep
35 // until the window is closed.
36 //
37 class GigEditState : public sigc::trackable {
38 public:
39 GigEditState(GigEdit* parent) : parent(parent) { }
40 void run(gig::Instrument* pInstrument);
41
42 private:
43
44 // simple condition variable abstraction
45 class Cond {
46 private:
47 bool pred;
48 Glib::Mutex mutex;
49 Glib::Cond cond;
50 public:
51 Cond() : pred(false) { }
52 void signal() {
53 Glib::Mutex::Lock lock(mutex);
54 pred = true;
55 cond.signal();
56 }
57 void wait() {
58 Glib::Mutex::Lock lock(mutex);
59 while (!pred) cond.wait(mutex);
60 }
61 };
62
63 static Glib::StaticMutex mutex;
64 static Glib::Dispatcher* dispatcher;
65 static GigEditState* current;
66
67 static void main_loop_run(Cond* intialized);
68 static void open_window_static();
69
70 GigEdit* parent;
71 Cond open;
72 Cond close;
73 gig::Instrument* instrument;
74 MainWindow* window;
75
76 void open_window();
77 void close_window();
78 };
79
80 void init_app() {
81 static bool process_initialized = false;
82 if (!process_initialized) {
83 std::cout << "Initializing 3rd party services needed by gigedit.\n"
84 << std::flush;
85 setlocale(LC_ALL, "");
86
87 #if HAVE_GETTEXT
88 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
89 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
90 textdomain(GETTEXT_PACKAGE);
91 #endif // HAVE_GETTEXT
92
93 // make sure thread_init() is called once and ONLY once per process
94 if (!Glib::thread_supported()) Glib::thread_init();
95
96 process_initialized = true;
97 }
98 }
99
100 void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
101 // the signals of the "GigEdit" class are actually just proxies, that
102 // is they simply forward the signals of the internal classes to the
103 // outer world
104 mainwindow->signal_file_structure_to_be_changed().connect(
105 gigedit->signal_file_structure_to_be_changed().make_slot()
106 );
107 mainwindow->signal_file_structure_changed().connect(
108 gigedit->signal_file_structure_changed().make_slot()
109 );
110 mainwindow->signal_samples_to_be_removed().connect(
111 gigedit->signal_samples_to_be_removed().make_slot()
112 );
113 mainwindow->signal_samples_removed().connect(
114 gigedit->signal_samples_removed().make_slot()
115 );
116 mainwindow->signal_region_to_be_changed().connect(
117 gigedit->signal_region_to_be_changed().make_slot()
118 );
119 mainwindow->signal_region_changed().connect(
120 gigedit->signal_region_changed().make_slot()
121 );
122 mainwindow->signal_dimreg_to_be_changed().connect(
123 gigedit->signal_dimreg_to_be_changed().make_slot()
124 );
125 mainwindow->signal_dimreg_changed().connect(
126 gigedit->signal_dimreg_changed().make_slot()
127 );
128 mainwindow->signal_sample_ref_changed().connect(
129 gigedit->signal_sample_ref_changed().make_slot()
130 );
131 }
132
133 }
134
135
136 int GigEdit::run(int argc, char* argv[]) {
137 init_app();
138
139 Gtk::Main kit(argc, argv);
140 MainWindow window;
141 connect_signals(this, &window);
142 if (argc >= 2) window.load_file(argv[1]);
143 kit.run(window);
144 return 0;
145 }
146
147 int GigEdit::run(gig::Instrument* pInstrument) {
148 init_app();
149
150 GigEditState state(this);
151 state.run(pInstrument);
152 return 0;
153 }
154
155 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
156 return file_structure_to_be_changed_signal;
157 }
158
159 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
160 return file_structure_changed_signal;
161 }
162
163 sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
164 return samples_to_be_removed_signal;
165 }
166
167 sigc::signal<void>& GigEdit::signal_samples_removed() {
168 return samples_removed_signal;
169 }
170
171 sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
172 return region_to_be_changed_signal;
173 }
174
175 sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
176 return region_changed_signal;
177 }
178
179 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
180 return dimreg_to_be_changed_signal;
181 }
182
183 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
184 return dimreg_changed_signal;
185 }
186
187 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
188 return sample_ref_changed_signal;
189 }
190
191
192 Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
193 Glib::Dispatcher* GigEditState::dispatcher = 0;
194 GigEditState* GigEditState::current = 0;
195
196 void GigEditState::open_window_static() {
197 GigEditState* c = GigEditState::current;
198 c->open.signal();
199 c->open_window();
200 }
201
202 void GigEditState::open_window() {
203 window = new MainWindow();
204
205 connect_signals(parent, window);
206 if (instrument) window->load_instrument(instrument);
207
208 window->signal_hide().connect(sigc::mem_fun(this,
209 &GigEditState::close_window));
210 window->present();
211 }
212
213 void GigEditState::close_window() {
214 delete window;
215 close.signal();
216 }
217
218 void GigEditState::main_loop_run(Cond* initialized) {
219 int argc = 1;
220 const char* argv_c[] = { "gigedit" };
221 char** argv = const_cast<char**>(argv_c);
222 Gtk::Main main_loop(argc, argv);
223
224 dispatcher = new Glib::Dispatcher();
225 dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
226 initialized->signal();
227
228 main_loop.run();
229 }
230
231 void GigEditState::run(gig::Instrument* pInstrument) {
232 mutex.lock(); // lock access to static variables
233
234 static bool main_loop_started = false;
235 if (!main_loop_started) {
236 Cond initialized;
237 Glib::Thread::create(
238 sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
239 &initialized),
240 false);
241 initialized.wait();
242 main_loop_started = true;
243 }
244 instrument = pInstrument;
245 current = this;
246 dispatcher->emit();
247 open.wait(); // wait until the GUI thread has read current
248 mutex.unlock();
249 close.wait(); // sleep until window is closed
250 }

  ViewVC Help
Powered by ViewVC