X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fardour_ui.cc;h=ec3f0becea433c5fd8d562c22c33f18a7443c015;hb=4dc1bbff359308ad884c9429d155f772ebb89bc4;hp=7e972b8032a63f171c51a3d558f93a5247a80cad;hpb=ebb1271b6f666dadcaf6a73a6cb81231a70d8ad7;p=ardour.git diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 7e972b8032..ec3f0becea 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,11 @@ 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_metadata_dialog.h" +#include "session_option_editor.h" #include "shuttle_control.h" #include "speaker_dialog.h" #include "splash.h" @@ -115,7 +118,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 +138,30 @@ 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 */ + + , _startup (0) + , engine (0) + , nsm (0) + , _was_dirty (false) + , _mixer_on_top (false) + , first_time_engine_run (true) /* transport */ @@ -167,6 +181,24 @@ 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")) + , 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")) @@ -175,45 +207,28 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) { 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; 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); @@ -307,26 +322,53 @@ 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()) - ); - } + /* Set this up so that our window proxies can register actions */ - setup_clock (); + ActionManager::init (); - 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); + /* 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 (&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); + starting.connect (sigc::mem_fun(*this, &ARDOUR_UI::startup)); stopping.connect (sigc::mem_fun(*this, &ARDOUR_UI::shutdown)); @@ -334,55 +376,169 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir) _process_thread->init (); DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets)); + + attach_to_engine (); } +GlobalPortMatrixWindow* +ARDOUR_UI::create_global_port_matrix (ARDOUR::DataType type) +{ + if (!_session) { + return 0; + } + return new GlobalPortMatrixWindow (_session, type); +} -int -ARDOUR_UI::create_engine () +void +ARDOUR_UI::attach_to_engine () { - // this gets called every time by new_session() + engine = AudioEngine::instance(); - if (engine) { - return 0; + 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()); + + engine->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); + + ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports); + + /* if there is only one audio/midi backend, and it does not require setup, get our use of it underway + * right here (we need to know the client name and potential session ID + * to do this, which is why this is here, rather than in, say, + * ARDOUR::init(). + */ + + if (!AudioEngine::instance()->setup_required()) { + const AudioBackendInfo* backend = AudioEngine::instance()->available_backends().front(); + AudioEngine::instance()->set_backend (backend->name, ARDOUR_COMMAND_LINE::backend_client_name, ARDOUR_COMMAND_LINE::backend_session_uuid); + AudioEngine::instance()->start (); } +} - loading_message (_("Starting audio engine")); +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); +} - try { - engine = new ARDOUR::AudioEngine (ARDOUR_COMMAND_LINE::jack_client_name, ARDOUR_COMMAND_LINE::jack_session_uuid); +void +ARDOUR_UI::engine_running () +{ + if (first_time_engine_run) { + post_engine(); + first_time_engine_run = false; + } + + ActionManager::set_sensitive (ActionManager::jack_sensitive_actions, true); + ActionManager::set_sensitive (ActionManager::jack_opposite_sensitive_actions, false); - } catch (...) { + Glib::RefPtr action; + const char* action_name = 0; - return -1; + switch (engine->samples_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; } - 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()); + if (action_name) { - engine->Halted.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); + action = ActionManager::get_action (X_("JACK"), action_name); - ARDOUR::Port::set_connecting_blocked (ARDOUR_COMMAND_LINE::no_connect_ports); + if (action) { + Glib::RefPtr ract = Glib::RefPtr::cast_dynamic (action); + ract->set_active (); + } - post_engine (); + update_disk_space (); + update_cpu_load (); + update_sample_rate (engine->sample_rate()); + update_timecode_format (); + } +} - return 0; +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)); + } } 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 (); - /* load up the UI manager */ - - ActionManager::init (); - _tooltips.enable(); + ActionManager::load_menus (); + if (setup_windows ()) { throw failed_constructor (); } @@ -440,25 +596,9 @@ 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 () @@ -466,10 +606,8 @@ ARDOUR_UI::~ARDOUR_UI () delete keyboard; delete editor; delete mixer; - delete add_route_dialog; - if (add_video_dialog) { - delete add_video_dialog; - } + delete meterbridge; + stop_video_server(); } @@ -646,6 +784,7 @@ ARDOUR_UI::startup () { Application* app = Application::instance (); char *nsm_url; + app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish)); app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load)); @@ -656,7 +795,6 @@ ARDOUR_UI::startup () app->ready (); nsm_url = getenv ("NSM_URL"); - nsm = 0; if (nsm_url) { nsm = new NSM_Client; @@ -714,14 +852,7 @@ ARDOUR_UI::startup () 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. @@ -781,13 +912,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 +994,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 +1007,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 +1019,8 @@ If you still wish to quit, please use the\n\n\ _session = 0; } - ArdourDialog::close_all_dialogs (); - engine->stop (true); + halt_connection.disconnect (); + engine->stop (); quit (); } @@ -933,7 +1066,6 @@ ARDOUR_UI::ask_about_saving_session (const vector& actions) window.get_vbox()->pack_start (dhbox); window.set_name (_("Prompter")); - window.set_position (Gtk::WIN_POS_MOUSE); window.set_modal (true); window.set_resizable (false); @@ -993,11 +1125,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; } @@ -1010,20 +1151,26 @@ ARDOUR_UI::update_sample_rate (framecnt_t) if (!engine->connected()) { - snprintf (buf, sizeof (buf), "%s", _("disconnected")); + snprintf (buf, sizeof (buf), _("Audio: none")); } else { - framecnt_t rate = engine->frame_rate(); + framecnt_t rate = engine->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, + (engine->usecs_per_cycle() / 1000.0f)); + } else { + snprintf (buf, sizeof (buf), _("Audio: %" PRId64 " kHz / %4.1f ms"), + rate/1000, + (engine->usecs_per_cycle() / 1000.0f)); + } } } @@ -1147,6 +1294,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")); @@ -1367,8 +1519,6 @@ ARDOUR_UI::open_recent_session () while (true) { - session_selector_window->set_position (WIN_POS_MOUSE); - ResponseType r = (ResponseType) session_selector_window->run (); switch (r) { @@ -1455,7 +1605,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"); @@ -1623,10 +1780,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 ()); @@ -1986,127 +2150,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 () { @@ -2306,11 +2349,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()); @@ -2661,10 +2700,6 @@ 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) { @@ -2945,18 +2980,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 () { @@ -2969,21 +2992,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) { @@ -3244,19 +3252,15 @@ ARDOUR_UI::add_route (Gtk::Window* float_window) return; } - if (add_route_dialog == 0) { - add_route_dialog = new AddRouteDialog (_session); - add_route_dialog->set_position (WIN_POS_MOUSE); - 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(); @@ -3428,9 +3432,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; } @@ -3447,23 +3470,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)) { @@ -3487,7 +3512,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: @@ -3522,6 +3550,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 (); @@ -3546,6 +3579,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); @@ -3786,9 +3823,16 @@ void ARDOUR_UI::disconnect_from_jack () { if (engine) { - if (engine->disconnect_from_jack ()) { + /* drop connection to AudioEngine::Halted so that we don't act + * as if the engine unexpectedly shut down + */ + halt_connection.disconnect (); + + if (engine->stop ()) { MessageDialog msg (*editor, _("Could not disconnect from JACK")); msg.run (); + } else { + engine->Halted.connect_same_thread (halt_connection, boost::bind (&ARDOUR_UI::engine_halted, this, _1, false)); } update_sample_rate (0); @@ -3799,7 +3843,7 @@ void ARDOUR_UI::reconnect_to_jack () { if (engine) { - if (engine->reconnect_to_jack ()) { + if (engine->start ()) { MessageDialog msg (*editor, _("Could not reconnect to JACK")); msg.run (); } @@ -3832,13 +3876,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) { @@ -3859,7 +3902,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; } @@ -3998,26 +4041,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) { @@ -4104,3 +4127,32 @@ 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 (); + } +}