From d6b87aa26ef482a8952437f7472b81a2240f01fd Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 21 Jan 2008 15:14:53 +0000 Subject: Work on generic LV2 events. git-svn-id: http://svn.drobilla.net/lad/ingen@1090 a436a847-0d15-0410-975c-d299462d15a1 --- src/libs/engine/BufferFactory.cpp | 13 +- src/libs/engine/ConnectionImpl.cpp | 10 +- src/libs/engine/Engine.cpp | 20 +- src/libs/engine/Engine.hpp | 3 +- src/libs/engine/EventBuffer.cpp | 296 +++++++++++++++++++++ src/libs/engine/EventBuffer.hpp | 97 +++++++ src/libs/engine/InputPort.hpp | 1 - src/libs/engine/JackMidiDriver.cpp | 22 +- src/libs/engine/LV2Info.hpp | 60 +++++ src/libs/engine/LV2Node.cpp | 71 +++-- src/libs/engine/LV2Node.hpp | 2 +- src/libs/engine/LV2Plugin.hpp | 10 +- src/libs/engine/Makefile.am | 7 +- src/libs/engine/MidiBuffer.cpp | 279 ------------------- src/libs/engine/MidiBuffer.hpp | 84 ------ src/libs/engine/MidiControlNode.cpp | 20 +- src/libs/engine/MidiControlNode.hpp | 1 - src/libs/engine/MidiDriver.hpp | 4 +- src/libs/engine/MidiNoteNode.cpp | 21 +- src/libs/engine/MidiNoteNode.hpp | 2 - src/libs/engine/MidiTriggerNode.cpp | 31 ++- src/libs/engine/MidiTriggerNode.hpp | 1 - src/libs/engine/NodeFactory.cpp | 5 +- src/libs/engine/NodeFactory.hpp | 9 +- src/libs/engine/OSCDriver.hpp | 2 +- src/libs/engine/PortImpl.cpp | 14 +- src/libs/engine/events/DestroyEvent.cpp | 2 +- src/libs/engine/events/RenameEvent.cpp | 2 +- src/libs/engine/events/SetPortValueEvent.cpp | 21 +- src/libs/engine/events/SetPortValueQueuedEvent.cpp | 11 +- 30 files changed, 611 insertions(+), 510 deletions(-) create mode 100644 src/libs/engine/EventBuffer.cpp create mode 100644 src/libs/engine/EventBuffer.hpp create mode 100644 src/libs/engine/LV2Info.hpp delete mode 100644 src/libs/engine/MidiBuffer.cpp delete mode 100644 src/libs/engine/MidiBuffer.hpp (limited to 'src/libs/engine') diff --git a/src/libs/engine/BufferFactory.cpp b/src/libs/engine/BufferFactory.cpp index 25b09a56..0358f9eb 100644 --- a/src/libs/engine/BufferFactory.cpp +++ b/src/libs/engine/BufferFactory.cpp @@ -17,8 +17,7 @@ #include "BufferFactory.hpp" #include "AudioBuffer.hpp" -#include "MidiBuffer.hpp" -#include "OSCBuffer.hpp" +#include "EventBuffer.hpp" namespace Ingen { namespace BufferFactory { @@ -27,12 +26,12 @@ namespace BufferFactory { Buffer* create(DataType type, size_t size) { - if (type.is_control() || type.is_audio()) + if (type.is_control()) + return new AudioBuffer(1); + else if (type.is_audio()) return new AudioBuffer(size); - else if (type.is_midi()) - return new MidiBuffer(size); - else if (type.is_osc()) - return new OSCBuffer(size); + else if (type.is_event()) + return new EventBuffer(size); else throw; } diff --git a/src/libs/engine/ConnectionImpl.cpp b/src/libs/engine/ConnectionImpl.cpp index f2bfeda5..9cd6f3c9 100644 --- a/src/libs/engine/ConnectionImpl.cpp +++ b/src/libs/engine/ConnectionImpl.cpp @@ -56,7 +56,7 @@ ConnectionImpl::ConnectionImpl(PortImpl* src_port, PortImpl* dst_port) /*assert((src_port->parent_node()->poly() == dst_port->parent_node()->poly()) || (src_port->parent_node()->poly() == 1 || dst_port->parent_node()->poly() == 1));*/ - if (type() == DataType::MIDI || type() == DataType::OSC) + if (type() == DataType::EVENT) _must_mix = false; // FIXME: kludge if (_must_mix) @@ -167,13 +167,9 @@ ConnectionImpl::process(ProcessContext& context) if (src_port()->poly() > 1) mix_buf->scale(1.0f/(float)src_port()->poly(), 0, _buffer_size-1); - } else if (_must_mix && type() == DataType::MIDI) { + } else if (_must_mix && type() == DataType::EVENT) { - cerr << "WARNING: No MIDI mixing." << endl; - - } else if (_must_mix && type() == DataType::OSC) { - - cerr << "WARNING: No OSC mixing." << endl; + cerr << "WARNING: No event mixing." << endl; } diff --git a/src/libs/engine/Engine.cpp b/src/libs/engine/Engine.cpp index f0b43dc8..0bfcbde7 100644 --- a/src/libs/engine/Engine.cpp +++ b/src/libs/engine/Engine.cpp @@ -26,6 +26,7 @@ #include CONFIG_H_PATH #include "tuning.hpp" #include "Event.hpp" +#include "common/interface/EventType.hpp" #include "JackAudioDriver.hpp" #include "NodeFactory.hpp" #include "ClientBroadcaster.hpp" @@ -97,16 +98,19 @@ Engine::~Engine() Driver* -Engine::driver(DataType type) +Engine::driver(DataType type, EventType event_type) { - if (type == DataType::AUDIO) + if (type == DataType::AUDIO) { return _audio_driver.get(); - else if (type == DataType::MIDI) - return _midi_driver; - else if (type == DataType::OSC) - return _osc_driver; - else - return NULL; + } else if (type == DataType::EVENT) { + if (event_type == EventType::MIDI) { + return _midi_driver; + } else if (event_type == EventType::OSC) { + return _osc_driver; + } + } + + return NULL; } diff --git a/src/libs/engine/Engine.hpp b/src/libs/engine/Engine.hpp index 9bc43ec8..2fa2ff3e 100644 --- a/src/libs/engine/Engine.hpp +++ b/src/libs/engine/Engine.hpp @@ -25,6 +25,7 @@ #include #include "module/global.hpp" #include "interface/DataType.hpp" +#include "interface/EventType.hpp" template class Queue; @@ -91,7 +92,7 @@ public: //LashDriver* lash_driver() const { return _lash_driver; } /** Return the active driver for the given type */ - Driver* driver(DataType type); + Driver* driver(DataType type, EventType event_type); Ingen::Shared::World* world() { return _world; } diff --git a/src/libs/engine/EventBuffer.cpp b/src/libs/engine/EventBuffer.cpp new file mode 100644 index 00000000..b706012c --- /dev/null +++ b/src/libs/engine/EventBuffer.cpp @@ -0,0 +1,296 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard + * + * Ingen 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. + * + * 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 General Public License for 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 + */ + +#define __STDC_LIMIT_MACROS 1 +#include +#include +#include "EventBuffer.hpp" +#include "lv2ext/lv2_event.h" + +using namespace std; + +namespace Ingen { + + +/** Allocate a new event buffer. + * \a capacity is in bytes (not number of events). + */ +EventBuffer::EventBuffer(size_t capacity) + : Buffer(DataType(DataType::EVENT), capacity) + , _latest_frames(0) + , _latest_subframes(0) +{ + if (capacity > UINT32_MAX) { + cerr << "Event buffer size " << capacity << " too large, aborting." << endl; + throw std::bad_alloc(); + } + + int ret = posix_memalign((void**)&_local_buf, 16, sizeof(LV2_Event_Buffer) + capacity); + if (ret) { + cerr << "Failed to allocate event buffer. Aborting." << endl; + exit(EXIT_FAILURE); + } + + _local_buf->event_count = 0; + _local_buf->capacity = (uint32_t)capacity; + _local_buf->size = 0; + _buf = _local_buf; + + reset(0); + + //cerr << "Creating MIDI Buffer " << _buf << ", capacity = " << _buf->capacity << endl; +} + +EventBuffer::~EventBuffer() +{ + free(_local_buf); +} + + +/** Use another buffer's data instead of the local one. + * + * This buffer will essentially be identical to @a buf after this call. + */ +bool +EventBuffer::join(Buffer* buf) +{ + EventBuffer* mbuf = dynamic_cast(buf); + if (mbuf) { + _position = mbuf->_position; + _buf = mbuf->local_data(); + _joined_buf = mbuf; + return false; + } else { + return false; + } + + //assert(mbuf->size() == _size); + + _joined_buf = mbuf; + + return true; +} + + +void +EventBuffer::unjoin() +{ + _joined_buf = NULL; + _buf = _local_buf; + reset(_this_nframes); +} + + +void +EventBuffer::prepare_read(SampleCount nframes) +{ + //cerr << "\t" << this << " prepare_read: " << event_count() << endl; + + rewind(); + _this_nframes = nframes; +} + + +void +EventBuffer::prepare_write(SampleCount nframes) +{ + //cerr << "\t" << this << " prepare_write: " << event_count() << endl; + reset(nframes); +} + +/** FIXME: parameters ignored */ +void +EventBuffer::copy(const Buffer* src_buf, size_t start_sample, size_t end_sample) +{ + const EventBuffer* src = dynamic_cast(src_buf); + assert(src); + assert(_buf->capacity >= src->_buf->capacity); + + clear(); + src->rewind(); + + memcpy(_buf, src->_buf, src->_buf->size); +} + + +/** Increment the read position by one event. + * + * \return true if increment was successful, or false if end of buffer reached. + */ +bool +EventBuffer::increment() const +{ + if (_position + sizeof(LV2_Event) >= _buf->size) { + _position = _buf->size; + return false; + } + + const LV2_Event* ev = (const LV2_Event*)(_buf + sizeof(LV2_Event_Buffer) + _position); + + _position += sizeof(LV2_Event) + ev->size; + + if (_position >= _buf->size) { + _position = _buf->size; + return false; + } else { + ev = (const LV2_Event*)(_buf + sizeof(LV2_Event_Buffer) + _position); + return true; + } +} + + +/** Append an event to the buffer. + * + * \a timestamp must be >= the latest event in the buffer, + * and < this_nframes() + * + * \return true on success + */ +bool +EventBuffer::append(uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size, + const uint8_t* data) +{ + /*cerr << "Append event " << size << " bytes @ " << timestamp << ":" << endl; + for (uint32_t i=0; i < size; ++i) { + fprintf(stderr, "( %X )", *((uint8_t*)data + i)); + }*/ + + if (_buf->capacity - _buf->size < sizeof(LV2_Event) + size) + return false; + + assert(size > 0); + assert(frames > _latest_frames + || (frames == _latest_frames && subframes >= _latest_subframes)); + + LV2_Event* ev = (LV2_Event*)(_buf + sizeof(LV2_Event_Buffer) + _position); + _position += sizeof(LV2_Event) + ev->size; + + ev = (LV2_Event*)(_buf + sizeof(LV2_Event_Buffer) + _position); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size); + + _buf->size += sizeof(LV2_Event) + size; + ++_buf->event_count; + + _latest_frames = frames; + _latest_subframes = subframes; + + return true; +} + + +/** Read an event from the current position in the buffer + * + * \return true if read was successful, or false if end of buffer reached + */ +bool +EventBuffer::get_event(uint32_t* frames, + uint32_t* subframes, + uint16_t* type, + uint16_t* size, + uint8_t** data) const +{ + const LV2_Event_Buffer* const buf = this->data(); + + if (_position >= buf->size) { + _position = buf->size; + *size = 0; + *data = NULL; + return false; + } + + const LV2_Event* const ev = (const LV2_Event*) + (_buf + sizeof(LV2_Event_Buffer) + _position); + + *frames = ev->frames; + *subframes = ev->subframes; + *type = ev->type; + *size = ev->size; + *data = (uint8_t*)ev + sizeof(LV2_Event); + + return true; +} + + +/** Clear, and merge \a a and \a b into this buffer. + * + * FIXME: This is slow. + * + * \return true if complete merge was successful + */ +bool +EventBuffer::merge(const EventBuffer& a, const EventBuffer& b) +{ + // Die if a merge isn't necessary as it's expensive + assert(a.size() > 0 && b.size() > 0); + + reset(_this_nframes); + + a.rewind(); + b.rewind(); + + uint32_t a_frames; + uint32_t a_subframes; + uint16_t a_type; + uint16_t a_size; + uint8_t* a_data; + + uint32_t b_frames; + uint32_t b_subframes; + uint16_t b_type; + uint16_t b_size; + uint8_t* b_data; + + cout << "FIXME: merge" << endl; +#if 0 + a.get_event(&a_frames, &a_subframes, &a_type, &a_size, &a_data); + b.get_event(&b_frames, &b_subframes, &b_type, &b_size, &b_data); + + while (true) { + if (a_data && (!b_data || (a_time < b_time))) { + append(a_time, a_size, a_data); + if (a.increment()) + a.get_event(&a_time, &a_size, &a_data); + else + a_data = NULL; + } else if (b_data) { + append(b_time, b_size, b_data); + if (b.increment()) + b.get_event(&b_time, &b_size, &b_data); + else + b_data = NULL; + } else { + break; + } + } + + _latest_stamp = max(a_time, b_time); +#endif + + return true; +} + + +} // namespace Ingen + diff --git a/src/libs/engine/EventBuffer.hpp b/src/libs/engine/EventBuffer.hpp new file mode 100644 index 00000000..0f8ce485 --- /dev/null +++ b/src/libs/engine/EventBuffer.hpp @@ -0,0 +1,97 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard + * + * Ingen 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. + * + * 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 General Public License for 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 EVENTBUFFER_H +#define EVENTBUFFER_H + +#include +#include +#include "Buffer.hpp" +#include "interface/DataType.hpp" + +namespace Ingen { + + +class EventBuffer : public Buffer { +public: + EventBuffer(size_t capacity); + + ~EventBuffer(); + + void prepare_read(SampleCount nframes); + void prepare_write(SampleCount nframes); + + bool join(Buffer* buf); + void unjoin(); + + inline uint32_t this_nframes() const { return _this_nframes; } + inline uint32_t event_count() const { return _buf->event_count; } + + inline void* raw_data() { return _buf; } + inline const void* raw_data() const { return _buf; } + + inline LV2_Event_Buffer* local_data() { return _local_buf; } + inline const LV2_Event_Buffer* local_data() const { return _local_buf; } + + inline LV2_Event_Buffer* data() { return _buf; } + inline const LV2_Event_Buffer* data() const { return _buf; } + + void copy(const Buffer* src, size_t start_sample, size_t end_sample); + + inline void rewind() const { _position = 0; } + inline void clear() { reset(_this_nframes); } + inline void reset(SampleCount nframes) { + //std::cerr << this << " reset" << std::endl; + _latest_frames = 0; + _latest_subframes = 0; + _position = sizeof(LV2_Event_Buffer); + _buf->event_count = 0; + _buf->size = 0; + } + + bool increment() const; + + uint32_t latest_frames() const { return _latest_frames; } + uint32_t latest_subframes() const { return _latest_subframes; } + + bool get_event(uint32_t* frames, + uint32_t* subframes, + uint16_t* type, + uint16_t* size, + uint8_t** data) const; + + bool append(uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size, + const uint8_t* data); + + bool merge(const EventBuffer& a, const EventBuffer& b); + +private: + uint32_t _latest_frames; ///< Latest time of all events (frames) + uint32_t _latest_subframes; ///< Latest time of all events (subframes) + uint32_t _this_nframes; ///< Current cycle nframes + mutable uint32_t _position; ///< Offset into _buf + LV2_Event_Buffer* _buf; ///< Contents (maybe belong to _joined_buf) + LV2_Event_Buffer* _local_buf; ///< Local contents +}; + + +} // namespace Ingen + +#endif // EVENTBUFFER_H diff --git a/src/libs/engine/InputPort.hpp b/src/libs/engine/InputPort.hpp index 0b739f4b..cd185ad8 100644 --- a/src/libs/engine/InputPort.hpp +++ b/src/libs/engine/InputPort.hpp @@ -24,7 +24,6 @@ #include #include #include "PortImpl.hpp" -#include "MidiBuffer.hpp" using std::string; namespace Ingen { diff --git a/src/libs/engine/JackMidiDriver.cpp b/src/libs/engine/JackMidiDriver.cpp index ff052256..8d9853f2 100644 --- a/src/libs/engine/JackMidiDriver.cpp +++ b/src/libs/engine/JackMidiDriver.cpp @@ -24,7 +24,7 @@ #include "JackMidiDriver.hpp" #include "ThreadManager.hpp" #include "AudioDriver.hpp" -#include "MidiBuffer.hpp" +#include "EventBuffer.hpp" #include "DuplexPort.hpp" #include "ProcessContext.hpp" #include "jack_compat.h" @@ -73,7 +73,7 @@ JackMidiPort::pre_process(ProcessContext& context) assert(_patch_port->poly() == 1); - MidiBuffer* patch_buf = dynamic_cast(_patch_port->buffer(0)); + EventBuffer* patch_buf = dynamic_cast(_patch_port->buffer(0)); assert(patch_buf); void* jack_buffer = jack_port_get_buffer(_jack_port, context.nframes()); @@ -86,7 +86,8 @@ JackMidiPort::pre_process(ProcessContext& context) jack_midi_event_t ev; jack_midi_event_get(&ev, jack_buffer, i); - bool success = patch_buf->append(ev.time, ev.size, ev.buffer); + // FIXME: type + const bool success = patch_buf->append(ev.time, 0, 0, ev.size, ev.buffer); if (!success) cerr << "WARNING: Failed to write MIDI to port buffer, event(s) lost!" << endl; } @@ -108,7 +109,7 @@ JackMidiPort::post_process(ProcessContext& context) assert(_patch_port->poly() == 1); - MidiBuffer* patch_buf = dynamic_cast(_patch_port->buffer(0)); + EventBuffer* patch_buf = dynamic_cast(_patch_port->buffer(0)); assert(patch_buf); void* jack_buffer = jack_port_get_buffer(_jack_port, context.nframes()); @@ -118,14 +119,17 @@ JackMidiPort::post_process(ProcessContext& context) jack_midi_clear_buffer(jack_buffer); - double time = 0; - uint32_t size = 0; - unsigned char* data = NULL; + uint32_t frames = 0; + uint32_t subframes = 0; + uint16_t type = 0; + uint16_t size = 0; + uint8_t* data = NULL; // Copy events from Jack port buffer into patch port buffer for (jack_nframes_t i=0; i < event_count; ++i) { - patch_buf->get_event(&time, &size, &data); - jack_midi_event_write(jack_buffer, time, data, size); + patch_buf->get_event(&frames, &subframes, &type, &size, &data); + // FIXME: type + jack_midi_event_write(jack_buffer, frames, data, size); } //if (event_count) diff --git a/src/libs/engine/LV2Info.hpp b/src/libs/engine/LV2Info.hpp new file mode 100644 index 00000000..7a9ad1cc --- /dev/null +++ b/src/libs/engine/LV2Info.hpp @@ -0,0 +1,60 @@ +/* This file is part of Ingen. + * Copyright (C) 2008 Dave Robillard + * + * Ingen 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. + * + * 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 General Public License for 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 LV2INFO_H +#define LV2INFO_H + +#include CONFIG_H_PATH +#ifndef HAVE_SLV2 +#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." +#endif + +#include "module/global.hpp" +#include + +namespace Ingen { + + +class LV2Info { +public: + LV2Info(SLV2World world) + : input_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_INPUT)) + , output_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_OUTPUT)) + , control_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_CONTROL)) + , audio_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_AUDIO)) + , event_class(slv2_value_new_uri(world, SLV2_PORT_CLASS_EVENT)) + {} + + ~LV2Info() { + slv2_value_free(input_class); + slv2_value_free(output_class); + slv2_value_free(control_class); + slv2_value_free(audio_class); + slv2_value_free(event_class); + } + + SLV2Value input_class; + SLV2Value output_class; + SLV2Value control_class; + SLV2Value audio_class; + SLV2Value event_class; +}; + + +} // namespace Ingen + +#endif // LV2INFO_H diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp index 13b842de..9b0fabeb 100644 --- a/src/libs/engine/LV2Node.cpp +++ b/src/libs/engine/LV2Node.cpp @@ -25,8 +25,7 @@ #include "InputPort.hpp" #include "LV2Node.hpp" #include "LV2Plugin.hpp" -#include "MidiBuffer.hpp" -#include "OSCBuffer.hpp" +#include "EventBuffer.hpp" #include "OutputPort.hpp" #include "ProcessContext.hpp" @@ -47,7 +46,7 @@ LV2Node::LV2Node(LV2Plugin* plugin, SampleRate srate, size_t buffer_size) : NodeBase(plugin, name, polyphonic, parent, srate, buffer_size) - , _lv2_plugin(plugin->slv2_plugin()) + , _lv2_plugin(plugin) , _instances(NULL) , _prepared_instances(NULL) { @@ -76,7 +75,9 @@ LV2Node::prepare_poly(uint32_t poly) _prepared_instances = new Raul::Array(poly, *_instances); for (uint32_t i = _polyphony; i < _prepared_instances->size(); ++i) { - _prepared_instances->at(i) = slv2_plugin_instantiate(_lv2_plugin, _srate, NULL); + _prepared_instances->at(i) = slv2_plugin_instantiate( + _lv2_plugin->slv2_plugin(), _srate, NULL); + if ((*_prepared_instances)[i] == NULL) { cerr << "Failed to instantiate plugin!" << endl; return false; @@ -123,7 +124,10 @@ LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly) bool LV2Node::instantiate() { - uint32_t num_ports = slv2_plugin_get_num_ports(_lv2_plugin); + SharedPtr info = _lv2_plugin->lv2_info(); + SLV2Plugin plug = _lv2_plugin->slv2_plugin(); + + uint32_t num_ports = slv2_plugin_get_num_ports(plug); assert(num_ports > 0); _ports = new Raul::Array(num_ports, NULL); @@ -133,7 +137,7 @@ LV2Node::instantiate() uint32_t port_buffer_size = 0; for (uint32_t i=0; i < _polyphony; ++i) { - (*_instances)[i] = slv2_plugin_instantiate(_lv2_plugin, _srate, NULL); + (*_instances)[i] = slv2_plugin_instantiate(plug, _srate, NULL); if ((*_instances)[i] == NULL) { cerr << "Failed to instantiate plugin!" << endl; return false; @@ -146,39 +150,35 @@ LV2Node::instantiate() PortImpl* port = NULL; for (uint32_t j=0; j < num_ports; ++j) { - SLV2Port id = slv2_plugin_get_port_by_index(_lv2_plugin, j); + SLV2Port id = slv2_plugin_get_port_by_index(plug, j); // LV2 shortnames are guaranteed to be unique, valid C identifiers - port_name = (char*)slv2_port_get_symbol(_lv2_plugin, id); + port_name = (char*)slv2_port_get_symbol(plug, id); assert(port_name.find("/") == string::npos); port_path = path() + "/" + port_name; - SLV2PortDirection port_direction = slv2_port_get_direction(_lv2_plugin, id); - SLV2PortDataType port_type = slv2_port_get_data_type(_lv2_plugin, id); - - // FIXME: MIDI/OSC buffer size? - if (port_type != SLV2_PORT_DATA_TYPE_CONTROL) - port_buffer_size = _buffer_size; - else - port_buffer_size = 1; - DataType data_type = DataType::UNKNOWN; - switch (port_type) { - case SLV2_PORT_DATA_TYPE_CONTROL: - data_type = DataType::CONTROL; break; - case SLV2_PORT_DATA_TYPE_AUDIO: - data_type = DataType::AUDIO; break; - case SLV2_PORT_DATA_TYPE_MIDI: - data_type = DataType::MIDI; break; - case SLV2_PORT_DATA_TYPE_OSC: - data_type = DataType::OSC; break; - default: - break; + if (slv2_port_is_a(plug, id, info->control_class)) { + data_type = DataType::CONTROL; + port_buffer_size = 1; + } else if (slv2_port_is_a(plug, id, info->audio_class)) { + data_type = DataType::AUDIO; + port_buffer_size = _buffer_size; + } else if (slv2_port_is_a(plug, id, info->event_class)) { + data_type = DataType::EVENT; + port_buffer_size = _buffer_size; } - if (data_type == DataType::UNKNOWN || port_direction == SLV2_PORT_DIRECTION_UNKNOWN) { + enum { UNKNOWN, INPUT, OUTPUT } direction = UNKNOWN; + if (slv2_port_is_a(plug, id, info->input_class)) { + direction = INPUT; + } else if (slv2_port_is_a(plug, id, info->output_class)) { + direction = OUTPUT; + } + + if (data_type == DataType::UNKNOWN || direction == UNKNOWN) { delete _ports; _ports = NULL; delete _instances; @@ -186,15 +186,14 @@ LV2Node::instantiate() return false; } - bool is_input = (port_direction == SLV2_PORT_DIRECTION_INPUT); - - if (is_input) + if (direction == INPUT) port = new InputPort(this, port_name, j, _polyphony, data_type, port_buffer_size); else port = new OutputPort(this, port_name, j, _polyphony, data_type, port_buffer_size); - if (is_input && port_type == SLV2_PORT_DATA_TYPE_CONTROL) - ((AudioBuffer*)port->buffer(0))->set(slv2_port_get_default_value(_lv2_plugin, id), 0); + if (direction == INPUT && data_type == DataType::CONTROL) + ((AudioBuffer*)port->buffer(0))->set( + slv2_port_get_default_value(_lv2_plugin->slv2_plugin(), id), 0); _ports->at(j) = port; } @@ -215,8 +214,8 @@ LV2Node::activate() if (port->type() == DataType::CONTROL) { - const float val = slv2_port_get_default_value(_lv2_plugin, - slv2_plugin_get_port_by_index(_lv2_plugin, j)); + const float val = slv2_port_get_default_value(_lv2_plugin->slv2_plugin(), + slv2_plugin_get_port_by_index(_lv2_plugin->slv2_plugin(), j)); ((AudioBuffer*)port->buffer(i))->set(val, 0); diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp index 4be1571d..47a628b9 100644 --- a/src/libs/engine/LV2Node.hpp +++ b/src/libs/engine/LV2Node.hpp @@ -57,7 +57,7 @@ public: void set_port_buffer(uint32_t voice, uint32_t port_num, Buffer* buf); protected: - SLV2Plugin _lv2_plugin; + LV2Plugin* _lv2_plugin; Raul::Array* _instances; Raul::Array* _prepared_instances; }; diff --git a/src/libs/engine/LV2Plugin.hpp b/src/libs/engine/LV2Plugin.hpp index 19f11732..effdefdc 100644 --- a/src/libs/engine/LV2Plugin.hpp +++ b/src/libs/engine/LV2Plugin.hpp @@ -31,8 +31,10 @@ #include #include #include +#include #include "types.hpp" #include "PluginImpl.hpp" +#include "LV2Info.hpp" using std::string; using Ingen::Shared::Plugin; @@ -49,8 +51,9 @@ class NodeImpl; class LV2Plugin : public PluginImpl { public: - LV2Plugin(const string& uri) + LV2Plugin(SharedPtr lv2_info, const string& uri) : PluginImpl(Plugin::LV2, uri) + , _lv2_info(lv2_info) {} NodeImpl* instantiate(const string& name, @@ -62,11 +65,14 @@ public: const string symbol() const; const string name() const; + SharedPtr lv2_info() const { return _lv2_info; } + SLV2Plugin slv2_plugin() const { return _slv2_plugin; } void slv2_plugin(SLV2Plugin p) { _slv2_plugin = p; } private: - SLV2Plugin _slv2_plugin; + SLV2Plugin _slv2_plugin; + SharedPtr _lv2_info; }; diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index ee515581..9e1d3047 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -50,6 +50,8 @@ libingen_engine_la_SOURCES = \ Engine.hpp \ Event.cpp \ Event.hpp \ + EventBuffer.cpp \ + EventBuffer.hpp \ EventSink.cpp \ EventSink.hpp \ EventSource.hpp \ @@ -65,10 +67,9 @@ libingen_engine_la_SOURCES = \ JackMidiDriver.hpp \ LADSPAPlugin.cpp \ LADSPAPlugin.hpp \ + LV2Info.hpp \ LV2Plugin.cpp \ LV2Plugin.hpp \ - MidiBuffer.cpp \ - MidiBuffer.hpp \ MidiControlNode.cpp \ MidiControlNode.hpp \ MidiDriver.hpp \ @@ -81,8 +82,6 @@ libingen_engine_la_SOURCES = \ NodeFactory.cpp \ NodeFactory.hpp \ NodeImpl.hpp \ - OSCBuffer.cpp \ - OSCBuffer.hpp \ OSCClientSender.cpp \ OSCClientSender.hpp \ OSCDriver.hpp \ diff --git a/src/libs/engine/MidiBuffer.cpp b/src/libs/engine/MidiBuffer.cpp deleted file mode 100644 index 929ac840..00000000 --- a/src/libs/engine/MidiBuffer.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007 Dave Robillard - * - * Ingen 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. - * - * 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 General Public License for 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 - */ - -#define __STDC_LIMIT_MACROS 1 -#include -#include -#include "MidiBuffer.hpp" - -using namespace std; - -namespace Ingen { - - -/** Allocate a new MIDI buffer. - * \a capacity is in bytes (not number of events). - */ -MidiBuffer::MidiBuffer(size_t capacity) - : Buffer(DataType(DataType::MIDI), capacity) - , _latest_stamp(0) -{ - if (capacity > UINT32_MAX) { - cerr << "MIDI buffer size " << capacity << " too large, aborting." << endl; - throw std::bad_alloc(); - } - - int ret = posix_memalign((void**)&_local_buf, 16, sizeof(LV2_MIDI)); - if (ret) { - cerr << "Failed to allocate MIDI buffer. Aborting." << endl; - exit(EXIT_FAILURE); - } - - ret = posix_memalign((void**)&_local_buf->data, 16, capacity); - if (ret) { - cerr << "Failed to allocate MIDI buffer contents. Aborting." << endl; - exit(EXIT_FAILURE); - } - - _local_buf->capacity = (uint32_t)capacity; - _buf = _local_buf; - reset(0); - - //cerr << "Creating MIDI Buffer " << _buf << ", capacity = " << _buf->capacity << endl; -} - -MidiBuffer::~MidiBuffer() -{ - free(_local_buf->data); - free(_local_buf); -} - - -/** Use another buffer's data instead of the local one. - * - * This buffer will essentially be identical to @a buf after this call. - */ -bool -MidiBuffer::join(Buffer* buf) -{ - MidiBuffer* mbuf = dynamic_cast(buf); - if (mbuf) { - _position = mbuf->_position; - _buf = mbuf->local_data(); - _joined_buf = mbuf; - return false; - } else { - return false; - } - - //assert(mbuf->size() == _size); - - _joined_buf = mbuf; - - return true; -} - - -void -MidiBuffer::unjoin() -{ - _joined_buf = NULL; - _buf = _local_buf; - reset(_this_nframes); -} - - -void -MidiBuffer::prepare_read(SampleCount nframes) -{ - //cerr << "\t" << this << " prepare_read: " << event_count() << endl; - - rewind(); - _this_nframes = nframes; -} - - -void -MidiBuffer::prepare_write(SampleCount nframes) -{ - //cerr << "\t" << this << " prepare_write: " << event_count() << endl; - reset(nframes); -} - -/** FIXME: parameters ignored */ -void -MidiBuffer::copy(const Buffer* src_buf, size_t start_sample, size_t end_sample) -{ - MidiBuffer* src = (MidiBuffer*)src_buf; - clear(); - src->rewind(); - const uint32_t frame_count = min(_this_nframes, src->this_nframes()); - double time; - uint32_t size; - unsigned char* data; - while (src->increment() < frame_count) { - src->get_event(&time, &size, &data); - assert(data[0] >= 0x80); - append(time, size, data); - } -} - -/** Increment the read position by one event. - * - * Returns the timestamp of the now current event, or this_nframes if - * there are no events left. - */ -double -MidiBuffer::increment() const -{ - if (_position + sizeof(double) + sizeof(uint32_t) >= _buf->size) { - _position = _buf->size; - return _this_nframes; // hit end - } - - _position += sizeof(double) + sizeof(uint32_t) + - *(uint32_t*)(_buf->data + _position + sizeof(double)); - - if (_position >= _buf->size) { - _position = _buf->size; - return _this_nframes; - } else { - return *(double*)(_buf->data + _position); - } -} - - -/** Append a MIDI event to the buffer. - * - * \a timestamp must be >= the latest event in the buffer, - * and < this_nframes() - * - * \return true on success - */ -bool -MidiBuffer::append(double timestamp, - uint32_t size, - const unsigned char* data) -{ - /*cerr << "Append midi " << size << " bytes @ " << timestamp << ":" << endl; - for (uint32_t i=0; i < size; ++i) { - fprintf(stderr, "( %X )", *((uint8_t*)data + i)); - }*/ - - if (_buf->capacity - _buf->size < sizeof(double) + sizeof(uint32_t) + size) - return false; - - assert(size > 0); - assert(data[0] >= 0x80); - assert(timestamp >= _latest_stamp); - - *(double*)(_buf->data + _buf->size) = timestamp; - _buf->size += sizeof(double); - *(uint32_t*)(_buf->data + _buf->size) = size; - _buf->size += sizeof(uint32_t); - memcpy(_buf->data + _buf->size, data, size); - _buf->size += size; - - ++_buf->event_count; - _latest_stamp = timestamp; - - return true; -} - - -/** Read an event from the current position in the buffer - * - * \return the timestamp for the read event, or this_nframes() - * if there are no more events in the buffer. - */ -double -MidiBuffer::get_event(double* timestamp, - uint32_t* size, - unsigned char** data) const -{ - const LV2_MIDI* buf = this->data(); - - if (_position >= buf->size) { - _position = buf->size; - *timestamp = _this_nframes; - *size = 0; - *data = NULL; - return _this_nframes; - } - - *timestamp = *(double*)(buf->data + _position); - *size = *(uint32_t*)(buf->data + _position + sizeof(double)); - *data = buf->data + _position + sizeof(double) + sizeof(uint32_t); - - return *timestamp; -} - - -/** Clear, and merge \a a and \a b into this buffer. - * - * FIXME: This is slow. - * - * \return true if complete merge was successful - */ -bool -MidiBuffer::merge(const MidiBuffer& a, const MidiBuffer& b) -{ - // Die if a merge isn't necessary as it's expensive - assert(a.size() > 0 && b.size() > 0); - - reset(_this_nframes); - - a.rewind(); - b.rewind(); - - double a_time; - uint32_t a_size; - unsigned char* a_data; - - double b_time; - uint32_t b_size; - unsigned char* b_data; - - a.get_event(&a_time, &a_size, &a_data); - b.get_event(&b_time, &b_size, &b_data); - - while (true) { - if (a_data && (!b_data || (a_time < b_time))) { - append(a_time, a_size, a_data); - if (a.increment()) - a.get_event(&a_time, &a_size, &a_data); - else - a_data = NULL; - } else if (b_data) { - append(b_time, b_size, b_data); - if (b.increment()) - b.get_event(&b_time, &b_size, &b_data); - else - b_data = NULL; - } else { - break; - } - } - - _latest_stamp = max(a_time, b_time); - - return true; -} - - -} // namespace Ingen - diff --git a/src/libs/engine/MidiBuffer.hpp b/src/libs/engine/MidiBuffer.hpp deleted file mode 100644 index e5ebc290..00000000 --- a/src/libs/engine/MidiBuffer.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* This file is part of Ingen. - * Copyright (C) 2007 Dave Robillard - * - * Ingen 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. - * - * 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 General Public License for 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 MIDIBUFFER_H -#define MIDIBUFFER_H - -#include -#include -#include "Buffer.hpp" -#include "interface/DataType.hpp" - -namespace Ingen { - - -class MidiBuffer : public Buffer { -public: - MidiBuffer(size_t capacity); - - ~MidiBuffer(); - - void prepare_read(SampleCount nframes); - void prepare_write(SampleCount nframes); - - bool join(Buffer* buf); - void unjoin(); - - inline uint32_t this_nframes() const { return _this_nframes; } - inline uint32_t event_count() const { return _buf->event_count; } - - inline void* raw_data() { return _buf; } - inline const void* raw_data() const { return _buf; } - - inline LV2_MIDI* local_data() { return _local_buf; } - inline const LV2_MIDI* local_data() const { return _local_buf; } - - inline LV2_MIDI* data() { return _buf; } - inline const LV2_MIDI* data() const { return _buf; } - - void copy(const Buffer* src, size_t start_sample, size_t end_sample); - - inline void rewind() const { _position = 0; } - inline void clear() { reset(_this_nframes); } - inline void reset(SampleCount nframes) { - //std::cerr << this << " reset" << std::endl; - _latest_stamp = 0; - _position = 0; - _buf->event_count = 0; - _buf->size = 0; - } - - double increment() const; - double latest_stamp() const { return _latest_stamp; } - - double get_event(double* timestamp, uint32_t* size, unsigned char** data) const; - - bool append(double timestamp, uint32_t size, const unsigned char* data); - bool merge(const MidiBuffer& a, const MidiBuffer& b); - -private: - double _latest_stamp; ///< Highest timestamp of all events - uint32_t _this_nframes; ///< Current cycle nframes - mutable uint32_t _position; ///< Index into _buf - LV2_MIDI* _buf; ///< Contents (maybe belong to _joined_buf) - LV2_MIDI* _local_buf; ///< Local contents -}; - - -} // namespace Ingen - -#endif // MIDIBUFFER_H diff --git a/src/libs/engine/MidiControlNode.cpp b/src/libs/engine/MidiControlNode.cpp index 2d98b2b0..c48d2e74 100644 --- a/src/libs/engine/MidiControlNode.cpp +++ b/src/libs/engine/MidiControlNode.cpp @@ -25,6 +25,7 @@ #include "InternalPlugin.hpp" #include "AudioBuffer.hpp" #include "ProcessContext.hpp" +#include "EventBuffer.hpp" #include "util.hpp" namespace Ingen { @@ -41,7 +42,7 @@ MidiControlNode::MidiControlNode(const string& path, { _ports = new Raul::Array(7); - _midi_in_port = new InputPort(this, "input", 0, 1, DataType::MIDI, _buffer_size); + _midi_in_port = new InputPort(this, "input", 0, 1, DataType::EVENT, _buffer_size); _ports->at(0) = _midi_in_port; _param_port = new InputPort(this, "controller", 1, 1, DataType::CONTROL, 1); @@ -76,17 +77,20 @@ MidiControlNode::process(ProcessContext& context) { NodeBase::pre_process(context); - double timestamp = 0; - uint32_t size = 0; - unsigned char* buffer = NULL; + uint32_t frames = 0; + uint32_t subframes = 0; + uint16_t type = 0; + uint16_t size = 0; + uint8_t* data = NULL; - MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0); + EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0); assert(midi_in->this_nframes() == context.nframes()); - while (midi_in->get_event(×tamp, &size, &buffer) < context.nframes()) { + while (midi_in->get_event(&frames, &subframes, &type, &size, &data) < context.nframes()) { - if (size >= 3 && (buffer[0] & 0xF0) == MIDI_CMD_CONTROL) - control(buffer[1], buffer[2], (SampleCount)timestamp); + // FIXME: type + if (size >= 3 && (data[0] & 0xF0) == MIDI_CMD_CONTROL) + control(data[1], data[2], (SampleCount)frames); midi_in->increment(); } diff --git a/src/libs/engine/MidiControlNode.hpp b/src/libs/engine/MidiControlNode.hpp index ab377248..c51f36f6 100644 --- a/src/libs/engine/MidiControlNode.hpp +++ b/src/libs/engine/MidiControlNode.hpp @@ -20,7 +20,6 @@ #include #include "NodeBase.hpp" -#include "MidiBuffer.hpp" namespace Ingen { diff --git a/src/libs/engine/MidiDriver.hpp b/src/libs/engine/MidiDriver.hpp index b4d7b1f1..8f603630 100644 --- a/src/libs/engine/MidiDriver.hpp +++ b/src/libs/engine/MidiDriver.hpp @@ -21,7 +21,7 @@ #include #include "types.hpp" #include "Driver.hpp" -#include "MidiBuffer.hpp" +#include "EventBuffer.hpp" #include "ProcessContext.hpp" namespace Ingen { @@ -36,7 +36,7 @@ class ProcessContext; class MidiDriver : public Driver { public: - MidiDriver() : Driver(DataType::MIDI) {} + MidiDriver() : Driver(DataType::EVENT) {} /** Prepare input for the specified (upcoming) cycle. * diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp index 962043b5..0ee5de92 100644 --- a/src/libs/engine/MidiNoteNode.cpp +++ b/src/libs/engine/MidiNoteNode.cpp @@ -24,7 +24,7 @@ #include "AudioDriver.hpp" #include "InputPort.hpp" #include "InternalPlugin.hpp" -#include "MidiBuffer.hpp" +#include "EventBuffer.hpp" #include "MidiNoteNode.hpp" #include "OutputPort.hpp" #include "PatchImpl.hpp" @@ -45,7 +45,7 @@ MidiNoteNode::MidiNoteNode(const string& path, bool polyphonic, PatchImpl* paren { _ports = new Raul::Array(5); - _midi_in_port = new InputPort(this, "input", 0, 1, DataType::MIDI, _buffer_size); + _midi_in_port = new InputPort(this, "input", 0, 1, DataType::EVENT, _buffer_size); _ports->at(0) = _midi_in_port; _freq_port = new OutputPort(this, "frequency", 1, _polyphony, DataType::AUDIO, _buffer_size); @@ -118,19 +118,26 @@ MidiNoteNode::process(ProcessContext& context) { NodeBase::pre_process(context); - double timestamp = 0; - uint32_t size = 0; + uint32_t frames = 0; + uint32_t subframes = 0; + uint16_t type = 0; + uint16_t size = 0; unsigned char* buffer = NULL; - MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0); + EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0); assert(midi_in->this_nframes() == context.nframes()); //cerr << path() << " # input events: " << midi_in->event_count() << endl; if (midi_in->event_count() > 0) - while (midi_in->get_event(×tamp, &size, &buffer) < context.nframes()) { + while (midi_in->get_event(&frames, &subframes, &type, &size, &buffer) < context.nframes()) { + + cout << "EVENT TYPE " << type << " @ " << frames << "." << subframes << ": "; + for (uint16_t i = 0; i < size; ++i) + cout << (int)((char)buffer[i]) << " "; + cout << endl; - const FrameTime time = context.start() + (FrameTime)timestamp; + const FrameTime time = context.start() + (FrameTime)frames; if (size >= 3) { switch (buffer[0] & 0xF0) { diff --git a/src/libs/engine/MidiNoteNode.hpp b/src/libs/engine/MidiNoteNode.hpp index ee708afd..e7e04acd 100644 --- a/src/libs/engine/MidiNoteNode.hpp +++ b/src/libs/engine/MidiNoteNode.hpp @@ -21,8 +21,6 @@ #include #include "types.hpp" #include "NodeBase.hpp" -#include "MidiBuffer.hpp" - namespace Ingen { diff --git a/src/libs/engine/MidiTriggerNode.cpp b/src/libs/engine/MidiTriggerNode.cpp index 4f099a1d..de257b2b 100644 --- a/src/libs/engine/MidiTriggerNode.cpp +++ b/src/libs/engine/MidiTriggerNode.cpp @@ -23,6 +23,7 @@ #include "OutputPort.hpp" #include "InternalPlugin.hpp" #include "ProcessContext.hpp" +#include "EventBuffer.hpp" #include "util.hpp" namespace Ingen { @@ -34,7 +35,7 @@ MidiTriggerNode::MidiTriggerNode(const string& path, bool polyphonic, PatchImpl* { _ports = new Raul::Array(5); - _midi_in_port = new InputPort(this, "input", 0, 1, DataType::MIDI, _buffer_size); + _midi_in_port = new InputPort(this, "input", 0, 1, DataType::EVENT, _buffer_size); _ports->at(0) = _midi_in_port; _note_port = new InputPort(this, "note", 1, 1, DataType::CONTROL, 1); @@ -60,31 +61,33 @@ MidiTriggerNode::process(ProcessContext& context) { NodeBase::pre_process(context); - double timestamp = 0; - uint32_t size = 0; - unsigned char* buffer = NULL; + uint32_t frames = 0; + uint32_t subframes = 0; + uint16_t type = 0; + uint16_t size = 0; + uint8_t* data = NULL; - MidiBuffer* const midi_in = (MidiBuffer*)_midi_in_port->buffer(0); + EventBuffer* const midi_in = (EventBuffer*)_midi_in_port->buffer(0); assert(midi_in->this_nframes() == context.nframes()); - while (midi_in->get_event(×tamp, &size, &buffer) < context.nframes()) { + while (midi_in->get_event(&frames, &subframes, &type, &size, &data) < context.nframes()) { - const FrameTime time = context.start() + (FrameTime)timestamp; + const FrameTime time = context.start() + (FrameTime)frames; if (size >= 3) { - switch (buffer[0] & 0xF0) { + switch (data[0] & 0xF0) { case MIDI_CMD_NOTE_ON: - if (buffer[2] == 0) - note_off(buffer[1], time, context); + if (data[2] == 0) + note_off(data[1], time, context); else - note_on(buffer[1], buffer[2], time, context); + note_on(data[1], data[2], time, context); break; case MIDI_CMD_NOTE_OFF: - note_off(buffer[1], time, context); + note_off(data[1], time, context); break; case MIDI_CMD_CONTROL: - if (buffer[1] == MIDI_CTL_ALL_NOTES_OFF - || buffer[1] == MIDI_CTL_ALL_SOUNDS_OFF) + if (data[1] == MIDI_CTL_ALL_NOTES_OFF + || data[1] == MIDI_CTL_ALL_SOUNDS_OFF) ((AudioBuffer*)_gate_port->buffer(0))->set(0.0f, time); default: break; diff --git a/src/libs/engine/MidiTriggerNode.hpp b/src/libs/engine/MidiTriggerNode.hpp index 308f4a9e..cebb64fe 100644 --- a/src/libs/engine/MidiTriggerNode.hpp +++ b/src/libs/engine/MidiTriggerNode.hpp @@ -20,7 +20,6 @@ #include #include "NodeBase.hpp" -#include "MidiBuffer.hpp" namespace Ingen { diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp index 8312a221..eb414978 100644 --- a/src/libs/engine/NodeFactory.cpp +++ b/src/libs/engine/NodeFactory.cpp @@ -48,6 +48,9 @@ namespace Ingen { NodeFactory::NodeFactory(Ingen::Shared::World* world) : _world(world) , _has_loaded(false) +#ifdef HAVE_SLV2 + , _lv2_info(new LV2Info(world->slv2_world)) +#endif { } @@ -182,7 +185,7 @@ NodeFactory::load_lv2_plugins() assert(_plugins.find(uri) == _plugins.end()); #endif - LV2Plugin* const plugin = new LV2Plugin(uri); + LV2Plugin* const plugin = new LV2Plugin(_lv2_info, uri); plugin->slv2_plugin(lv2_plug); plugin->library_path(slv2_uri_to_path(slv2_plugin_get_library_uri(lv2_plug))); diff --git a/src/libs/engine/NodeFactory.hpp b/src/libs/engine/NodeFactory.hpp index 016839e9..95194350 100644 --- a/src/libs/engine/NodeFactory.hpp +++ b/src/libs/engine/NodeFactory.hpp @@ -28,6 +28,7 @@ #include #ifdef HAVE_SLV2 #include +#include "LV2Info.hpp" #endif #include "types.hpp" @@ -77,10 +78,12 @@ private: void load_internal_plugins(); - Plugins _plugins; - + Plugins _plugins; Ingen::Shared::World* _world; - bool _has_loaded; + bool _has_loaded; +#ifdef HAVE_SLV2 + SharedPtr _lv2_info; +#endif }; diff --git a/src/libs/engine/OSCDriver.hpp b/src/libs/engine/OSCDriver.hpp index a8e5402d..c72952de 100644 --- a/src/libs/engine/OSCDriver.hpp +++ b/src/libs/engine/OSCDriver.hpp @@ -33,7 +33,7 @@ namespace Ingen { class OSCDriver : public Driver { public: - OSCDriver() : Driver(DataType::OSC) {} + OSCDriver() : Driver(DataType::EVENT) {} /** Prepare events (however neccessary) for the specified block (realtime safe) */ virtual void prepare_block(const SampleCount block_start, const SampleCount block_end) = 0; diff --git a/src/libs/engine/PortImpl.cpp b/src/libs/engine/PortImpl.cpp index ec27092a..4fc61c20 100644 --- a/src/libs/engine/PortImpl.cpp +++ b/src/libs/engine/PortImpl.cpp @@ -22,8 +22,7 @@ #include "NodeImpl.hpp" #include "interface/DataType.hpp" #include "AudioBuffer.hpp" -#include "MidiBuffer.hpp" -#include "OSCBuffer.hpp" +#include "EventBuffer.hpp" #include "BufferFactory.hpp" #include "ProcessContext.hpp" #include "SendPortActivityEvent.hpp" @@ -58,7 +57,7 @@ PortImpl::PortImpl(NodeImpl* const node, if (node->parent() == NULL) _polyphonic = false; - if (type == DataType::MIDI || type == DataType::OSC) + if (type == DataType::EVENT) _broadcast = true; // send activity blips assert(_buffers->size() > 0); @@ -180,13 +179,8 @@ PortImpl::broadcast(ProcessContext& context) context.event_sink().write(sizeof(ev), &ev); _last_broadcasted_value = value; } - } else if (_type == DataType::MIDI) { - if (((MidiBuffer*)buffer(0))->event_count() > 0) { - const SendPortActivityEvent ev(context.engine(), context.start(), this); - context.event_sink().write(sizeof(ev), &ev); - } - } else if (_type == DataType::OSC) { - if (((OSCBuffer*)buffer(0))->event_count() > 0) { + } else if (_type == DataType::EVENT) { + if (((EventBuffer*)buffer(0))->event_count() > 0) { const SendPortActivityEvent ev(context.engine(), context.start(), this); context.event_sink().write(sizeof(ev), &ev); } diff --git a/src/libs/engine/events/DestroyEvent.cpp b/src/libs/engine/events/DestroyEvent.cpp index 59e6af5b..d2b2d42b 100644 --- a/src/libs/engine/events/DestroyEvent.cpp +++ b/src/libs/engine/events/DestroyEvent.cpp @@ -154,7 +154,7 @@ DestroyEvent::execute(ProcessContext& context) if ( ! _port->parent_patch()->parent()) { if (_port->type() == DataType::AUDIO) _driver_port = _engine.audio_driver()->remove_port(_port->path()); - else if (_port->type() == DataType::MIDI) + else if (_port->type() == DataType::EVENT) _driver_port = _engine.midi_driver()->remove_port(_port->path()); } } diff --git a/src/libs/engine/events/RenameEvent.cpp b/src/libs/engine/events/RenameEvent.cpp index 1b563d11..7d487cc1 100644 --- a/src/libs/engine/events/RenameEvent.cpp +++ b/src/libs/engine/events/RenameEvent.cpp @@ -113,7 +113,7 @@ RenameEvent::execute(ProcessContext& context) if (port->type() == DataType::AUDIO) driver_port = _engine.audio_driver()->driver_port(_new_path); - else if (port->type() == DataType::MIDI) + else if (port->type() == DataType::EVENT) driver_port = _engine.midi_driver()->driver_port(_new_path); if (driver_port) { diff --git a/src/libs/engine/events/SetPortValueEvent.cpp b/src/libs/engine/events/SetPortValueEvent.cpp index b4d2571c..1abec64b 100644 --- a/src/libs/engine/events/SetPortValueEvent.cpp +++ b/src/libs/engine/events/SetPortValueEvent.cpp @@ -16,7 +16,7 @@ */ #include -#include +#include #include "Responder.hpp" #include "SetPortValueEvent.hpp" #include "Engine.hpp" @@ -25,8 +25,7 @@ #include "NodeImpl.hpp" #include "ObjectStore.hpp" #include "AudioBuffer.hpp" -#include "MidiBuffer.hpp" -#include "OSCBuffer.hpp" +#include "EventBuffer.hpp" #include "ProcessContext.hpp" using namespace std; @@ -109,19 +108,13 @@ SetPortValueEvent::execute(ProcessContext& context) return; } - MidiBuffer* const mbuf = dynamic_cast(buf); - if (mbuf) { - const double stamp = std::max((double)(_time - context.start()), mbuf->latest_stamp()); - mbuf->append(stamp, _data_size, (const unsigned char*)_data); + EventBuffer* const ebuf = dynamic_cast(buf); + if (ebuf) { + const uint32_t frames = std::max((uint32_t)(_time - context.start()), ebuf->latest_frames()); + // FIXME: type + ebuf->append(frames, 0, 0, _data_size, (const unsigned char*)_data); return; } - - OSCBuffer* const obuf = dynamic_cast(buf); - if (obuf) { - //cerr << "Appending OSC message:" << endl; - //lv2_osc_message_print((LV2Message*)_data); - lv2_osc_buffer_append_message(obuf->data(), (LV2Message*)_data); - } } } diff --git a/src/libs/engine/events/SetPortValueQueuedEvent.cpp b/src/libs/engine/events/SetPortValueQueuedEvent.cpp index 7d11b1ae..28bb6df1 100644 --- a/src/libs/engine/events/SetPortValueQueuedEvent.cpp +++ b/src/libs/engine/events/SetPortValueQueuedEvent.cpp @@ -25,7 +25,7 @@ #include "NodeImpl.hpp" #include "ObjectStore.hpp" #include "AudioBuffer.hpp" -#include "MidiBuffer.hpp" +#include "EventBuffer.hpp" #include "ProcessContext.hpp" namespace Ingen { @@ -111,10 +111,11 @@ SetPortValueQueuedEvent::execute(ProcessContext& context) return; } - MidiBuffer* const mbuf = dynamic_cast(buf); - if (mbuf) { - const double stamp = std::max((double)(_time - context.start()), mbuf->latest_stamp()); - mbuf->append(stamp, _data_size, (const unsigned char*)_data); + EventBuffer* const ebuf = dynamic_cast(buf); + if (ebuf) { + const uint32_t frames = std::max((uint32_t)(_time - context.start()), ebuf->latest_frames()); + // FIXME: type + ebuf->append(frames, 0, 0, _data_size, (const unsigned char*)_data); } } } -- cgit v1.2.1