2
* Copyright (C) 2007 Andreas Persson
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.
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.
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
22
#include <gtkmm/main.h>
23
#include "mainwindow.h"
29
// State for a gigedit thread.
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.
37
class GigEditState : public sigc::trackable {
39
GigEditState(GigEdit* parent) : parent(parent) { }
40
void run(gig::Instrument* pInstrument);
44
// simple condition variable abstraction
51
Cond() : pred(false) { }
53
Glib::Mutex::Lock lock(mutex);
58
Glib::Mutex::Lock lock(mutex);
59
while (!pred) cond.wait(mutex);
63
static Glib::StaticMutex mutex;
64
static Glib::Dispatcher* dispatcher;
65
static GigEditState* current;
67
static void main_loop_run(Cond* intialized);
68
static void open_window_static();
73
gig::Instrument* instrument;
81
static bool process_initialized = false;
82
if (!process_initialized) {
83
std::cout << "Initializing 3rd party services needed by gigedit.\n"
85
setlocale(LC_ALL, "");
88
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
89
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
90
textdomain(GETTEXT_PACKAGE);
91
#endif // HAVE_GETTEXT
93
// make sure thread_init() is called once and ONLY once per process
94
if (!Glib::thread_supported()) Glib::thread_init();
96
process_initialized = true;
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
104
mainwindow->signal_file_structure_to_be_changed().connect(
105
gigedit->signal_file_structure_to_be_changed().make_slot()
107
mainwindow->signal_file_structure_changed().connect(
108
gigedit->signal_file_structure_changed().make_slot()
110
mainwindow->signal_samples_to_be_removed().connect(
111
gigedit->signal_samples_to_be_removed().make_slot()
113
mainwindow->signal_samples_removed().connect(
114
gigedit->signal_samples_removed().make_slot()
116
mainwindow->signal_region_to_be_changed().connect(
117
gigedit->signal_region_to_be_changed().make_slot()
119
mainwindow->signal_region_changed().connect(
120
gigedit->signal_region_changed().make_slot()
122
mainwindow->signal_dimreg_to_be_changed().connect(
123
gigedit->signal_dimreg_to_be_changed().make_slot()
125
mainwindow->signal_dimreg_changed().connect(
126
gigedit->signal_dimreg_changed().make_slot()
128
mainwindow->signal_sample_ref_changed().connect(
129
gigedit->signal_sample_ref_changed().make_slot()
136
int GigEdit::run(int argc, char* argv[]) {
139
Gtk::Main kit(argc, argv);
141
connect_signals(this, &window);
142
if (argc >= 2) window.load_file(argv[1]);
147
int GigEdit::run(gig::Instrument* pInstrument) {
150
GigEditState state(this);
151
state.run(pInstrument);
155
sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_to_be_changed() {
156
return file_structure_to_be_changed_signal;
159
sigc::signal<void, gig::File*>& GigEdit::signal_file_structure_changed() {
160
return file_structure_changed_signal;
163
sigc::signal<void, std::list<gig::Sample*> >& GigEdit::signal_samples_to_be_removed() {
164
return samples_to_be_removed_signal;
167
sigc::signal<void>& GigEdit::signal_samples_removed() {
168
return samples_removed_signal;
171
sigc::signal<void, gig::Region*>& GigEdit::signal_region_to_be_changed() {
172
return region_to_be_changed_signal;
175
sigc::signal<void, gig::Region*>& GigEdit::signal_region_changed() {
176
return region_changed_signal;
179
sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_to_be_changed() {
180
return dimreg_to_be_changed_signal;
183
sigc::signal<void, gig::DimensionRegion*>& GigEdit::signal_dimreg_changed() {
184
return dimreg_changed_signal;
187
sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& GigEdit::signal_sample_ref_changed() {
188
return sample_ref_changed_signal;
192
Glib::StaticMutex GigEditState::mutex = GLIBMM_STATIC_MUTEX_INIT;
193
Glib::Dispatcher* GigEditState::dispatcher = 0;
194
GigEditState* GigEditState::current = 0;
196
void GigEditState::open_window_static() {
197
GigEditState* c = GigEditState::current;
202
void GigEditState::open_window() {
203
window = new MainWindow();
205
connect_signals(parent, window);
206
if (instrument) window->load_instrument(instrument);
208
window->signal_hide().connect(sigc::mem_fun(this,
209
&GigEditState::close_window));
213
void GigEditState::close_window() {
218
void GigEditState::main_loop_run(Cond* initialized) {
220
const char* argv_c[] = { "gigedit" };
221
char** argv = const_cast<char**>(argv_c);
222
Gtk::Main main_loop(argc, argv);
224
dispatcher = new Glib::Dispatcher();
225
dispatcher->connect(sigc::ptr_fun(&GigEditState::open_window_static));
226
initialized->signal();
231
void GigEditState::run(gig::Instrument* pInstrument) {
232
mutex.lock(); // lock access to static variables
234
static bool main_loop_started = false;
235
if (!main_loop_started) {
237
Glib::Thread::create(
238
sigc::bind(sigc::ptr_fun(&GigEditState::main_loop_run),
242
main_loop_started = true;
244
instrument = pInstrument;
247
open.wait(); // wait until the GUI thread has read current
249
close.wait(); // sleep until window is closed