a long tricky day of playing with ArdourStartup and session naming/loading etc.

git-svn-id: svn://localhost/ardour2/branches/3.0@4995 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-04-22 01:35:31 +00:00
parent 0d36301907
commit c287ebec9b
11 changed files with 316 additions and 147 deletions

View file

@ -313,7 +313,7 @@ AddRouteDialog::track_template ()
string str = track_template_combo.get_active_text();
for (vector<RouteTemplateInfo>::iterator x = route_templates.begin(); x != route_templates.end(); ++x) {
for (vector<TemplateInfo>::iterator x = route_templates.begin(); x != route_templates.end(); ++x) {
if ((*x).name == str) {
return (*x).path;
}
@ -337,7 +337,7 @@ AddRouteDialog::refill_track_templates ()
if (!route_templates.empty()) {
vector<string> v;
for (vector<RouteTemplateInfo>::iterator x = route_templates.begin(); x != route_templates.end(); ++x) {
for (vector<TemplateInfo>::iterator x = route_templates.begin(); x != route_templates.end(); ++x) {
v.push_back ((*x).name);
}
set_popdown_strings (track_template_combo, v);

View file

@ -62,7 +62,7 @@ class AddRouteDialog : public Gtk::Dialog
Gtk::ComboBoxText track_mode_combo;
Gtk::ComboBoxText track_template_combo;
std::vector<ARDOUR::RouteTemplateInfo> route_templates;
std::vector<ARDOUR::TemplateInfo> route_templates;
void track_type_chosen ();
void refill_track_templates ();

View file

@ -277,12 +277,13 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[])
}
void
ARDOUR_UI::run_startup ()
ARDOUR_UI::run_startup (bool should_be_new)
{
if (_startup == 0) {
_startup = new ArdourStartup ();
}
_startup->set_new_only (should_be_new);
_startup->present ();
main().run();
@ -537,7 +538,7 @@ ARDOUR_UI::save_ardour_state ()
if (session) {
session->add_instant_xml (enode);
session->add_instant_xml (mnode);
session->add_instant_xml (mnode);
} else {
Config->add_instant_xml (enode);
Config->add_instant_xml (mnode);
@ -644,18 +645,17 @@ Please consider the possibilities, and perhaps (re)start JACK."));
void
ARDOUR_UI::startup ()
{
string name, path;
bool backend_audio_is_running = EngineControl::engine_running();
XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
if (audio_setup && _startup && _startup->engine_control()) {
_startup->engine_control()->set_state (*audio_setup);
}
if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
return;
if (get_session_parameters (ARDOUR_COMMAND_LINE::new_session)) {
exit (1);
}
goto_editor_window ();
BootMessage (_("Ardour is ready for use"));
show ();
@ -2232,91 +2232,96 @@ ARDOUR_UI::loading_message (const std::string& msg)
flush_pending ();
}
/** @param offer_quit true to offer a Cancel button, otherwise call it Quit */
bool
ARDOUR_UI::get_session_parameters (bool backend_audio_is_running, bool should_be_new, bool offer_cancel)
int
ARDOUR_UI::get_session_parameters (bool should_be_new)
{
bool existing_session = false;
Glib::ustring session_name;
Glib::ustring session_path;
Glib::ustring template_name;
int response;
int ret = -1;
bool likely_new = false;
_session_is_new = false;
while (ret != 0) {
session_name = _startup->session_name (should_be_new);
if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
if (session_name.empty()) {
response = Gtk::RESPONSE_NONE;
goto try_again;
}
/* if the user mistakenly typed path information into the session filename entry,
convert what they typed into a path & a name
*/
if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);
} else {
session_path = _startup->session_folder();
}
template_name = Glib::ustring();
session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
} else {
if (create_engine ()) {
/* FAIL */
}
if (should_be_new) {
run_startup (should_be_new);
/* if we run the startup dialog again, offer more than just "new session" */
should_be_new = false;
session_name = _startup->session_name (likely_new);
/* this shouldn't happen, but we catch it just in case it does */
if (session_name.empty()) {
break;
}
if (_startup->use_session_template()) {
template_name = _startup->session_template_name();
_session_is_new = true;
}
//XXX This is needed because session constructor wants a
//non-existant path. hopefully this will be fixed at some point.
if (session_name[0] == '/' ||
(session_name.length() > 2 && session_name[0] == '.' && session_name[1] == '/') ||
(session_name.length() > 3 && session_name[0] == '.' && session_name[1] == '.' && session_name[2] == '/')) {
session_path = Glib::path_get_dirname (session_name);
session_name = Glib::path_get_basename (session_name);
} else {
session_path = _startup->session_folder();
}
}
if (create_engine ()) {
break;
}
session_path = Glib::build_filename (session_path, session_name);
if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
if (ask_about_loading_existing_session (session_path)) {
goto loadit;
} else {
response = RESPONSE_NONE;
goto try_again;
if (likely_new) {
if (!ask_about_loading_existing_session (session_path)) {
continue;
}
}
}
_session_is_new = true;
if (_startup->use_session_template()) {
template_name = _startup->session_template_name();
goto loadit;
_session_is_new = false;
} else {
if (build_session_from_nsd (session_path, session_name)) {
response = RESPONSE_NONE;
goto try_again;
}
goto done;
}
}
loadit:
if (load_session (session_path, session_name, template_name)) {
/* force a retry */
if (!likely_new) {
MessageDialog msg (string_compose (_("There is no existing session called \"%1\""),
ARDOUR_COMMAND_LINE::session_name));
msg.run ();
ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
continue;
}
_session_is_new = true;
}
if (likely_new && template_name.empty()) {
ret = build_session_from_nsd (session_path, session_name);
} else {
ret = load_session (session_path, session_name, template_name);
}
}
try_again:
done:
goto_editor_window ();
return true;
return ret;
}
void
@ -2328,7 +2333,7 @@ ARDOUR_UI::close_session()
unload_session (true);
get_session_parameters (true, false);
get_session_parameters (false);
}
int

