Remove redundant beat arg from TempoMap::add_meter
[ardour.git] / libs / ardour / smf_source.cc
index 7f5e8059c936c624b5d9a91bc29421bb740216ea..76d379e9477b34df62deecee23f863245c237157 100644 (file)
 #include "pbd/stl_delete.h"
 #include "pbd/strsplit.h"
 
-#include <glib/gstdio.h>
+#include "pbd/gstdio_compat.h"
 #include <glibmm/miscutils.h>
 #include <glibmm/fileutils.h>
 
 #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<framepos_t>*     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<framepos_t> ev;
+       Evoral::Event<framepos_t> 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<Evoral::Beats>*, gint >& a,
-       const std::pair< Evoral::Event<Evoral::Beats>*, gint >& b) {
+       const std::pair< const Evoral::Event<Evoral::Beats>*, gint >& a,
+       const std::pair< const Evoral::Event<Evoral::Beats>*, 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<Evoral::Beats> (
-                                                               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<Evoral::Beats>::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));
 }
-               
-