summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-06-16 08:44:03 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2015-06-16 08:44:03 -0400
commit90220998af4f9683d696b511a09b34034e799093 (patch)
treee974251993f9bf8b33c26bdeb117a8759b476d77 /libs
parentd65f03d07455c4ea38084af71a38c383bd2b3e19 (diff)
add Record-Safe feature to libardour (from Nikolay Polyanovskii)
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audio_diskstream.h1
-rw-r--r--libs/ardour/ardour/diskstream.h8
-rw-r--r--libs/ardour/ardour/midi_diskstream.h1
-rw-r--r--libs/ardour/ardour/midi_track.h1
-rw-r--r--libs/ardour/ardour/route.h2
-rw-r--r--libs/ardour/ardour/session.h2
-rw-r--r--libs/ardour/ardour/track.h4
-rw-r--r--libs/ardour/audio_diskstream.cc33
-rw-r--r--libs/ardour/diskstream.cc21
-rw-r--r--libs/ardour/midi_diskstream.cc26
-rw-r--r--libs/ardour/midi_track.cc10
-rw-r--r--libs/ardour/session_rtevents.cc30
-rw-r--r--libs/ardour/track.cc40
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 */