ardour
midi_diskstream.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000-2003 Paul Davis
3 
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.
8 
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.
13 
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.
17 */
18 
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 
31 #include "pbd/error.h"
32 #include "pbd/ffs.h"
33 #include "pbd/basename.h"
34 #include <glibmm/threads.h>
35 #include "pbd/xml++.h"
36 #include "pbd/memento_command.h"
37 #include "pbd/enumwriter.h"
39 #include "pbd/stacktrace.h"
40 
41 #include "ardour/audioengine.h"
42 #include "ardour/butler.h"
43 #include "ardour/debug.h"
44 #include "ardour/io.h"
45 #include "ardour/midi_diskstream.h"
46 #include "ardour/midi_model.h"
47 #include "ardour/midi_playlist.h"
48 #include "ardour/midi_port.h"
49 #include "ardour/midi_region.h"
51 #include "ardour/midi_track.h"
53 #include "ardour/region_factory.h"
54 #include "ardour/session.h"
56 #include "ardour/smf_source.h"
57 #include "ardour/types.h"
58 #include "ardour/utils.h"
59 
60 #include "midi++/types.h"
61 
62 #include "i18n.h"
63 #include <locale.h>
64 
65 using namespace std;
66 using namespace ARDOUR;
67 using namespace PBD;
68 
69 framecnt_t MidiDiskstream::midi_readahead = 4096;
70 
71 MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::Flag flag)
72  : Diskstream(sess, name, flag)
73  , _playback_buf(0)
74  , _capture_buf(0)
75  , _note_mode(Sustained)
76  , _frames_written_to_ringbuffer(0)
77  , _frames_read_from_ringbuffer(0)
78  , _frames_pending_write(0)
79  , _num_captured_loops(0)
80  , _accumulated_capture_offset(0)
81  , _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
82 {
83  in_set_state = true;
84 
85  init ();
86  use_new_playlist ();
87  use_new_write_source (0);
88 
89  in_set_state = false;
90 
91  if (destructive()) {
92  throw failed_constructor();
93  }
94 }
95 
97  : Diskstream(sess, node)
98  , _playback_buf(0)
99  , _capture_buf(0)
100  , _note_mode(Sustained)
101  , _frames_written_to_ringbuffer(0)
102  , _frames_read_from_ringbuffer(0)
103  , _frames_pending_write(0)
104  , _num_captured_loops(0)
105  , _accumulated_capture_offset(0)
106  , _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI))
107 {
108  in_set_state = true;
109 
110  init ();
111 
113  in_set_state = false;
114  throw failed_constructor();
115  }
116 
118 
119  in_set_state = false;
120 }
121 
122 void
124 {
125  /* there are no channels at this point, so these
126  two calls just get speed_buffer_size and wrap_buffer
127  size setup without duplicating their code.
128  */
129 
132 
133  const size_t size = _session.butler()->midi_diskstream_buffer_size();
136 
139 }
140 
142 {
144  delete _playback_buf;
145  delete _capture_buf;
146 }
147 
148 
149 void
151 {
152  if (_write_source) {
153  _write_source->set_timeline_position (position);
154  }
155  seek (position, false);
156 }
157 
158 
159 void
161 {
162  {
164 
166  return;
167  }
168 
170  uint32_t ni = _io->n_ports().n_midi();
171 
172  if (ni != _n_channels.n_midi()) {
173  error << string_compose (_("%1: I/O configuration change %4 requested to use %2, but channel setup is %3"),
174  name(),
175  _io->n_ports(),
177  << endmsg;
178  }
179 
180  if (ni == 0) {
181  _source_port.reset ();
182  } else {
183  _source_port = _io->midi(0);
184  }
185  }
186 
190  }
191 
193 
194  /* implicit unlock */
195  }
196 
197  /* unlike with audio, there is never any need to reset write sources
198  based on input configuration changes because ... a MIDI track
199  has just 1 MIDI port as input, always.
200  */
201 
202  /* now refill channel buffers */
203 
204  if (speed() != 1.0f || speed() != -1.0f) {
205  seek ((framepos_t) (_session.transport_frame() * (double) speed()));
206  }
207  else {
209  }
210 
211  g_atomic_int_set(const_cast<gint*> (&_frames_pending_write), 0);
212  g_atomic_int_set(const_cast<gint*> (&_num_captured_loops), 0);
213 }
214 
215 int
217 {
219 
220  if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist> (_session.playlists->by_name (name))) == 0) {
222  }
223 
224  if (!playlist) {
225  error << string_compose(_("MidiDiskstream: Playlist \"%1\" isn't a midi playlist"), name) << endmsg;
226  return -1;
227  }
228 
229  return use_playlist (playlist);
230 }
231 
232 int
234 {
235  if (boost::dynamic_pointer_cast<MidiPlaylist>(playlist)) {
236  Diskstream::use_playlist(playlist);
237  }
238 
239  return 0;
240 }
241 
242 int
244 {
245  string newname;
247 
248  if (!in_set_state && destructive()) {
249  return 0;
250  }
251 
252  if (_playlist) {
253  newname = Playlist::bump_name (_playlist->name(), _session);
254  } else {
255  newname = Playlist::bump_name (_name, _session);
256  }
257 
258  if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist> (PlaylistFactory::create (
259  DataType::MIDI, _session, newname, hidden()))) != 0) {
260 
261  return use_playlist (playlist);
262 
263  } else {
264  return -1;
265  }
266 }
267 
268 int
270 {
271  if (destructive()) {
272  return 0;
273  }
274 
275  if (_playlist == 0) {
276  error << string_compose(_("MidiDiskstream %1: there is no existing playlist to make a copy of!"), _name) << endmsg;
277  return -1;
278  }
279 
280  string newname;
282 
283  newname = Playlist::bump_name (_playlist->name(), _session);
284 
285  if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist>(PlaylistFactory::create (midi_playlist(), newname))) != 0) {
286  return use_playlist (playlist);
287  } else {
288  return -1;
289  }
290 }
291 
294 int
296 {
297  return yn ? -1 : 0;
298 }
299 
300 void
302 {
303  _note_mode = m;
304  midi_playlist()->set_note_mode(m);
305  if (_write_source && _write_source->model())
306  _write_source->model()->set_note_mode(m);
307 }
308 
316 static void
317 get_location_times(const Location* location,
318  framepos_t* start,
319  framepos_t* end,
321 {
322  if (location) {
323  *start = location->start();
324  *end = location->end();
325  *length = *end - *start;
326  }
327 }
328 
329 int
330 MidiDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t nframes, framecnt_t& playback_distance, bool need_disk_signal)
331 {
332  framecnt_t rec_offset = 0;
333  framecnt_t rec_nframes = 0;
334  bool nominally_recording;
335  bool re = record_enabled ();
336  bool can_record = _session.actively_recording ();
337 
338  playback_distance = 0;
339 
340  check_record_status (transport_frame, can_record);
341 
342  nominally_recording = (can_record && re);
343 
344  if (nframes == 0) {
345  return 0;
346  }
347 
349 
350  if (sp == 0) {
351  return 1;
352  }
353 
354  Glib::Threads::Mutex::Lock sm (state_lock, Glib::Threads::TRY_LOCK);
355 
356  if (!sm.locked()) {
357  return 1;
358  }
359 
360  const Location* const loop_loc = loop_location;
361  framepos_t loop_start = 0;
362  framepos_t loop_end = 0;
363  framepos_t loop_length = 0;
364  get_location_times(loop_loc, &loop_start, &loop_end, &loop_length);
365 
367 
368  if (nominally_recording || (re && was_recording && _session.get_record_enabled() && _session.config.get_punch_in())) {
369  Evoral::OverlapType ot = Evoral::coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
370  // XXX should this be transport_frame + nframes - 1 ? coverage() expects its parameter ranges to include their end points
371 
372  calculate_record_range(ot, transport_frame, nframes, rec_nframes, rec_offset);
373  /* For audio: not writing frames to the capture ringbuffer offsets
374  * the recording. For midi: we need to keep track of the record range
375  * and subtract the accumulated difference from the event time.
376  */
377  if (rec_nframes) {
378  _accumulated_capture_offset += rec_offset;
379  } else {
380  _accumulated_capture_offset += nframes;
381  }
382 
383  if (rec_nframes && !was_recording) {
384  if (loop_loc) {
385  /* Loop recording, so pretend the capture started at the loop
386  start rgardless of what time it is now, so the source starts
387  at the loop start and can handle time wrapping around.
388  Otherwise, start the source right now as usual.
389  */
390  capture_captured = transport_frame - loop_start;
391  capture_start_frame = loop_start;
392  }
393  _write_source->mark_write_starting_now(
394  capture_start_frame, capture_captured, loop_length);
395  g_atomic_int_set(const_cast<gint*> (&_frames_pending_write), 0);
396  g_atomic_int_set(const_cast<gint*> (&_num_captured_loops), 0);
397  was_recording = true;
398  }
399  }
400 
401  if (can_record && !_last_capture_sources.empty()) {
402  _last_capture_sources.clear ();
403  }
404 
405  if (nominally_recording || rec_nframes) {
406  // Pump entire port buffer into the ring buffer (TODO: split cycles?)
407  MidiBuffer& buf = sp->get_midi_buffer(nframes);
408  MidiTrack* mt = dynamic_cast<MidiTrack*>(_track);
409  MidiChannelFilter* filter = mt ? &mt->capture_filter() : NULL;
410 
411  for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
413  if (ev.time() + rec_offset > rec_nframes) {
414  break;
415  }
416 #ifndef NDEBUG
418  const uint8_t* __data = ev.buffer();
419  DEBUG_STR_DECL(a);
420  DEBUG_STR_APPEND(a, string_compose ("mididiskstream %1 capture event @ %2 + %3 sz %4 ", this, ev.time(), transport_frame, ev.size()));
421  for (size_t i=0; i < ev.size(); ++i) {
422  DEBUG_STR_APPEND(a,hex);
423  DEBUG_STR_APPEND(a,"0x");
424  DEBUG_STR_APPEND(a,(int)__data[i]);
425  DEBUG_STR_APPEND(a,' ');
426  }
427  DEBUG_STR_APPEND(a,'\n');
428  DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str());
429  }
430 #endif
431  /* Write events to the capture buffer in frames from session start,
432  but ignoring looping so event time progresses monotonically.
433  The source knows the loop length so it knows exactly where the
434  event occurs in the series of recorded loops and can implement
435  any desirable behaviour. We don't want to send event with
436  transport time here since that way the source can not
437  reconstruct their actual time; future clever MIDI looping should
438  probably be implemented in the source instead of here.
439  */
440  const framecnt_t loop_offset = _num_captured_loops * loop_length;
441  const framepos_t event_time = transport_frame + loop_offset - _accumulated_capture_offset + ev.time();
442  if (event_time < 0 || event_time < first_recordable_frame) {
443  /* Event out of range, skip */
444  continue;
445  }
446 
447  if (!filter || !filter->filter(ev.buffer(), ev.size())) {
448  _capture_buf->write(event_time, ev.type(), ev.size(), ev.buffer());
449  }
450  }
451  g_atomic_int_add(const_cast<gint*>(&_frames_pending_write), nframes);
452 
453  if (buf.size() != 0) {
454  Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK);
455 
456  if (lm.locked ()) {
457  /* Copy this data into our GUI feed buffer and tell the GUI
458  that it can read it if it likes.
459  */
461 
462  for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
463  /* This may fail if buf is larger than _gui_feed_buffer, but it's not really
464  the end of the world if it does.
465  */
466  _gui_feed_buffer.push_back ((*i).time() + transport_frame, (*i).size(), (*i).buffer());
467  }
468  }
469 
470  DataRecorded (_write_source); /* EMIT SIGNAL */
471  }
472 
473  } else {
474 
475  if (was_recording) {
476  finish_capture ();
477  }
479 
480  }
481 
482  if (rec_nframes) {
483 
484  /* data will be written to disk */
485 
486  if (rec_nframes == nframes && rec_offset == 0) {
487  playback_distance = nframes;
488  }
489 
490  adjust_capture_position = rec_nframes;
491 
492  } else if (nominally_recording) {
493 
494  /* XXXX do this for MIDI !!!
495  can't do actual capture yet - waiting for latency effects to finish before we start
496  */
497 
498  playback_distance = nframes;
499 
500  } else if (_actual_speed != 1.0f && _target_speed > 0) {
501 
503 
504  playback_distance = interpolation.distance (nframes);
505 
506  } else {
507  playback_distance = nframes;
508  }
509 
510  if (need_disk_signal) {
511  /* copy the diskstream data to all output buffers */
512 
513  MidiBuffer& mbuf (bufs.get_midi (0));
514  get_playback (mbuf, playback_distance);
515 
516  /* leave the audio count alone */
517  ChanCount cnt (DataType::MIDI, 1);
518  cnt.set (DataType::AUDIO, bufs.count().n_audio());
519  bufs.set_count (cnt);
520 
521  /* vari-speed */
522  if (_target_speed > 0 && _actual_speed != 1.0f) {
523  MidiBuffer& mbuf (bufs.get_midi (0));
524  for (MidiBuffer::iterator i = mbuf.begin(); i != mbuf.end(); ++i) {
525  MidiBuffer::TimeType *tme = i.timeptr();
526  *tme = (*tme) * nframes / playback_distance;
527  }
528  }
529  }
530 
531  return 0;
532 }
533 
536 {
537  frameoffset_t playback_distance = nframes;
538 
539  if (!record_enabled() && _actual_speed != 1.0f && _actual_speed > 0.f) {
541  playback_distance = interpolation.distance (nframes, false);
542  }
543 
544  if (_actual_speed < 0.0) {
545  return -playback_distance;
546  } else {
547  return playback_distance;
548  }
549 }
550 
551 bool
553 {
554  bool need_butler = false;
555 
556  if (!_io || !_io->active()) {
557  return false;
558  }
559 
560  if (_actual_speed < 0.0) {
561  playback_sample -= playback_distance;
562  } else {
563  playback_sample += playback_distance;
564  }
565 
566  if (adjust_capture_position != 0) {
569  }
570 
571  uint32_t frames_read = g_atomic_int_get(const_cast<gint*>(&_frames_read_from_ringbuffer));
572  uint32_t frames_written = g_atomic_int_get(const_cast<gint*>(&_frames_written_to_ringbuffer));
573 
574  /*
575  cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read <<
576  " = " << frames_written - frames_read
577  << " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl;
578  */
579 
580  /* frames_read will generally be less than frames_written, but
581  * immediately after an overwrite, we can end up having read some data
582  * before we've written any. we don't need to trip an assert() on this,
583  * but we do need to check so that the decision on whether or not we
584  * need the butler is done correctly.
585  */
586 
587  /* furthermore..
588  *
589  * Doing heavy GUI operations[1] can stall also the butler.
590  * The RT-thread meanwhile will happily continue and
591  * ‘frames_read’ (from buffer to output) will become larger
592  * than ‘frames_written’ (from disk to buffer).
593  *
594  * The disk-stream is now behind..
595  *
596  * In those cases the butler needs to be summed to refill the buffer (done now)
597  * AND we need to skip (frames_read - frames_written). ie remove old events
598  * before playback_sample from the rinbuffer.
599  *
600  * [1] one way to do so is described at #6170.
601  * For me just popping up the context-menu on a MIDI-track header
602  * of a track with a large (think beethoven :) midi-region also did the
603  * trick. The playhead stalls for 2 or 3 sec, until the context-menu shows.
604  *
605  * In both cases the root cause is that redrawing MIDI regions on the GUI is still very slow
606  * and can stall
607  */
608  if (frames_read <= frames_written) {
609  if ((frames_written - frames_read) + playback_distance < midi_readahead) {
610  need_butler = true;
611  }
612  } else {
613  need_butler = true;
614  }
615 
616 
617  return need_butler;
618 }
619 
620 void
622 {
623  /* called from audio thread, so we can use the read ptr and playback sample as we wish */
624 
625  _pending_overwrite = yn;
627 }
628 
629 int
631 {
632  /* Clear the playback buffer contents. This is safe as long as the butler
633  thread is suspended, which it should be. */
634  _playback_buf->reset ();
636 
637  g_atomic_int_set (&_frames_read_from_ringbuffer, 0);
638  g_atomic_int_set (&_frames_written_to_ringbuffer, 0);
639 
640  /* Resolve all currently active notes in the playlist. This is more
641  aggressive than it needs to be: ideally we would only resolve what is
642  absolutely necessary, but this seems difficult and/or impossible without
643  having the old data or knowing what change caused the overwrite. */
644  midi_playlist()->resolve_note_trackers (*_playback_buf, overwrite_frame);
645 
647  file_frame = overwrite_frame; // it was adjusted by ::read()
648  overwrite_queued = false;
649  _pending_overwrite = false;
650 
651  return 0;
652 }
653 
654 int
655 MidiDiskstream::seek (framepos_t frame, bool complete_refill)
656 {
658  int ret = -1;
659 
660  if (g_atomic_int_get (&_frames_read_from_ringbuffer) == 0) {
661  /* we haven't read anything since the last seek,
662  so flush all note trackers to prevent
663  wierdness
664  */
665  reset_tracker ();
666  }
667 
668  _playback_buf->reset();
669  _capture_buf->reset();
670  g_atomic_int_set(&_frames_read_from_ringbuffer, 0);
671  g_atomic_int_set(&_frames_written_to_ringbuffer, 0);
672 
673  playback_sample = frame;
674  file_frame = frame;
675 
676  if (complete_refill) {
677  while ((ret = do_refill_with_alloc ()) > 0) ;
678  } else {
679  ret = do_refill_with_alloc ();
680  }
681 
682  return ret;
683 }
684 
685 int
687 {
688  uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
689  uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
690  return ((frames_written - frames_read) < distance);
691 }
692 
693 int
695 {
696  first_recordable_frame += distance;
697  playback_sample += distance;
698 
699  return 0;
700 }
701 
703 int
705 {
706  framecnt_t this_read = 0;
707  bool reloop = false;
708  framepos_t loop_end = 0;
709  framepos_t loop_start = 0;
710  framecnt_t loop_length = 0;
711  Location* loc = 0;
712 
713  MidiTrack* mt = dynamic_cast<MidiTrack*>(_track);
714  MidiChannelFilter* filter = mt ? &mt->playback_filter() : NULL;
715 
716  if (!reversed) {
717 
718  loc = loop_location;
719  get_location_times(loc, &loop_start, &loop_end, &loop_length);
720 
721  /* if we are looping, ensure that the first frame we read is at the correct
722  position within the loop.
723  */
724 
725  if (loc && (start >= loop_end)) {
726  //cerr << "start adjusted from " << start;
727  start = loop_start + ((start - loop_start) % loop_length);
728  //cerr << "to " << start << endl;
729  }
730  // cerr << "start is " << start << " end " << start+dur << " loopstart: " << loop_start << " loopend: " << loop_end << endl;
731  }
732 
733  while (dur) {
734 
735  /* take any loop into account. we can't read past the end of the loop. */
736 
737  if (loc && (loop_end - start <= dur)) {
738  this_read = loop_end - start;
739  // cerr << "reloop true: thisread: " << this_read << " dur: " << dur << endl;
740  reloop = true;
741  } else {
742  reloop = false;
743  this_read = dur;
744  }
745 
746  if (this_read == 0) {
747  break;
748  }
749 
750  this_read = min(dur,this_read);
751 
752  if (midi_playlist()->read (*_playback_buf, start, this_read, 0, filter) != this_read) {
754  _("MidiDiskstream %1: cannot read %2 from playlist at frame %3"),
755  id(), this_read, start) << endmsg;
756  return -1;
757  }
758 
759  g_atomic_int_add (&_frames_written_to_ringbuffer, this_read);
760 
761  if (reversed) {
762 
763  // Swap note ons with note offs here. etc?
764  // Fully reversing MIDI requires look-ahead (well, behind) to find previous
765  // CC values etc. hard.
766 
767  } else {
768 
769  /* if we read to the end of the loop, go back to the beginning */
770  if (reloop) {
771  // Synthesize LoopEvent here, because the next events
772  // written will have non-monotonic timestamps.
773  start = loop_start;
774  } else {
775  start += this_read;
776  }
777  }
778 
779  dur -= this_read;
780  //offset += this_read;
781  }
782 
783  return 0;
784 }
785 
786 int
788 {
789  return do_refill();
790 }
791 
792 int
794 {
795  int ret = 0;
796  size_t write_space = _playback_buf->write_space();
798 
799  if (write_space == 0) {
800  return 0;
801  }
802 
803  if (reversed) {
804  return 0;
805  }
806 
807  /* at end: nothing to do */
808  if (file_frame == max_framepos) {
809  return 0;
810  }
811 
812  /* no space to write */
813  if (_playback_buf->write_space() == 0) {
814  return 0;
815  }
816 
817  uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
818  uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
819  if ((frames_read < frames_written) && (frames_written - frames_read) >= midi_readahead) {
820  return 0;
821  }
822 
823  framecnt_t to_read = midi_readahead - ((framecnt_t)frames_written - (framecnt_t)frames_read);
824 
825  //cout << "MDS read for midi_readahead " << to_read << " rb_contains: "
826  // << frames_written - frames_read << endl;
827 
828  to_read = min (to_read, (framecnt_t) (max_framepos - file_frame));
829  to_read = min (to_read, (framecnt_t) write_space);
830 
831  if (read (file_frame, to_read, reversed)) {
832  ret = -1;
833  }
834 
835  return ret;
836 }
837 
848 int
849 MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush)
850 {
851  framecnt_t to_write;
852  int32_t ret = 0;
853 
854  if (!_write_source) {
855  return 0;
856  }
857 
858  const framecnt_t total = g_atomic_int_get(const_cast<gint*> (&_frames_pending_write));
859 
860  if (total == 0 ||
861  _capture_buf->read_space() == 0 ||
862  (!force_flush && (total < disk_write_chunk_frames) && was_recording)) {
863  goto out;
864  }
865 
866  /* if there are 2+ chunks of disk i/o possible for
867  this track), let the caller know so that it can arrange
868  for us to be called again, ASAP.
869 
870  if we are forcing a flush, then if there is* any* extra
871  work, let the caller know.
872 
873  if we are no longer recording and there is any extra work,
874  let the caller know too.
875  */
876 
877  if (total >= 2 * disk_write_chunk_frames || ((force_flush || !was_recording) && total > disk_write_chunk_frames)) {
878  ret = 1;
879  }
880 
881  if (force_flush) {
882  /* push out everything we have, right now */
883  to_write = max_framecnt;
884  } else {
885  to_write = disk_write_chunk_frames;
886  }
887 
888  if (record_enabled() && ((total > disk_write_chunk_frames) || force_flush)) {
889  Source::Lock lm(_write_source->mutex());
890  if (_write_source->midi_write (lm, *_capture_buf, get_capture_start_frame (0), to_write) != to_write) {
891  error << string_compose(_("MidiDiskstream %1: cannot write to disk"), id()) << endmsg;
892  return -1;
893  }
894  g_atomic_int_add(const_cast<gint*> (&_frames_pending_write), -to_write);
895  }
896 
897 out:
898  return ret;
899 }
900 
901 void
902 MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen*/, bool abort_capture)
903 {
904  bool more_work = true;
905  int err = 0;
908  MidiRegion::SourceList::iterator src;
909  vector<CaptureInfo*>::iterator ci;
910 
911  finish_capture ();
912 
913  /* butler is already stopped, but there may be work to do
914  to flush remaining data to disk.
915  */
916 
917  while (more_work && !err) {
918  switch (do_flush (TransportContext, true)) {
919  case 0:
920  more_work = false;
921  break;
922  case 1:
923  break;
924  case -1:
925  error << string_compose(_("MidiDiskstream \"%1\": cannot flush captured data to disk!"), _name) << endmsg;
926  err++;
927  }
928  }
929 
930  /* XXX is there anything we can do if err != 0 ? */
932 
933  if (capture_info.empty()) {
934  goto no_capture_stuff_to_do;
935  }
936 
937  if (abort_capture) {
938 
939  if (_write_source) {
940  _write_source->mark_for_remove ();
941  _write_source->drop_references ();
942  _write_source.reset();
943  }
944 
945  /* new source set up in "out" below */
946 
947  } else {
948 
949  framecnt_t total_capture = 0;
950  for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
951  total_capture += (*ci)->frames;
952  }
953 
954  if (_write_source->length (capture_info.front()->start) != 0) {
955 
956  /* phew, we have data */
957 
958  Source::Lock source_lock(_write_source->mutex());
959 
960  /* figure out the name for this take */
961 
962  srcs.push_back (_write_source);
963 
964  _write_source->set_timeline_position (capture_info.front()->start);
965  _write_source->set_captured_for (_name);
966 
967  /* set length in beats to entire capture length */
968 
969  BeatsFramesConverter converter (_session.tempo_map(), capture_info.front()->start);
970  const Evoral::Beats total_capture_beats = converter.from (total_capture);
971  _write_source->set_length_beats (total_capture_beats);
972 
973  /* flush to disk: this step differs from the audio path,
974  where all the data is already on disk.
975  */
976 
977  _write_source->mark_midi_streaming_write_completed (source_lock, Evoral::Sequence<Evoral::Beats>::ResolveStuckNotes, total_capture_beats);
978 
979  /* we will want to be able to keep (over)writing the source
980  but we don't want it to be removable. this also differs
981  from the audio situation, where the source at this point
982  must be considered immutable. luckily, we can rely on
983  MidiSource::mark_streaming_write_completed() to have
984  already done the necessary work for that.
985  */
986 
987  string whole_file_region_name;
988  whole_file_region_name = region_name_from_path (_write_source->name(), true);
989 
990  /* Register a new region with the Session that
991  describes the entire source. Do this first
992  so that any sub-regions will obviously be
993  children of this one (later!)
994  */
995 
996  try {
997  PropertyList plist;
998 
999  plist.add (Properties::name, whole_file_region_name);
1000  plist.add (Properties::whole_file, true);
1001  plist.add (Properties::automatic, true);
1002  plist.add (Properties::start, 0);
1003  plist.add (Properties::length, total_capture);
1004  plist.add (Properties::layer, 0);
1005 
1007 
1008  region = boost::dynamic_pointer_cast<MidiRegion> (rx);
1009  region->special_set_position (capture_info.front()->start);
1010  }
1011 
1012 
1013  catch (failed_constructor& err) {
1014  error << string_compose(_("%1: could not create region for complete midi file"), _name) << endmsg;
1015  /* XXX what now? */
1016  }
1017 
1018  _last_capture_sources.insert (_last_capture_sources.end(), srcs.begin(), srcs.end());
1019 
1021  _playlist->freeze ();
1022 
1023  /* Session frame time of the initial capture in this pass, which is where the source starts */
1024  framepos_t initial_capture = 0;
1025  if (!capture_info.empty()) {
1026  initial_capture = capture_info.front()->start;
1027  }
1028 
1029  for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1030 
1031  string region_name;
1032 
1033  RegionFactory::region_name (region_name, _write_source->name(), false);
1034 
1035  DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 capture start @ %2 length %3 add new region %4\n",
1036  _name, (*ci)->start, (*ci)->frames, region_name));
1037 
1038 
1039  // cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add a region\n";
1040 
1041  try {
1042  PropertyList plist;
1043 
1044  /* start of this region is the offset between the start of its capture and the start of the whole pass */
1045  plist.add (Properties::start, (*ci)->start - initial_capture);
1046  plist.add (Properties::length, (*ci)->frames);
1047  plist.add (Properties::length_beats, converter.from((*ci)->frames));
1048  plist.add (Properties::name, region_name);
1049 
1051  region = boost::dynamic_pointer_cast<MidiRegion> (rx);
1052  }
1053 
1054  catch (failed_constructor& err) {
1055  error << _("MidiDiskstream: could not create region for captured midi!") << endmsg;
1056  continue; /* XXX is this OK? */
1057  }
1058 
1059  // cerr << "add new region, buffer position = " << buffer_position << " @ " << (*ci)->start << endl;
1060 
1062  _playlist->add_region (region, (*ci)->start);
1064  }
1065 
1066  _playlist->thaw ();
1068 
1069  } else {
1070 
1071  /* No data was recorded, so this capture will
1072  effectively be aborted; do the same as we
1073  do for an explicit abort.
1074  */
1075 
1076  if (_write_source) {
1077  _write_source->mark_for_remove ();
1078  _write_source->drop_references ();
1079  _write_source.reset();
1080  }
1081  }
1082 
1083  }
1084 
1086 
1087  for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
1088  delete *ci;
1089  }
1090 
1091  capture_info.clear ();
1092  capture_start_frame = 0;
1093 
1094  no_capture_stuff_to_do:
1095 
1096  reset_tracker ();
1097 }
1098 
1099 void
1101 {
1102  /* Here we only keep track of the number of captured loops so monotonic
1103  event times can be delivered to the write source in process(). Trying
1104  to be clever here is a world of trouble, it is better to simply record
1105  the input in a straightforward non-destructive way. In the future when
1106  we want to implement more clever MIDI looping modes it should be done in
1107  the Source and/or entirely after the capture is finished.
1108  */
1109  if (was_recording) {
1110  g_atomic_int_add(const_cast<gint*> (&_num_captured_loops), 1);
1111  }
1112 }
1113 
1114 void
1116 {
1117  was_recording = false;
1118 
1119  if (capture_captured == 0) {
1120  return;
1121  }
1122 
1123  CaptureInfo* ci = new CaptureInfo;
1124 
1125  ci->start = capture_start_frame;
1126  ci->frames = capture_captured;
1127 
1128  /* XXX theoretical race condition here. Need atomic exchange ?
1129  However, the circumstances when this is called right
1130  now (either on record-disable or transport_stopped)
1131  mean that no actual race exists. I think ...
1132  We now have a capture_info_lock, but it is only to be used
1133  to synchronize in the transport_stop and the capture info
1134  accessors, so that invalidation will not occur (both non-realtime).
1135  */
1136 
1137  // cerr << "Finish capture, add new CI, " << ci->start << '+' << ci->frames << endl;
1138 
1139  capture_info.push_back (ci);
1140  capture_captured = 0;
1141 }
1142 
1143 void
1145 {
1146  if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0) {
1147  return;
1148  }
1149 
1150  /* yes, i know that this not proof against race conditions, but its
1151  good enough. i think.
1152  */
1153 
1154  if (record_enabled() != yn) {
1155  if (yn) {
1157  } else {
1159  }
1160 
1161  RecordEnableChanged (); /* EMIT SIGNAL */
1162  }
1163 }
1164 
1165 bool
1167 {
1168  if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0) {
1169  return false;
1170  }
1171 
1172  bool const rolling = _session.transport_speed() != 0.0f;
1173 
1175 
1176  if (sp && Config->get_monitoring_model() == HardwareMonitoring) {
1177  sp->request_input_monitoring (!(_session.config.get_auto_input() && rolling));
1178  }
1179 
1180  return true;
1181 }
1182 
1183 bool
1185 {
1186 
1187  return true;
1188 }
1189 
1190 XMLNode&
1192 {
1193  XMLNode& node (Diskstream::get_state());
1194  char buf[64];
1195  LocaleGuard lg (X_("C"));
1196 
1198 
1199  XMLNode* cs_child = new XMLNode (X_("CapturingSources"));
1200  XMLNode* cs_grandchild;
1201 
1202  cs_grandchild = new XMLNode (X_("file"));
1203  cs_grandchild->add_property (X_("path"), _write_source->path());
1204  cs_child->add_child_nocopy (*cs_grandchild);
1205 
1206  /* store the location where capture will start */
1207 
1208  Location* pi;
1209 
1210  if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
1211  snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
1212  } else {
1213  snprintf (buf, sizeof (buf), "%" PRId64, _session.transport_frame());
1214  }
1215 
1216  cs_child->add_property (X_("at"), buf);
1217  node.add_child_nocopy (*cs_child);
1218  }
1219 
1220  return node;
1221 }
1222 
1223 int
1224 MidiDiskstream::set_state (const XMLNode& node, int version)
1225 {
1226  XMLNodeList nlist = node.children();
1227  XMLNodeIterator niter;
1228  XMLNode* capture_pending_node = 0;
1229  LocaleGuard lg (X_("C"));
1230 
1231  /* prevent write sources from being created */
1232 
1233  in_set_state = true;
1234 
1235  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1236  if ((*niter)->name() == X_("CapturingSources")) {
1237  capture_pending_node = *niter;
1238  }
1239  }
1240 
1241  if (Diskstream::set_state (node, version)) {
1242  return -1;
1243  }
1244 
1245  if (capture_pending_node) {
1246  use_pending_capture_data (*capture_pending_node);
1247  }
1248 
1249  in_set_state = false;
1250 
1251  return 0;
1252 }
1253 
1254 int
1256 {
1257  if (!_session.writable() || !recordable()) {
1258  return 1;
1259  }
1260 
1262  _write_source.reset();
1263 
1264  try {
1267 
1268  if (!_write_source) {
1269  throw failed_constructor();
1270  }
1271  }
1272 
1273  catch (failed_constructor &err) {
1274  error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
1275  _write_source.reset();
1276  return -1;
1277  }
1278 
1279  return 0;
1280 }
1288 std::string
1290 {
1291  string our_old_name = _write_source->name();
1292 
1293  /* this will bump the name of the current write source to the next one
1294  * (e.g. "MIDI 1-1" gets renamed to "MIDI 1-2"), thus leaving the
1295  * current write source name (e.g. "MIDI 1-1" available). See the
1296  * comments in Session::create_midi_source_by_stealing_name() about why
1297  * we do this.
1298  */
1299 
1300  try {
1301  string new_path = _session.new_midi_source_path (name());
1302 
1303  if (_write_source->rename (new_path)) {
1304  return string();
1305  }
1306  } catch (...) {
1307  return string ();
1308  }
1309 
1310  return our_old_name;
1311 }
1312 
1313 void
1314 MidiDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
1315 {
1316  if (!_session.writable() || !recordable()) {
1317  return;
1318  }
1319 
1320  if (_write_source && mark_write_complete) {
1321  Source::Lock lm(_write_source->mutex());
1322  _write_source->mark_streaming_write_completed (lm);
1323  }
1325 }
1326 
1327 void
1329 {
1330 }
1331 
1332 void
1334 {
1335 }
1336 
1337 void
1339 {
1341 
1342  if (sp) {
1343  sp->ensure_input_monitoring (yn);
1344  }
1345 }
1346 
1347 void
1349 {
1350  if (_alignment_choice != Automatic) {
1351  return;
1352  }
1353 
1354  /* XXX Not sure what, if anything we can do with MIDI
1355  as far as capture alignment etc.
1356  */
1357 
1359 }
1360 
1361 
1362 float
1364 {
1365  /* For MIDI it's not trivial to differentiate the following two cases:
1366 
1367  1. The playback buffer is empty because the system has run out of time to fill it.
1368  2. The playback buffer is empty because there is no more data on the playlist.
1369 
1370  If we use a simple buffer load computation, we will report that the MIDI diskstream
1371  cannot keep up when #2 happens, when in fact it can. Since MIDI data rates
1372  are so low compared to audio, just give a pretend answer here.
1373  */
1374 
1375  return 1;
1376 }
1377 
1378 float
1380 {
1381  /* We don't report playback buffer load, so don't report capture load either */
1382 
1383  return 1;
1384 }
1385 
1386 int
1388 {
1389  return 0;
1390 }
1391 
1392 void
1394 {
1395  _playback_buf->flush (start, end);
1396  g_atomic_int_add (&_frames_read_from_ringbuffer, end - start);
1397 }
1398 
1402 void
1404 {
1405  dst.clear();
1406 
1407  Location* loc = loop_location;
1408 
1410  "%1 MDS pre-read read %8 @ %4..%5 from %2 write to %3, LOOPED ? %6-%7\n", _name,
1412  (loc ? loc->start() : -1), (loc ? loc->end() : -1), nframes));
1413 
1414  // cerr << "================\n";
1415  // _playback_buf->dump (cerr);
1416  // cerr << "----------------\n";
1417 
1418  size_t events_read = 0;
1419 
1420  if (loc) {
1421  framepos_t effective_start;
1422 
1423  if (playback_sample >= loc->end()) {
1424  effective_start = loc->start() + ((playback_sample - loc->end()) % loc->length());
1425  } else {
1426  effective_start = playback_sample;
1427  }
1428 
1429  DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("looped, effective start adjusted to %1\n", effective_start));
1430 
1431  if (effective_start == loc->start()) {
1432  /* We need to turn off notes that may extend
1433  beyond the loop end.
1434  */
1435 
1436  _playback_buf->resolve_tracker (dst, 0);
1437  }
1438 
1439  _playback_buf->skip_to (effective_start);
1440 
1441  if (loc->end() >= effective_start && loc->end() < effective_start + nframes) {
1442  /* end of loop is within the range we are reading, so
1443  split the read in two, and lie about the location
1444  for the 2nd read
1445  */
1446  framecnt_t first, second;
1447 
1448  first = loc->end() - effective_start;
1449  second = nframes - first;
1450 
1451  DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read for eff %1 end %2: %3 and %4\n",
1452  effective_start, loc->end(), first, second));
1453 
1454  if (first) {
1455  DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #1, from %1 for %2\n",
1456  effective_start, first));
1457  events_read = _playback_buf->read (dst, effective_start, first);
1458  }
1459 
1460  if (second) {
1461  DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #2, from %1 for %2\n",
1462  loc->start(), second));
1463  events_read += _playback_buf->read (dst, loc->start(), second);
1464  }
1465 
1466  } else {
1467  DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("loop read #3, adjusted start as %1 for %2\n",
1468  effective_start, nframes));
1469  events_read = _playback_buf->read (dst, effective_start, effective_start + nframes);
1470  }
1471  } else {
1473  events_read = _playback_buf->read (dst, playback_sample, playback_sample + nframes);
1474  }
1475 
1477  "%1 MDS events read %2 range %3 .. %4 rspace %5 wspace %6 r@%7 w@%8\n",
1478  _name, events_read, playback_sample, playback_sample + nframes,
1481 
1482  g_atomic_int_add (&_frames_read_from_ringbuffer, nframes);
1483 }
1484 
1485 bool
1486 MidiDiskstream::set_name (string const & name)
1487 {
1488  if (_name == name) {
1489  return true;
1490  }
1491  Diskstream::set_name (name);
1492 
1493  /* get a new write source so that its name reflects the new diskstream name */
1495 
1496  return true;
1497 }
1498 
1499 bool
1500 MidiDiskstream::set_write_source_name (const std::string& str) {
1501  if (_write_source_name == str) {
1502  return true;
1503  }
1505  if (_write_source_name == name()) {
1506  return true;
1507  }
1509  return true;
1510 }
1511 
1514 {
1516 
1518  b->copy (_gui_feed_buffer);
1519  return b;
1520 }
1521 
1522 void
1524 {
1526 
1528 
1529  if (mp) {
1530  mp->reset_note_trackers ();
1531  }
1532 }
1533 
1534 void
1536 {
1537  _playback_buf->resolve_tracker(buffer, time);
1538 
1540 
1541  if (mp) {
1542  mp->reset_note_trackers ();
1543  }
1544 }
1545 
1546 
1549 {
1551 }
framepos_t first_recordable_frame
Definition: diskstream.h:306
void resolve_tracker(MidiBuffer &dst, framepos_t)
XMLNodeList::iterator XMLNodeIterator
Definition: xml++.h:48
framepos_t get_capture_start_frame(uint32_t n=0) const
Definition: diskstream.cc:322
ARDOUR::Session & _session
size_t size() const
Definition: midi_buffer.h:55
void calculate_record_range(Evoral::OverlapType ot, framepos_t transport_frame, framecnt_t nframes, framecnt_t &rec_nframes, framecnt_t &rec_offset)
Definition: diskstream.cc:689
static int region_name(std::string &, std::string, bool new_level=false)
framecnt_t distance(framecnt_t nframes, bool roll=true)
boost::shared_ptr< Playlist > _playlist
Definition: diskstream.h:287
MidiBuffer & get_midi(size_t i)
Definition: buffer_set.h:107
size_t get_read_ptr() const
void transport_looped(framepos_t transport_frame)
MidiDiskstream(Session &, const std::string &name, Diskstream::Flag f=Recordable)
NoteMode
Definition: types.h:204
bool get_record_enabled() const
Definition: session.h:272
Glib::Threads::Mutex::Lock Lock
Definition: source.h:54
double transport_speed() const
Definition: session.h:590
LIBARDOUR_API PBD::PropertyDescriptor< layer_t > layer
Definition: region.cc:67
bool writable() const
Definition: session.h:173
PBD::Signal0< void > RecordEnableChanged
Definition: diskstream.h:178
void set_count(const ChanCount &count)
Definition: buffer_set.h:93
virtual bool set_name(const std::string &str)
Definition: diskstream.cc:440
void disengage_record_enable()
Definition: diskstream.cc:767
virtual void set_capture_offset()
Definition: diskstream.cc:244
bool actively_recording() const
Definition: session.h:280
int use_pending_capture_data(XMLNode &node)
std::list< boost::shared_ptr< Source > > _last_capture_sources
Definition: diskstream.h:253
void special_set_position(framepos_t)
Definition: region.cc:532
int process(BufferSet &, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_diskstream)
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
bool reversed() const
Definition: diskstream.h:117
boost::shared_ptr< MidiSource > create_midi_source_for_session(std::string const &)
Definition: session.cc:4036
volatile gint _frames_pending_write
uint32_t i_am_the_modifier
Definition: diskstream.h:281
bool commit(framecnt_t nframes)
int find_and_use_playlist(const std::string &)
void add_command(Command *const cmd)
Definition: session.h:787
TempoMap & tempo_map()
Definition: session.h:596
void set_speed(double new_speed)
Definition: interpolation.h:45
LIBARDOUR_API uint64_t MidiIO
Definition: debug.cc:44
MidiRingBuffer< framepos_t > * _capture_buf
bool set_name(std::string const &)
framepos_t last_recordable_frame
Definition: diskstream.h:307
bool destructive() const
Definition: diskstream.h:109
JACK does monitoring.
Definition: types.h:381
uint32_t pframes_t
Definition: types.h:61
uint32_t n_audio() const
Definition: chan_count.h:63
tuple f
Definition: signals.py:35
void ensure_input_monitoring(bool)
Definition: port.cc:260
int use_playlist(boost::shared_ptr< Playlist >)
framepos_t end() const
Definition: location.h:72
std::string steal_write_source_name()
Definition: Beats.hpp:239
LIBARDOUR_API uint64_t MidiDiskstreamIO
Definition: debug.cc:30
LIBPBD_API Transmitter error
const XMLNodeList & children(const std::string &str=std::string()) const
Definition: xml++.cc:329
int use_new_write_source(uint32_t n=0)
uint32_t write(Time time, Evoral::EventType type, uint32_t size, const uint8_t *buf)
int set_state(const XMLNode &, int version)
LIBARDOUR_API uint64_t CaptureAlignment
Definition: debug.cc:52
void set_block_size(pframes_t)
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
bool active() const
Definition: io.h:87
SessionConfiguration config
Definition: session.h:866
AlignChoice _alignment_choice
Definition: diskstream.h:310
boost::weak_ptr< MidiPort > _source_port
RunContext
Definition: types.h:492
virtual void check_record_status(framepos_t transport_frame, bool can_record)
Definition: diskstream.cc:601
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
framepos_t TimeType
Definition: midi_buffer.h:38
static AudioEngine * instance()
Definition: audioengine.h:196
virtual bool set_write_source_name(const std::string &str)
Definition: diskstream.cc:451
MidiChannelFilter & playback_filter()
Definition: midi_track.h:122
std::string _write_source_name
Definition: diskstream.h:330
void thaw(bool from_undo=false)
Definition: playlist.cc:422
void set_record_enabled(bool yn)
uint32_t n_midi() const
Definition: chan_count.h:66
std::list< XMLNode * > XMLNodeList
Definition: xml++.h:44
PBD::Signal1< void, boost::weak_ptr< MidiSource > > DataRecorded
void flush(framepos_t start, framepos_t end)
void add_channel_to(int, int)
Definition: interpolation.h:51
void flush_playback(framepos_t, framepos_t)
Locations * locations()
Definition: session.h:382
Glib::Threads::Mutex _gui_feed_buffer_mutex
bool recordable() const
Definition: diskstream.h:115
#define _(Text)
Definition: i18n.h:11
static framecnt_t disk_write_chunk_frames
Definition: diskstream.h:276
MidiRingBuffer< framepos_t > * _playback_buf
CubicMidiInterpolation interpolation
IOChange input_change_pending
Definition: diskstream.h:317
void transport_stopped_wallclock(struct tm &, time_t, bool abort)
Location * loop_location
Definition: diskstream.h:312
void add_region(boost::shared_ptr< Region >, framepos_t position, float times=1, bool auto_partition=false)
Definition: playlist.cc:668
const ChanCount & n_ports() const
Definition: io.h:135
Glib::Threads::Mutex state_lock
Definition: diskstream.h:332
class LIBPBD_API StatefulDiffCommand
#define X_(Text)
Definition: i18n.h:13
LIBARDOUR_API PBD::PropertyDescriptor< bool > automatic
Definition: region.cc:53
int read(framepos_t &start, framecnt_t cnt, bool reversed)
int can_internal_playback_seek(framecnt_t distance)
void engage_record_enable()
Definition: diskstream.cc:761
int64_t framecnt_t
Definition: types.h:76
boost::shared_ptr< ARDOUR::IO > _io
Definition: diskstream.h:283
LIBARDOUR_API RCConfiguration * Config
Definition: globals.cc:119
void set_note_mode(NoteMode m)
void non_realtime_locate(framepos_t location)
std::vector< CaptureInfo * > capture_info
Definition: diskstream.h:278
uint32_t size() const
Definition: Event.hpp:134
enum ARDOUR::IOChange::Type type
MidiChannelFilter & capture_filter()
Definition: midi_track.h:123
size_t read(MidiBuffer &dst, framepos_t start, framepos_t end, framecnt_t offset=0, bool stop_on_overflow_in_destination=false)
static std::string bump_name(std::string old_name, Session &)
Definition: playlist.cc:2292
framepos_t transport_frame() const
Definition: session.h:551
Definition: amp.h:29
float playback_buffer_load() const
framecnt_t adjust_capture_position
Definition: diskstream.h:300
frameoffset_t calculate_playback_distance(pframes_t nframes)
static framecnt_t disk_read_chunk_frames
Definition: diskstream.h:275
boost::shared_ptr< MidiPort > midi(uint32_t n) const
Definition: io.cc:1437
std::vector< boost::shared_ptr< Source > > SourceList
Definition: region.h:91
framepos_t file_frame
Definition: diskstream.h:325
Time time() const
Definition: Event.hpp:132
std::string new_midi_source_path(const std::string &)
Definition: session.cc:3953
bool record_enabled() const
Definition: diskstream.h:106
#define DEBUG_TRACE(bits, str)
Definition: debug.h:55
int64_t framepos_t
Definition: types.h:66
MidiBuffer & get_midi_buffer(pframes_t nframes)
Definition: midi_port.cc:92
virtual int set_state(const XMLNode &, int version)
Definition: diskstream.cc:480
void filter(BufferSet &bufs)
int64_t frameoffset_t
Definition: types.h:71
bool set_write_source_name(const std::string &str)
static int loading_state_version
Definition: stateful.h:90
PBD::Property< std::string > _name
framepos_t capture_start_frame
Definition: diskstream.h:297
static void get_location_times(const Location *location, framepos_t *start, framepos_t *end, framepos_t *length)
int seek(framepos_t which_sample, bool complete_refill=false)
framepos_t _accumulated_capture_offset
void copy(const MidiBuffer &copy)
Definition: midi_buffer.cc:74
bool hidden() const
Definition: diskstream.h:114
uint8_t type() const
Definition: MIDIEvent.hpp:60
double speed() const
Definition: diskstream.h:118
XMLProperty * add_property(const char *name, const std::string &value)
LIBPBD_API uint64_t debug_bits
Definition: debug.cc:55
const char * name
void add_child_nocopy(XMLNode &)
Definition: xml++.cc:357
pframes_t get_block_size() const
Definition: session.h:393
int internal_playback_seek(framecnt_t distance)
#define DEBUG_STR_APPEND(id, s)
Definition: debug.h:58
Definition: xml++.h:95
ChanCount _n_channels
Definition: diskstream.h:285
LIBARDOUR_API PBD::PropertyDescriptor< Evoral::Beats > length_beats
Definition: midi_region.cc:57
std::string name() const
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > position
Definition: region.cc:65
const ChanCount & count() const
Definition: buffer_set.h:87
bool push_back(const Evoral::MIDIEvent< TimeType > &event)
Definition: midi_buffer.cc:136
void set(DataType t, uint32_t count)
Definition: chan_count.h:58
virtual void clear()
Definition: buffer.h:70
void reset_write_sources(bool, bool force=false)
OverlapType coverage(T sa, T ea, T sb, T eb)
Definition: Range.hpp:40
framecnt_t capture_captured
Definition: diskstream.h:298
size_t skip_to(framepos_t start)
OverlapType
Definition: Range.hpp:31
bool record_enabling_legal() const
Definition: session.cc:1275
int do_flush(RunContext context, bool force=false)
Definition: debug.h:30
framecnt_t length() const
Definition: location.h:73
void request_input_monitoring(bool)
Definition: port.cc:252
static framecnt_t midi_readahead
framepos_t playback_sample
Definition: diskstream.h:326
boost::shared_ptr< SessionPlaylists > playlists
Definition: session.h:907
framepos_t start() const
Definition: location.h:71
static const framepos_t max_framepos
Definition: types.h:78
iterator begin()
Definition: midi_buffer.h:127
const uint8_t * buffer() const
Definition: Event.hpp:135
framepos_t start() const
Definition: region.h:113
#define DEBUG_STR(id)
Definition: debug.h:57
boost::shared_ptr< SMFSource > _write_source
static const framecnt_t max_framecnt
Definition: types.h:79
std::string write_source_name() const
Definition: diskstream.h:75
#define DEBUG_STR_DECL(id)
Definition: debug.h:56
Glib::Threads::Mutex capture_info_lock
Definition: diskstream.h:279
boost::shared_ptr< MidiPlaylist > midi_playlist()
static boost::shared_ptr< Region > create(boost::shared_ptr< const Region > other, bool announce=false)
framepos_t overwrite_frame
Definition: diskstream.h:313
void get_playback(MidiBuffer &dst, framecnt_t)
virtual int use_playlist(boost::shared_ptr< Playlist >)
Definition: diskstream.cc:356
boost::shared_ptr< Playlist > playlist()
Definition: diskstream.h:127
uint32_t midi_diskstream_buffer_size() const
Definition: butler.h:66
virtual XMLNode & get_state(void)
Definition: diskstream.cc:457
void set_align_style(AlignStyle, bool force=false)
Definition: diskstream.cc:267
float capture_buffer_load() const
static boost::shared_ptr< Playlist > create(Session &, const XMLNode &, bool hidden=false, bool unused=false)
void clear_changes()
Definition: stateful.cc:184
LIBARDOUR_API bool init(bool with_vst, bool try_optimization, const char *localedir)
Definition: globals.cc:376
LIBARDOUR_API std::string region_name_from_path(std::string path, bool strip_channels, bool add_channel_suffix=false, uint32_t total=0, uint32_t this_one=0)
bool add(PropertyBase *prop)
boost::shared_ptr< MidiBuffer > get_gui_feed_buffer() const
LIBARDOUR_API PBD::PropertyDescriptor< bool > whole_file
Definition: region.cc:54
Definition: ardour.h:41
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208
void resolve_tracker(Evoral::EventSink< framepos_t > &buffer, framepos_t time)
size_t get_write_ptr() const
volatile gint _num_captured_loops
LIBARDOUR_API PBD::PropertyDescriptor< framecnt_t > length
Definition: region.cc:64
Location * auto_punch_location() const
Definition: location.cc:1370
Butler * butler()
Definition: session.h:221