/* Ingen.LV2 - A thin wrapper which allows Ingen to run as an LV2 plugin. * Copyright (C) 2008-2009 Dave Robillard * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This library 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 General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef PLUGIN_URI #error "This file requires PLUGIN_URI to be defined" #endif #include #include "lv2.h" #include "engine/Engine.hpp" #include "engine/AudioDriver.hpp" #include "engine/ProcessContext.hpp" #include "engine/PatchImpl.hpp" #include "module/World.hpp" extern "C" { using namespace Ingen; /* Plugin */ struct IngenLV2Driver : public Ingen::AudioDriver { IngenLV2Driver(Engine& engine, SampleCount buffer_size, SampleCount sample_rate) : _context(engine) , _buffer_size(buffer_size) , _sample_rate(sample_rate) , _frame_time(0) {} void activate() {} void deactivate() {} bool is_activated() const { return true; } void run(uint32_t nframes) { _context.set_time_slice(nframes, _frame_time, _frame_time + nframes); if (_root_patch) _root_patch->process(_context); _frame_time += nframes; } virtual void set_root_patch(PatchImpl* patch) {} virtual PatchImpl* root_patch() { return NULL; } virtual void add_port(DriverPort* port) {} virtual DriverPort* remove_port(const Raul::Path& path) { return NULL; } virtual DriverPort* create_port(DuplexPort* patch_port) { return NULL; } virtual DriverPort* driver_port(const Raul::Path& path) { return NULL; } virtual SampleCount buffer_size() const { return _buffer_size; } virtual SampleCount sample_rate() const { return _sample_rate; } virtual SampleCount frame_time() const { return _frame_time;} virtual bool is_realtime() const { return true; } virtual ProcessContext& context() { return _context; } private: ProcessContext _context; PatchImpl* _root_patch; SampleCount _buffer_size; SampleCount _sample_rate; SampleCount _frame_time; }; struct IngenPlugin { Ingen::Shared::World* world; SharedPtr engine; }; static void ingen_activate(LV2_Handle instance) { IngenPlugin* plugin = (IngenPlugin*)instance; plugin->engine->activate(1); } static void ingen_cleanup(LV2_Handle instance) { IngenPlugin* plugin = (IngenPlugin*)instance; plugin->engine.reset(); Ingen::Shared::destroy_world(); free(instance); } static void ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) { //IngenPlugin* plugin = (IngenPlugin*)instance; } static LV2_Handle ingen_instantiate(const LV2_Descriptor* descriptor, double rate, const char* bundle_path, const LV2_Feature*const* features) { IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); Shared::bundle_path = bundle_path; plugin->world = Ingen::Shared::get_world(); plugin->engine = SharedPtr(new Engine(plugin->world)); plugin->world->local_engine = plugin->engine; // FIXME: fixed buffer size plugin->engine->set_driver(PortType::AUDIO, SharedPtr(new IngenLV2Driver(*plugin->engine, rate, 4096))); return (LV2_Handle)plugin; } static void ingen_run(LV2_Handle instance, uint32_t sample_count) { IngenPlugin* plugin = (IngenPlugin*)instance; ((IngenLV2Driver*)plugin->engine->audio_driver())->run(sample_count); } static const void* ingen_extension_data(const char* uri) { return NULL; } static void ingen_deactivate(LV2_Handle instance) { IngenPlugin* plugin = (IngenPlugin*)instance; plugin->engine->deactivate(); } /* Library */ static LV2_Descriptor *ingen_descriptor = NULL; static void init_descriptor() { ingen_descriptor = (LV2_Descriptor*)malloc(sizeof(LV2_Descriptor)); ingen_descriptor->URI = PLUGIN_URI; ingen_descriptor->instantiate = ingen_instantiate; ingen_descriptor->connect_port = ingen_connect_port; ingen_descriptor->activate = ingen_activate; ingen_descriptor->run = ingen_run; ingen_descriptor->deactivate = ingen_deactivate; ingen_descriptor->cleanup = ingen_cleanup; ingen_descriptor->extension_data = ingen_extension_data; } LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index) { if (!ingen_descriptor) init_descriptor(); switch (index) { case 0: return ingen_descriptor; default: return NULL; } } } // extern "C"