packaging tweaks for OS X
[ardour.git] / gtk2_ardour / main.cc
index 6f03c5828ded91d486e1a4b5bc331d2e5d2c804f..284192ede24933fce2e26e3434d3e0b75c94e06f 100644 (file)
@@ -21,6 +21,7 @@
 #include <signal.h>
 #include <cerrno>
 #include <fstream>
 #include <signal.h>
 #include <cerrno>
 #include <fstream>
+#include <vector>
 
 #include <sigc++/bind.h>
 #include <gtkmm/settings.h>
 
 #include <sigc++/bind.h>
 #include <gtkmm/settings.h>
@@ -31,6 +32,9 @@
 #include "pbd/textreceiver.h"
 #include "pbd/failed_constructor.h"
 #include "pbd/pthread_utils.h"
 #include "pbd/textreceiver.h"
 #include "pbd/failed_constructor.h"
 #include "pbd/pthread_utils.h"
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+#include "pbd/boost_debug.h"
+#endif
 
 #include <jack/jack.h>
 
 
 #include <jack/jack.h>
 
@@ -71,9 +75,9 @@ void
 gui_jack_error ()
 {
        MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
 gui_jack_error ()
 {
        MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
-                    false,
-                    Gtk::MESSAGE_INFO,
-                    (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
+                          false,
+                          Gtk::MESSAGE_INFO,
+                          Gtk::BUTTONS_NONE);
 win.set_secondary_text(_("There are several possible reasons:\n\
 \n\
 1) JACK is not running.\n\
 win.set_secondary_text(_("There are several possible reasons:\n\
 \n\
 1) JACK is not running.\n\
@@ -97,6 +101,22 @@ Please consider the possibilities, and perhaps (re)start JACK."));
        win.run ();
 }
 
        win.run ();
 }
 
+static void export_search_path (const string& base_dir, const char* varname, const char* dir)
+{
+       string path;
+       const char * cstr = getenv (varname);
+
+       if (cstr) {
+               path = cstr;
+               path += ':';
+       } else {
+               path = "";
+       }
+       path += base_dir;
+       path += dir;
+
+       setenv (varname, path.c_str(), 1);
+}
 
 #ifdef __APPLE__
 
 
 #ifdef __APPLE__
 
@@ -106,13 +126,13 @@ Please consider the possibilities, and perhaps (re)start JACK."));
 extern void set_language_preference (); // cocoacarbon.mm
 
 void
 extern void set_language_preference (); // cocoacarbon.mm
 
 void
-fixup_bundle_environment ()
+fixup_bundle_environment (int, char* [])
 {
        if (!getenv ("ARDOUR_BUNDLED")) {
                return;
        }
 
 {
        if (!getenv ("ARDOUR_BUNDLED")) {
                return;
        }
 
-        EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
+       EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
 
        set_language_preference ();
 
 
        set_language_preference ();
 
@@ -121,8 +141,7 @@ fixup_bundle_environment ()
 
        _NSGetExecutablePath (execpath, &pathsz);
 
 
        _NSGetExecutablePath (execpath, &pathsz);
 
-       std::string exec_path (execpath);
-       std::string dir_path = Glib::path_get_dirname (exec_path);
+       std::string dir_path = Glib::path_get_dirname (execpath);
        std::string path;
        const char *cstr = getenv ("PATH");
 
        std::string path;
        const char *cstr = getenv ("PATH");
 
@@ -133,11 +152,11 @@ fixup_bundle_environment ()
 
        path = dir_path;
 
 
        path = dir_path;
 
-       /* JACK is often in /usr/local/bin and since Info.plist refuses to 
+       /* JACK is often in /usr/local/bin and since Info.plist refuses to
           set PATH, we have to force this in order to discover a running
           instance of JACK ...
        */
           set PATH, we have to force this in order to discover a running
           instance of JACK ...
        */
-       
+
        path += ':';
        path += "/usr/local/bin";
 
        path += ':';
        path += "/usr/local/bin";
 
@@ -147,91 +166,38 @@ fixup_bundle_environment ()
        }
        setenv ("PATH", path.c_str(), 1);
 
        }
        setenv ("PATH", path.c_str(), 1);
 
-       path = dir_path;
-       path += "/../Resources";
-       path += dir_path;
-       path += "/../Resources/Surfaces";
-       path += dir_path;
-       path += "/../Resources/Panners";
-
-       setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
+       export_search_path (dir_path, "ARDOUR_DLL_PATH", "/../lib");
 
 
-        path = user_config_directory().to_string();
-        path += ':';
-       path += dir_path;
-       path += "/../Resources/icons:";
-       path += dir_path;
-       path += "/../Resources/pixmaps:";
        path += dir_path;
        path += dir_path;
-       path += "/../Resources/share:";
-       path += dir_path;
-       path += "/../Resources";
-
-       setenv ("ARDOUR_PATH", path.c_str(), 1);
-       setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
-
-       path = dir_path;
        path += "/../Resources";
        path += "/../Resources";
-       setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
-
-       cstr = getenv ("LADSPA_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
-       }
-       path += dir_path;
-       path += "/../Plugins";
-
-       setenv ("LADSPA_PATH", path.c_str(), 1);
-
-       cstr = getenv ("VAMP_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
-       }
-       path += dir_path;
-       path += "/../Frameworks";
-
-       setenv ("VAMP_PATH", path.c_str(), 1);
-
-       cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
-       }
-       path += dir_path;
-       path += "/../Surfaces";
 
 
-       setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
+       /* inside an OS X .app bundle, there is no difference
+          between DATA and CONFIG locations, since OS X doesn't
+          attempt to do anything to expose the notion of
+          machine-independent shared data.
+       */
 
 
-       cstr = getenv ("LV2_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
-       }
-       path += dir_path;
-       path += "/../Plugins";
+       export_search_path (dir_path, "ARDOUR_DATA_PATH", "/../Resources");
+       export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/../Resources");
+       export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/../Resources");
 
 
-       setenv ("LV2_PATH", path.c_str(), 1);
+       export_search_path (dir_path, "LADSPA_PATH", "/../Plugins");
+       export_search_path (dir_path, "VAMP_PATH", "/../Frameworks");
 
        path = dir_path;
 
        path = dir_path;
