summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2008-01-21 15:14:53 +0000
committerDavid Robillard <d@drobilla.net>2008-01-21 15:14:53 +0000
commitd6b87aa26ef482a8952437f7472b81a2240f01fd (patch)
tree620d233b902c78413dc17ee5f921633251239695 /src
parent2356f96fbd6c9d70dedcd0d64bf0d72786ea36bb (diff)
downloadingen-d6b87aa26ef482a8952437f7472b81a2240f01fd.tar.gz
ingen-d6b87aa26ef482a8952437f7472b81a2240f01fd.tar.bz2
ingen-d6b87aa26ef482a8952437f7472b81a2240f01fd.zip
Work on generic LV2 events.
git-svn-id: http://svn.drobilla.net/lad/ingen@1090 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r--src/common/interface/DataType.hpp15
-rw-r--r--src/common/interface/EventType.hpp79
-rw-r--r--src/common/interface/Makefile.am1
-rw-r--r--src/common/lv2ext/Makefile.am2
-rw-r--r--src/common/lv2ext/lv2-midiport.h179
-rw-r--r--src/common/lv2ext/lv2_event.h178
l---------src/common/lv2ext/lv2_osc.h1
-rw-r--r--src/libs/engine/BufferFactory.cpp13
-rw-r--r--src/libs/engine/ConnectionImpl.cpp10
-rw-r--r--src/libs/engine/Engine.cpp20
-rw-r--r--src/libs/engine/Engine.hpp3
-rw-r--r--src/libs/engine/EventBuffer.cpp296
-rw-r--r--src/libs/engine/EventBuffer.hpp (renamed from src/libs/engine/MidiBuffer.hpp)59
-rw-r--r--src/libs/engine/InputPort.hpp1
-rw-r--r--src/libs/engine/JackMidiDriver.cpp22
-rw-r--r--src/libs/engine/LV2Info.hpp60
-rw-r--r--src/libs/engine/LV2Node.cpp71
-rw-r--r--src/libs/engine/LV2Node.hpp2
-rw-r--r--src/libs/engine/LV2Plugin.hpp10
-rw-r--r--src/libs/engine/Makefile.am7
-rw-r--r--src/libs/engine/MidiBuffer.cpp279
-rw-r--r--src/libs/engine/MidiControlNode.cpp20
-rw-r--r--src/libs/engine/MidiControlNode.hpp1
-rw-r--r--src/libs/engine/MidiDriver.hpp4
-rw-r--r--src/libs/engine/MidiNoteNode.cpp21
-rw-r--r--src/libs/engine/MidiNoteNode.hpp2
-rw-r--r--src/libs/engine/MidiTriggerNode.cpp31
-rw-r--r--src/libs/engine/MidiTriggerNode.hpp1
-rw-r--r--src/libs/engine/NodeFactory.cpp5
-rw-r--r--src/libs/engine/NodeFactory.hpp9
-rw-r--r--src/libs/engine/OSCDriver.hpp2
-rw-r--r--src/libs/engine/PortImpl.cpp14
-rw-r--r--src/libs/engine/events/DestroyEvent.cpp2
-rw-r--r--src/libs/engine/events/RenameEvent.cpp2
-rw-r--r--src/libs/engine/events/SetPortValueEvent.cpp21
-rw-r--r--src/libs/engine/events/SetPortValueQueuedEvent.cpp11
-rw-r--r--src/libs/gui/Configuration.cpp11
-rw-r--r--src/libs/gui/Configuration.hpp5
-rw-r--r--src/libs/gui/PatchCanvas.cpp2
39 files changed, 825 insertions, 647 deletions
diff --git a/src/common/interface/DataType.hpp b/src/common/interface/DataType.hpp
index 60056d2b..7ce76be1 100644
--- a/src/common/interface/DataType.hpp
+++ b/src/common/interface/DataType.hpp
@@ -35,8 +35,7 @@ public:
UNKNOWN = 0,
AUDIO = 1,
CONTROL = 2,
- MIDI = 3,
- OSC = 4
+ EVENT = 3
};
DataType(const std::string& uri)
@@ -46,10 +45,8 @@ public:
_symbol = AUDIO;
} else if (uri == type_uri(CONTROL)) {
_symbol = CONTROL;
- } else if (uri == type_uri(MIDI)) {
- _symbol = MIDI;
- } else if (uri == type_uri(OSC)) {
- _symbol = OSC;
+ } else if (uri == type_uri(EVENT)) {
+ _symbol = EVENT;
}
}
@@ -66,8 +63,7 @@ public:
inline bool is_audio() { return _symbol == AUDIO; }
inline bool is_control() { return _symbol == CONTROL; }
- inline bool is_midi() { return _symbol == MIDI; }
- inline bool is_osc() { return _symbol == OSC; }
+ inline bool is_event() { return _symbol == EVENT; }
private:
@@ -75,8 +71,7 @@ private:
switch (symbol_num) {
case 1: return "ingen:AudioPort";
case 2: return "ingen:ControlPort";
- case 3: return "ingen:MIDIPort";
- case 4: return "ingen:OSCPort";
+ case 3: return "ingen:EventPort";
default: return "";
}
}
diff --git a/src/common/interface/EventType.hpp b/src/common/interface/EventType.hpp
new file mode 100644
index 00000000..d74835e6
--- /dev/null
+++ b/src/common/interface/EventType.hpp
@@ -0,0 +1,79 @@
+/* This file is part of Ingen.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * 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 EVENTTYPE_H
+#define EVENTTYPE_H
+
+namespace Ingen {
+namespace Shared {
+
+
+/** A type of event (that can live in an EventBuffer).
+ */
+class EventType {
+public:
+
+ enum Symbol {
+ UNKNOWN = 0,
+ MIDI = 1,
+ OSC = 2
+ };
+
+ EventType(const std::string& uri)
+ : _symbol(UNKNOWN)
+ {
+ if (uri == type_uri(MIDI)) {
+ _symbol = MIDI;
+ } else if (uri == type_uri(OSC)) {
+ _symbol = OSC;
+ }
+ }
+
+ EventType(Symbol symbol)
+ : _symbol(symbol)
+ {}
+
+ inline const char* uri() const { return type_uri(_symbol); }
+
+ inline bool operator==(const Symbol& symbol) const { return (_symbol == symbol); }
+ inline bool operator!=(const Symbol& symbol) const { return (_symbol != symbol); }
+ inline bool operator==(const EventType& type) const { return (_symbol == type._symbol); }
+ inline bool operator!=(const EventType& type) const { return (_symbol != type._symbol); }
+
+ inline bool is_midi() { return _symbol == MIDI; }
+ inline bool is_osc() { return _symbol == OSC; }
+
+private:
+
+ static inline const char* type_uri(unsigned symbol_num) {
+ switch (symbol_num) {
+ case 1: return "ingen:MidiEvent";
+ case 2: return "ingen:OSCEvent";
+ default: return "";
+ }
+ }
+
+ Symbol _symbol;
+};
+
+
+} // namespace Shared
+} // namespace Ingen
+
+using Ingen::Shared::EventType;
+
+#endif // EVENTTYPE_H
diff --git a/src/common/interface/Makefile.am b/src/common/interface/Makefile.am
index b23e2583..9f56791d 100644
--- a/src/common/interface/Makefile.am
+++ b/src/common/interface/Makefile.am
@@ -3,6 +3,7 @@ EXTRA_DIST = \
Connection.hpp \
DataType.hpp \
EngineInterface.hpp \
+ EventType.hpp \
GraphObject.hpp \
Node.hpp \
Patch.hpp \
diff --git a/src/common/lv2ext/Makefile.am b/src/common/lv2ext/Makefile.am
index a4dceb45..ecbde5dd 100644
--- a/src/common/lv2ext/Makefile.am
+++ b/src/common/lv2ext/Makefile.am
@@ -1 +1 @@
-noinst_HEADERS = lv2-midiport.h
+noinst_HEADERS = lv2_event.h
diff --git a/src/common/lv2ext/lv2-midiport.h b/src/common/lv2ext/lv2-midiport.h
deleted file mode 100644
index 63980f64..00000000
--- a/src/common/lv2ext/lv2-midiport.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/****************************************************************************
-
- lv2-midiport.h - header file for using MIDI in LV2 plugins
-
- Copyright (C) 2006 Lars Luthman <lars.luthman@gmail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
-
-****************************************************************************/
-
-#include <stdint.h>
-
-/** @file
- This file contains the specification for an LV2 MIDI port extension.
-*/
-
-#ifndef LV2_MIDIPORT_H
-#define LV2_MIDIPORT_H
-
-
-/** This data structure is used to contain the MIDI events for one run()
- cycle. The port buffer for an LV2 port of the type
- <http://ll-plugins.nongnu.org/lv2/ext/MidiPort> should be a pointer
- to an instance of this struct.
-
- To store two Note On events on MIDI channel 0 in a buffer, with timestamps
- 12 and 35.5, you could use something like this code (assuming that
- midi_data is a variable of type LV2_MIDI):
- @code
-
- uint32_t buffer_offset = 0;
- *(double*)(midi_data->data + buffer_offset) = 12;
- buffer_offset += sizeof(double);
- *(uint32_t*)(midi_data->data + buffer_offset) = 3;
- buffer_offset += sizeof(uint32_t);
- midi_data->data[buffer_offset++] = 0x90;
- midi_data->data[buffer_offset++] = 0x48;
- midi_data->data[buffer_offset++] = 0x64;
- ++midi_data->event_count;
-
- *(double*)(midi_data->data + buffer_offset) = 35.5;
- buffer_offset += sizeof(double);
- *(uint32_t*)(midi_data->data + buffer_offset) = 3;
- buffer_offset += sizeof(uint32_t);
- midi_data->data[buffer_offset++] = 0x90;
- midi_data->data[buffer_offset++] = 0x55;
- midi_data->data[buffer_offset++] = 0x64;
- ++midi_data->event_count;
-
- midi_data->size = buffer_offset;
-
- @endcode
-
- This would be done by the host in the case of an input port, and by the
- plugin in the case of an output port. Whoever is writing events to the
- buffer must also take care not to exceed the capacity of the data buffer.
-
- To read events from a buffer, you could do something like this:
- @code
-
- uint32_t buffer_offset = 0;
- uint32_t i;
- for (i = 0; i < midi_data->event_count; ++i) {
- double timestamp = *(double*)(midi_data->data + buffer_offset);
- buffer_offset += sizeof(double);
- uint32_t size = *(uint32_t*)(midi_data->data + buffer_offset);
- buffer_offset += sizeof(uint32_t);
- do_something_with_event(timestamp, size,
- midi_data->data + buffer_offset);
- buffer_offset += size;
- }
-
- @endcode
-
- If you think this looks like too much code to simply read and write MIDI
- events, take a look at the helper functions in lv2-midifunctions.h. They
- are not an official part of this extension, but they can be convenient.
-*/
-typedef struct {
-
- /** The number of MIDI events in the data buffer.
- INPUT PORTS: It's the host's responsibility to set this field to the
- number of MIDI events contained in the data buffer before calling the
- plugin's run() function. The plugin may not change this field.
- OUTPUT PORTS: It's the plugin's responsibility to set this field to the
- number of MIDI events it has stored in the data buffer before returning
- from the run() function. Any initial value should be ignored by the
- plugin.
- */
- uint32_t event_count;
-
- /** The size of the data buffer in bytes. It is set by the host and may not
- be changed by the plugin. The host is allowed to change this between
- run() calls.
- */
- uint32_t capacity;
-
- /** The size of the initial part of the data buffer that actually contains
- data.
- INPUT PORTS: It's the host's responsibility to set this field to the
- number of bytes used by all MIDI events it has written to the buffer
- (including timestamps and size fields) before calling the plugin's
- run() function. The plugin may not change this field.
- OUTPUT PORTS: It's the plugin's responsibility to set this field to
- the number of bytes used by all MIDI events it has written to the
- buffer (including timestamps and size fields) before returning from
- the run() function. Any initial value should be ignored by the plugin.
- */
- uint32_t size;
-
- /** The data buffer that is used to store MIDI events. The events are packed
- after each other, and the format of each event is as follows:
-
- First there is a timestamp, which should have the type "double",
- i.e. have the same bit size as a double and the same bit layout as a
- double (whatever that is on the current platform). This timestamp gives
- the offset from the beginning of the current cycle, in frames, that
- the MIDI event occurs on. It must be strictly smaller than the 'nframes'
- parameter to the current run() call. The MIDI events in the buffer must
- be ordered by their timestamp, e.g. an event with a timestamp of 123.23
- must be stored after an event with a timestamp of 65.0.
-
- The second part of the event is a size field, which should have the type
- "uint32_t" (as defined in the standard C header stddef.h). It should
- contain the size of the MIDI data for this event, i.e. the number of
- bytes used to store the actual MIDI event. The bytes used by the
- timestamp and the size field should not be counted.
-
- The third part of the event is the actual MIDI data. There are some
- requirements that must be followed:
-
- * Running status is not allowed. Every event must have its own status
- byte.
- * Note On events with velocity 0 are not allowed. These events are
- equivalent to Note Off in standard MIDI streams, but in order to make
- plugins and hosts easier to write, as well as more efficient, only
- proper Note Off events are allowed as Note Off.
- * "Realtime events" (status bytes 0xF8 to 0xFF) are allowed, but may not
- occur inside other events like they are allowed to in hardware MIDI
- streams.
- * All events must be fully contained in a single data buffer, i.e. events
- may not "wrap around" by storing the first few bytes in one buffer and
- then wait for the next run() call to store the rest of the event. If
- there isn't enough space in the current data buffer to store an event,
- the event will either have to wait until next run() call, be ignored,
- or compensated for in some more clever way.
- * All events must be valid MIDI events. This means for example that
- only the first byte in each event (the status byte) may have the eighth
- bit set, that Note On and Note Off events are always 3 bytes long etc.
- The MIDI writer (host or plugin) is responsible for writing valid MIDI
- events to the buffer, and the MIDI reader (plugin or host) can assume
- that all events are valid.
-
- On a platform where double is 8 bytes the data buffer layout for a
- 3-byte event followed by a 4-byte event may look something like this:
- _______________________________________________________________
- | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ...
- |TIMESTAMP 1 |SIZE 1 |DATA |TIMESTAMP 2 |SIZE 2 |DATA | ...
-
- */
- unsigned char* data;
-
-} LV2_MIDI;
-
-
-
-#endif
diff --git a/src/common/lv2ext/lv2_event.h b/src/common/lv2ext/lv2_event.h
new file mode 100644
index 00000000..266ba180
--- /dev/null
+++ b/src/common/lv2ext/lv2_event.h
@@ -0,0 +1,178 @@
+/* lv2_events.h - C header file for the LV2 events extension.
+ *
+ * Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
+ * Copyright (C) 2008 Dave Robillard <dave@drobilla.net>
+ *
+ * This header is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This header 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
+ */
+
+#ifndef LV2_EVENTS_H
+#define LV2_EVENTS_H
+
+#include <stdint.h>
+
+/** @file
+ * This header defines the code portion of the LV2 events extension with URI
+ * <http://lv2plug.in/ns/ext/events> (preferred prefix 'lv2ev').
+ *
+ * This extension is a generic transport mechanism for time stamped events
+ * of any type (e.g. MIDI, OSC, ramps, etc). Each port can transport mixed
+ * events of any type; the type of events is defined by a URI (in some other
+ * extension) which is mapped to an integer by the host for performance
+ * reasons.
+ */
+
+
+/** The PPQN (pulses per quarter note) of tempo-based LV2 event time stamps.
+ * Equal to (2^5 * 3^4 * 5 * 7 * 11 * 13 * 17 * 19), which is evenly divisuble
+ * by all integers from 1 through 22 inclusive. */
+static const uint32_t LV2_EVENT_PPQN = 4190266080;
+
+
+
+/** Opaque host data passed to LV2_Event_Feature.
+ */
+typedef void* LV2_Event_Callback_Data;
+
+
+
+/** The data part of the LV2_Feature for the LV2 events extension.
+ *
+ * The host MUST pass an LV2_Feature struct to the plugin's instantiate
+ * method with URI set to "http://lv2plug.in/ns/ext/events" and data
+ * set to an instance of this struct.
+ *
+ * The plugin MUST pass callback_data to any invocation of the functions
+ * defined in this struct. Otherwise, callback_data is opaque and the
+ * plugin MUST NOT interpret its value in any way.
+ */
+typedef struct {
+
+ /** Get the numeric version of an event type from the host.
+ *
+ * The returned value is 0 if there is no type by that URI.
+ * The returned value correlates to the type field of LV2_Event, and is
+ * guaranteed never to change over the course of the plugin's
+ * instantiation, unless the returned value is 0 (i.e. new event types
+ * can be added, but existing ones can never be changed/removed).
+ */
+ uint16_t (*uri_to_event_type)(LV2_Event_Callback_Data callback_data,
+ char const* uri);
+
+ LV2_Event_Callback_Data callback_data;
+
+} LV2_Event_Feature;
+
+
+
+/** An LV2 event.
+ *
+ * LV2 events are generic time-stamped containers for any type of event.
+ * The type field defines the format of a given event's contents.
+ *
+ * This struct defined the header of an LV2 event. An LV2 event is a single
+ * chunk of POD (plain old data), usually contained in a flat buffer
+ * (see LV2_EventBuffer below). Unless a required feature says otherwise,
+ * hosts may assume a deep copy of an LV2 event can be created safely
+ * using a simple:
+ *
+ * memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size); (or equivalent)
+ */
+typedef struct {
+
+ /** The frames portion of timestamp. The units used here can optionally be
+ * set for a port (with the lv2ev:timeUnits property), otherwise this
+ * is audio frames, corresponding to the sample_count parameter of the
+ * LV2 run method (e.g. frame 0 is the first frame for that call to run).
+ */
+ uint32_t frames;
+
+ /** The sub-frames portion of timestamp. The units used here can
+ * optionally be set for a port (with the lv2ev:timeUnits property),
+ * otherwise this is 1/(2^32) of an audio frame.
+ */
+ uint32_t subframes;
+
+ /** The type of this event, where this numeric value refers to some URI
+ * defining an event type. The LV2_Event_Feature passed from the host
+ * provides a function to map URIs to event types for this field.
+ * The type 0 is a special nil value, meaning the event has no type and
+ * should be ignored or passed through without interpretation.
+ * Plugins MUST gracefully ignore or pass through any events of a type
+ * which the plugin does not recognize.
+ */
+ uint16_t type;
+
+ /** The size of the data portion of this event in bytes, which immediately
+ * follows. The header size (12 bytes) is not included in this value.
+ */
+ uint16_t size;
+
+ /* size bytes of data follow here */
+
+} LV2_Event;
+
+
+
+/** A buffer of LV2 events.
+ *
+ * Like events (which this contains) an event buffer is a single chunk of POD:
+ * the entire buffer (including contents) can be copied with a single memcpy.
+ * The first contained event begins sizeof(LV2_EventBuffer) bytes after
+ * the start of this struct.
+ *
+ * After this header, the buffer contains an event header (defined by struct
+ * LV2_Event), followed by that event's contents (padded to 64 bits), followed by
+ * another header, etc:
+ *
+ * | | | | | | |
+ * | | | | | | | | | | | | | | | | | | | | | | | | |
+ * |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ...
+ */
+typedef struct {
+
+ /** The number of events in this buffer.
+ * INPUT PORTS: The host must set this field to the number of events
+ * contained in the data buffer before calling run().
+ * The plugin must not change this field.
+ * OUTPUT PORTS: The plugin must set this field to the number of events it
+ * has written to the buffer before returning from run().
+ * Any initial value should be ignored by the plugin.
+ */
+ uint32_t event_count;
+
+ /** The size of the data buffer in bytes.
+ * This is set by the host and must not be changed by the plugin.
+ * The host is allowed to change this between run() calls.
+ */
+ uint32_t capacity;
+
+ /** The size of the initial portion of the data buffer containing data.
+ * INPUT PORTS: The host must set this field to the number of bytes used
+ * by all events it has written to the buffer (including headers)
+ * before calling the plugin's run().
+ * The plugin must not change this field.
+ * OUTPUT PORTS: The plugin must set this field to the number of bytes
+ * used by all events it has written to the buffer (including headers)
+ * before returning from run().
+ * Any initial value should be ignored by the plugin.
+ */
+ uint32_t size;
+
+} LV2_Event_Buffer;
+
+
+#endif // LV2_EVENTS_H
+
diff --git a/src/common/lv2ext/lv2_osc.h b/src/common/lv2ext/lv2_osc.h
deleted file mode 120000
index 8c97f7b8..00000000
--- a/src/common/lv2ext/lv2_osc.h
+++ /dev/null
@@ -1 +0,0 @@
-../../../../lv2/extensions/osc/lv2_osc.h \ No newline at end of file
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 <raul/SharedPtr.hpp>
#include "module/global.hpp"
#include "interface/DataType.hpp"
+#include "interface/EventType.hpp"
template<typename T> 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 <http://drobilla.net>
+ *
+ * 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 <stdint.h>
+#include <iostream>
+#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<EventBuffer*>(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<const EventBuffer*>(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/MidiBuffer.hpp b/src/libs/engine/EventBuffer.hpp
index e5ebc290..0f8ce485 100644
--- a/src/libs/engine/MidiBuffer.hpp
+++ b/src/libs/engine/EventBuffer.hpp
@@ -15,22 +15,22 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef MIDIBUFFER_H
-#define MIDIBUFFER_H
+#ifndef EVENTBUFFER_H
+#define EVENTBUFFER_H
#include <iostream>
-#include <lv2ext/lv2-midiport.h>
+#include <lv2ext/lv2_event.h>
#include "Buffer.hpp"
#include "interface/DataType.hpp"
namespace Ingen {
-class MidiBuffer : public Buffer {
+class EventBuffer : public Buffer {
public:
- MidiBuffer(size_t capacity);
+ EventBuffer(size_t capacity);
- ~MidiBuffer();
+ ~EventBuffer();
void prepare_read(SampleCount nframes);
void prepare_write(SampleCount nframes);
@@ -44,11 +44,11 @@ public:
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_Event_Buffer* local_data() { return _local_buf; }
+ inline const LV2_Event_Buffer* local_data() const { return _local_buf; }
- inline LV2_MIDI* data() { return _buf; }
- inline const LV2_MIDI* data() const { return _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);
@@ -56,29 +56,42 @@ public:
inline void clear() { reset(_this_nframes); }
inline void reset(SampleCount nframes) {
//std::cerr << this << " reset" << std::endl;
- _latest_stamp = 0;
- _position = 0;
+ _latest_frames = 0;
+ _latest_subframes = 0;
+ _position = sizeof(LV2_Event_Buffer);
_buf->event_count = 0;
_buf->size = 0;
}
- double increment() const;
- double latest_stamp() const { return _latest_stamp; }
+ bool increment() const;
+
+ uint32_t latest_frames() const { return _latest_frames; }
+ uint32_t latest_subframes() const { return _latest_subframes; }
- double get_event(double* timestamp, uint32_t* size, unsigned char** data) const;
+ 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 append(double timestamp, uint32_t size, const unsigned char* data);
- bool merge(const MidiBuffer& a, const MidiBuffer& b);
+ bool merge(const EventBuffer& a, const EventBuffer& 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
+ 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 // MIDIBUFFER_H
+#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 <raul/List.hpp>
#include <raul/SharedPtr.hpp>
#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<MidiBuffer*>(_patch_port->buffer(0));
+ EventBuffer* patch_buf = dynamic_cast<EventBuffer*>(_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<MidiBuffer*>(_patch_port->buffer(0));
+ EventBuffer* patch_buf = dynamic_cast<EventBuffer*>(_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 <http://drobilla.net>
+ *
+ * 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 <slv2/slv2.h>
+
+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<SLV2Instance>(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<LV2Info> 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<PortImpl*>(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<SLV2Instance>* _instances;
Raul::Array<SLV2Instance>* _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 <string>
#include <iostream>
#include <slv2/slv2.h>
+#include <raul/SharedPtr.hpp>
#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<LV2Info> 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<LV2Info> 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<LV2Info> _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 <http://drobilla.net>
- *
- * 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 <stdint.h>
-#include <iostream>
-#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<MidiBuffer*>(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/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<PortImpl*>(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(&timestamp, &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 <string>
#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 <iostream>
#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<PortImpl*>(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(&timestamp, &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 <string>
#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<PortImpl*>(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(&timestamp, &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 <string>
#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 <glibmm/module.h>
#ifdef HAVE_SLV2
#include <slv2/slv2.h>
+#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<LV2Info> _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 <sstream>
-#include <lv2ext/lv2-midiport.h>
+#include <lv2ext/lv2_event.h>
#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<MidiBuffer*>(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<EventBuffer*>(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<OSCBuffer*>(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<MidiBuffer*>(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<EventBuffer*>(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);
}
}
}
diff --git a/src/libs/gui/Configuration.cpp b/src/libs/gui/Configuration.cpp
index 2e4fc1c2..36d5ad75 100644
--- a/src/libs/gui/Configuration.cpp
+++ b/src/libs/gui/Configuration.cpp
@@ -41,8 +41,9 @@ Configuration::Configuration()
// Colours from the Tango palette with modified V and alpha
: _audio_port_color( 0x244678C0)
, _control_port_color(0x4A8A0EC0)
- , _midi_port_color( 0x960909C0)
- , _osc_port_color( 0x5C3566C0)
+ , _event_port_color( 0x960909C0)
+// , _midi_port_color( 0x960909C0)
+// , _osc_port_color( 0x5C3566C0)
{
}
@@ -91,11 +92,13 @@ Configuration::get_port_color(const PortModel* p)
return _control_port_color;
} else if (p->type().is_audio()) {
return _audio_port_color;
- } else if (p->type().is_midi()) {
+ } else if (p->type().is_event()) {
+ return _event_port_color;
+ }/* else if (p->type().is_midi()) {
return _midi_port_color;
} else if (p->type().is_osc()) {
return _osc_port_color;
- }
+ }*/
cerr << "[Configuration] Unknown port type " << p->type().uri()
<< ", port will appear black." << endl;
diff --git a/src/libs/gui/Configuration.hpp b/src/libs/gui/Configuration.hpp
index 0a3f94db..5baa7a09 100644
--- a/src/libs/gui/Configuration.hpp
+++ b/src/libs/gui/Configuration.hpp
@@ -59,8 +59,9 @@ private:
uint32_t _audio_port_color;
uint32_t _control_port_color;
- uint32_t _midi_port_color;
- uint32_t _osc_port_color;
+ uint32_t _event_port_color;
+ //uint32_t _midi_port_color;
+ //uint32_t _osc_port_color;
};
diff --git a/src/libs/gui/PatchCanvas.cpp b/src/libs/gui/PatchCanvas.cpp
index 90e873a9..ecd97318 100644
--- a/src/libs/gui/PatchCanvas.cpp
+++ b/src/libs/gui/PatchCanvas.cpp
@@ -363,7 +363,7 @@ PatchCanvas::connect(boost::shared_ptr<FlowCanvas::Connectable> src_port,
return;
// Midi binding/learn shortcut
- if (src->model()->type().is_midi() && dst->model()->type().is_control())
+ if (src->model()->type().is_event() && dst->model()->type().is_control())
{
cerr << "[PatchCanvas] FIXME: MIDI binding shortcut" << endl;
#if 0