/* * Carla LADSPA utils * Copyright (C) 2011-2012 Filipe Coelho * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * For a full copy of the GNU General Public License see the COPYING file */ #ifndef CARLA_LADSPA_UTILS_HPP #define CARLA_LADSPA_UTILS_HPP #include "carla_utils.hpp" #include "ladspa/ladspa.h" #include "ladspa_rdf.hpp" #include #include // ------------------------------------------------------------------------------------------------ // Copy RDF object static inline const LADSPA_RDF_Descriptor* ladspa_rdf_dup(const LADSPA_RDF_Descriptor* const oldDescriptor) { CARLA_ASSERT(oldDescriptor); if (! oldDescriptor) return nullptr; LADSPA_RDF_Descriptor* const newDescriptor = new LADSPA_RDF_Descriptor(); newDescriptor->Type = oldDescriptor->Type; newDescriptor->UniqueID = oldDescriptor->UniqueID; newDescriptor->PortCount = oldDescriptor->PortCount; if (oldDescriptor->Title) newDescriptor->Title = strdup(oldDescriptor->Title); if (oldDescriptor->Creator) newDescriptor->Creator = strdup(oldDescriptor->Creator); if (newDescriptor->PortCount > 0) { newDescriptor->Ports = new LADSPA_RDF_Port[newDescriptor->PortCount]; for (unsigned long i=0; i < newDescriptor->PortCount; i++) { LADSPA_RDF_Port* const newPort = &newDescriptor->Ports[i]; newPort->Type = oldDescriptor->Ports[i].Type; newPort->Hints = oldDescriptor->Ports[i].Hints; newPort->Default = oldDescriptor->Ports[i].Default; newPort->Unit = oldDescriptor->Ports[i].Unit; newPort->ScalePointCount = oldDescriptor->Ports[i].ScalePointCount; if (oldDescriptor->Ports[i].Label) newPort->Label = strdup(oldDescriptor->Ports[i].Label); if (newPort->ScalePointCount > 0) { newPort->ScalePoints = new LADSPA_RDF_ScalePoint[newPort->ScalePointCount]; for (unsigned long j=0; j < newPort->ScalePointCount; j++) { LADSPA_RDF_ScalePoint* const newScalePoint = &newPort->ScalePoints[j]; newScalePoint->Value = oldDescriptor->Ports[i].ScalePoints[j].Value; if (oldDescriptor->Ports[i].ScalePoints[j].Label) newScalePoint->Label = strdup(oldDescriptor->Ports[i].ScalePoints[j].Label); } } } } return newDescriptor; } // ------------------------------------------------------------------------------------------------ static inline bool is_ladspa_port_good(const LADSPA_PortDescriptor port1, const LADSPA_PortDescriptor port2) { if (LADSPA_IS_PORT_INPUT(port1) && ! LADSPA_IS_PORT_INPUT(port2)) return false; if (LADSPA_IS_PORT_OUTPUT(port1) && ! LADSPA_IS_PORT_OUTPUT(port2)) return false; if (LADSPA_IS_PORT_CONTROL(port1) && ! LADSPA_IS_PORT_CONTROL(port2)) return false; if (LADSPA_IS_PORT_AUDIO(port1) && ! LADSPA_IS_PORT_AUDIO(port2)) return false; return true; } static inline bool is_ladspa_rdf_descriptor_valid(const LADSPA_RDF_Descriptor* const rdfDescriptor, const LADSPA_Descriptor* const descriptor) { CARLA_ASSERT(rdfDescriptor); CARLA_ASSERT(descriptor); if (! rdfDescriptor) return false; if (! descriptor) return false; if (rdfDescriptor->UniqueID != descriptor->UniqueID) { qWarning("WARNING - Plugin has wrong UniqueID: %li != %li", rdfDescriptor->UniqueID, descriptor->UniqueID); return false; } if (rdfDescriptor->PortCount > descriptor->PortCount) { qWarning("WARNING - Plugin has RDF data, but invalid PortCount: %li > %li", rdfDescriptor->PortCount, descriptor->PortCount); return false; } for (unsigned long i=0; i < rdfDescriptor->PortCount; i++) { if (! is_ladspa_port_good(rdfDescriptor->Ports[i].Type, descriptor->PortDescriptors[i])) { qWarning("WARNING - Plugin has RDF data, but invalid PortTypes: %i != %i", rdfDescriptor->Ports[i].Type, descriptor->PortDescriptors[i]); return false; } } return true; } static inline LADSPA_Data get_default_ladspa_port_value(const LADSPA_PortRangeHintDescriptor hintDescriptor, const LADSPA_Data min, const LADSPA_Data max) { LADSPA_Data def; if (LADSPA_IS_HINT_HAS_DEFAULT(hintDescriptor)) { switch (hintDescriptor & LADSPA_HINT_DEFAULT_MASK) { case LADSPA_HINT_DEFAULT_MINIMUM: def = min; break; case LADSPA_HINT_DEFAULT_MAXIMUM: def = max; break; case LADSPA_HINT_DEFAULT_0: def = 0.0f; break; case LADSPA_HINT_DEFAULT_1: def = 1.0f; break; case LADSPA_HINT_DEFAULT_100: def = 100.0f; break; case LADSPA_HINT_DEFAULT_440: def = 440.0f; break; case LADSPA_HINT_DEFAULT_LOW: if (LADSPA_IS_HINT_LOGARITHMIC(hintDescriptor)) def = std::exp((std::log(min)*0.75f) + (std::log(max)*0.25f)); else def = (min*0.75f) + (max*0.25f); break; case LADSPA_HINT_DEFAULT_MIDDLE: if (LADSPA_IS_HINT_LOGARITHMIC(hintDescriptor)) def = std::sqrt(min*max); else def = (min+max)/2; break; case LADSPA_HINT_DEFAULT_HIGH: if (LADSPA_IS_HINT_LOGARITHMIC(hintDescriptor)) def = std::exp((std::log(min)*0.25f) + (std::log(max)*0.75f)); else def = (min*0.25f) + (max*0.75f); break; default: if (min < 0.0f && max > 0.0f) def = 0.0f; else def = min; break; } } else { // no default value if (min < 0.0f && max > 0.0f) def = 0.0f; else def = min; } return def; } // ------------------------------------------------------------------------------------------------ #endif // CARLA_LADSPA_UTILS_HPP