Make the session watch sources' DropReferences and drop accordingly. Remove a now...
[ardour.git] / libs / ardour / audio_diskstream.cc
index c88080a3d5a02454a360d5a78d72c7c631b906b8..2c0dcb3e97a77dcf571d8d4cfa201f6fcad8ea07 100644 (file)
@@ -114,9 +114,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 ()
@@ -410,8 +407,7 @@ AudioDiskstream::prepare_record_status(framepos_t capture_start_frame)
                                transvec.buf[0]->type = CaptureStart;
                                transvec.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,14 +417,14 @@ AudioDiskstream::prepare_record_status(framepos_t capture_start_frame)
 }
 
 int
-AudioDiskstream::process (framepos_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<ChannelList> 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;
@@ -503,7 +499,7 @@ AudioDiskstream::process (framepos_t transport_frame, nframes_t nframes, bool ca
 
                        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];
 
@@ -513,13 +509,13 @@ AudioDiskstream::process (framepos_t transport_frame, nframes_t nframes, bool ca
 
                                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 ();
@@ -530,7 +526,7 @@ AudioDiskstream::process (framepos_t transport_frame, nframes_t nframes, bool ca
                                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);
@@ -593,12 +589,12 @@ AudioDiskstream::process (framepos_t transport_frame, nframes_t nframes, bool ca
 
                /* 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;
                }
@@ -613,12 +609,12 @@ AudioDiskstream::process (framepos_t transport_frame, nframes_t nframes, bool ca
 
                        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;
@@ -662,7 +658,7 @@ AudioDiskstream::process (framepos_t transport_frame, nframes_t nframes, bool ca
 }
 
 void
-AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr<ChannelList> c)
+AudioDiskstream::process_varispeed_playback (pframes_t nframes, boost::shared_ptr<ChannelList> c)
 {
        ChannelList::iterator chan;
 
@@ -680,7 +676,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;
 
@@ -708,7 +704,11 @@ AudioDiskstream::commit (nframes_t /* nframes */)
                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;
@@ -717,10 +717,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);
                }
        }
 
@@ -735,13 +735,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<ChannelList> c = channels.reader ();
+       if (!c->empty ()) {
+               overwrite_offset = c->front()->playback_buf->get_read_ptr();
+       }
 }
 
 int
 AudioDiskstream::overwrite_existing_buffers ()
 {
        boost::shared_ptr<ChannelList> c = channels.reader();
+       if (c->empty ()) {
+               _pending_overwrite = false;
+               return 0;
+       }
+       
        Sample* mixdown_buffer;
        float* gain_buffer;
        int ret = -1;
@@ -750,7 +759,7 @@ 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];
@@ -764,7 +773,7 @@ AudioDiskstream::overwrite_existing_buffers ()
        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).
@@ -777,7 +786,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"),
@@ -864,7 +873,9 @@ AudioDiskstream::internal_playback_seek (framecnt_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;
@@ -872,14 +883,14 @@ AudioDiskstream::internal_playback_seek (framecnt_t distance)
 
 int
 AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, 
-                       framepos_t& start, nframes_t cnt,
+                       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;
        framepos_t loop_end = 0;
        framepos_t loop_start = 0;
-       nframes_t offset = 0;
+       framecnt_t offset = 0;
        Location *loc = 0;
 
        /* XXX we don't currently play loops in reverse. not sure why */
@@ -915,12 +926,12 @@ AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer,
                //cerr << "start is " << start << "  loopstart: " << loop_start << "  loopend: " << loop_end << endl;
        }
 
+       if (reversed) {
+               start -= cnt;
+       }
+       
        while (cnt) {
 
-               if (reversed) {
-                       start -= cnt;
-               }
-
                /* take any loop into account. we can't read past the end of the loop. */
 
                if (loc && (loop_end - start < cnt)) {
@@ -986,15 +997,15 @@ int
 AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
 {
        int32_t ret = 0;
-       nframes_t to_read;
+       framecnt_t to_read;
        RingBufferNPT<Sample>::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<ChannelList> c = channels.reader();
-       nframes_t ts;
+       framecnt_t ts;
 
        if (c->empty()) {
                return 0;
@@ -1039,7 +1050,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;
        }
 
@@ -1074,7 +1085,6 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
 
                        zero_fill = total_space - file_frame;
                        total_space = file_frame;
-                       file_frame = 0;
 
                } else {
 
@@ -1119,11 +1129,11 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
                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:
@@ -1157,6 +1167,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)) {
@@ -1191,7 +1203,8 @@ AudioDiskstream::_do_refill (Sample* mixdown_buffer, float* gain_buffer)
        }
 
        file_frame = file_frame_tmp;
-
+       assert (file_frame >= 0);
+       
   out:
 
        return ret;
@@ -1214,7 +1227,7 @@ AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush)
        int32_t ret = 0;
        RingBufferNPT<Sample>::rw_vector vector;
        RingBufferNPT<CaptureTransition>::rw_vector transvec;
-       nframes_t total;
+       framecnt_t total;
 
        _write_data_count = 0;
 
@@ -1249,7 +1262,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
@@ -1319,7 +1332,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;
@@ -1344,7 +1357,7 @@ AudioDiskstream::transport_stopped_wallclock (struct tm& when, time_t twhen, boo
        bool more_work = true;
        int err = 0;
        boost::shared_ptr<AudioRegion> region;
-       nframes_t total_capture;
+       framecnt_t total_capture;
        SourceList srcs;
        SourceList::iterator src;
        ChannelList::iterator chan;
@@ -1391,7 +1404,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 ();
                        }
 
@@ -1502,6 +1514,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--;
 
@@ -1941,7 +1962,6 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
                                 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 ();
@@ -1991,7 +2011,7 @@ AudioDiskstream::rename_write_sources ()
 }
 
 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 +2035,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) {
 
@@ -2126,6 +2146,10 @@ AudioDiskstream::playback_buffer_load () const
 {
        boost::shared_ptr<ChannelList> 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 +2159,10 @@ AudioDiskstream::capture_buffer_load () const
 {
        boost::shared_ptr<ChannelList> c = channels.reader();
 
+       if (c->empty ()) {
+               return 0;
+       }
+       
        return (float) ((double) c->front()->capture_buf->write_space()/
                        (double) c->front()->capture_buf->bufsize());
 }
@@ -2174,7 +2202,7 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                        try {
                                fs = boost::dynamic_pointer_cast<AudioFileSource> (
                                                SourceFactory::createWritable (DataType::AUDIO, _session,
-                                                               prop->value(), false, _session.frame_rate()));
+                                                                               prop->value(), string(), false, _session.frame_rate()));
                        }
 
                        catch (failed_constructor& err) {
@@ -2339,7 +2367,7 @@ AudioDiskstream::adjust_capture_buffering ()
         }
 }
 
-AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t playback_bufsize, nframes_t capture_bufsize, nframes_t speed_size, nframes_t wrap_size)
+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;
@@ -2367,7 +2395,7 @@ 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;
        playback_buf = new RingBufferNPT<Sample> (playback_bufsize);
@@ -2375,7 +2403,7 @@ AudioDiskstream::ChannelInfo::resize_playback (nframes_t playback_bufsize)
 }
 
 void
-AudioDiskstream::ChannelInfo::resize_capture (nframes_t capture_bufsize)
+AudioDiskstream::ChannelInfo::resize_capture (framecnt_t capture_bufsize)
 {
         delete capture_buf;