diff options
-rw-r--r-- | gtk2_ardour/ardour_ui.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/streamview.cc | 9 | ||||
-rw-r--r-- | gtk2_ardour/streamview.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/audio_diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 1 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 58 | ||||
-rw-r--r-- | libs/ardour/session.cc | 21 | ||||
-rw-r--r-- | libs/ardour/session_process.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 29 |
10 files changed, 106 insertions, 19 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 10f6a2fe7a..bde4ca2947 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1244,7 +1244,7 @@ ARDOUR_UI::transport_record () break; case Session::Recording: case Session::Enabled: - session->disable_record (true); + session->disable_record (false, true); } } } diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index 305b5c3240..b18e5efb42 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -76,6 +76,7 @@ StreamView::StreamView (RouteTimeAxisView& tv) if (_trackview.is_track()) { _trackview.track()->DiskstreamChanged.connect (mem_fun (*this, &StreamView::diskstream_changed)); _trackview.session().TransportStateChange.connect (mem_fun (*this, &StreamView::transport_changed)); + _trackview.session().TransportLooped.connect (mem_fun (*this, &StreamView::transport_looped)); _trackview.get_diskstream()->RecordEnableChanged.connect (mem_fun (*this, &StreamView::rec_enable_changed)); _trackview.session().RecordStateChanged.connect (mem_fun (*this, &StreamView::sess_rec_enable_changed)); } @@ -315,6 +316,14 @@ StreamView::transport_changed() } void +StreamView::transport_looped() +{ + // to force a new rec region + rec_active = false; + Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::setup_rec_box)); +} + +void StreamView::update_rec_box () { if (rec_active && rec_rects.size() > 0) { diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index 7011801560..15e354bdab 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -102,6 +102,7 @@ protected: //private: (FIXME?) void transport_changed(); + void transport_looped(); void rec_enable_changed(); void sess_rec_enable_changed(); virtual void setup_rec_box () = 0; diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 1bf94a4494..aaf5461361 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -227,6 +227,7 @@ class AudioDiskstream : public Diskstream void finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList>); void transport_stopped (struct tm&, time_t, bool abort); + void transport_looped (nframes_t transport_frame); void init (Diskstream::Flag); diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 3dd6555011..85fc3d3371 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -205,6 +205,7 @@ class Diskstream : public SessionObject virtual void playlist_deleted (boost::weak_ptr<Playlist>); virtual void transport_stopped (struct tm&, time_t, bool abort) = 0; + virtual void transport_looped (nframes_t transport_frame) = 0; struct CaptureInfo { uint32_t start; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 1fea324406..f0a175c624 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -351,6 +351,7 @@ class Session : public PBD::StatefulDestructible sigc::signal<void,nframes_t> PositionChanged; /* sent after any non-sequential motion */ sigc::signal<void> DurationChanged; sigc::signal<void> HaltOnXrun; + sigc::signal<void> TransportLooped; sigc::signal<void,RouteList&> RouteAdded; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 7e583afeb7..d0e2b24263 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -465,7 +465,7 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram } - if (_flags & Recordable) { + if (recordable() && destructive()) { boost::shared_ptr<ChannelList> c = channels.reader(); for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { @@ -594,7 +594,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ /* |--------| recrange -------------- transrange */ - rec_nframes = last_recordable_frame - last_recordable_frame; + rec_nframes = last_recordable_frame - first_recordable_frame; rec_offset = first_recordable_frame - transport_frame; break; } @@ -1640,6 +1640,57 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca } void +AudioDiskstream::transport_looped (nframes_t transport_frame) +{ + if (was_recording) { + // all we need to do is finish this capture, with modified capture length + boost::shared_ptr<ChannelList> c = channels.reader(); + + // adjust the capture length knowing that the data will be recorded to disk + // only necessary after the first loop where we're recording + if (capture_info.size() == 0) { + capture_captured += _capture_offset; + + if (_alignment_style == ExistingMaterial) { + capture_captured += _session.worst_output_latency(); + } else { + capture_captured += _roll_delay; + } + } + + finish_capture (true, c); + + // the next region will start recording via the normal mechanism + // we'll set the start position to the current transport pos + // 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; + was_recording = true; + + if (recordable() && destructive()) { + for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) { + + RingBufferNPT<CaptureTransition>::rw_vector transvec; + (*chan)->capture_transition_buf->get_write_vector(&transvec); + + if (transvec.len[0] > 0) { + transvec.buf[0]->type = CaptureStart; + transvec.buf[0]->capture_val = capture_start_frame; + (*chan)->capture_transition_buf->increment_write_ptr(1); + } + else { + // bad! + fatal << X_("programming error: capture_transition_buf is full on rec loop! inconceivable!") + << endmsg; + } + } + } + + } +} + +void AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList> c) { was_recording = false; @@ -1654,7 +1705,6 @@ AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<Chan RingBufferNPT<CaptureTransition>::rw_vector transvec; (*chan)->capture_transition_buf->get_write_vector(&transvec); - if (transvec.len[0] > 0) { transvec.buf[0]->type = CaptureEnd; transvec.buf[0]->capture_val = capture_captured; @@ -2348,7 +2398,7 @@ AudioDiskstream::ChannelInfo::ChannelInfo (nframes_t bufsize, nframes_t speed_si playback_buf = new RingBufferNPT<Sample> (bufsize); capture_buf = new RingBufferNPT<Sample> (bufsize); - capture_transition_buf = new RingBufferNPT<CaptureTransition> (128); + capture_transition_buf = new RingBufferNPT<CaptureTransition> (256); /* touch the ringbuffer buffers, which will cause them to be mapped into locked physical RAM if diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 10860b0c88..6df71611ce 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1120,7 +1120,7 @@ Session::disable_record (bool rt_context, bool force) if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) { - if (!Config->get_latched_record_enable () || force) { + if ((!Config->get_latched_record_enable () && !play_loop) || force) { g_atomic_int_set (&_record_status, Disabled); } else { if (rs == Recording) { @@ -1155,15 +1155,18 @@ Session::disable_record (bool rt_context, bool force) void Session::step_back_from_record () { - g_atomic_int_set (&_record_status, Enabled); + /* XXX really atomic compare+swap here */ + if (g_atomic_int_get (&_record_status) == Recording) { + g_atomic_int_set (&_record_status, Enabled); - if (Config->get_monitoring_model() == HardwareMonitoring) { - boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); - - for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if (Config->get_auto_input() && (*i)->record_enabled ()) { - //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; - (*i)->monitor_input (false); + if (Config->get_monitoring_model() == HardwareMonitoring) { + boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + if (Config->get_auto_input() && (*i)->record_enabled ()) { + //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; + (*i)->monitor_input (false); + } } } } diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 44ca7f1235..dc71a40ca2 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -489,7 +489,7 @@ Session::follow_slave (nframes_t nframes, nframes_t offset) cerr << "delta = " << (int) (dir * this_delta) << " speed = " << slave_speed << " ts = " << _transport_speed - << " M@"<< slave_transport_frame << " S@" << _transport_frame + << " M@ "<< slave_transport_frame << " S@ " << _transport_frame << " avgdelta = " << average_slave_delta << endl; #endif diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 60cc8b91ae..7deb40c161 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -386,7 +386,8 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) _transport_frame = last_stop_frame; - if (synced_to_jack()) { + if (synced_to_jack() && !play_loop) { + // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl; _engine.transport_locate (_transport_frame); } } @@ -422,14 +423,16 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) /* XXX its a little odd that we're doing this here when realtime_stop(), which has already executed, will have done this. + JLC - so let's not because it seems unnecessary and breaks loop record */ - +#if 0 if (!Config->get_latched_record_enable()) { g_atomic_int_set (&_record_status, Disabled); } else { g_atomic_int_set (&_record_status, Enabled); } RecordStateChanged (); /* emit signal */ +#endif } if ((post_transport_work & PostTransportLocate) && get_record_enabled()) { @@ -615,7 +618,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, void Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop) { - if (actively_recording()) { + if (actively_recording() && !with_loop) { return; } @@ -711,6 +714,22 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w // cancel looping directly, this is called from event handling context set_play_loop (false); } + else if (al && _transport_frame == al->start()) { + if (with_loop) { + // this is only necessary for seamless looping + + boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader(); + + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { + if ((*i)->record_enabled ()) { + // tell it we've looped, so it can deal with the record state + (*i)->transport_looped(_transport_frame); + } + } + } + + TransportLooped(); // EMIT SIGNAL + } } loop_changing = false; @@ -893,7 +912,9 @@ Session::start_transport () break; case Recording: - disable_record (false); + if (!play_loop) { + disable_record (false); + } break; default: |