diff options
Diffstat (limited to 'src/gui/Port.cpp')
-rw-r--r-- | src/gui/Port.cpp | 534 |
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 |