2 Copyright (C) 2001-2012 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);
145 std::string exec_dir = Glib::path_get_dirname (execpath);
146 std::string bundle_dir;
147 std::string userconfigdir = user_config_directory();
149 bundle_dir = Glib::path_get_dirname (exec_dir);
151 export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib");
153 /* inside an OS X .app bundle, there is no difference
154 between DATA and CONFIG locations, since OS X doesn't
155 attempt to do anything to expose the notion of
156 machine-independent shared data.
159 export_search_path (bundle_dir, "ARDOUR_DATA_PATH", "/Resources");
160 export_search_path (bundle_dir, "ARDOUR_CONFIG_PATH", "/Resources");
161 export_search_path (bundle_dir, "ARDOUR_INSTANT_XML_PATH", "/Resources");
162 export_search_path (bundle_dir, "LADSPA_PATH", "/Plugins");
163 export_search_path (bundle_dir, "VAMP_PATH", "/lib");
164 export_search_path (bundle_dir, "SUIL_MODULE_DIR", "/lib");
165 export_search_path (bundle_dir, "GTK_PATH", "/lib/clearlooks");
167 /* unset GTK_RC_FILES so that we only load the RC files that we define
170 unsetenv ("GTK_RC_FILES");
172 if (!ARDOUR::translations_are_disabled ()) {
173 export_search_path (bundle_dir, "GTK_LOCALEDIR", "/Resources/locale");
176 /* write a pango.rc file and tell pango to use it. we'd love
177 to put this into the PROGRAM_NAME.app bundle and leave it there,
178 but the user may not have write permission. so ...
180 we also have to make sure that the user ardour directory
184 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
185 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
189 path = Glib::build_filename (userconfigdir, "pango.rc");
190 std::ofstream pangorc (path.c_str());
192 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
194 pangorc << "[Pango]\nModuleFiles="
195 << Glib::build_filename (bundle_dir, "Resources/pango.modules")
199 setenv ("PANGO_RC_FILE", path.c_str(), 1);
203 setenv ("CHARSETALIASDIR", bundle_dir.c_str(), 1);
204 setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1);
205 setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (bundle_dir, "Resources/gdk-pixbuf.loaders").c_str(), 1);
211 fixup_bundle_environment (int /*argc*/, char* argv[])
213 /* THIS IS FOR LINUX - its just about the only place where its
214 * acceptable to build paths directly using '/'.
217 if (!getenv ("ARDOUR_BUNDLED")) {
221 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
224 std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
225 std::string userconfigdir = user_config_directory();
227 /* note that this function is POSIX/Linux specific, so using / as
228 a dir separator in this context is just fine.
231 export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
232 export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
233 export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
234 export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
235 export_search_path (dir_path, "LADSPA_PATH", "/plugins");
236 export_search_path (dir_path, "VAMP_PATH", "/lib");
237 export_search_path (dir_path, "SUIL_MODULE_DIR", "/lib");
239 export_search_path (dir_path, "GTK_PATH", "/lib/clearlooks");
241 /* unset GTK_RC_FILES so that we only load the RC files that we define
244 unsetenv ("GTK_RC_FILES");
246 if (!ARDOUR::translations_are_disabled ()) {
247 export_search_path (dir_path, "GTK_LOCALEDIR", "/share/locale");
250 /* Tell fontconfig where to find fonts.conf. Use the system version
251 if it exists, otherwise use the stuff we included in the bundle
254 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
255 setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
256 setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
258 /* use the one included in the bundle */
260 path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
261 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
262 export_search_path (dir_path, "FONTCONFIG_PATH", "/etc/fonts");
265 /* write a pango.rc file and tell pango to use it. we'd love
266 to put this into the Ardour.app bundle and leave it there,
267 but the user may not have write permission. so ...
269 we also have to make sure that the user ardour directory
273 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
274 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
278 path = Glib::build_filename (userconfigdir, "pango.rc");
279 std::ofstream pangorc (path.c_str());
281 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
283 pangorc << "[Pango]\nModuleFiles="
284 << Glib::build_filename (userconfigdir, "pango.modules")
289 setenv ("PANGO_RC_FILE", path.c_str(), 1);
291 /* similar for GDK pixbuf loaders, but there's no RC file required
292 to specify where it lives.
295 setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders").c_str(), 1);
298 /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack
299 from looking outside the bundle to find the charset.alias file.
301 setenv ("CHARSETALIASDIR", dir_path.c_str(), 1);
308 tell_about_jack_death (void* /* ignored */)
310 if (AudioEngine::instance()->processed_frames() == 0) {
311 /* died during startup */
312 MessageDialog msg (_("JACK exited"), false);
313 msg.set_position (Gtk::WIN_POS_CENTER);
314 msg.set_secondary_text (string_compose (_(
315 "JACK exited unexpectedly, and without notifying %1.\n\
317 This could be due to misconfiguration or to an error inside JACK.\n\
319 Click OK to exit %1."), PROGRAM_NAME));
326 /* engine has already run, so this is a mid-session JACK death */
328 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
329 msg->set_secondary_text (string_compose (_(
330 "JACK exited unexpectedly, and without notifying %1.\n\
332 This is probably due to an error inside JACK. You should restart JACK\n\
333 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
334 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
337 return false; /* do not call again */
341 sigpipe_handler (int /*signal*/)
343 /* XXX fix this so that we do this again after a reconnect to JACK
346 static bool done_the_jack_thing = false;
348 if (!done_the_jack_thing) {
349 AudioEngine::instance()->died ();
350 g_idle_add (tell_about_jack_death, 0);
351 done_the_jack_thing = true;
355 #ifdef WINDOWS_VST_SUPPORT
357 extern int windows_vst_gui_init (int* argc, char** argv[]);
359 /* this is called from the entry point of a wine-compiled
360 executable that is linked against gtk2_ardour built
364 int ardour_main (int argc, char *argv[])
366 int main (int argc, char *argv[])
369 fixup_bundle_environment (argc, argv);
371 if (!Glib::thread_supported()) {
377 #ifdef WINDOWS_VST_SUPPORT
378 /* this does some magic that is needed to make GTK and Wine's own
379 X11 client interact properly.
381 windows_vst_gui_init (&argc, &argv);
384 (void) bindtextdomain (PACKAGE, localedir);
385 /* our i18n translations are all in UTF-8, so make sure
386 that even if the user locale doesn't specify UTF-8,
387 we use that when handling them.
389 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
390 (void) textdomain (PACKAGE);
392 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
394 // catch error message system signals ();
396 text_receiver.listen_to (error);
397 text_receiver.listen_to (info);
398 text_receiver.listen_to (fatal);
399 text_receiver.listen_to (warning);
401 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
402 if (getenv ("BOOST_DEBUG")) {
403 boost_debug_shared_ptr_show_live_debugging (true);
407 if (parse_opts (argc, argv)) {
411 if (curvetest_file) {
412 return curvetest (curvetest_file);
417 << _(" (built using ")
420 << _(" and GCC version ") << __VERSION__
430 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
431 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus") << endl
433 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
434 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
435 << _("This is free software, and you are welcome to redistribute it ") << endl
436 << _("under certain conditions; see the source for copying conditions.")
440 /* some GUI objects need this */
444 if (::signal (SIGPIPE, sigpipe_handler)) {
445 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
449 ui = new ARDOUR_UI (&argc, &argv);
450 } catch (failed_constructor& err) {
451 error << _("could not create ARDOUR GUI") << endmsg;
455 ui->run (text_receiver);
456 Gtkmm2ext::Application::instance()->cleanup();
460 pthread_cancel_all ();
464 #ifdef WINDOWS_VST_SUPPORT
465 } // end of extern C block