X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_track.cc;h=f1344e7697640eac1d85cf604d8ada3f00a7f584;hb=d92686afb4105b84b014372b6feb0ccc454a5171;hp=3f154644812345e4bf56d641c1f3d07621c805b9;hpb=546cd974ec2d90f64dcaae6f347e68c6682117b9;p=ardour.git diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 3f15464481..f1344e7697 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -44,14 +44,17 @@ #include "ardour/midi_port.h" #include "ardour/midi_region.h" #include "ardour/midi_track.h" +#include "ardour/monitor_control.h" #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" -#include "i18n.h" +#include "pbd/i18n.h" namespace ARDOUR { class InterThreadInfo; @@ -64,8 +67,8 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mode) - : Track (sess, name, flag, mode, DataType::MIDI) +MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode) + : Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI) , _immediate_events(1024) // FIXME: size? , _step_edit_ring_buffer(64) // FIXME: size? , _note_mode(Sustained) @@ -101,14 +104,24 @@ MidiTrack::create_diskstream () } -void -MidiTrack::set_record_enabled (bool yn, void *src) +bool +MidiTrack::can_be_record_safe () { if (_step_editing) { - return; + return false; } - Track::set_record_enabled (yn, src); + return Track::can_be_record_safe (); +} + +bool +MidiTrack::can_be_record_enabled () +{ + if (_step_editing) { + return false; + } + + return Track::can_be_record_enabled (); } void @@ -119,13 +132,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 +162,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 +273,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 +358,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); } @@ -356,7 +373,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame if (!_active) { silence (nframes); - if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) { + if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) { _meter->reset(); } return 0; @@ -386,8 +403,8 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame /* filter captured data before meter sees it */ _capture_filter.filter (bufs); - if (_meter_point == MeterInput && (_monitoring & MonitorInput || _diskstream->record_enabled())) { - _meter->run (bufs, start_frame, end_frame, nframes, true); + if (_meter_point == MeterInput && ((_monitoring_control->monitoring_choice() & MonitorInput) || _diskstream->record_enabled())) { + _meter->run (bufs, start_frame, end_frame, 1.0 /*speed()*/, nframes, true); } @@ -415,27 +432,22 @@ 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())); - for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { - boost::shared_ptr d = boost::dynamic_pointer_cast (*i); - if (d) { - d->flush_buffers (nframes); - } - } + flush_processor_buffers_locked (nframes); need_butler = diskstream->commit (playback_distance); - + return 0; } @@ -498,6 +510,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 +529,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); + } } } } @@ -682,6 +701,7 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st case MidiPgmChangeAutomation: case MidiPitchBenderAutomation: case MidiChannelPressureAutomation: + case MidiNotePressureAutomation: case MidiSystemExclusiveAutomation: /* The track control for MIDI parameters is for immediate events to act as a control surface, write/touch for them is not currently @@ -693,7 +713,7 @@ MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState st } void -MidiTrack::MidiControl::set_value(double val) +MidiTrack::MidiControl::actually_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); @@ -738,6 +758,12 @@ MidiTrack::MidiControl::set_value(double val) ev[1] = int(val); break; + case MidiNotePressureAutomation: + ev[0] += MIDI_CMD_NOTE_PRESSURE; + ev[1] = parameter.id(); + ev[2] = int(val); + break; + case MidiPitchBenderAutomation: ev[0] += MIDI_CMD_BENDER; ev[1] = 0x7F & int(val); @@ -750,7 +776,7 @@ MidiTrack::MidiControl::set_value(double val) _route->write_immediate_event(size, ev); } - AutomationControl::set_value(val); + AutomationControl::actually_set_value(val, group_override); } void @@ -886,7 +912,7 @@ MidiTrack::act_on_mute () return; } - if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) { + if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) { /* only send messages for channels we are using */ uint16_t mask = _playback_filter.get_channel_mask(); @@ -905,36 +931,33 @@ 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::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd) { - if (mc != _monitoring) { + Track::monitoring_changed (self, gcd); - Track::set_monitoring (mc); - - /* monitoring state changed, so flush out any on notes at the - * port level. - */ + /* 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) { - mp->require_resolve (); - } - } + PortSet& ports (_output->ports()); - boost::shared_ptr md (midi_diskstream()); - - if (md) { - md->reset_tracker (); + for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) { + boost::shared_ptr mp = boost::dynamic_pointer_cast (*p); + if (mp) { + mp->require_resolve (); } } + + boost::shared_ptr md (midi_diskstream()); + + if (md) { + md->reset_tracker (); + } } MonitorState @@ -943,7 +966,6 @@ MidiTrack::monitoring_state () const MonitorState ms = Track::monitoring_state(); if (ms == MonitoringSilence) { return MonitoringInput; - } + } return ms; } -