/[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 1456 - (hide 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 schoenebeck 1225 /*
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 schoenebeck 1396 #include "global.h"
26 schoenebeck 1225
27 persson 1456 namespace {
28 schoenebeck 1225
29 persson 1456 // 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 schoenebeck 1333 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 schoenebeck 1396
87     #if HAVE_GETTEXT
88 schoenebeck 1333 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
89     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
90     textdomain(GETTEXT_PACKAGE);
91 schoenebeck 1396 #endif // HAVE_GETTEXT
92    
93 schoenebeck 1333 // 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 schoenebeck 1225 }
99    
100 persson 1456 void connect_signals(GigEdit* gigedit, MainWindow* mainwindow) {
101 schoenebeck 1322 // 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 schoenebeck 1225 }
134    
135 persson 1456
136     int GigEdit::run(int argc, char* argv[]) {
137     init_app();
138    
139     Gtk::Main kit(argc, argv);
140 schoenebeck 1225 MainWindow window;
141 persson 1456 connect_signals(this, &window);
142     if (argc >= 2) window.load_file(argv[1]);
143 schoenebeck 1225 kit.run(window);
144     return 0;
145     }
146    
147     int GigEdit::run(gig::Instrument* pInstrument) {
148 persson 1456 init_app();
149    
150     GigEditState state(this);
151     state.run(pInstrument);
152 schoenebeck 1225 return 0;
153     }
154 schoenebeck 1322
155 schoenebeck 1339 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
156 schoenebeck 1322 return file_structure_to_be_changed_signal;
157     }
158    
159 schoenebeck 1339 sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
160 schoenebeck 1322 return file_structure_changed_signal;
161     }
162    
163 schoenebeck 1339 sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
164 schoenebeck 1322 return samples_to_be_removed_signal;
165     }
166    
167 schoenebeck 1339 sigc::signal<void>& GigEdit::signal_samples_removed() {
168 schoenebeck 1322 return samples_removed_signal;
169     }
170    
171 schoenebeck 1339 sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
172 schoenebeck 1322 return region_to_be_changed_signal;
173     }
174    
175 schoenebeck 1339 sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
176 schoenebeck 1322 return region_changed_signal;
177     }
178    
179 schoenebeck 1339 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
180 schoenebeck 1322 return dimreg_to_be_changed_signal;
181     }
182    
183 schoenebeck 1339 sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
184 schoenebeck 1322 return dimreg_changed_signal;
185     }
186    
187 schoenebeck 1339 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
188 schoenebeck 1322 return sample_ref_changed_signal;
189     }
190 persson 1456
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