Vkeybd: add a mod-wheel
[ardour.git] / gtk2_ardour / startup_fsm.cc
index d77d2bc9d5a0162fefd8a18322ab66e056695294..9424160f4d7fb9f9e51cfc1ae76d8e1a680abd41 100644 (file)
@@ -21,6 +21,7 @@
 #include <gtkmm/dialog.h>
 #include <gtkmm/liststore.h>
 #include <gtkmm/messagedialog.h>
+#include <gtkmm/stock.h>
 
 #include "pbd/basename.h"
 #include "pbd/file_archive.h"
 
 #include "gtkmm2ext/application.h"
 #include <gtkmm2ext/doi.h>
+#include <gtkmm2ext/keyboard.h>
 
+#include "ardour_message.h"
+#include "ardour_ui.h"
+#include "debug.h"
 #include "engine_dialog.h"
 #include "new_user_wizard.h"
 #include "opts.h"
+#include "plugin_scan_dialog.h"
 #include "session_dialog.h"
+#include "splash.h"
 #include "startup_fsm.h"
 
+#ifdef WAF_BUILD
+#include "gtk2ardour-version.h"
+#endif
+
 using namespace ARDOUR;
 using namespace Gtk;
 using namespace Gtkmm2ext;
@@ -58,28 +69,53 @@ using std::vector;
 StartupFSM::StartupFSM (EngineControl& amd)
        : session_existing_sample_rate (0)
        , session_is_new (false)
-       , new_user (true /*NewUserWizard::required()*/)
-       , new_session (true)
-       , _state (NeedWizard)
-       , new_user_wizard (0)
+       , new_user (NewUserWizard::required())
+       , new_session_required (ARDOUR_COMMAND_LINE::new_session || (!ARDOUR::Profile->get_mixbus() && new_user))
+       , _state (new_user ? WaitingForNewUser : WaitingForSessionPath)
        , audiomidi_dialog (amd)
+       , new_user_dialog (0)
        , session_dialog (0)
+       , pre_release_dialog (0)
+       , plugin_scan_dialog (0)
 {
+       /* note that our initial state can be any of:
+        *
+        * WaitingForPreRelease:  if this is a pre-release build of Ardour and the user has not testified to their fidelity to our creed
+        * WaitingForNewUser:     if this is the first time any version appears to have been run on this machine by this user
+        * WaitingForSessionPath: if the previous two conditions are not true
+        */
+
+       if (string (VERSIONSTRING).find (".pre") != string::npos) {
+               string fn = Glib::build_filename (user_config_directory(), ".i_swear_that_i_will_heed_the_guidelines_stated_in_the_pre_release_dialog");
+               if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
+                       set_state (WaitingForPreRelease);
+               }
+       }
+
        Application* app = Application::instance ();
 
        app->ShouldQuit.connect (sigc::mem_fun (*this, &StartupFSM::queue_finish));
        app->ShouldLoad.connect (sigc::mem_fun (*this, &StartupFSM::load_from_application_api));
 
-       /* this may cause the delivery of ShouldLoad etc if we were invoked in
-        * particular ways. It will happen when the event loop runs again.
-        */
-
-       app->ready ();
+       Gtkmm2ext::Keyboard::HideMightMeanQuit.connect (sigc::mem_fun (*this, &StartupFSM::dialog_hidden));
 }
 
 StartupFSM::~StartupFSM ()
 {
        delete session_dialog;
+       delete pre_release_dialog;
+       delete plugin_scan_dialog;
+       delete new_user_dialog;
+}
+
+void
+StartupFSM::dialog_hidden (Gtk::Window* /* ignored */)
+{
+       /* since this object only exists during startup, any attempt to close
+        * any dialog that we manage with Ctrl/Cmd-w is assumed to indicate a
+        * desire to quit on the part of the user.
+        */
+       queue_finish ();
 }
 
 void
