13
0

add initial version of StartupFSM along with its owners/users

This commit is contained in:
Paul Davis 2019-10-09 20:50:34 -06:00
parent dd29e9b0e9
commit 18b4a4213f
6 changed files with 836 additions and 73 deletions

View File

@ -301,6 +301,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
, _mixer_on_top (false)
, _initial_verbose_plugin_scan (false)
, _shared_popup_menu (0)
, startup_fsm (0)
, secondary_clock_spacer (0)
, auto_input_button (ArdourButton::led_default_elements)
, latency_disable_button (ArdourButton::led_default_elements)

View File

@ -91,6 +91,7 @@
#include "enums.h"
#include "mini_timeline.h"
#include "shuttle_control.h"
#include "startup_fsm.h"
#include "transport_control.h"
#include "transport_control_ui.h"
#include "visibility_group.h"
@ -223,6 +224,7 @@ public:
int get_session_parameters (bool quit_on_cancel, bool should_be_new = false, std::string load_template = "");
int build_session_from_dialog (SessionDialog&, const std::string& session_name, const std::string& session_path);
bool ask_about_loading_existing_session (const std::string& session_path);
void load_session_from_startup_fsm ();
/// @return true if session was successfully unloaded.
int unload_session (bool hide_stuff = false);
@ -438,8 +440,12 @@ private:
static ARDOUR_UI *theArdourUI;
SessionDialog *_session_dialog;
StartupFSM* startup_fsm;
int starting ();
int nsm_init ();
void startup_done ();
void sfsm_response (StartupFSM::Result);
int ask_about_saving_session (const std::vector<std::string>& actions);

View File

@ -57,7 +57,6 @@
#include "ardour/filename_extensions.h"
#include "ardour/filesystem_paths.h"
#include "ardour/profile.h"
#include "ardour/recent_sessions.h"
#include "gtkmm2ext/application.h"
@ -480,27 +479,37 @@ ARDOUR_UI::nsm_init ()
return 0;
}
void
ARDOUR_UI::sfsm_response (StartupFSM::Result r)
{
switch (r) {
case StartupFSM::ExitProgram:
queue_finish ();
break;
case StartupFSM::LoadSession:
_initial_verbose_plugin_scan = false;
load_session_from_startup_fsm ();
break;
case StartupFSM::DoNothing:
break;
}
}
int
ARDOUR_UI::starting ()
{
Application* app = Application::instance ();
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.
*/
EngineControl* amd;
try {
audio_midi_setup.get (true);
amd = dynamic_cast<EngineControl*> (audio_midi_setup.get (true));
} catch (...) {
std::cerr << "audio-midi engine setup failed."<< std::endl;
return -1;
@ -510,68 +519,53 @@ ARDOUR_UI::starting ()
return -1;
} else {
if (brand_new_user) {
startup_fsm = new StartupFSM (*amd);
startup_fsm->start ();
startup_fsm->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::sfsm_response));
if (startup_fsm->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 (...) {}
}
}
/* go get a session */
const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || (!ARDOUR::Profile->get_mixbus() && 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;
}
}
return 0;
}
void
ARDOUR_UI::load_session_from_startup_fsm ()
{
string session_path = startup_fsm->session_path;
string session_name = startup_fsm->session_name;
string session_template = startup_fsm->session_template;
bool session_is_new = startup_fsm->session_is_new;
BusProfile bus_profile = startup_fsm->bus_profile;
std::cerr << " loading from " << session_path << " as " << session_name << " templ " << session_template << " is_new " << session_is_new << " bp " << bus_profile.master_out_channels << std::endl;
if (session_is_new) {
if (build_session (session_path, session_name, &bus_profile)) {
}
if (!session_template.empty() && session_template.substr (0, 11) == "urn:ardour:") {
meta_session_setup (session_template.substr (11));
}
} else {
int ret = load_session (session_path, session_name, session_template);
if (ret == -2) {
/* not connected to the AudioEngine, so quit to avoid an infinite loop */
exit (EXIT_FAILURE);
}
}
}
void
ARDOUR_UI::startup_done ()
{
use_config ();
WM::Manager::instance().show_visible ();
@ -582,10 +576,6 @@ ARDOUR_UI::starting ()
_status_bar_visibility.update ();
BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME));
/* all other dialogs are created conditionally */
return 0;
}
void

662
gtk2_ardour/startup_fsm.cc Normal file
View File

