summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/lv2ext/Makefile.am1
-rw-r--r--src/common/lv2ext/lv2-miditype.h169
-rw-r--r--src/libs/engine/LV2Node.cpp27
5 files changed, 192 insertions, 9 deletions
diff --git a/configure.ac b/configure.ac
index 03ba3ed3..018d9f3b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,7 @@
AC_PREREQ(2.59)
AC_INIT([ingen],[0.4.0pre],[drobilla@connect.carleton.ca])
AC_CONFIG_SRCDIR([src/common/interface/EngineInterface.h])
+AC_CONFIG_SRCDIR([src/common/lv2ext/lv2-miditype.h])
AC_CONFIG_SRCDIR([src/libs/engine/JackAudioDriver.cpp])
AC_CONFIG_SRCDIR([src/libs/engine/tests/node_tree_test.cpp])
AC_CONFIG_SRCDIR([src/libs/client/OSCController.cpp])
@@ -357,6 +358,7 @@ AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([src/Makefile])
AC_CONFIG_FILES([src/common/Makefile])
AC_CONFIG_FILES([src/common/interface/Makefile])
+AC_CONFIG_FILES([src/common/Makefile])
AC_CONFIG_FILES([src/libs/Makefile])
AC_CONFIG_FILES([src/libs/engine/Makefile])
AC_CONFIG_FILES([src/libs/engine/tests/Makefile])
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index a322ba06..e6c5258e 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -1 +1 @@
-DIST_SUBDIRS = interface
+DIST_SUBDIRS = interface lv2ext
diff --git a/src/common/lv2ext/Makefile.am b/src/common/lv2ext/Makefile.am
new file mode 100644
index 00000000..ba3c134a
--- /dev/null
+++ b/src/common/lv2ext/Makefile.am
@@ -0,0 +1 @@
+DIST_HEADERS = lv2-miditype.h
diff --git a/src/common/lv2ext/lv2-miditype.h b/src/common/lv2ext/lv2-miditype.h
new file mode 100644
index 00000000..332e57f1
--- /dev/null
+++ b/src/common/lv2ext/lv2-miditype.h
@@ -0,0 +1,169 @@
+/************************************************************************
+
+ LV2 MIDI Data Type Extension
+ Copyright 2006 Lars Luthman in 2006
+
+ This library 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.1 of
+ the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+
+*************************************************************************/
+
+#ifndef LV2_MIDITYPE_H
+#define LV2_MIDITYPE_H
+
+
+/** This data structure is used to contain the MIDI events for one run()
+ cycle. The port buffer for a LV2 port that has the datatype
+ <http://ll-plugins.nongnu.org/lv2/namespace#miditype> 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
+
+ size_t buffer_offset = 0;
+ *(double*)(midi_data->data + buffer_offset) = 12;
+ buffer_offset += sizeof(double);
+ *(size_t*)(midi_data->data + buffer_offset) = 3;
+ buffer_offset += sizeof(size_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);
+ *(size_t*)(midi_data->data + buffer_offset) = 3;
+ buffer_offset += sizeof(size_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
+
+ size_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);
+ size_t size = *(size_t*)(midi_data->data + buffer_offset);
+ buffer_offset += sizeof(size_t);
+ do_something_with_event(timestamp, size, midi_data->data + buffer_offset);
+ buffer_offset += size;
+ }
+
+ @endcode
+*/
+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
+ "size_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 and size_t is 4 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/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp
index 40270409..1f195dbe 100644
--- a/src/libs/engine/LV2Node.cpp
+++ b/src/libs/engine/LV2Node.cpp
@@ -87,8 +87,6 @@ LV2Node::instantiate()
port_path = path() + "/" + port_name;
- // Assumes there is only the 4 classes
-
SLV2PortClass port_class = slv2_port_get_class(_lv2_plugin, j);
const bool is_control = (port_class == SLV2_CONTROL_RATE_INPUT
|| port_class == SLV2_CONTROL_RATE_OUTPUT);
@@ -100,12 +98,25 @@ LV2Node::instantiate()
else
port_buffer_size = _buffer_size;
- if (is_input) {
- port = new InputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
- _ports->at(j) = port;
- } else /* output */ {
- port = new OutputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
- _ports->at(j) = port;
+ char* const data_type = slv2_port_get_data_type(_lv2_plugin, j);
+
+ if (!strcmp(data_type, SLV2_DATA_TYPE_FLOAT)) {
+ if (is_input) {
+ port = new InputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
+ _ports->at(j) = port;
+ } else /* output */ {
+ port = new OutputPort<Sample>(this, port_name, j, _poly, DataType::FLOAT, port_buffer_size);
+ _ports->at(j) = port;
+ }
+ } else if (!strcmp(data_type, "http://ll-plugins.nongnu.org/lv2/namespace#miditype")) {
+ cerr << "MIDI PORT!\n";
+ if (is_input) {
+ port = new InputPort<MidiMessage>(this, port_name, j, _poly, DataType::MIDI, port_buffer_size);
+ _ports->at(j) = port;
+ } else /* output */ {
+ port = new OutputPort<MidiMessage>(this, port_name, j, _poly, DataType::MIDI, port_buffer_size);
+ _ports->at(j) = port;
+ }
}
assert(_ports->at(j) != NULL);