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 (int, char* [])
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 ("ARDOUR_PANNER_PATH");
221 path += "/lib/panners";
223 setenv ("ARDOUR_PANNER_PATH", path.c_str(), 1);
225 cstr = getenv ("LV2_PATH");
233 path += "/../Plugins";
235 setenv ("LV2_PATH", path.c_str(), 1);
238 path += "/../Frameworks/clearlooks";
240 setenv ("GTK_PATH", path.c_str(), 1);
242 /* unset GTK_RC_FILES so that we only load the RC files that we define
245 unsetenv ("GTK_RC_FILES");
247 if (!ARDOUR::translations_are_disabled ()) {
250 path += "/../Resources/locale";
252 localedir = strdup (path.c_str());
253 setenv ("GTK_LOCALEDIR", localedir, 1);
256 /* write a pango.rc file and tell pango to use it. we'd love
257 to put this into the PROGRAM_NAME.app bundle and leave it there,
258 but the user may not have write permission. so ...
260 we also have to make sure that the user ardour directory
265 sys::create_directories (user_config_directory ());
267 catch (const sys::filesystem_error& ex) {
268 error << _("Could not create user configuration directory") << endmsg;
271 sys::path pangopath = user_config_directory();
272 pangopath /= "pango.rc";
273 path = pangopath.to_string();
275 std::ofstream pangorc (path.c_str());
277 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
280 pangorc << "[Pango]\nModuleFiles=";
282 pangopath = dir_path;
284 pangopath /= "Resources";
285 pangopath /= "pango.modules";
287 pangorc << pangopath.to_string() << endl;
291 setenv ("PANGO_RC_FILE", path.c_str(), 1);
294 // gettext charset aliases
296 setenv ("CHARSETALIASDIR", path.c_str(), 1);
301 path += "/../Resources/fonts.conf";
303 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
305 // GDK Pixbuf loader module file
308 path += "/../Resources/gdk-pixbuf.loaders";
310 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
312 if (getenv ("ARDOUR_WITH_JACK")) {
316 path += "/../Frameworks";
318 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
325 fixup_bundle_environment (int /*argc*/, char* argv[])
327 if (!getenv ("ARDOUR_BUNDLED")) {
331 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
333 Glib::ustring exec_path = argv[0];
334 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
336 const char *cstr = getenv ("PATH");
337 Glib::ustring userconfigdir = user_config_directory().to_string();
339 /* ensure that we find any bundled executables (e.g. JACK),
340 and find them before any instances of the same name
344 /* note that this function is POSIX/Linux specific, so using / as
345 a dir separator in this context is just fine.
351 path += "/lib/surfaces:";
353 path += "/lib/panners:";
355 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
357 path = userconfigdir;
360 path += "/etc/icons:";
362 path += "/etc/pixmaps:";
368 setenv ("ARDOUR_PATH", path.c_str(), 1);
369 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
373 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
375 cstr = getenv ("LADSPA_PATH");
383 path += "/lib/plugins";
385 setenv ("LADSPA_PATH", path.c_str(), 1);
387 cstr = getenv ("VAMP_PATH");
397 setenv ("VAMP_PATH", path.c_str(), 1);
399 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
407 path += "/lib/surfaces";
409 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
411 cstr = getenv ("ARDOUR_PANNER_PATH");
419 path += "/lib/panners";
421 setenv ("ARDOUR_PANNER_PATH", path.c_str(), 1);
423 cstr = getenv ("LV2_PATH");
431 path += "/lib/plugins";
433 setenv ("LV2_PATH", path.c_str(), 1);
436 path += "/lib/clearlooks";
438 setenv ("GTK_PATH", path.c_str(), 1);
440 /* unset GTK_RC_FILES so that we only load the RC files that we define
443 unsetenv ("GTK_RC_FILES");
445 if (!ARDOUR::translations_are_disabled ()) {
447 path += "/share/locale";
449 localedir = strdup (path.c_str());
450 setenv ("GTK_LOCALEDIR", localedir, 1);
453 /* write a pango.rc file and tell pango to use it. we'd love
454 to put this into the Ardour.app bundle and leave it there,
455 but the user may not have write permission. so ...
457 we also have to make sure that the user ardour directory
461 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
462 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
468 path = Glib::build_filename (userconfigdir, "pango.rc");
470 std::ofstream pangorc (path.c_str());
472 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
474 mpath = Glib::build_filename (userconfigdir, "pango.modules");
476 pangorc << "[Pango]\nModuleFiles=";
477 pangorc << mpath << endl;
481 setenv ("PANGO_RC_FILE", path.c_str(), 1);
483 /* similar for GDK pixbuf loaders, but there's no RC file required
484 to specify where it lives.
487 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
488 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
495 tell_about_jack_death (void* /* ignored */)
497 if (AudioEngine::instance()->processed_frames() == 0) {
498 /* died during startup */
499 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
500 msg.set_position (Gtk::WIN_POS_CENTER);
501 msg.set_secondary_text (string_compose (_(
502 "JACK exited unexpectedly, and without notifying %1.\n\
504 This could be due to misconfiguration or to an error inside JACK.\n\
506 Click OK to exit %1."), PROGRAM_NAME));
513 /* engine has already run, so this is a mid-session JACK death */
515 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
516 msg->set_secondary_text (string_compose (_(
517 "JACK exited unexpectedly, and without notifying %1.\n\
519 This is probably due to an error inside JACK. You should restart JACK\n\
520 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
521 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
524 return false; /* do not call again */
528 sigpipe_handler (int /*signal*/)
530 /* XXX fix this so that we do this again after a reconnect to JACK
533 static bool done_the_jack_thing = false;
535 if (!done_the_jack_thing) {
536 AudioEngine::instance()->died ();
537 g_idle_add (tell_about_jack_death, 0);
538 done_the_jack_thing = true;
543 void close_external_ui_windows();
548 extern int gui_init (int* argc, char** argv[]);
550 /* this is called from the entry point of a wine-compiled
551 executable that is linked against gtk2_ardour built
555 int ardour_main (int argc, char *argv[])
557 int main (int argc, char *argv[])
560 fixup_bundle_environment (argc, argv);
562 if (!Glib::thread_supported())
568 /* this does some magic that is needed to make GTK and Wine's own
569 X11 client interact properly.
571 gui_init (&argc, &argv);
574 (void) bindtextdomain (PACKAGE, localedir);
575 /* our i18n translations are all in UTF-8, so make sure
576 that even if the user locale doesn't specify UTF-8,
577 we use that when handling them.
579 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
580 (void) textdomain (PACKAGE);
582 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
584 // catch error message system signals ();
586 text_receiver.listen_to (error);
587 text_receiver.listen_to (info);
588 text_receiver.listen_to (fatal);
589 text_receiver.listen_to (warning);
591 if (parse_opts (argc, argv)) {
595 if (curvetest_file) {
596 return curvetest (curvetest_file);
601 << _(" (built using ")
604 << _(" and GCC version ") << __VERSION__
614 cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
615 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
617 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
618 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
619 << _("This is free software, and you are welcome to redistribute it ") << endl
620 << _("under certain conditions; see the source for copying conditions.")
624 /* some GUI objects need this */
628 if (::signal (SIGPIPE, sigpipe_handler)) {
629 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
633 ui = new ARDOUR_UI (&argc, &argv);
634 } catch (failed_constructor& err) {
635 error << _("could not create ARDOUR GUI") << endmsg;
639 ui->run (text_receiver);
640 Gtkmm2ext::Application::instance()->cleanup();
644 pthread_cancel_all ();
647 close_external_ui_windows();
652 } // end of extern C block