summaryrefslogtreecommitdiffstats
path: root/hosts/lv2-midifunctions.h
diff options
context:
space:
mode:
Diffstat (limited to 'hosts/lv2-midifunctions.h')
-rw-r--r--hosts/lv2-midifunctions.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/hosts/lv2-midifunctions.h b/hosts/lv2-midifunctions.h
new file mode 100644
index 0000000..3a17395
--- /dev/null
+++ b/hosts/lv2-midifunctions.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+
+ lv2-midifunctions.h - support 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
+
+****************************************************************************/
+
+#ifndef LV2_MIDIFUNCTIONS
+#define LV2_MIDIFUNCTIONS
+
+#include <string.h>
+
+#include "lv2-miditype.h"
+
+
+/** This structure contains information about a MIDI port buffer, the
+ current period size, and the position in the MIDI data buffer that
+ we are currently reading from or writing to. It needs to be recreated
+ or at least reinitialised every process() call. */
+typedef struct {
+
+ /** The MIDI port structure that we want to read or write. */
+ LV2_MIDI* midi;
+
+ /** The number of frames in this process cycle. */
+ uint32_t frame_count;
+
+ /** The current position in the data buffer. Should be initialised to 0. */
+ uint32_t position;
+
+} LV2_MIDIState;
+
+
+static LV2_MIDI* lv2midi_new(uint32_t capacity)
+{
+ LV2_MIDI* midi = malloc(sizeof(LV2_MIDI));
+
+ midi->event_count = 0;
+ midi->capacity = capacity;
+ midi->size = 0;
+ midi->data = malloc(sizeof(char) * capacity);
+
+ return midi;
+}
+
+
+static void lv2midi_free(LV2_MIDI* midi)
+{
+ free(midi->data);
+ free(midi);
+}
+
+
+static void lv2midi_reset_buffer(LV2_MIDI* midi)
+{
+ midi->event_count = 0;
+ midi->size = 0;
+}
+
+static void lv2midi_reset_state(LV2_MIDIState* state, LV2_MIDI* midi, uint32_t frame_count)
+{
+ state->midi = midi;
+ state->frame_count = frame_count;
+ state->position = 0;
+}
+
+
+/** This function advances the read/write position in @c state to the next
+ event and returns its timestamp, or the @c frame_count member of @c state
+ is there are no more events. */
+static double lv2midi_increment(LV2_MIDIState* state) {
+
+ if (state->position + sizeof(double) + sizeof(size_t) >= state->midi->size) {
+ state->position = state->midi->size;
+ return state->frame_count;
+ }
+
+ state->position += sizeof(double);
+ size_t size = *(size_t*)(state->midi->data + state->position);
+ state->position += sizeof(size_t);
+ state->position += size;
+
+ if (state->position >= state->midi->size)
+ return state->frame_count;
+
+ return *(double*)(state->midi->data + state->position);
+}
+
+
+/** This function reads one event from the port associated with the @c state
+ parameter and writes its timestamp, size and a pointer to its data bytes
+ into the parameters @c timestamp, @c size and @c data, respectively.
+ It does not advance the read position in the MIDI data buffer, two
+ subsequent calls to lv2midi_get_event() will read the same event.
+
+ The function returns the timestamp for the read event, or the @c frame_count
+ member of @c state if there are no more events in the buffer. */
+static double lv2midi_get_event(LV2_MIDIState* state,
+ double* timestamp,
+ uint32_t* size,
+ unsigned char** data) {
+
+ if (state->position >= state->midi->size) {
+ state->position = state->midi->size;
+ *timestamp = state->frame_count;
+ *size = 0;
+ *data = NULL;
+ return *timestamp;
+ }
+
+ *timestamp = *(double*)(state->midi->data + state->position);
+ *size = *(size_t*)(state->midi->data + state->position + sizeof(double));
+ *data = state->midi->data + state->position +
+ sizeof(double) + sizeof(size_t);
+ return *timestamp;
+}
+
+
+/** This function writes one MIDI event to the port buffer associated with
+ @c state. It returns 0 when the event was written successfully to the
+ buffer, and -1 when there was not enough room. The read/write position
+ is advanced automatically. */
+static int lv2midi_put_event(LV2_MIDIState* state,
+ double timestamp,
+ uint32_t size,
+ const unsigned char* data) {
+
+ if (state->midi->capacity - state->midi->size <
+ sizeof(double) + sizeof(size_t) + size)
+ return -1;
+
+ *(double*)(state->midi->data + state->midi->size) = timestamp;
+ state->midi->size += sizeof(double);
+ *(size_t*)(state->midi->data + state->midi->size) = size;
+ state->midi->size += sizeof(size_t);
+ memcpy(state->midi->data + state->midi->size, data, (size_t)size);
+ state->midi->size += size;
+
+ ++state->midi->event_count;
+
+ return 0;
+}
+
+
+#endif
+