#include <sys/mman.h>
#include "pbd/error.h"
-#include <glibmm/thread.h>
#include "pbd/xml++.h"
#include "pbd/memento_command.h"
#include "pbd/enumwriter.h"
#include "ardour/send.h"
#include "ardour/session.h"
#include "ardour/source_factory.h"
+#include "ardour/track.h"
#include "ardour/utils.h"
#include "ardour/session_playlists.h"
#include "ardour/route.h"
}
int
-AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler)
+AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool& need_butler)
{
uint32_t n;
boost::shared_ptr<ChannelList> c = channels.reader();
framecnt_t rec_offset = 0;
framecnt_t rec_nframes = 0;
bool collect_playback = false;
+ bool can_record = _session.actively_recording ();
playback_distance = 0;
(*chan)->current_playback_buffer = 0;
}
- // Safeguard against situations where process() goes haywire when autopunching
+ // Safeguard against situations where process() goes haywire when autopunching
// and last_recordable_frame < first_recordable_frame
if (last_recordable_frame < first_recordable_frame) {
OverlapType ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
calculate_record_range (ot, transport_frame, nframes, rec_nframes, rec_offset);
-
+
if (rec_nframes && !was_recording) {
capture_captured = 0;
was_recording = true;
AudioPort* const ap = _io->audio (n);
assert(ap);
assert(rec_nframes <= (framecnt_t) ap->get_audio_buffer(nframes).capacity());
- memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (nframes).data(rec_offset), sizeof (Sample) * rec_nframes);
+ Sample *buf = ap->get_audio_buffer (nframes).data (rec_offset);
+ memcpy (chaninfo->current_capture_buffer, buf, sizeof (Sample) * rec_nframes);
} else {
AudioPort* const ap = _io->audio (n);
assert(ap);
- Sample* buf = ap->get_audio_buffer(nframes).data();
+ Sample* buf = ap->get_audio_buffer(nframes).data (rec_offset);
framecnt_t first = chaninfo->capture_vector.len[0];
memcpy (chaninfo->capture_wrap_buffer, buf, sizeof (Sample) * first);
} else {
if (was_recording) {
- finish_capture (rec_monitors_input, c);
+ finish_capture (c);
}
}
collect_playback = true;
}
- if (collect_playback) {
-
+ if ((_track->monitoring_state () & MonitoringDisk) || collect_playback) {
+
/* we're doing playback */
framecnt_t necessary_samples;
_speed = _target_speed;
- }
+ }
ret = 0;
capture_captured += adjust_capture_position;
adjust_capture_position = 0;
}
-
+
if (c->empty()) {
return false;
}
-
+
if (_slaved) {
if (_io && _io->active()) {
need_butler = c->front()->playback_buf->write_space() >= c->front()->playback_buf->bufsize() / 2;
_pending_overwrite = false;
return 0;
}
-
+
Sample* mixdown_buffer;
float* gain_buffer;
int ret = -1;
if (read ((*chan)->playback_buf->buffer() + overwrite_offset, mixdown_buffer, gain_buffer, start, to_read, *chan, n, reversed)) {
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
- _id, size, playback_sample) << endmsg;
+ id(), size, playback_sample) << endmsg;
goto out;
}
if (read ((*chan)->playback_buf->buffer(), mixdown_buffer, gain_buffer,
start, cnt, *chan, n, reversed)) {
error << string_compose(_("AudioDiskstream %1: when refilling, cannot read %2 from playlist at frame %3"),
- _id, size, playback_sample) << endmsg;
+ id(), size, playback_sample) << endmsg;
goto out;
}
}
}
int
-AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
+AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
framepos_t& start, framecnt_t cnt,
ChannelInfo* /*channel_info*/, int channel, bool reversed)
{
if (reversed) {
start -= cnt;
}
-
+
while (cnt) {
/* take any loop into account. we can't read past the end of the loop. */
this_read = min(cnt,this_read);
if (audio_playlist()->read (buf+offset, mixdown_buffer, gain_buffer, start, this_read, channel) != this_read) {
- error << string_compose(_("AudioDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read,
+ error << string_compose(_("AudioDiskstream %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) {
swap_by_ptr (buf, buf + this_read - 1);
at higher speeds, just do it because the sync between butler
and audio thread may not be good enough.
+
+ Note: it is a design assumption that disk_io_chunk_frames is smaller
+ than the playback buffer size, so this check should never trip when
+ the playback buffer is empty.
*/
if ((total_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) {
file_frame = file_frame_tmp;
assert (file_frame >= 0);
-
+
out:
return ret;
RingBufferNPT<CaptureTransition>::rw_vector transvec;
framecnt_t total;
- _write_data_count = 0;
-
transvec.buf[0] = 0;
transvec.buf[1] = 0;
vector.buf[0] = 0;
if (destructive()) {
(*chan)->capture_transition_buf->get_read_vector(&transvec);
size_t transcount = transvec.len[0] + transvec.len[1];
- bool have_start = false;
size_t ti;
for (ti=0; ti < transcount; ++ti) {
(*chan)->write_source->mark_capture_start (captrans.capture_val);
(*chan)->curr_capture_cnt = 0;
- have_start = true;
- }
- else if (captrans.type == CaptureEnd) {
+ } else if (captrans.type == CaptureEnd) {
// capture end, the capture_val represents total frames in capture
}
if ((!(*chan)->write_source) || (*chan)->write_source->write (vector.buf[0], to_write) != to_write) {
- error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
+ error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
return -1;
}
to_write = min ((framecnt_t)(disk_io_chunk_frames - to_write), (framecnt_t) vector.len[1]);
if ((*chan)->write_source->write (vector.buf[1], to_write) != to_write) {
- error << string_compose(_("AudioDiskstream %1: cannot write to disk"), _id) << endmsg;
+ error << string_compose(_("AudioDiskstream %1: cannot write to disk"), id()) << endmsg;
return -1;
}
- _write_data_count += (*chan)->write_source->write_data_count();
-
(*chan)->capture_buf->increment_read_ptr (to_write);
(*chan)->curr_capture_cnt += to_write;
}
uint32_t n = 0;
bool mark_write_completed = false;
- finish_capture (true, c);
+ finish_capture (c);
/* butler is already stopped, but there may be work to do
to flush remaining data to disk.
string region_name;
RegionFactory::region_name (region_name, whole_file_region_name, false);
-
+
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1 capture start @ %2 length %3 add new region %4\n",
_name, (*ci)->start, (*ci)->frames, region_name));
try {
PropertyList plist;
-
+
plist.add (Properties::start, buffer_position);
plist.add (Properties::length, (*ci)->frames);
plist.add (Properties::name, region_name);
-
+
boost::shared_ptr<Region> rx (RegionFactory::create (srcs, plist));
region = boost::dynamic_pointer_cast<AudioRegion> (rx);
}
region->set_layer (_playlist->top_layer() + 1);
region->set_pending_explicit_relayer (true);
}
-
+
_playlist->add_region (region, (*ci)->start, 1, non_layered());
i_am_the_modifier--;
}
}
- finish_capture (true, c);
+ finish_capture (c);
// the next region will start recording via the normal mechanism
// we'll set the start position to the current transport pos
}
void
-AudioDiskstream::finish_capture (bool /*rec_monitors_input*/, boost::shared_ptr<ChannelList> c)
+AudioDiskstream::finish_capture (boost::shared_ptr<ChannelList> c)
{
was_recording = false;
first_recordable_frame = max_framepos;
/* do not remove destructive files even if they are empty */
chan->write_source->set_allow_remove_if_empty (!destructive());
-
+
return 0;
}
-list<boost::shared_ptr<Source> >
+list<boost::shared_ptr<Source> >
AudioDiskstream::steal_write_sources()
{
/* not possible to steal audio write sources */
(*chan)->write_source->mark_for_remove ();
(*chan)->write_source->drop_references ();
}
-
+
(*chan)->write_source.reset ();
}
{
while (how_many--) {
c->push_back (new ChannelInfo(
- _session.butler()->audio_diskstream_playback_buffer_size(),
+ _session.butler()->audio_diskstream_playback_buffer_size(),
_session.butler()->audio_diskstream_capture_buffer_size(),
speed_buffer_size, wrap_buffer_size));
interpolation.add_channel_to (
if (c->empty ()) {
return 0;
}
-
+
return (float) ((double) c->front()->capture_buf->write_space()/
(double) c->front()->capture_buf->bufsize());
}
boost::shared_ptr<AudioRegion> region;
try {
-
+
PropertyList plist;
-
+
plist.add (Properties::start, 0);
plist.add (Properties::length, first_fs->length (first_fs->timeline_position()));
plist.add (Properties::name, region_name_from_path (first_fs->name(), true));
return true;
}
-void
+void
AudioDiskstream::adjust_playback_buffering ()
{
boost::shared_ptr<ChannelList> c = channels.reader();
}
}
-void
+void
AudioDiskstream::adjust_capture_buffering ()
{
boost::shared_ptr<ChannelList> c = channels.reader();
boost::shared_ptr<ChannelList> c = channels.reader();
ChannelList::iterator i;
int n = 0;
-
+
for (n = 0, i = c->begin(); i != c->end(); ++i, ++n) {
use_new_write_source (n);
}