View file

@ -110,7 +110,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
ARDOUR_UI (int *argcp, char **argvp[]);
~ARDOUR_UI();
void run_startup ();
void run_startup (bool should_be_new);
void show ();
bool shown() { return shown_flag; }
@ -144,8 +144,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
void set_will_create_new_session_automatically (bool yn) {
_will_create_new_session_automatically = yn;
}
bool get_session_parameters (bool have_engine = false, bool should_be_new = false, bool offer_quit = false);
int get_session_parameters (bool should_be_new = false);
void parse_cmdline_path (const Glib::ustring& cmdline_path, Glib::ustring& session_name, Glib::ustring& session_path, bool& existing_session);
int load_cmdline_session (const Glib::ustring& session_name, const Glib::ustring& session_path, bool& existing_session);
int build_session_from_nsd (const Glib::ustring& session_name, const Glib::ustring& session_path);

View file

@ -107,7 +107,7 @@ ARDOUR_UI::install_actions ()
/* the real actions */
act = ActionManager::register_action (main_actions, X_("New"), _("New..."), hide_return (bind (mem_fun(*this, &ARDOUR_UI::get_session_parameters), true, true, true)));
act = ActionManager::register_action (main_actions, X_("New"), _("New..."), hide_return (bind (mem_fun(*this, &ARDOUR_UI::get_session_parameters), true)));
ActionManager::register_action (main_actions, X_("Open"), _("Open..."), mem_fun(*this, &ARDOUR_UI::open_session));
ActionManager::register_action (main_actions, X_("Recent"), _("Recent..."), mem_fun(*this, &ARDOUR_UI::open_recent_session));

View file

@ -382,8 +382,6 @@ int main (int argc, char *argv[])
exit (1);
}
ui->run_startup ();
ui->run (text_receiver);
ui = 0;

View file

@ -1231,7 +1231,7 @@ RouteUI::save_as_template ()
p.get_result (name, true);
safe_name = legalize_for_path (name);
safe_name += temp_suffix;
safe_name += template_suffix;
path /= safe_name;

View file

