X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Froute_ui.cc;h=bf14719d70f7de4d04c982f790c9b2ad3c6cc99e;hb=d1f45e9b3d6a7e272e5563cc50175dfb6d904361;hp=c0dd43404e9c77a1c3ceb0911d474890d69c899d;hpb=51ab5ccabf432540ca935065f6c6f40a96f42dad;p=ardour.git diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index c0dd43404e..bf14719d70 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -46,16 +46,13 @@ #include "route_time_axis.h" #include "group_tabs.h" -#include "ardour/route.h" -#include "ardour/event_type_map.h" -#include "ardour/session.h" -#include "ardour/audioengine.h" #include "ardour/audio_track.h" +#include "ardour/audioengine.h" +#include "ardour/filename_extensions.h" #include "ardour/midi_track.h" +#include "ardour/route.h" +#include "ardour/session.h" #include "ardour/template_utils.h" -#include "ardour/filename_extensions.h" -#include "ardour/directory_names.h" -#include "ardour/profile.h" #include "i18n.h" using namespace Gtk; @@ -64,11 +61,13 @@ using namespace ARDOUR; using namespace PBD; uint32_t RouteUI::_max_invert_buttons = 3; +sigc::signal > RouteUI::BusSendDisplayChanged; +boost::weak_ptr RouteUI::_showing_sends_to; RouteUI::RouteUI (ARDOUR::Session* sess) : AxisView(sess) { - init (); + if (sess) init (); } RouteUI::~RouteUI() @@ -81,7 +80,6 @@ RouteUI::~RouteUI() delete sends_menu; delete record_menu; delete _invert_menu; - delete solo_safe_image; } void @@ -108,45 +106,35 @@ RouteUI::init () multiple_mute_change = false; multiple_solo_change = false; _i_am_the_modifier = 0; - solo_safe_image = 0; setup_invert_buttons (); - mute_button = manage (new BindableToggleButton ()); - // mute_button->set_self_managed (true); - mute_button->set_name ("MuteButton"); - mute_button->add (mute_button_label); - mute_button_label.show (); + mute_button = manage (new ArdourButton); + mute_button->set_name ("mute button"); UI::instance()->set_tip (mute_button, _("Mute this track"), ""); - solo_button = manage (new BindableToggleButton ()); - // solo_button->set_self_managed (true); - solo_button->set_name ("SoloButton"); - solo_button->add (solo_button_label); - solo_button_label.show (); + solo_button = manage (new ArdourButton); + solo_button->set_name ("solo button"); UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), ""); solo_button->set_no_show_all (true); - rec_enable_button = manage (new BindableToggleButton ()); - rec_enable_button->set_name ("RecordEnableButton"); - // rec_enable_button->set_self_managed (true); - rec_enable_button->add (rec_enable_button_label); - rec_enable_button_label.show (); + rec_enable_button = manage (new ArdourButton); + rec_enable_button->set_name ("record enable button"); + rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor); UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), ""); - show_sends_button = manage (new BindableToggleButton ("")); - show_sends_button->set_name ("SendAlert"); - // show_sends_button->set_self_managed (true); + show_sends_button = manage (new ArdourButton); + show_sends_button->set_name ("send alert button"); UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), ""); - monitor_input_button = manage (new ArdourButton ()); - monitor_input_button->set_name ("monitor"); + monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements)); + monitor_input_button->set_name ("monitor button"); 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 ()); - monitor_disk_button->set_name ("monitor"); + + monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements)); + monitor_disk_button->set_name ("monitor button"); monitor_disk_button->set_text (_("Disk")); UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), ""); monitor_disk_button->set_no_show_all (true); @@ -155,8 +143,8 @@ RouteUI::init () _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context()); _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context()); - _session->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context()); - Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context()); + _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context()); + Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context()); rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false); rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false); @@ -177,6 +165,8 @@ RouteUI::init () monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press)); monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release)); + + BusSendDisplayChanged.connect (sigc::mem_fun (*this, &RouteUI::bus_send_display_changed)); } void @@ -218,7 +208,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), ui_bind (&RouteUI::mute_changed, this, _1), gui_context()); + _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context()); _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context()); _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context()); @@ -226,10 +216,10 @@ RouteUI::set_route (boost::shared_ptr rp) _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context()); _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context()); - _route->PropertyChanged.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::property_changed, this, _1), gui_context()); + _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context()); - _route->io_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::setup_invert_buttons, this), gui_context ()); - _route->gui_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::route_gui_changed, this, _1), gui_context ()); + _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ()); + _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ()); if (_session->writable() && is_track()) { boost::shared_ptr t = boost::dynamic_pointer_cast(_route); @@ -239,14 +229,18 @@ RouteUI::set_route (boost::shared_ptr rp) rec_enable_button->show(); rec_enable_button->set_controllable (t->rec_enable_control()); - update_rec_display (); - if (is_midi_track()) { midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this), - ui_bind (&RouteUI::step_edit_changed, this, _1), gui_context()); + 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. + */ + + update_rec_display (); if (is_track()) { boost::shared_ptr t = boost::dynamic_pointer_cast(_route); @@ -260,7 +254,7 @@ RouteUI::set_route (boost::shared_ptr rp) mute_button->show(); - if (_route->is_monitor()) { + if (_route->is_monitor() || _route->is_master()) { solo_button->hide (); } else { solo_button->show(); @@ -270,6 +264,12 @@ RouteUI::set_route (boost::shared_ptr rp) setup_invert_buttons (); set_invert_button_state (); + + boost::shared_ptr s = _showing_sends_to.lock (); + bus_send_display_changed (s); + + update_mute_display (); + update_solo_display (); } void @@ -319,11 +319,31 @@ RouteUI::mute_press (GdkEventButton* ev) if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { + /* toggle mute on everything (but + * exclude the master and monitor) + * + * because we are going to erase + * elements of the list we need to work + * on a copy. + */ + + boost::shared_ptr copy (new RouteList); + + *copy = *_session->get_routes (); + + for (RouteList::iterator i = copy->begin(); i != copy->end(); ) { + if ((*i)->is_master() || (*i)->is_monitor()) { + i = copy->erase (i); + } else { + ++i; + } + } + if (_mute_release) { - _mute_release->routes = _session->get_routes (); + _mute_release->routes = copy; } - _session->set_mute (_session->get_routes(), !_route->muted()); + _session->set_mute (copy, !_route->muted()); } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { @@ -331,12 +351,23 @@ RouteUI::mute_press (GdkEventButton* ev) NOTE: Primary-button2 is MIDI learn. */ - if (ev->button == 1 && _route->route_group()) { - if (_mute_release) { - _mute_release->routes = _session->get_routes (); + boost::shared_ptr rl; + + if (ev->button == 1) { + + if (_route->route_group()) { + + rl = _route->route_group()->route_list(); + + if (_mute_release) { + _mute_release->routes = rl; + } + } else { + rl.reset (new RouteList); + rl->push_back (_route); } - _session->set_mute (_session->get_routes(), !_route->muted(), Session::rt_cleanup, true); + _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true); } } else { @@ -345,7 +376,7 @@ RouteUI::mute_press (GdkEventButton* ev) boost::shared_ptr rl (new RouteList); rl->push_back (_route); - + if (_mute_release) { _mute_release->routes = rl; } @@ -390,7 +421,8 @@ RouteUI::solo_press(GdkEventButton* ev) if (Keyboard::is_context_menu_event (ev)) { - if (!solo_isolated_led) { + if (! (solo_isolated_led && solo_isolated_led->is_visible()) || + ! (solo_safe_led && solo_safe_led->is_visible())) { if (solo_menu == 0) { build_solo_menu (); @@ -467,16 +499,30 @@ RouteUI::solo_press(GdkEventButton* ev) NOTE: Primary-button2 is MIDI learn. */ - if (ev->button == 1 && _route->route_group()) { + /* Primary-button1 applies change to the mix group even if it is not active + NOTE: Primary-button2 is MIDI learn. + */ + + boost::shared_ptr rl; + + if (ev->button == 1) { - if (_solo_release) { - _solo_release->routes = _route->route_group()->route_list(); + if (_route->route_group()) { + + rl = _route->route_group()->route_list(); + + if (_solo_release) { + _solo_release->routes = rl; + } + } else { + rl.reset (new RouteList); + rl->push_back (_route); } if (Config->get_solo_control_is_listen_control()) { - _session->set_listen (_route->route_group()->route_list(), !_route->listening_via_monitor(), Session::rt_cleanup, true); + _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true); } else { - _session->set_solo (_route->route_group()->route_list(), !_route->self_soloed(), Session::rt_cleanup, true); + _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true); } } @@ -544,10 +590,11 @@ RouteUI::rec_enable_press(GdkEventButton* ev) if (is_midi_track()) { - /* cannot rec-enable while step-editing */ + /* rec-enable button exits from step editing */ if (midi_track()->step_editing()) { - return true; + midi_track()->set_step_editing (false); + return true; } } @@ -560,15 +607,28 @@ RouteUI::rec_enable_press(GdkEventButton* ev) } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) { - _session->set_record_enabled (_session->get_routes(), !rec_enable_button->get_active()); + _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state()); } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { /* Primary-button1 applies change to the route group (even if it is not active) NOTE: Primary-button2 is MIDI learn. */ - if (ev->button == 1 && _route->route_group()) { - _session->set_record_enabled (_route->route_group()->route_list(), !rec_enable_button->get_active(), Session::rt_cleanup, true); + + 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); + } + + _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true); } } else if (Keyboard::is_context_menu_event (ev)) { @@ -579,7 +639,7 @@ RouteUI::rec_enable_press(GdkEventButton* ev) boost::shared_ptr rl (new RouteList); rl->push_back (route()); - _session->set_record_enabled (rl, !rec_enable_button->get_active()); + _session->set_record_enabled (rl, !rec_enable_button->active_state()); } } @@ -608,32 +668,28 @@ RouteUI::update_monitoring_display () MonitorState ms = t->monitoring_state(); if (t->monitoring_choice() & MonitorInput) { - monitor_input_button->set_state (CairoWidget::Active, true); - monitor_input_button->set_state (CairoWidget::Mid, false); + monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive); } else { if (ms & MonitoringInput) { - monitor_input_button->set_state (CairoWidget::Mid, true); - monitor_input_button->set_state (CairoWidget::Active, false); + monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive); } else { - monitor_input_button->set_state (CairoWidget::State (CairoWidget::Active|CairoWidget::Mid), false); + monitor_input_button->unset_active_state (); } } if (t->monitoring_choice() & MonitorDisk) { - monitor_disk_button->set_state (CairoWidget::Active, true); - monitor_disk_button->set_state (CairoWidget::Mid, false); + monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive); } else { if (ms & MonitoringDisk) { - monitor_disk_button->set_state (CairoWidget::Mid, true); - monitor_disk_button->set_state (CairoWidget::Active, false); + monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive); } else { - monitor_disk_button->set_state (CairoWidget::State (CairoWidget::Active|CairoWidget::Mid), false); + monitor_disk_button->unset_active_state (); } } } bool -RouteUI::monitor_input_press(GdkEventButton* ev) +RouteUI::monitor_input_press(GdkEventButton*) { return true; } @@ -645,7 +701,7 @@ RouteUI::monitor_input_release(GdkEventButton* ev) } bool -RouteUI::monitor_disk_press (GdkEventButton* ev) +RouteUI::monitor_disk_press (GdkEventButton*) { return true; } @@ -748,7 +804,7 @@ RouteUI::step_edit_changed (bool yn) { if (yn) { if (rec_enable_button) { - rec_enable_button->set_visual_state (3); + rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive); } start_step_editing (); @@ -760,7 +816,7 @@ RouteUI::step_edit_changed (bool yn) } else { if (rec_enable_button) { - rec_enable_button->set_visual_state (0); + rec_enable_button->unset_active_state (); } stop_step_editing (); @@ -900,22 +956,13 @@ RouteUI::show_sends_press(GdkEventButton* ev) } else { - /* change button state */ - - show_sends_button->set_active (!show_sends_button->get_active()); + boost::shared_ptr s = _showing_sends_to.lock (); - /* start blinking */ - - if (show_sends_button->get_active()) { - /* show sends to this bus */ - MixerStrip::SwitchIO (_route); - send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun(*this, &RouteUI::send_blink)); + if (s == _route) { + set_showing_sends_to (boost::shared_ptr ()); } else { - /* everybody back to normal */ - send_blink_connection.disconnect (); - MixerStrip::SwitchIO (boost::shared_ptr()); + set_showing_sends_to (_route); } - } } @@ -936,121 +983,71 @@ RouteUI::send_blink (bool onoff) } if (onoff) { - show_sends_button->set_state (STATE_ACTIVE); + show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive); } else { - show_sends_button->set_state (STATE_NORMAL); + show_sends_button->unset_active_state (); } } -int -RouteUI::solo_visual_state (boost::shared_ptr r) +Gtkmm2ext::ActiveState +RouteUI::solo_active_state (boost::shared_ptr r) { if (r->is_master() || r->is_monitor()) { - return 0; + return Gtkmm2ext::Off; } if (Config->get_solo_control_is_listen_control()) { if (r->listening_via_monitor()) { - return 1; + return Gtkmm2ext::ExplicitActive; } else { - return 0; + return Gtkmm2ext::Off; } } if (r->soloed()) { if (!r->self_soloed()) { - return 3; + return Gtkmm2ext::ImplicitActive; } else { - return 1; + return Gtkmm2ext::ExplicitActive; } } else { - return 0; + return Gtkmm2ext::Off; } } -int -RouteUI::solo_visual_state_with_isolate (boost::shared_ptr r) +Gtkmm2ext::ActiveState +RouteUI::solo_isolate_active_state (boost::shared_ptr r) { if (r->is_master() || r->is_monitor()) { - return 0; - } - - if (Config->get_solo_control_is_listen_control()) { - - if (r->listening_via_monitor()) { - return 1; - } else { - return 0; - } - + return Gtkmm2ext::Off; } if (r->solo_isolated()) { - return 2; - } else if (r->soloed()) { - if (!r->self_soloed()) { - return 3; - } else { - return 1; - } + return Gtkmm2ext::ExplicitActive; } else { - return 0; + return Gtkmm2ext::Off; } } -int -RouteUI::solo_isolate_visual_state (boost::shared_ptr r) +Gtkmm2ext::ActiveState +RouteUI::solo_safe_active_state (boost::shared_ptr r) { if (r->is_master() || r->is_monitor()) { - return 0; - } - - if (r->solo_isolated()) { - return 1; - } else { - return 0; - } -} - -int -RouteUI::solo_safe_visual_state (boost::shared_ptr r) -{ - if (r->is_master() || r->is_monitor()) { - return 0; + return Gtkmm2ext::Off; } if (r->solo_safe()) { - return 1; + return Gtkmm2ext::ExplicitActive; } else { - return 0; + return Gtkmm2ext::Off; } } void RouteUI::update_solo_display () { - bool x; - - if (Config->get_solo_control_is_listen_control()) { - - if (solo_button->get_active() != (x = _route->listening_via_monitor())) { - ++_i_am_the_modifier; - solo_button->set_active(x); - --_i_am_the_modifier; - } - - } else { - - if (solo_button->get_active() != (x = _route->soloed())) { - ++_i_am_the_modifier; - solo_button->set_active (x); - --_i_am_the_modifier; - } - - } - bool yn = _route->solo_safe (); if (solo_safe_check && solo_safe_check->get_active() != yn) { @@ -1066,14 +1063,22 @@ RouteUI::update_solo_display () set_button_names (); if (solo_isolated_led) { - solo_isolated_led->set_state (CairoWidget::Active, _route->solo_isolated()); + if (_route->solo_isolated()) { + solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive); + } else { + solo_isolated_led->unset_active_state (); + } } if (solo_safe_led) { - solo_safe_led->set_state (CairoWidget::Active, _route->solo_safe()); + if (_route->solo_safe()) { + solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive); + } else { + solo_safe_led->unset_active_state (); + } } - solo_button->set_visual_state (solo_visual_state (_route)); + solo_button->set_active_state (solo_active_state (_route)); /* some changes to solo status can affect mute display, so catch up */ @@ -1093,11 +1098,11 @@ RouteUI::mute_changed(void* /*src*/) update_mute_display (); } -int -RouteUI::mute_visual_state (Session* s, boost::shared_ptr r) +ActiveState +RouteUI::mute_active_state (Session* s, boost::shared_ptr r) { - if (r->is_master() || r->is_monitor()) { - return 0; + if (r->is_monitor()) { + return ActiveState(0); } @@ -1105,26 +1110,27 @@ RouteUI::mute_visual_state (Session* s, boost::shared_ptr r) if (r->muted ()) { /* full mute */ - return 2; - } else if (s->soloing() && !r->soloed() && !r->solo_isolated()) { - return 1; + return Gtkmm2ext::ExplicitActive; + } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) { + /* master is NEVER muted by others */ + return Gtkmm2ext::ImplicitActive; } else { /* no mute at all */ - return 0; + return Gtkmm2ext::Off; } } else { if (r->muted()) { /* full mute */ - return 2; + return Gtkmm2ext::ExplicitActive; } else { /* no mute at all */ - return 0; + return Gtkmm2ext::Off; } } - return 0; + return ActiveState(0); } void @@ -1134,20 +1140,7 @@ RouteUI::update_mute_display () return; } - bool model = _route->muted(); - bool view = mute_button->get_active(); - - /* first make sure the button's "depressed" visual - is correct. - */ - - if (model != view) { - ++_i_am_the_modifier; - mute_button->set_active (model); - --_i_am_the_modifier; - } - - mute_button->set_visual_state (mute_visual_state (_session, _route)); + mute_button->set_active_state (mute_active_state (_session, _route)); } void @@ -1171,30 +1164,15 @@ RouteUI::update_rec_display () return; } - bool model = _route->record_enabled(); - bool view = rec_enable_button->get_active(); - - /* first make sure the button's "depressed" visual - is correct. - */ - - if (model != view) { - ++_i_am_the_modifier; - rec_enable_button->set_active (model); - --_i_am_the_modifier; - } - - /* now make sure its color state is correct */ - - if (model) { + if (_route->record_enabled()) { switch (_session->record_status ()) { case Session::Recording: - rec_enable_button->set_visual_state (1); + rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive); break; case Session::Disabled: case Session::Enabled: - rec_enable_button->set_visual_state (2); + rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive); break; } @@ -1204,7 +1182,7 @@ RouteUI::update_rec_display () } } else { - rec_enable_button->set_visual_state (0); + rec_enable_button->unset_active_state (); if (step_edit_item) { step_edit_item->set_sensitive (true); @@ -1340,7 +1318,7 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev) return true; } - bool view = (solo_isolated_led->state() & (CairoWidget::Active|CairoWidget::Mid)); + bool view = solo_isolated_led->active_state(); bool model = _route->solo_isolated(); /* called BEFORE the view has changed */ @@ -1369,10 +1347,13 @@ RouteUI::solo_isolate_button_release (GdkEventButton* ev) } bool -RouteUI::solo_safe_button_release (GdkEventButton*) +RouteUI::solo_safe_button_release (GdkEventButton* ev) { - _route->set_solo_safe (!(solo_safe_led->state() & (CairoWidget::Active|CairoWidget::Mid)), this); - return true; + if (ev->button == 1) { + _route->set_solo_safe (!solo_safe_led->active_state(), this); + return true; + } + return false; } void @@ -1416,17 +1397,19 @@ RouteUI::choose_color () void RouteUI::set_color (const Gdk::Color & c) { - char buf[64]; + /* leave _color alone in the group case so that tracks can retain their + * own pre-group colors. + */ + 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 (route_state_id(), X_("color"), buf); + gui_object_state().set_property (route_state_id(), X_("color"), buf); _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */ } @@ -1571,6 +1554,9 @@ RouteUI::route_rename () done = true; } break; + default: + done = true; + break; } } @@ -1707,14 +1693,14 @@ RouteUI::adjust_latency () void RouteUI::save_as_template () { - sys::path path; + std::string path; std::string safe_name; string name; path = ARDOUR::user_route_template_directory (); - if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) { - error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg; + if (g_mkdir_with_parents (path.c_str(), 0755)) { + error << string_compose (_("Cannot create route template directory %1"), path) << endmsg; return; } @@ -1736,15 +1722,15 @@ RouteUI::save_as_template () safe_name = legalize_for_path (name); safe_name += template_suffix; - path /= safe_name; + path = Glib::build_filename (path, safe_name); - _route->save_as_template (path.to_string(), name); + _route->save_as_template (path, name); } void RouteUI::check_rec_enable_sensitivity () { - if (_session->transport_rolling() && rec_enable_button->get_active() && Config->get_disable_disarm_during_roll()) { + if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) { rec_enable_button->set_sensitive (false); } else { rec_enable_button->set_sensitive (true); @@ -1795,27 +1781,53 @@ void RouteUI::open_remote_control_id_dialog () { ArdourDialog dialog (_("Remote Control ID")); + SpinButton* spin = 0; - uint32_t const limit = _session->ntracks() + _session->nbusses () + 4; + dialog.get_vbox()->set_border_width (18); - HBox* hbox = manage (new HBox); - hbox->set_spacing (6); - hbox->pack_start (*manage (new Label (_("Remote control ID:")))); - SpinButton* spin = manage (new SpinButton); - spin->set_digits (0); - spin->set_increments (1, 10); - spin->set_range (0, limit); - 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); + 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:")))); + spin = manage (new SpinButton); + spin->set_digits (0); + spin->set_increments (1, 10); + spin->set_range (0, limit); + 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 { + Label* l = manage (new Label()); + 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()), + _route->remote_control_id(), + (_route->is_master() ? _("the master bus") : _("the monitor bus")))); + } else { + l->set_markup (string_compose (_("The remote control ID of %6 is: %3\n\n\n" + "Remote Control IDs are currently determined by track/bus ordering in %1\n\n" + "%4Use the User Interaction tab of the Preferences window if you want to change this%5"), + (Config->get_remote_model() == MixerOrdered ? _("the mixer") : _("the editor")), + (is_track() ? _("track") : _("bus")), + _route->remote_control_id(), + "", + "", + Glib::Markup::escape_text (_route->name()))); + } + dialog.get_vbox()->pack_start (*l); + dialog.add_button (Stock::OK, RESPONSE_CANCEL); + } dialog.show_all (); int const r = dialog.run (); - if (r == RESPONSE_ACCEPT) { + if (r == RESPONSE_ACCEPT && spin) { _route->set_remote_control_id (spin->get_value_as_int ()); } } @@ -1824,7 +1836,7 @@ void RouteUI::setup_invert_buttons () { /* remove old invert buttons */ - for (list::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) { + for (vector::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) { _invert_button_box.remove (**i); } @@ -1839,27 +1851,33 @@ RouteUI::setup_invert_buttons () uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1; for (uint32_t i = 0; i < to_add; ++i) { - BindableToggleButton* b = manage (new BindableToggleButton); - b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_toggled), i, b)); + ArdourButton* b = manage (new ArdourButton); + b->set_size_request(20,20); b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press)); + b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i)); - b->set_name (X_("MixerInvertButton")); + b->set_name (X_("invert button")); if (to_add == 1) { - b->add (*manage (new Label (X_("Ø")))); + if (N > 1) { + b->set_text (string_compose (X_("Ø (%1)"), N)); + } else { + b->set_text (X_("Ø")); + } } else { - b->add (*manage (new Label (string_compose (X_("Ø%1"), i + 1)))); + b->set_text (string_compose (X_("Ø%1"), i + 1)); } - if (N <= 4) { + if (N <= _max_invert_buttons) { UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) channel %1 of this track. Right-click to show menu."), i + 1)); } else { - UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) all channels of this track. Right-click to show menu."), i + 1)); + UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)")); } _invert_buttons.push_back (b); _invert_button_box.pack_start (*b); } + _invert_button_box.set_spacing (1); _invert_button_box.show_all (); } @@ -1870,53 +1888,69 @@ RouteUI::set_invert_button_state () uint32_t const N = _route->input()->n_ports().n_audio(); if (N > _max_invert_buttons) { - _invert_buttons.front()->set_active (_route->phase_invert().any()); - --_i_am_the_modifier; - return; - } - int j = 0; - for (list::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) { - (*i)->set_active (_route->phase_invert (j)); + /* One button for many channels; explicit active if all channels are inverted, + implicit active if some are, off if none are. + */ + + 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()) { + b->set_active_state (Gtkmm2ext::ImplicitActive); + } else { + b->set_active_state (Gtkmm2ext::Off); + } + + } else { + + /* One button per channel; just set active */ + + int j = 0; + for (vector::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) { + (*i)->set_active (_route->phase_invert (j)); + } + } --_i_am_the_modifier; } -void -RouteUI::invert_toggled (uint32_t i, BindableToggleButton* b) -{ - if (_i_am_the_modifier) { - return; - } - - uint32_t const N = _route->input()->n_ports().n_audio(); - if (N <= _max_invert_buttons) { - _route->set_phase_invert (i, b->get_active ()); - } else { - boost::dynamic_bitset<> p (N); - if (b->get_active ()) { - p.set (); +bool +RouteUI::invert_release (GdkEventButton* ev, uint32_t i) +{ + if (ev->button == 1 && i < _invert_buttons.size()) { + uint32_t const N = _route->input()->n_ports().n_audio (); + if (N <= _max_invert_buttons) { + /* left-click inverts phase so long as we have a button per channel */ + _route->set_phase_invert (i, !_invert_buttons[i]->get_active()); + return true; } - _route->set_phase_invert (p); } + return false; } + bool RouteUI::invert_press (GdkEventButton* ev) { using namespace Menu_Helpers; - if (ev->button != 3) { + uint32_t const N = _route->input()->n_ports().n_audio(); + if (N <= _max_invert_buttons && ev->button != 3) { + /* If we have an invert button per channel, we only pop + up a menu on right-click; left click is handled + on release. + */ return true; } - + delete _invert_menu; _invert_menu = new Menu; _invert_menu->set_name ("ArdourContextMenu"); MenuList& items = _invert_menu->items (); - uint32_t const N = _route->input()->n_ports().n_audio(); for (uint32_t i = 0; i < N; ++i) { items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i))); CheckMenuItem* e = dynamic_cast (&items.back ()); @@ -1943,7 +1977,7 @@ RouteUI::invert_menu_toggled (uint32_t c) void RouteUI::set_invert_sensitive (bool yn) { - for (list::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) { + for (vector::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) { (*b)->set_sensitive (yn); } } @@ -1981,3 +2015,28 @@ RouteUI::color () const return _color; } + +void +RouteUI::set_showing_sends_to (boost::shared_ptr send_to) +{ + _showing_sends_to = send_to; + BusSendDisplayChanged (send_to); /* EMIT SIGNAL */ +} + +void +RouteUI::bus_send_display_changed (boost::shared_ptr send_to) +{ + if (_route == send_to) { + show_sends_button->set_active (true); + send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink)); + } else { + show_sends_button->set_active (false); + send_blink_connection.disconnect (); + } +} + +RouteGroup* +RouteUI::route_group() const +{ + return _route->route_group(); +}