advance track's play-position even if processing is locked
authorRobin Gareus <robin@gareus.org>
Sat, 3 Aug 2013 19:35:19 +0000 (21:35 +0200)
committerPaul Davis <paul@linuxaudiosystems.com>
Thu, 8 Aug 2013 19:26:19 +0000 (15:26 -0400)
fixes
  * http://tracker.ardour.org/view.php?id=5628
  * http://tracker.ardour.org/view.php?id=5561

libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/midi_diskstream.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_track.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_track.cc
libs/ardour/track.cc

index cbc6b93fe0d4b53d86ac5ce80502c9d84ab107e9..b636cb47346109d6f1a7e36e9b654c80f8d1833e 100644 (file)
@@ -152,6 +152,7 @@ class AudioDiskstream : public Diskstream
        friend class AudioTrack;
 
         int  process (BufferSet&, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_disk_signal);
+        frameoffset_t calculate_playback_distance (pframes_t nframes);
        bool commit  (framecnt_t);
 
   private:
index 85ca03caff7da8e5e179701ba86dd1826702441c..427b52b0545274f72b8c8e5a2947cbdc1328d9e7 100644 (file)
@@ -193,6 +193,7 @@ class Diskstream : public SessionObject, public PublicDiskstream
        friend class Track;
 
     virtual int  process (BufferSet&, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_disk_signal) = 0;
+    virtual frameoffset_t calculate_playback_distance (pframes_t nframes) = 0;
        virtual bool commit  (framecnt_t) = 0;
 
        //private:
index d6ad71863ab15e594a0a74450d6b7e141977fb5f..34fa0ae79a187166530b28602adfe0fe5031ab48 100644 (file)
@@ -125,6 +125,7 @@ class MidiDiskstream : public Diskstream
        friend class MidiTrack;
 
         int  process (BufferSet&, framepos_t transport_frame, pframes_t nframes, framecnt_t &, bool need_diskstream);
+        frameoffset_t calculate_playback_distance (pframes_t nframes);
        bool commit  (framecnt_t nframes);
        static framecnt_t midi_readahead;
 
index c302e06681ca05f394b14c7451eafafb6e27501b..b9ce987c876ae50243ea59fea63eed7ee4ec4715 100644 (file)
@@ -700,6 +700,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.
@@ -900,7 +925,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) {
index 6de833aeb4f5b3332299782d2b627cdd49275d42..0530dbfce93abd16b1ef1e7e9827dd3495ad812d 100644 (file)
@@ -313,6 +313,12 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram
        Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
 
        if (!lm.locked()) {
+               boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
+               framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
+               if (can_internal_playback_seek(llabs(playback_distance))) {
+                       /* TODO should declick */
+                       internal_playback_seek(playback_distance);
+               }
                return 0;
        }
 
index 26cd43aec415a2f0c1fd44e6c0d7366bb7b6a339..f059269b638a85efa54c12c94d2d65fe680e565f 100644 (file)
@@ -517,6 +517,20 @@ MidiDiskstream::process (BufferSet& bufs, framepos_t transport_frame, pframes_t
        return 0;
 }
 
+frameoffset_t
+MidiDiskstream::calculate_playback_distance (pframes_t nframes)
+{
+       frameoffset_t playback_distance = nframes;
+
+       /* XXX: should be doing varispeed stuff once it's implemented in ::process() above */
+
+       if (_actual_speed < 0.0) {
+               return -playback_distance;
+       } else {
+               return playback_distance;
+       }
+}
+
 bool
 MidiDiskstream::commit (framecnt_t playback_distance)
 {
index 90b866ca92b141b62373d30081338000e2a38c9c..f88c331c2ca8a0e7b171b7f1a4aea9a5f9ac7ba9 100644 (file)
@@ -319,6 +319,12 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
 {
        Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
        if (!lm.locked()) {
+               boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
+               framecnt_t playback_distance = diskstream->calculate_playback_distance(nframes);
+               if (can_internal_playback_seek(llabs(playback_distance))) {
+                       /* TODO should declick, and/or note-off */
+                       internal_playback_seek(playback_distance);
+               }
                return 0;
        }
 
index 7d90709b6ff01c493202eaa18e5b3003dbacf182..f02863393ef236151afe7799f9fc2b837ab00cf5 100644 (file)
@@ -477,6 +477,10 @@ Track::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*
 {
        Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
        if (!lm.locked()) {
+               framecnt_t playback_distance = _diskstream->calculate_playback_distance(nframes);
+               if (can_internal_playback_seek(playback_distance)) {
+                       internal_playback_seek(playback_distance);
+               }
                return 0;
        }