diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2015-06-16 08:44:03 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2015-06-16 08:44:03 -0400 |
commit | 90220998af4f9683d696b511a09b34034e799093 (patch) | |
tree | e974251993f9bf8b33c26bdeb117a8759b476d77 | |
parent | d65f03d07455c4ea38084af71a38c383bd2b3e19 (diff) |
add Record-Safe feature to libardour (from Nikolay Polyanovskii)
-rw-r--r-- | libs/ardour/ardour/audio_diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/diskstream.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_track.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/route.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/track.h | 4 | ||||
-rw-r--r-- | libs/ardour/audio_diskstream.cc | 33 | ||||
-rw-r--r-- | libs/ardour/diskstream.cc | 21 | ||||
-rw-r--r-- | libs/ardour/midi_diskstream.cc | 26 | ||||
-rw-r--r-- | libs/ardour/midi_track.cc | 10 | ||||
-rw-r--r-- | libs/ardour/session_rtevents.cc | 30 | ||||
-rw-r--r-- | libs/ardour/track.cc | 40 |
13 files changed, 171 insertions, 8 deletions
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index f93c949a38..f48204d7ab 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -73,6 +73,7 @@ class LIBARDOUR_API AudioDiskstream : public Diskstream } void set_record_enabled (bool yn); + void set_record_safe (bool yn); int set_destructive (bool yn); int set_non_layered (bool yn); bool can_become_destructive (bool& requires_bounce) const; diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index cde21b209f..fc41d10160 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -104,7 +104,9 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream void set_roll_delay (framecnt_t); bool record_enabled() const { return g_atomic_int_get (&_record_enabled); } + bool record_safe () const { return g_atomic_int_get (&_record_safe); } virtual void set_record_enabled (bool yn) = 0; + virtual void set_record_safe (bool yn) = 0; bool destructive() const { return _flags & Destructive; } virtual int set_destructive (bool /*yn*/) { return -1; } @@ -176,6 +178,7 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream } PBD::Signal0<void> RecordEnableChanged; + PBD::Signal0<void> RecordSafeChanged; PBD::Signal0<void> SpeedChanged; PBD::Signal0<void> ReverseChanged; /* Emitted when this diskstream is set to use a different playlist */ @@ -263,6 +266,8 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream void engage_record_enable (); void disengage_record_enable (); + void engage_record_safe (); + void disengage_record_safe (); virtual bool prep_record_enable () = 0; virtual bool prep_record_disable () = 0; @@ -286,7 +291,8 @@ class LIBARDOUR_API Diskstream : public SessionObject, public PublicDiskstream boost::shared_ptr<Playlist> _playlist; - mutable gint _record_enabled; + gint _record_enabled; + gint _record_safe; double _visible_speed; double _actual_speed; /* items needed for speed change logic */ diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 58b74bd54f..6610708581 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -70,6 +70,7 @@ class LIBARDOUR_API MidiDiskstream : public Diskstream void flush_playback (framepos_t, framepos_t); void set_record_enabled (bool yn); + void set_record_safe (bool yn); void reset_tracker (); void resolve_tracker (Evoral::EventSink<framepos_t>& buffer, framepos_t time); diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index f2542f0f6b..2ba57e4e01 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -51,6 +51,7 @@ public: boost::shared_ptr<Diskstream> create_diskstream (); void set_diskstream (boost::shared_ptr<Diskstream>); void set_record_enabled (bool yn, void *src); + void set_record_safe (bool yn, void *src); DataType data_type () const { return DataType::MIDI; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 8237219020..cce1e152a2 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -129,6 +129,8 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou virtual void set_record_enabled (bool /*yn*/, void * /*src*/) {} virtual bool record_enabled() const { return false; } + virtual void set_record_safe (bool yn, void *src) {} + virtual bool record_safe () const {return false; } virtual void nonrealtime_handle_transport_stopped (bool abort, bool did_locate, bool flush_processors); virtual void realtime_handle_transport_stopped () {} virtual void realtime_locate () {} diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 8379ed7ae5..bbc82939c7 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -700,6 +700,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); + void set_record_safe (boost::shared_ptr<RouteList>, bool yn, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_exclusive_input_active (boost::shared_ptr<RouteList> rt, bool onoff, bool flip_others=false); @@ -1699,6 +1700,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop void rt_set_listen (boost::shared_ptr<RouteList>, bool yn, bool group_override); void rt_set_solo_isolated (boost::shared_ptr<RouteList>, bool yn, bool group_override); void rt_set_record_enabled (boost::shared_ptr<RouteList>, bool yn, bool group_override); + void rt_set_record_safe (boost::shared_ptr<RouteList>, bool yn, bool group_override); void rt_set_monitoring (boost::shared_ptr<RouteList>, MonitorChoice, bool group_override); /** temporary list of Diskstreams used only during load of 2.X sessions */ diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 5e05ec373c..f699b5d5d3 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -107,7 +107,9 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream boost::shared_ptr<AutomationControl> rec_enable_control() { return _rec_enable_control; } bool record_enabled() const; + bool record_safe () const; void set_record_enabled (bool yn, void *src); + void set_record_safe (bool yn, void *src); void prep_record_enabled (bool yn, void *src); bool using_diskstream_id (PBD::ID) const; @@ -165,6 +167,7 @@ class LIBARDOUR_API Track : public Route, public PublicDiskstream /* Emitted when our diskstream is set to use a different playlist */ PBD::Signal0<void> PlaylistChanged; PBD::Signal0<void> RecordEnableChanged; + PBD::Signal0<void> RecordSafeChanged; PBD::Signal0<void> SpeedChanged; PBD::Signal0<void> AlignmentStyleChanged; @@ -227,6 +230,7 @@ private: void diskstream_playlist_changed (); void diskstream_record_enable_changed (); + void diskstream_record_safe_changed (); void diskstream_speed_changed (); void diskstream_alignment_style_changed (); void parameter_changed (std::string const & p); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 7e673c99d1..00e1f9298f 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1736,7 +1736,7 @@ AudioDiskstream::finish_capture (boost::shared_ptr<ChannelList> c) void AudioDiskstream::set_record_enabled (bool yn) { - if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) { + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0 || record_safe ()) { return; } @@ -1761,10 +1761,39 @@ AudioDiskstream::set_record_enabled (bool yn) } } +void +AudioDiskstream::set_record_safe (bool yn) +{ + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) { + return; + } + + /* can't rec-safe in destructive mode if transport is before start ???? + REQUIRES REVIEW */ + + if (destructive() && yn && _session.transport_frame() < _session.current_start_frame()) { + return; + } + + /* yes, i know that this not proof against race conditions, but its + good enough. i think. + */ + + if (record_safe () != yn) { + if (yn) { + engage_record_safe (); + } else { + disengage_record_safe (); + } + + RecordSafeChanged (); /* EMIT SIGNAL */ + } +} + bool AudioDiskstream::prep_record_enable () { - if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) { + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0 || record_safe ()) { // REQUIRES REVIEW "|| record_safe ()" return false; } diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 49d9d62ec4..9f3322dade 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -64,6 +64,7 @@ Diskstream::Diskstream (Session &sess, const string &name, Flag flag) , i_am_the_modifier (0) , _track (0) , _record_enabled (0) + , _record_safe (0) , _visible_speed (1.0f) , _actual_speed (1.0f) , _buffer_reallocation_required (false) @@ -102,6 +103,7 @@ Diskstream::Diskstream (Session& sess, const XMLNode& /*node*/) , i_am_the_modifier (0) , _track (0) , _record_enabled (0) + , _record_safe (0) , _visible_speed (1.0f) , _actual_speed (1.0f) , _buffer_reallocation_required (false) @@ -468,6 +470,7 @@ Diskstream::get_state () snprintf (buf, sizeof(buf), "%f", _visible_speed); node->add_property ("speed", buf); node->add_property ("capture-alignment", enum_2_string (_alignment_choice)); + node->add_property ("record-safe", _record_safe ? "yes" : "no"); if (_extra_xml) { node->add_child_copy (*_extra_xml); @@ -516,8 +519,12 @@ Diskstream::set_state (const XMLNode& node, int /*version*/) non_realtime_set_speed (); } } + + if ((prop = node.property ("record-safe")) != 0) { + _record_safe = PBD::string_is_affirmative (prop->value()) ? 1 : 0; + } - return 0; + return 0; } void @@ -769,6 +776,18 @@ Diskstream::disengage_record_enable () g_atomic_int_set (&_record_enabled, 0); } +void +Diskstream::engage_record_safe () +{ + g_atomic_int_set (&_record_safe, 1); +} + +void +Diskstream::disengage_record_safe () +{ + g_atomic_int_set (&_record_safe, 0); +} + framecnt_t Diskstream::default_disk_read_chunk_frames() { diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index f17b38d7ea..a2a80f780b 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -1143,7 +1143,7 @@ MidiDiskstream::finish_capture () void MidiDiskstream::set_record_enabled (bool yn) { - if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0) { + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0 || record_safe ()) { return; } @@ -1162,10 +1162,32 @@ MidiDiskstream::set_record_enabled (bool yn) } } +void +MidiDiskstream::set_record_safe (bool yn) +{ + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0) { // REQUIRES REVIEW + return; + } + + /* yes, i know that this not proof against race conditions, but its + good enough. i think. + */ + + if (record_safe () != yn) { + if (yn) { + engage_record_safe (); + } else { + disengage_record_safe (); + } + + RecordSafeChanged (); /* EMIT SIGNAL */ + } +} + bool MidiDiskstream::prep_record_enable () { - if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0) { + if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_midi() == 0 || record_safe ()) { // REQUIRES REVIEW "|| record_safe ()" return false; } diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 3f15464481..487eb2025c 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -112,6 +112,16 @@ MidiTrack::set_record_enabled (bool yn, void *src) } void +MidiTrack::set_record_safe (bool yn, void *src) +{ + if (_step_editing) { /* REQUIRES REVIEW */ + return; + } + + Track::set_record_safe (yn, src); +} + +void MidiTrack::set_diskstream (boost::shared_ptr<Diskstream> ds) { /* We have to do this here, as Track::set_diskstream will cause a buffer refill, diff --git a/libs/ardour/session_rtevents.cc b/libs/ardour/session_rtevents.cc index 4bd7c2da9a..11d8319c0d 100644 --- a/libs/ardour/session_rtevents.cc +++ b/libs/ardour/session_rtevents.cc @@ -197,7 +197,7 @@ Session::set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, SessionEv */ for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { - if ((*i)->is_auditioner()) { + if ((*i)->is_auditioner() || (*i)->record_safe ()) { continue; } @@ -215,7 +215,7 @@ void Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool group_override) { for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { - if ((*i)->is_auditioner()) { + if ((*i)->is_auditioner() || (*i)->record_safe ()) { continue; } @@ -229,6 +229,32 @@ Session::rt_set_record_enabled (boost::shared_ptr<RouteList> rl, bool yn, bool g set_dirty (); } + +void +Session::set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, SessionEvent::RTeventCallback after, bool group_override) +{ + set_record_enabled (rl, false, after, group_override); + queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_record_safe)); +} + +void +Session::rt_set_record_safe (boost::shared_ptr<RouteList> rl, bool yn, bool group_override) +{ + for (RouteList::iterator i = rl->begin (); i != rl->end (); ++i) { + if ((*i)->is_auditioner ()) { // REQUIRES REVIEW Can audiotioner be in Record Safe mode? + continue; + } + + boost::shared_ptr<Track> t; + + if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) { + t->set_record_safe (yn, (group_override ? (void*) t->route_group () : (void *) this)); + } + } + + set_dirty (); +} + void Session::process_rtop (SessionEvent* ev) { diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 1426c3926c..92ea993470 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -232,6 +232,10 @@ Track::can_record() void Track::prep_record_enabled (bool yn, void *src) { + if (yn && record_safe ()) { + return; + } + if (!_session.writable()) { return; } @@ -272,6 +276,10 @@ Track::prep_record_enabled (bool yn, void *src) void Track::set_record_enabled (bool yn, void *src) { + if (_diskstream->record_safe ()) { + return; + } + if (!_session.writable()) { return; } @@ -290,6 +298,31 @@ Track::set_record_enabled (bool yn, void *src) _rec_enable_control->Changed (); } +bool +Track::record_safe () const +{ + return _diskstream && _diskstream->record_safe (); +} + +void +Track::set_record_safe (bool yn, void *src) +{ + if (!_session.writable()) { /* REQUIRES REVIEW */ + return; + } + + if (_freeze_record.state == Frozen) { /* REQUIRES REVIEW */ + return; + } + + if (_route_group && src != _route_group && _route_group->is_active() && _route_group->is_recenable()) { + _route_group->apply (&Track::set_record_safe, yn, _route_group); + return; + } + + _diskstream->set_record_safe (yn); +} + void Track::parameter_changed (string const & p) { @@ -558,6 +591,7 @@ Track::set_diskstream (boost::shared_ptr<Diskstream> ds) ds->PlaylistChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_playlist_changed, this)); diskstream_playlist_changed (); ds->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_record_enable_changed, this)); + ds->RecordSafeChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_record_safe_changed, this)); ds->SpeedChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_speed_changed, this)); ds->AlignmentStyleChanged.connect_same_thread (*this, boost::bind (&Track::diskstream_alignment_style_changed, this)); } @@ -575,6 +609,12 @@ Track::diskstream_record_enable_changed () } void +Track::diskstream_record_safe_changed () +{ + RecordSafeChanged (); /* EMIT SIGNAL */ +} + +void Track::diskstream_speed_changed () { SpeedChanged (); /* EMIT SIGNAL */ |