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 /* Tell fontconfig where to find fonts.conf. Use the system version
368 if it exists, otherwise use the stuff we included in t
371 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
372 setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
373 setenv ("FONTCONFIG_PATH, "/etc/fonts", 1);
375 /* use the one included in the bundle */
377 path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
378 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
379 path = Glib::build_filename (dir_path, "etc/fonts");
380 setenv ("FONTCONFIG_PATH, "/etc/fonts", 1);
383 /* write a pango.rc file and tell pango to use it. we'd love
384 to put this into the Ardour.app bundle and leave it there,
385 but the user may not have write permission. so ...
387 we also have to make sure that the user ardour directory
391 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
392 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
399 path = Glib::build_filename (userconfigdir, "pango.rc");
401 std::ofstream pangorc (path.c_str());
403 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
405 mpath = Glib::build_filename (userconfigdir, "pango.modules");
407 pangorc << "[Pango]\nModuleFiles=";
408 pangorc << mpath << endl;
412 setenv ("PANGO_RC_FILE", path.c_str(), 1);
414 /* similar for GDK pixbuf loaders, but there's no RC file required
415 to specify where it lives.
418 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
419 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
425 tell_about_jack_death (void* /* ignored */)
427 if (AudioEngine::instance()->processed_frames() == 0) {
428 /* died during startup */
429 MessageDialog msg (_("JACK exited"), false);
430 msg.set_position (Gtk::WIN_POS_CENTER);
431 msg.set_secondary_text (string_compose (_(
432 "JACK exited unexpectedly, and without notifying %1.\n\
434 This could be due to misconfiguration or to an error inside JACK.\n\
436 Click OK to exit %1."), PROGRAM_NAME));
443 /* engine has already run, so this is a mid-session JACK death */
445 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
446 msg->set_secondary_text (string_compose (_(
447 "JACK exited unexpectedly, and without notifying %1.\n\
449 This is probably due to an error inside JACK. You should restart JACK\n\
450 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
451 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
454 return false; /* do not call again */
458 sigpipe_handler (int /*signal*/)
460 /* XXX fix this so that we do this again after a reconnect to JACK
463 static bool done_the_jack_thing = false;
465 if (!done_the_jack_thing) {
466 AudioEngine::instance()->died ();
467 g_idle_add (tell_about_jack_death, 0);
468 done_the_jack_thing = true;
473 void close_external_ui_windows();
476 #ifdef WINDOWS_VST_SUPPORT
478 extern int windows_vst_gui_init (int* argc, char** argv[]);
480 /* this is called from the entry point of a wine-compiled
481 executable that is linked against gtk2_ardour built
485 int ardour_main (int argc, char *argv[])
487 int main (int argc, char *argv[])
490 fixup_bundle_environment (argc, argv);
492 if (!Glib::thread_supported()) {
498 #ifdef WINDOWS_VST_SUPPORT
499 /* this does some magic that is needed to make GTK and Wine's own
500 X11 client interact properly.
502 windows_vst_gui_init (&argc, &argv);
505 (void) bindtextdomain (PACKAGE, localedir);
506 /* our i18n translations are all in UTF-8, so make sure
507 that even if the user locale doesn't specify UTF-8,
508 we use that when handling them.
510 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
511 (void) textdomain (PACKAGE);
513 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
515 // catch error message system signals ();
517 text_receiver.listen_to (error);
518 text_receiver.listen_to (info);
519 text_receiver.listen_to (fatal);
520 text_receiver.listen_to (warning);
522 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
523 if (getenv ("BOOST_DEBUG")) {
524 boost_debug_shared_ptr_show_live_debugging (true);
528 if (parse_opts (argc, argv)) {
532 if (curvetest_file) {
533 return curvetest (curvetest_file);
538 << _(" (built using ")
541 << _(" and GCC version ") << __VERSION__
551 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
552 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
554 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
555 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
556 << _("This is free software, and you are welcome to redistribute it ") << endl
557 << _("under certain conditions; see the source for copying conditions.")
561 /* some GUI objects need this */
565 if (::signal (SIGPIPE, sigpipe_handler)) {
566 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
570 ui = new ARDOUR_UI (&argc, &argv);
571 } catch (failed_constructor& err) {
572 error << _("could not create ARDOUR GUI") << endmsg;
576 ui->run (text_receiver);
577 Gtkmm2ext::Application::instance()->cleanup();
581 pthread_cancel_all ();
584 close_external_ui_windows();
588 #ifdef WINDOWS_VST_SUPPORT
589 } // end of extern C block