-       path += "/../Frameworks/clearlooks";
-
+       path += "/../lib/clearlooks";
        setenv ("GTK_PATH", path.c_str(), 1);
 
        setenv ("GTK_PATH", path.c_str(), 1);
 
+       /* unset GTK_RC_FILES so that we only load the RC files that we define
+        */
+
+       unsetenv ("GTK_RC_FILES");
+
        if (!ARDOUR::translations_are_disabled ()) {
 
                path = dir_path;
                path += "/../Resources/locale";
        if (!ARDOUR::translations_are_disabled ()) {
 
                path = dir_path;
                path += "/../Resources/locale";
-               
+
                localedir = strdup (path.c_str());
                setenv ("GTK_LOCALEDIR", localedir, 1);
        }
                localedir = strdup (path.c_str());
                setenv ("GTK_LOCALEDIR", localedir, 1);
        }
@@ -305,120 +271,70 @@ fixup_bundle_environment ()
 #else
 
 void
 #else
 
 void
-fixup_bundle_environment (int argc, char* argv[])
+fixup_bundle_environment (int /*argc*/, char* argv[])
 {
 {
+       /* THIS IS FOR LINUX - its just about the only place where its
+        * acceptable to build paths directly using '/'.
+        */
+
        if (!getenv ("ARDOUR_BUNDLED")) {
                return;
        }
        if (!getenv ("ARDOUR_BUNDLED")) {
                return;
        }
-       
-        EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
 
 
-       Glib::ustring exec_path = argv[0];
-       Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
+       EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
+
+       Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0]));
        Glib::ustring path;
        Glib::ustring path;
