summaryrefslogtreecommitdiffstats
path: root/src/gui/Port.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/Port.cpp')
-rw-r--r--src/gui/Port.cpp534
1 files changed, 0 insertions, 534 deletions
diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp
deleted file mode 100644
index 9742cee3..00000000
--- a/src/gui/Port.cpp
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- This file is part of Ingen.
- Copyright 2007-2016 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 <string>
-
-#include "ganv/Module.hpp"
-#include "ingen/Configuration.hpp"
-#include "ingen/Interface.hpp"
-#include "ingen/Log.hpp"
-#include "ingen/URIMap.hpp"
-#include "ingen/client/GraphModel.hpp"
-#include "ingen/client/PortModel.hpp"
-
-#include "App.hpp"
-#include "GraphWindow.hpp"
-#include "Port.hpp"
-#include "PortMenu.hpp"
-#include "RDFS.hpp"
-#include "Style.hpp"
-#include "WidgetFactory.hpp"
-#include "WindowFactory.hpp"
-#include "ingen_config.h"
-#include "rgba.hpp"
-
-using namespace Ingen::Client;
-
-namespace Ingen {
-namespace GUI {
-
-Port*
-Port::create(App& app,
- Ganv::Module& module,
- SPtr<const PortModel> pm,
- bool flip)
-{
- return new Port(app, module, pm, port_label(app, pm), flip);
-}
-
-/** @param flip Make an input port appear as an output port, and vice versa.
- */
-Port::Port(App& app,
- Ganv::Module& module,
- SPtr<const PortModel> pm,
- const std::string& name,
- bool flip)
- : Ganv::Port(module, name,
- flip ? (!pm->is_input()) : pm->is_input(),
- app.style()->get_port_color(pm.get()))
- , _app(app)
- , _port_model(pm)
- , _entered(false)
- , _flipped(flip)
-{
- assert(pm);
-
- if (app.can_control(pm.get())) {
- show_control();
- pm->signal_value_changed().connect(
- sigc::mem_fun(this, &Port::value_changed));
- }
-
- port_properties_changed();
-
- 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_activity().connect(
- sigc::mem_fun(this, &Port::activity));
- pm->signal_moved().connect(
- sigc::mem_fun(this, &Port::moved));
-
- signal_value_changed.connect(
- sigc::mem_fun(this, &Port::on_value_changed));
-
- signal_event().connect(
- sigc::mem_fun(this, &Port::on_event));
-
- set_is_controllable(pm->is_numeric() && pm->is_input());
-
- Ganv::Port::set_beveled(model()->is_a(_app.uris().lv2_ControlPort) ||
- model()->has_property(_app.uris().atom_bufferType,
- _app.uris().atom_Sequence));
-
- for (const auto& p : pm->properties()) {
- property_changed(p.first, p.second);
- }
-
- update_metadata();
- value_changed(pm->value());
-}
-
-Port::~Port()
-{
- _app.activity_port_destroyed(this);
-}
-
-std::string
-Port::port_label(App& app, SPtr<const PortModel> pm)
-{
- if (!pm) {
- return "";
- }
-
- std::string label;
- if (app.world()->conf().option("port-labels").get<int32_t>()) {
- if (app.world()->conf().option("human-names").get<int32_t>()) {
- const Atom& name = pm->get_property(app.uris().lv2_name);
- if (name.type() == app.forge().String) {
- label = name.ptr<char>();
- } else {
- const SPtr<const BlockModel> parent(
- dynamic_ptr_cast<const BlockModel>(pm->parent()));
- if (parent && parent->plugin_model()) {
- label = parent->plugin_model()->port_human_name(pm->index());
- }
- }
- } else {
- label = pm->path().symbol();
- }
- }
- return label;
-}
-
-void
-Port::ensure_label()
-{
- if (!get_label()) {
- set_label(port_label(_app, _port_model.lock()).c_str());
- }
-}
-
-void
-Port::update_metadata()
-{
- SPtr<const PortModel> pm = _port_model.lock();
- 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;
- float max = 1.0f;
- parent->port_value_range(pm, min, max, _app.sample_rate());
- set_control_min(min);
- set_control_max(max);
- }
- }
-}
-
-bool
-Port::show_menu(GdkEventButton* ev)
-{
- PortMenu* menu = nullptr;
- WidgetFactory::get_widget_derived("object_menu", menu);
- if (!menu) {
- _app.log().error("Failed to load port menu widget\n");
- return false;
- }
-
- menu->init(_app, model(), _flipped);
- menu->popup(ev->button, ev->time);
- return true;
-}
-
-void
-Port::moved()
-{
- if (_app.world()->conf().option("port-labels").get<int32_t>() &&
- !_app.world()->conf().option("human-names").get<int32_t>()) {
- set_label(model()->symbol().c_str());
- }
-}
-
-void
-Port::on_value_changed(double value)
-{
- const URIs& uris = _app.uris();
- const Atom& current_value = model()->value();
- if (current_value.type() != uris.forge.Float) {
- return; // Non-float, unsupported
- }
-
- if (current_value.get<float>() == (float)value) {
- return; // No change
- }
-
- const Atom atom = _app.forge().make(float(value));
- _app.set_property(model()->uri(),
- _app.world()->uris().ingen_value,
- atom);
-
- if (_entered) {
- GraphBox* box = get_graph_box();
- if (box) {
- box->show_port_status(model().get(), atom);
- }
- }
-}
-
-void
-Port::value_changed(const Atom& value)
-{
- if (value.type() == _app.forge().Float && !get_grabbed()) {
- Ganv::Port::set_control_value(value.get<float>());
- }
-}
-
-void
-Port::on_scale_point_activated(float f)
-{
- _app.set_property(model()->uri(),
- _app.world()->uris().ingen_value,
- _app.world()->forge().make(f));
-}
-
-Gtk::Menu*
-Port::build_enum_menu()
-{
- SPtr<const BlockModel> block = dynamic_ptr_cast<BlockModel>(model()->parent());
- Gtk::Menu* menu = Gtk::manage(new Gtk::Menu());
-
- PluginModel::ScalePoints points = block->plugin_model()->port_scale_points(
- model()->index());
- for (auto i = points.begin(); i != points.end(); ++i) {
- menu->items().push_back(Gtk::Menu_Helpers::MenuElem(i->second));
- Gtk::MenuItem* menu_item = &(menu->items().back());
- menu_item->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &Port::on_scale_point_activated),
- i->first));
- }
-
- return menu;
-}
-
-void
-Port::on_uri_activated(const URI& uri)
-{
- _app.set_property(model()->uri(),
- _app.world()->uris().ingen_value,
- _app.world()->forge().make_urid(
- _app.world()->uri_map().map_uri(uri.c_str())));
-}
-
-Gtk::Menu*
-Port::build_uri_menu()
-{
- World* world = _app.world();
- SPtr<const BlockModel> block = dynamic_ptr_cast<BlockModel>(model()->parent());
- Gtk::Menu* menu = Gtk::manage(new Gtk::Menu());
-
- // Get the port designation, which should be a rdf:Property
- const Atom& designation_atom = model()->get_property(
- _app.uris().lv2_designation);
- if (!designation_atom.is_valid()) {
- return nullptr;
- }
-
- LilvNode* designation = lilv_new_uri(
- world->lilv_world(), world->forge().str(designation_atom, false).c_str());
- LilvNode* rdfs_range = lilv_new_uri(
- world->lilv_world(), LILV_NS_RDFS "range");
-
- // Get every class in the range of the port's property
- RDFS::URISet ranges;
- LilvNodes* range = lilv_world_find_nodes(
- world->lilv_world(), designation, rdfs_range, nullptr);
- LILV_FOREACH(nodes, r, range) {
- ranges.insert(URI(lilv_node_as_string(lilv_nodes_get(range, r))));
- }
- RDFS::classes(world, ranges, false);
-
- // Get all objects in range
- RDFS::Objects values = RDFS::instances(world, ranges);
-
- // Add a menu item for each such class
- for (const auto& v : values) {
- if (!v.first.empty()) {
- const std::string qname = world->rdf_world()->prefixes().qualify(v.second);
- const std::string label = qname + " - " + v.first;
- menu->items().push_back(Gtk::Menu_Helpers::MenuElem(label));
- Gtk::MenuItem* menu_item = &(menu->items().back());
- menu_item->signal_activate().connect(
- sigc::bind(sigc::mem_fun(this, &Port::on_uri_activated),
- v.second));
- }
- }
-
- return menu;
-}
-
-bool
-Port::on_event(GdkEvent* ev)
-{
- GraphBox* box = nullptr;
- switch (ev->type) {
- case GDK_ENTER_NOTIFY:
- _entered = true;
- if ((box = get_graph_box())) {
- box->object_entered(model().get());
- }
- return false;
- case GDK_LEAVE_NOTIFY:
- _entered = false;
- if ((box = get_graph_box())) {
- box->object_left(model().get());
- }
- return false;
- case GDK_BUTTON_PRESS:
- if (ev->button.button == 1) {
- if (model()->is_enumeration()) {
- Gtk::Menu* menu = build_enum_menu();
- menu->popup(ev->button.button, ev->button.time);
- return true;
- } else if (model()->is_uri()) {
- Gtk::Menu* menu = build_uri_menu();
- if (menu) {
- menu->popup(ev->button.button, ev->button.time);
- return true;
- }
- }
- } else if (ev->button.button == 3) {
- return show_menu(&ev->button);
- }
- break;
- default:
- break;
- }
-
- return false;
-}
-
-inline static uint32_t
-peak_color(float peak)
-{
- static const uint32_t min = 0x4A8A0EC0;
- static const uint32_t max = 0xFFCE1FC0;
- static const uint32_t peak_min = 0xFF561FC0;
- static const uint32_t peak_max = 0xFF0A38C0;
-
- if (peak < 1.0) {
- return rgba_interpolate(min, max, peak);
- } else {
- return rgba_interpolate(peak_min, peak_max, fminf(peak, 2.0f) - 1.0f);
- }
-}
-
-void
-Port::activity(const Atom& value)
-{
- if (model()->is_a(_app.uris().lv2_AudioPort)) {
- set_fill_color(peak_color(value.get<float>()));
- } else if (_app.can_control(model().get()) && value.type() == _app.uris().atom_Float) {
- Ganv::Port::set_control_value(value.get<float>());
- } else {
- _app.port_activity(this);
- }
-}
-
-GraphBox*
-Port::get_graph_box() const
-{
- SPtr<const GraphModel> graph = dynamic_ptr_cast<const GraphModel>(model()->parent());
- GraphBox* box = _app.window_factory()->graph_box(graph);
- if (!box) {
- graph = dynamic_ptr_cast<const GraphModel>(model()->parent()->parent());
- box = _app.window_factory()->graph_box(graph);
- }
- return box;
-}
-
-void
-Port::set_type_tag()
-{
- const URIs& uris = _app.uris();
- std::string tag;
- if (model()->is_a(_app.uris().lv2_AudioPort)) {
- tag = "~";
- } else if (model()->is_a(_app.uris().lv2_CVPort)) {
- tag = "ℝ̰";
- } else if (model()->is_a(_app.uris().lv2_ControlPort)) {
- if (model()->is_enumeration()) {
- tag = "…";
- } else if (model()->is_integer()) {
- tag = "ℤ";
- } else if (model()->is_toggle()) {
- tag = ((model()->value() != _app.uris().forge.make(0.0f))
- ? "☑" : "☐");
-
- } else {
- tag = "ℝ";
- }
- } else if (model()->is_a(_app.uris().atom_AtomPort)) {
- if (model()->supports(_app.uris().atom_Float)) {
- if (model()->is_toggle()) {
- tag = ((model()->value() != _app.uris().forge.make(0.0f))
- ? "☑" : "☐");
- } else {
- tag = "ℝ";
- }
- }
- if (model()->supports(_app.uris().atom_Int)) {
- tag += "ℤ";
- }
- if (model()->supports(_app.uris().midi_MidiEvent)) {
- tag += "𝕄";
- }
- if (model()->supports(_app.uris().patch_Message)) {
- if (tag.empty()) {
- tag += "=";
- } else {
- tag += "̿";
- }
- }
- if (tag.empty()) {
- tag = "*";
- }
-
- if (model()->has_property(uris.atom_bufferType, uris.atom_Sequence)) {
- tag += "̤";
- }
- }
-
- if (!tag.empty()) {
- set_value_label(tag.c_str());
- }
-}
-
-void
-Port::port_properties_changed()
-{
- if (model()->is_toggle()) {
- set_control_is_toggle(true);
- } else if (model()->is_integer()) {
- set_control_is_integer(true);
- }
- set_type_tag();
-}
-
-void
-Port::property_changed(const URI& key, const Atom& value)
-{
- const URIs& uris = _app.uris();
- if (value.type() == uris.forge.Float) {
- float val = value.get<float>();
- if (key == uris.ingen_value && !get_grabbed()) {
- Ganv::Port::set_control_value(val);
- if (model()->is_toggle()) {
- std::string tag = (val == 0.0f) ? "☐" : "☑";
- if (model()->is_a(_app.uris().lv2_CVPort)) {
- tag += "̰";
- } else if (model()->has_property(uris.atom_bufferType,
- uris.atom_Sequence)) {
- tag += "̤";
- }
- set_value_label(tag.c_str());
- }
- } else if (key == uris.lv2_minimum) {
- if (model()->port_property(uris.lv2_sampleRate)) {
- val *= _app.sample_rate();
- }
- set_control_min(val);
- } else if (key == uris.lv2_maximum) {
- if (model()->port_property(uris.lv2_sampleRate)) {
- val *= _app.sample_rate();
- }
- set_control_max(val);
- }
- } else if (key == uris.lv2_portProperty) {
- port_properties_changed();
- } else if (key == uris.lv2_name) {
- if (value.type() == uris.forge.String &&
- _app.world()->conf().option("port-labels").get<int32_t>() &&
- _app.world()->conf().option("human-names").get<int32_t>()) {
- set_label(value.ptr<char>());
- }
- } else if (key == uris.rdf_type || key == uris.atom_bufferType) {
- set_fill_color(_app.style()->get_port_color(model().get()));
- Ganv::Port::set_beveled(model()->is_a(uris.lv2_ControlPort) ||
- model()->has_property(uris.atom_bufferType,
- uris.atom_Sequence));
- }
-}
-
-void
-Port::property_removed(const URI& key, const Atom& value)
-{
- const URIs& uris = _app.uris();
- if (key == uris.lv2_minimum || key == uris.lv2_maximum) {
- update_metadata();
- } else if (key == uris.rdf_type || key == uris.atom_bufferType) {
- Ganv::Port::set_beveled(model()->is_a(uris.lv2_ControlPort) ||
- model()->has_property(uris.atom_bufferType,
- uris.atom_Sequence));
- }
-}
-
-bool
-Port::on_selected(gboolean b)
-{
- if (b) {
- SPtr<const PortModel> pm = _port_model.lock();
- if (pm) {
- 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;
-#ifdef HAVE_WEBKIT
- html = true;
-#endif
- const std::string& doc = block->plugin_model()->port_documentation(
- pm->index(), html);
- win->set_documentation(doc, html);
- }
- }
- }
-
- return true;
-}
-
-} // namespace GUI
-} // namespace Ingen