X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_track.cc;h=9fdd80ac19e20888d2c51cd96acf97626d924590;hb=3dc7728038860bda6eb4b0de1f4a3e14ec9e86cc;hp=3f154644812345e4bf56d641c1f3d07621c805b9;hpb=ced4378d0914bcfb926267772c45d1d23f3bed38;p=ardour.git diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 3f15464481..9fdd80ac19 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -47,6 +47,8 @@ #include "ardour/parameter_types.h" #include "ardour/port.h" #include "ardour/processor.h" +#include "ardour/profile.h" +#include "ardour/route_group_specialized.h" #include "ardour/session.h" #include "ardour/session_playlists.h" #include "ardour/utils.h" @@ -102,13 +104,23 @@ MidiTrack::create_diskstream () void -MidiTrack::set_record_enabled (bool yn, void *src) +MidiTrack::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_override) { if (_step_editing) { return; } - Track::set_record_enabled (yn, src); + Track::set_record_enabled (yn, group_override); +} + +void +MidiTrack::set_record_safe (bool yn, Controllable::GroupControlDisposition group_override) +{ + if (_step_editing) { /* REQUIRES REVIEW */ + return; + } + + Track::set_record_safe (yn, group_override); } void @@ -119,13 +131,17 @@ MidiTrack::set_diskstream (boost::shared_ptr ds) */ boost::shared_ptr mds = boost::dynamic_pointer_cast (ds); mds->set_note_mode (_note_mode); - + Track::set_diskstream (ds); - mds->reset_tracker (); + mds->reset_tracker (); _diskstream->set_track (this); - _diskstream->set_destructive (_mode == Destructive); + if (Profile->get_trx()) { + _diskstream->set_destructive (false); + } else { + _diskstream->set_destructive (_mode == Destructive); + } _diskstream->set_record_enabled (false); _diskstream_data_recorded_connection.disconnect (); @@ -145,7 +161,7 @@ MidiTrack::midi_diskstream() const int MidiTrack::set_state (const XMLNode& node, int version) { - const XMLProperty *prop; + XMLProperty const * prop; /* This must happen before Track::set_state(), as there will be a buffer fill during that call, and we must fill buffers using the correct @@ -256,8 +272,8 @@ void MidiTrack::set_state_part_two () { XMLNode* fnode; - XMLProperty* prop; - LocaleGuard lg (X_("C")); + XMLProperty const * prop; + LocaleGuard lg (); /* This is called after all session state has been restored but before have been made ports and connections are established. @@ -341,7 +357,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame if (!lm.locked()) { boost::shared_ptr diskstream = midi_diskstream(); framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes); - if (can_internal_playback_seek(llabs(playback_distance))) { + if (can_internal_playback_seek(::llabs(playback_distance))) { /* TODO should declick, and/or note-off */ internal_playback_seek(playback_distance); } @@ -379,6 +395,16 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame return dret; } + if (_mute_control->list() && _mute_control->automation_playback()) { + bool valid = false; + const float mute = _mute_control->list()->rt_safe_eval(transport_frame, valid); + if (mute >= 0.5 && !muted()) { + _mute_control->set_value_unchecked(1.0); // mute + } else if (mute < 0.5 && muted()) { + _mute_control->set_value_unchecked(0.0); // unmute + } + } + BufferSet& bufs = _session.get_route_buffers (n_process_buffers()); fill_buffers_with_input (bufs, _input, nframes); @@ -415,15 +441,15 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame diskstream->flush_playback (start_frame, end_frame); - } + } + - /* append immediate messages to the first MIDI buffer (thus sending it to the first output port) */ - + write_out_of_band_data (bufs, start_frame, end_frame, nframes); - + /* final argument: don't waste time with automation if we're not recording or rolling */ - + process_output_buffers (bufs, start_frame, end_frame, nframes, declick, (!diskstream->record_enabled() && !_session.transport_stopped())); @@ -435,7 +461,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame } need_butler = diskstream->commit (playback_distance); - + return 0; } @@ -498,6 +524,11 @@ MidiTrack::non_realtime_locate (framepos_t pos) return; } + /* the source may be missing, but the control still referenced in the GUI */ + if (!region->midi_source() || !region->model()) { + return; + } + Glib::Threads::Mutex::Lock lm (_control_lock, Glib::Threads::TRY_LOCK); if (!lm.locked()) { return; @@ -512,7 +543,9 @@ MidiTrack::non_realtime_locate (framepos_t pos) if ((tcontrol = boost::dynamic_pointer_cast(c->second)) && (rcontrol = region->control(tcontrol->parameter()))) { const Evoral::Beats pos_beats = bfc.from(pos - origin); - tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double())); + if (rcontrol->list()->size() > 0) { + tcontrol->set_value(rcontrol->list()->eval(pos_beats.to_double()), Controllable::NoGroup); + } } } } @@ -693,7 +726,22 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st } void -MidiTrack::MidiControl::set_value(double val) +MidiTrack::MidiControl::set_value (double val, PBD::Controllable::GroupControlDisposition group_override) +{ + if (writable()) { + _set_value (val, group_override); + } +} + +void +MidiTrack::MidiControl::set_value_unchecked (double val) +{ + /* used only by automation playback */ + _set_value (val, Controllable::NoGroup); +} + +void +MidiTrack::MidiControl::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override) { const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter(); const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter); @@ -750,7 +798,7 @@ MidiTrack::MidiControl::set_value(double val) _route->write_immediate_event(size, ev); } - AutomationControl::set_value(val); + AutomationControl::set_value(val, group_override); } void @@ -905,23 +953,28 @@ MidiTrack::act_on_mute () } /* Resolve active notes. */ - midi_diskstream()->resolve_tracker(_immediate_events, 0); + midi_diskstream()->resolve_tracker(_immediate_events, Port::port_offset()); } } - + void -MidiTrack::set_monitoring (MonitorChoice mc) +MidiTrack::set_monitoring (MonitorChoice mc, Controllable::GroupControlDisposition gcd) { + if (use_group (gcd, &RouteGroup::is_monitoring)) { + _route_group->apply (&Track::set_monitoring, mc, Controllable::NoGroup); + return; + } + if (mc != _monitoring) { - Track::set_monitoring (mc); - + Track::set_monitoring (mc, gcd); + /* monitoring state changed, so flush out any on notes at the * port level. */ PortSet& ports (_output->ports()); - + for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) { boost::shared_ptr mp = boost::dynamic_pointer_cast (*p); if (mp) { @@ -930,7 +983,7 @@ MidiTrack::set_monitoring (MonitorChoice mc) } boost::shared_ptr md (midi_diskstream()); - + if (md) { md->reset_tracker (); } @@ -943,7 +996,7 @@ MidiTrack::monitoring_state () const MonitorState ms = Track::monitoring_state(); if (ms == MonitoringSilence) { return MonitoringInput; - } + } return ms; }