summaryrefslogtreecommitdiffstats
path: root/src/client/BlockModel.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2012-08-18 23:05:06 +0000
committerDavid Robillard <d@drobilla.net>2012-08-18 23:05:06 +0000
commit317627ef40f7654c298aa1ac707851c852259e3a (patch)
tree38f7ed57aafb7b3b8e21e6caa3429a39207e4a9a /src/client/BlockModel.cpp
parent160b2baf7df8b960f22619c013b3197c0dc51c2b (diff)
downloadingen-317627ef40f7654c298aa1ac707851c852259e3a.tar.gz
ingen-317627ef40f7654c298aa1ac707851c852259e3a.tar.bz2
ingen-317627ef40f7654c298aa1ac707851c852259e3a.zip
Node => Block
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@4720 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/client/BlockModel.cpp')
-rw-r--r--src/client/BlockModel.cpp270
1 files changed, 270 insertions, 0 deletions
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 <http://drobilla.net/>
+
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <cassert>
+#include <cmath>
+#include <string>
+
+#include "ingen/client/BlockModel.hpp"
+#include "ingen/URIs.hpp"
+#include "ingen/World.hpp"
+
+namespace Ingen {
+namespace Client {
+
+BlockModel::BlockModel(URIs& uris,
+ SharedPtr<PluginModel> 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<PortModel> 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<ObjectModel> c)
+{
+ assert(c->parent().get() == this);
+
+ //ObjectModel::add_child(c);
+
+ SharedPtr<PortModel> pm = PtrCast<PortModel>(c);
+ assert(pm);
+ add_port(pm);
+}
+
+bool
+BlockModel::remove_child(SharedPtr<ObjectModel> c)
+{
+ assert(c->path().is_child_of(path()));
+ assert(c->parent().get() == this);
+
+ //bool ret = ObjectModel::remove_child(c);
+
+ SharedPtr<PortModel> pm = PtrCast<PortModel>(c);
+ assert(pm);
+ remove_port(pm);
+
+ //return ret;
+ return true;
+}
+
+void
+BlockModel::add_port(SharedPtr<PortModel> 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<const PortModel>
+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<PortModel>();
+}
+
+Ingen::GraphObject*
+BlockModel::port(uint32_t index) const
+{
+ assert(index < num_ports());
+ return const_cast<Ingen::GraphObject*>(
+ dynamic_cast<const Ingen::GraphObject*>(_ports[index].get()));
+}
+
+void
+BlockModel::default_port_value_range(SharedPtr<const PortModel> 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<const PortModel> 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<const PortModel> 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<ObjectModel> model)
+{
+ SharedPtr<BlockModel> block = PtrCast<BlockModel>(model);
+ if (block) {
+ _plugin_uri = block->_plugin_uri;
+ _plugin = block->_plugin;
+ }
+
+ ObjectModel::set(model);
+}
+
+} // namespace Client
+} // namespace Ingen