using namespace ARDOUR;
using namespace PBD;
+nframes_t IO::_automation_interval = 0;
const string IO::state_node_name = "IO";
bool IO::connecting_legal = false;
bool IO::ports_legal = false;
apply_gain_automation = false;
_ignore_gain_on_deliver = false;
+ last_automation_snapshot = 0;
+
_gain_automation_state = Off;
_gain_automation_style = Absolute;
_session.add_controllable (&_gain_control);
}
+IO::IO (Session& s, const XMLNode& node, DataType dt)
+ : _session (s),
+ _default_type (dt),
+ _gain_control (X_("gaincontrol"), *this),
+ _gain_automation_curve (0, 0, 0) // all reset in set_state()
+{
+ _panner = 0;
+ deferred_state = 0;
+ no_panner_reset = false;
+ _desired_gain = 1.0;
+ _gain = 1.0;
+ _input_connection = 0;
+ _output_connection = 0;
+ _ninputs = 0;
+ _noutputs = 0;
+
+ apply_gain_automation = false;
+ _ignore_gain_on_deliver = false;
+
+ set_state (node);
+
+ {
+ // IO::Meter is emitted from another thread so the
+ // Meter signal must be protected.
+ Glib::Mutex::Lock guard (m_meter_signal_lock);
+ m_meter_connection = Meter.connect (mem_fun (*this, &IO::meter));
+ }
+
+ _session.add_controllable (&_gain_control);
+}
+
IO::~IO ()
{
Glib::Mutex::Lock guard (m_meter_signal_lock);
dst = (*o)->get_buffer (nframes) + offset;
src = bufs[min(nbufs,i)];
- if (dg != _gain || actual_gain == 1.0f) {
- memcpy (dst, src, sizeof (Sample) * nframes);
- } else if (actual_gain == 0.0f) {
- memset (dst, 0, sizeof (Sample) * nframes);
- } else {
+ if (_name == "Audio 2") {
for (nframes_t x = 0; x < nframes; ++x) {
- dst[x] = src[x] * actual_gain;
+ dst[x] = 0.7;
+ }
+
+ } else {
+
+ if (dg != _gain || actual_gain == 1.0f) {
+ memcpy (dst, src, sizeof (Sample) * nframes);
+ } else if (actual_gain == 0.0f) {
+ memset (dst, 0, sizeof (Sample) * nframes);
+ } else {
+ for (nframes_t x = 0; x < nframes; ++x) {
+ dst[x] = src[x] * actual_gain;
+ }
}
}
IO::panners_became_legal ()
{
_panner->reset (_noutputs, pans_required());
+ _panner->load (); // automation
panner_legal_c.disconnect ();
return 0;
}
snprintf (buf, sizeof (buf), "0x%x", ARDOUR::Off);
}
- node->add_property ("automation-state", buf);
- snprintf (buf, sizeof (buf), "0x%x", (int) _gain_automation_curve.automation_style());
- node->add_property ("automation-style", buf);
-
return *node;
}
-
-
int
IO::set_state (const XMLNode& node)
{
_gain = _desired_gain;
}
+ if ((prop = node.property ("automation-state")) != 0 || (prop = node.property ("automation-style")) != 0) {
+ /* old school automation handling */
+ }
+
for (iter = node.children().begin(); iter != node.children().end(); ++iter) {
if ((*iter)->name() == "Panner") {
+ if (_panner == 0) {
+ _panner = new Panner (_name, _session);
+ }
_panner->set_state (**iter);
}
}
}
- if ((prop = node.property ("automation-state")) != 0) {
-
- long int x;
- x = strtol (prop->value().c_str(), 0, 16);
- set_gain_automation_state (AutoState (x));
- }
-
- if ((prop = node.property ("automation-style")) != 0) {
-
- long int x;
- x = strtol (prop->value().c_str(), 0, 16);
- set_gain_automation_style (AutoStyle (x));
- }
-
if (ports_legal) {
if (create_ports (node)) {
pending_state_node = new XMLNode (node);
}
+ last_automation_snapshot = 0;
+
return 0;
}
return (_gain_automation_curve.get_state ());
}
+int
+IO::load_automation (string path)
+{
+ string fullpath;
+ ifstream in;
+ char line[128];
+ uint32_t linecnt = 0;
+ float version;
+ LocaleGuard lg (X_("POSIX"));
+
+ fullpath = _session.automation_dir();
+ fullpath += path;
+
+ in.open (fullpath.c_str());
+
+ if (!in) {
+ fullpath = _session.automation_dir();
+ fullpath += _session.snap_name();
+ fullpath += '-';
+ fullpath += path;
+
+ in.open (fullpath.c_str());
+
+ if (!in) {
+ error << string_compose(_("%1: cannot open automation event file \"%2\""), _name, fullpath) << endmsg;
+ return -1;
+ }
+ }
+
+ clear_automation ();
+
+ while (in.getline (line, sizeof(line), '\n')) {
+ char type;
+ jack_nframes_t when;
+ double value;
+
+ if (++linecnt == 1) {
+ if (memcmp (line, "version", 7) == 0) {
+ if (sscanf (line, "version %f", &version) != 1) {
+ error << string_compose(_("badly formed version number in automation event file \"%1\""), path) << endmsg;
+ return -1;
+ }
+ } else {
+ error << string_compose(_("no version information in automation event file \"%1\""), path) << endmsg;
+ return -1;
+ }
+
+ continue;
+ }
+
+ if (sscanf (line, "%c %" PRIu32 " %lf", &type, &when, &value) != 3) {
+ warning << string_compose(_("badly formatted automation event record at line %1 of %2 (ignored)"), linecnt, path) << endmsg;
+ continue;
+ }
+
+ switch (type) {
+ case 'g':
+ _gain_automation_curve.fast_simple_add (when, value);
+ break;
+
+ case 's':
+ break;
+
+ case 'm':
+ break;
+
+ case 'p':
+ /* older (pre-1.0) versions of ardour used this */
+ break;
+
+ default:
+ warning << _("dubious automation event found (and ignored)") << endmsg;
+ }
+ }
+
+ return 0;
+}
+
int
IO::connecting_became_legal ()
{
if (state != _gain_automation_curve.automation_state()) {
changed = true;
+ last_automation_snapshot = 0;
_gain_automation_curve.set_automation_state (state);
if (state != Off) {
}
+void
+IO::automation_snapshot (nframes_t now)
+{
+ if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) {
+
+ if (gain_automation_recording()) {
+ _gain_automation_curve.rt_add (now, gain());
+ }
+
+ _panner->snapshot (now);
+
+ last_automation_snapshot = now;
+ }
+}
+
void
IO::transport_stopped (nframes_t frame)
{