X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Froute_time_axis.cc;h=8871b7bbe119c0179a9e8cad3cc0a1af7a0399cc;hb=c78528dcea03a61685ad0586eaa6302847af6fe9;hp=3aee99b0fbad5db917e1654bf1ed3b21bd8e559c;hpb=465aaffdd44d3cfaed0c1313599f11b1f75086ee;p=ardour.git diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index 3aee99b0fb..8871b7bbe1 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -113,7 +113,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, boost::sh , playlist_button (_("p")) , automation_button (_("a")) , gm (sess, slider, true, 115) - , _ignore_track_mode_change (false) { gm.set_controls (_route, _route->shared_peak_meter(), _route->amp()); gm.get_level_meter().set_no_show_all(); @@ -135,9 +134,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, boost::sh timestretch_rect = 0; no_redraw = false; - destructive_track_mode_item = 0; - normal_track_mode_item = 0; - non_layered_track_mode_item = 0; ignore_toggle = false; @@ -216,7 +212,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, boost::sh if (is_track()) { - track()->TrackModeChanged.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::track_mode_changed, this), gui_context()); track()->FreezeChange.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::map_frozen, this), gui_context()); track()->SpeedChanged.connect (*this, invalidator (*this), boost::bind (&RouteTimeAxisView::speed_changed, this), gui_context()); @@ -236,10 +231,12 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, boost::sh plist->add (ARDOUR::Properties::solo, true); route_group_menu = new RouteGroupMenu (_session, plist); - route_group_menu->GroupSelected.connect (sigc::mem_fun (*this, &RouteTimeAxisView::set_route_group_from_menu)); gm.get_gain_slider().signal_scroll_event().connect(sigc::mem_fun(*this, &RouteTimeAxisView::controls_ebox_scroll), false); gm.get_gain_slider().set_name ("TrackGainFader"); + + show_name_entry (); + hide_name_label (); } RouteTimeAxisView::~RouteTimeAxisView () @@ -285,24 +282,15 @@ RouteTimeAxisView::route_group_click (GdkEventButton *ev) return false; } - route_group_menu->build (_route->route_group ()); + WeakRouteList r; + r.push_back (route ()); + + route_group_menu->build (r); route_group_menu->menu()->popup (ev->button, ev->time); return false; } -void -RouteTimeAxisView::set_route_group_from_menu (RouteGroup *eg) -{ - if (eg) { - eg->add (_route); - } else { - if (_route->route_group()) { - _route->route_group()->remove (_route); - } - } -} - void RouteTimeAxisView::playlist_changed () { @@ -353,7 +341,7 @@ void RouteTimeAxisView::automation_click () { conditionally_add_to_selection (); - build_automation_action_menu (); + build_automation_action_menu (false); automation_action_menu->popup (1, gtk_get_current_event_time()); } @@ -387,7 +375,7 @@ RouteTimeAxisView::set_state (const XMLNode& node, int version) } void -RouteTimeAxisView::build_automation_action_menu () +RouteTimeAxisView::build_automation_action_menu (bool for_selection) { using namespace Menu_Helpers; @@ -406,13 +394,13 @@ RouteTimeAxisView::build_automation_action_menu () automation_action_menu->set_name ("ArdourContextMenu"); items.push_back (MenuElem (_("Show All Automation"), - sigc::mem_fun(*this, &RouteTimeAxisView::show_all_automation))); + sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::show_all_automation), for_selection))); items.push_back (MenuElem (_("Show Existing Automation"), - sigc::mem_fun(*this, &RouteTimeAxisView::show_existing_automation))); + sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::show_existing_automation), for_selection))); items.push_back (MenuElem (_("Hide All Automation"), - sigc::mem_fun(*this, &RouteTimeAxisView::hide_all_automation))); + sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::hide_all_automation), for_selection))); items.push_back (SeparatorElem ()); @@ -420,7 +408,7 @@ RouteTimeAxisView::build_automation_action_menu () so it was detached above */ items.push_back (MenuElem (_("Plugins"), subplugin_menu)); - items.back().set_sensitive (!subplugin_menu.items().empty()); + items.back().set_sensitive (!subplugin_menu.items().empty() && (!for_selection || _editor.get_selection().tracks.size() == 1));; } void @@ -464,11 +452,49 @@ RouteTimeAxisView::build_display_menu () RadioMenuItem::Group layers_group; - layers_items.push_back(RadioMenuElem (layers_group, _("Overlaid"), - sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Overlaid))); - layers_items.push_back(RadioMenuElem (layers_group, _("Stacked"), - sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Stacked))); + /* Find out how many overlaid/stacked tracks we have in the selection */ + + int overlaid = 0; + int stacked = 0; + TrackSelection const & s = _editor.get_selection().tracks; + for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) { + StreamView* v = (*i)->view (); + if (!v) { + continue; + } + + switch (v->layer_display ()) { + case Overlaid: + ++overlaid; + break; + case Stacked: + ++stacked; + break; + } + } + /* We're not connecting to signal_toggled() here; in the case where these two items are + set to be in the `inconsistent' state, it seems that one or other will end up active + as well as inconsistent (presumably due to the RadioMenuItem::Group). Then when you + select the active one, no toggled signal is emitted so nothing happens. + */ + + layers_items.push_back (RadioMenuElem (layers_group, _("Overlaid"))); + RadioMenuItem* i = dynamic_cast (&layers_items.back ()); + i->set_active (overlaid != 0 && stacked == 0); + i->set_inconsistent (overlaid != 0 && stacked != 0); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Overlaid, true)); + + layers_items.push_back ( + RadioMenuElem (layers_group, _("Stacked"), + sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Stacked, true)) + ); + + i = dynamic_cast (&layers_items.back ()); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_layer_display), Stacked, true)); + i->set_active (overlaid == 0 && stacked != 0); + i->set_inconsistent (overlaid != 0 && stacked != 0); + items.push_back (MenuElem (_("Layers"), *layers_menu)); if (!Profile->get_sae()) { @@ -478,23 +504,101 @@ RouteTimeAxisView::build_display_menu () alignment_menu->set_name ("ArdourContextMenu"); RadioMenuItem::Group align_group; - - alignment_items.push_back (RadioMenuElem (align_group, _("Align With Existing Material"), - sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_style), ExistingMaterial))); - align_existing_item = dynamic_cast(&alignment_items.back()); - if (track()->alignment_style() == ExistingMaterial) { - align_existing_item->set_active(); - } - - alignment_items.push_back (RadioMenuElem (align_group, _("Align With Capture Time"), - sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_style), CaptureTime))); - align_capture_item = dynamic_cast(&alignment_items.back()); - if (track()->alignment_style() == CaptureTime) { - align_capture_item->set_active(); + + /* Same verbose hacks as for the layering options above */ + + int existing = 0; + int capture = 0; + int automatic = 0; + int styles = 0; + boost::shared_ptr first_track; + + TrackSelection const & s = _editor.get_selection().tracks; + for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) { + RouteTimeAxisView* r = dynamic_cast (*i); + if (!r || !r->is_track ()) { + continue; + } + + if (!first_track) { + first_track = r->track(); + } + + switch (r->track()->alignment_choice()) { + case Automatic: + ++automatic; + styles |= 0x1; + switch (r->track()->alignment_style()) { + case ExistingMaterial: + ++existing; + break; + case CaptureTime: + ++capture; + break; + } + break; + case UseExistingMaterial: + ++existing; + styles |= 0x2; + break; + case UseCaptureTime: + ++capture; + styles |= 0x4; + break; + } } - - items.push_back (MenuElem (_("Alignment"), *alignment_menu)); - track()->AlignmentStyleChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteTimeAxisView::align_style_changed, this), gui_context()); + + bool inconsistent; + switch (styles) { + case 1: + case 2: + case 4: + inconsistent = false; + break; + default: + inconsistent = true; + break; + } + + RadioMenuItem* i; + + if (!inconsistent && first_track) { + + alignment_items.push_back (RadioMenuElem (align_group, _("Automatic (based on I/O connections)"))); + i = dynamic_cast (&alignment_items.back()); + i->set_active (automatic != 0 && existing == 0 && capture == 0); + i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, Automatic, true)); + + switch (first_track->alignment_choice()) { + case Automatic: + switch (first_track->alignment_style()) { + case ExistingMaterial: + alignment_items.push_back (MenuElem (_("(Currently: Existing Material)"))); + break; + case CaptureTime: + alignment_items.push_back (MenuElem (_("(Currently: Capture Time)"))); + break; + } + break; + default: + break; + } + + alignment_items.push_back (RadioMenuElem (align_group, _("Align With Existing Material"))); + i = dynamic_cast (&alignment_items.back()); + i->set_active (existing != 0 && capture == 0 && automatic == 0); + i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, UseExistingMaterial, true)); + + alignment_items.push_back (RadioMenuElem (align_group, _("Align With Capture Time"))); + i = dynamic_cast (&alignment_items.back()); + i->set_active (existing == 0 && capture != 0 && automatic == 0); + i->signal_activate().connect (sigc::bind (sigc::mem_fun(*this, &RouteTimeAxisView::set_align_choice), i, UseCaptureTime, true)); + + items.push_back (MenuElem (_("Alignment"), *alignment_menu)); + + } else { + /* show nothing */ + } Menu* mode_menu = manage (new Menu); MenuList& mode_items = mode_menu->items (); @@ -502,36 +606,46 @@ RouteTimeAxisView::build_display_menu () RadioMenuItem::Group mode_group; - mode_items.push_back (RadioMenuElem (mode_group, _("Normal Mode"), sigc::bind ( - sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), - ARDOUR::Normal))); - normal_track_mode_item = dynamic_cast(&mode_items.back()); + int normal = 0; + int tape = 0; + int non_layered = 0; - mode_items.push_back (RadioMenuElem (mode_group, _("Tape Mode"), sigc::bind ( - sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), - ARDOUR::Destructive))); - destructive_track_mode_item = dynamic_cast(&mode_items.back()); + for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) { + RouteTimeAxisView* r = dynamic_cast (*i); + if (!r || !r->is_track ()) { + continue; + } + + switch (r->track()->mode()) { + case Normal: + ++normal; + break; + case Destructive: + ++tape; + break; + case NonLayered: + ++non_layered; + break; + } + } - mode_items.push_back (RadioMenuElem (mode_group, _("Non-Layered Mode"), - sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::NonLayered))); - non_layered_track_mode_item = dynamic_cast(&mode_items.back()); + mode_items.push_back (RadioMenuElem (mode_group, _("Normal Mode"))); + i = dynamic_cast (&mode_items.back ()); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal, true)); + i->set_active (normal != 0 && tape == 0 && non_layered == 0); + i->set_inconsistent (normal != 0 && (tape != 0 || non_layered != 0)); + mode_items.push_back (RadioMenuElem (mode_group, _("Tape Mode"))); + i = dynamic_cast (&mode_items.back ()); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive, true)); + i->set_active (normal == 0 && tape != 0 && non_layered == 0); + i->set_inconsistent (tape != 0 && (normal != 0 || non_layered != 0)); - _ignore_track_mode_change = true; - - switch (track()->mode()) { - case ARDOUR::Destructive: - destructive_track_mode_item->set_active (); - break; - case ARDOUR::Normal: - normal_track_mode_item->set_active (); - break; - case ARDOUR::NonLayered: - non_layered_track_mode_item->set_active (); - break; - } - - _ignore_track_mode_change = false; + mode_items.push_back (RadioMenuElem (mode_group, _("Non-Layered Mode"))); + i = dynamic_cast (&mode_items.back ()); + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::NonLayered, true)); + i->set_active (normal == 0 && tape == 0 && non_layered != 0); + i->set_inconsistent (non_layered != 0 && (normal != 0 || tape != 0)); items.push_back (MenuElem (_("Mode"), *mode_menu)); } @@ -545,133 +659,104 @@ RouteTimeAxisView::build_display_menu () build_playlist_menu (); items.push_back (MenuElem (_("Playlist"), *playlist_action_menu)); + items.back().set_sensitive (_editor.get_selection().tracks.size() <= 1); route_group_menu->detach (); - route_group_menu->build (_route->route_group ()); + + WeakRouteList r; + for (TrackSelection::iterator i = _editor.get_selection().tracks.begin(); i != _editor.get_selection().tracks.end(); ++i) { + RouteTimeAxisView* rtv = dynamic_cast (*i); + if (rtv) { + r.push_back (rtv->route ()); + } + } + + if (r.empty ()) { + r.push_back (route ()); + } + + route_group_menu->build (r); items.push_back (MenuElem (_("Route Group"), *route_group_menu->menu ())); - build_automation_action_menu (); + build_automation_action_menu (true); items.push_back (MenuElem (_("Automation"), *automation_action_menu)); items.push_back (SeparatorElem()); } - items.push_back (CheckMenuElem (_("Active"), sigc::mem_fun(*this, &RouteUI::toggle_route_active))); - route_active_menu_item = dynamic_cast (&items.back()); - route_active_menu_item->set_active (_route->active()); + int active = 0; + int inactive = 0; + TrackSelection const & s = _editor.get_selection().tracks; + for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) { + RouteTimeAxisView* r = dynamic_cast (*i); + if (!r) { + continue; + } - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Hide"), sigc::bind (sigc::mem_fun(_editor, &PublicEditor::hide_track_in_display), this, false))); - if (!Profile->get_sae()) { - items.push_back (MenuElem (_("Remove"), sigc::mem_fun(*this, &RouteUI::remove_this_route))); - } else { - items.push_front (SeparatorElem()); - items.push_front (MenuElem (_("Delete"), sigc::mem_fun(*this, &RouteUI::remove_this_route))); + if (r->route()->active()) { + ++active; + } else { + ++inactive; + } } -} - -static bool __reset_item (RadioMenuItem* item, RadioMenuItem* item_2) -{ - item->set_active (); - item_2->set_active (); - return false; -} -void -RouteTimeAxisView::set_track_mode (TrackMode mode) -{ - if (_ignore_track_mode_change) { - return; - } - - RadioMenuItem* item; - RadioMenuItem* other_item; - RadioMenuItem* other_item_2; - - switch (mode) { - case ARDOUR::Normal: - item = normal_track_mode_item; - other_item = non_layered_track_mode_item; - other_item_2 = destructive_track_mode_item; - break; - case ARDOUR::NonLayered: - item = non_layered_track_mode_item; - other_item = normal_track_mode_item; - other_item_2 = destructive_track_mode_item; - break; - case ARDOUR::Destructive: - item = destructive_track_mode_item; - other_item = normal_track_mode_item; - other_item_2 = non_layered_track_mode_item; - break; - default: - fatal << string_compose (_("programming error: %1 %2"), "illegal track mode in RouteTimeAxisView::set_track_mode", mode) << endmsg; - /*NOTREACHED*/ - return; + items.push_back (CheckMenuElem (_("Active"))); + CheckMenuItem* i = dynamic_cast (&items.back()); + bool click_sets_active = true; + if (active > 0 && inactive == 0) { + i->set_active (true); + click_sets_active = false; + } else if (active > 0 && inactive > 0) { + i->set_inconsistent (true); } + i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::set_route_active), click_sets_active, true)); - if (item && other_item && other_item_2 && track()->mode() != mode) { - _set_track_mode (track().get(), mode, other_item, other_item_2); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Hide"), sigc::bind (sigc::mem_fun(_editor, &PublicEditor::hide_track_in_display), this, true))); + if (!Profile->get_sae()) { + items.push_back (MenuElem (_("Remove"), sigc::bind (sigc::mem_fun(*this, &RouteUI::remove_this_route), true))); + } else { + items.push_front (SeparatorElem()); + items.push_front (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun(*this, &RouteUI::remove_this_route), true))); } } void -RouteTimeAxisView::_set_track_mode (Track* track, TrackMode mode, RadioMenuItem* reset_item, RadioMenuItem* reset_item_2) +RouteTimeAxisView::set_track_mode (TrackMode mode, bool apply_to_selection) { - bool needs_bounce; + if (apply_to_selection) { + _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_track_mode, _1, mode, false)); + } else { - if (!track->can_use_mode (mode, needs_bounce)) { + bool needs_bounce; - if (!needs_bounce) { - /* cannot be done */ - Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (__reset_item), reset_item, reset_item_2)); - return; - } else { - cerr << "would bounce this one\n"; - /* XXX: radio menu item becomes inconsistent with track state in this case */ - return; + if (!track()->can_use_mode (mode, needs_bounce)) { + + if (!needs_bounce) { + /* cannot be done */ + return; + } else { + cerr << "would bounce this one\n"; + return; + } } + + track()->set_mode (mode); + + rec_enable_button->remove (); + + switch (mode) { + case ARDOUR::NonLayered: + case ARDOUR::Normal: + rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_normal_red")))))); + break; + case ARDOUR::Destructive: + rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_tape_red")))))); + break; + } + + rec_enable_button->show_all (); } - - track->set_mode (mode); - - rec_enable_button->remove (); - - switch (mode) { - case ARDOUR::NonLayered: - case ARDOUR::Normal: - rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_normal_red")))))); - break; - case ARDOUR::Destructive: - rec_enable_button->add (*(manage (new Image (::get_icon (X_("record_tape_red")))))); - break; - } - - rec_enable_button->show_all (); -} - -void -RouteTimeAxisView::track_mode_changed () -{ - RadioMenuItem* item; - - switch (track()->mode()) { - case ARDOUR::Normal: - item = normal_track_mode_item; - break; - case ARDOUR::NonLayered: - item = non_layered_track_mode_item; - break; - case ARDOUR::Destructive: - item = destructive_track_mode_item; - break; - default: - fatal << string_compose (_("programming error: %1 %2"), "illegal track mode in RouteTimeAxisView::set_track_mode", track()->mode()) << endmsg; - /*NOTREACHED*/ - return; - } - - item->set_active (); } void @@ -780,9 +865,10 @@ RouteTimeAxisView::set_height (uint32_t h) xml_node->add_property ("height", buf); if (height >= preset_height (HeightNormal)) { + + _controls_padding_table.set_row_spacings (2); + reset_meter(); - show_name_entry (); - hide_name_label (); gm.get_gain_slider().show(); mute_button->show(); @@ -803,9 +889,9 @@ RouteTimeAxisView::set_height (uint32_t h) } else if (height >= preset_height (HeightSmaller)) { + _controls_padding_table.set_row_spacings (2); + reset_meter(); - show_name_entry (); - hide_name_label (); gm.get_gain_slider().hide(); mute_button->show(); @@ -826,31 +912,8 @@ RouteTimeAxisView::set_height (uint32_t h) } else { - - /* don't allow name_entry to be hidden while - it has focus, otherwise the GUI becomes unusable. - */ - - if (name_entry.has_focus()) { - if (name_entry.get_text() != _route->name()) { - name_entry_changed (); - } - controls_ebox.grab_focus (); - } - - hide_name_entry (); - show_name_label (); - - gm.get_gain_slider().hide(); - mute_button->hide(); - solo_button->hide(); - if (rec_enable_button) - rec_enable_button->hide(); - - route_group_button.hide (); - automation_button.hide (); - playlist_button.hide (); - name_label.set_text (_route->name()); + _controls_padding_table.set_row_spacings (0); + } if (height_changed && !no_redraw) { @@ -900,42 +963,21 @@ RouteTimeAxisView::set_samples_per_unit (double spu) } void -RouteTimeAxisView::align_style_changed () -{ - switch (track()->alignment_style()) { - case ExistingMaterial: - if (!align_existing_item->get_active()) { - align_existing_item->set_active(); - } - break; - case CaptureTime: - if (!align_capture_item->get_active()) { - align_capture_item->set_active(); - } - break; - } -} - -void -RouteTimeAxisView::set_align_style (AlignStyle style) +RouteTimeAxisView::set_align_choice (RadioMenuItem* mitem, AlignChoice choice, bool apply_to_selection) { - RadioMenuItem* item; - - switch (style) { - case ExistingMaterial: - item = align_existing_item; - break; - case CaptureTime: - item = align_capture_item; - break; - default: - fatal << string_compose (_("programming error: %1 %2"), "illegal align style in RouteTimeAxisView::set_align_style", style) << endmsg; - /*NOTREACHED*/ - return; - } + if (!mitem->get_active()) { + /* this is one of the two calls made when these radio menu items change status. this one + is for the item that became inactive, and we want to ignore it. + */ + return; + } - if (item->get_active()) { - track()->set_align_style (style); + if (apply_to_selection) { + _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_align_choice, _1, mitem, choice, false)); + } else { + if (track ()) { + track()->set_align_choice (choice); + } } } @@ -1026,7 +1068,7 @@ RouteTimeAxisView::use_copy_playlist (bool prompt, vectorname(); - if (route_group() && route_group()->is_active()) { + if (route_group() && route_group()->is_active() && route_group()->enabled_property (ARDOUR::Properties::edit.property_id)) { name = resolve_new_group_playlist_name(name, playlists_before_op); } @@ -1081,7 +1123,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt, vectorname(); - if (route_group() && route_group()->is_active()) { + if (route_group() && route_group()->is_active() && route_group()->enabled_property (ARDOUR::Properties::edit.property_id)) { name = resolve_new_group_playlist_name(name,playlists_before_op); } @@ -1464,7 +1506,7 @@ RouteTimeAxisView::build_playlist_menu () playlist_items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &RouteTimeAxisView::rename_current_playlist))); playlist_items.push_back (SeparatorElem()); - if (!route_group() || !route_group()->is_active()) { + if (!route_group() || !route_group()->is_active() || !route_group()->enabled_property (ARDOUR::Properties::edit.property_id)) { playlist_items.push_back (MenuElem (_("New..."), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::new_playlists), this))); playlist_items.push_back (MenuElem (_("New Copy..."), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::copy_playlists), this))); @@ -1508,8 +1550,10 @@ RouteTimeAxisView::use_playlist (RadioMenuItem *item, boost::weak_ptr } track()->use_playlist (apl); - if (route_group() && route_group()->is_active()) { - std::string group_string = "."+route_group()->name()+"."; + RouteGroup* rg = route_group(); + + if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::edit.property_id)) { + std::string group_string = "." + rg->name() + "."; std::string take_name = apl->name(); std::string::size_type idx = take_name.find(group_string); @@ -1519,7 +1563,7 @@ RouteTimeAxisView::use_playlist (RadioMenuItem *item, boost::weak_ptr take_name = take_name.substr(idx + group_string.length()); // find the bit containing the take number / name - boost::shared_ptr rl (route_group()->route_list()); + boost::shared_ptr rl (rg->route_list()); for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) { if ( (*i) == this->route()) { @@ -1530,7 +1574,6 @@ RouteTimeAxisView::use_playlist (RadioMenuItem *item, boost::weak_ptr boost::shared_ptr track = boost::dynamic_pointer_cast(*i); if (!track) { - std::cerr << "route " << (*i)->name() << " is not a Track" << std::endl; continue; } @@ -1644,109 +1687,121 @@ RouteTimeAxisView::automation_track_hidden (Evoral::Parameter param) void -RouteTimeAxisView::show_all_automation () +RouteTimeAxisView::show_all_automation (bool apply_to_selection) { - no_redraw = true; - - /* Show our automation */ - - for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { - i->second->set_marked_for_display (true); - i->second->canvas_display()->show(); - i->second->get_state_node()->add_property ("shown", X_("yes")); - - Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + if (apply_to_selection) { + _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::show_all_automation, _1, false)); + } else { + no_redraw = true; - if (menu) { - menu->set_active(true); - } - } - - - /* Show processor automation */ - - for (list::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { - for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - if ((*ii)->view == 0) { - add_processor_automation_curve ((*i)->processor, (*ii)->what); - } - - (*ii)->menu_item->set_active (true); - } - } - - no_redraw = false; - - /* Redraw */ - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ -} - -void -RouteTimeAxisView::show_existing_automation () -{ - no_redraw = true; - - /* Show our automation */ - - for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { - if (i->second->has_automation()) { + /* Show our automation */ + + for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { i->second->set_marked_for_display (true); i->second->canvas_display()->show(); i->second->get_state_node()->add_property ("shown", X_("yes")); - + Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + if (menu) { menu->set_active(true); } } - } - - - /* Show processor automation */ - - for (list::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { - for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - if ((*ii)->view != 0 && (*i)->processor->control((*ii)->what)->list()->size() > 0) { + + + /* Show processor automation */ + + for (list::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->view == 0) { + add_processor_automation_curve ((*i)->processor, (*ii)->what); + } + (*ii)->menu_item->set_active (true); } } + + no_redraw = false; + + /* Redraw */ + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } - - no_redraw = false; - - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } - + void -RouteTimeAxisView::hide_all_automation () +RouteTimeAxisView::show_existing_automation (bool apply_to_selection) { - no_redraw = true; - - /* Hide our automation */ - - for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { - i->second->set_marked_for_display (false); - i->second->hide (); - i->second->get_state_node()->add_property ("shown", X_("no")); - - Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + if (apply_to_selection) { + _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::show_existing_automation, _1, false)); + } else { + no_redraw = true; + + /* Show our automation */ + + for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + if (i->second->has_automation()) { + i->second->set_marked_for_display (true); + i->second->canvas_display()->show(); + i->second->get_state_node()->add_property ("shown", X_("yes")); + + Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + if (menu) { + menu->set_active(true); + } + } + } + + + /* Show processor automation */ - if (menu) { - menu->set_active (false); + for (list::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->view != 0 && (*i)->processor->control((*ii)->what)->list()->size() > 0) { + (*ii)->menu_item->set_active (true); + } + } } + + no_redraw = false; + + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } +} - /* Hide processor automation */ +void +RouteTimeAxisView::hide_all_automation (bool apply_to_selection) +{ + if (apply_to_selection) { + _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::hide_all_automation, _1, false)); + } else { + no_redraw = true; - for (list::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { - for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { - (*ii)->menu_item->set_active (false); + /* Hide our automation */ + + for (AutomationTracks::iterator i = _automation_tracks.begin(); i != _automation_tracks.end(); ++i) { + i->second->set_marked_for_display (false); + i->second->hide (); + i->second->get_state_node()->add_property ("shown", X_("no")); + + Gtk::CheckMenuItem* menu = automation_child_menu_item (i->first); + + if (menu) { + menu->set_active (false); + } + } + + /* Hide processor automation */ + + for (list::iterator i = processor_automation.begin(); i != processor_automation.end(); ++i) { + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + (*ii)->menu_item->set_active (false); + } } + + no_redraw = false; + _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } - - no_redraw = false; - _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ } @@ -2157,14 +2212,19 @@ RouteTimeAxisView::update_rec_display () } void -RouteTimeAxisView::set_layer_display (LayerDisplay d) +RouteTimeAxisView::set_layer_display (LayerDisplay d, bool apply_to_selection) { - if (_view) { - _view->set_layer_display (d); + if (apply_to_selection) { + _editor.get_selection().tracks.foreach_route_time_axis (boost::bind (&RouteTimeAxisView::set_layer_display, _1, d, false)); + } else { + + if (_view) { + _view->set_layer_display (d); + } + + ensure_xml_node (); + xml_node->add_property (N_("layer-display"), enum_2_string (d)); } - - ensure_xml_node (); - xml_node->add_property (N_("layer-display"), enum_2_string (d)); } LayerDisplay @@ -2410,6 +2470,10 @@ RouteTimeAxisView::create_gain_automation_child (const Evoral::Parameter& param, false, parent_canvas, _route->amp()->describe_parameter(param))); + + if (_view) { + _view->foreach_regionview (sigc::mem_fun (*gain_track.get(), &TimeAxisView::add_ghost)); + } add_automation_child (Evoral::Parameter(GainAutomation), gain_track, show); }