~ubuntu-branches/ubuntu/raring/gigedit/raring

« back to all changes in this revision

Viewing changes to src/gigedit/gigedit.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Free Ekanayaka
  • Date: 2008-01-14 11:44:44 UTC
  • Revision ID: james.westby@ubuntu.com-20080114114444-srami92sje45i3pm
Tags: upstream-0.1.1
ImportĀ upstreamĀ versionĀ 0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}