fix API errors after cherry-picking empty MIDI file fixes from cairocanvas
[ardour.git] / libs / ardour / smf_source.cc
1 /*
2     Copyright (C) 2006 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #include <vector>
22
23 #include <sys/time.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <regex.h>
28
29 #include "pbd/pathscanner.h"
30 #include "pbd/stl_delete.h"
31 #include "pbd/strsplit.h"
32
33 #include <glibmm/miscutils.h>
34 #include <glibmm/fileutils.h>
35
36 #include "evoral/Control.hpp"
37 #include "evoral/evoral/SMF.hpp"
38
39 #include "ardour/event_type_map.h"
40 #include "ardour/midi_model.h"
41 #include "ardour/midi_ring_buffer.h"
42 #include "ardour/midi_state_tracker.h"
43 #include "ardour/session.h"
44 #include "ardour/smf_source.h"
45 #include "ardour/debug.h"
46
47 #include "i18n.h"
48
49 using namespace ARDOUR;
50 using namespace Glib;
51 using namespace PBD;
52 using namespace Evoral;
53
54 /** Constructor used for new internal-to-session files.  File cannot exist. */
55 SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
56         : Source(s, DataType::MIDI, path, flags)
57         , MidiSource(s, path, flags)
58         , FileSource(s, DataType::MIDI, path, string(), flags)
59         , Evoral::SMF()
60         , _last_ev_time_beats(0.0)
61         , _last_ev_time_frames(0)
62         , _smf_last_read_end (0)
63         , _smf_last_read_time (0)
64 {
65         /* note that origin remains empty */
66
67         if (init (_path, false)) {
68                 throw failed_constructor ();
69         }
70  
71         assert (!Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
72         existence_check ();
73
74         _flags = Source::Flag (_flags | Empty);
75
76         /* file is not opened until write */
77
78         if (flags & Writable) {
79                 return;
80         }
81
82         if (open (_path)) {
83                 throw failed_constructor ();
84         }
85
86         _open = true;
87 }
88
89 /** Constructor used for external-to-session files.  File must exist. */
90 SMFSource::SMFSource (Session& s, const string& path)
91         : Source(s, DataType::MIDI, path, Source::Flag (0))
92         , MidiSource(s, path, Source::Flag (0))
93         , FileSource(s, DataType::MIDI, path, string(), Source::Flag (0))
94         , Evoral::SMF()
95         , _last_ev_time_beats(0.0)
96         , _last_ev_time_frames(0)
97         , _smf_last_read_end (0)
98         , _smf_last_read_time (0)
99 {
100         /* note that origin remains empty */
101
102         if (init (_path, true)) {
103                 throw failed_constructor ();
104         }
105  
106         assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
107         existence_check ();
108
109         if (_flags & Writable) {
110                 /* file is not opened until write */
111                 return;
112         }
113
114         if (open (_path)) {
115                 throw failed_constructor ();
116         }
117
118         _open = true;
119 }
120
121 /** Constructor used for existing internal-to-session files. */
122 SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
123         : Source(s, node)
124         , MidiSource(s, node)
125         , FileSource(s, node, must_exist)
126         , _last_ev_time_beats(0.0)
127         , _last_ev_time_frames(0)
128         , _smf_last_read_end (0)
129         , _smf_last_read_time (0)
130 {
131         if (set_state(node, Stateful::loading_state_version)) {
132                 throw failed_constructor ();
133         }
134
135         /* we expect the file to exist, but if no MIDI data was ever added
136            it will have been removed at last session close. so, we don't
137            require it to exist if it was marked Empty.
138         */
139
140         try {
141
142                 if (init (_path, true)) {
143                         throw failed_constructor ();
144                 }
145
146         } catch (MissingSource& err) {
147
148                 if (_flags & Source::Empty) {
149                         /* we don't care that the file was not found, because
150                            it was empty. But FileSource::init() will have
151                            failed to set our _path correctly, so we have to do
152                            this ourselves. Use the first entry in the search
153                            path for MIDI files, which is assumed to be the
154                            correct "main" location.
155                         */
156                         std::vector<Glib::ustring> sdirs;
157                         split (s.source_search_path (DataType::MIDI), sdirs, ':');
158                         if (sdirs.empty()) {
159                                 fatal << _("Empty MIDI source search path!") << endmsg;
160                                 /*NOTREACHED*/
161                         }
162                         _path = Glib::build_filename (sdirs.front(), _path);
163                         /* This might be important, too */
164                         _file_is_new = true;
165                 } else {
166                         /* pass it on */
167                         throw;
168                 }
169         }
170
171         if (!(_flags & Source::Empty)) {
172                 assert (Glib::file_test (_path, Glib::FILE_TEST_EXISTS));
173                 existence_check ();
174         } else {
175                 assert (_flags & Source::Writable);
176                 /* file will be opened on write */
177                 return;
178         }
179
180         if (open(_path)) {
181                 throw failed_constructor ();
182         }
183
184         _open = true;
185 }
186
187 SMFSource::~SMFSource ()
188 {
189         if (removable()) {
190                 unlink (_path.c_str());
191         }
192 }
193
194 int
195 SMFSource::open_for_write ()
196 {
197         if (create (_path)) {
198                 return -1;
199         }
200         _open = true;
201         return 0;
202 }
203
204 /** All stamps in audio frames */
205 framecnt_t
206 SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination,
207                           framepos_t const               source_start,
208                           framepos_t                     start,
209                           framecnt_t                     duration,
210                           MidiStateTracker*              tracker) const
211 {
212         int      ret  = 0;
213         uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
214
215         if (writable() && !_open) {
216                 /* nothing to read since nothing has ben written */
217                 return duration;
218         }
219
220         DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start %1 duration %2\n", start, duration));
221
222         // Output parameters for read_event (which will allocate scratch in buffer as needed)
223         uint32_t ev_delta_t = 0;
224         uint32_t ev_type    = 0;
225         uint32_t ev_size    = 0;
226         uint8_t* ev_buffer  = 0;
227
228         size_t scratch_size = 0; // keep track of scratch to minimize reallocs
229
230         BeatsFramesConverter converter(_session.tempo_map(), source_start);
231
232         const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
233         DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start in ticks %1\n", start_ticks));
234
235         if (_smf_last_read_end == 0 || start != _smf_last_read_end) {
236                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: seek to %1\n", start));
237                 Evoral::SMF::seek_to_start();
238                 while (time < start_ticks) {
239                         gint ignored;
240
241                         ret = read_event(&ev_delta_t, &ev_size, &ev_buffer, &ignored);
242                         if (ret == -1) { // EOF
243                                 _smf_last_read_end = start + duration;
244                                 return duration;
245                         }
246                         time += ev_delta_t; // accumulate delta time
247                 }
248         } else {
249                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: set time to %1\n", _smf_last_read_time));
250                 time = _smf_last_read_time;
251         }
252
253         _smf_last_read_end = start + duration;
254
255         while (true) {
256                 gint ignored; /* XXX don't ignore note id's ??*/
257
258                 ret = read_event(&ev_delta_t, &ev_size, &ev_buffer, &ignored);
259                 if (ret == -1) { // EOF
260                         break;
261                 }
262
263                 time += ev_delta_t; // accumulate delta time
264                 _smf_last_read_time = time;
265
266                 if (ret == 0) { // meta-event (skipped, just accumulate time)
267                         continue;
268                 }
269
270                 ev_type = EventTypeMap::instance().midi_event_type(ev_buffer[0]);
271
272                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked delta %1, time %2, buf[0] %3, type %4\n",
273                                                                   ev_delta_t, time, ev_buffer[0], ev_type));
274
275                 assert(time >= start_ticks);
276
277                 /* Note that we add on the source start time (in session frames) here so that ev_frame_time
278                    is in session frames.
279                 */
280                 const framepos_t ev_frame_time = converter.to(time / (double)ppqn()) + source_start;
281
282                 if (ev_frame_time < start + duration) {
283                         destination.write (ev_frame_time, ev_type, ev_size, ev_buffer);
284
285                         if (tracker) {
286                                 if (ev_buffer[0] & MIDI_CMD_NOTE_ON) {
287                                         tracker->add (ev_buffer[1], ev_buffer[0] & 0xf);
288                                 } else if (ev_buffer[0] & MIDI_CMD_NOTE_OFF) {
289                                         tracker->remove (ev_buffer[1], ev_buffer[0] & 0xf);
290                                 }
291                         }
292                 } else {
293                         break;
294                 }
295
296                 if (ev_size > scratch_size) {
297                         scratch_size = ev_size;
298                 }
299                 ev_size = scratch_size; // ensure read_event only allocates if necessary
300         }
301
302         return duration;
303 }
304
305 framecnt_t
306 SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source,
307                            framepos_t                  position,
308                            framecnt_t                  cnt)
309 {
310         if (!_writing) {
311                 mark_streaming_write_started ();
312         }
313
314         framepos_t        time;
315         Evoral::EventType type;
316         uint32_t          size;
317
318         size_t   buf_capacity = 4;
319         uint8_t* buf          = (uint8_t*)malloc(buf_capacity);
320
321         if (_model && !_model->writing()) {
322                 _model->start_write();
323         }
324
325         Evoral::MIDIEvent<framepos_t> ev;
326         while (true) {
327                 /* Get the event time, in frames since session start but ignoring looping. */
328                 bool ret;
329                 if (!(ret = source.peek ((uint8_t*)&time, sizeof (time)))) {
330                         /* Ring is empty, no more events. */
331                         break;
332                 }
333
334                 if ((cnt != max_framecnt) &&
335                     (time > position + _capture_length + cnt)) {
336                         /* The diskstream doesn't want us to write everything, and this
337                            event is past the end of this block, so we're done for now. */
338                         break;
339                 }
340
341                 /* Read the time, type, and size of the event. */
342                 if (!(ret = source.read_prefix (&time, &type, &size))) {
343                         error << _("Unable to read event prefix, corrupt MIDI ring") << endmsg;
344                         break;
345                 }
346
347                 /* Enlarge body buffer if necessary now that we know the size. */
348                 if (size > buf_capacity) {
349                         buf_capacity = size;
350                         buf = (uint8_t*)realloc(buf, size);
351                 }
352
353                 /* Read the event body into buffer. */
354                 ret = source.read_contents(size, buf);
355                 if (!ret) {
356                         error << _("Event has time and size but no body, corrupt MIDI ring") << endmsg;
357                         break;
358                 }
359
360                 /* Convert event time from absolute to source relative. */
361                 if (time < position) {
362                         error << _("Event time is before MIDI source position") << endmsg;
363                         break;
364                 }
365                 time -= position;
366                         
367                 ev.set(buf, size, time);
368                 ev.set_event_type(EventTypeMap::instance().midi_event_type(ev.buffer()[0]));
369                 ev.set_id(Evoral::next_event_id());
370
371                 if (!(ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex())) {
372                         continue;
373                 }
374
375                 append_event_unlocked_frames(ev, position);
376         }
377
378         Evoral::SMF::flush ();
379         free (buf);
380
381         return cnt;
382 }
383
384 /** Append an event with a timestamp in beats (double) */
385 void
386 SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
387 {
388         if (!_writing || ev.size() == 0)  {
389                 return;
390         }
391
392         /*printf("SMFSource: %s - append_event_unlocked_beats ID = %d time = %lf, size = %u, data = ",
393                name().c_str(), ev.id(), ev.time(), ev.size());
394                for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/
395
396         if (ev.time() < _last_ev_time_beats) {
397                 warning << string_compose(_("Skipping event with unordered time %1"), ev.time())
398                         << endmsg;
399                 return;
400         }
401
402         Evoral::event_id_t event_id;
403
404         if (ev.id() < 0) {
405                 event_id  = Evoral::next_event_id();
406         } else {
407                 event_id = ev.id();
408         }
409
410         if (_model) {
411                 _model->append (ev, event_id);
412         }
413
414         _length_beats = max(_length_beats, ev.time());
415
416         const double delta_time_beats   = ev.time() - _last_ev_time_beats;
417         const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
418
419         Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
420         _last_ev_time_beats = ev.time();
421         _flags = Source::Flag (_flags & ~Empty);
422 }
423
424 /** Append an event with a timestamp in frames (framepos_t) */
425 void
426 SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, framepos_t position)
427 {
428         if (!_writing || ev.size() == 0)  {
429                 return;
430         }
431
432         // printf("SMFSource: %s - append_event_unlocked_frames ID = %d time = %u, size = %u, data = ",
433         // name().c_str(), ev.id(), ev.time(), ev.size());
434         // for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");
435
436         if (ev.time() < _last_ev_time_frames) {
437                 warning << string_compose(_("Skipping event with unordered time %1"), ev.time())
438                         << endmsg;
439                 return;
440         }
441
442         BeatsFramesConverter converter(_session.tempo_map(), position);
443         const double ev_time_beats = converter.from(ev.time());
444         Evoral::event_id_t event_id;
445
446         if (ev.id() < 0) {
447                 event_id  = Evoral::next_event_id();
448         } else {
449                 event_id = ev.id();
450         }
451
452         if (_model) {
453                 const Evoral::Event<double> beat_ev (ev.event_type(),
454                                                      ev_time_beats,
455                                                      ev.size(),
456                                                      const_cast<uint8_t*>(ev.buffer()));
457                 _model->append (beat_ev, event_id);
458         }
459
460         _length_beats = max(_length_beats, ev_time_beats);
461
462         const Evoral::MusicalTime last_time_beats  = converter.from (_last_ev_time_frames);
463         const Evoral::MusicalTime delta_time_beats = ev_time_beats - last_time_beats;
464         const uint32_t            delta_time_ticks = (uint32_t)(lrint(delta_time_beats * (double)ppqn()));
465
466         Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
467         _last_ev_time_frames = ev.time();
468         _flags = Source::Flag (_flags & ~Empty);
469 }
470
471 XMLNode&
472 SMFSource::get_state ()
473 {
474         XMLNode& node = MidiSource::get_state();
475         node.add_property (X_("origin"), _origin);
476         return node;
477 }
478
479 int
480 SMFSource::set_state (const XMLNode& node, int version)
481 {
482         if (Source::set_state (node, version)) {
483                 return -1;
484         }
485
486         if (MidiSource::set_state (node, version)) {
487                 return -1;
488         }
489
490         if (FileSource::set_state (node, version)) {
491                 return -1;
492         }
493
494         return 0;
495 }
496
497 void
498 SMFSource::mark_streaming_midi_write_started (NoteMode mode)
499 {
500         /* CALLER MUST HOLD LOCK */
501
502         if (!_open && open_for_write()) {
503                 error << string_compose (_("cannot open MIDI file %1 for write"), _path) << endmsg;
504                 /* XXX should probably throw or return something */
505                 return;
506         }
507
508         MidiSource::mark_streaming_midi_write_started (mode);
509         Evoral::SMF::begin_write ();
510         _last_ev_time_beats = 0.0;
511         _last_ev_time_frames = 0;
512 }
513
514 void
515 SMFSource::mark_streaming_write_completed ()
516 {
517         mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes);
518 }
519
520 void
521 SMFSource::mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption stuck_notes_option, Evoral::MusicalTime when)
522 {
523         Glib::Threads::Mutex::Lock lm (_lock);
524         MidiSource::mark_midi_streaming_write_completed (stuck_notes_option, when);
525
526         if (!writable()) {
527                 warning << string_compose ("attempt to write to unwritable SMF file %1", _path) << endmsg;
528                 return;
529         }
530
531         if (_model) {
532                 _model->set_edited(false);
533         }
534
535         Evoral::SMF::end_write ();
536
537         /* data in the file now, not removable */
538
539         mark_nonremovable ();
540 }
541
542 bool
543 SMFSource::valid_midi_file (const string& file)
544 {
545         if (safe_midi_file_extension (file) ) {
546                 return (SMF::test (file) );
547         }
548         return false;
549 }
550
551 bool
552 SMFSource::safe_midi_file_extension (const string& file)
553 {
554         static regex_t compiled_pattern;
555         static bool compile = true;
556         const int nmatches = 2;
557         regmatch_t matches[nmatches];
558         
559         if (Glib::file_test (file, Glib::FILE_TEST_EXISTS)) {
560                 if (!Glib::file_test (file, Glib::FILE_TEST_IS_REGULAR)) {
561                         /* exists but is not a regular file */
562                         return false;
563                 }
564         }
565
566         if (compile && regcomp (&compiled_pattern, "\\.[mM][iI][dD][iI]?$", REG_EXTENDED)) {
567                 return false;
568         } else {
569                 compile = false;
570         }
571         
572         if (regexec (&compiled_pattern, file.c_str(), nmatches, matches, 0)) {
573                 return false;
574         }
575
576         return true;
577 }
578
579 static bool compare_eventlist (
580                 const std::pair< Evoral::Event<double>*, gint >& a,
581                 const std::pair< Evoral::Event<double>*, gint >& b) {
582         return ( a.first->time() < b.first->time() );
583 }
584
585 void
586 SMFSource::load_model (bool lock, bool force_reload)
587 {
588         if (_writing) {
589                 return;
590         }
591
592         boost::shared_ptr<Glib::Threads::Mutex::Lock> lm;
593         if (lock)
594                 lm = boost::shared_ptr<Glib::Threads::Mutex::Lock>(new Glib::Threads::Mutex::Lock(_lock));
595
596         if (_model && !force_reload) {
597                 return;
598         }
599
600         if (!_model) {
601                 _model = boost::shared_ptr<MidiModel> (new MidiModel (shared_from_this ()));
602         } else {
603                 _model->clear();
604         }
605
606         if (writable() && !_open) {
607                 return;
608         }
609
610         _model->start_write();
611         Evoral::SMF::seek_to_start();
612
613         uint64_t time = 0; /* in SMF ticks */
614         Evoral::Event<double> ev;
615
616         uint32_t scratch_size = 0; // keep track of scratch and minimize reallocs
617
618         uint32_t delta_t = 0;
619         uint32_t size    = 0;
620         uint8_t* buf     = NULL;
621         int ret;
622         gint event_id;
623         bool have_event_id;
624
625         // TODO simplify event allocation
626         std::list< std::pair< Evoral::Event<double>*, gint > > eventlist;
627
628         for (unsigned i = 1; i <= num_tracks(); ++i) {
629                 if (seek_to_track(i)) continue;
630
631                 time = 0;
632                 have_event_id = false;
633
634                 while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) {
635
636                         time += delta_t;
637
638                         if (ret == 0) {
639                                 /* meta-event : did we get an event ID ?  */
640                                 if (event_id >= 0) {
641                                         have_event_id = true;
642                                 }
643                                 continue;
644                         }
645
646                         if (ret > 0) {
647                                 /* not a meta-event */
648
649                                 if (!have_event_id) {
650                                         event_id = Evoral::next_event_id();
651                                 }
652                                 uint32_t event_type = EventTypeMap::instance().midi_event_type(buf[0]);
653                                 double   event_time = time / (double) ppqn();
654 #ifndef NDEBUG
655                                 std::string ss;
656
657                                 for (uint32_t xx = 0; xx < size; ++xx) {
658                                         char b[8];
659                                         snprintf (b, sizeof (b), "0x%x ", buf[xx]);
660                                         ss += b;
661                                 }
662
663                                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF %6 load model delta %1, time %2, size %3 buf %4, type %5\n",
664                                                         delta_t, time, size, ss , event_type, name()));
665 #endif
666
667                                 eventlist.push_back(make_pair (
668                                                         new Evoral::Event<double> (
669                                                                 event_type, event_time,
670                                                                 size, buf, true)
671                                                         , event_id));
672
673                                 // Set size to max capacity to minimize allocs in read_event
674                                 scratch_size = std::max(size, scratch_size);
675                                 size = scratch_size;
676
677                                 _length_beats = max(_length_beats, event_time);
678                         }
679
680                         /* event ID's must immediately precede the event they are for */
681                         have_event_id = false;
682                 }
683         }
684
685         eventlist.sort(compare_eventlist);
686
687         std::list< std::pair< Evoral::Event<double>*, gint > >::iterator it;
688         for (it=eventlist.begin(); it!=eventlist.end(); ++it) {
689                 _model->append (*it->first, it->second);
690                 delete it->first;
691         }
692
693         _model->end_write (Evoral::Sequence<Evoral::MusicalTime>::ResolveStuckNotes, _length_beats);
694         _model->set_edited (false);
695
696         _model_iter = _model->begin();
697
698         free(buf);
699 }
700
701 void
702 SMFSource::destroy_model ()
703 {
704         //cerr << _name << " destroying model " << _model.get() << endl;
705         _model.reset();
706 }
707
708 void
709 SMFSource::flush_midi ()
710 {
711         if (!writable() || _length_beats == 0.0) {
712                 return;
713         }
714
715         ensure_disk_file ();
716
717         Evoral::SMF::end_write ();
718         /* data in the file means its no longer removable */
719         mark_nonremovable ();
720 }
721
722 void
723 SMFSource::set_path (const string& p)
724 {
725         FileSource::set_path (p);
726         SMF::set_path (_path);
727 }
728
729 /** Ensure that this source has some file on disk, even if it's just a SMF header */
730 void
731 SMFSource::ensure_disk_file ()
732 {
733         if (!writable()) {
734                 return;
735         }
736
737         if (_model) {
738                 /* We have a model, so write it to disk; see MidiSource::session_saved
739                    for an explanation of what we are doing here.
740                 */
741                 boost::shared_ptr<MidiModel> mm = _model;
742                 _model.reset ();
743                 mm->sync_to_source ();
744                 _model = mm;
745         } else {
746                 /* No model; if it's not already open, it's an empty source, so create
747                    and open it for writing.
748                 */
749                 if (!_open) {
750                         open_for_write ();
751                 }
752         }
753 }
754
755 void
756 SMFSource::prevent_deletion ()
757 {
758         /* Unlike the audio case, the MIDI file remains mutable (because we can
759            edit MIDI data)
760         */
761   
762         _flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
763 }
764