Do not allow to de/activate a track while the transport is rolling.

roll_delay and latency are only re-calculated when the transport is stopped.
de/activating a track is also not RT-safe.

Conflicts:
	gtk2_ardour/mixer_strip.cc
	gtk2_ardour/route_time_axis.cc
This commit is contained in:
Robin Gareus 2014-06-22 23:16:32 +02:00 committed by Paul Davis
parent d003eda9c3
commit b130dc032e
3 changed files with 350 additions and 11 deletions

View file

@ -1200,6 +1200,50 @@ MixerStrip::show_passthru_color ()
reset_strip_style ();
}
<<<<<<< HEAD
=======
void
MixerStrip::build_route_ops_menu ()
{
using namespace Menu_Helpers;
route_ops_menu = new Menu;
route_ops_menu->set_name ("ArdourContextMenu");
MenuList& items = route_ops_menu->items();
items.push_back (MenuElem (_("Comments..."), sigc::mem_fun (*this, &MixerStrip::open_comment_editor)));
if (!_route->is_master()) {
items.push_back (MenuElem (_("Save As Template..."), sigc::mem_fun(*this, &RouteUI::save_as_template)));
}
items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &RouteUI::route_rename)));
rename_menu_item = &items.back();
items.push_back (SeparatorElem());
items.push_back (CheckMenuElem (_("Active")));
Gtk::CheckMenuItem* i = dynamic_cast<Gtk::CheckMenuItem *> (&items.back());
i->set_active (_route->active());
i->set_sensitive(! _session->transport_rolling());
i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::set_route_active), !_route->active(), false));
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Adjust Latency..."), sigc::mem_fun (*this, &RouteUI::adjust_latency)));
items.push_back (SeparatorElem());
items.push_back (CheckMenuElem (_("Protect Against Denormals"), sigc::mem_fun (*this, &RouteUI::toggle_denormal_protection)));
denormal_menu_item = dynamic_cast<Gtk::CheckMenuItem *> (&items.back());
denormal_menu_item->set_active (_route->denormal_protection());
if (!Profile->get_sae()) {
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Remote Control ID..."), sigc::mem_fun (*this, &RouteUI::open_remote_control_id_dialog)));
}
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Remove"), sigc::bind (sigc::mem_fun(*this, &RouteUI::remove_this_route), false)));
}
>>>>>>> 14c6dfa... Do not allow to de/activate a track while the transport is rolling.
gboolean
MixerStrip::name_button_button_press (GdkEventButton* ev)
{

View file

@ -388,18 +388,309 @@ RouteTimeAxisView::build_display_menu ()
build_size_menu ();
items.push_back (MenuElem (_("Height"), *_size_menu));
AudioTrack* atr = dynamic_cast<AudioTrack*>(route().get() );
if (! (atr && atr->is_master_track() ) ) {
items.push_back (SeparatorElem());
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)));
boost::shared_ptr<AudioTrack> atr = audio_track ();
if (!(atr && atr->is_master_track())) {
items.push_back (SeparatorElem());
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)));
}
}
}
if (Profile->get_trx()) {
/* no more stuff in the menu for Tracks but retain code for easier merging with Ardour */
return;
}
items.push_back (SeparatorElem());
if (!Profile->get_sae()) {
items.push_back (MenuElem (_("Remote Control ID..."), sigc::mem_fun (*this, &RouteUI::open_remote_control_id_dialog)));
items.back().set_sensitive (_editor.get_selection().tracks.size() <= 1);
items.push_back (SeparatorElem());
}
// Hook for derived classes to add type specific stuff
append_extra_display_menu_items ();
if (is_track()) {
Menu* layers_menu = manage (new Menu);
MenuList &layers_items = layers_menu->items();
layers_menu->set_name("ArdourContextMenu");
RadioMenuItem::Group layers_group;
/* 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:
case Expanded:
++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.
*/
_ignore_set_layer_display = true;
layers_items.push_back (RadioMenuElem (layers_group, _("Overlaid")));
RadioMenuItem* i = dynamic_cast<RadioMenuItem*> (&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")));
i = dynamic_cast<RadioMenuItem*> (&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), Stacked, true));
_ignore_set_layer_display = false;
items.push_back (MenuElem (_("Layers"), *layers_menu));
if (!Profile->get_sae()) {
Menu* alignment_menu = manage (new Menu);
MenuList& alignment_items = alignment_menu->items();
alignment_menu->set_name ("ArdourContextMenu");
RadioMenuItem::Group align_group;
/* Same verbose hacks as for the layering options above */
int existing = 0;
int capture = 0;
int automatic = 0;
int styles = 0;
boost::shared_ptr<Track> first_track;
TrackSelection const & s = _editor.get_selection().tracks;
for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*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;
}
}
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<RadioMenuItem*> (&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<RadioMenuItem*> (&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<RadioMenuItem*> (&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 ();
mode_menu->set_name ("ArdourContextMenu");
RadioMenuItem::Group mode_group;
int normal = 0;
int tape = 0;
int non_layered = 0;
for (TrackSelection::const_iterator i = s.begin(); i != s.end(); ++i) {
RouteTimeAxisView* r = dynamic_cast<RouteTimeAxisView*> (*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, _("Normal Mode")));
i = dynamic_cast<RadioMenuItem*> (&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<RadioMenuItem*> (&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));
mode_items.push_back (RadioMenuElem (mode_group, _("Non-Layered Mode")));
i = dynamic_cast<RadioMenuItem*> (&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));
}
items.push_back (SeparatorElem());
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 ();
WeakRouteList r;
for (TrackSelection::iterator i = _editor.get_selection().tracks.begin(); i != _editor.get_selection().tracks.end(); ++i) {
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*i);
if (rtv) {
r.push_back (rtv->route ());
}
}
if (r.empty ()) {
r.push_back (route ());
}
route_group_menu->build (r);
items.push_back (MenuElem (_("Group"), *route_group_menu->menu ()));
build_automation_action_menu (true);
items.push_back (MenuElem (_("Automation"), *automation_action_menu));
items.push_back (SeparatorElem());
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<RouteTimeAxisView*> (*i);
if (!r) {
continue;
}
if (r->route()->active()) {
++active;
} else {
++inactive;
}
}
items.push_back (CheckMenuElem (_("Active")));
Gtk::CheckMenuItem* i = dynamic_cast<Gtk::CheckMenuItem *> (&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->set_sensitive(! _session->transport_rolling());
i->signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::set_route_active), click_sets_active, true));
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

View file

@ -3691,6 +3691,10 @@ Route::denormal_protection () const
void
Route::set_active (bool yn, void* src)
{
if (_session.transport_rolling()) {
return;
}
if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_route_active()) {
_route_group->foreach_route (boost::bind (&Route::set_active, _1, yn, _route_group));
return;