take all tracks inside a midi-file into account when loading model
authorRobin Gareus <robin@gareus.org>
Mon, 20 Jan 2014 12:44:31 +0000 (13:44 +0100)
committerRobin Gareus <robin@gareus.org>
Wed, 22 Jan 2014 14:30:14 +0000 (15:30 +0100)
* fixes [region] length calculation,
* prepare for auditioning midi files (one track plays it all)

libs/ardour/smf_source.cc

index 3a1029fd7359631ff232d0ebb2dc0c623107474a..b2d01d24d2c6d5704bc56de5a379271db5b1db94 100644 (file)
@@ -476,6 +476,12 @@ SMFSource::safe_midi_file_extension (const string& file)
        return true;
 }
 
+static bool compare_eventlist (
+               const std::pair< Evoral::Event<double>*, gint >& a,
+               const std::pair< Evoral::Event<double>*, gint >& b) {
+       return ( a.first->time() < b.first->time() );
+}
+
 void
 SMFSource::load_model (bool lock, bool force_reload)
 {
@@ -514,60 +520,74 @@ SMFSource::load_model (bool lock, bool force_reload)
        uint8_t* buf     = NULL;
        int ret;
        gint event_id;
-       bool have_event_id = false;
-
-       while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) {
+       bool have_event_id;
 
-               time += delta_t;
+       // TODO simplify event allocation
+       std::list< std::pair< Evoral::Event<double>*, gint > > eventlist;
 
-               if (ret == 0) {
+       for (unsigned i = 1; i <= num_tracks(); ++i) {
+               if (seek_to_track(i)) continue;
 
-                       /* meta-event : did we get an event ID ?
-                        */
-
-                       if (event_id >= 0) {
-                               have_event_id = true;
-                       }
+               time = 0;
+               have_event_id = false;
 
-                       continue;
-               }
+               while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) {
 
-               if (ret > 0) {
+                       time += delta_t;
 
-                       /* not a meta-event */
+                       if (ret == 0) {
+                               /* meta-event : did we get an event ID ?  */
+                               if (event_id >= 0) {
+                                       have_event_id = true;
+                               }
+                               continue;
+                       }
 
-                       ev.set (buf, size, time / (double)ppqn());
-                       ev.set_event_type(EventTypeMap::instance().midi_event_type(buf[0]));
+                       if (ret > 0) {
+                               /* not a meta-event */
 
-                       if (!have_event_id) {
-                               event_id = Evoral::next_event_id();
-                       }
+                               if (!have_event_id) {
+                                       event_id = Evoral::next_event_id();
+                               }
+                               uint32_t event_type = EventTypeMap::instance().midi_event_type(buf[0]);
+                               double   event_time = time / (double) ppqn();
 #ifndef NDEBUG
-                       std::string ss;
+                               std::string ss;
 
-                       for (uint32_t xx = 0; xx < size; ++xx) {
-                               char b[8];
-                               snprintf (b, sizeof (b), "0x%x ", buf[xx]);
-                               ss += b;
-                       }
+                               for (uint32_t xx = 0; xx < size; ++xx) {
+                                       char b[8];
+                                       snprintf (b, sizeof (b), "0x%x ", buf[xx]);
+                                       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 , ev.event_type(), name()));
+                               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()));
 #endif
 
-                       _model->append (ev, event_id);
+                               eventlist.push_back(make_pair (
+                                                       new Evoral::Event<double> (
+                                                               event_type, event_time,
+                                                               size, buf, true)
+                                                       , event_id));
 
-                       // Set size to max capacity to minimize allocs in read_event
-                       scratch_size = std::max(size, scratch_size);
-                       size = scratch_size;
+                               // Set size to max capacity to minimize allocs in read_event
+                               scratch_size = std::max(size, scratch_size);
+                               size = scratch_size;
 
-                       _length_beats = max(_length_beats, ev.time());
+                               _length_beats = max(_length_beats, event_time);
+                       }
+
+                       /* event ID's must immediately precede the event they are for */
+                       have_event_id = false;
                }
+       }
 
-               /* event ID's must immediately precede the event they are for
-                */
+       eventlist.sort(compare_eventlist);
 
-               have_event_id = false;
+       std::list< std::pair< Evoral::Event<double>*, gint > >::iterator it;
+       for (it=eventlist.begin(); it!=eventlist.end(); ++it) {
+               _model->append (*it->first, it->second);
+               delete it->first;
        }
 
        _model->end_write (Evoral::Sequence<Evoral::MusicalTime>::ResolveStuckNotes, _length_beats);