X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_track.cc;h=ce07fa8f24991f2bcad3344e200e9377bf1aef03;hb=c35e94a3c83028220f6eb494fdfe9c1960aaf751;hp=7dff7ac639768ae1bfc13292ecbe2c1d4fce356c;hpb=d074bc586e494d7dd83d415a487195a477095a4f;p=ardour.git diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 7dff7ac639..ce07fa8f24 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -16,9 +16,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include -#include // for ffs(3) +#ifdef COMPILER_MSVC +#include +// 'std::isinf()' and 'std::isnan()' are not available in MSVC. +#define isinf_local(val) !((bool)_finite((double)val)) +#define isnan_local(val) (bool)_isnan((double)val) +#else +#define isinf_local std::isinf +#define isnan_local std::isnan +#endif + +#include "pbd/ffs.h" #include "pbd/enumwriter.h" #include "pbd/convert.h" #include "evoral/midi_util.h" @@ -26,11 +37,13 @@ #include "ardour/buffer_set.h" #include "ardour/debug.h" #include "ardour/delivery.h" +#include "ardour/event_type_map.h" #include "ardour/meter.h" #include "ardour/midi_diskstream.h" #include "ardour/midi_playlist.h" #include "ardour/midi_port.h" #include "ardour/midi_track.h" +#include "ardour/parameter_types.h" #include "ardour/port.h" #include "ardour/processor.h" #include "ardour/session.h" @@ -81,13 +94,7 @@ MidiTrack::init () boost::shared_ptr MidiTrack::create_diskstream () { - MidiDiskstream::Flag dflags = MidiDiskstream::Flag (0); - - if (_flags & Auditioner) { - dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Hidden); - } else { - dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable); - } + MidiDiskstream::Flag dflags = MidiDiskstream::Flag (MidiDiskstream::Recordable); assert(_mode != Destructive); @@ -321,7 +328,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(std::llabs(playback_distance))) { + if (can_internal_playback_seek(llabs(playback_distance))) { /* TODO should declick, and/or note-off */ internal_playback_seek(playback_distance); } @@ -513,7 +520,7 @@ MidiTrack::filter_channels (BufferSet& bufs, ChannelMode mode, uint32_t mask) } break; case ForceChannel: - ev.set_channel (ffs (mask) - 1); + ev.set_channel (PBD::ffs (mask) - 1); ++e; break; case AllChannels: @@ -543,36 +550,62 @@ MidiTrack::write_out_of_band_data (BufferSet& bufs, framepos_t /*start*/, framep * the last argument ("stop on overflow in destination") so that we'll * ship the rest out next time. * - * the (nframes-1) argument puts all these events at the last + * the Port::port_offset() + (nframes-1) argument puts all these events at the last * possible position of the output buffer, so that we do not - * violate monotonicity when writing. + * violate monotonicity when writing. Port::port_offset() will + * be non-zero if we're in a split process cycle. */ - - _immediate_events.read (buf, 0, 1, nframes-1, true); + _immediate_events.read (buf, 0, 1, Port::port_offset() + nframes - 1, true); } } int -MidiTrack::export_stuff (BufferSet& /*bufs*/, framepos_t /*start_frame*/, framecnt_t /*nframes*/, - boost::shared_ptr /*endpoint*/, bool /*include_endpoint*/, bool /*forexport*/) -{ - return -1; +MidiTrack::export_stuff (BufferSet& buffers, + framepos_t start, + framecnt_t nframes, + boost::shared_ptr endpoint, + bool include_endpoint, + bool for_export, + bool for_freeze) +{ + if (buffers.count().n_midi() == 0) { + return -1; + } + + boost::shared_ptr diskstream = midi_diskstream(); + + Glib::Threads::RWLock::ReaderLock rlock (_processor_lock); + + boost::shared_ptr mpl = boost::dynamic_pointer_cast(diskstream->playlist()); + if (!mpl) { + return -2; + } + + buffers.get_midi(0).clear(); + if (mpl->read(buffers.get_midi(0), start, nframes, 0) != nframes) { + return -1; + } + + //bounce_process (buffers, start, nframes, endpoint, include_endpoint, for_export, for_freeze); + + return 0; } boost::shared_ptr -MidiTrack::bounce (InterThreadInfo& /*itt*/) +MidiTrack::bounce (InterThreadInfo& itt) { - std::cerr << "MIDI bounce currently unsupported" << std::endl; - return boost::shared_ptr (); + return bounce_range (_session.current_start_frame(), _session.current_end_frame(), itt, main_outs(), false); } - boost::shared_ptr -MidiTrack::bounce_range (framepos_t /*start*/, framepos_t /*end*/, InterThreadInfo& /*itt*/, - boost::shared_ptr /*endpoint*/, bool /*include_endpoint*/) +MidiTrack::bounce_range (framepos_t start, + framepos_t end, + InterThreadInfo& itt, + boost::shared_ptr endpoint, + bool include_endpoint) { - std::cerr << "MIDI bounce range currently unsupported" << std::endl; - return boost::shared_ptr (); + vector > srcs; + return _session.write_one_track (*this, start, end, false, srcs, itt, endpoint, include_endpoint, false, false); } void @@ -625,22 +658,43 @@ MidiTrack::write_immediate_event(size_t size, const uint8_t* buf) cerr << "WARNING: Ignoring illegal immediate MIDI event" << endl; return false; } - const uint32_t type = EventTypeMap::instance().midi_event_type(buf[0]); - return (_immediate_events.write(0, type, size, buf) == size); + const uint32_t type = midi_parameter_type(buf[0]); + return (_immediate_events.write (0, type, size, buf) == size); +} + +void +MidiTrack::set_parameter_automation_state (Evoral::Parameter param, AutoState state) +{ + switch (param.type()) { + case MidiCCAutomation: + case MidiPgmChangeAutomation: + case MidiPitchBenderAutomation: + case MidiChannelPressureAutomation: + 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 + supported. */ + return; + default: + Automatable::set_parameter_automation_state(param, state); + } } void MidiTrack::MidiControl::set_value(double val) { + const Evoral::Parameter ¶meter = _list ? _list->parameter() : Control::parameter(); + const Evoral::ParameterDescriptor &desc = EventTypeMap::instance().descriptor(parameter); + bool valid = false; - if (std::isinf(val)) { + if (isinf_local(val)) { cerr << "MIDIControl value is infinity" << endl; - } else if (std::isnan(val)) { + } else if (isnan_local(val)) { cerr << "MIDIControl value is NaN" << endl; - } else if (val < _list->parameter().min()) { - cerr << "MIDIControl value is < " << _list->parameter().min() << endl; - } else if (val > _list->parameter().max()) { - cerr << "MIDIControl value is > " << _list->parameter().max() << endl; + } else if (val < desc.lower) { + cerr << "MIDIControl value is < " << desc.lower << endl; + } else if (val > desc.upper) { + cerr << "MIDIControl value is > " << desc.upper << endl; } else { valid = true; } @@ -649,14 +703,14 @@ MidiTrack::MidiControl::set_value(double val) return; } - assert(val <= _list->parameter().max()); - if ( ! automation_playback()) { + assert(val <= desc.upper); + if ( ! _list || ! automation_playback()) { size_t size = 3; - uint8_t ev[3] = { _list->parameter().channel(), uint8_t (val), 0 }; - switch(_list->parameter().type()) { + uint8_t ev[3] = { parameter.channel(), uint8_t (val), 0 }; + switch(parameter.type()) { case MidiCCAutomation: ev[0] += MIDI_CMD_CONTROL; - ev[1] = _list->parameter().id(); + ev[1] = parameter.id(); ev[2] = int(val); break;