-       const char *cstr = getenv ("PATH");
-        Glib::ustring userconfigdir = user_config_directory().to_string();
+       Glib::ustring userconfigdir = user_config_directory().to_string();
 
 
-       /* ensure that we find any bundled executables (e.g. JACK),
-          and find them before any instances of the same name
-          elsewhere in PATH
+       /* note that this function is POSIX/Linux specific, so using / as
+          a dir separator in this context is just fine.
        */
 
        */
 
-        /* note that this function is POSIX/Linux specific, so using / as 
-           a dir separator in this context is just fine.
-        */
-
-       path = dir_path;
-       path += "/etc:";
-       path += dir_path;
-       path += "/lib/surfaces:";
-       path += dir_path;
-       path += "/lib/panners:";
+       export_search_path (dir_path, "ARDOUR_DLL_PATH", "/lib");
+       export_search_path (dir_path, "ARDOUR_CONFIG_PATH", "/etc");
+       export_search_path (dir_path, "ARDOUR_INSTANT_XML_PATH", "/share");
+       export_search_path (dir_path, "ARDOUR_DATA_PATH", "/share");
 
 
-       setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
+       export_search_path (dir_path, "LADSPA_PATH", "/../plugins");
+       export_search_path (dir_path, "VAMP_PATH", "/lib");
 
 
-        path = userconfigdir;
-        path += ':';
-       path += dir_path;
-       path += "/etc/icons:";
-       path += dir_path;
-       path += "/etc/pixmaps:";
-       path += dir_path;
-       path += "/share:";
-       path += dir_path;
-       path += "/etc";
+       path = dir_path;
+       path += "/lib/clearlooks";
+       setenv ("GTK_PATH", path.c_str(), 1);
 
 
-       setenv ("ARDOUR_PATH", path.c_str(), 1);
-       setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
+       /* unset GTK_RC_FILES so that we only load the RC files that we define
+        */
 
 
-       path = dir_path;
-       path += "/etc";
-       setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
+       unsetenv ("GTK_RC_FILES");
 
 
-       cstr = getenv ("LADSPA_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
-       }
-       path += dir_path;
-       path += "/lib/plugins";
-       
-       setenv ("LADSPA_PATH", path.c_str(), 1);
+       if (!ARDOUR::translations_are_disabled ()) {
+               path = dir_path;
+               path += "/share/locale";
 
 
-       cstr = getenv ("VAMP_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
+               localedir = strdup (path.c_str());
+               setenv ("GTK_LOCALEDIR", localedir, 1);
        }
        }
-       path += dir_path;
-       path += "/lib";
-       
-       setenv ("VAMP_PATH", path.c_str(), 1);
 
 
-       cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
-       } else {
-               path = "";
-       }
-       path += dir_path;
-       path += "/lib/surfaces";
-       
-       setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
+       /* Tell fontconfig where to find fonts.conf. Use the system version
+          if it exists, otherwise use the stuff we included in the bundle
+       */
 
 
-       cstr = getenv ("LV2_PATH");
-       if (cstr) {
-               path = cstr;
-               path += ':';
+       if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) {
+               setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1);
+               setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
        } else {
        } else {
-               path = "";
+               /* use the one included in the bundle */
+               
+               path = Glib::build_filename (dir_path, "etc/fonts/fonts.conf");
+               setenv ("FONTCONFIG_FILE", path.c_str(), 1);
+               path = Glib::build_filename (dir_path, "etc/fonts");
+               setenv ("FONTCONFIG_PATH", "/etc/fonts", 1);
        }
        }