@@ -91,123 +127,133 @@ StartupFSM::queue_finish ()
 void
 StartupFSM::start ()
 {
-       if (new_user) {
-               /* show new user wizard */
-               _state = NeedSessionPath;
-               show_new_user_wizard ();
-       } else {
-               /* pretend we just showed the new user wizard and we're done
-                  with it
-               */
-               dialog_response_handler (RESPONSE_OK, NewUserDialog);
+       /* get the splash screen visible, if it isn't yet */
+       Splash::instance()->pop_front();
+       /* make it all happen on-screen */
+       ARDOUR_UI::instance()->flush_pending ();
+
+       DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("State at startup: %1\n"), enum_2_string (_state)));
+
+       switch (_state) {
+       case WaitingForPreRelease:
+               show_pre_release_dialog ();
+               break;
+       case WaitingForNewUser:
+               show_new_user_dialog ();
+               break;
+       case WaitingForSessionPath:
+               handle_waiting_for_session_path ();
+               break;
+       default:
+               fatal << string_compose (_("Programming error: %1"), string_compose (X_("impossible starting state in StartupFSM (%1)"), enum_2_string (_state))) << endmsg;
+               std::cerr << string_compose (_("Programming error: %1"), string_compose (X_("impossible starting state in StartupFSM (%1)"), enum_2_string (_state))) << std::endl;
+               /* NOTREACHED */
+               abort ();
        }
+
+       DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("State after startup: %1\n"), enum_2_string (_state)));
 }
 
+void
+StartupFSM::reset()
+{
+       show_session_dialog (new_session_required);
+}
 
 void
-StartupFSM::end()
+StartupFSM::set_state (MainState ms)
+{
+       DEBUG_TRACE (DEBUG::GuiStartup, string_compose (X_("new state: %1\n"), enum_2_string (ms)));
+       _state = ms;
+}
+
+template<typename T> void
+StartupFSM::end_dialog (T** d)
 {
+       assert (d);
+       assert (*d);
 
+       end_dialog (**d);
+       delete_when_idle (*d);
+       *d = 0;
+}
+
+template<typename T> void
+StartupFSM::end_dialog (T& d)
+{
+       d.hide ();
+       current_dialog_connection.disconnect ();
 }
 
 void
 StartupFSM::dialog_response_handler (int response, StartupFSM::DialogID dialog_id)
 {
-       const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || (!ARDOUR::Profile->get_mixbus() && new_user));
-       int csp;
+       DEBUG_TRACE (DEBUG::GuiStartup, string_compose ("Response %1 from %2 (nsr: %3 / nu: %4)\n", enum_2_string (Gtk::ResponseType (response)), enum_2_string (dialog_id), new_session_required, new_user));
 
