X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fardour%2Fsmf_source.cc;h=76d379e9477b34df62deecee23f863245c237157;hb=1399ef391de5b05888ea2e13e6ff80f14b6e84d9;hp=7f5e8059c936c624b5d9a91bc29421bb740216ea;hpb=2a251b457069ffb4b744fbd0dd7aca7acb31f381;p=ardour.git diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index 7f5e8059c9..76d379e947 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -30,22 +30,23 @@ #include "pbd/stl_delete.h" #include "pbd/strsplit.h" -#include +#include "pbd/gstdio_compat.h" #include #include #include "evoral/Control.hpp" #include "evoral/SMF.hpp" +#include "ardour/debug.h" +#include "ardour/midi_channel_filter.h" #include "ardour/midi_model.h" #include "ardour/midi_ring_buffer.h" #include "ardour/midi_state_tracker.h" #include "ardour/parameter_types.h" #include "ardour/session.h" #include "ardour/smf_source.h" -#include "ardour/debug.h" -#include "i18n.h" +#include "pbd/i18n.h" using namespace ARDOUR; using namespace Glib; @@ -70,7 +71,7 @@ SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags) if (init (_path, false)) { throw failed_constructor (); } - + assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS)); existence_check (); @@ -106,7 +107,7 @@ SMFSource::SMFSource (Session& s, const string& path) if (init (_path, true)) { throw failed_constructor (); } - + assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)); existence_check (); @@ -201,6 +202,12 @@ SMFSource::open_for_write () return 0; } +void +SMFSource::close () +{ + /* nothing to do: file descriptor is never kept open */ +} + /** All stamps in audio frames */ framecnt_t SMFSource::read_unlocked (const Lock& lock, @@ -208,7 +215,9 @@ SMFSource::read_unlocked (const Lock& lock, framepos_t const source_start, framepos_t start, framecnt_t duration, - MidiStateTracker* tracker) const + Evoral::Range* loop_range, + MidiStateTracker* tracker, + MidiChannelFilter* filter) const { int ret = 0; uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn @@ -222,7 +231,6 @@ SMFSource::read_unlocked (const Lock& lock, // Output parameters for read_event (which will allocate scratch in buffer as needed) uint32_t ev_delta_t = 0; - uint32_t ev_type = 0; uint32_t ev_size = 0; uint8_t* ev_buffer = 0; @@ -268,10 +276,8 @@ SMFSource::read_unlocked (const Lock& lock, continue; } - ev_type = midi_parameter_type(ev_buffer[0]); - - DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked delta %1, time %2, buf[0] %3, type %4\n", - ev_delta_t, time, ev_buffer[0], ev_type)); + DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked delta %1, time %2, buf[0] %3\n", + ev_delta_t, time, ev_buffer[0])); assert(time >= start_ticks); @@ -280,10 +286,16 @@ SMFSource::read_unlocked (const Lock& lock, */ const framepos_t ev_frame_time = converter.to(Evoral::Beats::ticks_at_rate(time, ppqn())) + source_start; + if (loop_range) { + loop_range->squish (ev_frame_time); + } + if (ev_frame_time < start + duration) { - destination.write (ev_frame_time, ev_type, ev_size, ev_buffer); - if (tracker) { - tracker->track(ev_buffer); + if (!filter || !filter->filter(ev_buffer, ev_size)) { + destination.write (ev_frame_time, Evoral::MIDI_EVENT, ev_size, ev_buffer); + if (tracker) { + tracker->track(ev_buffer); + } } } else { break; @@ -319,7 +331,7 @@ SMFSource::write_unlocked (const Lock& lock, _model->start_write(); } - Evoral::MIDIEvent ev; + Evoral::Event ev; while (true) { /* Get the event time, in frames since session start but ignoring looping. */ bool ret; @@ -360,9 +372,9 @@ SMFSource::write_unlocked (const Lock& lock, break; } time -= position; - + ev.set(buf, size, time); - ev.set_event_type(midi_parameter_type(ev.buffer()[0])); + ev.set_event_type(Evoral::MIDI_EVENT); ev.set_id(Evoral::next_event_id()); if (!(ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex())) { @@ -387,9 +399,11 @@ SMFSource::append_event_beats (const Glib::Threads::Mutex::Lock& lock, return; } - /*printf("SMFSource: %s - append_event_beats ID = %d time = %lf, size = %u, data = ", +#if 0 + printf("SMFSource: %s - append_event_beats ID = %d time = %lf, size = %u, data = ", name().c_str(), ev.id(), ev.time(), ev.size()); - for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/ + for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n"); +#endif Evoral::Beats time = ev.time(); if (time < _last_ev_time_beats) { @@ -485,7 +499,7 @@ XMLNode& SMFSource::get_state () { XMLNode& node = MidiSource::get_state(); - node.add_property (X_("origin"), _origin); + node.set_property (X_("origin"), _origin); return node; } @@ -542,7 +556,7 @@ SMFSource::mark_midi_streaming_write_completed (const Lock& lm, Evoral::Sequence _model->set_edited(false); } - Evoral::SMF::end_write (); + Evoral::SMF::end_write (_path); /* data in the file now, not removable */ @@ -565,7 +579,7 @@ SMFSource::safe_midi_file_extension (const string& file) static bool compile = true; const int nmatches = 2; regmatch_t matches[nmatches]; - + if (Glib::file_test (file, Glib::FILE_TEST_EXISTS)) { if (!Glib::file_test (file, Glib::FILE_TEST_IS_REGULAR)) { /* exists but is not a regular file */ @@ -578,7 +592,7 @@ SMFSource::safe_midi_file_extension (const string& file) } else { compile = false; } - + if (regexec (&compiled_pattern, file.c_str(), nmatches, matches, 0)) { return false; } @@ -587,8 +601,8 @@ SMFSource::safe_midi_file_extension (const string& file) } static bool compare_eventlist ( - const std::pair< Evoral::Event*, gint >& a, - const std::pair< Evoral::Event*, gint >& b) { + const std::pair< const Evoral::Event*, gint >& a, + const std::pair< const Evoral::Event*, gint >& b) { return ( a.first->time() < b.first->time() ); } @@ -657,7 +671,6 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload if (!have_event_id) { event_id = Evoral::next_event_id(); } - const uint32_t event_type = midi_parameter_type(buf[0]); const Evoral::Beats event_time = Evoral::Beats::ticks_at_rate(time, ppqn()); #ifndef NDEBUG std::string ss; @@ -668,13 +681,13 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload ss += b; } - DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF %6 load model delta %1, time %2, size %3 buf %4, type %5\n", - delta_t, time, size, ss , event_type, name())); + DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF %7 load model delta %1, time %2, size %3 buf %4, id %6\n", + delta_t, time, size, ss, event_id, name())); #endif eventlist.push_back(make_pair ( new Evoral::Event ( - event_type, event_time, + Evoral::MIDI_EVENT, event_time, size, buf, true) , event_id)); @@ -698,6 +711,10 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload delete it->first; } + // cerr << "----SMF-SRC-----\n"; + // _playback_buf->dump (cerr); + // cerr << "----------------\n"; + _model->end_write (Evoral::Sequence::ResolveStuckNotes, _length_beats); _model->set_edited (false); invalidate(lock); @@ -722,7 +739,7 @@ SMFSource::flush_midi (const Lock& lock) ensure_disk_file (lock); - Evoral::SMF::end_write (); + Evoral::SMF::end_write (_path); /* data in the file means its no longer removable */ mark_nonremovable (); @@ -733,7 +750,6 @@ void SMFSource::set_path (const string& p) { FileSource::set_path (p); - SMF::set_path (_path); } /** Ensure that this source has some file on disk, even if it's just a SMF header */ @@ -769,8 +785,6 @@ SMFSource::prevent_deletion () /* Unlike the audio case, the MIDI file remains mutable (because we can edit MIDI data) */ - + _flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy)); } - -