-       path += dir_path;
-       path += "/lib/plugins";
-       
-       setenv ("LV2_PATH", path.c_str(), 1);
-
-       path = dir_path;
-       path += "/lib/clearlooks";
-
-       setenv ("GTK_PATH", path.c_str(), 1);
-
-       if (!ARDOUR::translations_are_disabled ()) {
-                path = dir_path;
-                path += "/share/locale";
-                
-                localedir = strdup (path.c_str());
-                setenv ("GTK_LOCALEDIR", localedir, 1);
-        }
 
        /* write a pango.rc file and tell pango to use it. we'd love
           to put this into the Ardour.app bundle and leave it there,
 
        /* write a pango.rc file and tell pango to use it. we'd love
           to put this into the Ardour.app bundle and leave it there,
-          but the user may not have write permission. so ... 
+          but the user may not have write permission. so ...
 
           we also have to make sure that the user ardour directory
           actually exists ...
 
           we also have to make sure that the user ardour directory
           actually exists ...
@@ -427,32 +343,32 @@ fixup_bundle_environment (int argc, char* argv[])
        if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
                error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
                      << endmsg;
        if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
                error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
                      << endmsg;
-       } else {
-
-                Glib::ustring mpath;
-
-               path = Glib::build_filename (userconfigdir, "pango.rc");
-
-               std::ofstream pangorc (path.c_str());
-               if (!pangorc) {
-                       error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
-                } else {
-                        mpath = Glib::build_filename (userconfigdir, "pango.modules");
-                        
-                       pangorc << "[Pango]\nModuleFiles=";
-                       pangorc << mpath << endl;
-                       pangorc.close ();
-                }
-
-                setenv ("PANGO_RC_FILE", path.c_str(), 1);
-
-                /* similar for GDK pixbuf loaders, but there's no RC file required
-                   to specify where it lives.
-                */
+               return;
+       } 
 
 
-                mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
-                setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
+       Glib::ustring mpath;
+       
+       path = Glib::build_filename (userconfigdir, "pango.rc");
+       
+       std::ofstream pangorc (path.c_str());
+       if (!pangorc) {
+               error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
+       } else {
+               mpath = Glib::build_filename (userconfigdir, "pango.modules");
+               
+               pangorc << "[Pango]\nModuleFiles=";
+               pangorc << mpath << endl;
+               pangorc.close ();
        }
        }
+       
+       setenv ("PANGO_RC_FILE", path.c_str(), 1);
+
+       /* similar for GDK pixbuf loaders, but there's no RC file required
+          to specify where it lives.
+       */
+       
+       mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
+       setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
 }
 
 #endif
 }
 
 #endif
