diff options
-rw-r--r-- | src/client/ClientStore.cpp | 13 | ||||
-rw-r--r-- | src/gui/Port.cpp | 15 | ||||
-rw-r--r-- | src/gui/Port.hpp | 1 | ||||
-rw-r--r-- | src/gui/PortMenu.cpp | 24 | ||||
-rw-r--r-- | src/gui/PortPropertiesWindow.cpp | 166 | ||||
-rw-r--r-- | src/gui/PortPropertiesWindow.hpp | 69 | ||||
-rw-r--r-- | src/gui/wscript | 1 | ||||
-rw-r--r-- | src/serialisation/Parser.cpp | 47 | ||||
-rw-r--r-- | src/serialisation/Serialiser.cpp | 21 | ||||
-rw-r--r-- | src/server/DuplexPort.cpp | 12 | ||||
-rw-r--r-- | src/server/InputPort.cpp | 6 | ||||
-rw-r--r-- | src/server/LV2Block.cpp | 2 | ||||
-rw-r--r-- | src/server/PortImpl.cpp | 9 | ||||
-rw-r--r-- | src/server/events/Delta.cpp | 12 |
14 files changed, 96 insertions, 302 deletions
diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index 02f5f4f0..f5c99e38 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -289,16 +289,17 @@ ClientStore::put(const Raul::URI& uri, PortModel::Direction pdir = (is_output) ? PortModel::Direction::OUTPUT : PortModel::Direction::INPUT; - const Iterator i = properties.find(_uris.lv2_index); + uint32_t index = 0; + const Iterator i = properties.find(_uris.lv2_index); if (i != properties.end() && i->second.type() == _uris.forge.Int) { - const uint32_t index = i->second.get<int32_t>(); - SPtr<PortModel> p( - new PortModel(uris(), path, index, pdir)); - p->set_properties(properties); - add_object(p); + index = i->second.get<int32_t>(); } else { _log.error(fmt("Port %1% has no index\n") % path); } + + SPtr<PortModel> p(new PortModel(uris(), path, index, pdir)); + p->set_properties(properties); + add_object(p); } else { _log.warn(fmt("Ignoring object %1% with unknown type\n") % path.c_str()); diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp index 2bdf2e43..0d82d0cd 100644 --- a/src/gui/Port.cpp +++ b/src/gui/Port.cpp @@ -89,6 +89,8 @@ Port::Port(App& app, show_control(); pm->signal_property().connect( sigc::mem_fun(this, &Port::property_changed)); + pm->signal_property_removed().connect( + sigc::mem_fun(this, &Port::property_removed)); pm->signal_value_changed().connect( sigc::mem_fun(this, &Port::value_changed)); } @@ -121,7 +123,7 @@ void Port::update_metadata() { SPtr<const PortModel> pm = _port_model.lock(); - if (_app.can_control(pm.get()) && pm->is_numeric()) { + if (pm && _app.can_control(pm.get()) && pm->is_numeric()) { SPtr<const BlockModel> parent = dynamic_ptr_cast<const BlockModel>(pm->parent()); if (parent) { float min = 0.0f; @@ -435,13 +437,22 @@ Port::property_changed(const Raul::URI& key, const Atom& value) } } +void +Port::property_removed(const Raul::URI& key, const Atom& value) +{ + const URIs& uris = _app.uris(); + if (key == uris.lv2_minimum || key == uris.lv2_maximum) { + update_metadata(); + } +} + bool Port::on_selected(gboolean b) { if (b) { SPtr<const PortModel> pm = _port_model.lock(); if (pm) { - SPtr<const BlockModel> block = dynamic_ptr_cast<BlockModel>(pm->parent()); + SPtr<const BlockModel> block = dynamic_ptr_cast<const BlockModel>(pm->parent()); GraphWindow* win = _app.window_factory()->parent_graph_window(block); if (win && win->documentation_is_visible() && block->plugin_model()) { bool html = false; diff --git a/src/gui/Port.hpp b/src/gui/Port.hpp index a8d16095..216b8356 100644 --- a/src/gui/Port.hpp +++ b/src/gui/Port.hpp @@ -78,6 +78,7 @@ private: GraphBox* get_graph_box() const; void property_changed(const Raul::URI& key, const Atom& value); + void property_removed(const Raul::URI& key, const Atom& value); void moved(); void on_value_changed(double value); diff --git a/src/gui/PortMenu.cpp b/src/gui/PortMenu.cpp index 9c428dd8..138ee397 100644 --- a/src/gui/PortMenu.cpp +++ b/src/gui/PortMenu.cpp @@ -121,22 +121,14 @@ PortMenu::on_menu_set_max() void PortMenu::on_menu_reset_range() { - const URIs& uris = _app->uris(); - SPtr<const PortModel> model = dynamic_ptr_cast<const PortModel>(_object); - SPtr<const BlockModel> parent = dynamic_ptr_cast<const BlockModel>(_object->parent()); - - float min, max; - parent->default_port_value_range(model, min, max); - - if (!std::isnan(min)) - _app->interface()->set_property(_object->uri(), - uris.lv2_minimum, - _app->forge().make(min)); - - if (!std::isnan(max)) - _app->interface()->set_property(_object->uri(), - uris.lv2_maximum, - _app->forge().make(max)); + const URIs& uris = _app->uris(); + SPtr<const PortModel> model = dynamic_ptr_cast<const PortModel>(_object); + + // Remove lv2:minimum and lv2:maximum properties + Resource::Properties remove; + remove.insert({uris.lv2_minimum, Resource::Property(uris.patch_wildcard)}); + remove.insert({uris.lv2_maximum, Resource::Property(uris.patch_wildcard)}); + _app->interface()->delta(_object->uri(), remove, Resource::Properties()); } void diff --git a/src/gui/PortPropertiesWindow.cpp b/src/gui/PortPropertiesWindow.cpp deleted file mode 100644 index e4aec41d..00000000 --- a/src/gui/PortPropertiesWindow.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - 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 <list> - -#include "ingen/Interface.hpp" -#include "ingen/client/BlockModel.hpp" -#include "ingen/client/PluginModel.hpp" - -#include "App.hpp" -#include "PortPropertiesWindow.hpp" - -using namespace std; - -namespace Ingen { -using namespace Client; -namespace GUI { - -PortPropertiesWindow::PortPropertiesWindow(BaseObjectType* cobject, - const Glib::RefPtr<Gtk::Builder>& xml) - : Window(cobject) - , _initial_min(0.0f) - , _initial_max(1.0f) -{ - xml->get_widget("port_properties_min_spinner", _min_spinner); - xml->get_widget("port_properties_max_spinner", _max_spinner); - xml->get_widget("port_properties_cancel_button", _cancel_button); - xml->get_widget("port_properties_ok_button", _ok_button); - - _cancel_button->signal_clicked().connect(sigc::mem_fun(this, - &PortPropertiesWindow::cancel)); - - _ok_button->signal_clicked().connect(sigc::mem_fun(this, - &PortPropertiesWindow::ok)); -} - -/** Set the port this window is associated with. - * This function MUST be called before using this object in any way. - */ -void -PortPropertiesWindow::present(SPtr<const PortModel> pm) -{ - assert(pm); - - for (auto& c : _connections) - c.disconnect(); - - _connections.clear(); - - _port_model = pm; - - set_title(pm->path() + " Properties - Ingen"); - - float min = 0.0f, max = 1.0f; - SPtr<BlockModel> parent = dynamic_ptr_cast<BlockModel>(_port_model->parent()); - if (parent) - parent->port_value_range(_port_model, min, max, - _app->sample_rate()); - - _initial_min = min; - _initial_max = max; - - _min_spinner->set_value(min); - _connections.push_back( - _min_spinner->signal_value_changed().connect( - sigc::mem_fun(*this, &PortPropertiesWindow::min_changed))); - - _max_spinner->set_value(max); - _connections.push_back( - _max_spinner->signal_value_changed().connect( - sigc::mem_fun(*this, &PortPropertiesWindow::max_changed))); - - _connections.push_back( - pm->signal_property().connect( - sigc::mem_fun(this, &PortPropertiesWindow::property_changed))); - - Gtk::Window::present(); -} - -void -PortPropertiesWindow::property_changed(const Raul::URI& key, - const Atom& value) -{ - const URIs& uris = _app->uris(); - if (value.type() == uris.forge.Float) { - if (key == uris.lv2_minimum) - _min_spinner->set_value(value.get<float>()); - else if (key == uris.lv2_maximum) - _max_spinner->set_value(value.get<float>()); - } -} - -void -PortPropertiesWindow::min_changed() -{ - const float val = _port_model->value().get<float>(); - float min = _min_spinner->get_value(); - float max = _max_spinner->get_value(); - - if (min > val) { - _min_spinner->set_value(val); - return; // avoid recursion - } - - if (max <= min) { - max = min + 1.0; - _max_spinner->set_value(max); - } -} - -void -PortPropertiesWindow::max_changed() -{ - const float val = _port_model->value().get<float>(); - float min = _min_spinner->get_value(); - float max = _max_spinner->get_value(); - - if (max < val) { - _max_spinner->set_value(val); - return; // avoid recursion - } - - if (min >= max) { - min = max - 1.0; - _min_spinner->set_value(min); - } -} - -void -PortPropertiesWindow::cancel() -{ - hide(); -} - -void -PortPropertiesWindow::ok() -{ - const URIs& uris = _app->uris(); - Resource::Properties props; - props.insert( - make_pair(uris.lv2_minimum, - _app->forge().make(float(_min_spinner->get_value())))); - props.insert( - make_pair(uris.lv2_maximum, - _app->forge().make(float(_max_spinner->get_value())))); - _app->interface()->put(_port_model->uri(), props); - hide(); -} - -} // namespace GUI -} // namespace Ingen - diff --git a/src/gui/PortPropertiesWindow.hpp b/src/gui/PortPropertiesWindow.hpp deleted file mode 100644 index 684a2dfb..00000000 --- a/src/gui/PortPropertiesWindow.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - 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/>. -*/ - -#ifndef INGEN_GUI_PORTPROPERTIESWINDOW_HPP -#define INGEN_GUI_PORTPROPERTIESWINDOW_HPP - -#include <list> - -#include <gtkmm/builder.h> -#include <gtkmm/spinbutton.h> - -#include "ingen/client/PortModel.hpp" -#include "ingen/types.hpp" - -#include "Window.hpp" - -namespace Ingen { -namespace GUI { - -/** Port properties window. - * - * Loaded from XML as a derived object. - * - * \ingroup GUI - */ -class PortPropertiesWindow : public Window -{ -public: - PortPropertiesWindow(BaseObjectType* cobject, - const Glib::RefPtr<Gtk::Builder>& xml); - - void present(SPtr<const Client::PortModel> port_model); - -private: - void property_changed(const Raul::URI& key, const Atom& value); - void min_changed(); - void max_changed(); - - void ok(); - void cancel(); - - float _initial_min; - float _initial_max; - - SPtr<const Client::PortModel> _port_model; - Gtk::SpinButton* _min_spinner; - Gtk::SpinButton* _max_spinner; - Gtk::Button* _cancel_button; - Gtk::Button* _ok_button; - std::list<sigc::connection> _connections; -}; - -} // namespace GUI -} // namespace Ingen - -#endif // INGEN_GUI_PORTPROPERTIESWINDOW_HPP diff --git a/src/gui/wscript b/src/gui/wscript index 62731abe..153c4d15 100644 --- a/src/gui/wscript +++ b/src/gui/wscript @@ -47,7 +47,6 @@ def build(bld): PluginMenu.cpp Port.cpp PortMenu.cpp - PortPropertiesWindow.cpp PropertiesWindow.cpp RDFS.cpp RenameWindow.cpp diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index 3d8ba96d..d49ac9a6 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -140,31 +140,47 @@ get_port(Ingen::World* world, Sord::Model& model, const Sord::Node& subject, const Raul::Path& parent, - uint32_t& index) + uint32_t* index) { const URIs& uris = world->uris(); // Get all properties Resource::Properties props = get_properties(world, model, subject); - // Get index - Resource::Properties::const_iterator i = props.find(uris.lv2_index); - if (i == props.end() - || i->second.type() != world->forge().Int - || i->second.get<int32_t>() < 0) { - world->log().warn(fmt("Port %1% has no valid index\n") % subject); - return boost::optional<PortRecord>(); + // Get index if requested (for Graphs) + if (index) { + Resource::Properties::const_iterator i = props.find(uris.lv2_index); + if (i == props.end() + || i->second.type() != world->forge().Int + || i->second.get<int32_t>() < 0) { + world->log().error(fmt("Port %1% has no valid index\n") % subject); + return boost::optional<PortRecord>(); + } + *index = i->second.get<int32_t>(); } - index = i->second.get<int32_t>(); // Get symbol Resource::Properties::const_iterator s = props.find(uris.lv2_symbol); - if (s == props.end()) { - world->log().warn(fmt("Port %1% has no symbol\n") % subject); + std::string sym; + if (s != props.end()) { + sym = s->second.ptr<char>(); + } else { + const std::string subject_str = subject.to_string(); + const size_t last_slash = subject_str.find_last_of("/"); + + sym = ((last_slash == string::npos) + ? subject_str + : subject_str.substr(last_slash + 1)); + } + + if (!Raul::Symbol::is_valid(sym)) { + world->log().error(fmt("Port %1% has invalid symbol `%2%'\n") + % subject % sym); return boost::optional<PortRecord>(); } - const Raul::Symbol port_sym(s->second.ptr<char>()); - const Raul::Path port_path = parent.child(port_sym); + + const Raul::Symbol port_sym(sym); + const Raul::Path port_path(parent.child(port_sym)); return make_pair(port_path, props); } @@ -341,9 +357,8 @@ parse_graph(Ingen::World* world, Sord::Node port = p.get_object(); // Get all properties - uint32_t index = 0; boost::optional<PortRecord> port_record = get_port( - world, model, port, block_path, index); + world, model, port, block_path, NULL); if (!port_record) { world->log().error(fmt("Invalid port %1%\n") % port); return boost::optional<Raul::Path>(); @@ -364,7 +379,7 @@ parse_graph(Ingen::World* world, // Get all properties uint32_t index = 0; boost::optional<PortRecord> port_record = get_port( - world, model, port, graph_path, index); + world, model, port, graph_path, &index); if (!port_record) { world->log().error(fmt("Invalid port %1%\n") % port); return boost::optional<Raul::Path>(); diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp index 425ac00f..dd1be2b4 100644 --- a/src/serialisation/Serialiser.cpp +++ b/src/serialisation/Serialiser.cpp @@ -433,9 +433,6 @@ Serialiser::Impl::serialise_block(SPtr<const Node> block, _model->add_statement(block_id, Sord::URI(_model->world(), uris.ingen_prototype), class_id); - _model->add_statement(block_id, - Sord::URI(_model->world(), uris.lv2_symbol), - Sord::Literal(_model->world(), block->path().symbol())); const Node::Properties props = block->properties(Resource::Graph::EXTERNAL); serialise_properties(block_id, props); @@ -455,14 +452,20 @@ Serialiser::Impl::serialise_port(const Node* port, Resource::Graph context, const Sord::Node& port_id) { - URIs& uris = _world.uris(); - Sord::World& world = _model->world(); + URIs& uris = _world.uris(); + Sord::World& world = _model->world(); + Node::Properties props = port->properties(context); - _model->add_statement(port_id, - Sord::URI(world, uris.lv2_symbol), - Sord::Literal(world, port->path().symbol())); + if (context == Resource::Graph::INTERNAL) { + // Always write lv2:symbol for Graph ports (required for lv2:Plugin) + _model->add_statement(port_id, + Sord::URI(world, uris.lv2_symbol), + Sord::Literal(world, port->path().symbol())); + } else { + // Never write lv2:index for plugin instances (not persistent/stable) + props.erase(uris.lv2_index); + } - Node::Properties props = port->properties(context); if (context == Resource::Graph::INTERNAL && port->has_property(uris.rdf_type, uris.lv2_ControlPort) && port->has_property(uris.rdf_type, uris.lv2_InputPort)) diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp index 438d315c..256d45b1 100644 --- a/src/server/DuplexPort.cpp +++ b/src/server/DuplexPort.cpp @@ -42,8 +42,16 @@ DuplexPort::DuplexPort(BufferFactory& bufs, , OutputPort(bufs, parent, symbol, index, poly, type, buffer_type, value, buffer_size) , _is_output(is_output) { - set_property(bufs.uris().ingen_polyphonic, - bufs.forge().make(polyphonic)); + if (polyphonic) { + set_property(bufs.uris().ingen_polyphonic, bufs.forge().make(true)); + } + + // Set default control range + if (!is_output && (type == PortType::CONTROL || type == PortType::CV)) { + set_property(bufs.uris().lv2_minimum, bufs.forge().make(0.0f)); + set_property(bufs.uris().lv2_maximum, bufs.forge().make(1.0f)); + } + } DuplexPort::~DuplexPort() diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp index f1be3b8f..cdf70575 100644 --- a/src/server/InputPort.cpp +++ b/src/server/InputPort.cpp @@ -53,12 +53,6 @@ InputPort::InputPort(BufferFactory& bufs, if (parent->graph_type() != Node::GraphType::GRAPH) { add_property(uris.rdf_type, uris.lv2_InputPort); } - - // Set default control range - if (type == PortType::CONTROL || type == PortType::CV) { - set_property(uris.lv2_minimum, bufs.forge().make(0.0f)); - set_property(uris.lv2_maximum, bufs.forge().make(1.0f)); - } } bool diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp index 0525a2db..5e97bfe5 100644 --- a/src/server/LV2Block.cpp +++ b/src/server/LV2Block.cpp @@ -366,11 +366,9 @@ LV2Block::instantiate(BufferFactory& bufs) || port_type == PortType::CV)) { port->set_value(val); if (!isnan(min_values[j])) { - port->set_property(uris.lv2_minimum, forge.make(min_values[j])); port->set_minimum(forge.make(min_values[j])); } if (!isnan(max_values[j])) { - port->set_property(uris.lv2_maximum, forge.make(max_values[j])); port->set_maximum(forge.make(max_values[j])); } } diff --git a/src/server/PortImpl.cpp b/src/server/PortImpl.cpp index e4b3ad4d..aed67ec3 100644 --- a/src/server/PortImpl.cpp +++ b/src/server/PortImpl.cpp @@ -82,15 +82,14 @@ PortImpl::PortImpl(BufferFactory& bufs, set_type(type, buffer_type); - add_property(uris.rdf_type, bufs.forge().alloc_uri(type.uri())); set_property(uris.lv2_index, bufs.forge().make((int32_t)index)); if ((type == PortType::CONTROL || type == PortType::CV) && value.is_valid()) { set_property(uris.ingen_value, value); } - if (type == PortType::ATOM) { - add_property(uris.atom_bufferType, - bufs.forge().make_urid(buffer_type)); - } + // if (type == PortType::ATOM) { + // set_property(uris.atom_bufferType, + // bufs.forge().make_urid(buffer_type)); + // } } PortImpl::~PortImpl() diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 072d0ba3..0c134ede 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -148,9 +148,10 @@ Delta::pre_process() NodeImpl* obj = dynamic_cast<NodeImpl*>(_object); + // Remove any properties removed in delta for (const auto& r : _remove) { - const Raul::URI& key = r.first; - const Atom& value = r.second; + const Raul::URI& key = r.first; + const Atom& value = r.second; if (key == uris.midi_binding && value == uris.patch_wildcard) { PortImpl* port = dynamic_cast<PortImpl*>(_object); if (port) @@ -161,6 +162,13 @@ Delta::pre_process() } } + // Remove all added properties if this is a put + if (_create && _object) { + for (const auto& p : _properties) { + _object->remove_property(p.first, p.second); + } + } + for (const auto& p : _properties) { const Raul::URI& key = p.first; const Resource::Property& value = p.second; |