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/pathexpand.h"
35 #include "pbd/pthread_utils.h"
36 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
37 #include "pbd/boost_debug.h"
40 #include <jack/jack.h>
42 #include "ardour/revision.h"
43 #include "ardour/version.h"
44 #include "ardour/ardour.h"
45 #include "ardour/audioengine.h"
46 #include "ardour/session_utils.h"
47 #include "ardour/filesystem_paths.h"
49 #include <gtkmm/main.h>
50 #include <gtkmm2ext/application.h>
51 #include <gtkmm2ext/popup.h>
52 #include <gtkmm2ext/utils.h>
54 #include <fontconfig/fontconfig.h>
58 #include "ardour_ui.h"
65 #include <Carbon/Carbon.h>
70 using namespace ARDOUR_COMMAND_LINE;
71 using namespace ARDOUR;
74 TextReceiver text_receiver ("ardour");
76 extern int curvetest (string);
78 static ARDOUR_UI *ui = 0;
79 static const char* localedir = LOCALEDIR;
84 MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
88 win.set_secondary_text(string_compose (_("There are several possible reasons:\n\
90 1) JACK is not running.\n\
91 2) JACK is running as another user, perhaps root.\n\
92 3) There is already another client called \"%1\".\n\
94 Please consider the possibilities, and perhaps (re)start JACK."), PROGRAM_NAME));
96 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
97 win.set_default_response (RESPONSE_CLOSE);
100 win.set_position (Gtk::WIN_POS_CENTER);
106 /* we just don't care about the result, but we want to block */
111 static void export_search_path (const string& base_dir, const char* varname, const char* dir)
114 const char * cstr = g_getenv (varname);
125 g_setenv (varname, path.c_str(), 1);
130 #include <mach-o/dyld.h>
131 #include <sys/param.h>
133 extern void set_language_preference (); // cocoacarbon.mm
136 fixup_bundle_environment (int, char* [])
138 if (!g_getenv ("ARDOUR_BUNDLED")) {
142 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
144 set_language_preference ();
146 char execpath[MAXPATHLEN+1];
147 uint32_t pathsz = sizeof (execpath);
149 _NSGetExecutablePath (execpath, &pathsz);
152 std::string exec_dir = Glib::path_get_dirname (execpath);
153 std::string bundle_dir;
154 std::string userconfigdir = user_config_directory();
156 bundle_dir = Glib::path_get_dirname (exec_dir);
159 if (!ARDOUR::translations_are_enabled ()) {
160 localedir = "/this/cannot/exist";
162 /* force localedir into the bundle */
164 vector<string> lpath;
165 lpath.push_back (bundle_dir);
166 lpath.push_back ("share");
167 lpath.push_back ("locale");
168 localedir = strdup (Glib::build_filename (lpath).c_str());
172 export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib");
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 (bundle_dir, "ARDOUR_DATA_PATH", "/Resources");
181 export_search_path (bundle_dir, "ARDOUR_CONFIG_PATH", "/Resources");
182 export_search_path (bundle_dir, "ARDOUR_INSTANT_XML_PATH", "/Resources");
183 export_search_path (bundle_dir, "LADSPA_PATH", "/Plugins");
184 export_search_path (bundle_dir, "VAMP_PATH", "/lib");
185 export_search_path (bundle_dir, "SUIL_MODULE_DIR", "/lib");
186 export_search_path (bundle_dir, "GTK_PATH", "/lib/gtkengines");
188 g_setenv ("PATH", (bundle_dir + "/MacOS:" + std::string(getenv ("PATH"))).c_str(), 1);
190 /* unset GTK_RC_FILES so that we only load the RC files that we define
193 g_unsetenv ("GTK_RC_FILES");
195 /* write a pango.rc file and tell pango to use it. we'd love
196 to put this into the PROGRAM_NAME.app bundle and leave it there,
197 but the user may not have write permission. so ...
199 we also have to make sure that the user ardour directory
203 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
204 error << string_compose (_("cannot create user %3 folder %1 (%2)"), userconfigdir, strerror (errno), PROGRAM_NAME)
208 path = Glib::build_filename (userconfigdir, "pango.rc");
209 std::ofstream pangorc (path.c_str());
211 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
213 pangorc << "[Pango]\nModuleFiles="
214 << Glib::build_filename (bundle_dir, "Resources/pango.modules")
218 g_setenv ("PANGO_RC_FILE", path.c_str(), 1);
222 g_setenv ("CHARSETALIASDIR", bundle_dir.c_str(), 1);
223 g_setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1);
224 g_setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (bundle_dir, "Resources/gdk-pixbuf.loaders").c_str(), 1);
227 static void load_custom_fonts() {
228 /* this code will only compile on OS X 10.6 and above, and we currently do not
229 * need it for earlier versions since we fall back on a non-monospace,
232 #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060
233 std::string ardour_mono_file;
235 if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) {
236 cerr << _("Cannot find ArdourMono TrueType font") << endl;
242 ttf = CFStringCreateWithBytes(
243 kCFAllocatorDefault, (UInt8*) ardour_mono_file.c_str(),
244 ardour_mono_file.length(),
245 kCFStringEncodingUTF8, FALSE);
246 fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, ttf, kCFURLPOSIXPathStyle, TRUE);
247 if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error) != true) {
248 cerr << _("Cannot load ArdourMono TrueType font.") << endl;
256 fixup_bundle_environment (int /*argc*/, char* argv[])
258 /* THIS IS FOR LINUX - its just about the only place where its
259 * acceptable to build paths directly using '/'.
262 if (!g_getenv ("ARDOUR_BUNDLED")) {
266 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
269 std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
270 std::string userconfigdir = user_config_directory();
273 if (!ARDOUR::translations_are_enabled ()) {
274 localedir = "/this/cannot/exist";
276 /* force localedir into the bundle */
277 vector<string> lpath;
278 lpath.push_back (dir_path);
279 lpath.push_back ("share");
280 lpath.push_back ("locale");
281 localedir = canonical_path (Glib::build_filename (lpath)).c_str();
285 /* note that this function is POSIX/Linux specific, so using / as
286 a dir separator in this context is just fine.
289 export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
290 export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
291 export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
292 export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
293 export_search_path (dir_path, "LADSPA_PATH", "/plugins");
294 export_search_path (dir_path, "VAMP_PATH", "/lib");
295 export_search_path (dir_path, "SUIL_MODULE_DIR", "/lib");
296 export_search_path (dir_path, "GTK_PATH", "/lib/gtkengines");
298 g_setenv ("PATH", (dir_path + "/bin:" + std::string(getenv ("PATH"))).c_str(), 1);
300 /* unset GTK_RC_FILES so that we only load the RC files that we define
303 g_unsetenv ("GTK_RC_FILES");
305 /* Tell fontconfig where to find fonts.conf. Use the system version
306 if it exists, otherwise use the stuff we included in the bundle
309 if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
310 g_setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
311 g_setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
313 error << _("No fontconfig file found on your system. Things may looked very odd or ugly") << endmsg;
316 /* write a pango.rc file and tell pango to use it. we'd love
317 to put this into the Ardour.app bundle and leave it there,
318 but the user may not have write permission. so ...
320 we also have to make sure that the user ardour directory
324 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
325 error << string_compose (_("cannot create user %3 folder %1 (%2)"), userconfigdir, strerror (errno), PROGRAM_NAME)
329 path = Glib::build_filename (userconfigdir, "pango.rc");
330 std::ofstream pangorc (path.c_str());
332 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
334 pangorc << "[Pango]\nModuleFiles="
335 << Glib::build_filename (userconfigdir, "pango.modules")
340 g_setenv ("PANGO_RC_FILE", path.c_str(), 1);
342 /* similar for GDK pixbuf loaders, but there's no RC file required
343 to specify where it lives.
346 g_setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders").c_str(), 1);
349 /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack
350 from looking outside the bundle to find the charset.alias file.
352 g_setenv ("CHARSETALIASDIR", dir_path.c_str(), 1);
356 static void load_custom_fonts() {
357 std::string ardour_mono_file;
358 if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) {
359 cerr << _("Cannot find ArdourMono TrueType font") << endl;
362 FcConfig *config = FcInitLoadConfigAndFonts();
363 FcBool ret = FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(ardour_mono_file.c_str()));
364 if (ret == FcFalse) {
365 cerr << _("Cannot load ArdourMono TrueType font.") << endl;
367 ret = FcConfigSetCurrent(config);
368 if (ret == FcFalse) {
369 cerr << _("Failed to set fontconfig configuration.") << endl;
376 tell_about_backend_death (void* /* ignored */)
378 if (AudioEngine::instance()->processed_frames() == 0) {
379 /* died during startup */
380 MessageDialog msg (string_compose (_("The audio backend (%1) has failed, or terminated"), AudioEngine::instance()->current_backend_name()), false);
381 msg.set_position (Gtk::WIN_POS_CENTER);
382 msg.set_secondary_text (string_compose (_(
383 "%2 exited unexpectedly, and without notifying %1.\n\
385 This could be due to misconfiguration or to an error inside %2.\n\
387 Click OK to exit %1."), PROGRAM_NAME, AudioEngine::instance()->current_backend_name()));
394 /* engine has already run, so this is a mid-session backend death */
396 MessageDialog msg (string_compose (_("The audio backend (%1) has failed, or terminated"), AudioEngine::instance()->current_backend_name()), false);
397 msg.set_secondary_text (string_compose (_("%2 exited unexpectedly, and without notifying %1."),
398 PROGRAM_NAME, AudioEngine::instance()->current_backend_name()));
401 return false; /* do not call again */
405 sigpipe_handler (int /*signal*/)
407 /* XXX fix this so that we do this again after a reconnect to the backend
410 static bool done_the_backend_thing = false;
412 if (!done_the_backend_thing) {
413 AudioEngine::instance()->died ();
414 g_idle_add (tell_about_backend_death, 0);
415 done_the_backend_thing = true;
419 #ifdef WINDOWS_VST_SUPPORT
421 extern int windows_vst_gui_init (int* argc, char** argv[]);
423 /* this is called from the entry point of a wine-compiled
424 executable that is linked against gtk2_ardour built
428 int ardour_main (int argc, char *argv[])
430 int main (int argc, char *argv[])
433 fixup_bundle_environment (argc, argv);
435 load_custom_fonts(); /* needs to happend before any gtk and pango init calls */
437 if (!Glib::thread_supported()) {
445 #ifdef WINDOWS_VST_SUPPORT
446 /* this does some magic that is needed to make GTK and Wine's own
447 X11 client interact properly.
449 windows_vst_gui_init (&argc, &argv);
453 cerr << "bnd txt domain [" << PACKAGE << "] to " << localedir << endl;
455 (void) bindtextdomain (PACKAGE, localedir);
456 /* our i18n translations are all in UTF-8, so make sure
457 that even if the user locale doesn't specify UTF-8,
458 we use that when handling them.
460 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
463 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
465 // catch error message system signals ();
467 text_receiver.listen_to (error);
468 text_receiver.listen_to (info);
469 text_receiver.listen_to (fatal);
470 text_receiver.listen_to (warning);
472 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
473 if (g_getenv ("BOOST_DEBUG")) {
474 boost_debug_shared_ptr_show_live_debugging (true);
478 if (parse_opts (argc, argv)) {
484 << _(" (built using ")
487 << _(" and GCC version ") << __VERSION__
497 cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
498 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus") << endl
500 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
501 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
502 << _("This is free software, and you are welcome to redistribute it ") << endl
503 << _("under certain conditions; see the source for copying conditions.")
507 /* some GUI objects need this */
509 if (!ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization, localedir)) {
510 error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg;
514 if (curvetest_file) {
515 return curvetest (curvetest_file);
519 if (::signal (SIGPIPE, sigpipe_handler)) {
520 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
525 ui = new ARDOUR_UI (&argc, &argv, localedir);
526 } catch (failed_constructor& err) {
527 error << string_compose (_("could not create %1 GUI"), PROGRAM_NAME) << endmsg;
531 ui->run (text_receiver);
532 Gtkmm2ext::Application::instance()->cleanup();
536 pthread_cancel_all ();
540 #ifdef WINDOWS_VST_SUPPORT
541 } // end of extern C block