@@ -462,7 +378,7 @@ tell_about_jack_death (void* /* ignored */)
 {
        if (AudioEngine::instance()->processed_frames() == 0) {
                /* died during startup */
 {
        if (AudioEngine::instance()->processed_frames() == 0) {
                /* died during startup */
-               MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
+               MessageDialog msg (_("JACK exited"), false);
                msg.set_position (Gtk::WIN_POS_CENTER);
                msg.set_secondary_text (string_compose (_(
 "JACK exited unexpectedly, and without notifying %1.\n\
                msg.set_position (Gtk::WIN_POS_CENTER);
                msg.set_secondary_text (string_compose (_(
 "JACK exited unexpectedly, and without notifying %1.\n\
@@ -470,15 +386,15 @@ tell_about_jack_death (void* /* ignored */)
 This could be due to misconfiguration or to an error inside JACK.\n\
 \n\
 Click OK to exit %1."), PROGRAM_NAME));
 This could be due to misconfiguration or to an error inside JACK.\n\
 \n\
 Click OK to exit %1."), PROGRAM_NAME));
-    
+
                msg.run ();
                _exit (0);
                msg.run ();
                _exit (0);
-               
+
        } else {
 
                /* engine has already run, so this is a mid-session JACK death */
        } else {
 
                /* engine has already run, so this is a mid-session JACK death */
-               
-               MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
+
+               MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false));
                msg->set_secondary_text (string_compose (_(
 "JACK exited unexpectedly, and without notifying %1.\n\
 \n\
                msg->set_secondary_text (string_compose (_(
 "JACK exited unexpectedly, and without notifying %1.\n\
 \n\
@@ -493,11 +409,11 @@ session at this time, because we would lose your connection information.\n"), PR
 static void
 sigpipe_handler (int /*signal*/)
 {
 static void
 sigpipe_handler (int /*signal*/)
 {
-        /* XXX fix this so that we do this again after a reconnect to JACK
-         */
+       /* XXX fix this so that we do this again after a reconnect to JACK
+        */
+
+       static bool done_the_jack_thing = false;
 
 
-        static bool done_the_jack_thing = false;
-       
        if (!done_the_jack_thing) {
                AudioEngine::instance()->died ();
                g_idle_add (tell_about_jack_death, 0);
        if (!done_the_jack_thing) {
                AudioEngine::instance()->died ();
                g_idle_add (tell_about_jack_death, 0);
@@ -509,9 +425,9 @@ sigpipe_handler (int /*signal*/)
 void close_external_ui_windows();
 #endif
 
 void close_external_ui_windows();
 #endif
 
-#ifdef VST_SUPPORT
+#ifdef WINDOWS_VST_SUPPORT
 
 
-extern int gui_init (int* argc, char** argv[]);
+extern int windows_vst_gui_init (int* argc, char** argv[]);
 
 /* this is called from the entry point of a wine-compiled
    executable that is linked against gtk2_ardour built
 
 /* this is called from the entry point of a wine-compiled
    executable that is linked against gtk2_ardour built
@@ -523,20 +439,19 @@ int ardour_main (int argc, char *argv[])
 int main (int argc, char *argv[])
 #endif
 {
 int main (int argc, char *argv[])
 #endif
 {
-#ifdef __APPLE__
-       fixup_bundle_environment ();
-#endif
+       fixup_bundle_environment (argc, argv);
 
 
-       if (!Glib::thread_supported())
+       if (!Glib::thread_supported()) {
                Glib::thread_init();
                Glib::thread_init();
+       }
 
        gtk_set_locale ();
 
 
        gtk_set_locale ();
 
-#ifdef VST_SUPPORT
+#ifdef WINDOWS_VST_SUPPORT
        /* this does some magic that is needed to make GTK and Wine's own
           X11 client interact properly.
        */
        /* this does some magic that is needed to make GTK and Wine's own
           X11 client interact properly.
        */
-       gui_init (&argc, &argv);
+       windows_vst_gui_init (&argc, &argv);
 #endif
 
        (void) bindtextdomain (PACKAGE, localedir);
 #endif
 
        (void) bindtextdomain (PACKAGE, localedir);
@@ -556,6 +471,12 @@ int main (int argc, char *argv[])
        text_receiver.listen_to (fatal);
        text_receiver.listen_to (warning);
 
        text_receiver.listen_to (fatal);
        text_receiver.listen_to (warning);
 
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+       if (getenv ("BOOST_DEBUG")) {
+               boost_debug_shared_ptr_show_live_debugging (true);
+       }
+#endif
+
        if (parse_opts (argc, argv)) {
                exit (1);
        }
        if (parse_opts (argc, argv)) {
                exit (1);
        }
@@ -579,7 +500,7 @@ int main (int argc, char *argv[])
        }
 
        if (no_splash) {
        }
 
        if (no_splash) {
-               cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
+               cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl
                     << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
                     << endl
                     << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
                     << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
                     << endl
                     << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
@@ -605,7 +526,7 @@ int main (int argc, char *argv[])
        }
 
        ui->run (text_receiver);
        }
 
        ui->run (text_receiver);
-        Gtkmm2ext::Application::instance()->cleanup();
+       Gtkmm2ext::Application::instance()->cleanup();
        ui = 0;
 
        ARDOUR::cleanup ();
        ui = 0;
 
        ARDOUR::cleanup ();
@@ -616,7 +537,7 @@ int main (int argc, char *argv[])
 #endif
        return 0;
 }
 #endif
        return 0;
 }
-#ifdef VST_SUPPORT
+#ifdef WINDOWS_VST_SUPPORT
 } // end of extern C block
 #endif
 
 } // end of extern C block
 #endif