X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmain.cc;h=a123631a54cc0f2b3219b919e67f2f8767a49e9e;hb=00f12dc39582996ef930ce5caeeb3e2ecc32140e;hp=d212edef92fdfd2bb3f5f97baf46fc731cfb4f63;hpb=658bb3ccd43658de18fbd43cd91a8e66650e27a7;p=ardour.git diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index d212edef92..a123631a54 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -18,16 +18,20 @@ */ #include -#include #include -#include #include +#include +#include + #include #include +#ifdef HAVE_FFTW35F +#include +#endif + #include "pbd/error.h" -#include "pbd/epa.h" #include "pbd/file_utils.h" #include "pbd/textreceiver.h" #include "pbd/failed_constructor.h" @@ -38,7 +42,6 @@ #endif #include "ardour/revision.h" -#include "ardour/version.h" #include "ardour/ardour.h" #include "ardour/audioengine.h" #include "ardour/session_utils.h" @@ -49,18 +52,21 @@ #include #include -#include - -#include "version.h" -#include "utils.h" #include "ardour_ui.h" +#include "ui_config.h" #include "opts.h" #include "enums.h" +#include "bundle_env.h" + +#include "pbd/i18n.h" -#include "i18n.h" +#ifdef PLATFORM_WINDOWS +#include // Needed for '_fmode' +#include // console +#endif -#ifdef __APPLE__ -#include +#ifdef WAF_BUILD +#include "gtk2ardour-version.h" #endif using namespace std; @@ -74,7 +80,7 @@ TextReceiver text_receiver ("ardour"); extern int curvetest (string); static ARDOUR_UI *ui = 0; -static const char* localedir = LOCALEDIR; +static string localedir (LOCALEDIR); void gui_jack_error () @@ -99,268 +105,26 @@ gui_jack_error () win.run (); } -static void export_search_path (const string& base_dir, const char* varname, const char* dir) -{ - string path; - const char * cstr = g_getenv (varname); - - if (cstr) { - path = cstr; - path += ':'; - } else { - path = ""; - } - path += base_dir; - path += dir; - - g_setenv (varname, path.c_str(), 1); -} - -#ifdef __APPLE__ - -#include -#include - -extern void set_language_preference (); // cocoacarbon.mm - -void -fixup_bundle_environment (int, char* []) -{ - if (!g_getenv ("ARDOUR_BUNDLED")) { - return; - } - - EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV")); - - set_language_preference (); - - char execpath[MAXPATHLEN+1]; - uint32_t pathsz = sizeof (execpath); - - _NSGetExecutablePath (execpath, &pathsz); - - std::string path; - std::string exec_dir = Glib::path_get_dirname (execpath); - std::string bundle_dir; - std::string userconfigdir = user_config_directory(); - - bundle_dir = Glib::path_get_dirname (exec_dir); - -#ifdef ENABLE_NLS - if (!ARDOUR::translations_are_enabled ()) { - localedir = "/this/cannot/exist"; - } else { - /* force localedir into the bundle */ - - vector lpath; - lpath.push_back (bundle_dir); - lpath.push_back ("Resources"); - lpath.push_back ("locale"); - localedir = strdup (Glib::build_filename (lpath).c_str()); - } -#endif - - export_search_path (bundle_dir, "ARDOUR_DLL_PATH", "/lib"); - - /* 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. - */ - - export_search_path (bundle_dir, "ARDOUR_DATA_PATH", "/Resources"); - export_search_path (bundle_dir, "ARDOUR_CONFIG_PATH", "/Resources"); - export_search_path (bundle_dir, "ARDOUR_INSTANT_XML_PATH", "/Resources"); - export_search_path (bundle_dir, "LADSPA_PATH", "/Plugins"); - export_search_path (bundle_dir, "VAMP_PATH", "/lib"); - export_search_path (bundle_dir, "GTK_PATH", "/lib/gtkengines"); - - g_setenv ("SUIL_MODULE_DIR", (bundle_dir + "/lib").c_str(), 1); - g_setenv ("PATH", (bundle_dir + "/MacOS:" + std::string(g_getenv ("PATH"))).c_str(), 1); - - /* unset GTK_RC_FILES so that we only load the RC files that we define - */ - - g_unsetenv ("GTK_RC_FILES"); - - /* write a pango.rc file and tell pango to use it. we'd love - to put this into the PROGRAM_NAME.app bundle and leave it there, - but the user may not have write permission. so ... - - we also have to make sure that the user ardour directory - actually exists ... - */ - - if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) { - error << string_compose (_("cannot create user %3 folder %1 (%2)"), userconfigdir, strerror (errno), PROGRAM_NAME) - << endmsg; - } else { - - 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 { - pangorc << "[Pango]\nModuleFiles=" - << Glib::build_filename (bundle_dir, "Resources/pango.modules") - << endl; - pangorc.close (); - - g_setenv ("PANGO_RC_FILE", path.c_str(), 1); - } - } - - g_setenv ("CHARSETALIASDIR", bundle_dir.c_str(), 1); - g_setenv ("FONTCONFIG_FILE", Glib::build_filename (bundle_dir, "Resources/fonts.conf").c_str(), 1); - g_setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (bundle_dir, "Resources/gdk-pixbuf.loaders").c_str(), 1); -} - -static void load_custom_fonts() { -/* this code will only compile on OS X 10.6 and above, and we currently do not - * need it for earlier versions since we fall back on a non-monospace, - * non-custom font. - */ -#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 - std::string ardour_mono_file; - - if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) { - cerr << _("Cannot find ArdourMono TrueType font") << endl; +#ifndef NDEBUG +static void ardour_g_log (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { + switch (log_level) { + case G_LOG_FLAG_FATAL: + case G_LOG_LEVEL_CRITICAL: + fatal << "g_log: " << message << endmsg; + break; + case G_LOG_LEVEL_ERROR: + error << "g_log: " << message << endmsg; + break; + case G_LOG_LEVEL_WARNING: + warning << "g_log: " << message << endmsg; + break; + case G_LOG_LEVEL_MESSAGE: + case G_LOG_LEVEL_INFO: + default: + info << "g_log: " << message << endmsg; + break; } - - CFStringRef ttf; - CFURLRef fontURL; - CFErrorRef error; - ttf = CFStringCreateWithBytes( - kCFAllocatorDefault, (UInt8*) ardour_mono_file.c_str(), - ardour_mono_file.length(), - kCFStringEncodingUTF8, FALSE); - fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, ttf, kCFURLPOSIXPathStyle, TRUE); - if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error) != true) { - cerr << _("Cannot load ArdourMono TrueType font.") << endl; - } -#endif } - -#else - -void -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 (!g_getenv ("ARDOUR_BUNDLED")) { - return; - } - - EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV")); - - std::string path; - std::string dir_path = Glib::path_get_dirname (Glib::path_get_dirname (argv[0])); - std::string userconfigdir = user_config_directory(); - -#ifdef ENABLE_NLS - if (!ARDOUR::translations_are_enabled ()) { - localedir = "/this/cannot/exist"; - } else { - /* force localedir into the bundle */ - vector lpath; - lpath.push_back (dir_path); - lpath.push_back ("share"); - lpath.push_back ("locale"); - localedir = canonical_path (Glib::build_filename (lpath)).c_str(); - } -#endif - - /* note that this function is POSIX/Linux specific, so using / as - a dir separator in this context is just fine. - */ - - 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"); - export_search_path (dir_path, "LADSPA_PATH", "/plugins"); - export_search_path (dir_path, "VAMP_PATH", "/lib"); - export_search_path (dir_path, "GTK_PATH", "/lib/gtkengines"); - - g_setenv ("SUIL_MODULE_DIR", (dir_path + "/lib").c_str(), 1); - g_setenv ("PATH", (dir_path + "/bin:" + std::string(g_getenv ("PATH"))).c_str(), 1); - - /* unset GTK_RC_FILES so that we only load the RC files that we define - */ - - g_unsetenv ("GTK_RC_FILES"); - - /* Tell fontconfig where to find fonts.conf. Use the system version - if it exists, otherwise use the stuff we included in the bundle - */ - - if (Glib::file_test ("/etc/fonts/fonts.conf", Glib::FILE_TEST_EXISTS)) { - g_setenv ("FONTCONFIG_FILE", "/etc/fonts/fonts.conf", 1); - g_setenv ("FONTCONFIG_PATH", "/etc/fonts", 1); - } else { - error << _("No fontconfig file found on your system. Things may looked very odd or ugly") << endmsg; - } - - /* 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 ... - - we also have to make sure that the user ardour directory - actually exists ... - */ - - if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) { - error << string_compose (_("cannot create user %3 folder %1 (%2)"), userconfigdir, strerror (errno), PROGRAM_NAME) - << endmsg; - } else { - - 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 { - pangorc << "[Pango]\nModuleFiles=" - << Glib::build_filename (userconfigdir, "pango.modules") - << endl; - pangorc.close (); - } - - g_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. - */ - - g_setenv ("GDK_PIXBUF_MODULE_FILE", Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders").c_str(), 1); - } - - /* this doesn't do much but setting it should prevent various parts of the GTK/GNU stack - from looking outside the bundle to find the charset.alias file. - */ - g_setenv ("CHARSETALIASDIR", dir_path.c_str(), 1); - -} - -static void load_custom_fonts() { - std::string ardour_mono_file; - if (!find_file_in_search_path (ardour_data_search_path(), "ArdourMono.ttf", ardour_mono_file)) { - cerr << _("Cannot find ArdourMono TrueType font") << endl; - } - - FcConfig *config = FcInitLoadConfigAndFonts(); - FcBool ret = FcConfigAppFontAddFile(config, reinterpret_cast(ardour_mono_file.c_str())); - if (ret == FcFalse) { - cerr << _("Cannot load ArdourMono TrueType font.") << endl; - } - ret = FcConfigSetCurrent(config); - if (ret == FcFalse) { - cerr << _("Failed to set fontconfig configuration.") << endl; - } -} - #endif static gboolean @@ -383,7 +147,7 @@ Click OK to exit %1."), PROGRAM_NAME, AudioEngine::instance()->current_backend_n } else { /* engine has already run, so this is a mid-session backend death */ - + MessageDialog msg (string_compose (_("The audio backend (%1) has failed, or terminated"), AudioEngine::instance()->current_backend_name()), false); msg.set_secondary_text (string_compose (_("%2 exited unexpectedly, and without notifying %1."), PROGRAM_NAME, AudioEngine::instance()->current_backend_name())); @@ -392,11 +156,11 @@ Click OK to exit %1."), PROGRAM_NAME, AudioEngine::instance()->current_backend_n return false; /* do not call again */ } +#ifndef PLATFORM_WINDOWS static void sigpipe_handler (int /*signal*/) { - /* XXX fix this so that we do this again after a reconnect to the backend - */ + /* XXX fix this so that we do this again after a reconnect to the backend */ static bool done_the_backend_thing = false; @@ -406,9 +170,101 @@ sigpipe_handler (int /*signal*/) done_the_backend_thing = true; } } +#endif + +#if (!defined COMPILER_MSVC && defined PLATFORM_WINDOWS) + +static FILE* pStdOut = 0; +static FILE* pStdErr = 0; +static BOOL bConsole; +static HANDLE hStdOut; + +static bool +IsAConsolePort (HANDLE handle) +{ + DWORD mode; + return (GetConsoleMode(handle, &mode) != 0); +} + +static void +console_madness_begin () +{ + bConsole = AttachConsole(ATTACH_PARENT_PROCESS); + hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + + /* re-attach to the console so we can see 'printf()' output etc. + * for MSVC see gtk2_ardour/msvc/winmain.cc + */ + + if ((bConsole) && (IsAConsolePort(hStdOut))) { + pStdOut = freopen( "CONOUT$", "w", stdout ); + pStdErr = freopen( "CONOUT$", "w", stderr ); + } +} + +static void +console_madness_end () +{ + if (pStdOut) { + fclose (pStdOut); + } + if (pStdErr) { + fclose (pStdErr); + } -#ifdef WINDOWS_VST_SUPPORT + if (bConsole) { + // Detach and free the console from our application + INPUT_RECORD input_record; + input_record.EventType = KEY_EVENT; + input_record.Event.KeyEvent.bKeyDown = TRUE; + input_record.Event.KeyEvent.dwControlKeyState = 0; + input_record.Event.KeyEvent.uChar.UnicodeChar = VK_RETURN; + input_record.Event.KeyEvent.wRepeatCount = 1; + input_record.Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + input_record.Event.KeyEvent.wVirtualScanCode = MapVirtualKey( VK_RETURN, 0 ); + + DWORD written = 0; + WriteConsoleInput( GetStdHandle( STD_INPUT_HANDLE ), &input_record, 1, &written ); + + FreeConsole(); + } +} + +static void command_line_parse_error (int *argc, char** argv[]) {} + +#elif (defined(COMPILER_MSVC) && defined(NDEBUG) && !defined(RDC_BUILD)) + +// these are not used here. for MSVC see gtk2_ardour/msvc/winmain.cc +static void console_madness_begin () {} +static void console_madness_end () {} + +static void command_line_parse_error (int *argc, char** argv[]) { + // Since we don't ordinarily have access to stdout and stderr with + // an MSVC app, let the user know we encountered a parsing error. + Gtk::Main app(argc, argv); // Calls 'gtk_init()' + + Gtk::MessageDialog dlgReportParseError (string_compose (_("\n %1 could not understand your command line "), PROGRAM_NAME), + false, MESSAGE_ERROR, BUTTONS_CLOSE, true); + dlgReportParseError.set_title (string_compose (_("An error was encountered while launching %1"), PROGRAM_NAME)); + dlgReportParseError.run (); +} + +#else +static void console_madness_begin () {} +static void console_madness_end () {} +static void command_line_parse_error (int *argc, char** argv[]) {} +#endif + +#if (defined(COMPILER_MSVC) && defined(NDEBUG) && !defined(RDC_BUILD)) +/* + * Release build with MSVC uses ardour_main() + */ +int ardour_main (int argc, char *argv[]) + +#elif (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS) + +// prototype for function in windows_vst_plugin_ui.cc extern int windows_vst_gui_init (int* argc, char** argv[]); /* this is called from the entry point of a wine-compiled @@ -416,34 +272,52 @@ extern int windows_vst_gui_init (int* argc, char** argv[]); as a shared library. */ extern "C" { + int ardour_main (int argc, char *argv[]) + +#elif defined NOMAIN +int nomain (int argc, char *argv[]) #else int main (int argc, char *argv[]) #endif { - fixup_bundle_environment (argc, argv); + ARDOUR::check_for_old_configuration_files(); + + fixup_bundle_environment (argc, argv, localedir); - load_custom_fonts(); /* needs to happend before any gtk and pango init calls */ + load_custom_fonts(); /* needs to happen before any gtk and pango init calls */ if (!Glib::thread_supported()) { Glib::thread_init(); } +#ifdef HAVE_FFTW35F + fftwf_make_planner_thread_safe (); +#endif + #ifdef ENABLE_NLS - gtk_set_locale (); + /* initialize C and C++ locales to user preference */ + setlocale (LC_ALL, ""); + try { + std::locale::global (std::locale (setlocale (LC_ALL, 0))); + } catch (...) { + std::cerr << "Cannot set C++ locale\n"; + } #endif -#ifdef WINDOWS_VST_SUPPORT - /* this does some magic that is needed to make GTK and Wine's own - X11 client interact properly. - */ + console_madness_begin(); + +#if (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS) + /* this does some magic that is needed to make GTK and X11 client interact properly. + * the platform dependent code is in windows_vst_plugin_ui.cc + */ windows_vst_gui_init (&argc, &argv); #endif #ifdef ENABLE_NLS - cerr << "bnd txt domain [" << PACKAGE << "] to " << localedir << endl; + cerr << "bind txt domain [" << PACKAGE << "] to " << localedir << endl; - (void) bindtextdomain (PACKAGE, localedir); + (void) bindtextdomain (PACKAGE, localedir.c_str()); /* our i18n translations are all in UTF-8, so make sure that even if the user locale doesn't specify UTF-8, we use that when handling them. @@ -467,6 +341,7 @@ int main (int argc, char *argv[]) #endif if (parse_opts (argc, argv)) { + command_line_parse_error (&argc, &argv); exit (1); } @@ -485,7 +360,7 @@ int main (int argc, char *argv[]) } if (no_splash) { - cerr << _("Copyright (C) 1999-2012 Paul Davis") << endl + cerr << _("Copyright (C) 1999-2015 Paul Davis") << endl << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker, Robin Gareus") << endl << endl << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl @@ -495,9 +370,7 @@ int main (int argc, char *argv[]) << endl; } - /* some GUI objects need this */ - - if (!ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization, localedir)) { + if (!ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization, localedir.c_str())) { error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg; exit (1); } @@ -512,13 +385,26 @@ int main (int argc, char *argv[]) } #endif + DEBUG_TRACE (DEBUG::Locale, string_compose ("main() locale '%1'\n", setlocale (LC_NUMERIC, NULL))); + + if (UIConfiguration::instance().pre_gui_init ()) { + error << _("Could not complete pre-GUI initialization") << endmsg; + exit (1); + } + try { - ui = new ARDOUR_UI (&argc, &argv, localedir); + ui = new ARDOUR_UI (&argc, &argv, localedir.c_str()); } catch (failed_constructor& err) { error << string_compose (_("could not create %1 GUI"), PROGRAM_NAME) << endmsg; exit (1); } +#ifndef NDEBUG + g_log_set_handler (NULL, + GLogLevelFlags (G_LOG_LEVEL_WARNING | G_LOG_FLAG_FATAL | G_LOG_LEVEL_CRITICAL | G_LOG_FLAG_RECURSION), + &ardour_g_log, NULL); +#endif + ui->run (text_receiver); Gtkmm2ext::Application::instance()->cleanup(); delete ui; @@ -527,9 +413,10 @@ int main (int argc, char *argv[]) ARDOUR::cleanup (); pthread_cancel_all (); + console_madness_end (); + return 0; } -#ifdef WINDOWS_VST_SUPPORT -} // end of extern C block +#if (defined WINDOWS_VST_SUPPORT && !defined PLATFORM_WINDOWS) +} // end of extern "C" block #endif -