-       std::cerr << "SFSM state = " << _state << " r = " << response << " did " << dialog_id << std::endl;
+       /* Notes:
+        *
+        * 1) yes, a brand new user might have specified a command line
+        * argument naming a new session. We ignore it. You're new to Ardour?
+        * We want to guide you through the startup.
+        */
 
        switch (_state) {
-       case NeedSessionPath:
+       case WaitingForPreRelease:
                switch (dialog_id) {
-               case NewUserDialog:
+               case PreReleaseDialog:
+               default:
+                       /* any response value from the pre-release dialog means
+                          "move along now"
+                       */
+                       end_dialog (&pre_release_dialog);
 
-                       current_dialog_connection.disconnect ();
-                       delete_when_idle (new_user_wizard);
+                       if (NewUserWizard::required()) {
+                               show_new_user_dialog ();
+                       } else {
+                               handle_waiting_for_session_path ();
+                       }
+                       break;
+               }
+               break;
 
+       case WaitingForNewUser:
+               switch (dialog_id) {
+               case NewUserDialog:
                        switch (response) {
                        case RESPONSE_OK:
+                               end_dialog (&new_user_dialog);
+                               show_session_dialog (new_session_required);
                                break;
                        default:
-                               exit (1);
-                       }
-
-                       /* new user wizard done, now lets get session params
-                        * either from the command line (if given) or a dialog
-                        * (if nothing given on the command line or if the
-                        * command line arguments don't work for some reason
-                        */
-
-                       if (ARDOUR_COMMAND_LINE::session_name.empty()) {
-
-                               /* nothing given on the command line ... show new session dialog */
-
-                               session_path = string();
-                               session_name = string();
-                               session_template = string();
-
-                               _state = NeedSessionPath;
-                               session_dialog = new SessionDialog (new_session_required, string(), string(), string(), false);
-                               show_session_dialog ();
-
-                       } else {
-
-                               if (get_session_parameters_from_command_line (new_session_required)) {
-
-                                       /* command line arguments all OK. Get engine parameters */
-
-                                       _state = NeedEngineParams;
-
-                                       if (!new_session_required && session_existing_sample_rate > 0) {
-                                               audiomidi_dialog.set_desired_sample_rate (session_existing_sample_rate);
-                                       }
-
-                                       show_audiomidi_dialog ();
-
-                               } else {
-
-                                       /* command line arguments not good. Use
-                                        * dialog, but prime the dialog with
-                                        * the information we set up in
-                                        * get_session_parameters_from_command_line()
-                                        */
-
-                                       _state = NeedSessionPath;
-                                       session_dialog = new SessionDialog (new_session_required, session_name, session_path, session_template, false);
-                                       show_session_dialog ();
-                               }
+                               _signal_response (ExitProgram);
                        }
+               default:
+                       /* ERROR */
                        break;
+               }
+               break;
 
+       case WaitingForSessionPath:
+               switch (dialog_id) {
                case NewSessionDialog:
                        switch (response) {
                        case RESPONSE_OK:
                        case RESPONSE_ACCEPT:
-                               csp = check_session_parameters (new_session_required);
-                               std::cerr << "csp = " << csp << std::endl;
-                               switch (csp) {
+                               switch (check_session_parameters (new_session_required)) {
                                case -1:
                                        /* Unrecoverable error */
                                        _signal_response (ExitProgram);
                                        break;
+                               case 0:
+                                       end_dialog (&session_dialog);
+                                       start_audio_midi_setup ();
+                                       break;
                                case 1:
                                        /* do nothing - keep dialog up for a
                                         * retry. Errors were addressed by
                                         * ::check_session_parameters()
                                         */
                                        break;
-                               case 0:
-                                       _state = NeedEngineParams;
-                                       session_dialog->hide ();
-                                       delete session_dialog;
-                                       session_dialog = 0;
-                                       current_dialog_connection.disconnect();
-                                       if (!session_is_new && session_existing_sample_rate > 0) {
-                                               audiomidi_dialog.set_desired_sample_rate (session_existing_sample_rate);
-                                       }
-                                       show_audiomidi_dialog ();
-                                       break;
                                }
                                break;
 
@@ -223,19 +269,17 @@ StartupFSM::dialog_response_handler (int response, StartupFSM::DialogID dialog_i
                }
                break;
 
-       case NeedEngineParams:
+       case WaitingForEngineParams:
                switch (dialog_id) {
                case AudioMIDISetup:
-                       std::cerr << "AMS done, r = " << response << std::endl;
                        switch (response) {
                        case RESPONSE_OK:
                        case RESPONSE_ACCEPT:
-                               audiomidi_dialog.hide ();
-                               current_dialog_connection.disconnect();
-                               /* fallthru */
-                       case RESPONSE_DELETE_EVENT:
                                if (AudioEngine::instance()->running()) {
-                                       _signal_response (LoadSession);
+                                       end_dialog (audiomidi_dialog);
+                                       engine_running ();
+                               } else {
+                                       /* just keep going */
                                }
                                break;
                        default:
@@ -246,35 +290,194 @@ StartupFSM::dialog_response_handler (int response, StartupFSM::DialogID dialog_i
                        /* ERROR */
                        break;
                }
-
-       case NeedWizard:
-               /* ERROR */
                break;
+
+       case WaitingForPlugins:
+               switch (dialog_id) {
+               case PluginDialog:
+                       end_dialog (&plugin_scan_dialog);
+                       switch (response) {
+                       case RESPONSE_OK:
+                               _signal_response (LoadSession);
+                               break;
+                       default:
+                               _signal_response (ExitProgram);
+                               break;
+                       }
+               default:
+                       /* ERROR */
+                       break;
+               }
        }
 }
 
 void
-StartupFSM::show_new_user_wizard ()
+StartupFSM::handle_waiting_for_session_path ()
 {
-       new_user_wizard = new NewUserWizard;
-       current_dialog_connection = new_user_wizard->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), NewUserDialog));
-       new_user_wizard->present ();
+       if (ARDOUR_COMMAND_LINE::session_name.empty()) {
+
+               /* nothing given on the command line ... show new session dialog */
+
+               show_session_dialog (new_session_required);
+
+       } else {
+
+               if (get_session_parameters_from_command_line (new_session_required)) {
+
+                       /* command line arguments all OK. Get engine parameters */
+
+                       if (!new_session_required && session_existing_sample_rate > 0) {
+                               audiomidi_dialog.set_desired_sample_rate (session_existing_sample_rate);
+                       }
+
+                       start_audio_midi_setup ();
+
+               } else {
+
+                       /* command line arguments not good. Use
+                        * dialog, but prime the dialog with
+                        * the information we set up in
+                        * get_session_parameters_from_command_line()
+                        */
+
+                       show_session_dialog (new_session_required);
+               }
+       }
+}
+
+void
+StartupFSM::show_plugin_scan_dialog ()
+{
+       set_state (WaitingForPlugins);
+
+       /* if the user does not ask to discover VSTs at startup, or if this is Mixbus, then the plugin scan
+          that we run here, during startup, should only use the existing plugin cache (if any).
+       */
+
+       const bool cache_only = (!Config->get_discover_vst_on_start() || Profile->get_mixbus());
+       const bool verbose = new_user;
+
+       plugin_scan_dialog = new PluginScanDialog (cache_only, verbose);
+       current_dialog_connection = plugin_scan_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), PluginDialog));
+       plugin_scan_dialog->set_position (WIN_POS_CENTER);
+
+       /* We don't show the plugin scan dialog by default. It will appear using it's own code if/when plugins are discovered, if required.
+        *
+        * See also comments in PluginScanDialog::start() to understand the absurd complexities behind this call.
+        */
+
+       DEBUG_TRACE (DEBUG::GuiStartup, string_compose ("starting plugin dialog, cache only ? %1\n", !Config->get_discover_vst_on_start()));
+       plugin_scan_dialog->start();
+       DEBUG_TRACE (DEBUG::GuiStartup, "plugin dialog done\n");
 }
 
 void
