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.
26 #include <sigc++/bind.h>
27 #include <gtkmm/settings.h>
29 #include "pbd/error.h"
31 #include "pbd/file_utils.h"
32 #include "pbd/textreceiver.h"
33 #include "pbd/failed_constructor.h"
34 #include "pbd/pthread_utils.h"
35 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
36 #include "pbd/boost_debug.h"
39 #include <jack/jack.h>
41 #include "ardour/svn_revision.h"
42 #include "ardour/version.h"
43 #include "ardour/ardour.h"
44 #include "ardour/audioengine.h"
45 #include "ardour/session_utils.h"
46 #include "ardour/filesystem_paths.h"
48 #include <gtkmm/main.h>
49 #include <gtkmm2ext/application.h>
50 #include <gtkmm2ext/popup.h>
51 #include <gtkmm2ext/utils.h>
55 #include "ardour_ui.h"
63 using namespace ARDOUR_COMMAND_LINE;
64 using namespace ARDOUR;
67 TextReceiver text_receiver ("ardour");
69 extern int curvetest (string);
71 static ARDOUR_UI *ui = 0;
72 static const char* localedir = LOCALEDIR;
77 MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
81 win.set_secondary_text(_("There are several possible reasons:\n\
83 1) JACK is not running.\n\
84 2) JACK is running as another user, perhaps root.\n\
85 3) There is already another client called \"ardour\".\n\
87 Please consider the possibilities, and perhaps (re)start JACK."));
89 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
90 win.set_default_response (RESPONSE_CLOSE);
93 win.set_position (Gtk::WIN_POS_CENTER);
99 /* we just don't care about the result, but we want to block */
104 static void export_search_path (const string& base_dir, const char* varname, const char* dir)
107 const char * cstr = getenv (varname);
118 setenv (varname, path.c_str(), 1);
123 #include <mach-o/dyld.h>
124 #include <sys/param.h>
126 extern void set_language_preference (); // cocoacarbon.mm
129 fixup_bundle_environment (int, char* [])
131 if (!getenv ("ARDOUR_BUNDLED")) {
135 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
137 set_language_preference ();
139 char execpath[MAXPATHLEN+1];
140 uint32_t pathsz = sizeof (execpath);
142 _NSGetExecutablePath (execpath, &pathsz);
144 std::string dir_path = Glib::path_get_dirname (execpath);
146 const char *cstr = getenv ("PATH");
148 /* ensure that we find any bundled executables (e.g. JACK),
149 and find them before any instances of the same name
155 /* JACK is often in /usr/local/bin and since Info.plist refuses to
156 set PATH, we have to force this in order to discover a running
161 path += "/usr/local/bin";
167 setenv ("PATH", path.c_str(), 1);
170 path += "/../Resources";
172 path += "/../Surfaces";
174 path += "/../Panners";
176 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
178 path = user_config_directory().to_string();
181 path += "/../Resources/icons:";
183 path += "/../Resources/pixmaps:";
185 path += "/../Resources/share:";
187 path += "/../Resources";
189 setenv ("ARDOUR_PATH", path.c_str(), 1);
190 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
193 path += "/../Resources";
194 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
196 export_search_path (dir_path, "LADSPA_PATH", "/../Plugins");
197 export_search_path (dir_path, "VAMP_PATH", "/../Frameworks");
198 export_search_path (dir_path, "ARDOUR_PANNER_PATH", "/../Panners");
199 export_search_path (dir_path, "ARDOUR_SURFACES_PATH", "/../Surfaces");
200 export_search_path (dir_path, "ARDOUR_MIDIMAPS_PATH", "/../MidiMaps");
201 export_search_path (dir_path, "ARDOUR_EXPORT_FORMATS_PATH", "/../ExportFormats");
204 path += "/../Frameworks/clearlooks";
206 setenv ("GTK_PATH", path.c_str(), 1);
208 /* unset GTK_RC_FILES so that we only load the RC files that we define
211 unsetenv ("GTK_RC_FILES");
213 if (!ARDOUR::translations_are_disabled ()) {
216 path += "/../Resources/locale";
218 localedir = strdup (path.c_str());
219 setenv ("GTK_LOCALEDIR", localedir, 1);
222 /* write a pango.rc file and tell pango to use it. we'd love
223 to put this into the PROGRAM_NAME.app bundle and leave it there,
224 but the user may not have write permission. so ...
226 we also have to make sure that the user ardour directory
231 sys::create_directories (user_config_directory ());
233 catch (const sys::filesystem_error& ex) {
234 error << _("Could not create user configuration directory") << endmsg;
237 sys::path pangopath = user_config_directory();
238 pangopath /= "pango.rc";
239 path = pangopath.to_string();
241 std::ofstream pangorc (path.c_str());
243 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
246 pangorc << "[Pango]\nModuleFiles=";
248 pangopath = dir_path;
250 pangopath /= "Resources";
251 pangopath /= "pango.modules";
253 pangorc << pangopath.to_string() << endl;
257 setenv ("PANGO_RC_FILE", path.c_str(), 1);
260 // gettext charset aliases
262 setenv ("CHARSETALIASDIR", path.c_str(), 1);
267 path += "/../Resources/fonts.conf";
269 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
271 // GDK Pixbuf loader module file
274 path += "/../Resources/gdk-pixbuf.loaders";
276 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
278 if (getenv ("ARDOUR_WITH_JACK")) {
282 path += "/../Frameworks";
284 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
291 fixup_bundle_environment (int /*argc*/, char* argv[])
293 /* THIS IS FOR LINUX - its just about the only place where its
294 * acceptable to build paths directly using '/'.
297 if (!getenv ("ARDOUR_BUNDLED")) {
301 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
303 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
305 Glib::ustring userconfigdir = user_config_directory().to_string();
307 /* ensure that we find any bundled executables (e.g. JACK),
308 and find them before any instances of the same name
312 /* note that this function is POSIX/Linux specific, so using / as
313 a dir separator in this context is just fine.
319 path += "/lib/surfaces:";
321 path += "/lib/panners:";
323 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
325 path = userconfigdir;
328 path += "/etc/icons:";
330 path += "/etc/pixmaps:";
336 setenv ("ARDOUR_PATH", path.c_str(), 1);
337 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
341 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
343 export_search_path (dir_path, "LADSPA_PATH", "/../plugins");
344 export_search_path (dir_path, "VAMP_PATH", "/lib");
345 export_search_path (dir_path, "ARDOUR_PANNER_PATH", "/lib/panners");
346 export_search_path (dir_path, "ARDOUR_SURFACES_PATH", "/lib/surfaces");
347 export_search_path (dir_path, "ARDOUR_MIDIMAPS_PATH", "/share/midi_maps");
348 export_search_path (dir_path, "ARDOUR_EXPORT_FORMATS_PATH", "/share/export");
351 path += "/lib/clearlooks";
352 setenv ("GTK_PATH", path.c_str(), 1);
354 /* unset GTK_RC_FILES so that we only load the RC files that we define
357 unsetenv ("GTK_RC_FILES");
359 if (!ARDOUR::translations_are_disabled ()) {
361 path += "/share/locale";
363 localedir = strdup (path.c_str());
364 setenv ("GTK_LOCALEDIR", localedir, 1);
367 /* write a pango.rc file and tell pango to use it. we'd love
368 to put this into the Ardour.app bundle and leave it there,
369 but the user may not have write permission. so ...
371 we also have to make sure that the user ardour directory
375 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
376 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
383 path = Glib::build_filename (userconfigdir, "pango.rc");
385 std::ofstream pangorc (path.c_str());
387 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
389 mpath = Glib::build_filename (userconfigdir, "pango.modules");
391 pangorc << "[Pango]\nModuleFiles=";
392 pangorc << mpath << endl;
396 setenv ("PANGO_RC_FILE", path.c_str(), 1);
398 /* Tell fontconfig where to find fonts.conf. Use the system version
399 if it exists, otherwise use the stuff we included in t
402 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
403 setenv ("/etc/fonts/fonts.conf", path.c_str(), 1);
405 /* use the one included in the bundle */
407 path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
408 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
411 /* similar for GDK pixbuf loaders, but there's no RC file required
412 to specify where it lives.
415 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
416 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
422 tell_about_jack_death (void* /* ignored */)
424 if (AudioEngine::instance()->processed_frames() == 0) {
425 /* died during startup */
426 MessageDialog msg (_("JACK exited"), false);
427 msg.set_position (Gtk::WIN_POS_CENTER);
428 msg.set_secondary_text (string_compose (_(
429 "JACK exited unexpectedly, and without notifying %1.\n\
431 This could be due to misconfiguration or to an error inside JACK.\n\
433 Click OK to exit %1."), PROGRAM_NAME));
440 /* engine has already run, so this is a mid-session JACK death */
442 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
443 msg->set_secondary_text (string_compose (_(
444 "JACK exited unexpectedly, and without notifying %1.\n\
446 This is probably due to an error inside JACK. You should restart JACK\n\
447 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
448 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
451 return false; /* do not call again */
455 sigpipe_handler (int /*signal*/)
457 /* XXX fix this so that we do this again after a reconnect to JACK
460 static bool done_the_jack_thing = false;
462 if (!done_the_jack_thing) {
463 AudioEngine::instance()->died ();
464 g_idle_add (tell_about_jack_death, 0);
465 done_the_jack_thing = true;
470 void close_external_ui_windows();
473 #ifdef WINDOWS_VST_SUPPORT
475 extern int windows_vst_gui_init (int* argc, char** argv[]);
477 /* this is called from the entry point of a wine-compiled
478 executable that is linked against gtk2_ardour built
482 int ardour_main (int argc, char *argv[])
484 int main (int argc, char *argv[])
487 fixup_bundle_environment (argc, argv);
489 if (!Glib::thread_supported()) {
495 #ifdef WINDOWS_VST_SUPPORT
496 /* this does some magic that is needed to make GTK and Wine's own
497 X11 client interact properly.
499 windows_vst_gui_init (&argc, &argv);
502 (void) bindtextdomain (PACKAGE, localedir);
503 /* our i18n translations are all in UTF-8, so make sure
504 that even if the user locale doesn't specify UTF-8,
505 we use that when handling them.
507 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
508 (void) textdomain (PACKAGE);
510 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
512 // catch error message system signals ();
514 text_receiver.listen_to (error);
515 text_receiver.listen_to (info);
516 text_receiver.listen_to (fatal);
517 text_receiver.listen_to (warning);
519 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
520 if (getenv ("BOOST_DEBUG")) {
521 boost_debug_shared_ptr_show_live_debugging (true);
525 if (parse_opts (argc, argv)) {
529 if (curvetest_file) {
530 return curvetest (curvetest_file);
535 << _(" (built using ")
538 << _(" and GCC version ") << __VERSION__
548 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
549 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
551 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
552 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
553 << _("This is free software, and you are welcome to redistribute it ") << endl
554 << _("under certain conditions; see the source for copying conditions.")
558 /* some GUI objects need this */
562 if (::signal (SIGPIPE, sigpipe_handler)) {
563 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
567 ui = new ARDOUR_UI (&argc, &argv);
568 } catch (failed_constructor& err) {
569 error << _("could not create ARDOUR GUI") << endmsg;
573 ui->run (text_receiver);
574 Gtkmm2ext::Application::instance()->cleanup();
578 pthread_cancel_all ();
581 close_external_ui_windows();
585 #ifdef WINDOWS_VST_SUPPORT
586 } // end of extern C block