Properly announce support for Vendor string
[ardour.git] / libs / ardour / disk_writer.cc
index a3cfc69b1b821c6aae214433a033560d8395e67e..ed59da92316524f4fa874668814fbcd5c1ec42d9 100644 (file)
@@ -78,6 +78,34 @@ DiskWriter::default_chunk_samples ()
        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)
 {
@@ -89,18 +117,14 @@ void
 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;
@@ -112,14 +136,32 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo
                        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(),
@@ -138,29 +180,6 @@ DiskWriter::check_record_status (samplepos_t transport_sample, double speed, boo
 
                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;
@@ -281,9 +300,9 @@ DiskWriter::set_align_style (AlignStyle a, bool force)
 }
 
 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;
@@ -366,7 +385,9 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
        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;
 
@@ -391,7 +412,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
                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;
@@ -400,7 +421,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
                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
@@ -460,7 +481,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
                        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]) {
 
@@ -485,7 +506,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
                                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);
 
                }
 
@@ -532,6 +553,20 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
                                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());
                        }
@@ -574,7 +609,7 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp
        /* 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;
                }
        }
@@ -641,6 +676,16 @@ DiskWriter::finish_capture (boost::shared_ptr<ChannelList> c)
        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)
 {
@@ -740,8 +785,8 @@ DiskWriter::buffer_load () const
                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
@@ -767,7 +812,7 @@ DiskWriter::seek (samplepos_t sample, bool complete_refill)
        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 ();
@@ -802,7 +847,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
        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];
 
@@ -882,7 +927,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
                        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()) {
@@ -901,7 +946,7 @@ DiskWriter::do_flush (RunContext ctxt, bool force_flush)
                                return -1;
                        }
 
-                       (*chan)->buf->increment_read_ptr (to_write);
+                       (*chan)->wbuf->increment_read_ptr (to_write);
                        (*chan)->curr_capture_cnt += to_write;
                }
        }
@@ -1364,14 +1409,8 @@ DiskWriter::use_destructive_playlist ()
                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 */
@@ -1390,7 +1429,6 @@ DiskWriter::adjust_buffering ()
 void
 DiskWriter::realtime_handle_transport_stopped ()
 {
-       realtime_speed_change ();
 }
 
 bool