X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudio_diskstream.cc;h=1132b2a05037010188866874dd8b634428f33e53;hb=afdb298462cd7e6bb4ce866a1714a032c33be917;hp=0f485e73c8346e9ae1ba2cacf57e3c1843e5c247;hpb=1c1b359ff21aac57bd71d291049d657f66cf31f5;p=ardour.git diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 0f485e73c8..1132b2a050 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -31,7 +31,6 @@ #include #include "pbd/error.h" -#include #include "pbd/xml++.h" #include "pbd/memento_command.h" #include "pbd/enumwriter.h" @@ -74,7 +73,6 @@ gain_t* AudioDiskstream::_gain_buffer = 0; AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream::Flag flag) : Diskstream(sess, name, flag) - , deprecated_io_node(NULL) , channels (new ChannelList) { /* prevent any write sources from being created */ @@ -86,7 +84,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream: AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node) : Diskstream(sess, node) - , deprecated_io_node(NULL) , channels (new ChannelList) { in_set_state = true; @@ -114,9 +111,6 @@ AudioDiskstream::init () set_block_size (_session.get_block_size()); allocate_temporary_buffers (); - - add_channel (1); - assert(_n_channels == ChanCount(DataType::AUDIO, 1)); } AudioDiskstream::~AudioDiskstream () @@ -135,8 +129,6 @@ AudioDiskstream::~AudioDiskstream () } channels.flush (); - - delete deprecated_io_node; } void @@ -165,11 +157,11 @@ AudioDiskstream::non_realtime_input_change () { Glib::Mutex::Lock lm (state_lock); - if (input_change_pending == NoChange) { + if (input_change_pending.type == IOChange::NoChange) { return; } - { + if (input_change_pending.type == IOChange::ConfigurationChanged) { RCUWriter writer (channels); boost::shared_ptr c = writer.get_copy(); @@ -182,17 +174,13 @@ AudioDiskstream::non_realtime_input_change () } } - get_input_sources (); - set_capture_offset (); - - if (first_input_change) { - set_align_style (_persistent_alignment_style); - first_input_change = false; - } else { + if (input_change_pending.type & IOChange::ConnectionsChanged) { + get_input_sources (); + set_capture_offset (); set_align_style_from_io (); } - input_change_pending = NoChange; + input_change_pending = IOChange::NoChange; /* implicit unlock */ } @@ -204,19 +192,19 @@ AudioDiskstream::non_realtime_input_change () /* now refill channel buffers */ if (speed() != 1.0f || speed() != -1.0f) { - seek ((nframes_t) (_session.transport_frame() * (double) speed())); + seek ((framepos_t) (_session.transport_frame() * (double) speed())); } else { seek (_session.transport_frame()); } } void -AudioDiskstream::non_realtime_locate (nframes_t location) +AudioDiskstream::non_realtime_locate (framepos_t location) { /* now refill channel buffers */ if (speed() != 1.0f || speed() != -1.0f) { - seek ((nframes_t) (location * (double) speed())); + seek ((framepos_t) (location * (double) speed())); } else { seek (location); } @@ -237,15 +225,12 @@ AudioDiskstream::get_input_sources () connections.clear (); if (_io->nth (n)->get_connections (connections) == 0) { - - if ((*chan)->source) { + if (!(*chan)->source.name.empty()) { // _source->disable_metering (); } - - (*chan)->source = 0; - + (*chan)->source.name = string(); } else { - (*chan)->source = dynamic_cast(_session.engine().get_port_by_name (connections[0]) ); + (*chan)->source.name = connections[0]; } } } @@ -347,7 +332,7 @@ AudioDiskstream::setup_destructive_playlist () PropertyList plist; plist.add (Properties::name, _name.val()); plist.add (Properties::start, 0); - plist.add (Properties::length, max_frames - max_frames - srcs.front()->natural_position()); + plist.add (Properties::length, max_framepos - (max_framepos - srcs.front()->natural_position())); boost::shared_ptr region (RegionFactory::create (srcs, plist)); _playlist->add_region (region, srcs.front()->natural_position()); @@ -377,7 +362,7 @@ AudioDiskstream::use_destructive_playlist () /* be sure to stretch the region out to the maximum length */ - region->set_length (max_frames - region->position(), this); + region->set_length (max_framepos - region->position()); uint32_t n; ChannelList::iterator chan; @@ -397,21 +382,20 @@ AudioDiskstream::use_destructive_playlist () } void -AudioDiskstream::prepare_record_status(nframes_t capture_start_frame) +AudioDiskstream::prepare_record_status(framepos_t capture_start_frame) { if (recordable() && destructive()) { boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - RingBufferNPT::rw_vector transvec; - (*chan)->capture_transition_buf->get_write_vector(&transvec); + RingBufferNPT::rw_vector transitions; + (*chan)->capture_transition_buf->get_write_vector (&transitions); - if (transvec.len[0] > 0) { - transvec.buf[0]->type = CaptureStart; - transvec.buf[0]->capture_val = capture_start_frame; + if (transitions.len[0] > 0) { + transitions.buf[0]->type = CaptureStart; + transitions.buf[0]->capture_val = capture_start_frame; (*chan)->capture_transition_buf->increment_write_ptr(1); - } - else { + } else { // bad! fatal << X_("programming error: capture_transition_buf is full on rec start! inconceivable!") << endmsg; @@ -421,31 +405,31 @@ AudioDiskstream::prepare_record_status(nframes_t capture_start_frame) } int -AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler) +AudioDiskstream::process (framepos_t transport_frame, pframes_t nframes, bool can_record, bool rec_monitors_input, bool& need_butler) { uint32_t n; boost::shared_ptr c = channels.reader(); ChannelList::iterator chan; int ret = -1; - nframes_t rec_offset = 0; - nframes_t rec_nframes = 0; + framecnt_t rec_offset = 0; + framecnt_t rec_nframes = 0; bool collect_playback = false; - playback_distance = 0; + playback_distance = 0; if (!_io || !_io->active()) { return 0; } - check_record_status (transport_frame, nframes, can_record); + check_record_status (transport_frame, can_record); if (nframes == 0) { return 0; } - Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK); + Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK); - if (!sm.locked()) { + if (!sm.locked()) { return 1; } @@ -456,29 +440,23 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can (*chan)->current_playback_buffer = 0; } - /* two conditions to test for here: - - A: this track is rec-enabled, and the session has confirmed that we can record - B: this track is rec-enabled, has been recording, and we are set up for auto-punch-in + // Safeguard against situations where process() goes haywire when autopunching + // and last_recordable_frame < first_recordable_frame + + if (last_recordable_frame < first_recordable_frame) { + last_recordable_frame = max_framepos; + } - The second test is necessary to capture the extra material that arrives AFTER the transport - frame has left the punch range (which will cause the "can_record" argument to be false). - */ + if (record_enabled()) { + 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); - // Safeguard against situations where process() goes haywire when autopunching and last_recordable_frame < first_recordable_frame - if (last_recordable_frame < first_recordable_frame) { - last_recordable_frame = max_frames; - } - - 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; - } + if (rec_nframes && !was_recording) { + capture_captured = 0; + was_recording = true; + } + } if (can_record && !_last_capture_sources.empty()) { _last_capture_sources.clear (); @@ -501,7 +479,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can chaninfo->capture_buf->get_write_vector (&chaninfo->capture_vector); - if (rec_nframes <= chaninfo->capture_vector.len[0]) { + if (rec_nframes <= (framecnt_t) chaninfo->capture_vector.len[0]) { chaninfo->current_capture_buffer = chaninfo->capture_vector.buf[0]; @@ -511,13 +489,13 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can AudioPort* const ap = _io->audio (n); assert(ap); - assert(rec_nframes <= ap->get_audio_buffer(nframes).capacity()); + 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); } else { - nframes_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1]; + framecnt_t total = chaninfo->capture_vector.len[0] + chaninfo->capture_vector.len[1]; if (rec_nframes > total) { DiskOverrun (); @@ -528,7 +506,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can assert(ap); Sample* buf = ap->get_audio_buffer(nframes).data(); - nframes_t first = chaninfo->capture_vector.len[0]; + framecnt_t first = chaninfo->capture_vector.len[0]; memcpy (chaninfo->capture_wrap_buffer, buf, sizeof (Sample) * first); memcpy (chaninfo->capture_vector.buf[0], buf, sizeof (Sample) * first); @@ -591,12 +569,12 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can /* we're doing playback */ - nframes_t necessary_samples; + framecnt_t necessary_samples; /* no varispeed playback if we're recording, because the output .... TBD */ if (rec_nframes == 0 && _actual_speed != 1.0f) { - necessary_samples = (nframes_t) floor ((nframes * fabs (_actual_speed))) + 1; + necessary_samples = (framecnt_t) floor ((nframes * fabs (_actual_speed))) + 1; } else { necessary_samples = nframes; } @@ -611,12 +589,12 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can ChannelInfo* chaninfo (*chan); - if (necessary_samples <= chaninfo->playback_vector.len[0]) { + if (necessary_samples <= (framecnt_t) chaninfo->playback_vector.len[0]) { chaninfo->current_playback_buffer = chaninfo->playback_vector.buf[0]; } else { - nframes_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1]; + framecnt_t total = chaninfo->playback_vector.len[0] + chaninfo->playback_vector.len[1]; if (necessary_samples > total) { cerr << _name << " Need " << necessary_samples << " total = " << total << endl; @@ -647,20 +625,20 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can _speed = _target_speed; - } + } ret = 0; - if (commit (nframes)) { - need_butler = true; - } + if (commit (nframes)) { + need_butler = true; + } out: return ret; } void -AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr c) +AudioDiskstream::process_varispeed_playback (pframes_t nframes, boost::shared_ptr c) { ChannelList::iterator chan; @@ -678,7 +656,7 @@ AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr } bool -AudioDiskstream::commit (nframes_t /* nframes */) +AudioDiskstream::commit (framecnt_t /* nframes */) { bool need_butler = false; @@ -707,6 +685,10 @@ AudioDiskstream::commit (nframes_t /* nframes */) 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; @@ -715,10 +697,10 @@ AudioDiskstream::commit (nframes_t /* nframes */) } } else { if (_io && _io->active()) { - need_butler = c->front()->playback_buf->write_space() >= disk_io_chunk_frames - || c->front()->capture_buf->read_space() >= disk_io_chunk_frames; + need_butler = ((framecnt_t) c->front()->playback_buf->write_space() >= disk_io_chunk_frames) + || ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames); } else { - need_butler = c->front()->capture_buf->read_space() >= disk_io_chunk_frames; + need_butler = ((framecnt_t) c->front()->capture_buf->read_space() >= disk_io_chunk_frames); } } @@ -733,13 +715,22 @@ AudioDiskstream::set_pending_overwrite (bool yn) _pending_overwrite = yn; overwrite_frame = playback_sample; - overwrite_offset = channels.reader()->front()->playback_buf->get_read_ptr(); + + boost::shared_ptr c = channels.reader (); + if (!c->empty ()) { + overwrite_offset = c->front()->playback_buf->get_read_ptr(); + } } int AudioDiskstream::overwrite_existing_buffers () { boost::shared_ptr c = channels.reader(); + if (c->empty ()) { + _pending_overwrite = false; + return 0; + } + Sample* mixdown_buffer; float* gain_buffer; int ret = -1; @@ -748,21 +739,23 @@ AudioDiskstream::overwrite_existing_buffers () overwrite_queued = false; /* assume all are the same size */ - nframes_t size = c->front()->playback_buf->bufsize(); + framecnt_t size = c->front()->playback_buf->bufsize(); mixdown_buffer = new Sample[size]; gain_buffer = new float[size]; - /* reduce size so that we can fill the buffer correctly. */ + /* reduce size so that we can fill the buffer correctly (ringbuffers + can only handle size-1, otherwise they appear to be empty) + */ size--; uint32_t n=0; - nframes_t start; + framepos_t start; for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++n) { start = overwrite_frame; - nframes_t cnt = size; + framecnt_t cnt = size; /* to fill the buffer without resetting the playback sample, we need to do it one or two chunks (normally two). @@ -775,7 +768,7 @@ AudioDiskstream::overwrite_existing_buffers () */ - nframes_t to_read = size - overwrite_offset; + framecnt_t to_read = size - overwrite_offset; 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"), @@ -806,7 +799,7 @@ AudioDiskstream::overwrite_existing_buffers () } int -AudioDiskstream::seek (nframes_t frame, bool complete_refill) +AudioDiskstream::seek (framepos_t frame, bool complete_refill) { uint32_t n; int ret = -1; @@ -839,13 +832,13 @@ AudioDiskstream::seek (nframes_t frame, bool complete_refill) } int -AudioDiskstream::can_internal_playback_seek (nframes_t distance) +AudioDiskstream::can_internal_playback_seek (framecnt_t distance) { ChannelList::iterator chan; boost::shared_ptr c = channels.reader(); for (chan = c->begin(); chan != c->end(); ++chan) { - if ((*chan)->playback_buf->read_space() < distance) { + if ((*chan)->playback_buf->read_space() < (size_t) distance) { return false; } } @@ -853,7 +846,7 @@ AudioDiskstream::can_internal_playback_seek (nframes_t distance) } int -AudioDiskstream::internal_playback_seek (nframes_t distance) +AudioDiskstream::internal_playback_seek (framecnt_t distance) { ChannelList::iterator chan; boost::shared_ptr c = channels.reader(); @@ -862,28 +855,31 @@ AudioDiskstream::internal_playback_seek (nframes_t distance) (*chan)->playback_buf->increment_read_ptr (distance); } - first_recordable_frame += distance; + if (first_recordable_frame < max_framepos) { + first_recordable_frame += distance; + } playback_sample += distance; return 0; } int -AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, nframes_t& start, nframes_t cnt, - ChannelInfo* /*channel_info*/, int channel, bool reversed) +AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, + framepos_t& start, framecnt_t cnt, + ChannelInfo* /*channel_info*/, int channel, bool reversed) { - nframes_t this_read = 0; + framecnt_t this_read = 0; bool reloop = false; - nframes_t loop_end = 0; - nframes_t loop_start = 0; - nframes_t offset = 0; + framepos_t loop_end = 0; + framepos_t loop_start = 0; + framecnt_t offset = 0; Location *loc = 0; /* XXX we don't currently play loops in reverse. not sure why */ if (!reversed) { - nframes_t loop_length = 0; + framecnt_t loop_length = 0; /* Make the use of a Location atomic for this read operation. @@ -912,11 +908,11 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, //cerr << "start is " << start << " loopstart: " << loop_start << " loopend: " << loop_end << endl; } - while (cnt) { + if (reversed) { + start -= cnt; + } - if (reversed) { - start -= cnt; - } + while (cnt) { /* take any loop into account. we can't read past the end of the loop. */ @@ -983,15 +979,15 @@ int AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) { int32_t ret = 0; - nframes_t to_read; + framecnt_t to_read; RingBufferNPT::rw_vector vector; bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; - nframes_t total_space; - nframes_t zero_fill; + framecnt_t total_space; + framecnt_t zero_fill; uint32_t chan_n; ChannelList::iterator i; boost::shared_ptr c = channels.reader(); - nframes_t ts; + framecnt_t ts; if (c->empty()) { return 0; @@ -1036,7 +1032,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) work with. */ - if (_slaved && total_space < (c->front()->playback_buf->bufsize() / 2)) { + if (_slaved && total_space < (framecnt_t) (c->front()->playback_buf->bufsize() / 2)) { return 0; } @@ -1071,7 +1067,6 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) zero_fill = total_space - file_frame; total_space = file_frame; - file_frame = 0; } else { @@ -1080,7 +1075,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) } else { - if (file_frame == max_frames) { + if (file_frame == max_framepos) { /* at end: nothing to do but fill with silence */ @@ -1097,30 +1092,30 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) return 0; } - if (file_frame > max_frames - total_space) { + if (file_frame > max_framepos - 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; + zero_fill = total_space - (max_framepos - file_frame); + total_space = max_framepos - file_frame; } else { zero_fill = 0; } } - nframes_t file_frame_tmp = 0; + framepos_t file_frame_tmp = 0; for (chan_n = 0, i = c->begin(); i != c->end(); ++i, ++chan_n) { ChannelInfo* chan (*i); Sample* buf1; Sample* buf2; - nframes_t len1, len2; + framecnt_t len1, len2; chan->playback_buf->get_write_vector (&vector); - if (vector.len[0] > disk_io_chunk_frames) { + if ((framecnt_t) vector.len[0] > disk_io_chunk_frames) { /* we're not going to fill the first chunk, so certainly do not bother with the other part. it won't be connected with the part we do fill, as in: @@ -1154,6 +1149,8 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) to_read = min (ts, len1); to_read = min (to_read, disk_io_chunk_frames); + assert (to_read >= 0); + if (to_read) { if (read (buf1, mixdown_buffer, gain_buffer, file_frame_tmp, to_read, chan, chan_n, reversed)) { @@ -1188,6 +1185,7 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer) } file_frame = file_frame_tmp; + assert (file_frame >= 0); out: @@ -1211,7 +1209,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) int32_t ret = 0; RingBufferNPT::rw_vector vector; RingBufferNPT::rw_vector transvec; - nframes_t total; + framecnt_t total; _write_data_count = 0; @@ -1246,7 +1244,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) ret = 1; } - to_write = min (disk_io_chunk_frames, (nframes_t) vector.len[0]); + to_write = min (disk_io_chunk_frames, (framecnt_t) vector.len[0]); // check the transition buffer when recording destructive // important that we get this after the capture buf @@ -1254,7 +1252,6 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) 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) { @@ -1266,9 +1263,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) (*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 @@ -1316,7 +1311,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush) of vector.len[1] to be flushed to disk as well. */ - to_write = min ((nframes_t)(disk_io_chunk_frames - to_write), (nframes_t) vector.len[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; @@ -1341,7 +1336,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo bool more_work = true; int err = 0; boost::shared_ptr region; - nframes_t total_capture; + framecnt_t total_capture; SourceList srcs; SourceList::iterator src; ChannelList::iterator chan; @@ -1388,7 +1383,6 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo (*chan)->write_source->mark_for_remove (); (*chan)->write_source->drop_references (); - _session.remove_source ((*chan)->write_source); (*chan)->write_source.reset (); } @@ -1410,9 +1404,6 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo if (s) { srcs.push_back (s); - if (s->unstubify ()) { - error << string_compose (_("Could not move capture file from %1"), s->path()) << endmsg; - } s->update_header (capture_info.front()->start, when, twhen); s->set_captured_for (_name.val()); s->mark_immutable (); @@ -1470,7 +1461,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo // cerr << _name << ": there are " << capture_info.size() << " capture_info records\n"; - _playlist->clear_history (); + _playlist->clear_changes (); _playlist->freeze (); for (buffer_position = c->front()->write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) { @@ -1479,16 +1470,17 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo RegionFactory::region_name (region_name, whole_file_region_name, false); - // cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add region " << region_name << endl; + 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 rx (RegionFactory::create (srcs, plist)); region = boost::dynamic_pointer_cast (rx); } @@ -1499,6 +1491,15 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo } i_am_the_modifier++; + + if (_playlist->explicit_relayering()) { + /* We are in `explicit relayering' mode, so we must specify which layer this new region + should end up on. Put it at the top. + */ + 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--; @@ -1525,7 +1526,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo } void -AudioDiskstream::transport_looped (nframes_t transport_frame) +AudioDiskstream::transport_looped (framepos_t transport_frame) { if (was_recording) { // all we need to do is finish this capture, with modified capture length @@ -1550,7 +1551,7 @@ AudioDiskstream::transport_looped (nframes_t transport_frame) // no latency adjustment or capture offset needs to be made, as that already happened the first time capture_start_frame = transport_frame; first_recordable_frame = transport_frame; // mild lie - last_recordable_frame = max_frames; + last_recordable_frame = max_framepos; was_recording = true; if (recordable() && destructive()) { @@ -1579,8 +1580,8 @@ void AudioDiskstream::finish_capture (bool /*rec_monitors_input*/, boost::shared_ptr c) { was_recording = false; - first_recordable_frame = max_frames; - last_recordable_frame = max_frames; + first_recordable_frame = max_framepos; + last_recordable_frame = max_framepos; if (capture_captured == 0) { return; @@ -1625,7 +1626,7 @@ AudioDiskstream::finish_capture (bool /*rec_monitors_input*/, boost::shared_ptr< capture_captured = 0; /* now we've finished a capture, reset first_recordable_frame for next time */ - first_recordable_frame = max_frames; + first_recordable_frame = max_framepos; } void @@ -1666,9 +1667,7 @@ AudioDiskstream::engage_record_enable () if (Config->get_monitoring_model() == HardwareMonitoring) { for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - if ((*chan)->source) { - (*chan)->source->ensure_monitor_input (!(_session.config.get_auto_input() && rolling)); - } + (*chan)->source.ensure_monitor_input (!(_session.config.get_auto_input() && rolling)); capturing_sources.push_back ((*chan)->write_source); (*chan)->write_source->mark_streaming_write_started (); } @@ -1690,9 +1689,7 @@ AudioDiskstream::disengage_record_enable () boost::shared_ptr c = channels.reader(); if (Config->get_monitoring_model() == HardwareMonitoring) { for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - if ((*chan)->source) { - (*chan)->source->ensure_monitor_input (false); - } + (*chan)->source.ensure_monitor_input (false); } } capturing_sources.clear (); @@ -1702,24 +1699,13 @@ AudioDiskstream::disengage_record_enable () XMLNode& AudioDiskstream::get_state () { - XMLNode* node = new XMLNode ("Diskstream"); + XMLNode& node (Diskstream::get_state()); char buf[64] = ""; LocaleGuard lg (X_("POSIX")); - boost::shared_ptr c = channels.reader(); - - node->add_property ("flags", enum_2_string (_flags)); + boost::shared_ptr c = channels.reader(); snprintf (buf, sizeof(buf), "%zd", c->size()); - node->add_property ("channels", buf); - - node->add_property ("playlist", _playlist->name()); - - snprintf (buf, sizeof(buf), "%.12g", _visible_speed); - node->add_property ("speed", buf); - - node->add_property("name", _name); - id().print (buf, sizeof (buf)); - node->add_property("id", buf); + node.add_property ("channels", buf); if (!capturing_sources.empty() && _session.get_record_enabled()) { @@ -1743,18 +1729,14 @@ AudioDiskstream::get_state () } cs_child->add_property (X_("at"), buf); - node->add_child_nocopy (*cs_child); - } - - if (_extra_xml) { - node->add_child_copy (*_extra_xml); + node.add_child_nocopy (*cs_child); } - return* node; + return node; } int -AudioDiskstream::set_state (const XMLNode& node, int /*version*/) +AudioDiskstream::set_state (const XMLNode& node, int version) { const XMLProperty* prop; XMLNodeList nlist = node.children(); @@ -1763,6 +1745,8 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/) XMLNode* capture_pending_node = 0; LocaleGuard lg (X_("POSIX")); + /* prevent write sources from being created */ + in_set_state = true; for (niter = nlist.begin(); niter != nlist.end(); ++niter) { @@ -1775,26 +1759,8 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/) } } - /* prevent write sources from being created */ - - in_set_state = true; - - if ((prop = node.property ("name")) != 0) { - _name = prop->value(); - } - - if (deprecated_io_node) { - if ((prop = deprecated_io_node->property ("id")) != 0) { - _id = prop->value (); - } - } else { - if ((prop = node.property ("id")) != 0) { - _id = prop->value (); - } - } - - if ((prop = node.property ("flags")) != 0) { - _flags = Flag (string_2_enum (prop->value(), _flags)); + if (Diskstream::set_state (node, version)) { + return -1; } if ((prop = node.property ("channels")) != 0) { @@ -1816,37 +1782,14 @@ AudioDiskstream::set_state (const XMLNode& node, int /*version*/) remove_channel (_n_channels.n_audio() - nchans); } - if ((prop = node.property ("playlist")) == 0) { - return -1; - } - - { - bool had_playlist = (_playlist != 0); - - if (find_and_use_playlist (prop->value())) { - return -1; - } - - if (!had_playlist) { - _playlist->set_orig_diskstream_id (id()); - } - - if (!destructive() && capture_pending_node) { - /* destructive streams have one and only one source per channel, - and so they never end up in pending capture in any useful - sense. - */ - use_pending_capture_data (*capture_pending_node); - } - } - if ((prop = node.property ("speed")) != 0) { - double sp = atof (prop->value().c_str()); - - if (realtime_set_speed (sp, false)) { - non_realtime_set_speed (); - } + if (!destructive() && capture_pending_node) { + /* destructive streams have one and only one source per channel, + and so they never end up in pending capture in any useful + sense. + */ + use_pending_capture_data (*capture_pending_node); } in_set_state = false; @@ -1878,20 +1821,9 @@ AudioDiskstream::use_new_write_source (uint32_t n) ChannelInfo* chan = (*c)[n]; - if (chan->write_source) { - chan->write_source->done_with_peakfile_writes (); - chan->write_source->set_allow_remove_if_empty (true); - chan->write_source.reset (); - } - try { - /* file starts off as a stub file, it will be converted - when we're done with a capture pass. - */ - - if ((chan->write_source = _session.create_audio_source_for_session (n_channels().n_audio(), - name(), n, destructive(), - true)) == 0) { + if ((chan->write_source = _session.create_audio_source_for_session ( + n_channels().n_audio(), name(), n, destructive())) == 0) { throw failed_constructor(); } } @@ -1905,16 +1837,16 @@ AudioDiskstream::use_new_write_source (uint32_t n) /* do not remove destructive files even if they are empty */ chan->write_source->set_allow_remove_if_empty (!destructive()); - + return 0; } -list > +list > AudioDiskstream::steal_write_sources() { - /* not possible to steal audio write sources */ - list > ret; - return ret; + /* not possible to steal audio write sources */ + list > ret; + return ret; } void @@ -1934,18 +1866,20 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/) if (!destructive()) { - if ((*chan)->write_source && mark_write_complete) { - (*chan)->write_source->mark_streaming_write_completed (); - } + if ((*chan)->write_source) { + + if (mark_write_complete) { + (*chan)->write_source->mark_streaming_write_completed (); + (*chan)->write_source->done_with_peakfile_writes (); + } + + if ((*chan)->write_source->removable()) { + (*chan)->write_source->mark_for_remove (); + (*chan)->write_source->drop_references (); + } - if ((*chan)->write_source) { - if ((*chan)->write_source->removable()) { - (*chan)->write_source->mark_for_remove (); - (*chan)->write_source->drop_references (); - _session.remove_source ((*chan)->write_source); - } - (*chan)->write_source.reset (); - } + (*chan)->write_source.reset (); + } use_new_write_source (n); @@ -1973,25 +1907,8 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/) } } -int -AudioDiskstream::rename_write_sources () -{ - ChannelList::iterator chan; - boost::shared_ptr c = channels.reader(); - uint32_t n; - - for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) { - if ((*chan)->write_source != 0) { - (*chan)->write_source->set_source_name (_name.val(), destructive()); - /* XXX what to do if one of them fails ? */ - } - } - - return 0; -} - void -AudioDiskstream::set_block_size (nframes_t /*nframes*/) +AudioDiskstream::set_block_size (pframes_t /*nframes*/) { if (_session.get_block_size() > speed_buffer_size) { speed_buffer_size = _session.get_block_size(); @@ -2015,7 +1932,7 @@ AudioDiskstream::allocate_temporary_buffers () */ double const sp = max (fabsf (_actual_speed), 1.2f); - nframes_t required_wrap_size = (nframes_t) floor (_session.get_block_size() * sp) + 1; + framecnt_t required_wrap_size = (framecnt_t) floor (_session.get_block_size() * sp) + 1; if (required_wrap_size > wrap_buffer_size) { @@ -2040,10 +1957,7 @@ AudioDiskstream::monitor_input (bool yn) boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - - if ((*chan)->source) { - (*chan)->source->ensure_monitor_input (yn); - } + (*chan)->source.ensure_monitor_input (yn); } } @@ -2052,6 +1966,10 @@ AudioDiskstream::set_align_style_from_io () { bool have_physical = false; + if (_alignment_choice != Automatic) { + return; + } + if (_io == 0) { return; } @@ -2061,7 +1979,7 @@ AudioDiskstream::set_align_style_from_io () boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - if ((*chan)->source && (*chan)->source->flags() & JackPortIsPhysical) { + if ((*chan)->source.is_physical ()) { have_physical = true; break; } @@ -2078,10 +1996,13 @@ int AudioDiskstream::add_channel_to (boost::shared_ptr c, uint32_t how_many) { while (how_many--) { - c->push_back (new ChannelInfo(_session.butler()->audio_diskstream_playback_buffer_size(), - _session.butler()->audio_diskstream_capture_buffer_size(), - speed_buffer_size, wrap_buffer_size)); - interpolation.add_channel_to (_session.butler()->audio_diskstream_playback_buffer_size(), speed_buffer_size); + c->push_back (new ChannelInfo( + _session.butler()->audio_diskstream_playback_buffer_size(), + _session.butler()->audio_diskstream_capture_buffer_size(), + speed_buffer_size, wrap_buffer_size)); + interpolation.add_channel_to ( + _session.butler()->audio_diskstream_playback_buffer_size(), + speed_buffer_size); } _n_channels.set(DataType::AUDIO, c->size()); @@ -2126,6 +2047,10 @@ AudioDiskstream::playback_buffer_load () const { boost::shared_ptr c = channels.reader(); + if (c->empty ()) { + return 0; + } + return (float) ((double) c->front()->playback_buf->read_space()/ (double) c->front()->playback_buf->bufsize()); } @@ -2135,6 +2060,10 @@ AudioDiskstream::capture_buffer_load () const { boost::shared_ptr c = channels.reader(); + if (c->empty ()) { + return 0; + } + return (float) ((double) c->front()->capture_buf->write_space()/ (double) c->front()->capture_buf->bufsize()); } @@ -2148,13 +2077,13 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) boost::shared_ptr fs; boost::shared_ptr first_fs; SourceList pending_sources; - nframes_t position; + framepos_t position; if ((prop = node.property (X_("at"))) == 0) { return -1; } - if (sscanf (prop->value().c_str(), "%" PRIu32, &position) != 1) { + if (sscanf (prop->value().c_str(), "%" PRIu64, &position) != 1) { return -1; } @@ -2173,8 +2102,9 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) try { fs = boost::dynamic_pointer_cast ( - SourceFactory::createWritable (DataType::AUDIO, _session, - prop->value(), false, _session.frame_rate())); + SourceFactory::createWritable ( + DataType::AUDIO, _session, + prop->value(), string(), false, _session.frame_rate())); } catch (failed_constructor& err) { @@ -2208,9 +2138,9 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) boost::shared_ptr 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)); @@ -2319,30 +2249,49 @@ AudioDiskstream::can_become_destructive (bool& requires_bounce) const return true; } -void +void AudioDiskstream::adjust_playback_buffering () { boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->resize_playback (_session.butler()->audio_diskstream_playback_buffer_size()); - } + (*chan)->resize_playback (_session.butler()->audio_diskstream_playback_buffer_size()); + } } -void +void AudioDiskstream::adjust_capture_buffering () { boost::shared_ptr c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { - (*chan)->resize_capture (_session.butler()->audio_diskstream_capture_buffer_size()); - } + (*chan)->resize_capture (_session.butler()->audio_diskstream_capture_buffer_size()); + } +} + +bool +AudioDiskstream::ChannelSource::is_physical () const +{ + if (name.empty()) { + return false; + } + + return AudioEngine::instance()->port_is_physical (name); } -AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t playback_bufsize, nframes_t capture_bufsize, nframes_t speed_size, nframes_t wrap_size) +void +AudioDiskstream::ChannelSource::ensure_monitor_input (bool yn) const +{ + if (name.empty()) { + return; + } + + return AudioEngine::instance()->ensure_monitor_input (name, yn); +} + +AudioDiskstream::ChannelInfo::ChannelInfo (framecnt_t playback_bufsize, framecnt_t capture_bufsize, framecnt_t speed_size, framecnt_t wrap_size) { peak_power = 0.0f; - source = 0; current_capture_buffer = 0; current_playback_buffer = 0; curr_capture_cnt = 0; @@ -2367,17 +2316,17 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t playback_bufsize, nframes_t } void -AudioDiskstream::ChannelInfo::resize_playback (nframes_t playback_bufsize) +AudioDiskstream::ChannelInfo::resize_playback (framecnt_t playback_bufsize) { - delete playback_buf; + delete playback_buf; playback_buf = new RingBufferNPT (playback_bufsize); memset (playback_buf->buffer(), 0, sizeof (Sample) * playback_buf->bufsize()); } void -AudioDiskstream::ChannelInfo::resize_capture (nframes_t capture_bufsize) +AudioDiskstream::ChannelInfo::resize_capture (framecnt_t capture_bufsize) { - delete capture_buf; + delete capture_buf; capture_buf = new RingBufferNPT (capture_bufsize); memset (capture_buf->buffer(), 0, sizeof (Sample) * capture_buf->bufsize()); @@ -2385,7 +2334,7 @@ AudioDiskstream::ChannelInfo::resize_capture (nframes_t capture_bufsize) AudioDiskstream::ChannelInfo::~ChannelInfo () { - write_source.reset (); + write_source.reset (); delete [] speed_buffer; speed_buffer = 0; @@ -2406,3 +2355,21 @@ AudioDiskstream::ChannelInfo::~ChannelInfo () capture_transition_buf = 0; } + +bool +AudioDiskstream::set_name (string const & name) +{ + Diskstream::set_name (name); + + /* get a new write source so that its name reflects the new diskstream name */ + + boost::shared_ptr 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); + } + + return true; +}