-StartupFSM::show_session_dialog ()
+StartupFSM::show_new_user_dialog ()
 {
+       set_state (WaitingForNewUser);
+       new_user_dialog = new NewUserWizard;
+       current_dialog_connection = new_user_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), NewUserDialog));
+       new_user_dialog->set_position (WIN_POS_CENTER);
+       new_user_dialog->present ();
+}
+
+void
+StartupFSM::show_session_dialog (bool new_session_required)
+{
+       set_state (WaitingForSessionPath);
+       session_dialog = new SessionDialog (new_session_required, session_name, session_path, session_template, false);
        current_dialog_connection = session_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), NewSessionDialog));
+       session_dialog->set_position (WIN_POS_CENTER);
        session_dialog->present ();
 }
 
 void
 StartupFSM::show_audiomidi_dialog ()
 {
+       set_state (WaitingForEngineParams);
        current_dialog_connection = audiomidi_dialog.signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), AudioMIDISetup));
+       audiomidi_dialog.set_position (WIN_POS_CENTER);
        audiomidi_dialog.present ();
 }
 
+void
+StartupFSM::start_audio_midi_setup ()
+{
+       bool setup_required = false;
+
+       if (AudioEngine::instance()->current_backend() == 0) {
+               /* backend is unknown ... */
+               setup_required = true;
+
+       } else if (session_is_new && AudioEngine::instance()->running() && AudioEngine::instance()->sample_rate () == session_existing_sample_rate) {
+               /* keep engine */
+
+               warning << "A running engine should not be possible at this point" << endmsg;
+
+       } else if (AudioEngine::instance()->setup_required()) {
+               /* backend is known, but setup is needed */
+               setup_required = true;
+
+       } else if (!AudioEngine::instance()->running()) {
+               /* should always be true during startup */
+               if (AudioEngine::instance()->start()) {
+                       setup_required = true;
+               }
+       }
+
+       if (setup_required) {
+
+               if (!session_is_new && (Config->get_try_autostart_engine () || g_getenv ("ARDOUR_TRY_AUTOSTART_ENGINE"))) {
+
+                       AudioEngine::instance()->set_sample_rate(session_existing_sample_rate);
+                       if (!AudioEngine::instance()->start ()) {
+                               if (ARDOUR::AudioEngine::instance()->running()) {
+                                       DEBUG_TRACE (DEBUG::GuiStartup, "autostart successful, audio/MIDI setup dialog not required\n");
+                                       engine_running ();
+                                       return;
+                               }
+                       }
+               }
+
+               if (!session_is_new && session_existing_sample_rate > 0) {
+                       audiomidi_dialog.set_desired_sample_rate (session_existing_sample_rate);
+               }
+
+               show_audiomidi_dialog ();
+               DEBUG_TRACE (DEBUG::GuiStartup, "audiomidi shown and waiting\n");
+
+       } else {
+
+               DEBUG_TRACE (DEBUG::GuiStartup, "engine already running, audio/MIDI setup dialog not required\n");
+               engine_running ();
+       }
+}
+
+void
+StartupFSM::engine_running ()
+{
+       DEBUG_TRACE (DEBUG::GuiStartup, "engine running, start plugin scan then attach UI to engine\n");
+
+       /* This may be very slow. See comments in PluginScanDialog::start() */
+       show_plugin_scan_dialog ();
+
+       DEBUG_TRACE (DEBUG::GuiStartup, "attach UI to engine\n");
+
+       /* This may be very slow: it will run the GUI's post-engine
+          initialization which is essentially unbounded in time/scope of what
+          it can do.
+       */
+
+       ARDOUR_UI::instance()->attach_to_engine ();
+
+       /* now that we've done the plugin scan AND attached the UI to the engine, we can
+          proceed with the next (final) steps of startup. This uses the same response
+          signal mechanism we use for the other dialogs.
+       */
+
+       plugin_scan_dialog->response (RESPONSE_OK);
+}
+
 bool
 StartupFSM::get_session_parameters_from_command_line (bool new_session_required)
 {
@@ -291,6 +494,8 @@ StartupFSM::get_session_parameters_from_path (string const & path, string const
 
        if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS)) {
 
+               session_is_new = false;
+
                if (new_session_required) {
                        /* wait! it already exists */
 
@@ -306,14 +511,18 @@ StartupFSM::get_session_parameters_from_path (string const & path, string const
                if (Glib::file_test (path.c_str(), Glib::FILE_TEST_IS_REGULAR)) {
                        /* session/snapshot file, change path to be dir */
                        session_path = Glib::path_get_dirname (path);
+               } else {
+                       session_path = path;
                }
 
                float sr;
                SampleFormat fmt;
                string program_version;
 
-               if (Session::get_info_from_path (session_path, sr, fmt, program_version)) {
-                       /* exists but we can't read it */
+               const string statefile_path = Glib::build_filename (session_path, session_name + ARDOUR::statefile_suffix);
+               if (Session::get_info_from_path (statefile_path, sr, fmt, program_version)) {
+                       /* exists but we can't read it correctly */
+                       error << string_compose (_("Cannot get existing session information from %1"), statefile_path) << endmsg;
                        return false;
                }
 
@@ -335,6 +544,7 @@ StartupFSM::get_session_parameters_from_path (string const & path, string const
                session_path = Glib::build_filename (Config->get_default_session_parent_dir (), session_name);
        } else {
                session_name = basename_nosuffix (path);
+               session_path = path;
        }
 
 
@@ -389,6 +599,15 @@ StartupFSM::get_session_parameters_from_path (string const & path, string const
         */
 
        session_existing_sample_rate = 0;
+       session_is_new = true;
+
+       /* this is an arbitrary default value but since the user insists on
+        * starting a new session from the command line, it will do as well as
+        * any other possible value. I mean, seriously, what else could it be
+        * by default?
+        */
+
+       bus_profile.master_out_channels = 2;
 
        return true;
 }
@@ -416,7 +635,7 @@ StartupFSM::check_session_parameters (bool must_be_new)
 
                int rv = ARDOUR::inflate_session (session_name, Config->get_default_session_parent_dir(), session_path, session_name);
                if (rv < 0) {
-                       MessageDialog msg (*session_dialog, string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
+                       ArdourMessageDialog msg (*session_dialog, string_compose (_("Extracting session-archive failed: %1"), inflate_error (rv)));
                        msg.run ();
 
                        return 1;
@@ -483,10 +702,10 @@ StartupFSM::check_session_parameters (bool must_be_new)
        const char illegal = Session::session_name_is_legal (session_name);
 
        if (illegal) {
-               MessageDialog msg (*session_dialog,
-                                  string_compose (_("To ensure compatibility with various systems\n"
-                                                    "session names may not contain a '%1' character"),
-                                                  illegal));
+               ArdourMessageDialog msg (*session_dialog,
+                                        string_compose (_("To ensure compatibility with various systems\n"
+                                                          "session names may not contain a '%1' character"),
+                                                        illegal));
                msg.run ();
                ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
                return 1; /* keep running dialog */
@@ -516,8 +735,7 @@ StartupFSM::check_session_parameters (bool must_be_new)
                /* does not exist at present */
 
                if (!requested_new) {
-                       // pop_back_splash (session_dialog);
-                       MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
+                       ArdourMessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
                        msg.run ();
                        session_dialog->clear_name();
                        return 1;
@@ -529,13 +747,21 @@ StartupFSM::check_session_parameters (bool must_be_new)
        float sr;
        SampleFormat fmt;
        string program_version;
+       const string statefile_path = Glib::build_filename (session_path, session_name + ARDOUR::statefile_suffix);
 
-       if (!session_is_new && Session::get_info_from_path (session_path, sr, fmt, program_version)) {
-               /* exists but we can't read it */
-               return -1;
-       }
+       if (!session_is_new) {
 
-       session_existing_sample_rate = sr;
+               if (Session::get_info_from_path (statefile_path, sr, fmt, program_version)) {
+                       /* exists but we can't read it */
+                       return -1;
+               }
+
+               session_existing_sample_rate = sr;
+
+       } else {
+
+               bus_profile.master_out_channels = session_dialog->master_channel_count ();
+       }
 
        return 0;
 }
@@ -586,55 +812,17 @@ StartupFSM::copy_demo_sessions ()
 void
 StartupFSM::load_from_application_api (const std::string& path)
 {
-       /* macOS El Capitan (and probably later) now somehow passes the command
-          line arguments to an app via the openFile delegate protocol. Ardour
-          already does its own command line processing, and having both
-          pathways active causes crashes. So, if the command line was already
-          set, do nothing here.
-       */
-
        if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
                return;
        }
 
-       /* Cancel SessionDialog if it's visible to make macOS delegates work.
-        *
-        * there's a race condition here: we connect to app->ShouldLoad
-        * and then at some point (might) show a session dialog. The race is
-        * caused by the non-deterministic interaction between the macOS event
-        * loop(s) and the GDK one(s).
-        *
-        *  - ShouldLoad does not arrive before we show the session dialog
-        *          -> here we should hide the session dialog, then use the
-        *             supplied path as if it was provided on the command line
-        *  - ShouldLoad signal arrives before we show a session dialog
-        *          -> don't bother showing the session dialog, just use the
-        *             supplied path as if it was provided on the command line
-        *
+       /* just set this as if it was given on the command line, rather than
+        * supplied via some desktop system (e.g. macOS application delegate
+        * and "openFile". Note that this relies on this being invoked before
+        * StartupFSM::start().
         */
 
-       if (session_dialog) {
-               session_dialog->hide ();
-               delete_when_idle (session_dialog);
-               session_dialog = 0;
-       }
-
-       /* no command line argument given ... must just be via
-        * desktop/finder/window manager API (e.g. double click on "foo.ardour"
-        * icon)
-        */
-
-       if (get_session_parameters_from_path (path, string(), false)) {
-               _signal_response (LoadSession);
-               return;
-       }
-
-       /* given parameters failed for some reason. This is probably true
-        * anyway, but force it to be true and then carry on with whatever the
-        * main event loop is doing.
-        */
-
-       _state = NeedSessionPath;
+       ARDOUR_COMMAND_LINE::session_name = path;
 }
 
 bool
@@ -642,18 +830,17 @@ StartupFSM::ask_about_loading_existing_session (const std::string& session_path)
 {
        std::string str = string_compose (_("This session\n%1\nalready exists. Do you want to open it?"), session_path);
 
-       MessageDialog msg (str,
-                          false,
-                          Gtk::MESSAGE_WARNING,
-                          Gtk::BUTTONS_YES_NO,
-                          true);
+       ArdourMessageDialog msg (str,
+                                false,
+                                Gtk::MESSAGE_WARNING,
+                                Gtk::BUTTONS_YES_NO,
+                                true);
 
 
        msg.set_name (X_("OpenExistingDialog"));
        msg.set_title (_("Open Existing Session"));
        msg.set_wmclass (X_("existing_session"), PROGRAM_NAME);
        msg.set_position (Gtk::WIN_POS_CENTER);
-       // pop_back_splash (msg);
 
        switch (msg.run()) {
        case RESPONSE_YES:
@@ -662,3 +849,41 @@ StartupFSM::ask_about_loading_existing_session (const std::string& session_path)
        }
        return false;
 }
+
+void
+StartupFSM::show_pre_release_dialog ()
+{
+       pre_release_dialog = new ArdourDialog  (_("Pre-Release Warning"), true, false);
+       pre_release_dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
+
+       Label* label = manage (new Label);
+       label->set_markup (string_compose (_("<span size=\"x-large\" weight=\"bold\">Welcome to this pre-release build of %1 %2</span>\n\n\
+<span size=\"large\">There are still several issues and bugs to be worked on,\n\
+as well as general workflow improvements, before this can be considered\n\
+release software. So, a few guidelines:\n\
+\n\
+1) Please do <b>NOT</b> use this software with the expectation that it is stable or reliable\n\
+   though it may be so, depending on your workflow.\n\
+2) Please wait for a helpful writeup of new features.\n\
+3) <b>Please do NOT use the forums at ardour.org to report issues</b>.\n\
+4) <b>Please do NOT file bugs for this alpha-development versions at this point in time</b>.\n\
+   There is no bug triaging before the initial development concludes and\n\
+   reporting issue for incomplete, ongoing work-in-progress is mostly useless.\n\
+5) Please <b>DO</b> join us on IRC for real time discussions about %1 %2. You\n\
+   can get there directly from within the program via the Help->Chat menu option.\n\
+6) Please <b>DO</b> submit patches for issues after discussing them on IRC.\n\
+\n\
+Full information on all the above can be found on the support page at\n\
+\n\
+                http://ardour.org/support</span>\n\
+"), PROGRAM_NAME, VERSIONSTRING));
+
+
+       current_dialog_connection = pre_release_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (this, &StartupFSM::dialog_response_handler), PreReleaseDialog));
+
+       pre_release_dialog->get_vbox()->set_border_width (12);
+       pre_release_dialog->get_vbox()->pack_start (*label, false, false, 12);
+       pre_release_dialog->get_vbox()->show_all ();
+       pre_release_dialog->set_position (WIN_POS_CENTER);
+       pre_release_dialog->present ();
+}