/**************************************************************************** lv2-midifunctions.h - support file for using MIDI in LV2 plugins Copyright (C) 2006 Lars Luthman 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 #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