X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Froute_ui.cc;h=8afa706e37c1a89586dc089c410c435f18708651;hb=bb7c857a698f1eb208bd83a57eeca2b81b75cdb5;hp=b7bdeb0a6522a2984dc4602d1c369ed181909f16;hpb=69069e038126b0837853b913e8aebcd6cc0c5f3a;p=ardour.git diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index b7bdeb0a65..8afa706e37 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -47,12 +47,14 @@ #include "route_time_axis.h" #include "group_tabs.h" #include "timers.h" +#include "ui_config.h" #include "ardour/audio_track.h" #include "ardour/audioengine.h" #include "ardour/filename_extensions.h" #include "ardour/midi_track.h" #include "ardour/internal_send.h" +#include "ardour/profile.h" #include "ardour/send.h" #include "ardour/route.h" #include "ardour/session.h" @@ -87,6 +89,10 @@ RouteUI::RouteUI (ARDOUR::Session* sess) RouteUI::~RouteUI() { + if (_route) { + gui_object_state().remove_node (route_state_id()); + } + _route.reset (); /* drop reference to route, so that it can be cleaned up */ route_connections.drop_connections (); @@ -98,7 +104,7 @@ RouteUI::~RouteUI() delete input_selector; delete output_selector; delete _invert_menu; - + send_blink_connection.disconnect (); rec_blink_connection.disconnect (); } @@ -144,10 +150,10 @@ RouteUI::init () rec_enable_button = manage (new ArdourButton); rec_enable_button->set_name ("record enable button"); - rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton)); + rec_enable_button->set_icon (ArdourIcon::RecButton); UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), ""); - if (ARDOUR_UI::config()->get_blink_rec_arm()) { + if (UIConfiguration::instance().get_blink_rec_arm()) { rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display)); } @@ -160,7 +166,7 @@ RouteUI::init () monitor_input_button->set_text (_("In")); UI::instance()->set_tip (monitor_input_button, _("Monitor input"), ""); monitor_input_button->set_no_show_all (true); - + monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements)); monitor_disk_button->set_name ("monitor button"); monitor_disk_button->set_text (_("Disk")); @@ -184,7 +190,7 @@ RouteUI::init () solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false); mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false); mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false); - + monitor_input_button->set_distinct_led_click (false); monitor_disk_button->set_distinct_led_click (false); @@ -242,7 +248,7 @@ RouteUI::set_route (boost::shared_ptr rp) solo_button->set_controllable (_route->solo_control()); _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context()); - _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context()); + _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context()); _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context()); @@ -265,7 +271,7 @@ RouteUI::set_route (boost::shared_ptr rp) boost::shared_ptr t = boost::dynamic_pointer_cast(_route); t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context()); - + rec_enable_button->show(); rec_enable_button->set_controllable (t->rec_enable_control()); @@ -274,7 +280,7 @@ RouteUI::set_route (boost::shared_ptr rp) boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context()); } - } + } /* this will work for busses and tracks, and needs to be called to set up the name entry/name label display. @@ -309,7 +315,7 @@ RouteUI::set_route (boost::shared_ptr rp) update_mute_display (); update_solo_display (); - if (!ARDOUR_UI::config()->get_blink_rec_arm()) { + if (!UIConfiguration::instance().get_blink_rec_arm()) { blink_rec_display(true); // set initial rec-en button state } @@ -336,7 +342,7 @@ RouteUI::mute_press (GdkEventButton* ev) //if this is a binding action, let the ArdourButton handle it if ( BindingProxy::is_bind_action(ev) ) return false; - + multiple_mute_change = false; if (Keyboard::is_context_menu_event (ev)) { @@ -346,7 +352,7 @@ RouteUI::mute_press (GdkEventButton* ev) } mute_menu->popup(0,ev->time); - + return true; } else { @@ -368,7 +374,7 @@ RouteUI::mute_press (GdkEventButton* ev) * elements of the list we need to work * on a copy. */ - + boost::shared_ptr copy (new RouteList); *copy = *_session->get_routes (); @@ -396,12 +402,12 @@ RouteUI::mute_press (GdkEventButton* ev) boost::shared_ptr rl; - if (ev->button == 1) { + if (ev->button == 1) { if (_route->route_group()) { - + rl = _route->route_group()->route_list(); - + if (_mute_release) { _mute_release->routes = rl; } @@ -420,7 +426,7 @@ RouteUI::mute_press (GdkEventButton* ev) boost::shared_ptr rl (new RouteList); rl->push_back (_route); - + if (_mute_release) { _mute_release->routes = rl; } @@ -474,7 +480,7 @@ RouteUI::edit_output_configuration () output_selector->present (); } - output_selector->set_keep_above (true); + //output_selector->set_keep_above (true); } void @@ -490,7 +496,7 @@ RouteUI::edit_input_configuration () input_selector->present (); } - input_selector->set_keep_above (true); + //input_selector->set_keep_above (true); } bool @@ -505,7 +511,7 @@ RouteUI::solo_press(GdkEventButton* ev) //if this is a binding action, let the ArdourButton handle it if ( BindingProxy::is_bind_action(ev) ) return false; - + multiple_solo_change = false; if (Keyboard::is_context_menu_event (ev)) { @@ -540,9 +546,9 @@ RouteUI::solo_press(GdkEventButton* ev) DisplaySuspender ds; if (Config->get_solo_control_is_listen_control()) { - _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true); + _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, false); } else { - _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true); + _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, false); } } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) { @@ -590,12 +596,11 @@ RouteUI::solo_press(GdkEventButton* ev) boost::shared_ptr rl; - if (ev->button == 1) { + if (ev->button == 1) { + if (ARDOUR::Profile->get_mixbus() && _route->route_group()) { - if (_route->route_group()) { - rl = _route->route_group()->route_list(); - + if (_solo_release) { _solo_release->routes = rl; } @@ -612,6 +617,9 @@ RouteUI::solo_press(GdkEventButton* ev) } } + delete _solo_release; + _solo_release = 0; + } else { /* click: solo this route */ @@ -646,9 +654,9 @@ RouteUI::solo_release (GdkEventButton* /*ev*/) } else { DisplaySuspender ds; if (Config->get_solo_control_is_listen_control()) { - _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true); + _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, false); } else { - _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true); + _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, false); } } @@ -669,7 +677,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev) //if this is a binding action, let the ArdourButton handle it if ( BindingProxy::is_bind_action(ev) ) return false; - + if (!_session->engine().connected()) { MessageDialog msg (_("Not connected to AudioEngine - cannot engage record")); msg.run (); @@ -689,7 +697,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev) if (is_track() && rec_enable_button) { if (Keyboard::is_button2_event (ev)) { - + //rec arm does not have a momentary mode return false; @@ -707,11 +715,11 @@ RouteUI::rec_enable_press(GdkEventButton* ev) if (ev->button == 1) { boost::shared_ptr rl; - + if (_route->route_group()) { - + rl = _route->route_group()->route_list(); - + } else { rl.reset (new RouteList); rl->push_back (_route); @@ -805,7 +813,7 @@ RouteUI::monitor_disk_release (GdkEventButton* ev) bool RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice) -{ +{ if (ev->button != 1) { return false; } @@ -818,8 +826,8 @@ RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice) MonitorChoice mc; boost::shared_ptr rl; - - /* XXX for now, monitoring choices are orthogonal. cue monitoring + + /* XXX for now, monitoring choices are orthogonal. cue monitoring will follow in 3.X but requires mixing the input and playback (disk) signal together, which requires yet more buffers. */ @@ -832,7 +840,7 @@ RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice) mc = monitor_choice; } - if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { rl = _session->get_routes (); } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { @@ -848,7 +856,7 @@ RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice) } DisplaySuspender ds; - _session->set_monitoring (rl, mc, Session::rt_cleanup, true); + _session->set_monitoring (rl, mc, Session::rt_cleanup, true); return false; } @@ -1184,12 +1192,6 @@ RouteUI::solo_changed_so_update_mute () update_mute_display (); } -void -RouteUI::mute_changed(void* /*src*/) -{ - update_mute_display (); -} - ActiveState RouteUI::mute_active_state (Session* s, boost::shared_ptr r) { @@ -1203,8 +1205,7 @@ RouteUI::mute_active_state (Session* s, boost::shared_ptr r) if (r->muted ()) { /* full mute */ return Gtkmm2ext::ExplicitActive; - } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) { - /* master is NEVER muted by others */ + } else if (r->muted_by_others()) { return Gtkmm2ext::ImplicitActive; } else { /* no mute at all */ @@ -1267,7 +1268,7 @@ RouteUI::blink_rec_display (bool blinkOn) case Session::Disabled: case Session::Enabled: - if ( ARDOUR_UI::config()->get_blink_rec_arm() ) + if ( UIConfiguration::instance().get_blink_rec_arm() ) rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off ); else rec_enable_button->set_active_state ( ImplicitActive ); @@ -1428,9 +1429,14 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev) /* disable isolate for all routes */ DisplaySuspender ds; _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true); + } else { + /* enable isolate for all routes */ + DisplaySuspender ds; + _session->set_solo_isolated (_session->get_routes(), true, Session::rt_cleanup, true); } } else { + if (model == view) { /* flip just this route */ @@ -1449,9 +1455,38 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev) bool RouteUI::solo_safe_button_release (GdkEventButton* ev) { + if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) { + return true; + } + + bool view = solo_safe_led->active_state(); + bool model = _route->solo_safe(); + if (ev->button == 1) { - _route->set_solo_safe (!solo_safe_led->active_state(), this); + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { + boost::shared_ptr rl (_session->get_routes()); + if (model) { + /* disable solo safe for all routes */ + DisplaySuspender ds; + for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { + (*i)->set_solo_safe (false, this); + } + } else { + /* enable solo safe for all routes */ + DisplaySuspender ds; + for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { + (*i)->set_solo_safe (true, this); + } + } + } + else { + if (model == view) { + /* flip just this route */ + _route->set_solo_safe (!view, this); + } + } } + return false; } @@ -1500,11 +1535,11 @@ RouteUI::set_color (const Gdk::Color & c) char buf[64]; _color = c; snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue()); - + /* note: we use the route state ID here so that color is the same for both the time axis view and the mixer strip */ - + gui_object_state().set_property (route_state_id(), X_("color"), buf); _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */ } @@ -1536,66 +1571,6 @@ RouteUI::set_color_from_route () return 0; } -void -RouteUI::remove_this_route (bool apply_to_selection) -{ - if (apply_to_selection) { - ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false)); - } else { - if ((route()->is_master() || route()->is_monitor()) && - !Config->get_allow_special_bus_removal()) { - MessageDialog msg (_("That would be bad news ...."), - false, - Gtk::MESSAGE_INFO, - Gtk::BUTTONS_OK); - msg.set_secondary_text (string_compose (_( -"Removing the master or monitor bus is such a bad idea\n\ -that %1 is not going to allow it.\n\ -\n\ -If you really want to do this sort of thing\n\ -edit your ardour.rc file to set the\n\ -\"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME)); - - msg.present (); - msg.run (); - return; - } - - vector choices; - string prompt; - - if (is_track()) { - prompt = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name()); - } else { - prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name()); - } - - choices.push_back (_("No, do nothing.")); - choices.push_back (_("Yes, remove it.")); - - string title; - if (is_track()) { - title = _("Remove track"); - } else { - title = _("Remove bus"); - } - - Choice prompter (title, prompt, choices); - - if (prompter.run () == 1) { - Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this)); - } - } -} - -gint -RouteUI::idle_remove_this_route (RouteUI *rui) -{ - DisplaySuspender ds; - rui->_session->remove_route (rui->route()); - return false; -} - /** @return true if this name should be used for the route, otherwise false */ bool RouteUI::verify_new_route_name (const std::string& name) @@ -1603,12 +1578,12 @@ RouteUI::verify_new_route_name (const std::string& name) if (name.find (':') == string::npos) { return true; } - + MessageDialog colon_msg ( _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"), false, MESSAGE_QUESTION, BUTTONS_NONE ); - + colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT); colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL); @@ -1754,6 +1729,12 @@ RouteUI::set_route_active (bool a, bool apply_to_selection) } } +void +RouteUI::duplicate_selected_routes () +{ + ARDOUR_UI::instance()->start_duplicate_routes(); +} + void RouteUI::toggle_denormal_protection () { @@ -1862,41 +1843,64 @@ RouteUI::adjust_latency () LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle()); } -void -RouteUI::save_as_template () +bool +RouteUI::process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir) { std::string path; std::string safe_name; - string name; + std::string name; - path = ARDOUR::user_route_template_directory (); + prompter.get_result (name, true); - if (g_mkdir_with_parents (path.c_str(), 0755)) { - error << string_compose (_("Cannot create route template directory %1"), path) << endmsg; - return; + safe_name = legalize_for_path (name); + safe_name += template_suffix; + + path = Glib::build_filename (dir, safe_name); + + if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) { + bool overwrite = overwrite_file_dialog (prompter, + _("Confirm Template Overwrite"), + _("A template already exists with that name. Do you want to overwrite it?")); + + if (!overwrite) { + return false; + } } - Prompter p (true); // modal + _route->save_as_template (path, name); + + return true; +} + +void +RouteUI::save_as_template () +{ + std::string dir; + + dir = ARDOUR::user_route_template_directory (); - p.set_title (_("Save As Template")); - p.set_prompt (_("Template name:")); - p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); - switch (p.run()) { - case RESPONSE_ACCEPT: - break; - default: + if (g_mkdir_with_parents (dir.c_str(), 0755)) { + error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg; return; } - p.hide (); - p.get_result (name, true); + ArdourPrompter prompter (true); // modal - safe_name = legalize_for_path (name); - safe_name += template_suffix; + prompter.set_title (_("Save As Template")); + prompter.set_prompt (_("Template name:")); + prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT); - path = Glib::build_filename (path, safe_name); - - _route->save_as_template (path, name); + bool finished = false; + while (!finished) { + switch (prompter.run()) { + case RESPONSE_ACCEPT: + finished = process_save_template_prompter (prompter, dir); + break; + default: + finished = true; + break; + } + } } void @@ -1923,7 +1927,7 @@ RouteUI::parameter_changed (string const & p) } else if (p == "auto-input") { update_monitoring_display (); } else if (p == "blink-rec-arm") { - if (ARDOUR_UI::config()->get_blink_rec_arm()) { + if (UIConfiguration::instance().get_blink_rec_arm()) { rec_blink_connection.disconnect (); rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display)); } else { @@ -1967,7 +1971,7 @@ RouteUI::open_remote_control_id_dialog () if (Config->get_remote_model() == UserOrdered) { uint32_t const limit = _session->ntracks() + _session->nbusses () + 4; - + HBox* hbox = manage (new HBox); hbox->set_spacing (6); hbox->pack_start (*manage (new Label (_("Remote control ID:")))); @@ -1978,7 +1982,7 @@ RouteUI::open_remote_control_id_dialog () spin->set_value (_route->remote_control_id()); hbox->pack_start (*spin); dialog.get_vbox()->pack_start (*hbox); - + dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL); dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT); } else { @@ -1986,7 +1990,7 @@ RouteUI::open_remote_control_id_dialog () if (_route->is_master() || _route->is_monitor()) { l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n" "The remote control ID of %3 cannot be changed."), - Glib::Markup::escape_text (_route->name()), + Gtkmm2ext::markup_escape_text (_route->name()), _route->remote_control_id(), (_route->is_master() ? _("the master bus") : _("the monitor bus")))); } else { @@ -1997,7 +2001,7 @@ RouteUI::open_remote_control_id_dialog () _route->remote_control_id(), "", "", - Glib::Markup::escape_text (_route->name()), + Gtkmm2ext::markup_escape_text (_route->name()), PROGRAM_NAME)); } dialog.get_vbox()->pack_start (*l); @@ -2071,7 +2075,7 @@ RouteUI::set_invert_button_state () */ ArdourButton* b = _invert_buttons.front (); - + if (_route->phase_invert().count() == _route->phase_invert().size()) { b->set_active_state (Gtkmm2ext::ExplicitActive); } else if (_route->phase_invert().any()) { @@ -2088,7 +2092,7 @@ RouteUI::set_invert_button_state () for (vector::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) { (*i)->set_active (_route->phase_invert (j)); } - + } } @@ -2120,7 +2124,7 @@ RouteUI::invert_press (GdkEventButton* ev) */ return false; } - + delete _invert_menu; _invert_menu = new Menu; _invert_menu->set_name ("ArdourContextMenu"); @@ -2183,10 +2187,10 @@ RouteUI::track_mode_changed (void) switch (track()->mode()) { case ARDOUR::NonLayered: case ARDOUR::Normal: - rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton)); + rec_enable_button->set_icon (ArdourIcon::RecButton); break; case ARDOUR::Destructive: - rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton|ArdourButton::RecTapeMode)); + rec_enable_button->set_icon (ArdourIcon::RecTapeMode); break; } rec_enable_button->queue_draw(); @@ -2199,7 +2203,7 @@ Gdk::Color RouteUI::color () const { RouteGroup* g = _route->route_group (); - + if (g && g->is_color()) { Gdk::Color c; set_color_from_rgba (c, GroupTabs::group_color (g));