summaryrefslogtreecommitdiff
path: root/gtk2_ardour/ardour_ui_startup.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2019-09-23 14:49:06 -0600
committerPaul Davis <paul@linuxaudiosystems.com>2019-09-23 14:49:06 -0600
commit5beeca2e95a7ea70a4225eaca979179649cb2e90 (patch)
tree832643fc664d4d82d059dbebb7bd658fd79b9a59 /gtk2_ardour/ardour_ui_startup.cc
parent9c0beeb7591302747eee6e28c448314313f8d54a (diff)
split apart ardour_ui.cc into a series of distinct source modules.
Should be a 100% no-op - no code was altered, just moved
Diffstat (limited to 'gtk2_ardour/ardour_ui_startup.cc')
-rw-r--r--gtk2_ardour/ardour_ui_startup.cc712
1 files changed, 712 insertions, 0 deletions
diff --git a/gtk2_ardour/ardour_ui_startup.cc b/gtk2_ardour/ardour_ui_startup.cc
new file mode 100644
index 0000000000..62be3e5aa4
--- /dev/null
+++ b/gtk2_ardour/ardour_ui_startup.cc
@@ -0,0 +1,712 @@
+/*
+ * Copyright (C) 2005-2007 Doug McLain <doug@nostar.net>
+ * Copyright (C) 2005-2017 Tim Mayberry <mojofunk@gmail.com>
+ * Copyright (C) 2005-2019 Paul Davis <paul@linuxaudiosystems.com>
+ * Copyright (C) 2005 Karsten Wiese <fzuuzf@googlemail.com>
+ * Copyright (C) 2005 Taybin Rutkin <taybin@taybin.com>
+ * Copyright (C) 2006-2015 David Robillard <d@drobilla.net>
+ * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
+ * Copyright (C) 2008-2010 Sakari Bergen <sakari.bergen@beatwaves.net>
+ * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
+ * Copyright (C) 2013-2015 Colin Fletcher <colin.m.fletcher@googlemail.com>
+ * Copyright (C) 2013-2016 John Emmas <john@creativepost.co.uk>
+ * Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
+ * Copyright (C) 2014-2018 Ben Loftis <ben@harrisonconsoles.com>
+ * Copyright (C) 2015 André Nusser <andre.nusser@googlemail.com>
+ * Copyright (C) 2016-2018 Len Ovens <len@ovenwerks.net>
+ * Copyright (C) 2017 Johannes Mueller <github@johannes-mueller.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef WAF_BUILD
+#include "gtk2ardour-config.h"
+#include "gtk2ardour-version.h"
+#endif
+
+#ifndef PLATFORM_WINDOWS
+#include <sys/resource.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
+#include <glib.h>
+#include "pbd/gstdio_compat.h"
+
+#include <gtkmm/stock.h>
+
+#include "pbd/basename.h"
+#include "pbd/file_utils.h"
+#include "pbd/i18n.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/filename_extensions.h"
+#include "ardour/filesystem_paths.h"
+#include "ardour/profile.h"
+#include "ardour/recent_sessions.h"
+
+#include "gtkmm2ext/application.h"
+
+#include "ambiguous_file_dialog.h"
+#include "ardour_ui.h"
+#include "engine_dialog.h"
+#include "keyboard.h"
+#include "missing_file_dialog.h"
+#include "nsm.h"
+#include "opts.h"
+#include "pingback.h"
+#include "public_editor.h"
+#include "splash.h"
+#include "startup.h"
+
+using namespace ARDOUR;
+using namespace PBD;
+using namespace Gtk;
+using namespace Gtkmm2ext;
+using namespace std;
+
+
+static bool
+_hide_splash (gpointer arg)
+{
+ ((ARDOUR_UI*)arg)->hide_splash();
+ return false;
+}
+
+bool
+ARDOUR_UI::first_idle ()
+{
+ if (_session) {
+ _session->allow_auto_play (true);
+ }
+
+ if (editor) {
+ editor->first_idle();
+ }
+
+ /* in 1 second, hide the splash screen
+ *
+ * Consider hiding it *now*. If a user opens opens a dialog
+ * during that one second while the splash is still visible,
+ * the dialog will push-back the splash.
+ * Closing the dialog later will pop it back.
+ */
+ Glib::signal_timeout().connect (sigc::bind (sigc::ptr_fun (_hide_splash), this), 1000);
+
+ Keyboard::set_can_save_keybindings (true);
+ return false;
+}
+
+
+void
+ARDOUR_UI::setup_profile ()
+{
+ if (gdk_screen_width() < 1200 || getenv ("ARDOUR_NARROW_SCREEN")) {
+ Profile->set_small_screen ();
+ }
+
+ if (g_getenv ("TRX")) {
+ Profile->set_trx ();
+ }
+
+ if (g_getenv ("MIXBUS")) {
+ Profile->set_mixbus ();
+ }
+}
+
+int
+ARDOUR_UI::missing_file (Session*s, std::string str, DataType type)
+{
+ MissingFileDialog dialog (s, str, type);
+
+ dialog.show ();
+ dialog.present ();
+
+ int result = dialog.run ();
+ dialog.hide ();
+
+ switch (result) {
+ case RESPONSE_OK:
+ break;
+ default:
+ return 1; // quit entire session load
+ }
+
+ result = dialog.get_action ();
+
+ return result;
+}
+
+int
+ARDOUR_UI::ambiguous_file (std::string file, std::vector<std::string> hits)
+{
+ AmbiguousFileDialog dialog (file, hits);
+
+ dialog.show ();
+ dialog.present ();
+
+ dialog.run ();
+
+ return dialog.get_which ();
+}
+
+void
+ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_path)
+{
+ const char* start_big = "<span size=\"x-large\" weight=\"bold\">";
+ const char* end_big = "</span>";
+ const char* start_mono = "<tt>";
+ const char* end_mono = "</tt>";
+
+ MessageDialog msg (string_compose (_("%4This is a session from an older version of %3%5\n\n"
+ "%3 has copied the old session file\n\n%6%1%7\n\nto\n\n%6%2%7\n\n"
+ "From now on, use the backup copy with older versions of %3"),
+ xml_path, backup_path, PROGRAM_NAME,
+ start_big, end_big,
+ start_mono, end_mono), true);
+
+ msg.run ();
+}
+
+
+int
+ARDOUR_UI::sr_mismatch_dialog (samplecnt_t desired, samplecnt_t actual)
+{
+ HBox* hbox = new HBox();
+ Image* image = new Image (Stock::DIALOG_WARNING, ICON_SIZE_DIALOG);
+ ArdourDialog dialog (_("Sample Rate Mismatch"), true);
+ Label message (string_compose (_("\
+This session was created with a sample rate of %1 Hz, but\n\
+%2 is currently running at %3 Hz. If you load this session,\n\
+audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual));
+
+ image->set_alignment(ALIGN_CENTER, ALIGN_TOP);
+ hbox->pack_start (*image, PACK_EXPAND_WIDGET, 12);
+ hbox->pack_end (message, PACK_EXPAND_PADDING, 12);
+ dialog.get_vbox()->pack_start(*hbox, PACK_EXPAND_PADDING, 6);
+ dialog.add_button (_("Do not load session"), RESPONSE_REJECT);
+ dialog.add_button (_("Load session anyway"), RESPONSE_ACCEPT);
+ dialog.set_default_response (RESPONSE_ACCEPT);
+ dialog.set_position (WIN_POS_CENTER);
+ message.show();
+ image->show();
+ hbox->show();
+
+ switch (dialog.run()) {
+ case RESPONSE_ACCEPT:
+ return 0;
+ default:
+ break;
+ }
+
+ return 1;
+}
+
+void
+ARDOUR_UI::sr_mismatch_message (samplecnt_t desired, samplecnt_t actual)
+{
+ MessageDialog msg (string_compose (_("\
+This session was created with a sample rate of %1 Hz, but\n\
+%2 is currently running at %3 Hz.\n\
+Audio will be recorded and played at the wrong sample rate.\n\
+Re-Configure the Audio Engine in\n\
+Menu > Window > Audio/Midi Setup"),
+ desired, PROGRAM_NAME, actual),
+ true,
+ Gtk::MESSAGE_WARNING);
+ msg.run ();
+}
+
+
+XMLNode*
+ARDOUR_UI::preferences_settings () const
+{
+ XMLNode* node = 0;
+
+ if (_session) {
+ node = _session->instant_xml(X_("Preferences"));
+ } else {
+ node = Config->instant_xml(X_("Preferences"));
+ }
+
+ if (!node) {
+ node = new XMLNode (X_("Preferences"));
+ }
+
+ return node;
+}
+
+XMLNode*
+ARDOUR_UI::mixer_settings () const
+{
+ XMLNode* node = 0;
+
+ if (_session) {
+ node = _session->instant_xml(X_("Mixer"));
+ } else {
+ node = Config->instant_xml(X_("Mixer"));
+ }
+
+ if (!node) {
+ node = new XMLNode (X_("Mixer"));
+ }
+
+ return node;
+}
+
+XMLNode*
+ARDOUR_UI::main_window_settings () const
+{
+ XMLNode* node = 0;
+
+ if (_session) {
+ node = _session->instant_xml(X_("Main"));
+ } else {
+ node = Config->instant_xml(X_("Main"));
+ }
+
+ if (!node) {
+ if (getenv("ARDOUR_INSTANT_XML_PATH")) {
+ node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
+ }
+ }
+
+ if (!node) {
+ node = new XMLNode (X_("Main"));
+ }
+
+ return node;
+}
+
+XMLNode*
+ARDOUR_UI::editor_settings () const
+{
+ XMLNode* node = 0;
+
+ if (_session) {
+ node = _session->instant_xml(X_("Editor"));
+ } else {
+ node = Config->instant_xml(X_("Editor"));
+ }
+
+ if (!node) {
+ if (getenv("ARDOUR_INSTANT_XML_PATH")) {
+ node = Config->instant_xml(getenv("ARDOUR_INSTANT_XML_PATH"));
+ }
+ }
+
+ if (!node) {
+ node = new XMLNode (X_("Editor"));
+ }
+
+ return node;
+}
+
+XMLNode*
+ARDOUR_UI::keyboard_settings () const
+{
+ XMLNode* node = 0;
+
+ node = Config->extra_xml(X_("Keyboard"));
+
+ if (!node) {
+ node = new XMLNode (X_("Keyboard"));
+ }
+
+ return node;
+}
+
+
+void
+ARDOUR_UI::loading_message (const std::string& msg)
+{
+ if (ARDOUR_COMMAND_LINE::no_splash) {
+ return;
+ }
+
+ if (!splash) {
+ show_splash ();
+ }
+
+ splash->message (msg);
+}
+
+void
+ARDOUR_UI::show_splash ()
+{
+ if (splash == 0) {
+ try {
+ splash = new Splash;
+ } catch (...) {
+ return;
+ }
+ }
+
+ splash->display ();
+}
+
+void
+ARDOUR_UI::hide_splash ()
+{
+ delete splash;
+ splash = 0;
+}
+
+void
+ARDOUR_UI::check_announcements ()
+{
+#ifdef PHONE_HOME
+ string _annc_filename;
+
+#ifdef __APPLE__
+ _annc_filename = PROGRAM_NAME "_announcements_osx_";
+#elif defined PLATFORM_WINDOWS
+ _annc_filename = PROGRAM_NAME "_announcements_windows_";
+#else
+ _annc_filename = PROGRAM_NAME "_announcements_linux_";
+#endif
+ _annc_filename.append (VERSIONSTRING);
+
+ _announce_string = "";
+
+ std::string path = Glib::build_filename (user_config_directory(), _annc_filename);
+ FILE* fin = g_fopen (path.c_str(), "rb");
+ if (fin) {
+ while (!feof (fin)) {
+ char tmp[1024];
+ size_t len;
+ if ((len = fread (tmp, sizeof(char), 1024, fin)) == 0 || ferror (fin)) {
+ break;
+ }
+ _announce_string.append (tmp, len);
+ }
+ fclose (fin);
+ }
+
+ pingback (VERSIONSTRING, path);
+#endif
+}
+
+int
+ARDOUR_UI::starting ()
+{
+ Application* app = Application::instance ();
+ const char *nsm_url;
+ bool brand_new_user = ArdourStartup::required ();
+
+ app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
+ app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::load_from_application_api));
+
+ if (ARDOUR_COMMAND_LINE::check_announcements) {
+ check_announcements ();
+ }
+
+ app->ready ();
+
+ /* we need to create this early because it may need to set the
+ * audio backend end up.
+ */
+
+ try {
+ audio_midi_setup.get (true);
+ } catch (...) {
+ std::cerr << "audio-midi engine setup failed."<< std::endl;
+ return -1;
+ }
+
+ if ((nsm_url = g_getenv ("NSM_URL")) != 0) {
+ nsm = new NSM_Client;
+ if (!nsm->init (nsm_url)) {
+ /* the ardour executable may have different names:
+ *
+ * waf's obj.target for distro versions: eg ardour4, ardourvst4
+ * Ardour4, Mixbus3 for bundled versions + full path on OSX & windows
+ * argv[0] does not apply since we need the wrapper-script (not the binary itself)
+ *
+ * The wrapper startup script should set the environment variable 'ARDOUR_SELF'
+ */
+ const char *process_name = g_getenv ("ARDOUR_SELF");
+ nsm->announce (PROGRAM_NAME, ":dirty:", process_name ? process_name : "ardour6");
+
+ unsigned int i = 0;
+ // wait for announce reply from nsm server
+ for ( i = 0; i < 5000; ++i) {
+ nsm->check ();
+
+ Glib::usleep (i);
+ if (nsm->is_active()) {
+ break;
+ }
+ }
+ if (i == 5000) {
+ error << _("NSM server did not announce itself") << endmsg;
+ return -1;
+ }
+ // wait for open command from nsm server
+ for ( i = 0; i < 5000; ++i) {
+ nsm->check ();
+ Glib::usleep (1000);
+ if (nsm->client_id ()) {
+ break;
+ }
+ }
+
+ if (i == 5000) {
+ error << _("NSM: no client ID provided") << endmsg;
+ return -1;
+ }
+
+ if (_session && nsm) {
+ _session->set_nsm_state( nsm->is_active() );
+ } else {
+ error << _("NSM: no session created") << endmsg;
+ return -1;
+ }
+
+ // nsm requires these actions disabled
+ vector<string> action_names;
+ action_names.push_back("SaveAs");
+ action_names.push_back("Rename");
+ action_names.push_back("New");
+ action_names.push_back("Open");
+ action_names.push_back("Recent");
+ action_names.push_back("Close");
+
+ for (vector<string>::const_iterator n = action_names.begin(); n != action_names.end(); ++n) {
+ Glib::RefPtr<Action> act = ActionManager::get_action (X_("Main"), (*n).c_str());
+ if (act) {
+ act->set_sensitive (false);
+ }
+ }
+
+ } else {
+ delete nsm;
+ nsm = 0;
+ error << _("NSM: initialization failed") << endmsg;
+ return -1;
+ }
+
+ } else {
+
+ if (brand_new_user) {
+ _initial_verbose_plugin_scan = true;
+ ArdourStartup s;
+ s.present ();
+ main().run();
+ s.hide ();
+ _initial_verbose_plugin_scan = false;
+ switch (s.response ()) {
+ case Gtk::RESPONSE_OK:
+ break;
+ default:
+ return -1;
+ }
+ }
+
+ // TODO: maybe IFF brand_new_user
+ if (ARDOUR::Profile->get_mixbus () && Config->get_copy_demo_sessions ()) {
+ std::string dspd (Config->get_default_session_parent_dir());
+ Searchpath ds (ARDOUR::ardour_data_search_path());
+ ds.add_subdirectory_to_paths ("sessions");
+ vector<string> demos;
+ find_files_matching_pattern (demos, ds, ARDOUR::session_archive_suffix);
+
+ ARDOUR::RecentSessions rs;
+ ARDOUR::read_recent_sessions (rs);
+
+ for (vector<string>::iterator i = demos.begin(); i != demos.end (); ++i) {
+ /* "demo-session" must be inside "demo-session.<session_archive_suffix>" */
+ std::string name = basename_nosuffix (basename_nosuffix (*i));
+ std::string path = Glib::build_filename (dspd, name);
+ /* skip if session-dir already exists */
+ if (Glib::file_test(path.c_str(), Glib::FILE_TEST_IS_DIR)) {
+ continue;
+ }
+ /* skip sessions that are already in 'recent'.
+ * eg. a new user changed <session-default-dir> shorly after installation
+ */
+ for (ARDOUR::RecentSessions::iterator r = rs.begin(); r != rs.end(); ++r) {
+ if ((*r).first == name) {
+ continue;
+ }
+ }
+ try {
+ PBD::FileArchive ar (*i);
+ if (0 == ar.inflate (dspd)) {
+ store_recent_sessions (name, path);
+ info << string_compose (_("Copied Demo Session %1."), name) << endmsg;
+ }
+ } catch (...) {}
+ }
+ }
+
+#ifdef NO_PLUGIN_STATE
+
+ ARDOUR::RecentSessions rs;
+ ARDOUR::read_recent_sessions (rs);
+
+ string path = Glib::build_filename (user_config_directory(), ".iknowaboutfreeversion");
+
+ if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS) && !rs.empty()) {
+
+ /* already used Ardour, have sessions ... warn about plugin state */
+
+ ArdourDialog d (_("Free/Demo Version Warning"), true);
+ Label l;
+ Button b (string_compose (_("Subscribe and support development of %1"), PROGRAM_NAME));
+ CheckButton c (_("Don't warn me about this again"));
+
+ l.set_markup (string_compose (_("<span weight=\"bold\" size=\"large\">%1</span>\n\n<b>%2</b>\n\n<i>%3</i>\n\n%4"),
+ string_compose (_("This is a free/demo version of %1"), PROGRAM_NAME),
+ _("It will not restore OR save any plugin settings"),
+ _("If you load an existing session with plugin settings\n"
+ "they will not be used and will be lost."),
+ _("To get full access to updates without this limitation\n"
+ "consider becoming a subscriber for a low cost every month.")));
+ l.set_justify (JUSTIFY_CENTER);
+
+ b.signal_clicked().connect (mem_fun(*this, &ARDOUR_UI::launch_subscribe));
+
+ d.get_vbox()->pack_start (l, true, true);
+ d.get_vbox()->pack_start (b, false, false, 12);
+ d.get_vbox()->pack_start (c, false, false, 12);
+
+ d.add_button (_("Quit now"), RESPONSE_CANCEL);
+ d.add_button (string_compose (_("Continue using %1"), PROGRAM_NAME), RESPONSE_OK);
+
+ d.show_all ();
+
+ c.signal_toggled().connect (sigc::hide_return (sigc::bind (sigc::ptr_fun (toggle_file_existence), path)));
+
+ if (d.run () != RESPONSE_OK) {
+ _exit (EXIT_SUCCESS);
+ }
+ }
+#endif
+
+ /* go get a session */
+
+ const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user);
+
+ if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) {
+ std::cerr << "Cannot get session parameters."<< std::endl;
+ return -1;
+ }
+ }
+
+ use_config ();
+
+ WM::Manager::instance().show_visible ();
+
+ /* We have to do this here since goto_editor_window() ends up calling show_all() on the
+ * editor window, and we may want stuff to be hidden.
+ */
+ _status_bar_visibility.update ();
+
+ BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
+
+ /* all other dialogs are created conditionally */
+
+ return 0;
+}
+
+void
+ARDOUR_UI::use_config ()
+{
+ XMLNode* node = Config->extra_xml (X_("TransportControllables"));
+ if (node) {
+ set_transport_controllable_state (*node);
+ }
+}
+
+void
+ARDOUR_UI::check_memory_locking ()
+{
+#if defined(__APPLE__) || defined(PLATFORM_WINDOWS)
+ /* OS X doesn't support mlockall(2), and so testing for memory locking capability there is pointless */
+ return;
+#else // !__APPLE__
+
+ XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning"));
+
+ if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) {
+
+ struct rlimit limits;
+ int64_t ram;
+ long pages, page_size;
+#ifdef __FreeBSD__
+ size_t pages_len=sizeof(pages);
+ if ((page_size = getpagesize()) < 0 ||
+ sysctlbyname("hw.availpages", &pages, &pages_len, NULL, 0))
+#else
+ if ((page_size = sysconf (_SC_PAGESIZE)) < 0 ||(pages = sysconf (_SC_PHYS_PAGES)) < 0)
+#endif
+ {
+ ram = 0;
+ } else {
+ ram = (int64_t) pages * (int64_t) page_size;
+ }
+
+ if (getrlimit (RLIMIT_MEMLOCK, &limits)) {
+ return;
+ }
+
+ if (limits.rlim_cur != RLIM_INFINITY) {
+
+ if (ram == 0 || ((double) limits.rlim_cur / ram) < 0.75) {
+
+ MessageDialog msg (
+ string_compose (
+ _("WARNING: Your system has a limit for maximum amount of locked memory. "
+ "This might cause %1 to run out of memory before your system "
+ "runs out of memory. \n\n"
+ "You can view the memory limit with 'ulimit -l', "
+ "and it is normally controlled by %2"),
+ PROGRAM_NAME,
+#ifdef __FreeBSD__
+ X_("/etc/login.conf")
+#else
+ X_(" /etc/security/limits.conf")
+#endif
+ ).c_str());
+
+ msg.set_default_response (RESPONSE_OK);
+
+ VBox* vbox = msg.get_vbox();
+ HBox hbox;
+ CheckButton cb (_("Do not show this window again"));
+ hbox.pack_start (cb, true, false);
+ vbox->pack_start (hbox);
+ cb.show();
+ vbox->show();
+ hbox.show ();
+
+ pop_back_splash (msg);
+
+ msg.run ();
+
+ if (cb.get_active()) {
+ XMLNode node (X_("no-memory-warning"));
+ Config->add_instant_xml (node);
+ }
+ }
+ }
+ }
+#endif // !__APPLE__
+}
+