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"
34 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
35 #include "pbd/boost_debug.h"
38 #include <jack/jack.h>
40 #include "ardour/svn_revision.h"
41 #include "ardour/version.h"
42 #include "ardour/ardour.h"
43 #include "ardour/audioengine.h"
44 #include "ardour/session_utils.h"
45 #include "ardour/filesystem_paths.h"
47 #include <gtkmm/main.h>
48 #include <gtkmm2ext/application.h>
49 #include <gtkmm2ext/popup.h>
50 #include <gtkmm2ext/utils.h>
54 #include "ardour_ui.h"
62 using namespace ARDOUR_COMMAND_LINE
;
63 using namespace ARDOUR
;
66 TextReceiver
text_receiver ("ardour");
68 extern int curvetest (string
);
70 static ARDOUR_UI
*ui
= 0;
71 static const char* localedir
= LOCALEDIR
;
76 MessageDialog
win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME
),
79 (Gtk::ButtonsType
)(Gtk::BUTTONS_NONE
));
80 win
.set_secondary_text(_("There are several possible reasons:\n\
82 1) JACK is not running.\n\
83 2) JACK is running as another user, perhaps root.\n\
84 3) There is already another client called \"ardour\".\n\
86 Please consider the possibilities, and perhaps (re)start JACK."));
88 win
.add_button (Stock::QUIT
, RESPONSE_CLOSE
);
89 win
.set_default_response (RESPONSE_CLOSE
);
92 win
.set_position (Gtk::WIN_POS_CENTER
);
98 /* we just don't care about the result, but we want to block */
103 static void export_search_path (const string
& base_dir
, const char* varname
, const char* dir
)
106 const char * cstr
= getenv (varname
);
117 setenv (varname
, path
.c_str(), 1);
122 #include <mach-o/dyld.h>
123 #include <sys/param.h>
125 extern void set_language_preference (); // cocoacarbon.mm
128 fixup_bundle_environment (int, char* [])
130 if (!getenv ("ARDOUR_BUNDLED")) {
134 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
136 set_language_preference ();
138 char execpath
[MAXPATHLEN
+1];
139 uint32_t pathsz
= sizeof (execpath
);
141 _NSGetExecutablePath (execpath
, &pathsz
);
143 std::string
exec_path (execpath
);
144 std::string dir_path
= Glib::path_get_dirname (exec_path
);
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
+= "/../Resources/Surfaces";
174 path
+= "/../Resources/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", "/lib/panners");
199 export_search_path (dir_path
, "ARDOUR_SURFACES_PATH", "/lib/surfaces");
200 export_search_path (dir_path
, "ARDOUR_MIDIMAPS_PATH", "/share/midi_maps");
201 export_search_path (dir_path
, "ARDOUR_EXPORT_FORMATS_PATH", "/share/exports");
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 if (!getenv ("ARDOUR_BUNDLED")) {
297 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
299 Glib::ustring exec_path
= argv
[0];
300 Glib::ustring dir_path
= Glib::path_get_dirname (Glib::path_get_dirname (exec_path
));
302 Glib::ustring userconfigdir
= user_config_directory().to_string();
304 /* ensure that we find any bundled executables (e.g. JACK),
305 and find them before any instances of the same name
309 /* note that this function is POSIX/Linux specific, so using / as
310 a dir separator in this context is just fine.
316 path
+= "/lib/surfaces:";
318 path
+= "/lib/panners:";
320 setenv ("ARDOUR_MODULE_PATH", path
.c_str(), 1);
322 path
= userconfigdir
;
325 path
+= "/etc/icons:";
327 path
+= "/etc/pixmaps:";
333 setenv ("ARDOUR_PATH", path
.c_str(), 1);
334 setenv ("ARDOUR_CONFIG_PATH", path
.c_str(), 1);
338 setenv ("ARDOUR_INSTANT_XML_PATH", path
.c_str(), 1);
340 export_search_path (dir_path
, "LADSPA_PATH", "/../plugins");
341 export_search_path (dir_path
, "VAMP_PATH", "/lib");
342 export_search_path (dir_path
, "ARDOUR_PANNER_PATH", "/lib/panners");
343 export_search_path (dir_path
, "ARDOUR_SURFACES_PATH", "/lib/surfaces");
344 export_search_path (dir_path
, "ARDOUR_MIDIMAPS_PATH", "/share/midi_maps");
345 export_search_path (dir_path
, "ARDOUR_EXPORT_FORMATS_PATH", "/share/export");
348 path
+= "/lib/clearlooks";
349 setenv ("GTK_PATH", path
.c_str(), 1);
351 /* unset GTK_RC_FILES so that we only load the RC files that we define
354 unsetenv ("GTK_RC_FILES");
356 if (!ARDOUR::translations_are_disabled ()) {
358 path
+= "/share/locale";
360 localedir
= strdup (path
.c_str());
361 setenv ("GTK_LOCALEDIR", localedir
, 1);
364 /* write a pango.rc file and tell pango to use it. we'd love
365 to put this into the Ardour.app bundle and leave it there,
366 but the user may not have write permission. so ...
368 we also have to make sure that the user ardour directory
372 if (g_mkdir_with_parents (userconfigdir
.c_str(), 0755) < 0) {
373 error
<< string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir
, strerror (errno
))
379 path
= Glib::build_filename (userconfigdir
, "pango.rc");
381 std::ofstream
pangorc (path
.c_str());
383 error
<< string_compose (_("cannot open pango.rc file %1") , path
) << endmsg
;
385 mpath
= Glib::build_filename (userconfigdir
, "pango.modules");
387 pangorc
<< "[Pango]\nModuleFiles=";
388 pangorc
<< mpath
<< endl
;
392 setenv ("PANGO_RC_FILE", path
.c_str(), 1);
394 /* similar for GDK pixbuf loaders, but there's no RC file required
395 to specify where it lives.
398 mpath
= Glib::build_filename (userconfigdir
, "gdk-pixbuf.loaders");
399 setenv ("GDK_PIXBUF_MODULE_FILE", mpath
.c_str(), 1);
406 tell_about_jack_death (void* /* ignored */)
408 if (AudioEngine::instance()->processed_frames() == 0) {
409 /* died during startup */
410 MessageDialog
msg (_("JACK exited"), false, Gtk::MESSAGE_INFO
, Gtk::BUTTONS_OK
);
411 msg
.set_position (Gtk::WIN_POS_CENTER
);
412 msg
.set_secondary_text (string_compose (_(
413 "JACK exited unexpectedly, and without notifying %1.\n\
415 This could be due to misconfiguration or to an error inside JACK.\n\
417 Click OK to exit %1."), PROGRAM_NAME
));
424 /* engine has already run, so this is a mid-session JACK death */
426 MessageDialog
* msg
= manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO
, Gtk::BUTTONS_NONE
));
427 msg
->set_secondary_text (string_compose (_(
428 "JACK exited unexpectedly, and without notifying %1.\n\
430 This is probably due to an error inside JACK. You should restart JACK\n\
431 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
432 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME
));
435 return false; /* do not call again */
439 sigpipe_handler (int /*signal*/)
441 /* XXX fix this so that we do this again after a reconnect to JACK
444 static bool done_the_jack_thing
= false;
446 if (!done_the_jack_thing
) {
447 AudioEngine::instance()->died ();
448 g_idle_add (tell_about_jack_death
, 0);
449 done_the_jack_thing
= true;
454 void close_external_ui_windows();
459 extern int gui_init (int* argc
, char** argv
[]);
461 /* this is called from the entry point of a wine-compiled
462 executable that is linked against gtk2_ardour built
466 int ardour_main (int argc
, char *argv
[])
468 int main (int argc
, char *argv
[])
471 fixup_bundle_environment (argc
, argv
);
473 if (!Glib::thread_supported()) {
480 /* this does some magic that is needed to make GTK and Wine's own
481 X11 client interact properly.
483 gui_init (&argc
, &argv
);
486 (void) bindtextdomain (PACKAGE
, localedir
);
487 /* our i18n translations are all in UTF-8, so make sure
488 that even if the user locale doesn't specify UTF-8,
489 we use that when handling them.
491 (void) bind_textdomain_codeset (PACKAGE
,"UTF-8");
492 (void) textdomain (PACKAGE
);
494 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS
, 0);
496 // catch error message system signals ();
498 text_receiver
.listen_to (error
);
499 text_receiver
.listen_to (info
);
500 text_receiver
.listen_to (fatal
);
501 text_receiver
.listen_to (warning
);
503 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
504 if (getenv ("BOOST_DEBUG")) {
505 boost_debug_shared_ptr_show_live_debugging (true);
509 if (parse_opts (argc
, argv
)) {
513 if (curvetest_file
) {
514 return curvetest (curvetest_file
);
519 << _(" (built using ")
522 << _(" and GCC version ") << __VERSION__
532 cerr
<< _("Copyright (C) 1999-2011 Paul Davis") << endl
533 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
535 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME
) << endl
536 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
537 << _("This is free software, and you are welcome to redistribute it ") << endl
538 << _("under certain conditions; see the source for copying conditions.")
542 /* some GUI objects need this */
546 if (::signal (SIGPIPE
, sigpipe_handler
)) {
547 cerr
<< _("Cannot xinstall SIGPIPE error handler") << endl
;
551 ui
= new ARDOUR_UI (&argc
, &argv
);
552 } catch (failed_constructor
& err
) {
553 error
<< _("could not create ARDOUR GUI") << endmsg
;
557 ui
->run (text_receiver
);
558 Gtkmm2ext::Application::instance()->cleanup();
562 pthread_cancel_all ();
565 close_external_ui_windows();
570 } // end of extern C block