remove unused SHUTTLE_FRACT constant
[ardour2.git] / libs / ardour / midi_diskstream.cc
blob6c51958caa859200ac6c41e40a64ccb392fb5c94
1 /*
2 Copyright (C) 2000-2003 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <fstream>
20 #include <cstdio>
21 #include <unistd.h>
22 #include <cmath>
23 #include <cerrno>
24 #include <string>
25 #include <climits>
26 #include <fcntl.h>
27 #include <cstdlib>
28 #include <ctime>
29 #include <sys/stat.h>
30 #include <sys/mman.h>
32 #include "pbd/error.h"
33 #include "pbd/basename.h"
34 #include <glibmm/thread.h>
35 #include "pbd/xml++.h"
36 #include "pbd/memento_command.h"
37 #include "pbd/enumwriter.h"
38 #include "pbd/stateful_diff_command.h"
39 #include "pbd/stacktrace.h"
41 #include "ardour/ardour.h"
42 #include "ardour/audioengine.h"
43 #include "ardour/butler.h"
44 #include "ardour/configuration.h"
45 #include "ardour/cycle_timer.h"
46 #include "ardour/debug.h"
47 #include "ardour/io.h"
48 #include "ardour/midi_diskstream.h"
49 #include "ardour/midi_playlist.h"
50 #include "ardour/midi_port.h"
51 #include "ardour/midi_region.h"
52 #include "ardour/playlist_factory.h"
53 #include "ardour/region_factory.h"
54 #include "ardour/send.h"
55 #include "ardour/session.h"
56 #include "ardour/smf_source.h"
57 #include "ardour/utils.h"
58 #include "ardour/session_playlists.h"
59 #include "ardour/route.h"
61 #include "midi++/types.h"
63 #include "i18n.h"
64 #include <locale.h>
66 using namespace std;
67 using namespace ARDOUR;
68 using namespace PBD;
70 framecnt_t MidiDiskstream::midi_readahead = 4096;
72 MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
73 : Diskstream(sess, name, flag)
74 , _playback_buf(0)
75 , _capture_buf(0)
76 , _source_port(0)
77 , _last_flush_frame(0)
78 , _note_mode(Sustained)
79 , _frames_written_to_ringbuffer(0)
80 , _frames_read_from_ringbuffer(0)
82 in_set_state = true;
84 init ();
85 use_new_playlist ();
86 use_new_write_source (0);
88 in_set_state = false;
90 assert(!destructive());
93 MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
94 : Diskstream(sess, node)
95 , _playback_buf(0)
96 , _capture_buf(0)
97 , _source_port(0)
98 , _last_flush_frame(0)
99 , _note_mode(Sustained)
100 , _frames_written_to_ringbuffer(0)
101 , _frames_read_from_ringbuffer(0)
103 in_set_state = true;
105 init ();
107 if (set_state (node, Stateful::loading_state_version)) {
108 in_set_state = false;
109 throw failed_constructor();
112 use_new_write_source (0);
114 in_set_state = false;
117 void
118 MidiDiskstream::init ()
120 /* there are no channels at this point, so these
121 two calls just get speed_buffer_size and wrap_buffer
122 size setup without duplicating their code.
125 set_block_size (_session.get_block_size());
126 allocate_temporary_buffers ();
128 const size_t size = _session.butler()->midi_diskstream_buffer_size();
129 _playback_buf = new MidiRingBuffer<framepos_t>(size);
130 _capture_buf = new MidiRingBuffer<framepos_t>(size);
132 _n_channels = ChanCount(DataType::MIDI, 1);
134 assert(recordable());
137 MidiDiskstream::~MidiDiskstream ()
139 Glib::Mutex::Lock lm (state_lock);
143 void
144 MidiDiskstream::non_realtime_locate (framepos_t position)
146 if (_write_source) {
147 _write_source->set_timeline_position (position);
149 seek(position, false);
153 void
154 MidiDiskstream::non_realtime_input_change ()
157 Glib::Mutex::Lock lm (state_lock);
159 if (input_change_pending.type == IOChange::NoChange) {
160 return;
163 if (input_change_pending.type & IOChange::ConfigurationChanged) {
164 uint32_t ni = _io->n_ports().n_midi();
166 if (ni != _n_channels.n_midi()) {
167 error << string_compose (_("%1: I/O configuration change %4 requested to use %2, but channel setup is %3"),
168 name(),
169 _io->n_ports(),
170 _n_channels, input_change_pending.type)
171 << endmsg;
174 if (ni == 0) {
175 _source_port = 0;
176 } else {
177 _source_port = _io->midi(0);
181 if (input_change_pending.type & IOChange::ConnectionsChanged) {
182 set_capture_offset ();
183 set_align_style_from_io ();
186 input_change_pending.type = IOChange::NoChange;
188 /* implicit unlock */
191 /* unlike with audio, there is never any need to reset write sources
192 based on input configuration changes because ... a MIDI track
193 has just 1 MIDI port as input, always.
196 /* now refill channel buffers */
198 if (speed() != 1.0f || speed() != -1.0f) {
199 seek ((framepos_t) (_session.transport_frame() * (double) speed()));
201 else {
202 seek (_session.transport_frame());
205 _last_flush_frame = _session.transport_frame();
209 MidiDiskstream::find_and_use_playlist (const string& name)
211 boost::shared_ptr<MidiPlaylist> playlist;
213 if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist> (_session.playlists->by_name (name))) == 0) {
214 playlist = boost::dynamic_pointer_cast<MidiPlaylist> (PlaylistFactory::create (DataType::MIDI, _session, name));
217 if (!playlist) {
218 error << string_compose(_("MidiDiskstream: Playlist \"%1\" isn't an midi playlist"), name) << endmsg;
219 return -1;
222 return use_playlist (playlist);
226 MidiDiskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
228 assert(boost::dynamic_pointer_cast<MidiPlaylist>(playlist));
230 Diskstream::use_playlist(playlist);
232 return 0;
236 MidiDiskstream::use_new_playlist ()
238 string newname;
239 boost::shared_ptr<MidiPlaylist> playlist;
241 if (!in_set_state && destructive()) {
242 return 0;
245 if (_playlist) {
246 newname = Playlist::bump_name (_playlist->name(), _session);
247 } else {
248 newname = Playlist::bump_name (_name, _session);
251 if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist> (PlaylistFactory::create (
252 DataType::MIDI, _session, newname, hidden()))) != 0) {
254 playlist->set_orig_diskstream_id (id());
255 return use_playlist (playlist);
257 } else {
258 return -1;
263 MidiDiskstream::use_copy_playlist ()
265 assert(midi_playlist());
267 if (destructive()) {
268 return 0;
271 if (_playlist == 0) {
272 error << string_compose(_("MidiDiskstream %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
273 return -1;
276 string newname;
277 boost::shared_ptr<MidiPlaylist> playlist;
279 newname = Playlist::bump_name (_playlist->name(), _session);
281 if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist>(PlaylistFactory::create (midi_playlist(), newname))) != 0) {
282 playlist->set_orig_diskstream_id (id());
283 return use_playlist (playlist);
284 } else {
285 return -1;
289 /** Overloaded from parent to die horribly
292 MidiDiskstream::set_destructive (bool yn)
294 assert( ! destructive());
295 assert( ! yn);
296 return -1;
299 void
300 MidiDiskstream::set_note_mode (NoteMode m)
302 _note_mode = m;
303 midi_playlist()->set_note_mode(m);
304 if (_write_source && _write_source->model())
305 _write_source->model()->set_note_mode(m);
308 #if 0
309 static void
310 trace_midi (ostream& o, MIDI::byte *msg, size_t len)
312 using namespace MIDI;
313 eventType type;
314 const char trace_prefix = ':';
316 type = (eventType) (msg[0]&0xF0);
318 switch (type) {
319 case off:
320 o << trace_prefix
321 << "Channel "
322 << (msg[0]&0xF)+1
323 << " NoteOff NoteNum "
324 << (int) msg[1]
325 << " Vel "
326 << (int) msg[2]
327 << endl;
328 break;
330 case on:
331 o << trace_prefix
332 << "Channel "
333 << (msg[0]&0xF)+1
334 << " NoteOn NoteNum "
335 << (int) msg[1]
336 << " Vel "
337 << (int) msg[2]
338 << endl;
339 break;
341 case polypress:
342 o << trace_prefix
343 << "Channel "
344 << (msg[0]&0xF)+1
345 << " PolyPressure"
346 << (int) msg[1]
347 << endl;
348 break;
350 case MIDI::controller:
351 o << trace_prefix
352 << "Channel "
353 << (msg[0]&0xF)+1
354 << " Controller "
355 << (int) msg[1]
356 << " Value "
357 << (int) msg[2]
358 << endl;
359 break;
361 case program:
362 o << trace_prefix
363 << "Channel "
364 << (msg[0]&0xF)+1
365 << " Program Change ProgNum "
366 << (int) msg[1]
367 << endl;
368 break;
370 case chanpress:
371 o << trace_prefix
372 << "Channel "
373 << (msg[0]&0xF)+1
374 << " Channel Pressure "
375 << (int) msg[1]
376 << endl;
377 break;
379 case MIDI::pitchbend:
380 o << trace_prefix
381 << "Channel "
382 << (msg[0]&0xF)+1
383 << " Pitch Bend "
384 << ((msg[2]<<7)|msg[1])
385 << endl;
386 break;
388 case MIDI::sysex:
389 if (len == 1) {
390 switch (msg[0]) {
391 case 0xf8:
392 o << trace_prefix
393 << "Clock"
394 << endl;
395 break;
396 case 0xfa:
397 o << trace_prefix
398 << "Start"
399 << endl;
400 break;
401 case 0xfb:
402 o << trace_prefix
403 << "Continue"
404 << endl;
405 break;
406 case 0xfc:
407 o << trace_prefix
408 << "Stop"
409 << endl;
410 break;
411 case 0xfe:
412 o << trace_prefix
413 << "Active Sense"
414 << endl;
415 break;
416 case 0xff:
417 o << trace_prefix
418 << "System Reset"
419 << endl;
420 break;
421 default:
422 o << trace_prefix
423 << "System Exclusive (1 byte : " << hex << (int) *msg << dec << ')'
424 << endl;
425 break;
427 } else {
428 o << trace_prefix
429 << "System Exclusive (" << len << ") = [ " << hex;
430 for (unsigned int i = 0; i < len; ++i) {
431 o << (int) msg[i] << ' ';
433 o << dec << ']' << endl;
436 break;
438 case MIDI::song:
439 o << trace_prefix << "Song" << endl;
440 break;
442 case MIDI::tune:
443 o << trace_prefix << "Tune" << endl;
444 break;
446 case MIDI::eox:
447 o << trace_prefix << "End-of-System Exclusive" << endl;
448 break;
450 case MIDI::timing:
451 o << trace_prefix << "Timing" << endl;
452 break;
454 case MIDI::start:
455 o << trace_prefix << "Start" << endl;
456 break;
458 case MIDI::stop:
459 o << trace_prefix << "Stop" << endl;
460 break;
462 case MIDI::contineu:
463 o << trace_prefix << "Continue" << endl;
464 break;
466 case active:
467 o << trace_prefix << "Active Sense" << endl;
468 break;
470 default:
471 o << trace_prefix << "Unrecognized MIDI message" << endl;
472 break;
475 #endif
478 MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler)
480 int ret = -1;
481 framecnt_t rec_offset = 0;
482 framecnt_t rec_nframes = 0;
483 bool nominally_recording;
484 bool re = record_enabled ();
486 playback_distance = 0;
488 check_record_status (transport_frame, can_record);
490 nominally_recording = (can_record && re);
492 if (nframes == 0) {
493 return 0;
496 if (_source_port == 0) {
497 return 1;
500 Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK);
502 if (!sm.locked()) {
503 return 1;
506 adjust_capture_position = 0;
508 if (nominally_recording || (re && was_recording && _session.get_record_enabled() && _session.config.get_punch_in())) {
509 OverlapType ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
511 calculate_record_range(ot, transport_frame, nframes, rec_nframes, rec_offset);
513 if (rec_nframes && !was_recording) {
514 _write_source->mark_write_starting_now ();
515 capture_captured = 0;
516 was_recording = true;
520 if (can_record && !_last_capture_sources.empty()) {
521 _last_capture_sources.clear ();
524 if (nominally_recording || rec_nframes) {
526 // Pump entire port buffer into the ring buffer (FIXME: split cycles?)
527 MidiBuffer& buf = _source_port->get_midi_buffer(nframes);
528 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
529 const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
530 assert(ev.buffer());
531 _capture_buf->write(ev.time() + transport_frame, ev.type(), ev.size(), ev.buffer());
534 if (buf.size() != 0) {
535 /* Make a copy of this data and emit it for the GUI to see */
536 boost::shared_ptr<MidiBuffer> copy (new MidiBuffer (buf.capacity ()));
537 for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
538 copy->push_back ((*i).time() + transport_frame, (*i).size(), (*i).buffer());
541 DataRecorded (copy, _write_source); /* EMIT SIGNAL */
544 } else {
546 if (was_recording) {
547 finish_capture (rec_monitors_input);
552 if (rec_nframes) {
554 /* data will be written to disk */
556 if (rec_nframes == nframes && rec_offset == 0) {
557 playback_distance = nframes;
560 adjust_capture_position = rec_nframes;
562 } else if (nominally_recording) {
564 /* XXXX do this for MIDI !!!
565 can't do actual capture yet - waiting for latency effects to finish before we start
568 playback_distance = nframes;
570 } else {
572 /* XXX: should be doing varispeed stuff here, similar to the code in AudioDiskstream::process */
574 playback_distance = nframes;
578 ret = 0;
580 if (commit (nframes)) {
581 need_butler = true;
584 return ret;
587 bool
588 MidiDiskstream::commit (framecnt_t nframes)
590 bool need_butler = false;
592 if (_actual_speed < 0.0) {
593 playback_sample -= playback_distance;
594 } else {
595 playback_sample += playback_distance;
598 if (adjust_capture_position != 0) {
599 capture_captured += adjust_capture_position;
600 adjust_capture_position = 0;
603 uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
604 uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
605 if ((frames_written - frames_read) + nframes < midi_readahead) {
606 need_butler = true;
609 /*cerr << "MDS written: " << frames_written << " - read: " << frames_read <<
610 " = " << frames_written - frames_read
611 << " + " << nframes << " < " << midi_readahead << " = " << need_butler << ")" << endl;*/
613 return need_butler;
616 void
617 MidiDiskstream::set_pending_overwrite (bool yn)
619 /* called from audio thread, so we can use the read ptr and playback sample as we wish */
621 _pending_overwrite = yn;
622 overwrite_frame = playback_sample;
626 MidiDiskstream::overwrite_existing_buffers ()
628 /* This is safe as long as the butler thread is suspended, which it should be */
629 _playback_buf->reset ();
631 g_atomic_int_set (&_frames_read_from_ringbuffer, 0);
632 g_atomic_int_set (&_frames_written_to_ringbuffer, 0);
634 read (overwrite_frame, disk_io_chunk_frames, false);
635 file_frame = overwrite_frame; // it was adjusted by ::read()
636 overwrite_queued = false;
637 _pending_overwrite = false;
639 return 0;
643 MidiDiskstream::seek (framepos_t frame, bool complete_refill)
645 Glib::Mutex::Lock lm (state_lock);
646 int ret = -1;
648 _playback_buf->reset();
649 _capture_buf->reset();
650 g_atomic_int_set(&_frames_read_from_ringbuffer, 0);
651 g_atomic_int_set(&_frames_written_to_ringbuffer, 0);
653 playback_sample = frame;
654 file_frame = frame;
656 if (complete_refill) {
657 while ((ret = do_refill_with_alloc ()) > 0) ;
658 } else {
659 ret = do_refill_with_alloc ();
662 return ret;
666 MidiDiskstream::can_internal_playback_seek (framecnt_t distance)
668 uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
669 uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
670 return ((frames_written - frames_read) < distance);
674 MidiDiskstream::internal_playback_seek (framecnt_t distance)
676 first_recordable_frame += distance;
677 playback_sample += distance;
679 return 0;
682 /** @a start is set to the new frame position (TIME) read up to */
684 MidiDiskstream::read (framepos_t& start, framecnt_t dur, bool reversed)
686 framecnt_t this_read = 0;
687 bool reloop = false;
688 framepos_t loop_end = 0;
689 framepos_t loop_start = 0;
690 Location *loc = 0;
692 if (!reversed) {
694 framecnt_t loop_length = 0;
696 /* Make the use of a Location atomic for this read operation.
698 Note: Locations don't get deleted, so all we care about
699 when I say "atomic" is that we are always pointing to
700 the same one and using a start/length values obtained
701 just once.
704 if ((loc = loop_location) != 0) {
705 loop_start = loc->start();
706 loop_end = loc->end();
707 loop_length = loop_end - loop_start;
710 /* if we are looping, ensure that the first frame we read is at the correct
711 position within the loop.
714 if (loc && (start >= loop_end)) {
715 //cerr << "start adjusted from " << start;
716 start = loop_start + ((start - loop_start) % loop_length);
717 //cerr << "to " << start << endl;
719 //cerr << "start is " << start << " loopstart: " << loop_start << " loopend: " << loop_end << endl;
722 while (dur) {
724 /* take any loop into account. we can't read past the end of the loop. */
726 if (loc && (loop_end - start < dur)) {
727 this_read = loop_end - start;
728 //cerr << "reloop true: thisread: " << this_read << " dur: " << dur << endl;
729 reloop = true;
730 } else {
731 reloop = false;
732 this_read = dur;
735 if (this_read == 0) {
736 break;
739 this_read = min(dur,this_read);
741 if (midi_playlist()->read (*_playback_buf, start, this_read) != this_read) {
742 error << string_compose(
743 _("MidiDiskstream %1: cannot read %2 from playlist at frame %3"),
744 _id, this_read, start) << endmsg;
745 return -1;
748 g_atomic_int_add(&_frames_written_to_ringbuffer, this_read);
750 _read_data_count = _playlist->read_data_count();
752 if (reversed) {
754 // Swap note ons with note offs here. etc?
755 // Fully reversing MIDI requires look-ahead (well, behind) to find previous
756 // CC values etc. hard.
758 } else {
760 /* if we read to the end of the loop, go back to the beginning */
762 if (reloop) {
763 // Synthesize LoopEvent here, because the next events
764 // written will have non-monotonic timestamps.
765 _playback_buf->write(loop_end - 1, LoopEventType, sizeof (framepos_t), (uint8_t *) &loop_start);
766 start = loop_start;
767 } else {
768 start += this_read;
772 dur -= this_read;
773 //offset += this_read;
776 return 0;
780 MidiDiskstream::do_refill_with_alloc ()
782 return do_refill();
786 MidiDiskstream::do_refill ()
788 int ret = 0;
789 size_t write_space = _playback_buf->write_space();
790 bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
792 if (write_space == 0) {
793 return 0;
796 if (reversed) {
797 return 0;
800 /* at end: nothing to do */
801 if (file_frame == max_framepos) {
802 return 0;
805 // At this point we...
806 assert(_playback_buf->write_space() > 0); // ... have something to write to, and
807 assert(file_frame <= max_framepos); // ... something to write
809 // now calculate how much time is in the ringbuffer.
810 // and lets write as much as we need to get this to be midi_readahead;
811 uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
812 uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
813 if ((frames_written - frames_read) >= midi_readahead) {
814 return 0;
817 framecnt_t to_read = midi_readahead - (frames_written - frames_read);
819 //cout << "MDS read for midi_readahead " << to_read << " rb_contains: "
820 // << frames_written - frames_read << endl;
822 to_read = (framecnt_t) min ((framecnt_t) to_read, (framecnt_t) (max_framepos - file_frame));
824 if (read (file_frame, to_read, reversed)) {
825 ret = -1;
828 return ret;
831 /** Flush pending data to disk.
833 * Important note: this function will write *AT MOST* disk_io_chunk_frames
834 * of data to disk. it will never write more than that. If it writes that
835 * much and there is more than that waiting to be written, it will return 1,
836 * otherwise 0 on success or -1 on failure.
838 * If there is less than disk_io_chunk_frames to be written, no data will be
839 * written at all unless @a force_flush is true.
842 MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush)
844 uint32_t to_write;
845 int32_t ret = 0;
846 framecnt_t total;
848 _write_data_count = 0;
850 total = _session.transport_frame() - _last_flush_frame;
852 if (_last_flush_frame > _session.transport_frame() || _last_flush_frame < capture_start_frame) {
853 _last_flush_frame = _session.transport_frame();
856 if (total == 0 || _capture_buf->read_space() == 0
857 || (!force_flush && (total < disk_io_chunk_frames && was_recording))) {
858 goto out;
861 /* if there are 2+ chunks of disk i/o possible for
862 this track, let the caller know so that it can arrange
863 for us to be called again, ASAP.
865 if we are forcing a flush, then if there is* any* extra
866 work, let the caller know.
868 if we are no longer recording and there is any extra work,
869 let the caller know too.
872 if (total >= 2 * disk_io_chunk_frames || ((force_flush || !was_recording) && total > disk_io_chunk_frames)) {
873 ret = 1;
876 to_write = disk_io_chunk_frames;
878 assert(!destructive());
880 if (record_enabled() &&
881 ((_session.transport_frame() - _last_flush_frame > disk_io_chunk_frames) ||
882 force_flush)) {
883 if ((!_write_source) || _write_source->midi_write (*_capture_buf, get_capture_start_frame (0), to_write) != to_write) {
884 error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
885 return -1;
886 } else {
887 _last_flush_frame = _session.transport_frame();
891 out:
892 return ret;
895 void
896 MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen*/, bool abort_capture)
898 bool more_work = true;
899 int err = 0;
900 boost::shared_ptr<MidiRegion> region;
901 MidiRegion::SourceList srcs;
902 MidiRegion::SourceList::iterator src;
903 vector<CaptureInfo*>::iterator ci;
904 bool mark_write_completed = false;
906 finish_capture (true);
908 /* butler is already stopped, but there may be work to do
909 to flush remaining data to disk.
912 while (more_work && !err) {
913 switch (do_flush (TransportContext, true)) {
914 case 0:
915 more_work = false;
916 break;
917 case 1:
918 break;
919 case -1:
920 error << string_compose(_("MidiDiskstream \"%1\": cannot flush captured data to disk!"), _name) << endmsg;
921 err++;
925 /* XXX is there anything we can do if err != 0 ? */
926 Glib::Mutex::Lock lm (capture_info_lock);
928 if (capture_info.empty()) {
929 return;
932 if (abort_capture) {
934 if (_write_source) {
935 _write_source->mark_for_remove ();
936 _write_source->drop_references ();
937 _write_source.reset();
940 /* new source set up in "out" below */
942 } else {
944 assert(_write_source);
946 framecnt_t total_capture = 0;
947 for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
948 total_capture += (*ci)->frames;
951 if (_write_source->length (capture_info.front()->start) != 0) {
953 /* phew, we have data */
955 /* figure out the name for this take */
957 srcs.push_back (_write_source);
959 _write_source->set_timeline_position (capture_info.front()->start);
960 _write_source->set_captured_for (_name);
962 /* flush to disk: this step differs from the audio path,
963 where all the data is already on disk.
966 _write_source->mark_streaming_write_completed ();
968 /* set length in beats to entire capture length */
970 BeatsFramesConverter converter (_session.tempo_map(), capture_info.front()->start);
971 const double total_capture_beats = converter.from(total_capture);
972 _write_source->set_length_beats(total_capture_beats);
974 /* we will want to be able to keep (over)writing the source
975 but we don't want it to be removable. this also differs
976 from the audio situation, where the source at this point
977 must be considered immutable. luckily, we can rely on
978 MidiSource::mark_streaming_write_completed() to have
979 already done the necessary work for that.
982 string whole_file_region_name;
983 whole_file_region_name = region_name_from_path (_write_source->name(), true);
985 /* Register a new region with the Session that
986 describes the entire source. Do this first
987 so that any sub-regions will obviously be
988 children of this one (later!)
991 try {
992 PropertyList plist;
994 plist.add (Properties::name, whole_file_region_name);
995 plist.add (Properties::whole_file, true);
996 plist.add (Properties::automatic, true);
997 plist.add (Properties::start, 0);
998 plist.add (Properties::length, total_capture);
999 plist.add (Properties::layer, 0);
1001 boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
1003 region = boost::dynamic_pointer_cast<MidiRegion> (rx);
1004 region->special_set_position (capture_info.front()->start);
1008 catch (failed_constructor& err) {
1009 error << string_compose(_("%1: could not create region for complete midi file"), _name) << endmsg;
1010 /* XXX what now? */
1013 _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end());
1015 _playlist->clear_changes ();
1016 _playlist->freeze ();
1018 /* Session frame time of the initial capture in this pass, which is where the source starts */
1019 framepos_t initial_capture = 0;
1020 if (!capture_info.empty()) {
1021 initial_capture = capture_info.front()->start;
1024 for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1026 string region_name;
1028 RegionFactory::region_name (region_name, _write_source->name(), false);
1030 // cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add a region\n";
1032 try {
1033 PropertyList plist;
1035 /* start of this region is the offset between the start of its capture and the start of the whole pass */
1036 plist.add (Properties::start, (*ci)->start - initial_capture);
1037 plist.add (Properties::length, (*ci)->frames);
1038 plist.add (Properties::length_beats, converter.from((*ci)->frames));
1039 plist.add (Properties::name, region_name);
1041 boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
1042 region = boost::dynamic_pointer_cast<MidiRegion> (rx);
1045 catch (failed_constructor& err) {
1046 error << _("MidiDiskstream: could not create region for captured midi!") << endmsg;
1047 continue; /* XXX is this OK? */
1050 // cerr << "add new region, buffer position = " << buffer_position << " @ " << (*ci)->start << endl;
1052 i_am_the_modifier++;
1053 _playlist->add_region (region, (*ci)->start);
1054 i_am_the_modifier--;
1057 _playlist->thaw ();
1058 _session.add_command (new StatefulDiffCommand(_playlist));
1060 } else {
1062 /* No data was recorded, so this capture will
1063 effectively be aborted; do the same as we
1064 do for an explicit abort.
1067 if (_write_source) {
1068 _write_source->mark_for_remove ();
1069 _write_source->drop_references ();
1070 _write_source.reset();
1075 mark_write_completed = true;
1078 use_new_write_source (0);
1080 for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1081 delete *ci;
1084 if (_playlist) {
1085 midi_playlist()->clear_note_trackers ();
1088 capture_info.clear ();
1089 capture_start_frame = 0;
1092 void
1093 MidiDiskstream::transport_looped (framepos_t transport_frame)
1095 if (was_recording) {
1097 // adjust the capture length knowing that the data will be recorded to disk
1098 // only necessary after the first loop where we're recording
1099 if (capture_info.size() == 0) {
1100 capture_captured += _capture_offset;
1102 if (_alignment_style == ExistingMaterial) {
1103 capture_captured += _session.worst_output_latency();
1104 } else {
1105 capture_captured += _roll_delay;
1109 finish_capture (true);
1111 // the next region will start recording via the normal mechanism
1112 // we'll set the start position to the current transport pos
1113 // no latency adjustment or capture offset needs to be made, as that already happened the first time
1114 capture_start_frame = transport_frame;
1115 first_recordable_frame = transport_frame; // mild lie
1116 last_recordable_frame = max_framepos;
1117 was_recording = true;
1121 void
1122 MidiDiskstream::finish_capture (bool /*rec_monitors_input*/)
1124 was_recording = false;
1126 if (capture_captured == 0) {
1127 return;
1130 // Why must we destroy?
1131 assert(!destructive());
1133 CaptureInfo* ci = new CaptureInfo;
1135 ci->start = capture_start_frame;
1136 ci->frames = capture_captured;
1138 /* XXX theoretical race condition here. Need atomic exchange ?
1139 However, the circumstances when this is called right
1140 now (either on record-disable or transport_stopped)
1141 mean that no actual race exists. I think ...
1142 We now have a capture_info_lock, but it is only to be used
1143 to synchronize in the transport_stop and the capture info
1144 accessors, so that invalidation will not occur (both non-realtime).
1147 // cerr << "Finish capture, add new CI, " << ci->start << '+' << ci->frames << endl;
1149 capture_info.push_back (ci);
1150 capture_captured = 0;
1153 void
1154 MidiDiskstream::set_record_enabled (bool yn)
1156 if (!recordable() || !_session.record_enabling_legal()) {
1157 return;
1160 assert(!destructive());
1162 /* yes, i know that this not proof against race conditions, but its
1163 good enough. i think.
1166 if (record_enabled() != yn) {
1167 if (yn) {
1168 engage_record_enable ();
1169 } else {
1170 disengage_record_enable ();
1175 void
1176 MidiDiskstream::engage_record_enable ()
1178 bool const rolling = _session.transport_speed() != 0.0f;
1180 g_atomic_int_set (&_record_enabled, 1);
1182 if (_source_port && Config->get_monitoring_model() == HardwareMonitoring) {
1183 _source_port->request_monitor_input (!(_session.config.get_auto_input() && rolling));
1186 RecordEnableChanged (); /* EMIT SIGNAL */
1189 void
1190 MidiDiskstream::disengage_record_enable ()
1192 g_atomic_int_set (&_record_enabled, 0);
1193 RecordEnableChanged (); /* EMIT SIGNAL */
1196 XMLNode&
1197 MidiDiskstream::get_state ()
1199 XMLNode& node (Diskstream::get_state());
1200 char buf[64];
1201 LocaleGuard lg (X_("POSIX"));
1203 node.add_property("channel-mode", enum_2_string(get_channel_mode()));
1204 snprintf (buf, sizeof(buf), "0x%x", get_channel_mask());
1205 node.add_property("channel-mask", buf);
1207 if (_write_source && _session.get_record_enabled()) {
1209 XMLNode* cs_child = new XMLNode (X_("CapturingSources"));
1210 XMLNode* cs_grandchild;
1212 cs_grandchild = new XMLNode (X_("file"));
1213 cs_grandchild->add_property (X_("path"), _write_source->path());
1214 cs_child->add_child_nocopy (*cs_grandchild);
1216 /* store the location where capture will start */
1218 Location* pi;
1220 if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
1221 snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
1222 } else {
1223 snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
1226 cs_child->add_property (X_("at"), buf);
1227 node.add_child_nocopy (*cs_child);
1230 return node;
1234 MidiDiskstream::set_state (const XMLNode& node, int version)
1236 const XMLProperty* prop;
1237 XMLNodeList nlist = node.children();
1238 XMLNodeIterator niter;
1239 XMLNode* capture_pending_node = 0;
1240 LocaleGuard lg (X_("POSIX"));
1242 /* prevent write sources from being created */
1244 in_set_state = true;
1246 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1247 assert ((*niter)->name() != IO::state_node_name);
1249 if ((*niter)->name() == X_("CapturingSources")) {
1250 capture_pending_node = *niter;
1254 if (Diskstream::set_state (node, version)) {
1255 return -1;
1258 ChannelMode channel_mode = AllChannels;
1259 if ((prop = node.property ("channel-mode")) != 0) {
1260 channel_mode = ChannelMode (string_2_enum(prop->value(), channel_mode));
1263 unsigned int channel_mask = 0xFFFF;
1264 if ((prop = node.property ("channel-mask")) != 0) {
1265 sscanf (prop->value().c_str(), "0x%x", &channel_mask);
1266 if (channel_mask & (~0xFFFF)) {
1267 warning << _("MidiDiskstream: XML property channel-mask out of range") << endmsg;
1272 if (capture_pending_node) {
1273 use_pending_capture_data (*capture_pending_node);
1276 set_channel_mode (channel_mode, channel_mask);
1278 in_set_state = false;
1280 return 0;
1284 MidiDiskstream::use_new_write_source (uint32_t n)
1286 if (!_session.writable() || !recordable()) {
1287 return 1;
1290 assert(n == 0);
1292 _write_source.reset();
1294 try {
1295 _write_source = boost::dynamic_pointer_cast<SMFSource>(
1296 _session.create_midi_source_for_session (0, name ()));
1298 if (!_write_source) {
1299 throw failed_constructor();
1303 catch (failed_constructor &err) {
1304 error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
1305 _write_source.reset();
1306 return -1;
1309 return 0;
1312 list<boost::shared_ptr<Source> >
1313 MidiDiskstream::steal_write_sources()
1315 list<boost::shared_ptr<Source> > ret;
1317 /* put some data on the disk, even if its just a header for an empty file */
1318 boost::dynamic_pointer_cast<SMFSource> (_write_source)->ensure_disk_file ();
1320 /* never let it go away */
1321 _write_source->mark_nonremovable ();
1323 ret.push_back (_write_source);
1325 /* get a new one */
1327 use_new_write_source (0);
1329 return ret;
1332 void
1333 MidiDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
1335 if (!_session.writable() || !recordable()) {
1336 return;
1339 if (_write_source && mark_write_complete) {
1340 _write_source->mark_streaming_write_completed ();
1342 use_new_write_source (0);
1345 void
1346 MidiDiskstream::set_block_size (pframes_t /*nframes*/)
1350 void
1351 MidiDiskstream::allocate_temporary_buffers ()
1355 void
1356 MidiDiskstream::monitor_input (bool yn)
1358 if (_source_port)
1359 _source_port->ensure_monitor_input (yn);
1362 void
1363 MidiDiskstream::set_align_style_from_io ()
1365 if (_alignment_choice != Automatic) {
1366 return;
1369 /* XXX Not sure what, if anything we can do with MIDI
1370 as far as capture alignment etc.
1373 set_align_style (ExistingMaterial);
1377 float
1378 MidiDiskstream::playback_buffer_load () const
1380 return (float) ((double) _playback_buf->read_space()/
1381 (double) _playback_buf->capacity());
1384 float
1385 MidiDiskstream::capture_buffer_load () const
1387 return (float) ((double) _capture_buf->write_space()/
1388 (double) _capture_buf->capacity());
1392 MidiDiskstream::use_pending_capture_data (XMLNode& /*node*/)
1394 return 0;
1397 /** Writes playback events in the given range to \a dst, translating time stamps
1398 * so that an event at \a start has time = 0
1400 void
1401 MidiDiskstream::get_playback (MidiBuffer& dst, framepos_t start, framepos_t end)
1403 dst.clear();
1404 assert(dst.size() == 0);
1406 // Reverse. ... We just don't do reverse, ok? Back off.
1407 if (end <= start) {
1408 return;
1411 // Translate stamps to be relative to start
1414 #ifndef NDEBUG
1415 DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
1416 "%1 MDS pre-read read from %2 write to %3\n", _name,
1417 _playback_buf->get_read_ptr(), _playback_buf->get_write_ptr()));
1418 // cerr << "================\n";
1419 // _playback_buf->dump (cerr);
1420 // cerr << "----------------\n";
1422 const size_t events_read = _playback_buf->read(dst, start, end);
1423 DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose (
1424 "%1 MDS events read %2 range %3 .. %4 rspace %5 wspace %6 r@%7 w@%8\n",
1425 _name, events_read, start, end,
1426 _playback_buf->read_space(), _playback_buf->write_space(),
1427 _playback_buf->get_read_ptr(), _playback_buf->get_write_ptr()));
1428 #else
1429 _playback_buf->read(dst, start, end);
1430 #endif
1432 gint32 frames_read = end - start;
1433 g_atomic_int_add(&_frames_read_from_ringbuffer, frames_read);
1436 bool
1437 MidiDiskstream::set_name (string const & name)
1439 Diskstream::set_name (name);
1441 /* get a new write source so that its name reflects the new diskstream name */
1442 use_new_write_source (0);
1444 return true;