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 /* force localedir into the bundle */
153 vector<string> lpath;
154 lpath.push_back (bundle_dir);
155 lpath.push_back ("share");
156 lpath.push_back ("locale");
157 localedir = strdup (Glib::build_filename (lpath).c_str());
159 export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib");
161 /* inside an OS X .app bundle, there is no difference
162 between DATA and CONFIG locations, since OS X doesn't
163 attempt to do anything to expose the notion of
164 machine-independent shared data.
167 export_search_path (bundle_dir, "ARDOUR_DATA_PATH", "/Resources");
168 export_search_path (bundle_dir, "ARDOUR_CONFIG_PATH", "/Resources");
169 export_search_path (bundle_dir, "ARDOUR_INSTANT_XML_PATH", "/Resources");
170 export_search_path (bundle_dir, "LADSPA_PATH", "/Plugins");
171 export_search_path (bundle_dir, "VAMP_PATH", "/lib");
172 export_search_path (bundle_dir, "SUIL_MODULE_DIR", "/lib");
173 export_search_path (bundle_dir, "GTK_PATH", "/lib/clearlooks");
175 /* unset GTK_RC_FILES so that we only load the RC files that we define
178 unsetenv ("GTK_RC_FILES");
180 if (!ARDOUR::translations_are_disabled ()) {
181 export_search_path (bundle_dir, "GTK_LOCALEDIR", "/Resources/locale");
184 /* write a pango.rc file and tell pango to use it. we'd love
185 to put this into the PROGRAM_NAME.app bundle and leave it there,
186 but the user may not have write permission. so ...
188 we also have to make sure that the user ardour directory
192 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
193 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
197 path = Glib::build_filename (userconfigdir, "pango.rc");
198 std::ofstream pangorc (path.c_str());
200 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
202 pangorc << "[Pango]\nModuleFiles="
203 << Glib::build_filename (bundle_dir, "Resources/pango.modules")
207 setenv ("PANGO_RC_FILE", path.c_str(), 1);
211 setenv ("CHARSETALIASDIR", bundle_dir.c_str(), 1);
212 setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1);
213 setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (bundle_dir, "Resources/gdk-pixbuf.loaders").c_str(), 1);
219 fixup_bundle_environment (int /*argc*/, char* argv[])
221 /* THIS IS FOR LINUX - its just about the only place where its
222 * acceptable to build paths directly using '/'.
225 if (!getenv ("ARDOUR_BUNDLED")) {
229 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
232 std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
233 std::string userconfigdir = user_config_directory();
235 /* force localedir into the bundle */
237 vector<string> lpath;
238 lpath.push_back (dir_path);
239 lpath.push_back ("share");
240 lpath.push_back ("locale");
241 localedir = strdup (Glib::build_filename (lpath).c_str());
243 /* note that this function is POSIX/Linux specific, so using / as
244 a dir separator in this context is just fine.
247 export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
248 export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
249 export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
250 export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
251 export_search_path (dir_path, "LADSPA_PATH", "/plugins");
252 export_search_path (dir_path, "VAMP_PATH", "/lib");
253 export_search_path (dir_path, "SUIL_MODULE_DIR", "/lib");
255 export_search_path (dir_path, "GTK_PATH", "/lib/clearlooks");
257 /* unset GTK_RC_FILES so that we only load the RC files that we define
260 unsetenv ("GTK_RC_FILES");
262 if (!ARDOUR::translations_are_disabled ()) {
263 export_search_path (dir_path, "GTK_LOCALEDIR", "/share/locale");
266 /* Tell fontconfig where to find fonts.conf. Use the system version
267 if it exists, otherwise use the stuff we included in the bundle
270 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
271 setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
272 setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
274 /* use the one included in the bundle */
276 path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
277 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
278 export_search_path (dir_path, "FONTCONFIG_PATH", "/etc/fonts");
281 /* write a pango.rc file and tell pango to use it. we'd love
282 to put this into the Ardour.app bundle and leave it there,
283 but the user may not have write permission. so ...
285 we also have to make sure that the user ardour directory
289 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
290 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
294 path = Glib::build_filename (userconfigdir, "pango.rc");
295 std::ofstream pangorc (path.c_str());
297 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
299 pangorc << "[Pango]\nModuleFiles="
300 << Glib::build_filename (userconfigdir, "pango.modules")
305 setenv ("PANGO_RC_FILE", path.c_str(), 1);
307 /* similar for GDK pixbuf loaders, but there's no RC file required
308 to specify where it lives.
311 setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders").c_str(), 1);
314 /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack
315 from looking outside the bundle to find the charset.alias file.
317 setenv ("CHARSETALIASDIR", dir_path.c_str(), 1);
324 tell_about_jack_death (void* /* ignored */)
326 if (AudioEngine::instance()->processed_frames() == 0) {
327 /* died during startup */
328 MessageDialog msg (_("JACK exited"), false);
329 msg.set_position (Gtk::WIN_POS_CENTER);
330 msg.set_secondary_text (string_compose (_(
331 "JACK exited unexpectedly, and without notifying %1.\n\
333 This could be due to misconfiguration or to an error inside JACK.\n\
335 Click OK to exit %1."), PROGRAM_NAME));
342 /* engine has already run, so this is a mid-session JACK death */
344 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
345 msg->set_secondary_text (string_compose (_(
346 "JACK exited unexpectedly, and without notifying %1.\n\
348 This is probably due to an error inside JACK. You should restart JACK\n\
349 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
350 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
353 return false; /* do not call again */
357 sigpipe_handler (int /*signal*/)
359 /* XXX fix this so that we do this again after a reconnect to JACK
362 static bool done_the_jack_thing = false;
364 if (!done_the_jack_thing) {
365 AudioEngine::instance()->died ();
366 g_idle_add (tell_about_jack_death, 0);
367 done_the_jack_thing = true;
371 #ifdef WINDOWS_VST_SUPPORT
373 extern int windows_vst_gui_init (int* argc, char** argv[]);
375 /* this is called from the entry point of a wine-compiled
376 executable that is linked against gtk2_ardour built
380 int ardour_main (int argc, char *argv[])
382 int main (int argc, char *argv[])
385 fixup_bundle_environment (argc, argv);
387 if (!Glib::thread_supported()) {
393 #ifdef WINDOWS_VST_SUPPORT
394 /* this does some magic that is needed to make GTK and Wine's own
395 X11 client interact properly.
397 windows_vst_gui_init (&argc, &argv);
400 (void) bindtextdomain (PACKAGE, localedir);
401 /* our i18n translations are all in UTF-8, so make sure
402 that even if the user locale doesn't specify UTF-8,
403 we use that when handling them.
405 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
406 (void) textdomain (PACKAGE);
408 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
410 // catch error message system signals ();
412 text_receiver.listen_to (error);
413 text_receiver.listen_to (info);
414 text_receiver.listen_to (fatal);
415 text_receiver.listen_to (warning);
417 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
418 if (getenv ("BOOST_DEBUG")) {
419 boost_debug_shared_ptr_show_live_debugging (true);
423 if (parse_opts (argc, argv)) {
427 if (curvetest_file) {
428 return curvetest (curvetest_file);
433 << _(" (built using ")
436 << _(" and GCC version ") << __VERSION__
446 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
447 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus") << endl
449 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
450 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
451 << _("This is free software, and you are welcome to redistribute it ") << endl
452 << _("under certain conditions; see the source for copying conditions.")
456 /* some GUI objects need this */
460 if (::signal (SIGPIPE, sigpipe_handler)) {
461 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
465 ui = new ARDOUR_UI (&argc, &argv, localedir);
466 } catch (failed_constructor& err) {
467 error << _("could not create ARDOUR GUI") << endmsg;
471 ui->run (text_receiver);
472 Gtkmm2ext::Application::instance()->cleanup();
476 pthread_cancel_all ();
480 #ifdef WINDOWS_VST_SUPPORT
481 } // end of extern C block