dramatic change in logic and naming for operations related to adding a MIDI region...
[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 <glib/gstdio.h>
34 #include <glibmm/miscutils.h>
35 #include <glibmm/fileutils.h>
36
37 #include "evoral/Control.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
53 /** Constructor used for new internal-to-session files.  File cannot exist. */
54 SMFSource::SMFSource (Session& s, const string& path, Source::Flag flags)
55         : Source(s, DataType::MIDI, path, flags)
56         , MidiSource(s, path, flags)
57         , FileSource(s, DataType::MIDI, path, string(), flags)
58         , Evoral::SMF()
59         , _last_ev_time_beats(0.0)
60         , _last_ev_time_frames(0)
61         , _smf_last_read_end (0)
62         , _smf_last_read_time (0)
63 {
64         /* note that origin remains empty */
65
66         if (init(_path, false)) {
67                 throw failed_constructor ();
68         }
69
70         /* file is not opened until write */
71
72         if (flags & Writable) {
73                 return;
74         }
75
76         if (open (_path)) {
77                 throw failed_constructor ();
78         }
79
80         _open = true;
81 }
82
83 /** Constructor used for existing internal-to-session files. */
84 SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
85         : Source(s, node)
86         , MidiSource(s, node)
87         , FileSource(s, node, must_exist)
88         , _last_ev_time_beats(0.0)
89         , _last_ev_time_frames(0)
90         , _smf_last_read_end (0)
91         , _smf_last_read_time (0)
92 {
93         if (set_state(node, Stateful::loading_state_version)) {
94                 throw failed_constructor ();
95         }
96
97         if (init(_path, true)) {
98                 throw failed_constructor ();
99         }
100
101         if (open(_path)) {
102                 throw failed_constructor ();
103         }
104
105         _open = true;
106 }
107
108 SMFSource::~SMFSource ()
109 {
110         if (removable()) {
111                 ::g_unlink (_path.c_str());
112         }
113 }
114
115 int
116 SMFSource::open_for_write ()
117 {
118         if (create (_path)) {
119                 return -1;
120         }
121         _open = true;
122         return 0;
123 }
124
125 /** All stamps in audio frames */
126 framecnt_t
127 SMFSource::read_unlocked (Evoral::EventSink<framepos_t>& destination,
128                           framepos_t const               source_start,
129                           framepos_t                     start,
130                           framecnt_t                     duration,
131                           MidiStateTracker*              tracker) const
132 {
133         int      ret  = 0;
134         uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
135
136         if (writable() && !_open) {
137                 /* nothing to read since nothing has ben written */
138                 return duration;
139         }
140
141         DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start %1 duration %2\n", start, duration));
142
143         // Output parameters for read_event (which will allocate scratch in buffer as needed)
144         uint32_t ev_delta_t = 0;
145         uint32_t ev_type    = 0;
146         uint32_t ev_size    = 0;
147         uint8_t* ev_buffer  = 0;
148
149         size_t scratch_size = 0; // keep track of scratch to minimize reallocs
150
151         BeatsFramesConverter converter(_session.tempo_map(), source_start);
152
153         const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
154         DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: start in ticks %1\n", start_ticks));
155
156         if (_smf_last_read_end == 0 || start != _smf_last_read_end) {
157                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: seek to %1\n", start));
158                 Evoral::SMF::seek_to_start();
159                 while (time < start_ticks) {
160                         gint ignored;
161
162                         ret = read_event(&ev_delta_t, &ev_size, &ev_buffer, &ignored);
163                         if (ret == -1) { // EOF
164                                 _smf_last_read_end = start + duration;
165                                 return duration;
166                         }
167                         time += ev_delta_t; // accumulate delta time
168                 }
169         } else {
170                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked: set time to %1\n", _smf_last_read_time));
171                 time = _smf_last_read_time;
172         }
173
174         _smf_last_read_end = start + duration;
175
176         while (true) {
177                 gint ignored; /* XXX don't ignore note id's ??*/
178
179                 ret = read_event(&ev_delta_t, &ev_size, &ev_buffer, &ignored);
180                 if (ret == -1) { // EOF
181                         break;
182                 }
183
184                 time += ev_delta_t; // accumulate delta time
185                 _smf_last_read_time = time;
186
187                 if (ret == 0) { // meta-event (skipped, just accumulate time)
188                         continue;
189                 }
190
191                 ev_type = EventTypeMap::instance().midi_event_type(ev_buffer[0]);
192
193                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF read_unlocked delta %1, time %2, buf[0] %3, type %4\n",
194                                                                   ev_delta_t, time, ev_buffer[0], ev_type));
195
196                 assert(time >= start_ticks);
197
198                 /* Note that we add on the source start time (in session frames) here so that ev_frame_time
199                    is in session frames.
200                 */
201                 const framepos_t ev_frame_time = converter.to(time / (double)ppqn()) + source_start;
202
203                 if (ev_frame_time < start + duration) {
204                         destination.write (ev_frame_time, ev_type, ev_size, ev_buffer);
205
206                         if (tracker) {
207                                 if (ev_buffer[0] & MIDI_CMD_NOTE_ON) {
208                                         tracker->add (ev_buffer[1], ev_buffer[0] & 0xf);
209                                 } else if (ev_buffer[0] & MIDI_CMD_NOTE_OFF) {
210                                         tracker->remove (ev_buffer[1], ev_buffer[0] & 0xf);
211                                 }
212                         }
213                 } else {
214                         break;
215                 }
216
217                 if (ev_size > scratch_size) {
218                         scratch_size = ev_size;
219                 }
220                 ev_size = scratch_size; // ensure read_event only allocates if necessary
221         }
222
223         return duration;
224 }
225
226 framecnt_t
227 SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source,
228                            framepos_t                  position,
229                            framecnt_t                  cnt)
230 {
231         if (!_writing) {
232                 mark_streaming_write_started ();
233         }
234
235         framepos_t        time;
236         Evoral::EventType type;
237         uint32_t          size;
238
239         size_t   buf_capacity = 4;
240         uint8_t* buf          = (uint8_t*)malloc(buf_capacity);
241
242         if (_model && !_model->writing()) {
243                 _model->start_write();
244         }
245
246         Evoral::MIDIEvent<framepos_t> ev;
247         while (true) {
248                 /* Get the event time, in frames since session start but ignoring looping. */
249                 bool ret;
250                 if (!(ret = source.peek ((uint8_t*)&time, sizeof (time)))) {
251                         /* Ring is empty, no more events. */
252                         break;
253                 }
254
255                 if ((cnt != max_framecnt) &&
256                     (time > position + _capture_length + cnt)) {
257                         /* The diskstream doesn't want us to write everything, and this
258                            event is past the end of this block, so we're done for now. */
259                         break;
260                 }
261
262                 /* Read the time, type, and size of the event. */
263                 if (!(ret = source.read_prefix (&time, &type, &size))) {
264                         error << _("Unable to read event prefix, corrupt MIDI ring") << endmsg;
265                         break;
266                 }
267
268                 /* Enlarge body buffer if necessary now that we know the size. */
269                 if (size > buf_capacity) {
270                         buf_capacity = size;
271                         buf = (uint8_t*)realloc(buf, size);
272                 }
273
274                 /* Read the event body into buffer. */
275                 ret = source.read_contents(size, buf);
276                 if (!ret) {
277                         error << _("Event has time and size but no body, corrupt MIDI ring") << endmsg;
278                         break;
279                 }
280
281                 /* Convert event time from absolute to source relative. */
282                 if (time < position) {
283                         error << _("Event time is before MIDI source position") << endmsg;
284                         break;
285                 }
286                 time -= position;
287                         
288                 ev.set(buf, size, time);
289                 ev.set_event_type(EventTypeMap::instance().midi_event_type(ev.buffer()[0]));
290                 ev.set_id(Evoral::next_event_id());
291
292                 if (!(ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex())) {
293                         continue;
294                 }
295
296                 append_event_unlocked_frames(ev, position);
297         }
298
299         Evoral::SMF::flush ();
300         free (buf);
301
302         return cnt;
303 }
304
305 /** Append an event with a timestamp in beats (double) */
306 void
307 SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
308 {
309         if (!_writing || ev.size() == 0)  {
310                 return;
311         }
312
313         /*printf("SMFSource: %s - append_event_unlocked_beats ID = %d time = %lf, size = %u, data = ",
314                name().c_str(), ev.id(), ev.time(), ev.size());
315                for (size_t i = 0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/
316
317         if (ev.time() < _last_ev_time_beats) {
318                 warning << string_compose(_("Skipping event with unordered time %1"), ev.time())
319                         << endmsg;
320                 return;
321         }
322
323         Evoral::event_id_t event_id;
324
325         if (ev.id() < 0) {
326                 event_id  = Evoral::next_event_id();
327         } else {
328                 event_id = ev.id();
329         }
330
331         if (_model) {
332                 _model->append (ev, event_id);
333         }
334
335         _length_beats = max(_length_beats, ev.time());
336
337         const double delta_time_beats   = ev.time() - _last_ev_time_beats;
338         const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
339
340         Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
341         _last_ev_time_beats = ev.time();
342 }
343
344 /** Append an event with a timestamp in frames (framepos_t) */
345 void
346 SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, framepos_t position)
347 {
348         if (!_writing || ev.size() == 0)  {
349                 return;
350         }
351
352         // printf("SMFSource: %s - append_event_unlocked_frames ID = %d time = %u, size = %u, data = ",
353         // name().c_str(), ev.id(), ev.time(), ev.size());
354         // for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");
355
356         if (ev.time() < _last_ev_time_frames) {
357                 warning << string_compose(_("Skipping event with unordered time %1"), ev.time())
358                         << endmsg;
359                 return;
360         }
361
362         BeatsFramesConverter converter(_session.tempo_map(), position);
363         const double ev_time_beats = converter.from(ev.time());
364         Evoral::event_id_t event_id;
365
366         if (ev.id() < 0) {
367                 event_id  = Evoral::next_event_id();
368         } else {
369                 event_id = ev.id();
370         }
371
372         if (_model) {
373                 const Evoral::Event<double> beat_ev (ev.event_type(),
374                                                      ev_time_beats,
375                                                      ev.size(),
376                                                      const_cast<uint8_t*>(ev.buffer()));
377                 _model->append (beat_ev, event_id);
378         }
379
380         _length_beats = max(_length_beats, ev_time_beats);
381
382         const Evoral::MusicalTime last_time_beats  = converter.from (_last_ev_time_frames);
383         const Evoral::MusicalTime delta_time_beats = ev_time_beats - last_time_beats;
384         const uint32_t            delta_time_ticks = (uint32_t)(lrint(delta_time_beats * (double)ppqn()));
385
386         Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer(), event_id);
387         _last_ev_time_frames = ev.time();
388 }
389
390 XMLNode&
391 SMFSource::get_state ()
392 {
393         XMLNode& node = MidiSource::get_state();
394         node.add_property (X_("origin"), _origin);
395         return node;
396 }
397
398 int
399 SMFSource::set_state (const XMLNode& node, int version)
400 {
401         if (Source::set_state (node, version)) {
402                 return -1;
403         }
404
405         if (MidiSource::set_state (node, version)) {
406                 return -1;
407         }
408
409         if (FileSource::set_state (node, version)) {
410                 return -1;
411         }
412
413         return 0;
414 }
415
416 void
417 SMFSource::mark_streaming_midi_write_started (NoteMode mode)
418 {
419         /* CALLER MUST HOLD LOCK */
420
421         if (!_open && open_for_write()) {
422                 error << string_compose (_("cannot open MIDI file %1 for write"), _path) << endmsg;
423                 /* XXX should probably throw or return something */
424                 return;
425         }
426
427         MidiSource::mark_streaming_midi_write_started (mode);
428         Evoral::SMF::begin_write ();
429         _last_ev_time_beats = 0.0;
430         _last_ev_time_frames = 0;
431 }
432
433 void
434 SMFSource::mark_streaming_write_completed ()
435 {
436         mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::DeleteStuckNotes);
437 }
438
439 void
440 SMFSource::mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::MusicalTime>::StuckNoteOption stuck_notes_option, Evoral::MusicalTime when)
441 {
442         Glib::Threads::Mutex::Lock lm (_lock);
443         MidiSource::mark_midi_streaming_write_completed (stuck_notes_option, when);
444
445         if (!writable()) {
446                 warning << string_compose ("attempt to write to unwritable SMF file %1", _path) << endmsg;
447                 return;
448         }
449
450         if (_model) {
451                 _model->set_edited(false);
452         }
453
454         Evoral::SMF::end_write ();
455
456         /* data in the file now, not removable */
457
458         mark_nonremovable ();
459 }
460
461 bool
462 SMFSource::safe_midi_file_extension (const string& file)
463 {
464         static regex_t compiled_pattern;
465         static bool compile = true;
466         const int nmatches = 2;
467         regmatch_t matches[nmatches];
468         
469         if (Glib::file_test (file, Glib::FILE_TEST_EXISTS)) {
470                 if (!Glib::file_test (file, Glib::FILE_TEST_IS_REGULAR)) {
471                         /* exists but is not a regular file */
472                         return false;
473                 }
474         }
475
476         if (compile && regcomp (&compiled_pattern, "\\.[mM][iI][dD][iI]?$", REG_EXTENDED)) {
477                 return false;
478         } else {
479                 compile = false;
480         }
481         
482         if (regexec (&compiled_pattern, file.c_str(), nmatches, matches, 0)) {
483                 return false;
484         }
485
486         return true;
487 }
488
489 static bool compare_eventlist (
490                 const std::pair< Evoral::Event<double>*, gint >& a,
491                 const std::pair< Evoral::Event<double>*, gint >& b) {
492         return ( a.first->time() < b.first->time() );
493 }
494
495 void
496 SMFSource::load_model (bool lock, bool force_reload)
497 {
498         if (_writing) {
499                 return;
500         }
501
502         boost::shared_ptr<Glib::Threads::Mutex::Lock> lm;
503         if (lock)
504                 lm = boost::shared_ptr<Glib::Threads::Mutex::Lock>(new Glib::Threads::Mutex::Lock(_lock));
505
506         if (_model && !force_reload) {
507                 return;
508         }
509
510         if (!_model) {
511                 _model = boost::shared_ptr<MidiModel> (new MidiModel (shared_from_this ()));
512         } else {
513                 _model->clear();
514         }
515
516         if (writable() && !_open) {
517                 return;
518         }
519
520         _model->start_write();
521         Evoral::SMF::seek_to_start();
522
523         uint64_t time = 0; /* in SMF ticks */
524         Evoral::Event<double> ev;
525
526         uint32_t scratch_size = 0; // keep track of scratch and minimize reallocs
527
528         uint32_t delta_t = 0;
529         uint32_t size    = 0;
530         uint8_t* buf     = NULL;
531         int ret;
532         gint event_id;
533         bool have_event_id;
534
535         // TODO simplify event allocation
536         std::list< std::pair< Evoral::Event<double>*, gint > > eventlist;
537
538         for (unsigned i = 1; i <= num_tracks(); ++i) {
539                 if (seek_to_track(i)) continue;
540
541                 time = 0;
542                 have_event_id = false;
543
544                 while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) {
545
546                         time += delta_t;
547
548                         if (ret == 0) {
549                                 /* meta-event : did we get an event ID ?  */
550                                 if (event_id >= 0) {
551                                         have_event_id = true;
552                                 }
553                                 continue;
554                         }
555
556                         if (ret > 0) {
557                                 /* not a meta-event */
558
559                                 if (!have_event_id) {
560                                         event_id = Evoral::next_event_id();
561                                 }
562                                 uint32_t event_type = EventTypeMap::instance().midi_event_type(buf[0]);
563                                 double   event_time = time / (double) ppqn();
564 #ifndef NDEBUG
565                                 std::string ss;
566
567                                 for (uint32_t xx = 0; xx < size; ++xx) {
568                                         char b[8];
569                                         snprintf (b, sizeof (b), "0x%x ", buf[xx]);
570                                         ss += b;
571                                 }
572
573                                 DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("SMF %6 load model delta %1, time %2, size %3 buf %4, type %5\n",
574                                                         delta_t, time, size, ss , event_type, name()));
575 #endif
576
577                                 eventlist.push_back(make_pair (
578                                                         new Evoral::Event<double> (
579                                                                 event_type, event_time,
580                                                                 size, buf, true)
581                                                         , event_id));
582
583                                 // Set size to max capacity to minimize allocs in read_event
584                                 scratch_size = std::max(size, scratch_size);
585                                 size = scratch_size;
586
587                                 _length_beats = max(_length_beats, event_time);
588                         }
589
590                         /* event ID's must immediately precede the event they are for */
591                         have_event_id = false;
592                 }
593         }
594
595         eventlist.sort(compare_eventlist);
596
597         std::list< std::pair< Evoral::Event<double>*, gint > >::iterator it;
598         for (it=eventlist.begin(); it!=eventlist.end(); ++it) {
599                 _model->append (*it->first, it->second);
600                 delete it->first;
601         }
602
603         _model->end_write (Evoral::Sequence<Evoral::MusicalTime>::ResolveStuckNotes, _length_beats);
604         _model->set_edited (false);
605
606         _model_iter = _model->begin();
607
608         free(buf);
609 }
610
611 void
612 SMFSource::destroy_model ()
613 {
614         //cerr << _name << " destroying model " << _model.get() << endl;
615         _model.reset();
616 }
617
618 void
619 SMFSource::flush_midi ()
620 {
621         if (!writable() || (writable() && !_open)) {
622                 return;
623         }
624
625         Evoral::SMF::end_write ();
626         /* data in the file means its no longer removable */
627         mark_nonremovable ();
628 }
629
630 void
631 SMFSource::set_path (const string& p)
632 {
633         FileSource::set_path (p);
634         SMF::set_path (_path);
635 }
636
637 /** Ensure that this source has some file on disk, even if it's just a SMF header */
638 void
639 SMFSource::ensure_disk_file ()
640 {
641         if (_model) {
642                 /* We have a model, so write it to disk; see MidiSource::session_saved
643                    for an explanation of what we are doing here.
644                 */
645                 boost::shared_ptr<MidiModel> mm = _model;
646                 _model.reset ();
647                 mm->sync_to_source ();
648                 _model = mm;
649         } else {
650                 /* No model; if it's not already open, it's an empty source, so create
651                    and open it for writing.
652                 */
653                 if (!_open) {
654                         open_for_write ();
655                 }
656
657                 /* Flush, which will definitely put something on disk */
658                 flush_midi ();
659         }
660 }
661
662 void
663 SMFSource::prevent_deletion ()
664 {
665         /* Unlike the audio case, the MIDI file remains mutable (because we can
666            edit MIDI data)
667         */
668   
669         _flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
670 }