#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/click_box.h"
#include "gtkmm2ext/fastmeter.h"
-#include "gtkmm2ext/stop_signal.h"
#include "gtkmm2ext/popup.h"
#include "gtkmm2ext/window_title.h"
last_shuttle_request = last_peak_grab = 0; // get_microseconds();
- ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
- ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
+ ARDOUR::Diskstream::DiskOverrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_overrun_handler, this), gui_context());
+ ARDOUR::Diskstream::DiskUnderrun.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::disk_underrun_handler, this), gui_context());
/* handle dialog requests */
- ARDOUR::Session::Dialog.connect (forever_connections, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
+ ARDOUR::Session::Dialog.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::session_dialog, this, _1), gui_context());
/* handle pending state with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
/** @return true if a session was chosen and `apply' clicked, otherwise false if `cancel' was clicked */
bool
-ARDOUR_UI::run_startup (bool should_be_new)
+ARDOUR_UI::run_startup (bool should_be_new, string load_template)
{
if (_startup == 0) {
_startup = new ArdourStartup ();
}
+
+ XMLNode* audio_setup = Config->extra_xml ("AudioSetup");
+
+ if (audio_setup && _startup->engine_control()) {
+ _startup->engine_control()->set_state (*audio_setup);
+ }
_startup->set_new_only (should_be_new);
+ if (!load_template.empty()) {
+ _startup->set_load_template( load_template );
+ }
_startup->present ();
main().run();
loading_message (_("Starting audio engine"));
try {
- engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name);
+ engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid);
} catch (...) {
return -1;
}
- engine->Stopped.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
- engine->Running.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
- engine->Halted.connect (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this), gui_context());
- engine->SampleRateChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
+ engine->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context());
+ engine->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context());
+ engine->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context());
+
+ engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false));
+
+ ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports);
post_engine ();
update_cpu_load ();
update_sample_rate (engine->frame_rate());
- Config->ParameterChanged.connect (forever_connections, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
+ Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, ui_bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context());
boost::function<void (string)> pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1));
Config->map_parameters (pc);
void
ARDOUR_UI::startup ()
{
- 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 (true, ARDOUR_COMMAND_LINE::new_session)) {
+ if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) {
exit (1);
}
ARDOUR_UI::finish()
{
if (_session) {
+ int tries = 0;
- if (_session->transport_rolling()) {
- _session->request_stop ();
- usleep (250000);
+ if (_session->transport_rolling() && (++tries < 8)) {
+ _session->request_stop (false, true);
+ usleep (10000);
}
if (_session->dirty()) {
_session = 0;
}
- ArdourDialog::close_all_dialogs ();
- engine->stop (true);
cerr << "Save before quit\n";
save_ardour_state ();
+
+ ArdourDialog::close_all_dialogs ();
+ engine->stop (true);
quit ();
}
int
ARDOUR_UI::ask_about_saving_session (const string & what)
{
- ArdourDialog window (_("ardour: save session?"));
+ ArdourDialog window (_("Unsaved Session"));
Gtk::HBox dhbox; // the hbox for the image and text
Gtk::Label prompt_label;
Gtk::Image* dimage = manage (new Gtk::Image(Stock::DIALOG_WARNING, Gtk::ICON_SIZE_DIALOG));
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);
ARDOUR_UI::count_recenabled_streams (Route& route)
{
Track* track = dynamic_cast<Track*>(&route);
- if (track && track->diskstream()->record_enabled()) {
+ if (track && track->record_enabled()) {
rec_enabled_streams += track->n_inputs().n_total();
}
}
}
}
}
-
-#if CONTROLOUTS
- if (need_control_room_outs) {
- pan_t pans[2];
-
- pans[0] = 0.5;
- pans[1] = 0.5;
-
- route->set_stereo_control_outs (control_lr_channels);
- route->control_outs()->set_stereo_pan (pans, this);
- }
-#endif /* CONTROLOUTS */
}
catch (...) {
return;
}
- _session->request_stop ();
+ _session->request_stop (false, true);
}
void
ARDOUR_UI::transport_stop_and_forget_capture ()
{
if (_session) {
- _session->request_stop (true);
+ _session->request_stop (true, true);
}
}
bool rolling = _session->transport_rolling();
if (_session->get_play_loop()) {
- _session->request_play_loop (false, true);
+ /* XXX it is not possible to just leave seamless loop and keep
+ playing at present (nov 4th 2009)
+ */
+ if (!Config->get_seamless_loop()) {
+ _session->request_play_loop (false, true);
+ }
} else if (_session->get_play_range () && !join_play_range_button.get_active()) {
/* stop playing a range if we currently are */
_session->request_play_range (0, true);
if (!rolling) {
_session->request_transport_speed (1.0f);
}
-
- map_transport_state ();
}
void
_session->request_play_loop (false, true);
} else if (_session->get_play_range ()) {
affect_transport = false;
- _session->request_play_range (0, true);
+ _session->request_play_range (0, true);
}
}
_session->request_transport_speed (1.0f);
}
}
-
- map_transport_state ();
}
void
Track* t;
if ((t = dynamic_cast<Track*>(r.get())) != 0) {
- t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
+ t->set_record_enabled (!t->record_enabled());
}
}
if (_session == 0) {
play_selection_button.set_visual_state (0);
auto_loop_button.set_visual_state (0);
}
-
}
void
}
void
-ARDOUR_UI::engine_halted ()
+ARDOUR_UI::engine_halted (const char* reason, bool free_reason)
{
- ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_halted)
+ if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
+ /* we can't rely on the original string continuing to exist when we are called
+ again in the GUI thread, so make a copy and note that we need to
+ free it later.
+ */
+ char *copy = strdup (reason);
+ Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&ARDOUR_UI::engine_halted, this, copy, true));
+ return;
+ }
ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false);
ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true);
update_sample_rate (0);
- MessageDialog msg (*editor,
- _("\
+ string msgstr;
+
+ /* if the reason is a non-empty string, it means that the backend was shutdown
+ rather than just Ardour.
+ */
+
+ if (strlen (reason)) {
+ msgstr = string_compose (_("The audio backend (JACK) was shutdown because:\n\n%1"), reason);
+ } else {
+ msgstr = _("\
JACK has either been shutdown or it\n\
disconnected Ardour because Ardour\n\
was not fast enough. Try to restart\n\
-JACK, reconnect and save the session."));
+JACK, reconnect and save the session.");
+ }
+
+ MessageDialog msg (*editor, msgstr);
pop_back_splash ();
msg.run ();
+
+ if (free_reason) {
+ free ((char*) reason);
+ }
}
int32_t
/** Ask the user for the name of a new shapshot and then take it.
*/
+
void
-ARDOUR_UI::snapshot_session ()
+ARDOUR_UI::snapshot_session (bool switch_to_it)
{
ArdourPrompter prompter (true);
string snapname;
- char timebuf[128];
- time_t n;
- struct tm local_time;
-
- time (&n);
- localtime_r (&n, &local_time);
- strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
prompter.set_name ("Prompter");
prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
prompter.set_title (_("Take Snapshot"));
- prompter.set_prompt (_("Name of New Snapshot"));
- prompter.set_initial_text (timebuf);
+ prompter.set_title (_("Take Snapshot"));
+ prompter.set_prompt (_("Name of new snapshot"));
+
+ if (!switch_to_it) {
+ char timebuf[128];
+ time_t n;
+ struct tm local_time;
+
+ time (&n);
+ localtime_r (&n, &local_time);
+ strftime (timebuf, sizeof(timebuf), "%FT%T", &local_time);
+ prompter.set_initial_text (timebuf);
+ }
again:
switch (prompter.run()) {
vector<string> n = get_file_names_no_extension (p);
if (find (n.begin(), n.end(), snapname) != n.end()) {
- ArdourDialog confirm (_("Confirm snapshot overwrite"), true);
+ 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);
}
if (do_save) {
- save_state (snapname);
+ save_state (snapname, switch_to_it);
}
break;
}
}
void
-ARDOUR_UI::save_state (const string & name)
+ARDOUR_UI::save_state (const string & name, bool switch_to_it)
{
- save_state_canfail (name);
+ save_state_canfail (name, switch_to_it);
}
int
-ARDOUR_UI::save_state_canfail (string name)
+ARDOUR_UI::save_state_canfail (string name, bool switch_to_it)
{
if (_session) {
int ret;
name = _session->snap_name();
}
- if ((ret = _session->save_state (name)) != 0) {
+ if ((ret = _session->save_state (name, false, switch_to_it)) != 0) {
return ret;
}
}
}
Session::RecordState const r = _session->record_status ();
- bool const h = _session->have_rec_enabled_diskstream ();
+ bool const h = _session->have_rec_enabled_track ();
if (r == Session::Enabled || (r == Session::Recording && !h)) {
if (onoff) {
int
ARDOUR_UI::build_session_from_nsd (const Glib::ustring& session_path, const Glib::ustring& session_name)
{
-
- uint32_t mchns;
- AutoConnectOption iconnect;
- AutoConnectOption oconnect;
- uint32_t nphysin;
- uint32_t nphysout;
+ BusProfile bus_profile;
if (Profile->get_sae()) {
- mchns = 2;
- iconnect = AutoConnectPhysical;
- oconnect = AutoConnectMaster;
- nphysin = 0; // use all available
- nphysout = 0; // use all available
+ bus_profile.master_out_channels = 2;
+ bus_profile.input_ac = AutoConnectPhysical;
+ bus_profile.output_ac = AutoConnectMaster;
+ bus_profile.requested_physical_in = 0; // use all available
+ bus_profile.requested_physical_out = 0; // use all available
} else {
/* get settings from advanced section of NSD */
if (_startup->create_master_bus()) {
- mchns = (uint32_t) _startup->master_channel_count();
+ bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count();
} else {
- mchns = 0;
+ bus_profile.master_out_channels = 0;
}
if (_startup->connect_inputs()) {
- iconnect = AutoConnectPhysical;
+ bus_profile.input_ac = AutoConnectPhysical;
} else {
- iconnect = AutoConnectOption (0);
+ bus_profile.input_ac = AutoConnectOption (0);
}
/// @todo some minor tweaks.
-
- oconnect = AutoConnectOption (0);
+
+ bus_profile.output_ac = AutoConnectOption (0);
if (_startup->connect_outputs ()) {
if (_startup->connect_outs_to_master()) {
- oconnect = AutoConnectMaster;
+ bus_profile.output_ac = AutoConnectMaster;
} else if (_startup->connect_outs_to_physical()) {
- oconnect = AutoConnectPhysical;
+ bus_profile.output_ac = AutoConnectPhysical;
}
}
- nphysin = (uint32_t) _startup->input_limit_count();
- nphysout = (uint32_t) _startup->output_limit_count();
+ bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count();
+ bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count();
}
- if (build_session (session_path,
- session_name,
- mchns,
- iconnect,
- oconnect,
- nphysin,
- nphysout,
- engine->frame_rate() * 60 * 5)) {
-
+ if (build_session (session_path, session_name, bus_profile)) {
return -1;
}
/** @param quit_on_cancel true if exit() should be called if the user clicks `cancel' in the new session dialog */
int
-ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new)
+ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, string load_template)
{
Glib::ustring session_name;
Glib::ustring session_path;
int ret = -1;
bool likely_new = false;
+ if (! load_template.empty()) {
+ should_be_new = true;
+ template_name = load_template;
+ }
+
while (ret != 0) {
if (!should_be_new && !ARDOUR_COMMAND_LINE::session_name.empty()) {
} else {
- bool const apply = run_startup (should_be_new);
+ bool const apply = run_startup (should_be_new, load_template);
if (!apply) {
if (quit_on_cancel) {
exit (1);
loading_message (string_compose (_("Please wait while %1loads your session"), PROGRAM_NAME));
try {
- new_session = new Session (*engine, path, snap_name, mix_template);
+ new_session = new Session (*engine, path, snap_name, 0, mix_template);
}
/* this one is special */
}
int
-ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name,
- uint32_t master_channels,
- AutoConnectOption input_connect,
- AutoConnectOption output_connect,
- uint32_t nphysin,
- uint32_t nphysout,
- nframes_t initial_length)
+ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_name, BusProfile& bus_profile)
{
Session *new_session;
int x;
_session_is_new = true;
try {
- new_session = new Session (*engine, path, snap_name, input_connect, output_connect,
- master_channels, nphysin, nphysout, initial_length);
+ new_session = new Session (*engine, path, snap_name, &bus_profile);
}
catch (...) {
return;
}
- ArdourDialog results (_("ardour: cleanup"), true, false);
+ ArdourDialog results (_("Clean-up"), true, false);
struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord {
CleanupResultsModelColumns() {
}
}
-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 ()
-{
- std::ofstream fout;
- struct tm tm;
- char buf[64];
- char path[PATH_MAX+1]; int fd;
-
- strcpy (path, "ardourBufferingXXXXXX");
-
- if ((fd = mkstemp (path )) < 0) {
- cerr << X_("cannot find temporary name for buffer stats") << endl;
- return;
- }
-
- fout.open (path);
- close (fd);
-
- if (!fout) {
- cerr << string_compose (X_("cannot open file %1 for buffer stats"), path) << endl;
- return;
- }
-
- for (list<DiskBufferStat>::iterator i = disk_buffer_stats.begin(); i != disk_buffer_stats.end(); ++i) {
- localtime_r (&(*i).when, &tm);
- strftime (buf, sizeof (buf), "%T", &tm);
- fout << buf << ' ' << (*i).capture << ' ' << (*i).playback << endl;
- }
-
- disk_buffer_stats.clear ();
-
- fout.close ();
-
- cerr << "buffering statistics can be found in: " << path << endl;
-}
-
void
ARDOUR_UI::disk_overrun_handler ()
{
ENSURE_GUI_THREAD (*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 (*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,
}
Session::RecordState const r = _session->record_status ();
- bool const h = _session->have_rec_enabled_diskstream ();
+ bool const h = _session->have_rec_enabled_track ();
if (r == Session::Recording && h) {
big_clock.set_widget_name ("BigClockRecording");