MixerScene: correctly restore controls with VCA master

The master needs to be restored first, otherwise setting
the master value with be propagated. Furthermore the
actual value is saved at the time of VCA assignment.
Restoring the vaule needs to scale by the master-reduced value.
This commit is contained in:
Robin Gareus 2022-05-20 19:00:40 +02:00
parent 7d6e429001
commit 2129552777
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 60 additions and 10 deletions

View File

@ -21,14 +21,15 @@
#include <boost/shared_ptr.hpp>
#include "pbd/controllable.h"
#include "pbd/properties.h"
#include "pbd/stateful.h"
#include "ardour/automation_control.h"
#include "ardour/libardour_visibility.h"
#include "ardour/session_handle.h"
namespace PBD {
class Controllable;
}
namespace ARDOUR {
class LIBARDOUR_API MixerScene : public SessionHandleRef, public PBD::Stateful
@ -50,6 +51,8 @@ public:
private:
typedef std::map<PBD::ID, double> ControllableValueMap;
bool recurse_to_master (boost::shared_ptr<PBD::Controllable>, std::set <PBD::ID>&) const;
ControllableValueMap _ctrl_map;
std::string _name;
};

View File

@ -16,9 +16,12 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pbd/controllable.h"
#include "pbd/types_convert.h"
#include "ardour/automation_control.h"
#include "ardour/mixer_scene.h"
#include "ardour/slavable_automation_control.h"
#include "ardour/session.h"
#include "pbd/i18n.h"
@ -56,24 +59,68 @@ MixerScene::snapshot ()
if (!boost::dynamic_pointer_cast<AutomationControl> (c)) {
continue;
}
if (c->flags () & Controllable::HiddenControl) {
continue;
}
_ctrl_map[c->id ()] = c->get_save_value ();
}
_session.set_dirty ();
}
bool
MixerScene::recurse_to_master (boost::shared_ptr<PBD::Controllable> c, std::set <PBD::ID>& done) const
{
if (done.find (c->id()) != done.end ()) {
return false;
}
#if 1 /* ignore controls in Write, or Touch + touching() state */
auto ac = boost::dynamic_pointer_cast<AutomationControl> (c);
if (ac && ac->automation_write ()) {
done.insert (c->id ());
return false;
}
#endif
auto sc = boost::dynamic_pointer_cast<SlavableAutomationControl> (c);
if (sc && sc->slaved ()) {
/* first set masters, then set own value */
for (auto const& m : sc->masters ()) {
recurse_to_master (m, done);
}
}
ControllableValueMap::const_iterator it = _ctrl_map.find (c->id ());
if (it == _ctrl_map.end ()) {
done.insert (c->id ());
return false;
}
if (sc && sc->slaved ()) {
double x = sc->reduce_by_masters (1.0);
if (x <= 0) {
c->set_value (0, Controllable::NoGroup);
} else {
c->set_value (it->second / x, Controllable::NoGroup);
}
} else {
c->set_value (it->second, Controllable::NoGroup);
}
done.insert (it->first);
return true;
}
bool
MixerScene::apply () const
{
bool rv = false;
// TODO special-case solo-iso, and solo (restore order, or ignore)
std::set<PBD::ID> done;
for (auto const& c : Controllable::registered_controllables ()) {
ControllableValueMap::const_iterator it = _ctrl_map.find (c->id ());
if (it == _ctrl_map.end ()) {
continue;
}
rv = true;
c->set_value (it->second, Controllable::NoGroup);
rv |= recurse_to_master (c, done);
}
return rv;
}