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 set_language_preference ();
117 char execpath[MAXPATHLEN+1];
118 uint32_t pathsz = sizeof (execpath);
120 _NSGetExecutablePath (execpath, &pathsz);
122 std::string exec_path (execpath);
123 std::string dir_path = Glib::path_get_dirname (exec_path);
125 const char *cstr = getenv ("PATH");
127 /* ensure that we find any bundled executables (e.g. JACK),
128 and find them before any instances of the same name
134 /* JACK is often in /usr/local/bin and since Info.plist refuses to
135 set PATH, we have to force this in order to discover a running
140 path += "/usr/local/bin";
146 setenv ("PATH", path.c_str(), 1);
149 path += "/../Resources";
151 path += "/../Resources/Surfaces";
153 path += "/../Resources/Panners";
155 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
157 path = user_config_directory().to_string();
160 path += "/../Resources/icons:";
162 path += "/../Resources/pixmaps:";
164 path += "/../Resources/share:";
166 path += "/../Resources";
168 setenv ("ARDOUR_PATH", path.c_str(), 1);
169 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
172 path += "/../Resources";
173 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
175 cstr = getenv ("LADSPA_PATH");
183 path += "/../Plugins";
185 setenv ("LADSPA_PATH", path.c_str(), 1);
187 cstr = getenv ("VAMP_PATH");
195 path += "/../Frameworks";
197 setenv ("VAMP_PATH", path.c_str(), 1);
199 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
207 path += "/../Surfaces";
209 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
211 cstr = getenv ("LV2_PATH");
219 path += "/../Plugins";
221 setenv ("LV2_PATH", path.c_str(), 1);
224 path += "/../Frameworks/clearlooks";
226 setenv ("GTK_PATH", path.c_str(), 1);
228 if (!ARDOUR::translations_are_disabled ()) {
231 path += "/../Resources/locale";
233 localedir = strdup (path.c_str());
234 setenv ("GTK_LOCALEDIR", localedir, 1);
237 /* write a pango.rc file and tell pango to use it. we'd love
238 to put this into the PROGRAM_NAME.app bundle and leave it there,
239 but the user may not have write permission. so ...
241 we also have to make sure that the user ardour directory
246 sys::create_directories (user_config_directory ());
248 catch (const sys::filesystem_error& ex) {
249 error << _("Could not create user configuration directory") << endmsg;
252 sys::path pangopath = user_config_directory();
253 pangopath /= "pango.rc";
254 path = pangopath.to_string();
256 std::ofstream pangorc (path.c_str());
258 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
261 pangorc << "[Pango]\nModuleFiles=";
263 pangopath = dir_path;
265 pangopath /= "Resources";
266 pangopath /= "pango.modules";
268 pangorc << pangopath.to_string() << endl;
272 setenv ("PANGO_RC_FILE", path.c_str(), 1);
275 // gettext charset aliases
277 setenv ("CHARSETALIASDIR", path.c_str(), 1);
282 path += "/../Resources/fonts.conf";
284 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
286 // GDK Pixbuf loader module file
289 path += "/../Resources/gdk-pixbuf.loaders";
291 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
293 if (getenv ("ARDOUR_WITH_JACK")) {
297 path += "/../Frameworks";
299 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
306 fixup_bundle_environment (int argc, char* argv[])
308 if (!getenv ("ARDOUR_BUNDLED")) {
312 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency);
314 Glib::ustring exec_path = argv[0];
315 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
317 const char *cstr = getenv ("PATH");
318 Glib::ustring userconfigdir = user_config_directory().to_string();
320 /* ensure that we find any bundled executables (e.g. JACK),
321 and find them before any instances of the same name
325 /* note that this function is POSIX/Linux specific, so using / as
326 a dir separator in this context is just fine.
332 path += "/lib/surfaces:";
334 path += "/lib/panners:";
336 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
338 path = userconfigdir;
341 path += "/etc/icons:";
343 path += "/etc/pixmaps:";
349 setenv ("ARDOUR_PATH", path.c_str(), 1);
350 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
354 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
356 cstr = getenv ("LADSPA_PATH");
364 path += "/lib/plugins";
366 setenv ("LADSPA_PATH", path.c_str(), 1);
368 cstr = getenv ("VAMP_PATH");
378 setenv ("VAMP_PATH", path.c_str(), 1);
380 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
388 path += "/lib/surfaces";
390 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
392 cstr = getenv ("LV2_PATH");
400 path += "/lib/plugins";
402 setenv ("LV2_PATH", path.c_str(), 1);
405 path += "/lib/clearlooks";
407 setenv ("GTK_PATH", path.c_str(), 1);
409 if (!ARDOUR::translations_are_disabled ()) {
411 path += "/share/locale";
413 localedir = strdup (path.c_str());
414 setenv ("GTK_LOCALEDIR", localedir, 1);
417 /* write a pango.rc file and tell pango to use it. we'd love
418 to put this into the Ardour.app bundle and leave it there,
419 but the user may not have write permission. so ...
421 we also have to make sure that the user ardour directory
425 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
426 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
432 path = Glib::build_filename (userconfigdir, "pango.rc");
434 std::ofstream pangorc (path.c_str());
436 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
438 mpath = Glib::build_filename (userconfigdir, "pango.modules");
440 pangorc << "[Pango]\nModuleFiles=";
441 pangorc << mpath << endl;
445 setenv ("PANGO_RC_FILE", path.c_str(), 1);
447 /* similar for GDK pixbuf loaders, but there's no RC file required
448 to specify where it lives.
451 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
452 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
459 tell_about_jack_death (void* /* ignored */)
461 if (AudioEngine::instance()->processed_frames() == 0) {
462 /* died during startup */
463 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
464 msg.set_position (Gtk::WIN_POS_CENTER);
465 msg.set_secondary_text (string_compose (_(
466 "JACK exited unexpectedly, and without notifying %1.\n\
468 This could be due to misconfiguration or to an error inside JACK.\n\
470 Click OK to exit %1."), PROGRAM_NAME));
477 /* engine has already run, so this is a mid-session JACK death */
479 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
480 msg->set_secondary_text (string_compose (_(
481 "JACK exited unexpectedly, and without notifying %1.\n\
483 This is probably due to an error inside JACK. You should restart JACK\n\
484 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
485 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
488 return false; /* do not call again */
492 sigpipe_handler (int /*signal*/)
494 /* XXX fix this so that we do this again after a reconnect to JACK
497 static bool done_the_jack_thing = false;
499 if (!done_the_jack_thing) {
500 AudioEngine::instance()->died ();
501 g_idle_add (tell_about_jack_death, 0);
502 done_the_jack_thing = true;
507 void close_external_ui_windows();
512 extern int gui_init (int* argc, char** argv[]);
514 /* this is called from the entry point of a wine-compiled
515 executable that is linked against gtk2_ardour built
519 int ardour_main (int argc, char *argv[])
521 int main (int argc, char *argv[])
525 fixup_bundle_environment ();
528 if (!Glib::thread_supported())
534 /* this does some magic that is needed to make GTK and Wine's own
535 X11 client interact properly.
537 gui_init (&argc, &argv);
540 (void) bindtextdomain (PACKAGE, localedir);
541 /* our i18n translations are all in UTF-8, so make sure
542 that even if the user locale doesn't specify UTF-8,
543 we use that when handling them.
545 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
546 (void) textdomain (PACKAGE);
548 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
550 // catch error message system signals ();
552 text_receiver.listen_to (error);
553 text_receiver.listen_to (info);
554 text_receiver.listen_to (fatal);
555 text_receiver.listen_to (warning);
557 if (parse_opts (argc, argv)) {
561 if (curvetest_file) {
562 return curvetest (curvetest_file);
567 << _(" (built using ")
570 << _(" and GCC version ") << __VERSION__
580 cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
581 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
583 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
584 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
585 << _("This is free software, and you are welcome to redistribute it ") << endl
586 << _("under certain conditions; see the source for copying conditions.")
590 /* some GUI objects need this */
594 if (::signal (SIGPIPE, sigpipe_handler)) {
595 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
599 ui = new ARDOUR_UI (&argc, &argv);
600 } catch (failed_constructor& err) {
601 error << _("could not create ARDOUR GUI") << endmsg;
605 ui->run (text_receiver);
606 Gtkmm2ext::Application::instance()->cleanup();
610 pthread_cancel_all ();
613 close_external_ui_windows();
618 } // end of extern C block