@ -0,0 +1,662 @@
/*
* Copyright (C) 2019 Paul Davis <paul@linuxaudiosystems.com>
*
* 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.
*/
#include <vector>
#include <gtkmm/dialog.h>
#include <gtkmm/liststore.h>
#include <gtkmm/messagedialog.h>
#include "pbd/basename.h"
#include "pbd/file_archive.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 "ardour/rc_configuration.h"
#include "ardour/search_paths.h"
#include "ardour/session.h"
#include "ardour/session_utils.h"
#include "ardour/template_utils.h"
#include "gtkmm2ext/application.h"
#include <gtkmm2ext/doi.h>
#include "engine_dialog.h"
#include "new_user_wizard.h"
#include "opts.h"
#include "session_dialog.h"
#include "startup_fsm.h"
using namespace ARDOUR;
using namespace Gtk;
using namespace Gtkmm2ext;
using namespace PBD;
using std::string;
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)
, audiomidi_dialog (amd)
, session_dialog (0)
{
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 ();
}
StartupFSM::~StartupFSM ()
{
delete session_dialog;
}
void
StartupFSM::queue_finish ()
{
_signal_response (ExitProgram);
}
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);
}
}
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;
std::cerr << "SFSM state = " << _state << " r = " << response << " did " << dialog_id << std::endl;
switch (_state) {
case NeedSessionPath:
switch (dialog_id) {
case NewUserDialog:
current_dialog_connection.disconnect ();
delete_when_idle (new_user_wizard);
switch (response) {
case RESPONSE_OK:
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 ();
}
}
break;
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) {
case -1:
/* Unrecoverable error */
_signal_response (ExitProgram);
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;
default:
_signal_response (ExitProgram);
break;
}
break;
default:
/* ERROR */
break;
}
break;
case NeedEngineParams:
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);
}
break;
default:
_signal_response (ExitProgram);
}
break;
default:
/* ERROR */
break;
}
case NeedWizard:
break;
case NeedSessionSR:
break;
case NeedEngine:
break;
}
}
void
StartupFSM::show_new_user_wizard ()
{
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 ();
}
void
StartupFSM::show_session_dialog ()
{
current_dialog_connection = session_dialog->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), NewSessionDialog));
session_dialog->present ();
}
void
StartupFSM::show_audiomidi_dialog ()
{
current_dialog_connection = audiomidi_dialog.signal_response().connect (sigc::bind (sigc::mem_fun (*this, &StartupFSM::dialog_response_handler), AudioMIDISetup));
audiomidi_dialog.present ();
}
bool
StartupFSM::get_session_parameters_from_command_line (bool new_session_required)
{
return get_session_parameters_from_path (ARDOUR_COMMAND_LINE::session_name, ARDOUR_COMMAND_LINE::load_template, new_session_required);
}
bool
StartupFSM::get_session_parameters_from_path (string const & path, string const & template_name, bool new_session_required)
{
if (path.empty()) {
/* use GUI to ask the user */
return false;
}
if (Glib::file_test (path.c_str(), Glib::FILE_TEST_EXISTS)) {
if (new_session_required) {
/* wait! it already exists */
if (!ask_about_loading_existing_session (path)) {
return false;
} else {
/* load it anyway */
}
}
session_name = basename_nosuffix (path);
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);
}
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 */
return false;
}
session_existing_sample_rate = sr;
return true;
}
/* Everything after this involves a new session
*
* ... did the user give us a path or just a name?
*/
if (path.find (G_DIR_SEPARATOR) == string::npos) {
/* user gave session name with no path info, use
default session folder.
*/
session_name = ARDOUR_COMMAND_LINE::session_name;
session_path = Glib::build_filename (Config->get_default_session_parent_dir (), session_name);
} else {
session_name = basename_nosuffix (path);
}
if (!template_name.empty()) {
/* Allow the user to specify a template via path or name on the
* command line
*/
bool have_resolved_template_name = false;
/* compare by name (path may or may not be UTF-8) */
vector<TemplateInfo> templates;
find_session_templates (templates, false);
for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
if ((*x).name == template_name) {
session_template = (*x).path;
have_resolved_template_name = true;
break;
}
}
/* look up script by name */
LuaScriptList scripts (LuaScripting::instance ().scripts (LuaScriptInfo::SessionInit));
LuaScriptList& as (LuaScripting::instance ().scripts (LuaScriptInfo::EditorAction));
for (LuaScriptList::const_iterator s = as.begin(); s != as.end(); ++s) {
if ((*s)->subtype & LuaScriptInfo::SessionSetup) {
scripts.push_back (*s);
}
}
std::sort (scripts.begin(), scripts.end(), LuaScripting::Sorter());
for (LuaScriptList::const_iterator s = scripts.begin(); s != scripts.end(); ++s) {
if ((*s)->name == template_name) {
session_template = "urn:ardour:" + (*s)->path;
have_resolved_template_name = true;
break;
}
}
if (!have_resolved_template_name) {
/* this will produce a more or less meaninful error later:
* "ERROR: Could not open session template [abs-path to user-config dir]"
*/
session_template = Glib::build_filename (ARDOUR::user_template_directory (), template_name);
}
}
/* We don't know what this is, because the session is new and the
* command line doesn't let us specify it. The user will get to decide
* in the audio/MIDI dialog.
*/
session_existing_sample_rate = 0;
return true;
}
/** return values:
* -1: failure
* 1: failure but user can retry
* 0: success, seesion parameters ready for use
*/
int
StartupFSM::check_session_parameters (bool must_be_new)
{
bool requested_new = false;
session_name = session_dialog->session_name (requested_new);
session_path = session_dialog->session_folder ();
if (must_be_new) {
assert (requested_new);
}
if (!must_be_new) {
/* See if the specified session is a session archive */
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)));
msg.run ();
return 1;
} else if (rv == 0) {
/* names are good (and session is unarchived/inflated */
return 0;
}
}
/* check for ".ardour" in statefile name, because we don't want
* it
*
* XXX Note this wierd conflation of a
* file-name-without-a-suffix and the session name. It's not
* really a session name at all, but rather the suffix-free
* name of a statefile (snapshot).
*/
const string::size_type suffix_at = session_name.find (statefile_suffix);
if (suffix_at != string::npos) {
session_name = session_name.substr (0, suffix_at);
}
/* this shouldn't happen, but we catch it just in case it does */
if (session_name.empty()) {
return 1; /* keep running dialog */
}
if (session_dialog->use_session_template()) {
session_template = session_dialog->session_template_name();
}
if (session_name[0] == G_DIR_SEPARATOR ||
#ifdef PLATFORM_WINDOWS
// Windows file system .. detect absolute path
// C:/*
(session_name.length() > 3 && session_name[1] == ':' && session_name[2] == G_DIR_SEPARATOR)
#else
// Sensible file systems
// /* or ./* or ../*
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == G_DIR_SEPARATOR) ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == G_DIR_SEPARATOR)
#endif
)
{
/* user typed absolute path or cwd-relative path
specified into session name field. So ... infer
session path and name from what was given.
*/
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);
} else {
/* session name is just a name */
}
/* check if name is legal */
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));
msg.run ();
ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
return 1; /* keep running dialog */
}
/* check if the currently-exists status matches whether or not
* it should be new
*/
if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
if (requested_new /*&& !nsm*/) {
std::string existing = Glib::build_filename (session_path, session_name);
if (!ask_about_loading_existing_session (existing)) {
session_dialog->clear_name ();
return 1; /* try again */
}
}
session_is_new = false;
} else {
/* 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));
msg.run ();
session_dialog->clear_name();
return 1;
}
session_is_new = true;
}
float sr;
SampleFormat fmt;
string program_version;
if (!session_is_new && Session::get_info_from_path (session_path, sr, fmt, program_version)) {
/* exists but we can't read it */
return -1;
}
session_existing_sample_rate = sr;
return 0;
}
void
StartupFSM::copy_demo_sessions ()
{
// 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 (...) {
/* relax ? */
}
}
}
}
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
*
*/
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;
}
bool
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);
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:
return true;
break;
}
return false;
}

