#include "prompter.h"
#include "opts.h"
#include "add_route_dialog.h"
-#include "new_session_dialog.h"
#include "about.h"
#include "splash.h"
#include "utils.h"
#include "session_metadata_dialog.h"
#include "gain_meter.h"
#include "route_time_axis.h"
+#include "startup.h"
+#include "engine_dialog.h"
#include "i18n.h"
about = 0;
splash = 0;
-
- if (ARDOUR_COMMAND_LINE::session_name.length()) {
- /* only show this if we're not going to post the new session dialog */
- show_splash ();
- }
+ _startup = 0;
if (theArdourUI == 0) {
theArdourUI = this;
session_selector_window = 0;
last_key_press_time = 0;
_will_create_new_session_automatically = false;
- new_session_dialog = 0;
add_route_dialog = 0;
route_params = 0;
- option_editor = 0;
+ rc_option_editor = 0;
+ session_option_editor = 0;
location_ui = 0;
open_session_selector = 0;
have_configure_timeout = false;
}
setup_gtk_ardour_enums ();
- Config->set_current_owner (ConfigVariableBase::Interface);
setup_profile ();
GainMeter::setup_slider_pix ();
platform_setup ();
}
+void
+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();
+
+ /* we don't return here until the startup assistant is finished */
+
+ _startup->hide ();
+}
+
int
ARDOUR_UI::create_engine ()
{
blink_timeout_tag = -1;
- /* the global configuration object is now valid */
-
- use_config ();
-
/* this being a GUI and all, we want peakfiles */
AudioFileSource::set_build_peakfiles (true);
delete editor;
delete mixer;
delete add_route_dialog;
- delete new_session_dialog;
}
void
XMLNode* node = new XMLNode (keyboard->get_state());
Config->add_extra_xml (*node);
Config->add_extra_xml (get_transport_controllable_state());
- if (new_session_dialog && new_session_dialog->engine_control.was_used()) {
- Config->add_extra_xml (new_session_dialog->engine_control.get_state());
+ if (_startup && _startup->engine_control() && _startup->engine_control()->was_used()) {
+ Config->add_extra_xml (_startup->engine_control()->get_state());
}
Config->save_state();
ui_config->save_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);
void
ARDOUR_UI::startup ()
{
- string name, path;
-
- new_session_dialog = new NewSessionDialog();
-
- bool backend_audio_is_running = EngineControl::engine_running();
XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
- if (audio_setup) {
- new_session_dialog->engine_control.set_state (*audio_setup);
+ 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);
}
+
+ use_config ();
+
+ goto_editor_window ();
BootMessage (_("Ardour is ready for use"));
show ();
ARDOUR_UI::update_buffer_load ()
{
char buf[64];
+ uint32_t c, p;
if (session) {
+ c = session->capture_load ();
+ p = session->playback_load ();
+
+ push_buffer_stats (c, p);
+
snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"),
session->playback_load(), session->capture_load());
buffer_load_label.set_text (buf);
}
}
-void
-ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg)
-{
- snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[
- (int) adj.get_value()].c_str());
-}
-
void
ARDOUR_UI::engine_stopped ()
{
switch (prompter.run()) {
case RESPONSE_ACCEPT:
+ {
prompter.get_result (snapname);
- if (snapname.length()){
+
+ bool do_save = (snapname.length() != 0);
+
+ vector<sys::path> p;
+ get_state_files_in_directory (session->session_directory().root_path(), p);
+ vector<string> n = get_file_names_no_extension (p);
+ if (find (n.begin(), n.end(), snapname) != n.end()) {
+
+ ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
+ Label m (_("A snapshot already exists with that name. Do you want to overwrite it?"));
+ confirm.get_vbox()->pack_start (m, true, true);
+ confirm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ confirm.add_button (_("Overwrite"), Gtk::RESPONSE_ACCEPT);
+ confirm.show_all ();
+ switch (confirm.run()) {
+ case RESPONSE_CANCEL:
+ do_save = false;
+ }
+ }
+
+ if (do_save) {
save_state (snapname);
}
break;
+ }
default:
break;
if (session == 0) {
return;
}
+
+ Session::RecordState const r = session->record_status ();
+ bool const h = session->have_rec_enabled_diskstream ();
- switch (session->record_status()) {
- case Session::Enabled:
+ if (r == Session::Enabled || (r == Session::Recording && !h)) {
if (onoff) {
rec_button.set_visual_state (2);
} else {
rec_button.set_visual_state (0);
}
- break;
-
- case Session::Recording:
+ } else if (r == Session::Recording && h) {
rec_button.set_visual_state (1);
- break;
-
- default:
+ } else {
rec_button.set_visual_state (0);
- break;
}
}
Glib::ustring fontconfig = Glib::build_filename (Glib::get_home_dir(), ".fontconfig");
if (!Glib::file_test (fontconfig, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
- MessageDialog msg (*new_session_dialog,
+ MessageDialog msg (*_startup,
_("Welcome to Ardour.\n\n"
"The program will take a bit longer to start up\n"
"while the system fonts are checked.\n\n"
/* lets just try to load it */
if (create_engine ()) {
- backend_audio_error (false, new_session_dialog);
+ backend_audio_error (false, _startup);
return -1;
}
/* get settings from advanced section of NSD */
- if (new_session_dialog->create_control_bus()) {
- cchns = (uint32_t) new_session_dialog->control_channel_count();
+ if (_startup->create_control_bus()) {
+ cchns = (uint32_t) _startup->control_channel_count();
} else {
cchns = 0;
}
- if (new_session_dialog->create_master_bus()) {
- mchns = (uint32_t) new_session_dialog->master_channel_count();
+ if (_startup->create_master_bus()) {
+ mchns = (uint32_t) _startup->master_channel_count();
} else {
mchns = 0;
}
- if (new_session_dialog->connect_inputs()) {
+ if (_startup->connect_inputs()) {
iconnect = AutoConnectPhysical;
} else {
iconnect = AutoConnectOption (0);
/// @todo some minor tweaks.
- if (new_session_dialog->connect_outs_to_master()) {
+ if (_startup->connect_outs_to_master()) {
oconnect = AutoConnectMaster;
- } else if (new_session_dialog->connect_outs_to_physical()) {
+ } else if (_startup->connect_outs_to_physical()) {
oconnect = AutoConnectPhysical;
} else {
oconnect = AutoConnectOption (0);
}
- nphysin = (uint32_t) new_session_dialog->input_limit_count();
- nphysout = (uint32_t) new_session_dialog->output_limit_count();
+ nphysin = (uint32_t) _startup->input_limit_count();
+ nphysout = (uint32_t) _startup->output_limit_count();
}
if (build_session (session_path,
void
ARDOUR_UI::loading_message (const std::string& msg)
{
- show_splash ();
- splash->message (msg);
+ // show_splash ();
+ // splash->message (msg);
flush_pending ();
}
-void
-ARDOUR_UI::idle_load (const Glib::ustring& path)
-{
- if (session) {
- if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
- /* /path/to/foo => /path/to/foo, foo */
- load_session (path, basename_nosuffix (path));
- } else {
- /* /path/to/foo/foo.ardour => /path/to/foo, foo */
- load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
- }
- } else {
-
- ARDOUR_COMMAND_LINE::session_name = path;
-
- if (new_session_dialog) {
-
-
- /* make it break out of Dialog::run() and
- start again.
- */
-
- new_session_dialog->response (1);
- }
- }
-}
-
-/** @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;
- begin:
- response = Gtk::RESPONSE_NONE;
+ while (ret != 0) {
- if (!ARDOUR_COMMAND_LINE::session_name.empty()) {
+ if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
- parse_cmdline_path (ARDOUR_COMMAND_LINE::session_name, session_name, session_path, existing_session);
-
- /* don't ever reuse this */
-
- ARDOUR_COMMAND_LINE::session_name = string();
-
- if (existing_session && backend_audio_is_running) {
-
- /* just load the thing already */
+ /* if they named a specific statefile, use it, otherwise they are
+ just giving a session folder, and we want to use it as is
+ to find the session.
+ */
- if (load_cmdline_session (session_name, session_path, existing_session) == 0) {
- return true;
+ if (ARDOUR_COMMAND_LINE::session_name.find (statefile_suffix) != string::npos) {
+ session_path = Glib::path_get_dirname (ARDOUR_COMMAND_LINE::session_name);
+ } else {
+ session_path = ARDOUR_COMMAND_LINE::session_name;
}
- }
-
- /* make the NSD use whatever information we have */
-
- new_session_dialog->set_session_name (session_name);
- new_session_dialog->set_session_folder (session_path);
- }
-
- /* loading failed, or we need the NSD for something */
- new_session_dialog->set_modal (false);
- new_session_dialog->set_position (WIN_POS_CENTER);
- new_session_dialog->set_current_page (0);
- new_session_dialog->set_existing_session (existing_session);
- new_session_dialog->reset_recent();
- new_session_dialog->set_offer_cancel (offer_cancel);
+ session_name = Glib::path_get_basename (ARDOUR_COMMAND_LINE::session_name);
- do {
- new_session_dialog->set_have_engine (backend_audio_is_running);
- new_session_dialog->present ();
- end_loading_messages ();
- response = new_session_dialog->run ();
-
- _session_is_new = false;
-
- /* handle possible negative responses */
-
- switch (response) {
- case 1:
- /* sent by idle_load, meaning restart the whole process again */
- new_session_dialog->hide();
- new_session_dialog->reset();
- goto begin;
- break;
+ } else {
- case Gtk::RESPONSE_CANCEL:
- case Gtk::RESPONSE_DELETE_EVENT:
- if (!session) {
- if (engine && engine->running()) {
- engine->stop (true);
- }
- quit();
- }
- new_session_dialog->hide ();
- return false;
+ run_startup (should_be_new);
- case Gtk::RESPONSE_NONE:
- /* "Clear" was pressed */
- goto try_again;
- }
-
- fontconfig_dialog();
-
- if (!backend_audio_is_running) {
- int ret = new_session_dialog->engine_control.setup_engine ();
- if (ret < 0) {
- return false;
- } else if (ret > 0) {
- response = Gtk::RESPONSE_REJECT;
- goto try_again;
- }
- }
-
- if (create_engine ()) {
-
- backend_audio_error (!backend_audio_is_running, new_session_dialog);
- flush_pending ();
-
- new_session_dialog->set_existing_session (false);
- new_session_dialog->set_current_page (2);
-
- response = Gtk::RESPONSE_NONE;
- goto try_again;
- }
-
- backend_audio_is_running = true;
+ /* 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 (response == Gtk::RESPONSE_OK) {
-
- session_name = new_session_dialog->session_name();
-
if (session_name.empty()) {
- response = Gtk::RESPONSE_NONE;
- goto try_again;
+ break;
+ }
+ if (_startup->use_session_template()) {
+ template_name = _startup->session_template_name();
+ _session_is_new = true;
}
- /* 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 = new_session_dialog->session_folder();
+
+ session_path = _startup->session_folder();
}
+ }
- template_name = Glib::ustring();
- switch (new_session_dialog->which_page()) {
+ if (create_engine ()) {
+ break;
+ }
+
+ if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) {
- case NewSessionDialog::OpenPage:
- case NewSessionDialog::EnginePage:
- goto loadit;
- break;
+ if (likely_new) {
- case NewSessionDialog::NewPage: /* nominally the "new" session creator, but could be in use for an old session */
+ Glib::ustring existing = Glib::build_filename (session_path, session_name);
- should_be_new = true;
-
- //XXX This is needed because session constructor wants a
- //non-existant path. hopefully this will be fixed at some point.
-
- 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 (!ask_about_loading_existing_session (existing)) {
+ ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
+ continue;
+ }
+ }
- _session_is_new = true;
-
- if (new_session_dialog->use_session_template()) {
+ _session_is_new = false;
- template_name = new_session_dialog->session_template_name();
- goto loadit;
-
- } else {
- if (build_session_from_nsd (session_path, session_name)) {
- response = RESPONSE_NONE;
- goto try_again;
- }
- goto done;
- }
- break;
-
- default:
- break;
- }
-
- loadit:
- new_session_dialog->hide ();
+ } else {
- if (load_session (session_path, session_name, template_name)) {
- /* force a retry */
- response = Gtk::RESPONSE_NONE;
+ if (!likely_new) {
+ MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path));
+ msg.run ();
+ ARDOUR_COMMAND_LINE::session_name = ""; // cancel that
+ continue;
}
- try_again:
- if (response == Gtk::RESPONSE_NONE) {
- new_session_dialog->set_existing_session (false);
- new_session_dialog->reset ();
- }
+ _session_is_new = true;
}
- } while (response == Gtk::RESPONSE_NONE || response == Gtk::RESPONSE_REJECT);
+ if (likely_new && template_name.empty()) {
+
+ ret = build_session_from_nsd (session_path, session_name);
- done:
- show();
- new_session_dialog->hide();
- new_session_dialog->reset();
- goto_editor_window ();
- return true;
+ } else {
+
+ ret = load_session (session_path, session_name, template_name);
+ }
+ }
+
+ return ret;
}
void
unload_session (true);
- get_session_parameters (true, false);
+ get_session_parameters (false);
}
int
connect_to_session (new_session);
- Config->set_current_owner (ConfigVariableBase::Interface);
-
session_loaded = true;
goto_editor_window ();
}
}
+void
+ARDOUR_UI::push_buffer_stats (uint32_t capture, uint32_t playback)
+{
+ time_t now;
+ time (&now);
+
+ while (disk_buffer_stats.size() > 60) {
+ disk_buffer_stats.pop_front ();
+ }
+
+ disk_buffer_stats.push_back (DiskBufferStat (now, capture, playback));
+}
+
+void
+ARDOUR_UI::write_buffer_stats ()
+{
+ struct tm tm;
+ char buf[64];
+ char* path;
+
+ char* tmplt = (char*)calloc(strlen("ardourXXXXXX"), sizeof(char));
+ int fd = mkstemp (tmplt);
+ if (fd) {
+ cerr << X_("cannot find temporary name for ardour buffer stats") << endl;
+ return;
+ }
+
+ FILE* fout = fdopen (fd, "w");
+ if (!fout) {
+ cerr << string_compose (X_("cannot open file %1 for ardour buffer stats"), path) << endl;
+ return;
+ }
+
+ for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
+ std::ostringstream ss;
+ localtime_r (&(*i).when, &tm);
+ strftime (buf, sizeof (buf), "%T", &tm);
+ fprintf(fout, "%s %u %u\n", buf, (*i).capture, (*i).playback);
+ }
+
+ disk_buffer_stats.clear ();
+
+ fclose (fout);
+ close (fd);
+
+ cerr << "Ardour buffering statistics can be found in: " << path << endl;
+ free (path);
+ free (tmplt);
+}
+
void
ARDOUR_UI::disk_overrun_handler ()
{
ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler));
+ write_buffer_stats ();
+
if (!have_disk_speed_dialog_displayed) {
have_disk_speed_dialog_displayed = true;
MessageDialog* msg = new MessageDialog (*editor, _("\
{
ENSURE_GUI_THREAD (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler));
+ write_buffer_stats ();
+
if (!have_disk_speed_dialog_displayed) {
have_disk_speed_dialog_displayed = true;
MessageDialog* msg = new MessageDialog (*editor,
{
Glib::RefPtr<Action> act;
- switch (Config->get_native_file_data_format ()) {
+ assert (session);
+
+ switch (session->config.get_native_file_data_format ()) {
case FormatFloat:
act = ActionManager::get_action (X_("options"), X_("FileDataFormatFloat"));
break;
ract->set_active ();
}
- switch (Config->get_native_file_header_format ()) {
+ switch (session->config.get_native_file_header_format ()) {
case BWF:
act = ActionManager::get_action (X_("options"), X_("FileHeaderFormatBWF"));
break;
return;
}
- switch (session->record_status()) {
- case Session::Recording:
+ Session::RecordState const r = session->record_status ();
+ bool const h = session->have_rec_enabled_diskstream ();
+
+ if (r == Session::Recording && h) {
big_clock.set_widget_name ("BigClockRecording");
- break;
- default:
+ } else {
big_clock.set_widget_name ("BigClockNonRecording");
- break;
}
}