#include <ardour/smf_source.h>
#include <ardour/destructive_filesource.h>
#include <ardour/send.h>
+#include <ardour/region_factory.h>
#include <ardour/midi_playlist.h>
#include <ardour/cycle_timer.h>
#include <ardour/midi_region.h>
: Diskstream(sess, name, flag)
, _playback_buf(0)
, _capture_buf(0)
- , _current_playback_buffer(0)
- , _current_capture_buffer(0)
- , _playback_wrap_buffer(0)
- , _capture_wrap_buffer(0)
+ //, _current_playback_buffer(0)
+ //, _current_capture_buffer(0)
+ //, _playback_wrap_buffer(0)
+ //, _capture_wrap_buffer(0)
, _source_port(0)
- , _write_source(0)
, _capture_transition_buf(0)
+ , _last_flush_frame(0)
{
/* prevent any write sources from being created */
in_set_state = false;
assert(!destructive());
- DiskstreamCreated (this); /* EMIT SIGNAL */
}
MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
: Diskstream(sess, node)
, _playback_buf(0)
, _capture_buf(0)
- , _current_playback_buffer(0)
- , _current_capture_buffer(0)
- , _playback_wrap_buffer(0)
- , _capture_wrap_buffer(0)
+ //, _current_playback_buffer(0)
+ //, _current_capture_buffer(0)
+ //, _playback_wrap_buffer(0)
+ //, _capture_wrap_buffer(0)
, _source_port(0)
- , _write_source(0)
, _capture_transition_buf(0)
+ , _last_flush_frame(0)
{
in_set_state = true;
init (Recordable);
if (destructive()) {
use_destructive_playlist ();
}
-
- DiskstreamCreated (this); /* EMIT SIGNAL */
}
void
set_block_size (_session.get_block_size());
allocate_temporary_buffers ();
- _playback_wrap_buffer = new RawMidi[wrap_buffer_size];
- _capture_wrap_buffer = new RawMidi[wrap_buffer_size];
- _playback_buf = new RingBufferNPT<RawMidi> (_session.diskstream_buffer_size());
- _capture_buf = new RingBufferNPT<RawMidi> (_session.diskstream_buffer_size());
+ //_playback_wrap_buffer = new RawMidi[wrap_buffer_size];
+ //_capture_wrap_buffer = new RawMidi[wrap_buffer_size];
+ _playback_buf = new MidiRingBuffer (_session.diskstream_buffer_size());
+ _capture_buf = new MidiRingBuffer (_session.diskstream_buffer_size());
_capture_transition_buf = new RingBufferNPT<CaptureTransition> (128);
_n_channels = ChanCount(DataType::MIDI, 1);
else {
seek (_session.transport_frame());
}
+
+ _last_flush_frame = _session.transport_frame();
}
void
if (_alignment_style == ExistingMaterial) {
- if (!_session.get_punch_in()) {
+ if (!Config->get_punch_in()) {
/* manual punch in happens at the correct transport frame
because the user hit a button. but to get alignment correct
} else {
- if (_session.get_punch_in()) {
+ if (Config->get_punch_in()) {
first_recordable_frame += _roll_delay;
} else {
capture_start_frame -= _roll_delay;
bool nominally_recording;
bool re = record_enabled ();
bool collect_playback = false;
-
- _current_capture_buffer = 0;
- _current_playback_buffer = 0;
+
+ /*_current_capture_buffer = 0;
+ _current_playback_buffer = 0;*/
/* if we've already processed the frames corresponding to this call,
just return. this allows multiple routes that are taking input
this stuff only happen once. more commonly, it allows both
the AudioTrack that is using this AudioDiskstream *and* the Session
to call process() without problems.
- */
+ */
if (_processed) {
return 0;
/* This lock is held until the end of AudioDiskstream::commit, so these two functions
must always be called as a pair. The only exception is if this function
returns a non-zero value, in which case, ::commit should not be called.
- */
+ */
// If we can't take the state lock return.
if (!state_lock.trylock()) {
return 1;
}
-
+
adjust_capture_position = 0;
- if (nominally_recording || (_session.get_record_enabled() && _session.get_punch_in())) {
+ if (nominally_recording || (_session.get_record_enabled() && Config->get_punch_in())) {
OverlapType ot;
-
+
ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
switch (ot) {
- case OverlapNone:
- rec_nframes = 0;
- break;
-
- case OverlapInternal:
- /* ---------- recrange
- |---| transrange
- */
- rec_nframes = nframes;
- rec_offset = 0;
- break;
-
- case OverlapStart:
- /* |--------| recrange
- -----| transrange
- */
- rec_nframes = transport_frame + nframes - first_recordable_frame;
- if (rec_nframes) {
+ case OverlapNone:
+ rec_nframes = 0;
+ break;
+
+ case OverlapInternal:
+ /* ---------- recrange
+ |---| transrange
+ */
+ rec_nframes = nframes;
+ rec_offset = 0;
+ break;
+
+ case OverlapStart:
+ /* |--------| recrange
+ -----| transrange
+ */
+ rec_nframes = transport_frame + nframes - first_recordable_frame;
+ if (rec_nframes) {
+ rec_offset = first_recordable_frame - transport_frame;
+ }
+ break;
+
+ case OverlapEnd:
+ /* |--------| recrange
+ |-------- transrange
+ */
+ rec_nframes = last_recordable_frame - transport_frame;
+ rec_offset = 0;
+ break;
+
+ case OverlapExternal:
+ /* |--------| recrange
+ -------------- transrange
+ */
+ rec_nframes = last_recordable_frame - last_recordable_frame;
rec_offset = first_recordable_frame - transport_frame;
- }
- break;
-
- case OverlapEnd:
- /* |--------| recrange
- |-------- transrange
- */
- rec_nframes = last_recordable_frame - transport_frame;
- rec_offset = 0;
- break;
-
- case OverlapExternal:
- /* |--------| recrange
- -------------- transrange
- */
- rec_nframes = last_recordable_frame - last_recordable_frame;
- rec_offset = first_recordable_frame - transport_frame;
- break;
+ break;
}
if (rec_nframes && !was_recording) {
}
if (nominally_recording || rec_nframes) {
- _capture_buf->get_write_vector (&_capture_vector);
-
- if (rec_nframes <= _capture_vector.len[0]) {
-
- _current_capture_buffer = _capture_vector.buf[0];
- /* note: grab the entire port buffer, but only copy what we were supposed to for recording, and use
- rec_offset
- */
+ assert(_source_port);
- // FIXME: midi buffer size?
+ // Pump entire port buffer into the ring buffer (FIXME!)
+ _capture_buf->write(_source_port->get_midi_buffer(), transport_frame);
- // FIXME: reading from a MIDI port is different, can't just memcpy
- //memcpy (_current_capture_buffer, _io->input(0)->get_buffer (rec_nframes) + offset + rec_offset, sizeof (RawMidi) * rec_nframes);
- assert(_source_port);
- for (size_t i=0; i < _source_port->size(); ++i) {
- cerr << "DISKSTREAM GOT EVENT " << i << "!!\n";
- }
-
- //if (_source_port->size() == 0)
- // cerr << "No events :/ (1)\n";
+ // FIXME: hackitty hack, don't come back
+ //_write_source->ViewDataRangeReady (_write_source->length(), rec_nframes); /* EMIT SIGNAL */
+ /*
+ for (size_t i=0; i < _source_port->size(); ++i) {
+ cerr << "DISKSTREAM GOT EVENT(1) " << i << "!!\n";
+ }
-
- } else {
-
- jack_nframes_t total = _capture_vector.len[0] + _capture_vector.len[1];
-
- if (rec_nframes > total) {
- cerr << "DiskOverrun\n";
- //DiskOverrun (); // FIXME
- goto out;
- }
-
- // FIXME (see above)
- //RawMidi* buf = _io->input (0)->get_buffer (nframes) + offset;
- assert(_source_port);
- for (size_t i=0; i < _source_port->size(); ++i) {
- cerr << "DISKSTREAM GOT EVENT " << i << "!!\n";
- }
- //if (_source_port->size() == 0)
- // cerr << "No events :/ (2)\n";
- RawMidi* buf = NULL; // FIXME FIXME FIXME (make it compile)
- assert(false);
- jack_nframes_t first = _capture_vector.len[0];
-
- memcpy (_capture_wrap_buffer, buf, sizeof (RawMidi) * first);
- memcpy (_capture_vector.buf[0], buf, sizeof (RawMidi) * first);
- memcpy (_capture_wrap_buffer+first, buf + first, sizeof (RawMidi) * (rec_nframes - first));
- memcpy (_capture_vector.buf[1], buf + first, sizeof (RawMidi) * (rec_nframes - first));
-
- _current_capture_buffer = _capture_wrap_buffer;
- }
+ if (_source_port->size() == 0)
+ cerr << "No events :/ (1)\n";
+ */
} else {
if (was_recording) {
}
}
-
+
if (rec_nframes) {
-
- // FIXME: filthy hack to fool the GUI into thinking we're doing something
- if (_write_source)
- _write_source->ViewDataRangeReady (transport_frame, rec_nframes); /* EMIT SIGNAL */
+ /* XXX XXX XXX XXX XXX XXX XXX XXX */
/* data will be written to disk */
- if (rec_nframes == nframes && rec_offset == 0) {
-
- _current_playback_buffer = _current_capture_buffer;
- playback_distance = nframes;
-
- } else {
-
-
- /* we can't use the capture buffer as the playback buffer, because
- we recorded only a part of the current process' cycle data
- for capture.
- */
-
- collect_playback = true;
- }
-
adjust_capture_position = rec_nframes;
} else if (nominally_recording) {
/* can't do actual capture yet - waiting for latency effects to finish before we start*/
- _current_playback_buffer = _current_capture_buffer;
+ // Ummm.. well, I suppose we'll just hang out for a bit?
playback_distance = nframes;
} else {
necessary_samples = nframes;
}
-
- _playback_buf->get_read_vector (&_playback_vector);
-
- if (necessary_samples <= _playback_vector.len[0]) {
- _current_playback_buffer = _playback_vector.buf[0];
-
- } else {
- jack_nframes_t total = _playback_vector.len[0] + _playback_vector.len[1];
-
- if (necessary_samples > total) {
- //cerr << "DiskUnderrun\n";
- //DiskUnderrun (); // FIXME
- //goto out;
-
- } else {
-
- memcpy (_playback_wrap_buffer, _playback_vector.buf[0],
- _playback_vector.len[0] * sizeof (RawMidi));
- memcpy (_playback_wrap_buffer + _playback_vector.len[0], _playback_vector.buf[1],
- (necessary_samples - _playback_vector.len[0]) * sizeof (RawMidi));
-
- _current_playback_buffer = _playback_wrap_buffer;
- }
- }
-
-#if 0
- if (rec_nframes == 0 && _actual_speed != 1.0f && _actual_speed != -1.0f) {
-
- uint64_t phase = last_phase;
- jack_nframes_t i = 0;
-
- // Linearly interpolate into the alt buffer
- // using 40.24 fixp maths (swh)
-
- for (c = channels.begin(); c != channels.end(); ++c) {
-
- float fr;
- ChannelInfo& chan (*c);
-
- i = 0;
- phase = last_phase;
-
- for (jack_nframes_t outsample = 0; outsample < nframes; ++outsample) {
- i = phase >> 24;
- fr = (phase & 0xFFFFFF) / 16777216.0f;
- chan.speed_buffer[outsample] =
- chan._current_playback_buffer[i] * (1.0f - fr) +
- chan._current_playback_buffer[i+1] * fr;
- phase += phi;
- }
-
- chan._current_playback_buffer = chan.speed_buffer;
- }
-
- playback_distance = i + 1;
- last_phase = (phase & 0xFFFFFF);
-
- } else {
- playback_distance = nframes;
- }
-#endif
-
- playback_distance = nframes;
+ // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
+ // Write into playback buffer here, and whatnot
}
ret = 0;
- out:
_processed = true;
if (ret) {
/* we're exiting with failure, so ::commit will not
be called. unlock the state lock.
- */
-
+ */
+
state_lock.unlock();
}
playback_sample += playback_distance;
}
- _playback_buf->increment_read_ptr (playback_distance);
-
- if (adjust_capture_position) {
- _capture_buf->increment_write_ptr (adjust_capture_position);
- }
-
+ /* XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX */
+
+ /*
+ _playback_buf->increment_read_ptr (playback_distance);
+
+ if (adjust_capture_position) {
+ _capture_buf->increment_write_ptr (adjust_capture_position);
+ }
+*/
if (adjust_capture_position != 0) {
capture_captured += adjust_capture_position;
adjust_capture_position = 0;
}
-
+
if (_slaved) {
- need_butler = _playback_buf->write_space() >= _playback_buf->bufsize() / 2;
+ need_butler = _playback_buf->write_space() >= _playback_buf->capacity() / 2;
} else {
need_butler = _playback_buf->write_space() >= disk_io_chunk_frames
|| _capture_buf->read_space() >= disk_io_chunk_frames;
}
-
+
state_lock.unlock();
_processed = false;
MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill)
{
Glib::Mutex::Lock lm (state_lock);
- return 0;
+ int ret = -1;
+
+ _playback_buf->reset();
+ _capture_buf->reset();
+
+ playback_sample = frame;
+ file_frame = frame;
+ _last_flush_frame = frame;
+
+ if (complete_refill) {
+ while ((ret = do_refill_with_alloc ()) > 0) ;
+ } else {
+ ret = do_refill_with_alloc ();
+ }
+
+ return ret;
}
int
MidiDiskstream::can_internal_playback_seek (jack_nframes_t distance)
{
- return 0;
+ if (_playback_buf->read_space() < distance) {
+ return false;
+ } else {
+ return true;
+ }
}
int
MidiDiskstream::internal_playback_seek (jack_nframes_t distance)
{
+ first_recordable_frame += distance;
+ playback_sample += distance;
+
return 0;
}
+/** @a start is set to the new frame position (TIME) read up to */
int
-MidiDiskstream::read (RawMidi* buf, jack_nframes_t& start, jack_nframes_t cnt, bool reversed)
-{
+MidiDiskstream::read (jack_nframes_t& start, jack_nframes_t dur, bool reversed)
+{
+ jack_nframes_t this_read = 0;
+ bool reloop = false;
+ jack_nframes_t loop_end = 0;
+ jack_nframes_t loop_start = 0;
+ jack_nframes_t loop_length = 0;
+ Location *loc = 0;
+
+ if (!reversed) {
+ /* Make the use of a Location atomic for this read operation.
+
+ Note: Locations don't get deleted, so all we care about
+ when I say "atomic" is that we are always pointing to
+ the same one and using a start/length values obtained
+ just once.
+ */
+
+ if ((loc = loop_location) != 0) {
+ loop_start = loc->start();
+ loop_end = loc->end();
+ loop_length = loop_end - loop_start;
+ }
+
+ /* if we are looping, ensure that the first frame we read is at the correct
+ position within the loop.
+ */
+
+ if (loc && start >= loop_end) {
+ //cerr << "start adjusted from " << start;
+ start = loop_start + ((start - loop_start) % loop_length);
+ //cerr << "to " << start << endl;
+ }
+ //cerr << "start is " << start << " loopstart: " << loop_start << " loopend: " << loop_end << endl;
+ }
+
+ while (dur) {
+
+ /* take any loop into account. we can't read past the end of the loop. */
+
+ if (loc && (loop_end - start < dur)) {
+ this_read = loop_end - start;
+ //cerr << "reloop true: thisread: " << this_read << " dur: " << dur << endl;
+ reloop = true;
+ } else {
+ reloop = false;
+ this_read = dur;
+ }
+
+ if (this_read == 0) {
+ break;
+ }
+
+ this_read = min(dur,this_read);
+
+ if (midi_playlist()->read (*_playback_buf, start, this_read) != this_read) {
+ error << string_compose(_("MidiDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read,
+ start) << endmsg;
+ return -1;
+ }
+
+ _read_data_count = _playlist->read_data_count();
+
+ if (reversed) {
+
+ cerr << "Reversed MIDI.. that's just crazy talk." << endl;
+ // Swap note ons with note offs here
+
+ } else {
+
+ /* if we read to the end of the loop, go back to the beginning */
+
+ if (reloop) {
+ start = loop_start;
+ } else {
+ start += this_read;
+ }
+ }
+
+ dur -= this_read;
+ }
+
return 0;
}
int
MidiDiskstream::do_refill ()
{
- // yeah, the data's ready. promise.
- return 0;
+ int32_t ret = 0;
+ size_t write_space = _playback_buf->write_space();
+
+ bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f;
+
+ if (write_space == 0) {
+ return 0;
+ }
+
+ /* if there are 2+ chunks of disk i/o possible for
+ this track, let the caller know so that it can arrange
+ for us to be called again, ASAP.
+ */
+
+ // FIXME: using disk_io_chunk_frames as an event count, not good
+ if (_playback_buf->write_space() >= (_slaved?3:2) * disk_io_chunk_frames) {
+ ret = 1;
+ }
+
+ /* if we're running close to normal speed and there isn't enough
+ space to do disk_io_chunk_frames of I/O, then don't bother.
+
+ at higher speeds, just do it because the sync between butler
+ and audio thread may not be good enough.
+ */
+
+ if ((write_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) {
+ cerr << "No refill 1\n";
+ return 0;
+ }
+
+ /* when slaved, don't try to get too close to the read pointer. this
+ leaves space for the buffer reversal to have something useful to
+ work with.
+ */
+
+ if (_slaved && write_space < (_playback_buf->capacity() / 2)) {
+ cerr << "No refill 2\n";
+ return 0;
+ }
+
+ if (reversed) {
+ cerr << "No refill 3 (reverse)\n";
+ return 0;
+ }
+
+ if (file_frame == max_frames) {
+ //cerr << "No refill 4 (EOF)\n";
+
+ /* at end: nothing to do */
+
+ return 0;
+ }
+
+#if 0
+ // or this
+ if (file_frame > max_frames - total_space) {
+
+ /* to close to the end: read what we can, and zero fill the rest */
+
+ zero_fill = total_space - (max_frames - file_frame);
+ total_space = max_frames - file_frame;
+
+ } else {
+ zero_fill = 0;
+ }
+#endif
+
+ // At this point we:
+ assert(_playback_buf->write_space() > 0); // ... have something to write to, and
+ assert(file_frame <= max_frames); // ... something to write
+
+ // So (read it, then) write it:
+
+ jack_nframes_t file_frame_tmp = file_frame;
+ jack_nframes_t to_read = min(disk_io_chunk_frames, (max_frames - file_frame));
+
+ // FIXME: read count?
+ if (read (file_frame_tmp, to_read, reversed)) {
+ ret = -1;
+ goto out;
+ }
+
+ file_frame = file_frame_tmp;
+
+out:
+
+ return ret;
}
/** Flush pending data to disk.
int
MidiDiskstream::do_flush (Session::RunContext context, bool force_flush)
{
- /* hey, so did you write that data? */
+ uint32_t to_write;
+ int32_t ret = 0;
+ // FIXME: I'd be lying if I said I knew what this thing was
+ //RingBufferNPT<CaptureTransition>::rw_vector transvec;
+ jack_nframes_t total;
- // oh yeah, you bet. wrote it good. honest.
-
+ _write_data_count = 0;
+
+ if (_last_flush_frame > _session.transport_frame()) {
+ _last_flush_frame = _session.transport_frame();
+ }
+
+ total = _session.transport_frame() - _last_flush_frame;
+
+
+ // FIXME: put this condition back in! (removed for testing)
+ if (total == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
+ //cerr << "MDS - no flush 1\n";
+ goto out;
+ }
+
+ /* if there are 2+ chunks of disk i/o possible for
+ this track, let the caller know so that it can arrange
+ for us to be called again, ASAP.
+
+ if we are forcing a flush, then if there is* any* extra
+ work, let the caller know.
+
+ if we are no longer recording and there is any extra work,
+ let the caller know too.
+ */
+
+ if (total >= 2 * disk_io_chunk_frames || ((force_flush || !was_recording) && total > disk_io_chunk_frames)) {
+ ret = 1;
+ }
+
+ //to_write = min (disk_io_chunk_frames, (jack_nframes_t) vector.len[0]);
+ to_write = disk_io_chunk_frames;
+
+ assert(!destructive());
+
+ if ((!_write_source) || _write_source->write (*_capture_buf, to_write) != to_write) {
+ //cerr << "MDS - no flush 2\n";
+ error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
+ return -1;
+ } else {
+ _last_flush_frame = _session.transport_frame();
+ //cerr << "MDS - flushed\n";
+ }
+
+ //(*chan).curr_capture_cnt += to_write;
+
+out:
+ //return ret;
return 0;
}
uint32_t buffer_position;
bool more_work = true;
int err = 0;
- MidiRegion* region = 0;
+ boost::shared_ptr<MidiRegion> region;
jack_nframes_t total_capture;
MidiRegion::SourceList srcs;
MidiRegion::SourceList::iterator src;
if (abort_capture) {
- list<Source*>* deletion_list = new list<Source*>;
-
if (_write_source) {
- _write_source->mark_for_remove ();
- _write_source->release ();
-
- deletion_list->push_back (_write_source);
- _write_source = 0;
+ _write_source->mark_for_remove ();
+ _write_source->drop_references ();
+ _write_source.reset();
}
/* new source set up in "out" below */
- if (!deletion_list->empty()) {
- DeleteSources (deletion_list);
- } else {
- delete deletion_list;
- }
-
} else {
assert(_write_source);
/* figure out the name for this take */
- SMFSource* s = _write_source;
+ boost::shared_ptr<SMFSource> s = _write_source;
if (s) {
*/
try {
assert(_write_source);
- region = new MidiRegion (srcs, _write_source->last_capture_start_frame(), total_capture,
- region_name_from_path (_write_source->name()),
- 0, Region::Flag (Region::DefaultFlags|Region::Automatic|Region::WholeFile));
+
+ boost::shared_ptr<Region> rx (RegionFactory::create (srcs, _write_source->last_capture_start_frame(), total_capture,
+ region_name_from_path (_write_source->name()),
+ 0, Region::Flag (Region::DefaultFlags|Region::Automatic|Region::WholeFile)));
+ region = boost::dynamic_pointer_cast<MidiRegion> (rx);
region->special_set_position (capture_info.front()->start);
}
// cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add a region\n";
try {
- region = new MidiRegion (srcs, buffer_position, (*ci)->frames, region_name);
+ boost::shared_ptr<Region> rx (RegionFactory::create (srcs, buffer_position, (*ci)->frames, region_name));
+ region = boost::dynamic_pointer_cast<MidiRegion> (rx);
}
catch (failed_constructor& err) {
- error << _("MidiDiskstream: could not create region for captured audio!") << endmsg;
+ error << _("MidiDiskstream: could not create region for captured midi!") << endmsg;
continue; /* XXX is this OK? */
}
// cerr << "add new region, buffer position = " << buffer_position << " @ " << (*ci)->start << endl;
i_am_the_modifier++;
- _playlist->add_region (*region, (*ci)->start);
+ _playlist->add_region (region, (*ci)->start);
i_am_the_modifier--;
buffer_position += (*ci)->frames;
_playlist->thaw ();
XMLNode &after = _playlist->get_state();
- _session.add_command (new MementoCommand<Playlist>(*_playlist, before, after));
+ _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after));
mark_write_completed = true;
CaptureInfo* ci = new CaptureInfo;
- ci->start = capture_start_frame;
+ ci->start = capture_start_frame;
ci->frames = capture_captured;
/* XXX theoretical race condition here. Need atomic exchange ?
g_atomic_int_set (&_record_enabled, 1);
- if (Config->get_use_hardware_monitoring() && _source_port) {
- _source_port->request_monitor_input (!(_session.get_auto_input() && rolling));
+ if (_source_port && Config->get_monitoring_model() == HardwareMonitoring) {
+ _source_port->request_monitor_input (!(Config->get_auto_input() && rolling));
}
RecordEnableChanged (); /* EMIT SIGNAL */
MidiDiskstream::disengage_record_enable ()
{
g_atomic_int_set (&_record_enabled, 0);
- if (Config->get_use_hardware_monitoring()) {
+ if (_source_port && Config->get_monitoring_model() == HardwareMonitoring) {
if (_source_port) {
_source_port->request_monitor_input (false);
}
node->add_property ("speed", buf);
node->add_property("name", _name);
- id().print(buf);
+ id().print(buf, sizeof(buf));
node->add_property("id", buf);
if (_write_source && _session.get_record_enabled()) {
Location* pi;
- if (_session.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
+ if (Config->get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
snprintf (buf, sizeof (buf), "%" PRIu32, pi->start());
} else {
snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
if (SMFSource::is_empty (_write_source->path())) {
_write_source->mark_for_remove ();
- _write_source->release();
- delete _write_source;
+ _write_source.reset();
} else {
- _write_source->release();
- _write_source = 0;
+ _write_source.reset();
}
}
try {
- _write_source = dynamic_cast<SMFSource*>(_session.create_midi_source_for_session (*this));
+ _write_source = boost::dynamic_pointer_cast<SMFSource>(_session.create_midi_source_for_session (*this));
if (!_write_source) {
throw failed_constructor();
}
catch (failed_constructor &err) {
error << string_compose (_("%1:%2 new capture file not initialized correctly"), _name, n) << endmsg;
- _write_source = 0;
+ _write_source.reset();
return -1;
}
- _write_source->use ();
_write_source->set_allow_remove_if_empty (true);
return 0;
if (_write_source && mark_write_complete) {
_write_source->mark_streaming_write_completed ();
}
- use_new_write_source ();
- assert(_write_source);
+
+ if (!_write_source) {
+ use_new_write_source ();
+ }
}
int
MidiDiskstream::playback_buffer_load () const
{
return (float) ((double) _playback_buf->read_space()/
- (double) _playback_buf->bufsize());
+ (double) _playback_buf->capacity());
}
float
MidiDiskstream::capture_buffer_load () const
{
return (float) ((double) _capture_buf->write_space()/
- (double) _capture_buf->bufsize());
+ (double) _capture_buf->capacity());
}
{
return 0;
}
+
+/** Writes playback events in the given range to dst, translating time stamps
+ * so that an event at start has time = 0
+ */
+void
+MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end)
+{
+ dst.clear();
+ assert(dst.size() == 0);
+
+ // I think this happens with reverse varispeed? maybe?
+ if (end <= start) {
+ return;
+ }
+
+/*
+ cerr << "MIDI Diskstream pretending to read" << endl;
+
+ MidiEvent ev;
+ RawMidi data[4];
+
+ const char note = rand()%30 + 30;
+
+ ev.buffer = data;
+ ev.time = 0;
+ ev.size = 3;
+
+ data[0] = 0x90;
+ data[1] = note;
+ data[2] = 120;
+
+ dst.push_back(ev);
+
+ ev.buffer = data;
+ ev.time = (end - start) / 2;
+ ev.size = 3;
+
+ data[0] = 0x80;
+ data[1] = note;
+ data[2] = 64;
+*/
+ _playback_buf->read(dst, start, end);
+
+ // Translate time stamps to be relative to the start of this cycle
+ for (size_t i=0; i < dst.size(); ++i) {
+ assert(dst[i].time >= start);
+ assert(dst[i].time <= end);
+ //cerr << "Translating event stamp " << dst[i].time << " to ";
+ dst[i].time -= start;
+ //cerr << dst[i].time << endl;
+
+ }
+}