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.
25 #include <sigc++/bind.h>
26 #include <gtkmm/settings.h>
28 #include "pbd/error.h"
30 #include "pbd/file_utils.h"
31 #include "pbd/textreceiver.h"
32 #include "pbd/failed_constructor.h"
33 #include "pbd/pthread_utils.h"
35 #include <jack/jack.h>
37 #include "ardour/svn_revision.h"
38 #include "ardour/version.h"
39 #include "ardour/ardour.h"
40 #include "ardour/audioengine.h"
41 #include "ardour/session_utils.h"
42 #include "ardour/filesystem_paths.h"
44 #include <gtkmm/main.h>
45 #include <gtkmm2ext/application.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/utils.h>
51 #include "ardour_ui.h"
59 using namespace ARDOUR_COMMAND_LINE;
60 using namespace ARDOUR;
63 TextReceiver text_receiver ("ardour");
65 extern int curvetest (string);
67 static ARDOUR_UI *ui = 0;
68 static const char* localedir = LOCALEDIR;
73 MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
76 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
77 win.set_secondary_text(_("There are several possible reasons:\n\
79 1) JACK is not running.\n\
80 2) JACK is running as another user, perhaps root.\n\
81 3) There is already another client called \"ardour\".\n\
83 Please consider the possibilities, and perhaps (re)start JACK."));
85 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
86 win.set_default_response (RESPONSE_CLOSE);
89 win.set_position (Gtk::WIN_POS_CENTER);
95 /* we just don't care about the result, but we want to block */
103 #include <mach-o/dyld.h>
104 #include <sys/param.h>
106 extern void set_language_preference (); // cocoacarbon.mm
109 fixup_bundle_environment ()
111 if (!getenv ("ARDOUR_BUNDLED")) {
115 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
117 set_language_preference ();
119 char execpath[MAXPATHLEN+1];
120 uint32_t pathsz = sizeof (execpath);
122 _NSGetExecutablePath (execpath, &pathsz);
124 std::string exec_path (execpath);
125 std::string dir_path = Glib::path_get_dirname (exec_path);
127 const char *cstr = getenv ("PATH");
129 /* ensure that we find any bundled executables (e.g. JACK),
130 and find them before any instances of the same name
136 /* JACK is often in /usr/local/bin and since Info.plist refuses to
137 set PATH, we have to force this in order to discover a running
142 path += "/usr/local/bin";
148 setenv ("PATH", path.c_str(), 1);
151 path += "/../Resources";
153 path += "/../Resources/Surfaces";
155 path += "/../Resources/Panners";
157 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
159 path = user_config_directory().to_string();
162 path += "/../Resources/icons:";
164 path += "/../Resources/pixmaps:";
166 path += "/../Resources/share:";
168 path += "/../Resources";
170 setenv ("ARDOUR_PATH", path.c_str(), 1);
171 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
174 path += "/../Resources";
175 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
177 cstr = getenv ("LADSPA_PATH");
185 path += "/../Plugins";
187 setenv ("LADSPA_PATH", path.c_str(), 1);
189 cstr = getenv ("VAMP_PATH");
197 path += "/../Frameworks";
199 setenv ("VAMP_PATH", path.c_str(), 1);
201 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
209 path += "/../Surfaces";
211 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
213 cstr = getenv ("LV2_PATH");
221 path += "/../Plugins";
223 setenv ("LV2_PATH", path.c_str(), 1);
226 path += "/../Frameworks/clearlooks";
228 setenv ("GTK_PATH", path.c_str(), 1);
230 if (!ARDOUR::translations_are_disabled ()) {
233 path += "/../Resources/locale";
235 localedir = strdup (path.c_str());
236 setenv ("GTK_LOCALEDIR", localedir, 1);
239 /* write a pango.rc file and tell pango to use it. we'd love
240 to put this into the PROGRAM_NAME.app bundle and leave it there,
241 but the user may not have write permission. so ...
243 we also have to make sure that the user ardour directory
248 sys::create_directories (user_config_directory ());
250 catch (const sys::filesystem_error& ex) {
251 error << _("Could not create user configuration directory") << endmsg;
254 sys::path pangopath = user_config_directory();
255 pangopath /= "pango.rc";
256 path = pangopath.to_string();
258 std::ofstream pangorc (path.c_str());
260 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
263 pangorc << "[Pango]\nModuleFiles=";
265 pangopath = dir_path;
267 pangopath /= "Resources";
268 pangopath /= "pango.modules";
270 pangorc << pangopath.to_string() << endl;
274 setenv ("PANGO_RC_FILE", path.c_str(), 1);
277 // gettext charset aliases
279 setenv ("CHARSETALIASDIR", path.c_str(), 1);
284 path += "/../Resources/fonts.conf";
286 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
288 // GDK Pixbuf loader module file
291 path += "/../Resources/gdk-pixbuf.loaders";
293 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
295 if (getenv ("ARDOUR_WITH_JACK")) {
299 path += "/../Frameworks";
301 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
308 fixup_bundle_environment (int argc, char* argv[])
310 if (!getenv ("ARDOUR_BUNDLED")) {
314 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
316 Glib::ustring exec_path = argv[0];
317 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
319 const char *cstr = getenv ("PATH");
320 Glib::ustring userconfigdir = user_config_directory().to_string();
322 cerr << "Ardour: bundle root = " << dir_path << endl;
324 /* ensure that we find any bundled executables (e.g. JACK),
325 and find them before any instances of the same name
329 /* note that this function is POSIX/Linux specific, so using / as
330 a dir separator in this context is just fine.
336 path += "/lib/surfaces:";
338 path += "/lib/panners:";
340 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
342 path = userconfigdir;
345 path += "/etc/icons:";
347 path += "/etc/pixmaps:";
353 setenv ("ARDOUR_PATH", path.c_str(), 1);
354 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
358 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
360 cstr = getenv ("LADSPA_PATH");
368 path += "/lib/plugins";
370 setenv ("LADSPA_PATH", path.c_str(), 1);
372 cstr = getenv ("VAMP_PATH");
382 setenv ("VAMP_PATH", path.c_str(), 1);
384 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
392 path += "/lib/surfaces";
394 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
396 cstr = getenv ("LV2_PATH");
404 path += "/lib/plugins";
406 setenv ("LV2_PATH", path.c_str(), 1);
409 path += "/lib/clearlooks";
411 setenv ("GTK_PATH", path.c_str(), 1);
413 if (!ARDOUR::translations_are_disabled ()) {
415 path += "/share/locale";
417 localedir = strdup (path.c_str());
418 setenv ("GTK_LOCALEDIR", localedir, 1);
421 /* write a pango.rc file and tell pango to use it. we'd love
422 to put this into the Ardour.app bundle and leave it there,
423 but the user may not have write permission. so ...
425 we also have to make sure that the user ardour directory
429 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
430 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
436 path = Glib::build_filename (userconfigdir, "pango.rc");
438 std::ofstream pangorc (path.c_str());
440 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
442 mpath = Glib::build_filename (userconfigdir, "pango.modules");
444 pangorc << "[Pango]\nModuleFiles=";
445 pangorc << mpath << endl;
449 setenv ("PANGO_RC_FILE", path.c_str(), 1);
451 /* similar for GDK pixbuf loaders, but there's no RC file required
452 to specify where it lives.
455 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
456 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
463 tell_about_jack_death (void* /* ignored */)
465 if (AudioEngine::instance()->processed_frames() == 0) {
466 /* died during startup */
467 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
468 msg.set_position (Gtk::WIN_POS_CENTER);
469 msg.set_secondary_text (string_compose (_(
470 "JACK exited unexpectedly, and without notifying %1.\n\
472 This could be due to misconfiguration or to an error inside JACK.\n\
474 Click OK to exit %1."), PROGRAM_NAME));
481 /* engine has already run, so this is a mid-session JACK death */
483 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
484 msg->set_secondary_text (string_compose (_(
485 "JACK exited unexpectedly, and without notifying %1.\n\
487 This is probably due to an error inside JACK. You should restart JACK\n\
488 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
489 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
492 return false; /* do not call again */
496 sigpipe_handler (int /*signal*/)
498 /* XXX fix this so that we do this again after a reconnect to JACK
501 static bool done_the_jack_thing = false;
503 if (!done_the_jack_thing) {
504 AudioEngine::instance()->died ();
505 g_idle_add (tell_about_jack_death, 0);
506 done_the_jack_thing = true;
511 void close_external_ui_windows();
516 extern int gui_init (int* argc, char** argv[]);
518 /* this is called from the entry point of a wine-compiled
519 executable that is linked against gtk2_ardour built
523 int ardour_main (int argc, char *argv[])
525 int main (int argc, char *argv[])
529 fixup_bundle_environment ();
532 if (!Glib::thread_supported())
538 /* this does some magic that is needed to make GTK and Wine's own
539 X11 client interact properly.
541 gui_init (&argc, &argv);
544 (void) bindtextdomain (PACKAGE, localedir);
545 /* our i18n translations are all in UTF-8, so make sure
546 that even if the user locale doesn't specify UTF-8,
547 we use that when handling them.
549 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
550 (void) textdomain (PACKAGE);
552 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
554 // catch error message system signals ();
556 text_receiver.listen_to (error);
557 text_receiver.listen_to (info);
558 text_receiver.listen_to (fatal);
559 text_receiver.listen_to (warning);
561 if (parse_opts (argc, argv)) {
565 if (curvetest_file) {
566 return curvetest (curvetest_file);
571 << _(" (built using ")
574 << _(" and GCC version ") << __VERSION__
584 cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
585 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
587 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
588 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
589 << _("This is free software, and you are welcome to redistribute it ") << endl
590 << _("under certain conditions; see the source for copying conditions.")
594 /* some GUI objects need this */
598 if (::signal (SIGPIPE, sigpipe_handler)) {
599 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
603 ui = new ARDOUR_UI (&argc, &argv);
604 } catch (failed_constructor& err) {
605 error << _("could not create ARDOUR GUI") << endmsg;
609 ui->run (text_receiver);
610 Gtkmm2ext::Application::instance()->cleanup();
614 pthread_cancel_all ();
617 close_external_ui_windows();
622 } // end of extern C block