gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

parameterlinks.cpp (4966B)


      1 #include "parameterlinks.h"
      2 
      3 #include "controller.h"
      4 
      5 namespace pluginLib
      6 {
      7 	ParameterLinks::ParameterLinks(Controller& _controller) : m_controller(_controller)
      8 	{
      9 	}
     10 
     11 	bool ParameterLinks::add(Parameter* _source, Parameter* _dest, bool _applyCurrentSourceToTarget)
     12 	{
     13 		if(!_source || !_dest)
     14 			return false;
     15 
     16 		if(_source == _dest)
     17 			return false;
     18 
     19 		const auto it = m_parameterLinks.find(_source);
     20 
     21 		if(it != m_parameterLinks.end())
     22 			return it->second->add(_dest, _applyCurrentSourceToTarget);
     23 
     24 		m_parameterLinks.insert({_source, std::make_unique<ParameterLink>(_source, _dest, _applyCurrentSourceToTarget)});
     25 		m_destToSource[_dest].insert(_source);
     26 
     27 		_dest->setLinkState(Target);
     28 
     29 		return true;
     30 	}
     31 
     32 	bool ParameterLinks::remove(const Parameter* _source, Parameter* _dest)
     33 	{
     34 		const auto it = m_parameterLinks.find(_source);
     35 		if(it == m_parameterLinks.end())
     36 			return false;
     37 		if(!it->second->remove(_dest))
     38 			return false;
     39 		if(it->second->empty())
     40 			m_parameterLinks.erase(it);
     41 
     42 		auto& sources = m_destToSource[_dest];
     43 
     44 		sources.erase(_source);
     45 
     46 		if(sources.empty())
     47 		{
     48 			m_destToSource.erase(_dest);
     49 			_dest->clearLinkState(Target);
     50 		}
     51 
     52 		return true;
     53 	}
     54 
     55 	ParameterLinkType ParameterLinks::getRegionLinkType(const std::string& _regionId, const uint8_t _part) const
     56 	{
     57 		const auto& regions = m_controller.getParameterDescriptions().getRegions();
     58 
     59 		const auto itRegion = regions.find(_regionId);
     60 
     61 		if(itRegion == regions.end())
     62 			return None;
     63 
     64 		uint32_t totalCount = 0;
     65 		uint32_t sourceCount = 0;
     66 		uint32_t targetCount = 0;
     67 
     68 		for (const auto& [name, desc] : itRegion->second.getParams())
     69 		{
     70 			const auto* parameter = m_controller.getParameter(name, _part);
     71 
     72 			if(!parameter)
     73 				continue;
     74 
     75 			++totalCount;
     76 
     77 			const auto state = parameter->getLinkState();
     78 
     79 			if(state & ParameterLinkType::Source)	++sourceCount;
     80 			if(state & ParameterLinkType::Target)	++targetCount;
     81 		}
     82 
     83 		ParameterLinkType result = None;
     84 
     85 		if(sourceCount > (totalCount>>1))
     86 			result = static_cast<ParameterLinkType>(result | ParameterLinkType::Source);
     87 		if(targetCount > (totalCount>>1))
     88 			result = static_cast<ParameterLinkType>(result | ParameterLinkType::Target);
     89 
     90 		return result;
     91 	}
     92 
     93 	bool ParameterLinks::linkRegion(const std::string& _regionId, const uint8_t _partSource, const uint8_t _partDest, bool _applyCurrentSourceToTarget)
     94 	{
     95 		const auto& regions = m_controller.getParameterDescriptions().getRegions();
     96 
     97 		const auto itRegion = regions.find(_regionId);
     98 
     99 		if(itRegion == regions.end())
    100 			return false;
    101 
    102 		const RegionLink link{_regionId, _partSource, _partDest};
    103 
    104 		if(!m_linkedRegions.insert(link).second)
    105 			return false;
    106 
    107 		return updateRegionLinks(itRegion->second, _partSource, _partDest, true, _applyCurrentSourceToTarget);
    108 	}
    109 
    110 	bool ParameterLinks::unlinkRegion(const std::string& _regionId, const uint8_t _partSource, const uint8_t _partDest)
    111 	{
    112 		const RegionLink link{_regionId, _partSource, _partDest};
    113 
    114 		if(!m_linkedRegions.erase(link))
    115 			return false;
    116 
    117 		const auto& regions = m_controller.getParameterDescriptions().getRegions();
    118 
    119 		const auto itRegion = regions.find(_regionId);
    120 
    121 		if(itRegion == regions.end())
    122 			return false;
    123 
    124 		return updateRegionLinks(itRegion->second, _partSource, _partDest, false, false);
    125 	}
    126 
    127 	bool ParameterLinks::isRegionLinked(const std::string& _regionId, const uint8_t _partSource, const uint8_t _partDest) const
    128 	{
    129 		const RegionLink link{_regionId, _partSource, _partDest};
    130 		return m_linkedRegions.find(link) != m_linkedRegions.end();
    131 	}
    132 
    133 	void ParameterLinks::saveChunkData(baseLib::BinaryStream& s) const
    134 	{
    135 		if(m_linkedRegions.empty())
    136 			return;
    137 
    138 		baseLib::ChunkWriter cw(s, "PLNK", 1);
    139 
    140 		s.write(static_cast<uint32_t>(m_linkedRegions.size()));
    141 
    142 		for (const auto& linkedRegion : m_linkedRegions)
    143 		{
    144 			s.write(linkedRegion.regionId);
    145 			s.write(linkedRegion.sourcePart);
    146 			s.write(linkedRegion.destPart);
    147 		}
    148 	}
    149 
    150 	void ParameterLinks::loadChunkData(baseLib::ChunkReader& _cr)
    151 	{
    152 		_cr.add("PLNK", 1, [this](baseLib::BinaryStream& _binaryStream, unsigned _version)
    153 		{
    154 			const uint32_t count = _binaryStream.read<uint32_t>();
    155 
    156 			for(uint32_t i=0; i<count; ++i)
    157 			{
    158 				const auto regionId = _binaryStream.readString();
    159 				const auto sourcePart = _binaryStream.read<uint8_t>();
    160 				const auto destPart = _binaryStream.read<uint8_t>();
    161 
    162 				linkRegion(regionId, sourcePart, destPart, false);
    163 			}
    164 		});
    165 	}
    166 
    167 	bool ParameterLinks::updateRegionLinks(const ParameterRegion& _region, const uint8_t _partSource, const uint8_t _partDest, const bool _enableLink, const bool _applyCurrentSourceToTarget)
    168 	{
    169 		bool res = false;
    170 
    171 		for(const auto& [name, desc] : _region.getParams())
    172 		{
    173 			auto* paramSource = m_controller.getParameter(name, _partSource);
    174 			auto* paramDest = m_controller.getParameter(name, _partDest);
    175 
    176 			if(_enableLink)
    177 				res |= add(paramSource, paramDest, _applyCurrentSourceToTarget);
    178 			else
    179 				res |= remove(paramSource, paramDest);
    180 		}
    181 
    182 		return res;
    183 	}
    184 }