/* This file is part of Ingen. Copyright 2007-2015 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 "App.hpp" #include "GraphBox.hpp" #include "ingen/AtomReader.hpp" #include "ingen/AtomSink.hpp" #include "ingen/AtomWriter.hpp" #include "ingen/Forge.hpp" #include "ingen/Interface.hpp" #include "ingen/Properties.hpp" #include "ingen/URI.hpp" #include "ingen/URIs.hpp" #include "ingen/World.hpp" #include "ingen/client/ClientStore.hpp" #include "ingen/client/GraphModel.hpp" #include "ingen/client/SigClientInterface.hpp" #include "ingen/ingen.h" #include "ingen/paths.hpp" #include "ingen/runtime_paths.hpp" #include "ingen/types.hpp" #include "lv2/atom/atom.h" #include "lv2/atom/util.h" #include "lv2/core/lv2.h" #include "lv2/core/lv2.h" #include "lv2/log/log.h" #include "lv2/ui/ui.h" #include "lv2/urid/urid.h" #include "lv2/urid/urid.h" #include "raul/Path.hpp" #include #include #include #define INGEN_LV2_UI_URI INGEN_NS "GraphUIGtk2" namespace ingen { /** A sink that writes atoms to a port via the UI extension. */ struct IngenLV2AtomSink : public AtomSink { IngenLV2AtomSink(URIs& uris, LV2UI_Write_Function ui_write, LV2UI_Controller ui_controller) : _uris(uris) , _ui_write(ui_write) , _ui_controller(ui_controller) {} bool write(const LV2_Atom* atom, int32_t default_id) override { _ui_write(_ui_controller, 0, lv2_atom_total_size(atom), _uris.atom_eventTransfer, atom); return true; } URIs& _uris; LV2UI_Write_Function _ui_write; LV2UI_Controller _ui_controller; }; struct IngenLV2UI { IngenLV2UI() : argc(0) , argv(nullptr) , forge(nullptr) , world(nullptr) , sink(nullptr) {} int argc; char** argv; Forge* forge; World* world; IngenLV2AtomSink* sink; SPtr app; SPtr view; SPtr engine; SPtr reader; SPtr client; }; } // namespace ingen static LV2UI_Handle instantiate(const LV2UI_Descriptor* descriptor, const char* plugin_uri, const char* bundle_path, LV2UI_Write_Function write_function, LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features) { #if __cplusplus >= 201103L using ingen::SPtr; #endif ingen::set_bundle_path(bundle_path); ingen::IngenLV2UI* ui = new ingen::IngenLV2UI(); LV2_URID_Map* map = nullptr; LV2_URID_Unmap* unmap = nullptr; LV2_Log_Log* log = nullptr; for (int i = 0; features[i]; ++i) { if (!strcmp(features[i]->URI, LV2_URID__map)) { map = static_cast(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_URID__unmap)) { unmap = static_cast(features[i]->data); } else if (!strcmp(features[i]->URI, LV2_LOG__log)) { log = static_cast(features[i]->data); } } ui->world = new ingen::World(map, unmap, log); ui->forge = new ingen::Forge(ui->world->uri_map()); ui->world->load_configuration(ui->argc, ui->argv); if (!ui->world->load_module("client")) { delete ui; return nullptr; } ui->sink = new ingen::IngenLV2AtomSink( ui->world->uris(), write_function, controller); // Set up an engine interface that writes LV2 atoms ui->engine = SPtr( new ingen::AtomWriter( ui->world->uri_map(), ui->world->uris(), *ui->sink)); ui->world->set_interface(ui->engine); // Create App and client ui->app = ingen::gui::App::create(*ui->world); ui->client = SPtr( new ingen::client::SigClientInterface()); ui->app->set_is_plugin(true); ui->app->attach(ui->client); ui->reader = SPtr( new ingen::AtomReader(ui->world->uri_map(), ui->world->uris(), ui->world->log(), *ui->client.get())); // Create empty root graph model ingen::Properties props; props.emplace(ui->app->uris().rdf_type, ingen::Property(ui->app->uris().ingen_Graph)); ui->app->store()->put(ingen::main_uri(), props); // Create a GraphBox for the root and set as the UI widget SPtr root = std::dynamic_pointer_cast( ui->app->store()->object(Raul::Path("/"))); ui->view = ingen::gui::GraphBox::create(*ui->app, root); ui->view->unparent(); *widget = ui->view->gobj(); // Request the actual root graph ui->world->interface()->get(ingen::main_uri()); return ui; } static void cleanup(LV2UI_Handle handle) { ingen::IngenLV2UI* ui = static_cast(handle); delete ui; } static void port_event(LV2UI_Handle handle, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer) { ingen::IngenLV2UI* ui = static_cast(handle); const LV2_Atom* atom = static_cast(buffer); ui->reader->write(atom); } static const void* extension_data(const char* uri) { return nullptr; } static const LV2UI_Descriptor descriptor = { INGEN_LV2_UI_URI, instantiate, cleanup, port_event, extension_data }; LV2_SYMBOL_EXPORT const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index) { switch (index) { case 0: return &descriptor; default: return nullptr; } }