103
gtk2_ardour/startup_fsm.h Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2019 Paul Davis <paul@linuxaudiosystems.com>
*
* 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.
*/
#ifndef __gtk2_ardour_startup_fsm_h__
#define __gtk2_ardour_startup_fsm_h__
#include <string>
#include <sigc++/trackable.h>
#include "ardour/types.h"
class NewUserWizard;
class EngineControl;
class SessionDialog;
class StartupFSM : public sigc::trackable
{
public:
enum DialogID {
NewUserDialog,
NewSessionDialog,
AudioMIDISetup
};
enum Result {
LoadSession,
ExitProgram,
DoNothing, /* seriously? how can this be an option */
};
StartupFSM (EngineControl&);
~StartupFSM ();
void start ();
std::string session_path;
std::string session_name;
std::string session_template;
int session_existing_sample_rate;
bool session_is_new;
ARDOUR::BusProfile bus_profile;
/* It's not a dialog but we provide this to make it behave like a (non-modal)
* dialog
*/
sigc::signal1<void,Result>& signal_response() { return _signal_response; }
bool brand_new_user() const { return new_user; }
private:
enum MainState {
NeedWizard,
NeedSessionPath,
NeedSessionSR,
NeedEngineParams,
NeedEngine
};
bool new_user;
bool new_session;
MainState _state;
void dialog_response_handler (int response, DialogID);
void show_new_user_wizard ();
void show_session_dialog ();
void show_audiomidi_dialog ();
void copy_demo_sessions ();
void load_from_application_api (std::string const &);
bool get_session_parameters_from_command_line (bool new_session_required);
bool get_session_parameters_from_path (std::string const & path, std::string const & template_name, bool new_session_required);
void queue_finish ();
bool ask_about_loading_existing_session (const std::string& session_path);
int check_session_parameters (bool must_be_new);
NewUserWizard* new_user_wizard;
EngineControl& audiomidi_dialog;
SessionDialog* session_dialog;
sigc::connection current_dialog_connection;
sigc::signal1<void,Result> _signal_response;
};
#endif /* __gtk2_ardour_startup_fsm_h__ */

View File

@ -175,6 +175,7 @@ gtk2_ardour_sources = [
'mouse_cursors.cc',
'nag.cc',
'new_plugin_preset_dialog.cc',
'new_user_wizard.cc',
'normalize_dialog.cc',
'note.cc',
'note_base.cc',
@ -251,7 +252,7 @@ gtk2_ardour_sources = [
'soundcloud_export_selector.cc',
'splash.cc',
'speaker_dialog.cc',
'startup.cc',
'startup_fsm.cc',
'step_editor.cc',
'step_entry.cc',
'stereo_panner.cc',