mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-06 21:55:43 +01:00
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:
parent
d003eda9c3
commit
b130dc032e
3 changed files with 350 additions and 11 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue