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"
29 #include "pbd/file_utils.h"
30 #include "pbd/textreceiver.h"
31 #include "pbd/failed_constructor.h"
32 #include "pbd/pthread_utils.h"
34 #include <jack/jack.h>
36 #include "ardour/svn_revision.h"
37 #include "ardour/version.h"
38 #include "ardour/ardour.h"
39 #include "ardour/audioengine.h"
40 #include "ardour/session_utils.h"
41 #include "ardour/filesystem_paths.h"
43 #include <gtkmm/main.h>
44 #include <gtkmm2ext/application.h>
45 #include <gtkmm2ext/popup.h>
46 #include <gtkmm2ext/utils.h>
50 #include "ardour_ui.h"
58 using namespace ARDOUR_COMMAND_LINE;
59 using namespace ARDOUR;
62 TextReceiver text_receiver ("ardour");
64 extern int curvetest (string);
66 static ARDOUR_UI *ui = 0;
67 static const char* localedir = LOCALEDIR;
72 MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
75 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
76 win.set_secondary_text(_("There are several possible reasons:\n\
78 1) JACK is not running.\n\
79 2) JACK is running as another user, perhaps root.\n\
80 3) There is already another client called \"ardour\".\n\
82 Please consider the possibilities, and perhaps (re)start JACK."));
84 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
85 win.set_default_response (RESPONSE_CLOSE);
88 win.set_position (Gtk::WIN_POS_CENTER);
94 /* we just don't care about the result, but we want to block */
102 #include <mach-o/dyld.h>
103 #include <sys/param.h>
105 extern void set_language_preference (); // cocoacarbon.mm
108 fixup_bundle_environment ()
110 if (!getenv ("ARDOUR_BUNDLED")) {
114 set_language_preference ();
116 char execpath[MAXPATHLEN+1];
117 uint32_t pathsz = sizeof (execpath);
119 _NSGetExecutablePath (execpath, &pathsz);
121 std::string exec_path (execpath);
122 std::string dir_path = Glib::path_get_dirname (exec_path);
124 const char *cstr = getenv ("PATH");
126 /* ensure that we find any bundled executables (e.g. JACK),
127 and find them before any instances of the same name
133 /* JACK is often in /usr/local/bin and since Info.plist refuses to
134 set PATH, we have to force this in order to discover a running
139 path += "/usr/local/bin";
145 setenv ("PATH", path.c_str(), 1);
148 path += "/../Resources";
150 path += "/../Resources/Surfaces";
152 path += "/../Resources/Panners";
154 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
156 path = user_config_directory().to_string();
159 path += "/../Resources/icons:";
161 path += "/../Resources/pixmaps:";
163 path += "/../Resources/share:";
165 path += "/../Resources";
167 setenv ("ARDOUR_PATH", path.c_str(), 1);
168 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
171 path += "/../Resources";
172 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
174 cstr = getenv ("LADSPA_PATH");
182 path += "/../Plugins";
184 setenv ("LADSPA_PATH", path.c_str(), 1);
186 cstr = getenv ("VAMP_PATH");
194 path += "/../Frameworks";
196 setenv ("VAMP_PATH", path.c_str(), 1);
198 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
206 path += "/../Surfaces";
208 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
210 cstr = getenv ("LV2_PATH");
218 path += "/../Plugins";
220 setenv ("LV2_PATH", path.c_str(), 1);
223 path += "/../Frameworks/clearlooks";
225 setenv ("GTK_PATH", path.c_str(), 1);
227 if (!ARDOUR::translations_are_disabled ()) {
230 path += "/../Resources/locale";
232 localedir = strdup (path.c_str());
233 setenv ("GTK_LOCALEDIR", localedir, 1);
236 /* write a pango.rc file and tell pango to use it. we'd love
237 to put this into the PROGRAM_NAME.app bundle and leave it there,
238 but the user may not have write permission. so ...
240 we also have to make sure that the user ardour directory
245 sys::create_directories (user_config_directory ());
247 catch (const sys::filesystem_error& ex) {
248 error << _("Could not create user configuration directory") << endmsg;
251 sys::path pangopath = user_config_directory();
252 pangopath /= "pango.rc";
253 path = pangopath.to_string();
255 std::ofstream pangorc (path.c_str());
257 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
260 pangorc << "[Pango]\nModuleFiles=";
262 pangopath = dir_path;
264 pangopath /= "Resources";
265 pangopath /= "pango.modules";
267 pangorc << pangopath.to_string() << endl;
271 setenv ("PANGO_RC_FILE", path.c_str(), 1);
274 // gettext charset aliases
276 setenv ("CHARSETALIASDIR", path.c_str(), 1);
281 path += "/../Resources/fonts.conf";
283 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
285 // GDK Pixbuf loader module file
288 path += "/../Resources/gdk-pixbuf.loaders";
290 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
292 if (getenv ("ARDOUR_WITH_JACK")) {
296 path += "/../Frameworks";
298 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
305 fixup_bundle_environment (int argc, char* argv[])
307 if (!getenv ("ARDOUR_BUNDLED")) {
311 Glib::ustring exec_path = argv[0];
312 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
314 const char *cstr = getenv ("PATH");
315 Glib::ustring userconfigdir = user_config_directory().to_string();
317 /* ensure that we find any bundled executables (e.g. JACK),
318 and find them before any instances of the same name
322 /* note that this function is POSIX/Linux specific, so using / as
323 a dir separator in this context is just fine.
329 path += "/lib/surfaces:";
331 path += "/lib/panners:";
333 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
335 path = userconfigdir;
338 path += "/etc/icons:";
340 path += "/etc/pixmaps:";
346 setenv ("ARDOUR_PATH", path.c_str(), 1);
347 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
351 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
353 cstr = getenv ("LADSPA_PATH");
361 path += "/lib/plugins";
363 setenv ("LADSPA_PATH", path.c_str(), 1);
365 cstr = getenv ("VAMP_PATH");
375 setenv ("VAMP_PATH", path.c_str(), 1);
377 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
385 path += "/lib/surfaces";
387 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
389 cstr = getenv ("LV2_PATH");
397 path += "/lib/plugins";
399 setenv ("LV2_PATH", path.c_str(), 1);
402 path += "/lib/clearlooks";
404 setenv ("GTK_PATH", path.c_str(), 1);
406 if (!ARDOUR::translations_are_disabled ()) {
408 path += "/share/locale";
410 localedir = strdup (path.c_str());
411 setenv ("GTK_LOCALEDIR", localedir, 1);
414 /* write a pango.rc file and tell pango to use it. we'd love
415 to put this into the Ardour.app bundle and leave it there,
416 but the user may not have write permission. so ...
418 we also have to make sure that the user ardour directory
422 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
423 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
429 path = Glib::build_filename (userconfigdir, "pango.rc");
431 std::ofstream pangorc (path.c_str());
433 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
435 mpath = Glib::build_filename (userconfigdir, "pango.modules");
437 pangorc << "[Pango]\nModuleFiles=";
438 pangorc << mpath << endl;
442 setenv ("PANGO_RC_FILE", path.c_str(), 1);
444 /* similar for GDK pixbuf loaders, but there's no RC file required
445 to specify where it lives.
448 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
449 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
456 tell_about_jack_death (void* /* ignored */)
458 if (AudioEngine::instance()->processed_frames() == 0) {
459 /* died during startup */
460 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
461 msg.set_position (Gtk::WIN_POS_CENTER);
462 msg.set_secondary_text (string_compose (_(
463 "JACK exited unexpectedly, and without notifying %1.\n\
465 This could be due to misconfiguration or to an error inside JACK.\n\
467 Click OK to exit %1."), PROGRAM_NAME));
474 /* engine has already run, so this is a mid-session JACK death */
476 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
477 msg->set_secondary_text (string_compose (_(
478 "JACK exited unexpectedly, and without notifying %1.\n\
480 This is probably due to an error inside JACK. You should restart JACK\n\
481 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
482 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
485 return false; /* do not call again */
489 sigpipe_handler (int /*signal*/)
491 /* XXX fix this so that we do this again after a reconnect to JACK
494 static bool done_the_jack_thing = false;
496 if (!done_the_jack_thing) {
497 AudioEngine::instance()->died ();
498 g_idle_add (tell_about_jack_death, 0);
499 done_the_jack_thing = true;
504 void close_external_ui_windows();
509 extern int gui_init (int* argc, char** argv[]);
511 /* this is called from the entry point of a wine-compiled
512 executable that is linked against gtk2_ardour built
516 int ardour_main (int argc, char *argv[])
518 int main (int argc, char *argv[])
522 fixup_bundle_environment ();
525 if (!Glib::thread_supported())
531 /* this does some magic that is needed to make GTK and Wine's own
532 X11 client interact properly.
534 gui_init (&argc, &argv);
537 (void) bindtextdomain (PACKAGE, localedir);
538 /* our i18n translations are all in UTF-8, so make sure
539 that even if the user locale doesn't specify UTF-8,
540 we use that when handling them.
542 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
543 (void) textdomain (PACKAGE);
545 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
547 // catch error message system signals ();
549 text_receiver.listen_to (error);
550 text_receiver.listen_to (info);
551 text_receiver.listen_to (fatal);
552 text_receiver.listen_to (warning);
554 if (parse_opts (argc, argv)) {
558 if (curvetest_file) {
559 return curvetest (curvetest_file);
564 << _(" (built using ")
567 << _(" and GCC version ") << __VERSION__
577 cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
578 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
580 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
581 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
582 << _("This is free software, and you are welcome to redistribute it ") << endl
583 << _("under certain conditions; see the source for copying conditions.")
587 /* some GUI objects need this */
591 if (::signal (SIGPIPE, sigpipe_handler)) {
592 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
596 ui = new ARDOUR_UI (&argc, &argv);
597 } catch (failed_constructor& err) {
598 error << _("could not create ARDOUR GUI") << endmsg;
602 ui->run (text_receiver);
603 Gtkmm2ext::Application::instance()->cleanup();
607 pthread_cancel_all ();
610 close_external_ui_windows();
615 } // end of extern C block