@ -7,6 +7,7 @@
#include "pbd/failed_constructor.h"
#include "pbd/file_utils.h"
#include "pbd/filesystem.h"
#include "pbd/replace_all.h"
#include "ardour/filesystem_paths.h"
#include "ardour/recent_sessions.h"
@ -15,6 +16,7 @@
#include "ardour/template_utils.h"
#include "startup.h"
#include "opts.h"
#include "engine_dialog.h"
#include "i18n.h"
@ -27,6 +29,14 @@ using namespace ARDOUR;
ArdourStartup* ArdourStartup::the_startup = 0;
static string poor_mans_glob (string path)
{
string copy = path;
replace_all (copy, "~", Glib::get_home_dir());
return copy;
}
ArdourStartup::ArdourStartup ()
: applying (false)
, ic_new_session_button (_("Open a new session"))
@ -50,11 +60,15 @@ Ardour will play NO role in monitoring"))
session_page_index = -1;
final_page_index = -1;
session_options_page_index = -1;
new_only = false;
engine_dialog = 0;
config_modified = false;
default_dir_chooser = 0;
use_template_button.set_group (session_template_group);
use_session_as_template_button.set_group (session_template_group);
set_keep_above (true);
set_position (WIN_POS_CENTER);
@ -74,7 +88,8 @@ Ardour will play NO role in monitoring"))
sys::path been_here_before = user_config_directory();
been_here_before /= ".a3"; // XXXX use more specific version so we can catch upgrades
bool new_user = !exists (been_here_before);
new_user = !exists (been_here_before);
bool need_audio_setup = !EngineControl::engine_running();
if (new_user) {
@ -111,6 +126,44 @@ ArdourStartup::~ArdourStartup ()
{
}
void
ArdourStartup::set_new_only (bool yn)
{
new_only = yn;
if (new_only) {
ic_vbox.hide ();
} else {
ic_vbox.show ();
}
}
bool
ArdourStartup::use_session_template ()
{
if (use_template_button.get_active()) {
return template_chooser.get_active_row_number() != 0;
} else {
return !session_template_chooser.get_filename().empty();
}
}
Glib::ustring
ArdourStartup::session_template_name ()
{
string ret;
if (use_template_button.get_active()) {
TreeModel::iterator iter = template_chooser.get_active ();
TreeModel::Row row = (*iter);
string s = row[session_template_columns.path];
return s;
} else {
return session_template_chooser.get_filename();
}
}
Glib::ustring
ArdourStartup::session_name (bool& should_be_new)
{
@ -226,14 +279,7 @@ Where would you like new Ardour sessions to be stored by default?\n\
vbox->pack_start (*txt, false, true);
vbox->pack_start (*hbox1, false, true);
string def = Config->get_default_session_parent_dir();
/* XXX really need glob here */
if (def == "~") {
def = Glib::get_home_dir();
}
default_dir_chooser->set_current_folder (def);
default_dir_chooser->set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
default_dir_chooser->signal_current_folder_changed().connect (mem_fun (*this, &ArdourStartup::default_dir_changed));
default_dir_chooser->show ();
@ -408,6 +454,25 @@ ArdourStartup::on_prepare (Gtk::Widget* page)
}
}
void
ArdourStartup::populate_session_templates ()
{
vector<TemplateInfo> templates;
find_session_templates (templates);
template_model->clear ();
for (vector<TemplateInfo>::iterator x = templates.begin(); x != templates.end(); ++x) {
TreeModel::Row row;
row = *(template_model->append ());
row[session_template_columns.name] = (*x).name;
row[session_template_columns.path] = (*x).path;
}
}
void
ArdourStartup::setup_new_session_page ()
{
@ -417,6 +482,8 @@ ArdourStartup::setup_new_session_page ()
if (session_new_vbox.get_children().empty()) {
session_new_vbox.set_spacing (12);
HBox* hbox1 = manage (new HBox);
Label* label1 = manage (new Label);
@ -429,10 +496,20 @@ ArdourStartup::setup_new_session_page ()
hbox1->show();
label1->show();
new_name_entry.show ();
if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
new_name_entry.set_text (Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name));
/* name provided - they can move right along */
set_page_complete (session_vbox, true);
}
new_name_entry.signal_changed().connect (mem_fun (*this, &ArdourStartup::new_name_changed));
new_name_entry.signal_activate().connect (mem_fun (*this, &ArdourStartup::move_along_now));
session_new_vbox.pack_start (*hbox1, false, false);
/* --- */
HBox* hbox2 = manage (new HBox);
Label* label2 = manage (new Label);
@ -442,51 +519,79 @@ ArdourStartup::setup_new_session_page ()
label2->set_text (_("Create session folder in:"));
string def = Config->get_default_session_parent_dir();
/* XXX really need glob here */
if (def == "~") {
def = Glib::get_home_dir();
if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
new_folder_chooser.set_current_folder (poor_mans_glob (Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name)));
} else {
new_folder_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
}
new_folder_chooser.set_current_folder (def);
new_folder_chooser.set_title (_("Select folder for session"));
hbox2->show();
label2->show();
new_folder_chooser.show ();
if (is_directory (user_template_directory ())) {
session_template_chooser.set_current_folder (user_template_directory().to_string());
} else if (is_directory (system_template_directory ())) {
session_template_chooser.set_current_folder (system_template_directory().to_string());
} else {
/* hmm, no templates ... what to do? */
session_new_vbox.pack_start (*hbox2, false, false);
/* --- */
template_model = ListStore::create (session_template_columns);
populate_session_templates ();
if (!template_model->children().empty()) {
HBox* hbox3 = manage (new HBox);
use_template_button.set_label (_("Use this template"));
TreeModel::Row row = *template_model->prepend ();
row[session_template_columns.name] = (_("no template"));
row[session_template_columns.path] = string();
hbox3->set_spacing (6);
hbox3->pack_start (use_template_button, false, false);
hbox3->pack_start (template_chooser, true, true);
template_chooser.set_model (template_model);
Gtk::CellRendererText* text_renderer = Gtk::manage (new Gtk::CellRendererText);
text_renderer->property_editable() = false;
template_chooser.pack_start (*text_renderer);
template_chooser.add_attribute (text_renderer->property_text(), session_template_columns.name);
template_chooser.set_active (0);
hbox3->show ();
use_template_button.show();
template_chooser.show ();
session_new_vbox.pack_start (*hbox3, false, false);
}
if (is_directory (system_template_directory ())) {
session_template_chooser.add_shortcut_folder (system_template_directory().to_string());
/* --- */
if (!new_user) {
session_template_chooser.set_current_folder (poor_mans_glob (Config->get_default_session_parent_dir()));
HBox* hbox3a = manage (new HBox);
use_session_as_template_button.set_label (_("Use an existing session as a template:"));
hbox3a->set_spacing (6);
hbox3a->pack_start (use_session_as_template_button, false, false);
hbox3a->pack_start (session_template_chooser, true, true);
hbox3a->show ();
use_session_as_template_button.show ();
session_template_chooser.show ();
Gtk::FileFilter* template_filter = manage (new (Gtk::FileFilter));
template_filter->add_pattern(X_("*.template"));
session_template_chooser.set_filter (*template_filter);
session_template_chooser.set_title (_("Select template"));
session_new_vbox.pack_start (*hbox3a, false, false);
}
HBox* hbox3 = manage (new HBox);
Label* label3 = manage (new Label);
hbox3->set_spacing (6);
hbox3->pack_start (*label3, false, false);
hbox3->pack_start (session_template_chooser, true, true);
label3->set_text (_("Use this template:"));
hbox3->show ();
label3->show ();
session_template_chooser.show ();
Gtk::FileFilter* template_filter = manage (new (Gtk::FileFilter));
template_filter->add_pattern(X_("*.template"));
session_template_chooser.set_filter (*template_filter);
session_template_chooser.set_title (_("Select template"));
/* --- */
HBox* hbox4 = manage (new HBox);
@ -496,11 +601,7 @@ ArdourStartup::setup_new_session_page ()
hbox4->show ();
more_new_session_options_button.show ();
more_new_session_options_button.signal_clicked().connect (mem_fun (*this, &ArdourStartup::more_new_session_options_button_clicked));
session_new_vbox.set_spacing (12);
session_new_vbox.pack_start (*hbox1, false, false);
session_new_vbox.pack_start (*hbox2, false, false);
session_new_vbox.pack_start (*hbox3, false, false);
session_new_vbox.pack_start (*hbox4, false, false);
}

View file

@ -17,6 +17,8 @@
#include <gtkmm/table.h>
#include <gtkmm/frame.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/liststore.h>
#include <gtkmm/combobox.h>
class EngineControl;
@ -25,11 +27,13 @@ class ArdourStartup : public Gtk::Assistant {
ArdourStartup ();
~ArdourStartup ();
void set_new_only (bool);
Glib::ustring session_name (bool& should_be_new);
Glib::ustring session_folder ();
bool use_session_template() { return false; }
Glib::ustring session_template_name() { return ""; }
bool use_session_template();
Glib::ustring session_template_name();
EngineControl* engine_control() { return engine_dialog; }
@ -55,6 +59,8 @@ class ArdourStartup : public Gtk::Assistant {
private:
bool applying;
bool config_modified;
bool new_user;
bool new_only;
void on_apply ();
void on_cancel ();
@ -136,11 +142,30 @@ class ArdourStartup : public Gtk::Assistant {
Gtk::Entry new_name_entry;
Gtk::FileChooserButton new_folder_chooser;
Gtk::FileChooserButton session_template_chooser;
struct SessionTemplateColumns : public Gtk::TreeModel::ColumnRecord {
SessionTemplateColumns () {
add (name);
add (path);
}
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<std::string> path;
};
SessionTemplateColumns session_template_columns;
Glib::RefPtr<Gtk::ListStore> template_model;
Gtk::ComboBox template_chooser;
Gtk::VBox session_new_vbox;
Gtk::CheckButton more_new_session_options_button;
Gtk::RadioButtonGroup session_template_group;
Gtk::RadioButton use_session_as_template_button;
Gtk::RadioButton use_template_button;
void more_new_session_options_button_clicked();
void new_name_changed ();
void populate_session_templates ();
/* more options for new sessions */

View file

@ -17,12 +17,13 @@ namespace ARDOUR {
sys::path user_template_directory ();
sys::path user_route_template_directory ();
struct RouteTemplateInfo {
struct TemplateInfo {
std::string name;
std::string path;
};
void find_route_templates (std::vector<RouteTemplateInfo>& template_names);
void find_route_templates (std::vector<TemplateInfo>& template_names);
void find_session_templates (std::vector<TemplateInfo>& template_names);
} // namespace ARDOUR

View file

@ -2,6 +2,7 @@
#include <cstring>
#include "pbd/filesystem.h"
#include "pbd/basename.h"
#include "pbd/pathscanner.h"
#include "pbd/xml++.h"
@ -62,19 +63,57 @@ user_route_template_directory ()
static bool
template_filter (const string &str, void *arg)
{
return (str.length() > strlen(temp_suffix) &&
str.find (temp_suffix) == (str.length() - strlen (temp_suffix)));
cerr << "Checking into " << str << " using " << template_suffix << endl;
return (str.length() > strlen(template_suffix) &&
str.find (template_suffix) == (str.length() - strlen (template_suffix)));
}
void
find_route_templates (vector<RouteTemplateInfo>& template_names)
find_session_templates (vector<TemplateInfo>& template_names)
{
vector<string *> *templates;
PathScanner scanner;
SearchPath spath (system_data_search_path());
SearchPath spath (system_template_directory());
spath += user_template_directory ();
spath += user_config_directory();
spath.add_subdirectory_to_paths(route_templates_dir_name);
templates = scanner (spath.to_string(), template_filter, 0, false, true);
if (!templates) {
cerr << "Found nothing along " << spath.to_string() << endl;
return;
}
cerr << "Found " << templates->size() << " along " << spath.to_string() << endl;
for (vector<string*>::iterator i = templates->begin(); i != templates->end(); ++i) {
string fullpath = *(*i);
XMLTree tree;
if (!tree.read (fullpath.c_str())) {
continue;
}
XMLNode* root = tree.root();
TemplateInfo rti;
rti.name = basename_nosuffix (fullpath);
rti.path = fullpath;
template_names.push_back (rti);
}
free (templates);
}
void
find_route_templates (vector<TemplateInfo>& template_names)
{
vector<string *> *templates;
PathScanner scanner;
SearchPath spath (system_route_template_directory());
spath += user_route_template_directory ();
templates = scanner (spath.to_string(), template_filter, 0, false, true);
@ -93,7 +132,7 @@ find_route_templates (vector<RouteTemplateInfo>& template_names)
XMLNode* root = tree.root();
RouteTemplateInfo rti;
TemplateInfo rti;
rti.name = IO::name_from_state (*root->children().front());
rti.path = fullpath;
@ -104,4 +143,4 @@ find_route_templates (vector<RouteTemplateInfo>& template_names)
free (templates);
}
} // namespace ARDOUR
}