From 317627ef40f7654c298aa1ac707851c852259e3a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 18 Aug 2012 23:05:06 +0000 Subject: Node => Block git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4720 a436a847-0d15-0410-975c-d299462d15a1 --- src/client/BlockModel.cpp | 270 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 src/client/BlockModel.cpp (limited to 'src/client/BlockModel.cpp') diff --git a/src/client/BlockModel.cpp b/src/client/BlockModel.cpp new file mode 100644 index 00000000..865f081c --- /dev/null +++ b/src/client/BlockModel.cpp @@ -0,0 +1,270 @@ +/* + This file is part of Ingen. + Copyright 2007-2012 David Robillard + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen 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 Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see . +*/ + +#include +#include +#include + +#include "ingen/client/BlockModel.hpp" +#include "ingen/URIs.hpp" +#include "ingen/World.hpp" + +namespace Ingen { +namespace Client { + +BlockModel::BlockModel(URIs& uris, + SharedPtr plugin, + const Raul::Path& path) + : ObjectModel(uris, path) + , _plugin_uri(plugin->uri()) + , _plugin(plugin) + , _num_values(0) + , _min_values(0) + , _max_values(0) +{ +} + +BlockModel::BlockModel(URIs& uris, + const Raul::URI& plugin_uri, + const Raul::Path& path) + : ObjectModel(uris, path) + , _plugin_uri(plugin_uri) + , _num_values(0) + , _min_values(0) + , _max_values(0) +{ +} + +BlockModel::BlockModel(const BlockModel& copy) + : ObjectModel(copy) + , _plugin_uri(copy._plugin_uri) + , _num_values(copy._num_values) + , _min_values((float*)malloc(sizeof(float) * _num_values)) + , _max_values((float*)malloc(sizeof(float) * _num_values)) +{ + memcpy(_min_values, copy._min_values, sizeof(float) * _num_values); + memcpy(_max_values, copy._max_values, sizeof(float) * _num_values); +} + +BlockModel::~BlockModel() +{ + clear(); +} + +void +BlockModel::remove_port(SharedPtr port) +{ + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) { + if ((*i) == port) { + _ports.erase(i); + break; + } + } + _signal_removed_port.emit(port); +} + +void +BlockModel::remove_port(const Raul::Path& port_path) +{ + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) { + if ((*i)->path() == port_path) { + _ports.erase(i); + break; + } + } +} + +void +BlockModel::clear() +{ + _ports.clear(); + assert(_ports.empty()); + delete[] _min_values; + delete[] _max_values; + _min_values = 0; + _max_values = 0; +} + +void +BlockModel::add_child(SharedPtr c) +{ + assert(c->parent().get() == this); + + //ObjectModel::add_child(c); + + SharedPtr pm = PtrCast(c); + assert(pm); + add_port(pm); +} + +bool +BlockModel::remove_child(SharedPtr c) +{ + assert(c->path().is_child_of(path())); + assert(c->parent().get() == this); + + //bool ret = ObjectModel::remove_child(c); + + SharedPtr pm = PtrCast(c); + assert(pm); + remove_port(pm); + + //return ret; + return true; +} + +void +BlockModel::add_port(SharedPtr pm) +{ + assert(pm); + assert(pm->path().is_child_of(path())); + assert(pm->parent().get() == this); + + // Store should have handled this by merging the two + assert(find(_ports.begin(), _ports.end(), pm) == _ports.end()); + + _ports.push_back(pm); + _signal_new_port.emit(pm); +} + +SharedPtr +BlockModel::get_port(const Raul::Symbol& symbol) const +{ + for (Ports::const_iterator i = _ports.begin(); i != _ports.end(); ++i) + if ((*i)->symbol() == symbol) + return (*i); + return SharedPtr(); +} + +Ingen::GraphObject* +BlockModel::port(uint32_t index) const +{ + assert(index < num_ports()); + return const_cast( + dynamic_cast(_ports[index].get())); +} + +void +BlockModel::default_port_value_range(SharedPtr port, + float& min, + float& max, + uint32_t srate) const +{ + // Default control values + min = 0.0; + max = 1.0; + + // Get range from client-side LV2 data + if (_plugin && _plugin->type() == PluginModel::LV2) { + if (!_min_values) { + _num_values = lilv_plugin_get_num_ports(_plugin->lilv_plugin()); + _min_values = new float[_num_values]; + _max_values = new float[_num_values]; + lilv_plugin_get_port_ranges_float(_plugin->lilv_plugin(), + _min_values, _max_values, 0); + } + + if (!std::isnan(_min_values[port->index()])) + min = _min_values[port->index()]; + if (!std::isnan(_max_values[port->index()])) + max = _max_values[port->index()]; + } + + if (port->port_property(_uris.lv2_sampleRate)) { + min *= srate; + max *= srate; + } +} + +void +BlockModel::port_value_range(SharedPtr port, + float& min, float& max, uint32_t srate) const +{ + assert(port->parent().get() == this); + + default_port_value_range(port, min, max); + + // Possibly overriden + const Raul::Atom& min_atom = port->get_property(_uris.lv2_minimum); + const Raul::Atom& max_atom = port->get_property(_uris.lv2_maximum); + if (min_atom.type() == _uris.forge.Float) + min = min_atom.get_float(); + if (max_atom.type() == _uris.forge.Float) + max = max_atom.get_float(); + + if (max <= min) + max = min + 1.0; + + if (port->port_property(_uris.lv2_sampleRate)) { + min *= srate; + max *= srate; + } +} + +std::string +BlockModel::label() const +{ + const Raul::Atom& name_property = get_property(_uris.lv2_name); + if (name_property.type() == _uris.forge.String) { + return name_property.get_string(); + } else if (plugin_model()) { + return plugin_model()->human_name(); + } else { + return symbol().c_str(); + } +} + +std::string +BlockModel::port_label(SharedPtr port) const +{ + const Raul::Atom& name = port->get_property(Raul::URI(LV2_CORE__name)); + if (name.is_valid()) { + return name.get_string(); + } + + if (_plugin && _plugin->type() == PluginModel::LV2) { + LilvWorld* w = _plugin->lilv_world(); + const LilvPlugin* plug = _plugin->lilv_plugin(); + LilvNode* sym = lilv_new_string(w, port->symbol().c_str()); + const LilvPort* lport = lilv_plugin_get_port_by_symbol(plug, sym); + if (lport) { + LilvNode* lname = lilv_port_get_name(plug, lport); + if (lname && lilv_node_is_string(lname)) { + std::string ret(lilv_node_as_string(lname)); + lilv_node_free(lname); + return ret; + } + lilv_node_free(lname); + } + } + + return port->symbol().c_str(); +} + +void +BlockModel::set(SharedPtr model) +{ + SharedPtr block = PtrCast(model); + if (block) { + _plugin_uri = block->_plugin_uri; + _plugin = block->_plugin; + } + + ObjectModel::set(model); +} + +} // namespace Client +} // namespace Ingen -- cgit v1.2.1