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);
169 export_search_path (dir_path, "ARDOUR_DLL_PATH", "/../lib");
172 path += "/../Resources";
174 /* inside an OS X .app bundle, there is no difference
175 between DATA and CONFIG locations, since OS X doesn't
176 attempt to do anything to expose the notion of
177 machine-independent shared data.
180 export_search_path (dir_path, "ARDOUR_DATA_PATH", "/../Resources");
181 export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/../Resources");
182 export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/../Resources");
184 export_search_path (dir_path, "LADSPA_PATH", "/../Plugins");
185 export_search_path (dir_path, "VAMP_PATH", "/../lib");
186 export_search_path (dir_path, "SUIL_MODULE_DIR", "/../lib");
189 path += "/../lib/clearlooks";
190 setenv ("GTK_PATH", path.c_str(), 1);
192 /* unset GTK_RC_FILES so that we only load the RC files that we define
195 unsetenv ("GTK_RC_FILES");
197 if (!ARDOUR::translations_are_disabled ()) {
200 path += "/../Resources/locale";
202 localedir = strdup (path.c_str());
203 setenv ("GTK_LOCALEDIR", localedir, 1);
206 /* write a pango.rc file and tell pango to use it. we'd love
207 to put this into the PROGRAM_NAME.app bundle and leave it there,
208 but the user may not have write permission. so ...
210 we also have to make sure that the user ardour directory
215 sys::create_directories (user_config_directory ());
217 catch (const sys::filesystem_error& ex) {
218 error << _("Could not create user configuration directory") << endmsg;
221 sys::path pangopath = user_config_directory();
222 pangopath /= "pango.rc";
223 path = pangopath.to_string();
225 std::ofstream pangorc (path.c_str());
227 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
230 pangorc << "[Pango]\nModuleFiles=";
232 pangopath = dir_path;
234 pangopath /= "Resources";
235 pangopath /= "pango.modules";
237 pangorc << pangopath.to_string() << endl;
241 setenv ("PANGO_RC_FILE", path.c_str(), 1);
244 // gettext charset aliases
246 setenv ("CHARSETALIASDIR", path.c_str(), 1);
251 path += "/../Resources/fonts.conf";
253 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
255 // GDK Pixbuf loader module file
258 path += "/../Resources/gdk-pixbuf.loaders";
260 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
262 if (getenv ("ARDOUR_WITH_JACK")) {
268 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
275 fixup_bundle_environment (int /*argc*/, char* argv[])
277 /* THIS IS FOR LINUX - its just about the only place where its
278 * acceptable to build paths directly using '/'.
281 if (!getenv ("ARDOUR_BUNDLED")) {
285 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
287 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
289 Glib::ustring userconfigdir = user_config_directory().to_string();
291 /* note that this function is POSIX/Linux specific, so using / as
292 a dir separator in this context is just fine.
295 export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
296 export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
297 export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
298 export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
300 export_search_path (dir_path, "LADSPA_PATH", "/../plugins");
301 export_search_path (dir_path, "VAMP_PATH", "/lib");
302 export_search_path (dir_path, "SUIL_MODULE_DIR", "/lib");
305 path += "/lib/clearlooks";
306 setenv ("GTK_PATH", path.c_str(), 1);
308 /* unset GTK_RC_FILES so that we only load the RC files that we define
311 unsetenv ("GTK_RC_FILES");
313 if (!ARDOUR::translations_are_disabled ()) {
315 path += "/share/locale";
317 localedir = strdup (path.c_str());
318 setenv ("GTK_LOCALEDIR", localedir, 1);
321 /* Tell fontconfig where to find fonts.conf. Use the system version
322 if it exists, otherwise use the stuff we included in the bundle
325 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
326 setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
327 setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
329 /* use the one included in the bundle */
331 path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
332 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
333 path = Glib::build_filename (dir_path, "etc/fonts");
334 setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
337 /* write a pango.rc file and tell pango to use it. we'd love
338 to put this into the Ardour.app bundle and leave it there,
339 but the user may not have write permission. so ...
341 we also have to make sure that the user ardour directory
345 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
346 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
353 path = Glib::build_filename (userconfigdir, "pango.rc");
355 std::ofstream pangorc (path.c_str());
357 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
359 mpath = Glib::build_filename (userconfigdir, "pango.modules");
361 pangorc << "[Pango]\nModuleFiles=";
362 pangorc << mpath << endl;
366 setenv ("PANGO_RC_FILE", path.c_str(), 1);
368 /* similar for GDK pixbuf loaders, but there's no RC file required
369 to specify where it lives.
372 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
373 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
379 tell_about_jack_death (void* /* ignored */)
381 if (AudioEngine::instance()->processed_frames() == 0) {
382 /* died during startup */
383 MessageDialog msg (_("JACK exited"), false);
384 msg.set_position (Gtk::WIN_POS_CENTER);
385 msg.set_secondary_text (string_compose (_(
386 "JACK exited unexpectedly, and without notifying %1.\n\
388 This could be due to misconfiguration or to an error inside JACK.\n\
390 Click OK to exit %1."), PROGRAM_NAME));
397 /* engine has already run, so this is a mid-session JACK death */
399 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
400 msg->set_secondary_text (string_compose (_(
401 "JACK exited unexpectedly, and without notifying %1.\n\
403 This is probably due to an error inside JACK. You should restart JACK\n\
404 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
405 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
408 return false; /* do not call again */
412 sigpipe_handler (int /*signal*/)
414 /* XXX fix this so that we do this again after a reconnect to JACK
417 static bool done_the_jack_thing = false;
419 if (!done_the_jack_thing) {
420 AudioEngine::instance()->died ();
421 g_idle_add (tell_about_jack_death, 0);
422 done_the_jack_thing = true;
427 void close_external_ui_windows();
430 #ifdef WINDOWS_VST_SUPPORT
432 extern int windows_vst_gui_init (int* argc, char** argv[]);
434 /* this is called from the entry point of a wine-compiled
435 executable that is linked against gtk2_ardour built
439 int ardour_main (int argc, char *argv[])
441 int main (int argc, char *argv[])
444 fixup_bundle_environment (argc, argv);
446 if (!Glib::thread_supported()) {
452 #ifdef WINDOWS_VST_SUPPORT
453 /* this does some magic that is needed to make GTK and Wine's own
454 X11 client interact properly.
456 windows_vst_gui_init (&argc, &argv);
459 (void) bindtextdomain (PACKAGE, localedir);
460 /* our i18n translations are all in UTF-8, so make sure
461 that even if the user locale doesn't specify UTF-8,
462 we use that when handling them.
464 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
465 (void) textdomain (PACKAGE);
467 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
469 // catch error message system signals ();
471 text_receiver.listen_to (error);
472 text_receiver.listen_to (info);
473 text_receiver.listen_to (fatal);
474 text_receiver.listen_to (warning);
476 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
477 if (getenv ("BOOST_DEBUG")) {
478 boost_debug_shared_ptr_show_live_debugging (true);
482 if (parse_opts (argc, argv)) {
486 if (curvetest_file) {
487 return curvetest (curvetest_file);
492 << _(" (built using ")
495 << _(" and GCC version ") << __VERSION__
505 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
506 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
508 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
509 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
510 << _("This is free software, and you are welcome to redistribute it ") << endl
511 << _("under certain conditions; see the source for copying conditions.")
515 /* some GUI objects need this */
519 if (::signal (SIGPIPE, sigpipe_handler)) {
520 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
524 ui = new ARDOUR_UI (&argc, &argv);
525 } catch (failed_constructor& err) {
526 error << _("could not create ARDOUR GUI") << endmsg;
530 ui->run (text_receiver);
531 Gtkmm2ext::Application::instance()->cleanup();
535 pthread_cancel_all ();
538 close_external_ui_windows();
542 #ifdef WINDOWS_VST_SUPPORT
543 } // end of extern C block