add latency callback to dummy backend
[ardour.git] / libs / ardour / audio_diskstream.cc
index 7bfc9426cd56e86bd5a7279c8914e20b29f61c2d..095bbf075a3a94b0ea685a50d6bdb54c0b5223cd 100644 (file)
@@ -698,6 +698,31 @@ AudioDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
        return 0;
 }
 
+frameoffset_t
+AudioDiskstream::calculate_playback_distance (pframes_t nframes)
+{
+       frameoffset_t playback_distance = nframes;
+
+       if (record_enabled()) {
+               playback_distance = nframes;
+       } else if (_actual_speed != 1.0f && _actual_speed != -1.0f) {
+               interpolation.set_speed (_target_speed);
+               boost::shared_ptr<ChannelList> c = channels.reader();
+               int channel = 0;
+               for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan, ++channel) {
+                       playback_distance = interpolation.interpolate (channel, nframes, NULL, NULL);
+               }
+       } else {
+               playback_distance = nframes;
+       }
+
+       if (_actual_speed < 0.0) {
+               return -playback_distance;
+       } else {
+               return playback_distance;
+       }
+}
+
 /** Update various things including playback_sample, read pointer on each channel's playback_buf
  *  and write pointer on each channel's capture_buf.  Also wout whether the butler is needed.
  *  @return true if the butler is required.
@@ -898,7 +923,7 @@ AudioDiskstream::internal_playback_seek (framecnt_t distance)
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        for (chan = c->begin(); chan != c->end(); ++chan) {
-               (*chan)->playback_buf->increment_read_ptr (distance);
+               (*chan)->playback_buf->increment_read_ptr (llabs(distance));
        }
 
        if (first_recordable_frame < max_framepos) {
@@ -1727,7 +1752,7 @@ AudioDiskstream::prep_record_enable ()
        if (Config->get_monitoring_model() == HardwareMonitoring) {
 
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-                       (*chan)->source.request_jack_monitors_input (!(_session.config.get_auto_input() && rolling));
+                       (*chan)->source.request_input_monitoring (!(_session.config.get_auto_input() && rolling));
                        capturing_sources.push_back ((*chan)->write_source);
                        (*chan)->write_source->mark_streaming_write_started ();
                }
@@ -1748,7 +1773,7 @@ AudioDiskstream::prep_record_disable ()
        boost::shared_ptr<ChannelList> c = channels.reader();
        if (Config->get_monitoring_model() == HardwareMonitoring) {
                for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-                       (*chan)->source.request_jack_monitors_input (false);
+                       (*chan)->source.request_input_monitoring (false);
                }
        }
        capturing_sources.clear ();
@@ -1764,7 +1789,7 @@ AudioDiskstream::get_state ()
        LocaleGuard lg (X_("POSIX"));
 
        boost::shared_ptr<ChannelList> c = channels.reader();
-       snprintf (buf, sizeof(buf), "%zd", c->size());
+       snprintf (buf, sizeof(buf), "%u", (unsigned int) c->size());
        node.add_property ("channels", buf);
 
        if (!capturing_sources.empty() && _session.get_record_enabled()) {
@@ -1901,14 +1926,6 @@ AudioDiskstream::use_new_write_source (uint32_t n)
        return 0;
 }
 
-list<boost::shared_ptr<Source> >
-AudioDiskstream::steal_write_sources()
-{
-       /* not possible to steal audio write sources */
-       list<boost::shared_ptr<Source> > ret;
-       return ret;
-}
-
 void
 AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
 {
@@ -2014,12 +2031,12 @@ AudioDiskstream::allocate_temporary_buffers ()
 }
 
 void
-AudioDiskstream::request_jack_monitors_input (bool yn)
+AudioDiskstream::request_input_monitoring (bool yn)
 {
        boost::shared_ptr<ChannelList> c = channels.reader();
 
        for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
-               (*chan)->source.request_jack_monitors_input (yn);
+               (*chan)->source.request_input_monitoring (yn);
        }
 }
 
@@ -2162,11 +2179,16 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                                continue;
                        }
 
+                       /* XXX as of June 2014, we always record to mono
+                          files. Since this Source is being created as part of
+                          crash recovery, we know that we need the first
+                          channel (the final argument to the SourceFactory
+                          call below). If we ever support non-mono files for
+                          capture, this will need rethinking.
+                       */
+
                        try {
-                               fs = boost::dynamic_pointer_cast<AudioFileSource> (
-                                       SourceFactory::createWritable (
-                                               DataType::AUDIO, _session,
-                                               prop->value(), false, _session.frame_rate()));
+                               fs = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createForRecovery (DataType::AUDIO, _session, prop->value(), 0));
                        }
 
                        catch (failed_constructor& err) {
@@ -2197,21 +2219,31 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                return -1;
        }
 
-       boost::shared_ptr<AudioRegion> region;
-
        try {
 
-               PropertyList plist;
+               boost::shared_ptr<AudioRegion> wf_region;
+               boost::shared_ptr<AudioRegion> region;
+               
+               /* First create the whole file region */
 
+               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));
 
-               region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
+               wf_region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
 
-               region->set_automatic (true);
-               region->set_whole_file (true);
-               region->special_set_position (0);
+               wf_region->set_automatic (true);
+               wf_region->set_whole_file (true);
+               wf_region->special_set_position (position);
+
+               /* Now create a region that isn't the whole file for adding to
+                * the playlist */
+
+               region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (pending_sources, plist));
+               
+               _playlist->add_region (region, position);
        }
 
        catch (failed_constructor& err) {
@@ -2222,7 +2254,6 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node)
                return -1;
        }
 
-       _playlist->add_region (region, position);
 
        return 0;
 }
@@ -2342,13 +2373,13 @@ AudioDiskstream::ChannelSource::is_physical () const
 }
 
 void
-AudioDiskstream::ChannelSource::request_jack_monitors_input (bool yn) const
+AudioDiskstream::ChannelSource::request_input_monitoring (bool yn) const
 {
        if (name.empty()) {
                return;
        }
 
-       return AudioEngine::instance()->request_jack_monitors_input (name, yn);
+       return AudioEngine::instance()->request_input_monitoring (name, yn);
 }
 
 AudioDiskstream::ChannelInfo::ChannelInfo (framecnt_t playback_bufsize, framecnt_t capture_bufsize, framecnt_t speed_size, framecnt_t wrap_size)