X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=43fd6bf11f97033b02ba41b9848d04fa64a367df;hb=58eaab0e428823047846c713b623dae923377b95;hp=c138fb1567f7cb84f1ab1fb81256ce96ef73af1e;hpb=e2f0c5f91e2579c41d8efc9495b6ebac31a61ba3;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index c138fb1567..43fd6bf11f 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -21,18 +21,17 @@ #include "gtk2ardour-config.h" #endif -#include - #include #include +#include +#include +#include + +#include #include #include #include #include -#include -#include - -#include #include #include @@ -59,9 +58,8 @@ #include "gtkmm2ext/popup.h" #include "gtkmm2ext/window_title.h" -#include "midi++/manager.h" - #include "ardour/ardour.h" +#include "ardour/audio_backend.h" #include "ardour/audioengine.h" #include "ardour/audiofilesource.h" #include "ardour/automation_watch.h" @@ -88,6 +86,7 @@ typedef uint64_t microseconds_t; #include "ambiguous_file_dialog.h" #include "ardour_ui.h" #include "audio_clock.h" +#include "big_clock_window.h" #include "bundle_manager.h" #include "engine_dialog.h" #include "gain_meter.h" @@ -95,6 +94,7 @@ typedef uint64_t microseconds_t; #include "gui_object.h" #include "gui_thread.h" #include "keyboard.h" +#include "keyeditor.h" #include "location_ui.h" #include "main_clock.h" #include "missing_file_dialog.h" @@ -106,8 +106,12 @@ typedef uint64_t microseconds_t; #include "processor_box.h" #include "prompter.h" #include "public_editor.h" +#include "rc_option_editor.h" #include "route_time_axis.h" +#include "route_params_ui.h" +#include "session_dialog.h" #include "session_metadata_dialog.h" +#include "session_option_editor.h" #include "shuttle_control.h" #include "speaker_dialog.h" #include "splash.h" @@ -115,7 +119,6 @@ typedef uint64_t microseconds_t; #include "theme_manager.h" #include "time_axis_view_item.h" #include "utils.h" -#include "window_proxy.h" #include "video_server_dialog.h" #include "add_video_dialog.h" #include "transcode_video_dialog.h" @@ -136,18 +139,28 @@ sigc::signal ARDOUR_UI::Blink; sigc::signal ARDOUR_UI::RapidScreenUpdate; sigc::signal ARDOUR_UI::SuperRapidScreenUpdate; sigc::signal ARDOUR_UI::Clock; +sigc::signal ARDOUR_UI::CloseAllDialogs; ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) : Gtkmm2ext::UI (PROGRAM_NAME, argcp, argvp) - + , gui_object_state (new GUIObjectState) + , primary_clock (new MainClock (X_("primary"), false, X_("transport"), true, true, true, false, true)) , secondary_clock (new MainClock (X_("secondary"), false, X_("secondary"), true, true, false, false, true)) /* big clock */ , big_clock (new AudioClock (X_("bigclock"), false, "big", true, true, false, false)) + , video_timeline(0) + + /* start of private members */ + + , nsm (0) + , _was_dirty (false) + , _mixer_on_top (false) + , first_time_engine_run (true) /* transport */ @@ -167,53 +180,57 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) , solo_alert_button (_("solo")) , feedback_alert_button (_("feedback")) + , editor_meter(0) + , editor_meter_peak_display() + + , speaker_config_window (X_("speaker-config"), _("Speaker Configuration")) + , theme_manager (X_("theme-manager"), _("Theme Manager")) + , key_editor (X_("key-editor"), _("Key Bindings")) + , rc_option_editor (X_("rc-options-editor"), _("Preferences")) + , add_route_dialog (X_("add-routes"), _("Add Tracks/Busses")) + , about (X_("about"), _("About")) + , location_ui (X_("locations"), _("Locations")) + , route_params (X_("inspector"), _("Tracks and Busses")) + , audio_midi_setup (X_("audio-midi-setup"), _("Audio/MIDI Setup")) + , session_option_editor (X_("session-options-editor"), _("Properties"), boost::bind (&ARDOUR_UI::create_session_option_editor, this)) + , add_video_dialog (X_("add-video"), _("Add Tracks/Busses"), boost::bind (&ARDOUR_UI::create_add_video_dialog, this)) + , bundle_manager (X_("bundle-manager"), _("Bundle Manager"), boost::bind (&ARDOUR_UI::create_bundle_manager, this)) + , big_clock_window (X_("big-clock"), _("Big Clock"), boost::bind (&ARDOUR_UI::create_big_clock_window, this)) + , audio_port_matrix (X_("audio-connection-manager"), _("Audio Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::AUDIO)) + , midi_port_matrix (X_("midi-connection-manager"), _("MIDI Connections"), boost::bind (&ARDOUR_UI::create_global_port_matrix, this, ARDOUR::DataType::MIDI)) + , error_log_button (_("Errors")) , _status_bar_visibility (X_("status-bar")) , _feedback_exists (false) - { Gtkmm2ext::init(localedir); - about = 0; splash = 0; - _startup = 0; if (theArdourUI == 0) { theArdourUI = this; } ui_config = new UIConfiguration(); - theme_manager = new ThemeManager(); - key_editor = 0; + ui_config->ParameterChanged.connect (sigc::mem_fun (*this, &ARDOUR_UI::parameter_changed)); + boost::function pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1)); + ui_config->map_parameters (pc); editor = 0; mixer = 0; + meterbridge = 0; editor = 0; - engine = 0; _session_is_new = false; - big_clock_window = 0; - big_clock_height = 0; - big_clock_resize_in_progress = false; session_selector_window = 0; last_key_press_time = 0; - add_route_dialog = 0; - add_video_dialog = 0; video_server_process = 0; - route_params = 0; - bundle_manager = 0; - rc_option_editor = 0; - session_option_editor = 0; - location_ui = 0; open_session_selector = 0; have_configure_timeout = false; have_disk_speed_dialog_displayed = false; session_loaded = false; ignore_dual_punch = false; - original_big_clock_width = -1; - original_big_clock_height = -1; - original_big_clock_font_size = 0; roll_button.set_controllable (roll_controllable); stop_button.set_controllable (stop_controllable); @@ -252,6 +269,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) ARDOUR::Session::AskAboutPendingState.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::pending_state_dialog, this)); + /* handle Audio/MIDI setup when session requires it */ + + ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1)); + /* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */ ARDOUR::Session::AskAboutSampleRateMismatch.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::sr_mismatch_dialog, this, _1, _2)); @@ -275,21 +296,10 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) /* lets get this party started */ - try { - if (ARDOUR::init (ARDOUR_COMMAND_LINE::use_vst, ARDOUR_COMMAND_LINE::try_hw_optimization, localedir)) { - throw failed_constructor (); - } - - setup_gtk_ardour_enums (); - setup_profile (); - - SessionEvent::create_per_thread_pool ("GUI", 512); + setup_gtk_ardour_enums (); + setup_profile (); - } catch (failed_constructor& err) { - error << string_compose (_("could not initialize %1."), PROGRAM_NAME) << endmsg; - // pass it on up - throw; - } + SessionEvent::create_per_thread_pool ("GUI", 512); /* we like keyboards */ @@ -307,82 +317,162 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) TimeAxisViewItem::set_constant_heights (); - /* The following must happen after ARDOUR::init() so that Config is set up */ - - location_ui = new ActionWindowProxy (X_("locations"), Config->extra_xml (X_("UI")), X_("ToggleLocations")); - big_clock_window = new ActionWindowProxy (X_("bigclock"), Config->extra_xml (X_("UI")), X_("ToggleBigClock")); - speaker_config_window = new ActionWindowProxy (X_("speakerconf"), Config->extra_xml (X_("UI")), X_("toggle-speaker-config")); - - for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { - _global_port_matrix[*i] = new ActionWindowProxy ( - string_compose ("GlobalPortMatrix-%1", (*i).to_string()), - Config->extra_xml (X_("UI")), - string_compose ("toggle-%1-connection-manager", (*i).to_string()) - ); - } - - setup_clock (); + /* Set this up so that our window proxies can register actions */ - SpeakerDialog* s = new SpeakerDialog (); - s->signal_unmap().connect (sigc::bind (sigc::ptr_fun (&ActionManager::uncheck_toggleaction), X_("/Common/toggle-speaker-config"))); - speaker_config_window->set (s); + ActionManager::init (); - starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup)); - stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown)); + /* The following must happen after ARDOUR::init() so that Config is set up */ + const XMLNode* ui_xml = Config->extra_xml (X_("UI")); + + if (ui_xml) { + theme_manager.set_state (*ui_xml); + key_editor.set_state (*ui_xml); + rc_option_editor.set_state (*ui_xml); + session_option_editor.set_state (*ui_xml); + speaker_config_window.set_state (*ui_xml); + about.set_state (*ui_xml); + add_route_dialog.set_state (*ui_xml); + add_video_dialog.set_state (*ui_xml); + route_params.set_state (*ui_xml); + bundle_manager.set_state (*ui_xml); + location_ui.set_state (*ui_xml); + big_clock_window.set_state (*ui_xml); + audio_port_matrix.set_state (*ui_xml); + midi_port_matrix.set_state (*ui_xml); + } + + WM::Manager::instance().register_window (&theme_manager); + WM::Manager::instance().register_window (&key_editor); + WM::Manager::instance().register_window (&rc_option_editor); + WM::Manager::instance().register_window (&session_option_editor); + WM::Manager::instance().register_window (&speaker_config_window); + WM::Manager::instance().register_window (&about); + WM::Manager::instance().register_window (&add_route_dialog); + WM::Manager::instance().register_window (&add_video_dialog); + WM::Manager::instance().register_window (&route_params); + WM::Manager::instance().register_window (&audio_midi_setup); + WM::Manager::instance().register_window (&bundle_manager); + WM::Manager::instance().register_window (&location_ui); + WM::Manager::instance().register_window (&big_clock_window); + WM::Manager::instance().register_window (&audio_port_matrix); + WM::Manager::instance().register_window (&midi_port_matrix); + + /* We need to instantiate the theme manager because it loads our + theme files. This should really change so that its window + and its functionality are separate + */ + + (void) theme_manager.get (true); + _process_thread = new ProcessThread (); _process_thread->init (); DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets)); -} + attach_to_engine (); +} -int -ARDOUR_UI::create_engine () +GlobalPortMatrixWindow* +ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type) { - // this gets called every time by new_session() - - if (engine) { + if (!_session) { return 0; } + return new GlobalPortMatrixWindow (_session, type); +} - loading_message (_("Starting audio engine")); +void +ARDOUR_UI::attach_to_engine () +{ + AudioEngine::instance()->Running.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_running, this), gui_context()); + ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports); +} - try { - engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid); +void +ARDOUR_UI::engine_stopped () +{ + ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped) + ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false); + ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true); +} - } catch (...) { +void +ARDOUR_UI::engine_running () +{ + if (first_time_engine_run) { + post_engine(); + first_time_engine_run = false; + } + + update_disk_space (); + update_cpu_load (); + update_sample_rate (AudioEngine::instance()->sample_rate()); + update_timecode_format (); +} - return -1; +void +ARDOUR_UI::engine_halted (const char* reason, bool free_reason) +{ + 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; } - 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, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context()); + ActionManager::set_sensitive (ActionManager::engine_sensitive_actions, false); + ActionManager::set_sensitive (ActionManager::engine_opposite_sensitive_actions, true); - engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); + update_sample_rate (0); - ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports); + string msgstr; - post_engine (); + /* if the reason is a non-empty string, it means that the backend was shutdown + rather than just Ardour. + */ - return 0; + if (strlen (reason)) { + msgstr = string_compose (_("The audio backend was shutdown because:\n\n%1"), reason); + } else { + msgstr = string_compose (_("\ +The audio backend has either been shutdown or it\n\ +disconnected %1 because %1\n\ +was not fast enough. Try to restart\n\ +the audio backend and save the session."), PROGRAM_NAME); + } + + MessageDialog msg (*editor, msgstr); + pop_back_splash (msg); + msg.set_keep_above (true); + msg.run (); + + if (free_reason) { + free (const_cast (reason)); + } } void ARDOUR_UI::post_engine () { - /* Things to be done once we create the AudioEngine + /* Things to be done once (and once ONLY) after we have a backend running in the AudioEngine */ ARDOUR::init_post_engine (); + + /* connect to important signals */ - /* load up the UI manager */ - - ActionManager::init (); + AudioEngine::instance()->Stopped.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::engine_stopped, this), gui_context()); + AudioEngine::instance()->SampleRateChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::update_sample_rate, this, _1), gui_context()); + AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); _tooltips.enable(); + ActionManager::load_menus (); + if (setup_windows ()) { throw failed_constructor (); } @@ -440,36 +530,22 @@ ARDOUR_UI::post_engine () Glib::signal_timeout().connect_seconds (sigc::mem_fun(*this, &ARDOUR_UI::update_wall_clock), 1); #endif - update_disk_space (); - update_cpu_load (); - update_sample_rate (engine->frame_rate()); - update_timecode_format (); - Config->ParameterChanged.connect (forever_connections, MISSING_INVALIDATOR, boost::bind (&ARDOUR_UI::parameter_changed, this, _1), gui_context()); boost::function pc (boost::bind (&ARDOUR_UI::parameter_changed, this, _1)); Config->map_parameters (pc); - - /* now start and maybe save state */ - - if (do_engine_start () == 0) { - if (_session && _session_is_new) { - /* we need to retain initial visual - settings for a new session - */ - _session->save_state (""); - } - } } ARDOUR_UI::~ARDOUR_UI () { + if (ui_config->dirty()) { + ui_config->save_state(); + } + delete keyboard; delete editor; delete mixer; - delete add_route_dialog; - if (add_video_dialog) { - delete add_video_dialog; - } + delete meterbridge; + stop_video_server(); } @@ -641,11 +717,13 @@ ARDOUR_UI::check_announcements () #endif } -void -ARDOUR_UI::startup () +int +ARDOUR_UI::starting () { Application* app = Application::instance (); char *nsm_url; + 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::idle_load)); @@ -656,7 +734,6 @@ ARDOUR_UI::startup () app->ready (); nsm_url = getenv ("NSM_URL"); - nsm = 0; if (nsm_url) { nsm = new NSM_Client; @@ -704,24 +781,46 @@ ARDOUR_UI::startup () delete nsm; nsm = 0; } - } - else if (get_session_parameters (true, ARDOUR_COMMAND_LINE::new_session, ARDOUR_COMMAND_LINE::load_template)) { - exit (1); + } else { + + if (brand_new_user) { + ArdourStartup s; + s.present (); + main().run(); + s.hide (); + switch (s.response ()) { + case Gtk::RESPONSE_OK: + break; + default: + return -1; + } + } + + /* we need to create this early because it may need to set the + * audio backend end up. + */ + + try { + audio_midi_setup.get (true); + } catch (...) { + return -1; + } + + /* go get a session */ + + const bool new_session_required = (ARDOUR_COMMAND_LINE::new_session || brand_new_user); + + if (get_session_parameters (false, new_session_required, ARDOUR_COMMAND_LINE::load_template)) { + return -1; + } } use_config (); goto_editor_window (); - /* Add the window proxies here; their addition may cause windows to be opened, and we want them - to be opened on top of the editor window that goto_editor_window() just opened. - */ - add_window_proxy (location_ui); - add_window_proxy (big_clock_window); - for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) { - add_window_proxy (_global_port_matrix[*i]); - } + WM::Manager::instance().show_visible (); /* We have to do this here since goto_editor_window() ends up calling show_all() on the * editor window, and we may want stuff to be hidden. @@ -729,6 +828,7 @@ ARDOUR_UI::startup () _status_bar_visibility.update (); BootMessage (string_compose (_("%1 is ready for use"), PROGRAM_NAME)); + return 0; } void @@ -748,7 +848,7 @@ ARDOUR_UI::check_memory_locking () XMLNode* memory_warning_node = Config->instant_xml (X_("no-memory-warning")); - if (engine->is_realtime() && memory_warning_node == 0) { + if (AudioEngine::instance()->is_realtime() && memory_warning_node == 0) { struct rlimit limits; int64_t ram; @@ -781,13 +881,13 @@ ARDOUR_UI::check_memory_locking () "runs out of memory. \n\n" "You can view the memory limit with 'ulimit -l', " "and it is normally controlled by %2"), - PROGRAM_NAME).c_str(), + PROGRAM_NAME, #ifdef __FreeBSD__ - X_("/etc/login.conf") + X_("/etc/login.conf") #else - X_(" /etc/security/limits.conf") + X_(" /etc/security/limits.conf") #endif - ); + ).c_str()); msg.set_default_response (RESPONSE_OK); @@ -863,11 +963,11 @@ If you still wish to quit, please use the\n\n\ second_connection.disconnect (); point_one_second_connection.disconnect (); - point_oh_five_second_connection.disconnect (); - point_zero_one_second_connection.disconnect(); + point_zero_something_second_connection.disconnect(); } delete ARDOUR_UI::instance()->video_timeline; + ARDOUR_UI::instance()->video_timeline = NULL; stop_video_server(); /* Save state before deleting the session, as that causes some @@ -876,6 +976,8 @@ If you still wish to quit, please use the\n\n\ */ save_ardour_state (); + close_all_dialogs (); + loading_message (string_compose (_("Please wait while %1 cleans up..."), PROGRAM_NAME)); if (_session) { @@ -886,8 +988,8 @@ If you still wish to quit, please use the\n\n\ _session = 0; } - ArdourDialog::close_all_dialogs (); - engine->stop (true); + halt_connection.disconnect (); + AudioEngine::instance()->stop (); quit (); } @@ -992,11 +1094,20 @@ ARDOUR_UI::every_point_one_seconds () } gint -ARDOUR_UI::every_point_zero_one_seconds () +ARDOUR_UI::every_point_zero_something_seconds () { - // august 2007: actual update frequency: 40Hz, not 100Hz + // august 2007: actual update frequency: 25Hz (40ms), not 100Hz SuperRapidScreenUpdate(); /* EMIT_SIGNAL */ + if (editor_meter && Config->get_show_editor_meter()) { + float mpeak = editor_meter->update_meters(); + if (mpeak > editor_meter_max_peak) { + if (mpeak >= Config->get_meter_peak()) { + editor_meter_peak_display.set_name ("meterbridge peakindicator on"); + editor_meter_peak_display.set_elements((ArdourButton::Element) (ArdourButton::Edge|ArdourButton::Body)); + } + } + } return TRUE; } @@ -1007,25 +1118,30 @@ ARDOUR_UI::update_sample_rate (framecnt_t) ENSURE_GUI_THREAD (*this, &ARDOUR_UI::update_sample_rate, ignored) - if (!engine->connected()) { + if (!AudioEngine::instance()->connected()) { - snprintf (buf, sizeof (buf), "%s", _("disconnected")); + snprintf (buf, sizeof (buf), _("Audio: none")); } else { - framecnt_t rate = engine->frame_rate(); + framecnt_t rate = AudioEngine::instance()->sample_rate(); - if (fmod (rate, 1000.0) != 0.0) { - snprintf (buf, sizeof (buf), _("JACK: %.1f kHz / %4.1f ms"), - (float) rate/1000.0f, - (engine->frames_per_cycle() / (float) rate) * 1000.0f); + if (rate == 0) { + /* no sample rate available */ + snprintf (buf, sizeof (buf), _("Audio: none")); } else { - snprintf (buf, sizeof (buf), _("JACK: %" PRId64 " kHz / %4.1f ms"), - rate/1000, - (engine->frames_per_cycle() / (float) rate) * 1000.0f); + + if (fmod (rate, 1000.0) != 0.0) { + snprintf (buf, sizeof (buf), _("Audio: %.1f kHz / %4.1f ms"), + (float) rate / 1000.0f, + (AudioEngine::instance()->usecs_per_cycle() / 1000.0f)); + } else { + snprintf (buf, sizeof (buf), _("Audio: %" PRId64 " kHz / %4.1f ms"), + rate/1000, + (AudioEngine::instance()->usecs_per_cycle() / 1000.0f)); + } } } - sample_rate_label.set_markup (buf); } @@ -1092,7 +1208,7 @@ ARDOUR_UI::update_cpu_load () should also be changed. */ - float const c = engine->get_cpu_load (); + float const c = AudioEngine::instance()->get_cpu_load (); snprintf (buf, sizeof (buf), _("DSP: %5.1f%%"), c >= 90 ? X_("red") : X_("green"), c); cpu_load_label.set_markup (buf); } @@ -1146,6 +1262,11 @@ ARDOUR_UI::update_disk_space() char buf[64]; framecnt_t fr = _session->frame_rate(); + if (fr == 0) { + /* skip update - no SR available */ + return; + } + if (!opt_frames) { /* Available space is unknown */ snprintf (buf, sizeof (buf), "%s", _("Disk: Unknown")); @@ -1408,20 +1529,16 @@ ARDOUR_UI::open_recent_session () bool ARDOUR_UI::check_audioengine () { - if (engine) { - if (!engine->connected()) { - MessageDialog msg (string_compose ( - _("%1 is not connected to JACK\n" - "You cannot open or close sessions in this condition"), - PROGRAM_NAME)); - pop_back_splash (msg); - msg.run (); - return false; - } - return true; - } else { + if (!AudioEngine::instance()->connected()) { + MessageDialog msg (string_compose ( + _("%1 is not connected to any audio backend.\n" + "You cannot open or close sessions in this condition"), + PROGRAM_NAME)); + pop_back_splash (msg); + msg.run (); return false; } + return true; } void @@ -1452,7 +1569,14 @@ ARDOUR_UI::open_session () open_session_selector->set_current_folder(Config->get_default_session_parent_dir()); } - open_session_selector->add_shortcut_folder (Config->get_default_session_parent_dir()); + string default_session_folder = Config->get_default_session_parent_dir(); + try { + /* add_shortcut_folder throws an exception if the folder being added already has a shortcut */ + open_session_selector->add_shortcut_folder (default_session_folder); + } + catch (Glib::Error & e) { + std::cerr << "open_session_selector->add_shortcut_folder (" << default_session_folder << ") threw Glib::Error " << e.what() << std::endl; + } FileFilter session_filter; session_filter.add_pattern ("*.ardour"); @@ -1620,10 +1744,17 @@ ARDOUR_UI::transport_goto_wallclock () time (&now); localtime_r (&now, &tmnow); + + int frame_rate = _session->frame_rate(); + + if (frame_rate == 0) { + /* no frame rate available */ + return; + } - frames = tmnow.tm_hour * (60 * 60 * _session->frame_rate()); - frames += tmnow.tm_min * (60 * _session->frame_rate()); - frames += tmnow.tm_sec * _session->frame_rate(); + frames = tmnow.tm_hour * (60 * 60 * frame_rate); + frames += tmnow.tm_min * (60 * frame_rate); + frames += tmnow.tm_sec * frame_rate; _session->request_locate (frames, _session->transport_rolling ()); @@ -1714,7 +1845,7 @@ ARDOUR_UI::transport_roll () #if 0 if (_session->config.get_external_sync()) { switch (Config->get_sync_source()) { - case JACK: + case Engine: break; default: /* transport controlled by the master */ @@ -1764,7 +1895,7 @@ ARDOUR_UI::toggle_roll (bool with_abort, bool roll_out_of_bounded_mode) if (_session->config.get_external_sync()) { switch (Config->get_sync_source()) { - case JACK: + case Engine: break; default: /* transport controlled by the master */ @@ -1983,127 +2114,6 @@ ARDOUR_UI::map_transport_state () } } -void -ARDOUR_UI::engine_stopped () -{ - ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_stopped) - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, false); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, true); -} - -void -ARDOUR_UI::engine_running () -{ - ENSURE_GUI_THREAD (*this, &ARDOUR_UI::engine_running) - ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true); - ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false); - - Glib::RefPtr action; - const char* action_name = 0; - - switch (engine->frames_per_cycle()) { - case 32: - action_name = X_("JACKLatency32"); - break; - case 64: - action_name = X_("JACKLatency64"); - break; - case 128: - action_name = X_("JACKLatency128"); - break; - case 512: - action_name = X_("JACKLatency512"); - break; - case 1024: - action_name = X_("JACKLatency1024"); - break; - case 2048: - action_name = X_("JACKLatency2048"); - break; - case 4096: - action_name = X_("JACKLatency4096"); - break; - case 8192: - action_name = X_("JACKLatency8192"); - break; - default: - /* XXX can we do anything useful ? */ - break; - } - - if (action_name) { - - action = ActionManager::get_action (X_("JACK"), action_name); - - if (action) { - Glib::RefPtr ract = Glib::RefPtr::cast_dynamic (action); - ract->set_active (); - } - } -} - -void -ARDOUR_UI::engine_halted (const char* reason, bool free_reason) -{ - 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); - - 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 = string_compose (_("\ -JACK has either been shutdown or it\n\ -disconnected %1 because %1\n\ -was not fast enough. Try to restart\n\ -JACK, reconnect and save the session."), PROGRAM_NAME); - } - - MessageDialog msg (*editor, msgstr); - pop_back_splash (msg); - msg.set_keep_above (true); - msg.run (); - - if (free_reason) { - free (const_cast (reason)); - } -} - -int32_t -ARDOUR_UI::do_engine_start () -{ - try { - engine->start(); - } - - catch (...) { - engine->stop (); - error << _("Unable to start the session running") - << endmsg; - unload_session (); - return -2; - } - - return 0; -} - void ARDOUR_UI::update_clocks () { @@ -2303,11 +2313,7 @@ ARDOUR_UI::save_state (const string & name, bool switch_to_it) { XMLNode* node = new XMLNode (X_("UI")); - for (list::iterator i = _window_proxies.begin(); i != _window_proxies.end(); ++i) { - if (!(*i)->rc_configured()) { - node->add_child_nocopy (*((*i)->get_state ())); - } - } + WM::Manager::instance().add_state (*node); node->add_child_nocopy (gui_object_state->get_state()); @@ -2461,7 +2467,7 @@ ARDOUR_UI::ask_about_loading_existing_session (const std::string& session_path) } int -ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::string& session_name) +ARDOUR_UI::build_session_from_dialog (SessionDialog& sd, const std::string& session_path, const std::string& session_name) { BusProfile bus_profile; @@ -2477,13 +2483,13 @@ ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::s /* get settings from advanced section of NSD */ - if (_startup->create_master_bus()) { - bus_profile.master_out_channels = (uint32_t) _startup->master_channel_count(); + if (sd.create_master_bus()) { + bus_profile.master_out_channels = (uint32_t) sd.master_channel_count(); } else { bus_profile.master_out_channels = 0; } - if (_startup->connect_inputs()) { + if (sd.connect_inputs()) { bus_profile.input_ac = AutoConnectPhysical; } else { bus_profile.input_ac = AutoConnectOption (0); @@ -2491,16 +2497,16 @@ ARDOUR_UI::build_session_from_nsd (const std::string& session_path, const std::s bus_profile.output_ac = AutoConnectOption (0); - if (_startup->connect_outputs ()) { - if (_startup->connect_outs_to_master()) { + if (sd.connect_outputs ()) { + if (sd.connect_outs_to_master()) { bus_profile.output_ac = AutoConnectMaster; - } else if (_startup->connect_outs_to_physical()) { + } else if (sd.connect_outs_to_physical()) { bus_profile.output_ac = AutoConnectPhysical; } } - bus_profile.requested_physical_in = (uint32_t) _startup->input_limit_count(); - bus_profile.requested_physical_out = (uint32_t) _startup->output_limit_count(); + bus_profile.requested_physical_in = (uint32_t) sd.input_limit_count(); + bus_profile.requested_physical_out = (uint32_t) sd.output_limit_count(); } if (build_session (session_path, session_name, bus_profile)) { @@ -2536,6 +2542,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri string template_name; int ret = -1; bool likely_new = false; + bool cancel_not_quit; /* deal with any existing DIRTY session now, rather than later. don't * treat a non-dirty session this way, so that it stays visible @@ -2546,6 +2553,11 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri ARDOUR_UI::instance()->video_timeline->sync_session_state(); } + /* if there is already a session, relabel the button + on the SessionDialog so that we don't Quit directly + */ + cancel_not_quit = (_session != 0); + if (_session && _session->dirty()) { if (unload_session (false)) { /* unload cancelled by user */ @@ -2559,6 +2571,20 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri template_name = load_template; } + session_name = basename_nosuffix (ARDOUR_COMMAND_LINE::session_name); + session_path = ARDOUR_COMMAND_LINE::session_name; + + if (!session_path.empty()) { + if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_EXISTS)) { + if (Glib::file_test (session_path.c_str(), Glib::FILE_TEST_IS_REGULAR)) { + /* session/snapshot file, change path to be dir */ + session_path = Glib::path_get_dirname (session_path); + } + } + } + + SessionDialog session_dialog (should_be_new, session_name, session_path, load_template, cancel_not_quit); + while (ret != 0) { if (!ARDOUR_COMMAND_LINE::session_name.empty()) { @@ -2581,34 +2607,35 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri } else { session_path = ""; session_name = ""; - } - - delete _startup; - _startup = new ArdourStartup (should_be_new, session_name, session_path, load_template); - - if (!_startup->ready_without_display()) { - _startup->present (); - main().run(); - _startup->hide (); + session_dialog.clear_given (); } - switch (_startup->response()) { - case RESPONSE_OK: - break; - default: - if (quit_on_cancel) { - exit (1); - } else { - return ret; + if (should_be_new || session_name.empty()) { + /* need the dialog to get info from user */ + + cerr << "run dialog\n"; + + switch (session_dialog.run()) { + case RESPONSE_ACCEPT: + break; + default: + if (quit_on_cancel) { + exit (1); + } else { + return ret; + } } + + session_dialog.hide (); } /* if we run the startup dialog again, offer more than just "new session" */ should_be_new = false; - session_name = _startup->session_name (likely_new); - + session_name = session_dialog.session_name (likely_new); + session_path = session_dialog.session_folder (); + if (nsm) { likely_new = true; } @@ -2625,8 +2652,8 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri continue; } - if (_startup->use_session_template()) { - template_name = _startup->session_template_name(); + if (session_dialog.use_session_template()) { + template_name = session_dialog.session_template_name(); _session_is_new = true; } @@ -2643,12 +2670,12 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri } else { - session_path = _startup->session_folder(); + session_path = session_dialog.session_folder(); char illegal = Session::session_name_is_legal (session_name); if (illegal) { - MessageDialog msg (*_startup, + MessageDialog msg (session_dialog, string_compose (_("To ensure compatibility with various systems\n" "session names may not contain a '%1' character"), illegal)); @@ -2658,12 +2685,9 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri } } - if (create_engine ()) { - break; - } - if (Glib::file_test (session_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { + if (likely_new && !nsm) { std::string existing = Glib::build_filename (session_path, session_name); @@ -2679,12 +2703,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri } else { if (!likely_new) { - if (_startup) { - pop_back_splash (*_startup); - } else { - hide_splash (); - } - + pop_back_splash (session_dialog); MessageDialog msg (string_compose (_("There is no existing session at \"%1\""), session_path)); msg.run (); ARDOUR_COMMAND_LINE::session_name = ""; // cancel that @@ -2692,10 +2711,11 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri } char illegal = Session::session_name_is_legal(session_name); + if (illegal) { - pop_back_splash (*_startup); - MessageDialog msg (*_startup, string_compose(_("To ensure compatibility with various systems\n" - "session names may not contain a '%1' character"), illegal)); + pop_back_splash (session_dialog); + 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 continue; @@ -2706,7 +2726,7 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri if (likely_new && template_name.empty()) { - ret = build_session_from_nsd (session_path, session_name); + ret = build_session_from_dialog (session_dialog, session_path, session_name); } else { @@ -2721,6 +2741,12 @@ ARDOUR_UI::get_session_parameters (bool quit_on_cancel, bool should_be_new, stri _session->save_state (ARDOUR_COMMAND_LINE::immediate_save, false); exit (1); } + + /* clear this to avoid endless attempts to load the + same session. + */ + + ARDOUR_COMMAND_LINE::session_name = ""; } } @@ -2757,25 +2783,23 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, int unload_status; int retval = -1; - session_loaded = false; - - if (!check_audioengine()) { - return -2; + if (_session) { + unload_status = unload_session (); + + if (unload_status < 0) { + goto out; + } else if (unload_status > 0) { + retval = 0; + goto out; + } } - unload_status = unload_session (); - - if (unload_status < 0) { - goto out; - } else if (unload_status > 0) { - retval = 0; - goto out; - } + session_loaded = false; loading_message (string_compose (_("Please wait while %1 loads your session"), PROGRAM_NAME)); try { - new_session = new Session (*engine, path, snap_name, 0, mix_template); + new_session = new Session (*AudioEngine::instance(), path, snap_name, 0, mix_template); } /* this one is special */ @@ -2815,22 +2839,12 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, Gtk::MESSAGE_INFO, BUTTONS_OK); + msg.set_keep_above (true); msg.set_title (_("Loading Error")); - msg.set_secondary_text (_("Click the Refresh button to try again.")); - msg.add_button (Stock::REFRESH, 1); msg.set_position (Gtk::WIN_POS_CENTER); pop_back_splash (msg); msg.present (); - - int response = msg.run (); - - switch (response) { - case 1: - break; - default: - exit (1); - } - + (void) msg.run (); msg.hide (); goto out; @@ -2844,6 +2858,22 @@ ARDOUR_UI::load_session (const std::string& path, const std::string& snap_name, } } + if (!new_session->writable()) { + MessageDialog msg (_("This session has been opened in read-only mode.\n\nYou will not be able to record or save."), + true, + Gtk::MESSAGE_INFO, + BUTTONS_OK); + + msg.set_keep_above (true); + msg.set_title (_("Read-only Session")); + msg.set_position (Gtk::WIN_POS_CENTER); + pop_back_splash (msg); + msg.present (); + (void) msg.run (); + msg.hide (); + } + + /* Now the session been created, add the transport controls */ new_session->add_controllable(roll_controllable); new_session->add_controllable(stop_controllable); @@ -2876,12 +2906,7 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, Session *new_session; int x; - if (!check_audioengine()) { - return -1; - } - session_loaded = false; - x = unload_session (); if (x < 0) { @@ -2893,7 +2918,7 @@ ARDOUR_UI::build_session (const std::string& path, const std::string& snap_name, _session_is_new = true; try { - new_session = new Session (*engine, path, snap_name, &bus_profile); + new_session = new Session (*AudioEngine::instance(), path, snap_name, &bus_profile); } catch (...) { @@ -2942,18 +2967,6 @@ ARDOUR_UI::launch_chat () #endif } -void -ARDOUR_UI::show_about () -{ - if (about == 0) { - about = new About; - about->signal_response().connect (sigc::mem_fun (*this, &ARDOUR_UI::about_signal_response)); - } - - about->set_transient_for(*editor); - about->show_all (); -} - void ARDOUR_UI::launch_manual () { @@ -2966,21 +2979,6 @@ ARDOUR_UI::launch_reference () PBD::open_uri (Config->get_reference_manual_url()); } -void -ARDOUR_UI::hide_about () -{ - if (about) { - about->get_window()->set_cursor (); - about->hide (); - } -} - -void -ARDOUR_UI::about_signal_response (int /*response*/) -{ - hide_about(); -} - void ARDOUR_UI::loading_message (const std::string& msg) { @@ -3241,18 +3239,15 @@ ARDOUR_UI::add_route (Gtk::Window* float_window) return; } - if (add_route_dialog == 0) { - add_route_dialog = new AddRouteDialog (_session); - if (float_window) { - add_route_dialog->set_transient_for (*float_window); - } - } - if (add_route_dialog->is_visible()) { /* we're already doing this */ return; } + if (float_window) { + add_route_dialog->set_transient_for (*float_window); + } + ResponseType r = (ResponseType) add_route_dialog->run (); add_route_dialog->hide(); @@ -3424,9 +3419,28 @@ ARDOUR_UI::start_video_server (Gtk::Window* float_window, bool popup_msg) Config->set_video_advanced_setup(true); } + if (video_server_process) { + delete video_server_process; + } + video_server_process = new SystemExec(icsd_exec, argp); - video_server_process->start(); - sleep(1); + if (video_server_process->start()) { + warning << _("Cannot launch the video-server") << endmsg; + continue; + } + int timeout = 120; // 6 sec + while (!ARDOUR_UI::instance()->video_timeline->check_server()) { + usleep (50000); + if (--timeout <= 0 || !video_server_process->is_running()) break; + } + if (timeout <= 0) { + warning << _("Video-server was started but does not respond to requests...") << endmsg; + } else { + if (!ARDOUR_UI::instance()->video_timeline->check_server_docroot()) { + delete video_server_process; + video_server_process = 0; + } + } } return true; } @@ -3443,23 +3457,25 @@ ARDOUR_UI::add_video (Gtk::Window* float_window) return; } - if (add_video_dialog == 0) { - add_video_dialog = new AddVideoDialog (_session); - if (float_window) { - add_video_dialog->set_transient_for (*float_window); - } + if (float_window) { + add_video_dialog->set_transient_for (*float_window); } if (add_video_dialog->is_visible()) { /* we're already doing this */ return; } + ResponseType r = (ResponseType) add_video_dialog->run (); add_video_dialog->hide(); if (r != RESPONSE_ACCEPT) { return; } - bool local_file; + bool local_file, orig_local_file; std::string path = add_video_dialog->file_name(local_file); + + std::string orig_path = path; + orig_local_file = local_file; + bool auto_set_session_fps = add_video_dialog->auto_set_session_fps(); if (local_file && !Glib::file_test(path, Glib::FILE_TEST_EXISTS)) { @@ -3483,7 +3499,10 @@ ARDOUR_UI::add_video (Gtk::Window* float_window) return; } if (!transcode_video_dialog->get_audiofile().empty()) { - editor->embed_audio_from_video(transcode_video_dialog->get_audiofile()); + editor->embed_audio_from_video( + transcode_video_dialog->get_audiofile(), + video_timeline->get_offset() + ); } switch (transcode_video_dialog->import_option()) { case VTL_IMPORT_TRANSCODED: @@ -3518,6 +3537,11 @@ ARDOUR_UI::add_video (Gtk::Window* float_window) node->add_property (X_("Filename"), path); node->add_property (X_("AutoFPS"), auto_set_session_fps?X_("1"):X_("0")); node->add_property (X_("LocalFile"), local_file?X_("1"):X_("0")); + if (orig_local_file) { + node->add_property (X_("OriginalVideoFile"), orig_path); + } else { + node->remove_property (X_("OriginalVideoFile")); + } _session->add_extra_xml (*node); _session->set_dirty (); @@ -3542,6 +3566,10 @@ ARDOUR_UI::remove_video () video_timeline->close_session(); editor->toggle_ruler_video(false); + /* reset state */ + video_timeline->set_offset_locked(false); + video_timeline->set_offset(0); + /* delete session state */ XMLNode* node = new XMLNode(X_("Videotimeline")); _session->add_extra_xml(*node); @@ -3777,31 +3805,43 @@ audio may be played at the wrong sample rate.\n"), desired, PROGRAM_NAME, actual return 1; } - -void -ARDOUR_UI::disconnect_from_jack () +int +ARDOUR_UI::disconnect_from_engine () { - if (engine) { - if (engine->disconnect_from_jack ()) { - MessageDialog msg (*editor, _("Could not disconnect from JACK")); - msg.run (); - } + /* drop connection to AudioEngine::Halted so that we don't act + * as if the engine unexpectedly shut down + */ - update_sample_rate (0); + halt_connection.disconnect (); + + if (AudioEngine::instance()->stop ()) { + MessageDialog msg (*editor, _("Could not disconnect from Audio/MIDI engine")); + msg.run (); + return -1; + } else { + AudioEngine::instance()->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); } + + update_sample_rate (0); + return 0; } -void -ARDOUR_UI::reconnect_to_jack () +int +ARDOUR_UI::reconnect_to_engine () { - if (engine) { - if (engine->reconnect_to_jack ()) { - MessageDialog msg (*editor, _("Could not reconnect to JACK")); + if (AudioEngine::instance()->start ()) { + if (editor) { + MessageDialog msg (*editor, _("Could not reconnect to the Audio/MIDI engine")); + msg.run (); + } else { + MessageDialog msg (_("Could not reconnect to the Audio/MIDI engine")); msg.run (); } - - update_sample_rate (0); + return -1; } + + update_sample_rate (0); + return 0; } void @@ -3828,13 +3868,12 @@ ARDOUR_UI::update_transport_clocks (framepos_t pos) secondary_clock->set (pos); } - if (big_clock_window->get()) { + if (big_clock_window) { big_clock->set (pos); } ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos); } - void ARDOUR_UI::step_edit_status_change (bool yn) { @@ -3855,7 +3894,7 @@ ARDOUR_UI::record_state_changed () { ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed); - if (!_session || !big_clock_window->get()) { + if (!_session || !big_clock_window) { /* why bother - the clock isn't visible */ return; } @@ -3994,26 +4033,6 @@ ARDOUR_UI::setup_profile () } } -/** Add a window proxy to our list, so that its state will be saved. - * This call also causes the window to be created and opened if its - * state was saved as `visible'. - */ -void -ARDOUR_UI::add_window_proxy (WindowProxyBase* p) -{ - _window_proxies.push_back (p); - p->maybe_show (); -} - -/** Remove a window proxy from our list. Must be called if a WindowProxy - * is deleted, to prevent hanging pointers. - */ -void -ARDOUR_UI::remove_window_proxy (WindowProxyBase* p) -{ - _window_proxies.remove (p); -} - int ARDOUR_UI::missing_file (Session*s, std::string str, DataType type) { @@ -4100,3 +4119,50 @@ ARDOUR_UI::session_format_mismatch (std::string xml_path, std::string backup_pat msg.run (); } + + +void +ARDOUR_UI::reset_peak_display () +{ + if (!_session || !_session->master_out() || !editor_meter) return; + editor_meter->clear_meters(); + editor_meter_max_peak = -INFINITY; + editor_meter_peak_display.set_name ("meterbridge peakindicator"); + editor_meter_peak_display.set_elements((ArdourButton::Element) (ArdourButton::Edge|ArdourButton::Body)); +} + +void +ARDOUR_UI::reset_group_peak_display (RouteGroup* group) +{ + if (!_session || !_session->master_out()) return; + if (group == _session->master_out()->route_group()) { + reset_peak_display (); + } +} + +void +ARDOUR_UI::reset_route_peak_display (Route* route) +{ + if (!_session || !_session->master_out()) return; + if (_session->master_out().get() == route) { + reset_peak_display (); + } +} + +int +ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate) +{ + audio_midi_setup->set_desired_sample_rate (desired_sample_rate); + audio_midi_setup->set_position (WIN_POS_CENTER); + + switch (audio_midi_setup->run()) { + case Gtk::RESPONSE_OK: + return 0; + case Gtk::RESPONSE_APPLY: + return 0; + default: + return -1; + } +} + +