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", "/../Frameworks");
188 path += "/../lib/clearlooks";
189 setenv ("GTK_PATH", path.c_str(), 1);
191 /* unset GTK_RC_FILES so that we only load the RC files that we define
194 unsetenv ("GTK_RC_FILES");
196 if (!ARDOUR::translations_are_disabled ()) {
199 path += "/../Resources/locale";
201 localedir = strdup (path.c_str());
202 setenv ("GTK_LOCALEDIR", localedir, 1);
205 /* write a pango.rc file and tell pango to use it. we'd love
206 to put this into the PROGRAM_NAME.app bundle and leave it there,
207 but the user may not have write permission. so ...
209 we also have to make sure that the user ardour directory
214 sys::create_directories (user_config_directory ());
216 catch (const sys::filesystem_error& ex) {
217 error << _("Could not create user configuration directory") << endmsg;
220 sys::path pangopath = user_config_directory();
221 pangopath /= "pango.rc";
222 path = pangopath.to_string();
224 std::ofstream pangorc (path.c_str());
226 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
229 pangorc << "[Pango]\nModuleFiles=";
231 pangopath = dir_path;
233 pangopath /= "Resources";
234 pangopath /= "pango.modules";
236 pangorc << pangopath.to_string() << endl;
240 setenv ("PANGO_RC_FILE", path.c_str(), 1);
243 // gettext charset aliases
245 setenv ("CHARSETALIASDIR", path.c_str(), 1);
250 path += "/../Resources/fonts.conf";
252 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
254 // GDK Pixbuf loader module file
257 path += "/../Resources/gdk-pixbuf.loaders";
259 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
261 if (getenv ("ARDOUR_WITH_JACK")) {
265 path += "/../Frameworks";
267 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
274 fixup_bundle_environment (int /*argc*/, char* argv[])
276 /* THIS IS FOR LINUX - its just about the only place where its
277 * acceptable to build paths directly using '/'.
280 if (!getenv ("ARDOUR_BUNDLED")) {
284 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
286 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
288 Glib::ustring userconfigdir = user_config_directory().to_string();
290 /* note that this function is POSIX/Linux specific, so using / as
291 a dir separator in this context is just fine.
294 export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
295 export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
296 export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
297 export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
299 export_search_path (dir_path, "LADSPA_PATH", "/../plugins");
300 export_search_path (dir_path, "VAMP_PATH", "/lib");
303 path += "/lib/clearlooks";
304 setenv ("GTK_PATH", path.c_str(), 1);
306 /* unset GTK_RC_FILES so that we only load the RC files that we define
309 unsetenv ("GTK_RC_FILES");
311 if (!ARDOUR::translations_are_disabled ()) {
313 path += "/share/locale";
315 localedir = strdup (path.c_str());
316 setenv ("GTK_LOCALEDIR", localedir, 1);
319 /* Tell fontconfig where to find fonts.conf. Use the system version
320 if it exists, otherwise use the stuff we included in the bundle
323 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
324 setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
325 setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
327 /* use the one included in the bundle */
329 path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
330 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
331 path = Glib::build_filename (dir_path, "etc/fonts");
332 setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
335 /* write a pango.rc file and tell pango to use it. we'd love
336 to put this into the Ardour.app bundle and leave it there,
337 but the user may not have write permission. so ...
339 we also have to make sure that the user ardour directory
343 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
344 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
351 path = Glib::build_filename (userconfigdir, "pango.rc");
353 std::ofstream pangorc (path.c_str());
355 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
357 mpath = Glib::build_filename (userconfigdir, "pango.modules");
359 pangorc << "[Pango]\nModuleFiles=";
360 pangorc << mpath << endl;
364 setenv ("PANGO_RC_FILE", path.c_str(), 1);
366 /* similar for GDK pixbuf loaders, but there's no RC file required
367 to specify where it lives.
370 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
371 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
377 tell_about_jack_death (void* /* ignored */)
379 if (AudioEngine::instance()->processed_frames() == 0) {
380 /* died during startup */
381 MessageDialog msg (_("JACK exited"), false);
382 msg.set_position (Gtk::WIN_POS_CENTER);
383 msg.set_secondary_text (string_compose (_(
384 "JACK exited unexpectedly, and without notifying %1.\n\
386 This could be due to misconfiguration or to an error inside JACK.\n\
388 Click OK to exit %1."), PROGRAM_NAME));
395 /* engine has already run, so this is a mid-session JACK death */
397 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
398 msg->set_secondary_text (string_compose (_(
399 "JACK exited unexpectedly, and without notifying %1.\n\
401 This is probably due to an error inside JACK. You should restart JACK\n\
402 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
403 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
406 return false; /* do not call again */
410 sigpipe_handler (int /*signal*/)
412 /* XXX fix this so that we do this again after a reconnect to JACK
415 static bool done_the_jack_thing = false;
417 if (!done_the_jack_thing) {
418 AudioEngine::instance()->died ();
419 g_idle_add (tell_about_jack_death, 0);
420 done_the_jack_thing = true;
425 void close_external_ui_windows();
428 #ifdef WINDOWS_VST_SUPPORT
430 extern int windows_vst_gui_init (int* argc, char** argv[]);
432 /* this is called from the entry point of a wine-compiled
433 executable that is linked against gtk2_ardour built
437 int ardour_main (int argc, char *argv[])
439 int main (int argc, char *argv[])
442 fixup_bundle_environment (argc, argv);
444 if (!Glib::thread_supported()) {
450 #ifdef WINDOWS_VST_SUPPORT
451 /* this does some magic that is needed to make GTK and Wine's own
452 X11 client interact properly.
454 windows_vst_gui_init (&argc, &argv);
457 (void) bindtextdomain (PACKAGE, localedir);
458 /* our i18n translations are all in UTF-8, so make sure
459 that even if the user locale doesn't specify UTF-8,
460 we use that when handling them.
462 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
463 (void) textdomain (PACKAGE);
465 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
467 // catch error message system signals ();
469 text_receiver.listen_to (error);
470 text_receiver.listen_to (info);
471 text_receiver.listen_to (fatal);
472 text_receiver.listen_to (warning);
474 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
475 if (getenv ("BOOST_DEBUG")) {
476 boost_debug_shared_ptr_show_live_debugging (true);
480 if (parse_opts (argc, argv)) {
484 if (curvetest_file) {
485 return curvetest (curvetest_file);
490 << _(" (built using ")
493 << _(" and GCC version ") << __VERSION__
503 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
504 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
506 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
507 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
508 << _("This is free software, and you are welcome to redistribute it ") << endl
509 << _("under certain conditions; see the source for copying conditions.")
513 /* some GUI objects need this */
517 if (::signal (SIGPIPE, sigpipe_handler)) {
518 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
522 ui = new ARDOUR_UI (&argc, &argv);
523 } catch (failed_constructor& err) {
524 error << _("could not create ARDOUR GUI") << endmsg;
528 ui->run (text_receiver);
529 Gtkmm2ext::Application::instance()->cleanup();
533 pthread_cancel_all ();
536 close_external_ui_windows();
540 #ifdef WINDOWS_VST_SUPPORT
541 } // end of extern C block