make AU Cocoa plugin views with "client-side-windows" versions of GTK+; make keyboard...
[ardour2.git] / gtk2_ardour / main.cc
blob7a34e9339044a76dc6789a0775e72cea2adf8fc4
1 /*
2 Copyright (C) 2001-2007 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <cstdlib>
21 #include <signal.h>
23 #include <sigc++/bind.h>
24 #include <gtkmm/settings.h>
25 #include <glibmm/ustring.h>
27 #include <pbd/error.h>
28 #include <pbd/textreceiver.h>
29 #include <pbd/failed_constructor.h>
30 #include <pbd/pthread_utils.h>
32 #include <jack/jack.h>
34 #include <ardour/svn_revision.h>
35 #include <ardour/version.h>
36 #include <ardour/ardour.h>
37 #include <ardour/audioengine.h>
39 #include <gtkmm/main.h>
41 #include <gtkmm2ext/application.h>
42 #include <gtkmm2ext/popup.h>
43 #include <gtkmm2ext/utils.h>
45 #include "version.h"
46 #include "ardour_ui.h"
47 #include "opts.h"
48 #include "enums.h"
50 #include "i18n.h"
52 using namespace Gtk;
53 using namespace ARDOUR_COMMAND_LINE;
54 using namespace ARDOUR;
55 using namespace PBD;
56 using namespace sigc;
58 TextReceiver text_receiver ("ardour");
60 extern int curvetest (string);
62 static ARDOUR_UI *ui = 0;
63 static const char* localedir = LOCALEDIR;
65 #ifdef __APPLE__
67 #include <mach-o/dyld.h>
68 #include <sys/param.h>
69 #include <fstream>
71 extern void set_language_preference (); // cocoacarbon.mm
73 void
74 fixup_bundle_environment ()
76 if (!getenv ("ARDOUR_BUNDLED")) {
77 return;
80 set_language_preference ();
82 char execpath[MAXPATHLEN+1];
83 uint32_t pathsz = sizeof (execpath);
85 _NSGetExecutablePath (execpath, &pathsz);
87 Glib::ustring exec_path (execpath);
88 Glib::ustring dir_path = Glib::path_get_dirname (exec_path);
89 Glib::ustring path;
90 const char *cstr = getenv ("PATH");
92 /* ensure that we find any bundled executables (e.g. JACK),
93 and find them before any instances of the same name
94 elsewhere in PATH
97 path = dir_path;
98 if (cstr) {
99 path += ':';
100 path += cstr;
102 setenv ("PATH", path.c_str(), 1);
104 path = dir_path;
105 path += "/../Resources";
106 path += dir_path;
107 path += "/../Resources/Surfaces";
108 path += dir_path;
109 path += "/../Resources/Panners";
111 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
113 path = dir_path;
114 path += "/../Resources/icons:";
115 path += dir_path;
116 path += "/../Resources/pixmaps:";
117 path += dir_path;
118 path += "/../Resources/share:";
119 path += dir_path;
120 path += "/../Resources";
122 setenv ("ARDOUR_PATH", path.c_str(), 1);
123 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
124 setenv ("ARDOUR_DATA_PATH", path.c_str(), 1);
126 path = dir_path;
127 path += "/../Resources";
128 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
130 cstr = getenv ("LADSPA_PATH");
131 if (cstr) {
132 path = cstr;
133 path += ':';
134 } else {
135 path = "";
137 path += dir_path;
138 path += "/../Plugins";
140 setenv ("LADSPA_PATH", path.c_str(), 1);
142 cstr = getenv ("VAMP_PATH");
143 if (cstr) {
144 path = cstr;
145 path += ':';
146 } else {
147 path = "";
149 path += dir_path;
150 path += "/../Frameworks";
152 setenv ("VAMP_PATH", path.c_str(), 1);
154 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
155 if (cstr) {
156 path = cstr;
157 path += ':';
158 } else {
159 path = "";
161 path += dir_path;
162 path += "/../Surfaces";
164 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
166 cstr = getenv ("LV2_PATH");
167 if (cstr) {
168 path = cstr;
169 path += ':';
170 } else {
171 path = "";
173 path += dir_path;
174 path += "/../Plugins";
176 setenv ("LV2_PATH", path.c_str(), 1);
178 path = dir_path;
179 path += "/../Frameworks/clearlooks";
181 setenv ("GTK_PATH", path.c_str(), 1);
183 if (!ARDOUR::translations_are_disabled ()) {
185 path = dir_path;
186 path += "/../Resources/locale";
188 localedir = strdup (path.c_str());
189 setenv ("GTK_LOCALEDIR", localedir, 1);
192 /* write a pango.rc file and tell pango to use it. we'd love
193 to put this into the Ardour.app bundle and leave it there,
194 but the user may not have write permission. so ...
196 we also have to make sure that the user ardour directory
197 actually exists ...
200 if (g_mkdir_with_parents (ARDOUR::get_user_ardour_path().c_str(), 0755) < 0) {
201 error << string_compose (_("cannot create user ardour folder %1 (%2)"), ARDOUR::get_user_ardour_path(), strerror (errno))
202 << endmsg;
203 } else {
205 path = Glib::build_filename (ARDOUR::get_user_ardour_path(), "pango.rc");
207 std::ofstream pangorc (path.c_str());
208 if (!pangorc) {
209 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
210 } else {
211 pangorc << "[Pango]\nModuleFiles=";
212 Glib::ustring mpath;
214 mpath = dir_path;
215 mpath += "/../Resources/pango.modules";
217 pangorc << mpath << endl;
219 pangorc.close ();
220 setenv ("PANGO_RC_FILE", path.c_str(), 1);
224 // gettext charset aliases
226 setenv ("CHARSETALIASDIR", path.c_str(), 1);
228 // font config
230 path = dir_path;
231 path += "/../Resources/fonts.conf";
233 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
235 // GDK Pixbuf loader module file
237 path = dir_path;
238 path += "/../Resources/gdk-pixbuf.loaders";
240 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
242 if (getenv ("ARDOUR_WITH_JACK")) {
243 // JACK driver dir
245 path = dir_path;
246 path += "/../Frameworks";
248 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
252 #endif
254 static gboolean
255 tell_about_jack_death (void* /* ignored */)
257 if (AudioEngine::instance()->processed_frames() == 0) {
258 /* died during startup */
259 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
260 msg.set_position (Gtk::WIN_POS_CENTER);
261 msg.set_secondary_text (string_compose (_(
262 "JACK exited unexpectedly, and without notifying %1.\n\
264 This could be due to misconfiguration or to an error inside JACK.\n\
266 Click OK to exit %1."), PROGRAM_NAME));
268 msg.run ();
269 _exit (0);
271 } else {
273 /* engine has already run, so this is a mid-session JACK death */
275 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
276 msg->set_secondary_text (string_compose (_(
277 "JACK exited unexpectedly, and without notifying %1.\n\
279 This is probably due to an error inside JACK. You should restart JACK\n\
280 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
281 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
282 msg->present ();
284 return false; /* do not call again */
287 static void
288 sigpipe_handler (int sig)
290 static bool done_the_jack_thing = false;
292 if (!done_the_jack_thing) {
293 AudioEngine::instance()->died ();
294 g_idle_add (tell_about_jack_death, 0);
295 done_the_jack_thing = true;
299 #ifdef VST_SUPPORT
301 extern int gui_init (int* argc, char** argv[]);
303 /* this is called from the entry point of a wine-compiled
304 executable that is linked against gtk2_ardour built
305 as a shared library.
308 extern "C" {
309 int ardour_main (int argc, char *argv[])
310 #else
311 int main (int argc, char* argv[])
312 #endif
314 vector<Glib::ustring> null_file_list;
316 #ifdef __APPLE__
317 fixup_bundle_environment ();
318 #endif
320 Glib::thread_init();
322 #ifdef VST_SUPPORT
323 /* this does some magic that is needed to make GTK and Wine's own
324 X11 client interact properly.
326 gui_init (&argc, &argv);
327 #endif
329 (void) bindtextdomain (PACKAGE, localedir);
330 /* our i18n translations are all in UTF-8, so make sure
331 that even if the user locale doesn't specify UTF-8,
332 we use that when handling them.
334 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
336 /* this really does nothing since we don't get gettext(),
337 only dgettext(), but whatever ...
339 (void) textdomain (PACKAGE);
341 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
343 // catch error message system signals ();
345 text_receiver.listen_to (error);
346 text_receiver.listen_to (info);
347 text_receiver.listen_to (fatal);
348 text_receiver.listen_to (warning);
350 if (parse_opts (argc, argv)) {
351 exit (1);
354 if (curvetest_file) {
355 return curvetest (curvetest_file);
358 cout << PROGRAM_NAME << ' '
359 << VERSIONSTRING
360 << _("\n (built using ")
361 << svn_revision
362 #ifdef __GNUC__
363 << _(" and GCC version ") << __VERSION__
364 #endif
365 << ')'
366 << endl;
368 if (just_version) {
369 exit (0);
372 if (no_splash) {
373 cerr << _("Copyright (C) 1999-2008 Paul Davis") << endl
374 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
375 << endl
376 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
377 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
378 << _("This is free software, and you are welcome to redistribute it ") << endl
379 << _("under certain conditions; see the source for copying conditions.")
380 << endl;
383 /* some GUI objects need this */
385 PBD::ID::init ();
387 if (::signal (SIGPIPE, sigpipe_handler)) {
388 cerr << _("Cannot install SIGPIPE error handler") << endl;
391 try {
392 ui = new ARDOUR_UI (&argc, &argv);
393 } catch (failed_constructor& err) {
394 error << _("could not create ARDOUR GUI") << endmsg;
395 exit (1);
398 ui->run (text_receiver);
399 Gtkmm2ext::Application::instance()->cleanup();
400 ui = 0;
402 ARDOUR::cleanup ();
403 pthread_cancel_all ();
405 return 0;
407 #ifdef VST_SUPPORT
408 } // end of extern C block
409 #endif