X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=0a8209fe22c0da90969df7d7742ce2da209ecf4b;hb=51ad790745400eeb38547fa4de842202fec934b8;hp=a6236b2038f5099d0a5a92f91a663caad7190211;hpb=0015553c4a1e24386df60a7a1dc49c2da19794da;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index a6236b2038..0a8209fe22 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -49,7 +49,6 @@ #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" @@ -240,12 +239,12 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) 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) */ @@ -295,13 +294,22 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[]) /** @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(); @@ -328,17 +336,20 @@ ARDOUR_UI::create_engine () 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 (); @@ -413,7 +424,7 @@ ARDOUR_UI::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 pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1)); Config->map_parameters (pc); @@ -636,13 +647,7 @@ Please consider the possibilities, and perhaps (re)start JACK.")); 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); } @@ -726,10 +731,11 @@ void 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()) { @@ -767,17 +773,18 @@ If you still wish to quit, please use the\n\n\ _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)); @@ -918,8 +925,6 @@ ARDOUR_UI::update_buffer_load () 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); @@ -932,7 +937,7 @@ void ARDOUR_UI::count_recenabled_streams (Route& route) { Track* track = dynamic_cast(&route); - if (track && track->diskstream()->record_enabled()) { + if (track && track->record_enabled()) { rec_enabled_streams += track->n_inputs().n_total(); } } @@ -1323,18 +1328,6 @@ ARDOUR_UI::session_add_audio_route (bool track, bool aux, int32_t input_channels } } } - -#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 (...) { @@ -1456,14 +1449,14 @@ ARDOUR_UI::transport_stop () 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); } } @@ -1531,7 +1524,12 @@ ARDOUR_UI::transport_roll () 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); @@ -1544,8 +1542,6 @@ ARDOUR_UI::transport_roll () if (!rolling) { _session->request_transport_speed (1.0f); } - - map_transport_state (); } void @@ -1590,7 +1586,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode) _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); } } @@ -1605,8 +1601,6 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode) _session->request_transport_speed (1.0f); } } - - map_transport_state (); } void @@ -1710,7 +1704,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream) Track* t; if ((t = dynamic_cast(r.get())) != 0) { - t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled()); + t->set_record_enabled (!t->record_enabled()); } } if (_session == 0) { @@ -1780,7 +1774,6 @@ ARDOUR_UI::map_transport_state () play_selection_button.set_visual_state (0); auto_loop_button.set_visual_state (0); } - } void @@ -1843,23 +1836,46 @@ ARDOUR_UI::engine_running () } 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 @@ -1957,24 +1973,29 @@ ARDOUR_UI::stop_blinking () /** 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()) { @@ -2004,7 +2025,7 @@ ARDOUR_UI::snapshot_session () vector 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); @@ -2017,7 +2038,7 @@ ARDOUR_UI::snapshot_session () } if (do_save) { - save_state (snapname); + save_state (snapname, switch_to_it); } break; } @@ -2028,13 +2049,13 @@ ARDOUR_UI::snapshot_session () } 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; @@ -2043,7 +2064,7 @@ ARDOUR_UI::save_state_canfail (string name) name = _session->snap_name(); } - if ((ret = _session->save_state (name)) != 0) { + if ((ret = _session->save_state (name, false, switch_to_it)) != 0) { return ret; } } @@ -2084,7 +2105,7 @@ ARDOUR_UI::transport_rec_enable_blink (bool onoff) } 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) { @@ -2272,62 +2293,49 @@ ARDOUR_UI::ask_about_loading_existing_session (const Glib::ustring& session_path 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; } @@ -2385,7 +2393,7 @@ ARDOUR_UI::loading_message (const std::string& /*msg*/) /** @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; @@ -2393,6 +2401,11 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new) 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()) { @@ -2412,7 +2425,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new) } 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); @@ -2557,7 +2570,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na 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 */ @@ -2632,13 +2645,7 @@ ARDOUR_UI::load_session (const Glib::ustring& path, const Glib::ustring& snap_na } 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; @@ -2660,8 +2667,7 @@ ARDOUR_UI::build_session (const Glib::ustring& path, const Glib::ustring& snap_n _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 (...) { @@ -2781,7 +2787,7 @@ require some unused files to continue to exist.")); return; } - ArdourDialog results (_("ardour: cleanup"), true, false); + ArdourDialog results (_("Clean-up"), true, false); struct CleanupResultsModelColumns : public Gtk::TreeModel::ColumnRecord { CleanupResultsModelColumns() { @@ -3143,62 +3149,11 @@ ARDOUR_UI::xrun_handler(nframes_t where) } } -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::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, _("\ @@ -3217,8 +3172,6 @@ ARDOUR_UI::disk_underrun_handler () { 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, @@ -3401,7 +3354,7 @@ ARDOUR_UI::record_state_changed () } 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");