return 65536;
}
+void
+DiskWriter::WriterChannelInfo::resize (samplecnt_t bufsize)
+{
+ if (!capture_transition_buf) {
+ capture_transition_buf = new RingBufferNPT<CaptureTransition> (256);
+ }
+ delete wbuf;
+ wbuf = new RingBufferNPT<Sample> (bufsize);
+ /* touch memory to lock it */
+ memset (wbuf->buffer(), 0, sizeof (Sample) * wbuf->bufsize());
+}
+
+int
+DiskWriter::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
+{
+ while (how_many--) {
+ c->push_back (new WriterChannelInfo (_session.butler()->audio_diskstream_capture_buffer_size()));
+ DEBUG_TRACE (DEBUG::DiskIO, string_compose ("%1: new writer channel, write space = %2 read = %3\n",
+ name(),
+ c->back()->wbuf->write_space(),
+ c->back()->wbuf->read_space()));
+ }
+
+ return 0;
+}
+
+
+
bool
DiskWriter::set_write_source_name (string const & str)
{
DiskWriter::check_record_status (samplepos_t transport_sample, double speed, bool can_record)
{
int possibly_recording;
- int rolling;
- int change;
const int transport_rolling = 0x4;
const int track_rec_enabled = 0x2;
const int global_rec_enabled = 0x1;
- const int fully_rec_enabled = (transport_rolling|track_rec_enabled|global_rec_enabled);
+ const int fully_rec_enabled = (transport_rolling |track_rec_enabled | global_rec_enabled);
/* merge together the 3 factors that affect record status, and compute what has changed. */
- rolling = speed != 0.0f;
- possibly_recording = (rolling << 2) | ((int)record_enabled() << 1) | (int)can_record;
- change = possibly_recording ^ last_possibly_recording;
+ possibly_recording = (speed != 0.0f ? 4 : 0) | (record_enabled() ? 2 : 0) | (can_record ? 1 : 0);
if (possibly_recording == last_possibly_recording) {
return;
return;
}
- capture_start_sample = _session.transport_sample ();
+ Location* loc;
+ if (_session.config.get_punch_in () && 0 != (loc = _session.locations()->auto_punch_location ())) {
+ capture_start_sample = loc->start ();
+ } else {
+ capture_start_sample = _session.transport_sample ();
+ }
+
first_recordable_sample = capture_start_sample;
if (_alignment_style == ExistingMaterial) {
first_recordable_sample += _capture_offset + _playback_offset;
}
- last_recordable_sample = max_samplepos;
+ if (_session.config.get_punch_out () && 0 != (loc = _session.locations()->auto_punch_location ())) {
+ /* this freezes the punch-out point when starting to record.
+ *
+ * We should allow to move it or at least allow to disable punch-out
+ * while rolling..
+ */
+ last_recordable_sample = loc->end ();
+ if (_alignment_style == ExistingMaterial) {
+ last_recordable_sample += _capture_offset + _playback_offset;
+ }
+ } else {
+ last_recordable_sample = max_samplepos;
+ }
DEBUG_TRACE (DEBUG::CaptureAlignment, string_compose ("%1: @ %2 (STS: %3) CS:%4 FRS: %5 IL: %7, OL: %8 CO: %r9 PO: %10 WOL: %11 WIL: %12\n",
name(),
prepare_record_status (capture_start_sample);
- } else {
-
- if (last_possibly_recording == fully_rec_enabled) {
-
- /* we were recording last time */
-
- if (change & transport_rolling) {
-
- /* transport-change (stopped rolling): last_recordable_sample was set in ::prepare_to_stop(). We
- * had to set it there because we likely rolled past the stopping point to declick out,
- * and then backed up.
- */
-
- } else {
- /* punch out */
-
- last_recordable_sample = _session.transport_sample();
-
- if (_alignment_style == ExistingMaterial) {
- //XXX
- }
- }
- }
}
last_possibly_recording = possibly_recording;
}
XMLNode&
-DiskWriter::state (bool full)
+DiskWriter::state ()
{
- XMLNode& node (DiskIOProcessor::state (full));
+ XMLNode& node (DiskIOProcessor::state ());
node.set_property (X_("type"), X_("diskwriter"));
node.set_property (X_("record-safe"), (_record_safe ? X_("yes" : "no")));
return node;
bool nominally_recording;
bool re = record_enabled ();
+ bool punch_in = _session.config.get_punch_in () && _session.locations()->auto_punch_location ();
bool can_record = _session.actively_recording ();
+ can_record |= speed != 0 && _session.get_record_enabled () && punch_in && _session.transport_sample () <= _session.locations()->auto_punch_location ()->start ();
_need_butler = false;
last_recordable_sample = max_samplepos;
}
- const Location* const loop_loc = loop_location;
+ const Location* const loop_loc = _loop_location;
samplepos_t loop_start = 0;
samplepos_t loop_end = 0;
samplepos_t loop_length = 0;
get_location_times (loop_loc, &loop_start, &loop_end, &loop_length);
}
- if (nominally_recording || (re && was_recording && _session.get_record_enabled() && (_session.config.get_punch_in() || _session.preroll_record_punch_enabled()))) {
+ if (nominally_recording || (re && was_recording && _session.get_record_enabled() && punch_in)) {
Evoral::OverlapType ot = Evoral::coverage (first_recordable_sample, last_recordable_sample, start_sample, end_sample);
// XXX should this be transport_sample + nframes - 1 ? coverage() expects its parameter ranges to include their end points
ChannelInfo* chaninfo (*chan);
AudioBuffer& buf (bufs.get_audio (n%n_buffers));
- chaninfo->buf->get_write_vector (&chaninfo->rw_vector);
+ chaninfo->wbuf->get_write_vector (&chaninfo->rw_vector);
if (rec_nframes <= (samplecnt_t) chaninfo->rw_vector.len[0]) {
memcpy (chaninfo->rw_vector.buf[1], incoming + first, sizeof (Sample) * (rec_nframes - first));
}
- chaninfo->buf->increment_write_ptr (rec_nframes);
+ chaninfo->wbuf->increment_write_ptr (rec_nframes);
}
continue;
}
+ bool skip_event = false;
+ if (mt) {
+ /* skip injected immediate/out-of-band events */
+ MidiBuffer const& ieb (mt->immediate_event_buffer());
+ for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) {
+ if (*j == ev) {
+ skip_event = true;
+ }
+ }
+ }
+ if (skip_event) {
+ continue;
+ }
+
if (!filter || !filter->filter(ev.buffer(), ev.size())) {
_midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer());
}
/* AUDIO BUTLER REQUIRED CODE */
if (_playlists[DataType::AUDIO] && !c->empty()) {
- if (((samplecnt_t) c->front()->buf->read_space() >= _chunk_samples)) {
+ if (((samplecnt_t) c->front()->wbuf->read_space() >= _chunk_samples)) {
_need_butler = true;
}
}
first_recordable_sample = max_samplepos;
}
+boost::shared_ptr<MidiBuffer>
+DiskWriter::get_gui_feed_buffer () const
+{
+ boost::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
+
+ Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex);
+ b->copy (_gui_feed_buffer);
+ return b;
+}
+
void
DiskWriter::set_record_enabled (bool yn)
{
return 1.0;
}
- return (float) ((double) c->front()->buf->write_space()/
- (double) c->front()->buf->bufsize());
+ return (float) ((double) c->front()->wbuf->write_space()/
+ (double) c->front()->wbuf->bufsize());
}
void
boost::shared_ptr<ChannelList> c = channels.reader();
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
- (*chan)->buf->reset ();
+ (*chan)->wbuf->reset ();
}
_midi_buf->reset ();
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- (*chan)->buf->get_read_vector (&vector);
+ (*chan)->wbuf->get_read_vector (&vector);
total = vector.len[0] + vector.len[1];
return -1;
}
- (*chan)->buf->increment_read_ptr (to_write);
+ (*chan)->wbuf->increment_read_ptr (to_write);
(*chan)->curr_capture_cnt += to_write;
if ((to_write == vector.len[0]) && (total > to_write) && (to_write < _chunk_samples) && !destructive()) {
return -1;
}
- (*chan)->buf->increment_read_ptr (to_write);
+ (*chan)->wbuf->increment_read_ptr (to_write);
(*chan)->curr_capture_cnt += to_write;
}
}
assert((*chan)->write_source);
(*chan)->write_source->set_allow_remove_if_empty (false);
- /* this might be false if we switched modes, so force it */
-
-#ifdef XXX_OLD_DESTRUCTIVE_API_XXX
- (*chan)->write_source->set_destructive (true);
-#else
// should be set when creating the source or loading the state
assert ((*chan)->write_source->destructive());
-#endif
}
/* the source list will never be reset for a destructive track */
void
DiskWriter::realtime_handle_transport_stopped ()
{
- realtime_speed_change ();
}
bool