X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fpanner.cc;h=a7cf40519008d64c5b702a4c0c01d573b13c4af3;hb=e666c8e98fb95a69afae8818f22c25094adae7eb;hp=3e57037d6fb66a449425fab092a2d42c14500ee5;hpb=133a66920bbdd3bc11bd4ae866048b0f1f52ecd4;p=ardour.git diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index 3e57037d6f..a7cf405190 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -40,9 +40,11 @@ #include #include #include +#include #include #include +#include #include "i18n.h" @@ -65,20 +67,20 @@ static pan_t direct_control_to_pan (double fract) { return fract; } -static double direct_pan_to_control (pan_t val) { - return val; -} -StreamPanner::StreamPanner (Panner& p, Parameter param) +//static double direct_pan_to_control (pan_t val) { +// return val; +//} + +StreamPanner::StreamPanner (Panner& p, Evoral::Parameter param) : parent (p) - , _control (new PanControllable(p.session(), X_("panner"), *this, param)) { assert(param.type() != NullAutomation); _muted = false; - parent.session().add_controllable (_control); - + _control = boost::dynamic_pointer_cast( parent.control( param, true ) ); + x = 0.5; y = 0.5; z = 0.5; @@ -89,29 +91,16 @@ StreamPanner::~StreamPanner () } void -StreamPanner::PanControllable::set_value (float val) +Panner::PanControllable::set_value (float val) { - panner.set_position (direct_control_to_pan (val)); + panner.streampanner(parameter().id()).set_position (direct_control_to_pan (val)); + AutomationControl::set_value(val); } float -StreamPanner::PanControllable::get_value (void) const +Panner::PanControllable::get_value (void) const { - float xpos; - panner.get_effective_position (xpos); - return direct_pan_to_control (xpos); -} - -bool -StreamPanner::PanControllable::can_send_feedback () const -{ - AutoState astate = panner.get_parent().automation_state (); - - if ((astate == Play) || (astate == Touch && !panner.get_parent().touching())) { - return true; - } - - return false; + return AutomationControl::get_value(); } void @@ -191,7 +180,7 @@ StreamPanner::add_state (XMLNode& node) /*---------------------------------------------------------------------- */ -BaseStereoPanner::BaseStereoPanner (Panner& p, Parameter param) +BaseStereoPanner::BaseStereoPanner (Panner& p, Evoral::Parameter param) : StreamPanner (p, param) { } @@ -228,7 +217,7 @@ BaseStereoPanner::load (istream& in, string path, uint32_t& linecnt) /* now that we are done loading */ - _control->list()->StateChanged (); + ((AutomationList*)_control->list().get())->StateChanged (); return 0; } @@ -269,7 +258,7 @@ BaseStereoPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain pan = left * gain_coeff; - mix_buffers_with_gain(dst+n,src+n,nframes-n,pan); + mix_buffers_with_gain (dst+n,src+n,nframes-n,pan); } else { @@ -348,7 +337,7 @@ BaseStereoPanner::distribute (AudioBuffer& srcbuf, BufferSet& obufs, gain_t gain /*---------------------------------------------------------------------- */ -EqualPowerStereoPanner::EqualPowerStereoPanner (Panner& p, Parameter param) +EqualPowerStereoPanner::EqualPowerStereoPanner (Panner& p, Evoral::Parameter param) : BaseStereoPanner (p, param) { update (); @@ -388,7 +377,7 @@ EqualPowerStereoPanner::update () desired_right = panR * (scale * panR + 1.0f - scale); effective_x = x; - _control->set_value(x); + //_control->set_value(x); } void @@ -416,7 +405,6 @@ EqualPowerStereoPanner::distribute_automated (AudioBuffer& srcbuf, BufferSet& ob if (nframes > 0) { effective_x = buffers[0][nframes-1]; - _control->set_value(effective_x); // signal, update UI } if (_muted) { @@ -463,7 +451,7 @@ EqualPowerStereoPanner::distribute_automated (AudioBuffer& srcbuf, BufferSet& ob } StreamPanner* -EqualPowerStereoPanner::factory (Panner& parent, Parameter param) +EqualPowerStereoPanner::factory (Panner& parent, Evoral::Parameter param) { return new EqualPowerStereoPanner (parent, param); } @@ -485,9 +473,7 @@ EqualPowerStereoPanner::state (bool full_state) root->add_property (X_("x"), buf); root->add_property (X_("type"), EqualPowerStereoPanner::name); - XMLNode* autonode = new XMLNode (X_("Automation")); - autonode->add_child_nocopy (_control->list()->state (full_state)); - root->add_child_nocopy (*autonode); + // XXX: dont save automation here... its part of the automatable panner now. StreamPanner::add_state (*root); @@ -519,9 +505,9 @@ EqualPowerStereoPanner::set_state (const XMLNode& node) } else if ((*iter)->name() == X_("Automation")) { - _control->list()->set_state (*((*iter)->children().front())); + _control->alist()->set_state (*((*iter)->children().front())); - if (_control->list()->automation_state() != Off) { + if (_control->alist()->automation_state() != Off) { set_position (_control->list()->eval (parent.session().transport_frame())); } } @@ -532,7 +518,7 @@ EqualPowerStereoPanner::set_state (const XMLNode& node) /*----------------------------------------------------------------------*/ -Multi2dPanner::Multi2dPanner (Panner& p, Parameter param) +Multi2dPanner::Multi2dPanner (Panner& p, Evoral::Parameter param) : StreamPanner (p, param) { update (); @@ -572,7 +558,6 @@ Multi2dPanner::update () } effective_x = x; - _control->set_value(x); } void @@ -650,7 +635,7 @@ Multi2dPanner::distribute_automated (AudioBuffer& src, BufferSet& obufs, } StreamPanner* -Multi2dPanner::factory (Panner& p, Parameter param) +Multi2dPanner::factory (Panner& p, Evoral::Parameter param) { return new Multi2dPanner (p, param); } @@ -716,8 +701,9 @@ Multi2dPanner::set_state (const XMLNode& node) /*---------------------------------------------------------------------- */ Panner::Panner (string name, Session& s) - : _session (s) + : Processor(s, name, PostFader) { + //set_name_old_auto (name); set_name (name); _linked = false; @@ -749,6 +735,7 @@ Panner::set_link_direction (LinkDirection ld) } } + void Panner::set_bypassed (bool yn) { @@ -764,13 +751,19 @@ Panner::reset (uint32_t nouts, uint32_t npans) { uint32_t n; bool changed = false; + bool do_not_and_did_not_need_panning = ((nouts < 2) && (outputs.size() < 2)); + + /* if new and old config don't need panning, or if + the config hasn't changed, we're done. + */ - if (nouts < 2 || (nouts == outputs.size() && npans == size())) { + if (do_not_and_did_not_need_panning || + ((nouts == outputs.size()) && (npans == _streampanners.size()))) { return; } - n = size(); - clear (); + n = _streampanners.size(); + clear_panners (); if (n != npans) { changed = true; @@ -783,24 +776,30 @@ Panner::reset (uint32_t nouts, uint32_t npans) changed = true; } + if (nouts < 2) { + /* no need for panning with less than 2 outputs */ + goto send_changed; + } + switch (nouts) { case 0: + /* XXX: this can never happen */ break; case 1: + /* XXX: this can never happen */ fatal << _("programming error:") << X_("Panner::reset() called with a single output") << endmsg; /*NOTREACHED*/ break; - case 2: - /* line */ + case 2: // line outputs.push_back (Output (0, 0)); outputs.push_back (Output (1.0, 0)); for (n = 0; n < npans; ++n) { - push_back (new EqualPowerStereoPanner (*this, Parameter(PanAutomation, n))); + _streampanners.push_back (new EqualPowerStereoPanner (*this, Evoral::Parameter(PanAutomation, 0, n))); } break; @@ -810,7 +809,7 @@ Panner::reset (uint32_t nouts, uint32_t npans) outputs.push_back (Output (1.0, 1.0)); for (n = 0; n < npans; ++n) { - push_back (new Multi2dPanner (*this, Parameter(PanAutomation, n))); + _streampanners.push_back (new Multi2dPanner (*this, Evoral::Parameter(PanAutomation, 0, n))); } break; @@ -822,7 +821,7 @@ Panner::reset (uint32_t nouts, uint32_t npans) outputs.push_back (Output (0, 1.0)); for (n = 0; n < npans; ++n) { - push_back (new Multi2dPanner (*this, Parameter(PanAutomation, n))); + _streampanners.push_back (new Multi2dPanner (*this, Evoral::Parameter(PanAutomation, 0, n))); } break; @@ -835,7 +834,7 @@ Panner::reset (uint32_t nouts, uint32_t npans) outputs.push_back (Output (0.5, 0.75)); for (n = 0; n < npans; ++n) { - push_back (new Multi2dPanner (*this, Parameter(PanAutomation, n))); + _streampanners.push_back (new Multi2dPanner (*this, Evoral::Parameter(PanAutomation, 0, n))); } break; @@ -847,13 +846,13 @@ Panner::reset (uint32_t nouts, uint32_t npans) } for (n = 0; n < npans; ++n) { - push_back (new Multi2dPanner (*this, Parameter(PanAutomation, n))); + _streampanners.push_back (new Multi2dPanner (*this, Evoral::Parameter(PanAutomation, 0, n))); } break; } - for (iterator x = begin(); x != end(); ++x) { + for (std::vector::iterator x = _streampanners.begin(); x != _streampanners.end(); ++x) { (*x)->update (); } @@ -869,21 +868,22 @@ Panner::reset (uint32_t nouts, uint32_t npans) float left; float right; - front()->get_position (left); - back()->get_position (right); + _streampanners.front()->get_position (left); + _streampanners.back()->get_position (right); if (changed || ((left == 0.5) && (right == 0.5))) { - front()->set_position (0.0); - front()->pan_control()->list()->reset_default (0.0); + _streampanners.front()->set_position (0.0); + _streampanners.front()->pan_control()->list()->reset_default (0.0); - back()->set_position (1.0); - back()->pan_control()->list()->reset_default (1.0); + _streampanners.back()->set_position (1.0); + _streampanners.back()->pan_control()->list()->reset_default (1.0); changed = true; } } + send_changed: if (changed) { Changed (); /* EMIT SIGNAL */ } @@ -895,29 +895,31 @@ void Panner::remove (uint32_t which) { vector::iterator i; - for (i = begin(); i != end() && which; ++i, --which); + for (i = _streampanners.begin(); i != _streampanners.end() && which; ++i, --which); - if (i != end()) { + if (i != _streampanners.end()) { delete *i; - erase (i); + _streampanners.erase (i); } } + +/** Remove all our StreamPanners */ void -Panner::clear () +Panner::clear_panners () { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { delete *i; } - vector::clear (); + _streampanners.clear (); } void Panner::set_automation_style (AutoStyle style) { - for (vector::iterator i = begin(); i != end(); ++i) { - (*i)->pan_control()->list()->set_automation_style (style); + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { + ((AutomationList*)(*i)->pan_control()->list().get())->set_automation_style (style); } _session.set_dirty (); } @@ -925,8 +927,8 @@ Panner::set_automation_style (AutoStyle style) void Panner::set_automation_state (AutoState state) { - for (vector::iterator i = begin(); i != end(); ++i) { - (*i)->pan_control()->list()->set_automation_state (state); + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { + ((AutomationList*)(*i)->pan_control()->list().get())->set_automation_state (state); } _session.set_dirty (); } @@ -935,7 +937,7 @@ AutoState Panner::automation_state () const { if (!empty()) { - return front()->pan_control()->list()->automation_state (); + return ((AutomationList*)_streampanners.front()->pan_control()->list().get())->automation_state (); } else { return Off; } @@ -945,43 +947,17 @@ AutoStyle Panner::automation_style () const { if (!empty()) { - return front()->pan_control()->list()->automation_style (); + return ((AutomationList*)_streampanners.front()->pan_control()->list().get())->automation_style (); } else { return Absolute; } } -void -Panner::transport_stopped (nframes_t frame) -{ - for (vector::iterator i = begin(); i != end(); ++i) { - (*i)->pan_control()->list()->reposition_for_rt_add (frame); - } -} - -void -Panner::snapshot (nframes_t now) -{ - for (vector::iterator i = begin(); i != end(); ++i) { - boost::shared_ptr list = (*i)->pan_control()->list(); - if (list->automation_write()) - list->rt_add(now, (*i)->pan_control()->get_value()); - } -} - -void -Panner::clear_automation () -{ - for (vector::iterator i = begin(); i != end(); ++i) { - (*i)->pan_control()->list()->clear (); - } - _session.set_dirty (); -} struct PanPlugins { string name; uint32_t nouts; - StreamPanner* (*factory)(Panner&, Parameter); + StreamPanner* (*factory)(Panner&, Evoral::Parameter); }; PanPlugins pan_plugins[] = { @@ -999,14 +975,15 @@ Panner::get_state (void) XMLNode& Panner::state (bool full) { - XMLNode* root = new XMLNode (X_("Panner")); - char buf[32]; + XMLNode& node = Processor::state(full); + + node.add_property ("type", "panner"); - root->add_property (X_("linked"), (_linked ? "yes" : "no")); - root->add_property (X_("link_direction"), enum_2_string (_link_direction)); - root->add_property (X_("bypassed"), (bypassed() ? "yes" : "no")); + char buf[32]; - /* add each output */ + node.add_property (X_("linked"), (_linked ? "yes" : "no")); + node.add_property (X_("link_direction"), enum_2_string (_link_direction)); + node.add_property (X_("bypassed"), (bypassed() ? "yes" : "no")); for (vector::iterator o = outputs.begin(); o != outputs.end(); ++o) { XMLNode* onode = new XMLNode (X_("Output")); @@ -1014,14 +991,15 @@ Panner::state (bool full) onode->add_property (X_("x"), buf); snprintf (buf, sizeof (buf), "%.12g", (*o).y); onode->add_property (X_("y"), buf); - root->add_child_nocopy (*onode); + node.add_child_nocopy (*onode); } - for (vector::const_iterator i = begin(); i != end(); ++i) { - root->add_child_nocopy ((*i)->state (full)); + for (vector::const_iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { + node.add_child_nocopy ((*i)->state (full)); } - return *root; + + return node; } int @@ -1031,10 +1009,18 @@ Panner::set_state (const XMLNode& node) XMLNodeConstIterator niter; const XMLProperty *prop; uint32_t i; + uint32_t num_panners = 0; StreamPanner* sp; LocaleGuard lg (X_("POSIX")); - clear (); + clear_panners (); + + Processor::set_state(node); + + ChanCount ins = ChanCount::ZERO; + ChanCount outs = ChanCount::ZERO; + + // XXX: this might not be necessary anymore outputs.clear (); if ((prop = node.property (X_("linked"))) != 0) { @@ -1045,7 +1031,7 @@ Panner::set_state (const XMLNode& node) if ((prop = node.property (X_("bypassed"))) != 0) { set_bypassed (prop->value() == "yes"); } - + if ((prop = node.property (X_("link_direction"))) != 0) { LinkDirection ld; /* here to provide type information */ set_link_direction (LinkDirection (string_2_enum (prop->value(), ld))); @@ -1080,13 +1066,14 @@ Panner::set_state (const XMLNode& node) /* note that we assume that all the stream panners are of the same type. pretty good - assumption, but its still an assumption. + assumption, but it's still an assumption. */ - sp = pan_plugins[i].factory (*this, Parameter(PanAutomation, 0)); + sp = pan_plugins[i].factory (*this, Evoral::Parameter(PanAutomation, 0, num_panners)); + num_panners++; if (sp->set_state (**niter) == 0) { - push_back (sp); + _streampanners.push_back (sp); } break; @@ -1109,26 +1096,24 @@ Panner::set_state (const XMLNode& node) } } + reset (outputs.size (), num_panners); /* don't try to do old-school automation loading if it wasn't marked as existing */ if ((prop = node.property (X_("automation")))) { /* automation path is relative */ - automation_path = _session.automation_dir(); - automation_path += prop->value (); + automation_path = Glib::build_filename(_session.automation_dir(), prop->value ()); } return 0; } - - bool Panner::touching () const { - for (vector::const_iterator i = begin(); i != end(); ++i) { - if ((*i)->pan_control()->list()->touching ()) { + for (vector::const_iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { + if (((AutomationList*)(*i)->pan_control()->list().get())->touching ()) { return true; } } @@ -1148,7 +1133,7 @@ Panner::set_position (float xpos, StreamPanner& orig) if (_link_direction == SameDirection) { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { if (*i == &orig) { (*i)->set_position (xpos, true); } else { @@ -1161,7 +1146,7 @@ Panner::set_position (float xpos, StreamPanner& orig) } else { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { if (*i == &orig) { (*i)->set_position (xpos, true); } else { @@ -1187,7 +1172,7 @@ Panner::set_position (float xpos, float ypos, StreamPanner& orig) if (_link_direction == SameDirection) { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { if (*i == &orig) { (*i)->set_position (xpos, ypos, true); } else { @@ -1205,7 +1190,7 @@ Panner::set_position (float xpos, float ypos, StreamPanner& orig) } else { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { if (*i == &orig) { (*i)->set_position (xpos, ypos, true); } else { @@ -1237,7 +1222,7 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig) if (_link_direction == SameDirection) { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { if (*i == &orig) { (*i)->set_position (xpos, ypos, zpos, true); } else { @@ -1258,7 +1243,7 @@ Panner::set_position (float xpos, float ypos, float zpos, StreamPanner& orig) } else { - for (vector::iterator i = begin(); i != end(); ++i) { + for (vector::iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) { if (*i == &orig) { (*i)->set_position (xpos, ypos, true); } else { @@ -1311,10 +1296,12 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes dst.read_from(inbufs.get_audio(0), nframes, offset); // accumulate starting with the second - BufferSet::audio_iterator i = inbufs.audio_begin(); - for (++i; i != inbufs.audio_end(); ++i) { - dst.accumulate_from(*i, nframes, offset); - } + if (inbufs.count().n_audio() > 0) { + BufferSet::audio_iterator i = inbufs.audio_begin(); + for (++i; i != inbufs.audio_end(); ++i) { + dst.accumulate_from(*i, nframes, offset); + } + } } else { @@ -1324,10 +1311,12 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes dst.read_from(inbufs.get_audio(0), nframes, offset); // accumulate (with gain) starting with the second - BufferSet::audio_iterator i = inbufs.audio_begin(); - for (++i; i != inbufs.audio_end(); ++i) { - dst.accumulate_with_gain_from(*i, nframes, offset, gain_coeff); - } + if (inbufs.count().n_audio() > 0) { + BufferSet::audio_iterator i = inbufs.audio_begin(); + for (++i; i != inbufs.audio_end(); ++i) { + dst.accumulate_with_gain_from(*i, nframes, offset, gain_coeff); + } + } } @@ -1341,13 +1330,13 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes BufferSet::audio_iterator i = inbufs.audio_begin(); - for (iterator pan = begin(); pan != end() && i != inbufs.audio_end(); ++pan, ++i) { + for (vector::iterator pan = _streampanners.begin(); pan != _streampanners.end() && i != inbufs.audio_end(); ++pan, ++i) { (*pan)->distribute (*i, outbufs, gain_coeff, nframes); } } void -Panner::distribute (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) +Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset) { if (outbufs.count().n_audio() == 0) { // Failing to deliver audio we were asked to deliver is a bug @@ -1394,7 +1383,7 @@ Panner::distribute (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame } // More than 1 output, we should have 1 panner for each input - assert(size() == inbufs.count().n_audio()); + //assert(_streampanners.size() == inbufs.count().n_audio()); /* the terrible silence ... */ for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) { @@ -1402,22 +1391,21 @@ Panner::distribute (BufferSet& inbufs, BufferSet& outbufs, nframes_t start_frame } BufferSet::audio_iterator i = inbufs.audio_begin(); - for (iterator pan = begin(); pan != end(); ++pan, ++i) { + for (vector::iterator pan = _streampanners.begin(); pan != _streampanners.end(); ++pan, ++i) { (*pan)->distribute_automated (*i, outbufs, start_frame, end_frame, nframes, _session.pan_automation_buffer()); } } /* old school automation handling */ +/* void Panner::set_name (string str) { - automation_path = _session.automation_dir(); - automation_path += _session.snap_name(); - automation_path += "-pan-"; - automation_path += legalize_for_path (str); - automation_path += ".automation"; + automation_path = Glib::build_filename(_session.automation_dir(), + _session.snap_name() + "-pan-" + legalize_for_path (str) + ".automation"); } +*/ int Panner::load () @@ -1425,7 +1413,7 @@ Panner::load () char line[128]; uint32_t linecnt = 0; float version; - iterator sp; + vector::iterator sp; LocaleGuard lg (X_("POSIX")); if (automation_path.length() == 0) { @@ -1445,7 +1433,7 @@ Panner::load () return -1; } - sp = begin(); + sp = _streampanners.begin(); while (in.getline (line, sizeof(line), '\n')) { @@ -1470,7 +1458,7 @@ Panner::load () if (strcmp (line, "begin") == 0) { - if (sp == end()) { + if (sp == _streampanners.end()) { error << string_compose (_("too many panner states found in pan automation file %1"), automation_path) << endmsg;