diff options
author | David Robillard <d@drobilla.net> | 2008-10-12 06:47:11 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-10-12 06:47:11 +0000 |
commit | d154ae5b114a6a04acd17a83f6d59caa9ec1005a (patch) | |
tree | 5803f386ddfc608ec565226ad658c9562157ada7 /src/engine | |
parent | 57698964f1e88b2b74a0ce31ffaba3044d884dac (diff) | |
download | ingen-d154ae5b114a6a04acd17a83f6d59caa9ec1005a.tar.gz ingen-d154ae5b114a6a04acd17a83f6d59caa9ec1005a.tar.bz2 ingen-d154ae5b114a6a04acd17a83f6d59caa9ec1005a.zip |
Split OSC/HTTP/JACK dependencies from ingen into separate libraries so engine library doesn't have a link time dependence on liblo/soap/libjack.
Preliminary Ingen LV2 code wrapper (not functional yet).
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@1653 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/engine')
-rw-r--r-- | src/engine/AudioDriver.hpp | 4 | ||||
-rw-r--r-- | src/engine/Engine.cpp | 96 | ||||
-rw-r--r-- | src/engine/Engine.hpp | 13 | ||||
-rw-r--r-- | src/engine/HTTPEngineReceiver.cpp | 13 | ||||
-rw-r--r-- | src/engine/HTTPEngineReceiver.hpp | 6 | ||||
-rw-r--r-- | src/engine/JackAudioDriver.cpp | 13 | ||||
-rw-r--r-- | src/engine/JackAudioDriver.hpp | 8 | ||||
-rw-r--r-- | src/engine/OSCEngineReceiver.cpp | 11 | ||||
-rw-r--r-- | src/engine/OSCEngineReceiver.hpp | 6 | ||||
-rw-r--r-- | src/engine/QueuedEngineInterface.cpp | 11 | ||||
-rw-r--r-- | src/engine/QueuedEngineInterface.hpp | 5 | ||||
-rw-r--r-- | src/engine/events/SendPortValueEvent.hpp | 4 | ||||
-rw-r--r-- | src/engine/ingen.lv2/ingen_lv2.cpp | 193 | ||||
-rw-r--r-- | src/engine/ingen_engine.cpp | 8 | ||||
-rw-r--r-- | src/engine/wscript | 41 |
15 files changed, 335 insertions, 97 deletions
diff --git a/src/engine/AudioDriver.hpp b/src/engine/AudioDriver.hpp index 6b5ea8dc..1a611846 100644 --- a/src/engine/AudioDriver.hpp +++ b/src/engine/AudioDriver.hpp @@ -42,9 +42,9 @@ public: AudioDriver() : Driver(DataType::AUDIO) {} virtual void set_root_patch(PatchImpl* patch) = 0; - virtual PatchImpl* root_patch() = 0; + virtual PatchImpl* root_patch() = 0; - virtual void add_port(DriverPort* port) = 0; + virtual void add_port(DriverPort* port) = 0; virtual DriverPort* remove_port(const Raul::Path& path) = 0; virtual SampleCount buffer_size() const = 0; diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index a7681156..bcc5a54c 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -28,7 +28,6 @@ #include "Event.hpp" #include "common/interface/EventType.hpp" #include "shared/Store.hpp" -#include "JackAudioDriver.hpp" #include "NodeFactory.hpp" #include "ClientBroadcaster.hpp" #include "PatchImpl.hpp" @@ -39,21 +38,12 @@ #include "PostProcessor.hpp" #include "events/CreatePatchEvent.hpp" #include "events/EnablePatchEvent.hpp" -#ifdef HAVE_LIBLO -#include "OSCEngineReceiver.hpp" -#endif -#ifdef HAVE_SOUP -#include "HTTPEngineReceiver.hpp" -#endif #include "PostProcessor.hpp" +#include "AudioDriver.hpp" #include "ProcessSlave.hpp" #include "ProcessContext.hpp" #include "MessageContext.hpp" #include "ThreadManager.hpp" -#include "QueuedEngineInterface.hpp" -#ifdef HAVE_JACK_MIDI -#include "JackMidiDriver.hpp" -#endif using namespace std; namespace Ingen { @@ -125,6 +115,17 @@ Engine::driver(DataType type, EventType event_type) } +void +Engine::set_driver(DataType type, SharedPtr<Driver> driver) +{ + if (type == DataType::AUDIO) { + _audio_driver = PtrCast<AudioDriver>(driver); + } else { + cerr << "WARNING: Unable to set driver for type " << type.uri() << endl; + } +} + + int Engine::main() { @@ -164,67 +165,20 @@ Engine::main_iteration() void -Engine::start_jack_driver() -{ - if ( ! _audio_driver) - _audio_driver = SharedPtr<AudioDriver>(new JackAudioDriver(*this)); - else - cerr << "[Engine::start_jack_driver] Audio driver already running" << endl; -} - - -void -Engine::start_osc_driver(int port) +Engine::set_event_source(SharedPtr<EventSource> source) { -#ifdef HAVE_LIBLO - if (_event_source) { - cerr << "WARNING: Replacing event source" << endl; - _event_source.reset(); - } - - _event_source = SharedPtr<EventSource>(new OSCEngineReceiver( - *this, pre_processor_queue_size, port)); -#endif -} + if (_event_source) + cerr << "Warning: Dropped event source (engine interface)" << endl; - -void -Engine::start_http_driver(int port) -{ -#ifdef HAVE_SOUP - // FIXE: leak - HTTPEngineReceiver* server = new HTTPEngineReceiver(*this, port); - server->activate(); -#endif + _event_source = source; } - - -SharedPtr<QueuedEngineInterface> -Engine::new_queued_interface() -{ - if (_event_source) { - cerr << "WARNING: Replacing event source" << endl; - _event_source.reset(); - } - - SharedPtr<QueuedEngineInterface> result(new QueuedEngineInterface( - *this, Ingen::event_queue_size, Ingen::event_queue_size)); - - _event_source = result; - return result; -} -/* void -Engine::set_event_source(SharedPtr<EventSource> source) +Engine::set_midi_driver(MidiDriver* driver) { - if (_event_source) - cerr << "Warning: Dropped event source (engine interface)" << endl; - - _event_source = source; + _midi_driver = driver; } -*/ bool @@ -234,15 +188,12 @@ Engine::activate(size_t parallelism) return false; assert(_audio_driver); - assert(_event_source); -#ifdef HAVE_JACK_MIDI - _midi_driver = new JackMidiDriver(((JackAudioDriver*)_audio_driver.get())->jack_client()); -#else - _midi_driver = new DummyMidiDriver(); -#endif + if (!_midi_driver) + _midi_driver = new DummyMidiDriver(); - _event_source->activate(); + if (_event_source) + _event_source->activate(); // Create root patch @@ -278,7 +229,8 @@ Engine::deactivate() if (!_activated) return; - _event_source->deactivate(); + if (_event_source) + _event_source->deactivate(); /*for (Tree<GraphObject*>::iterator i = _engine_store->objects().begin(); i != _engine_store->objects().end(); ++i) diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index 9c824c9a..e2e5ea09 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -43,7 +43,6 @@ class EventSource; class PostProcessor; class Event; class QueuedEvent; -class QueuedEngineInterface; class Driver; class ProcessSlave; class ProcessContext; @@ -74,12 +73,6 @@ public: * Note that it will take some time. */ virtual void quit() { _quit_flag = true; } - virtual void start_jack_driver(); - virtual void start_osc_driver(int port); - virtual void start_http_driver(int port); - - virtual SharedPtr<QueuedEngineInterface> new_queued_interface(); - virtual bool activate(size_t parallelism); virtual void deactivate(); @@ -102,6 +95,12 @@ public: /** Return the active driver for the given type */ Driver* driver(DataType type, EventType event_type); + /** Set the driver for the given data type (replacing the old) */ + virtual void set_driver(DataType type, SharedPtr<Driver> driver); + + virtual void set_event_source(SharedPtr<EventSource> source); + virtual void set_midi_driver(MidiDriver* driver); + Ingen::Shared::World* world() { return _world; } typedef std::vector<ProcessSlave*> ProcessSlaves; diff --git a/src/engine/HTTPEngineReceiver.cpp b/src/engine/HTTPEngineReceiver.cpp index 58b2bbe8..d7d246db 100644 --- a/src/engine/HTTPEngineReceiver.cpp +++ b/src/engine/HTTPEngineReceiver.cpp @@ -202,5 +202,16 @@ HTTPEngineReceiver::ReceiveThread::_run() soup_server_run(_receiver._server); } - } // namespace Ingen + + +extern "C" { + +Ingen::HTTPEngineReceiver* +new_http_receiver(Ingen::Engine& engine, uint16_t port) +{ + return new Ingen::HTTPEngineReceiver(engine, port); +} + +} // extern "C" + diff --git a/src/engine/HTTPEngineReceiver.hpp b/src/engine/HTTPEngineReceiver.hpp index f156d855..8d474bf5 100644 --- a/src/engine/HTTPEngineReceiver.hpp +++ b/src/engine/HTTPEngineReceiver.hpp @@ -56,4 +56,10 @@ private: } // namespace Ingen +extern "C" { + /// Module interface + extern Ingen::HTTPEngineReceiver* new_http_receiver( + Ingen::Engine& engine, uint16_t port); +} + #endif // HTTPENGINERECEIVER_H diff --git a/src/engine/JackAudioDriver.cpp b/src/engine/JackAudioDriver.cpp index fe5fa0b7..15c8f785 100644 --- a/src/engine/JackAudioDriver.cpp +++ b/src/engine/JackAudioDriver.cpp @@ -36,6 +36,7 @@ #include "EventSource.hpp" #include "AudioBuffer.hpp" #include "ProcessSlave.hpp" +#include "JackMidiDriver.hpp" using namespace std; @@ -173,6 +174,9 @@ JackAudioDriver::activate() _engine.lash_driver()->set_jack_client_name(jack_client_get_name(_client)); #endif*/ } + + if (!_engine.midi_driver()) + _engine.set_midi_driver(new JackMidiDriver(_client)); } @@ -382,3 +386,12 @@ JackAudioDriver::_buffer_size_cb(jack_nframes_t nframes) } // namespace Ingen +Ingen::JackAudioDriver* +new_jack_audio_driver( + Ingen::Engine& engine, + std::string server_name, + jack_client_t* jack_client) +{ + return new Ingen::JackAudioDriver(engine, server_name, jack_client); +} + diff --git a/src/engine/JackAudioDriver.hpp b/src/engine/JackAudioDriver.hpp index 3beb775a..8cf2e5d3 100644 --- a/src/engine/JackAudioDriver.hpp +++ b/src/engine/JackAudioDriver.hpp @@ -182,4 +182,12 @@ inline int JackAudioDriver::sample_rate_cb(jack_nframes_t nframes, void* jack_dr } // namespace Ingen +extern "C" { + /// Module interface + extern Ingen::JackAudioDriver* new_jack_audio_driver( + Ingen::Engine& engine, + std::string server_name = "", + jack_client_t* jack_client = 0); +} + #endif // JACKAUDIODRIVER_H diff --git a/src/engine/OSCEngineReceiver.cpp b/src/engine/OSCEngineReceiver.cpp index 87f4abd2..d9c8f7c2 100644 --- a/src/engine/OSCEngineReceiver.cpp +++ b/src/engine/OSCEngineReceiver.cpp @@ -882,3 +882,14 @@ OSCEngineReceiver::unknown_cb(const char* path, const char* types, lo_arg** argv } // namespace Ingen + + +extern "C" { + +Ingen::OSCEngineReceiver* +new_osc_receiver(Ingen::Engine& engine, size_t queue_size, uint16_t port) +{ + return new Ingen::OSCEngineReceiver(engine, queue_size, port); +} + +} // extern "C" diff --git a/src/engine/OSCEngineReceiver.hpp b/src/engine/OSCEngineReceiver.hpp index 361bd4bb..05eb0322 100644 --- a/src/engine/OSCEngineReceiver.hpp +++ b/src/engine/OSCEngineReceiver.hpp @@ -126,4 +126,10 @@ private: } // namespace Ingen +extern "C" { + /// Module interface + extern Ingen::OSCEngineReceiver* new_osc_receiver( + Ingen::Engine& engine, size_t queue_size, uint16_t port); +} + #endif // OSCENGINERECEIVER_H diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp index 356a6980..4e0e82d1 100644 --- a/src/engine/QueuedEngineInterface.cpp +++ b/src/engine/QueuedEngineInterface.cpp @@ -18,6 +18,7 @@ #include <iostream> #include "QueuedEngineInterface.hpp" #include "config.h" +#include "tuning.hpp" #include "QueuedEventSource.hpp" #include "events.hpp" #include "Engine.hpp" @@ -368,3 +369,13 @@ QueuedEngineInterface::request_all_objects() } // namespace Ingen +extern "C" { + +Ingen::QueuedEngineInterface* +new_queued_interface(Ingen::Engine& engine) +{ + return new Ingen::QueuedEngineInterface(engine, Ingen::event_queue_size, Ingen::event_queue_size); +} + +} // extern "C" + diff --git a/src/engine/QueuedEngineInterface.hpp b/src/engine/QueuedEngineInterface.hpp index 89810434..5665c2c7 100644 --- a/src/engine/QueuedEngineInterface.hpp +++ b/src/engine/QueuedEngineInterface.hpp @@ -22,6 +22,7 @@ #include <string> #include <memory> #include <raul/SharedPtr.hpp> +#include "tuning.hpp" #include "interface/EngineInterface.hpp" #include "interface/ClientInterface.hpp" #include "Responder.hpp" @@ -156,5 +157,9 @@ private: } // namespace Ingen +extern "C" { + extern Ingen::QueuedEngineInterface* new_queued_interface(Ingen::Engine& engine); +} + #endif // QUEUEDENGINEINTERFACE_H diff --git a/src/engine/events/SendPortValueEvent.hpp b/src/engine/events/SendPortValueEvent.hpp index e8505914..ad9ae5a1 100644 --- a/src/engine/events/SendPortValueEvent.hpp +++ b/src/engine/events/SendPortValueEvent.hpp @@ -19,8 +19,8 @@ #define SENDPORTVALUEEVENT_H #include <string> -#include "Event.hpp" -#include "types.hpp" +#include "engine/Event.hpp" +#include "engine/types.hpp" using std::string; namespace Ingen { diff --git a/src/engine/ingen.lv2/ingen_lv2.cpp b/src/engine/ingen.lv2/ingen_lv2.cpp new file mode 100644 index 00000000..4c81c42b --- /dev/null +++ b/src/engine/ingen.lv2/ingen_lv2.cpp @@ -0,0 +1,193 @@ +/* Ingen.LV2 - A thin wrapper which allows Ingen to run as an LV2 plugin. + * Copyright (C) 2008 Dave Robillard <http://drobilla.net> + * + * 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 <stdlib.h> +#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<Ingen::Engine> 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)); + + plugin->world = Ingen::Shared::get_world(); + plugin->engine = SharedPtr<Engine>(new Engine(plugin->world)); + plugin->world->local_engine = plugin->engine; + + // FIXME: fixed buffer size + plugin->engine->set_driver(DataType::AUDIO, + SharedPtr<Driver>(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" + diff --git a/src/engine/ingen_engine.cpp b/src/engine/ingen_engine.cpp index 3c393a7f..137499ee 100644 --- a/src/engine/ingen_engine.cpp +++ b/src/engine/ingen_engine.cpp @@ -17,10 +17,10 @@ #include "config.h" +#include <string> #include <raul/Process.hpp> #include "ingen_engine.hpp" #include "Engine.hpp" -#include "QueuedEngineInterface.hpp" #include "tuning.hpp" #include "util.hpp" @@ -39,18 +39,16 @@ launch_osc_engine(int port) { char port_str[6]; snprintf(port_str, 6, "%u", port); - const string cmd = string("ingen -e --engine-port=").append(port_str); + const std::string cmd = std::string("ingen -e --engine-port=").append(port_str); if (Raul::Process::launch(cmd)) { return true; - //return SharedPtr<EngineInterface>(new OSCEngineSender( - // string("osc.udp://localhost:").append(port_str))); } else { std::cerr << "Failed to launch engine process." << std::endl; - //return SharedPtr<EngineInterface>(); return false; } } + } // namespace Ingen diff --git a/src/engine/wscript b/src/engine/wscript index 1f2ec1f3..ad5c3a96 100644 --- a/src/engine/wscript +++ b/src/engine/wscript @@ -18,8 +18,6 @@ def build(bld): GraphObjectImpl.cpp InputPort.cpp InternalPlugin.cpp - JackAudioDriver.cpp - JackMidiDriver.cpp LADSPAPlugin.cpp LV2Info.cpp LV2Plugin.cpp @@ -36,7 +34,6 @@ def build(bld): PortImpl.cpp PostProcessor.cpp ProcessSlave.cpp - QueuedEngineInterface.cpp QueuedEvent.cpp QueuedEventSource.cpp TransportNode.cpp @@ -75,13 +72,41 @@ def build(bld): obj.source += ' LADSPANode.cpp ' if bld.env()['HAVE_SLV2']: obj.source += ' LV2Node.cpp ' - if bld.env()['HAVE_SOUP']: - obj.source += ' HTTPEngineReceiver.cpp ' - if bld.env()['HAVE_LIBLO']: - obj.source += ' OSCEngineReceiver.cpp OSCClientSender.cpp ' obj.includes = ['.', '..', '../common', './events'] obj.name = 'libingen_engine' obj.target = 'ingen_engine' obj.inst_dir = 'lib/ingen' - autowaf.use_lib(bld, obj, 'GLIBMM GTHREAD LV2CORE SLV2 JACK LIBLO RAUL REDLANDMM SOUP') + core_libs = 'GLIBMM GTHREAD LV2CORE SLV2 RAUL REDLANDMM' + autowaf.use_lib(bld, obj, core_libs) + + if bld.env()['HAVE_SOUP'] or bld.env()['HAVE_LIBLO']: + obj.source += ' QueuedEngineInterface.cpp ' + + if bld.env()['HAVE_SOUP']: + obj = bld.create_obj('cpp', 'shlib') + obj.source = 'HTTPEngineReceiver.cpp' + obj.includes = ['.', '..', '../common', './events', '../engine'] + obj.name = 'libingen_engine_http' + obj.target = 'ingen_engine_http' + obj.inst_dir = 'lib/ingen' + autowaf.use_lib(bld, obj, core_libs + ' SOUP') + + if bld.env()['HAVE_LIBLO']: + obj = bld.create_obj('cpp', 'shlib') + obj.source = 'OSCClientSender.cpp OSCEngineReceiver.cpp' + obj.includes = ['.', '..', '../common', './events', '../engine'] + obj.name = 'libingen_engine_osc' + obj.target = 'ingen_engine_osc' + obj.inst_dir = 'lib/ingen' + autowaf.use_lib(bld, obj, core_libs + ' LIBLO') + + if bld.env()['HAVE_JACK']: + obj = bld.create_obj('cpp', 'shlib') + obj.source = 'JackAudioDriver.cpp JackMidiDriver.cpp' + obj.includes = ['.', '..', '../common', './events', '../engine'] + obj.name = 'libingen_engine_jack' + obj.target = 'ingen_engine_jack' + obj.inst_dir = 'lib/ingen' + autowaf.use_lib(bld, obj, core_libs + ' JACK') + |