| @@ -426,7 +426,7 @@ lv2_atom_forge_literal(LV2_Atom_Forge* forge, | |||||
| uint32_t lang) | uint32_t lang) | ||||
| { | { | ||||
| const LV2_Atom_Literal a = { | const LV2_Atom_Literal a = { | ||||
| { (uint32_t)(sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1), | |||||
| { (uint32_t)(sizeof(LV2_Atom_Literal) - sizeof(LV2_Atom) + len + 1), | |||||
| forge->Literal }, | forge->Literal }, | ||||
| { datatype, | { datatype, | ||||
| lang } | lang } | ||||
| @@ -466,7 +466,8 @@ lv2_atom_forge_vector(LV2_Atom_Forge* forge, | |||||
| const void* elems) | const void* elems) | ||||
| { | { | ||||
| const LV2_Atom_Vector a = { | const LV2_Atom_Vector a = { | ||||
| { (uint32_t)(sizeof(LV2_Atom_Vector_Body) + n_elems * child_size), forge->Vector }, | |||||
| { (uint32_t)(sizeof(LV2_Atom_Vector_Body) + n_elems * child_size), | |||||
| forge->Vector }, | |||||
| { child_size, child_type } | { child_size, child_type } | ||||
| }; | }; | ||||
| LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); | LV2_Atom_Forge_Ref out = lv2_atom_forge_write(forge, &a, sizeof(a)); | ||||
| @@ -558,7 +559,7 @@ lv2_atom_forge_blank(LV2_Atom_Forge* forge, | |||||
| /** | /** | ||||
| Write the header for a property body (likely in an Object). | Write the header for a property body (likely in an Object). | ||||
| See lv2_atom_forge_object() documentation for an example. | |||||
| See lv2_atom_forge_resource() documentation for an example. | |||||
| */ | */ | ||||
| static inline LV2_Atom_Forge_Ref | static inline LV2_Atom_Forge_Ref | ||||
| lv2_atom_forge_property_head(LV2_Atom_Forge* forge, | lv2_atom_forge_property_head(LV2_Atom_Forge* forge, | ||||
| @@ -571,8 +572,6 @@ lv2_atom_forge_property_head(LV2_Atom_Forge* forge, | |||||
| /** | /** | ||||
| Write the header for a Sequence. | Write the header for a Sequence. | ||||
| The size of the returned sequence will be 0, so passing it as the parent | |||||
| parameter to other forge methods will do the right thing. | |||||
| */ | */ | ||||
| static inline LV2_Atom_Forge_Ref | static inline LV2_Atom_Forge_Ref | ||||
| lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, | lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, | ||||
| @@ -589,8 +588,8 @@ lv2_atom_forge_sequence_head(LV2_Atom_Forge* forge, | |||||
| /** | /** | ||||
| Write the time stamp header of an Event (in a Sequence) in audio frames. | Write the time stamp header of an Event (in a Sequence) in audio frames. | ||||
| After this, call the appropriate forge method(s) to write the body, passing | |||||
| the same @p parent parameter. Note the returned LV2_Event is NOT an Atom. | |||||
| After this, call the appropriate forge method(s) to write the body. Note | |||||
| the returned reference is to an LV2_Event which is NOT an Atom. | |||||
| */ | */ | ||||
| static inline LV2_Atom_Forge_Ref | static inline LV2_Atom_Forge_Ref | ||||
| lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames) | lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames) | ||||
| @@ -599,9 +598,9 @@ lv2_atom_forge_frame_time(LV2_Atom_Forge* forge, int64_t frames) | |||||
| } | } | ||||
| /** | /** | ||||
| Write the time stamp header of an Event (in a Sequence) in beats. | |||||
| After this, call the appropriate forge method(s) to write the body, passing | |||||
| the same @p parent parameter. Note the returned LV2_Event is NOT an Atom. | |||||
| Write the time stamp header of an Event (in a Sequence) in beats. After | |||||
| this, call the appropriate forge method(s) to write the body. Note the | |||||
| returned reference is to an LV2_Event which is NOT an Atom. | |||||
| */ | */ | ||||
| static inline LV2_Atom_Forge_Ref | static inline LV2_Atom_Forge_Ref | ||||
| lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats) | lv2_atom_forge_beat_time(LV2_Atom_Forge* forge, double beats) | ||||
| @@ -204,10 +204,11 @@ lv2_atom_object_is_end(const LV2_Atom_Object_Body* body, | |||||
| static inline LV2_Atom_Property_Body* | static inline LV2_Atom_Property_Body* | ||||
| lv2_atom_object_next(const LV2_Atom_Property_Body* i) | lv2_atom_object_next(const LV2_Atom_Property_Body* i) | ||||
| { | { | ||||
| const LV2_Atom* const value = (LV2_Atom*)((uint8_t*)i + sizeof(i)); | |||||
| return (LV2_Atom_Property_Body*)((uint8_t*)i | |||||
| + sizeof(LV2_Atom_Property_Body) | |||||
| + lv2_atom_pad_size(value->size)); | |||||
| const LV2_Atom* const value = (LV2_Atom*)( | |||||
| (uint8_t*)i + 2 * sizeof(uint32_t)); | |||||
| return (LV2_Atom_Property_Body*)( | |||||
| (uint8_t*)i + lv2_atom_pad_size(sizeof(LV2_Atom_Property_Body) | |||||
| + value->size)); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -299,7 +300,44 @@ lv2_atom_object_query(const LV2_Atom_Object* object, | |||||
| } | } | ||||
| /** | /** | ||||
| Variable argument version of lv2_atom_object_get(). | |||||
| Body only version of lv2_atom_object_get(). | |||||
| */ | |||||
| static inline int | |||||
| lv2_atom_object_body_get(uint32_t size, const LV2_Atom_Object_Body* body, ...) | |||||
| { | |||||
| int matches = 0; | |||||
| int n_queries = 0; | |||||
| /* Count number of keys so we can short-circuit when done */ | |||||
| va_list args; | |||||
| va_start(args, body); | |||||
| for (n_queries = 0; va_arg(args, uint32_t); ++n_queries) { | |||||
| if (!va_arg(args, const LV2_Atom**)) { | |||||
| return -1; | |||||
| } | |||||
| } | |||||
| va_end(args); | |||||
| LV2_ATOM_OBJECT_BODY_FOREACH(body, size, prop) { | |||||
| va_start(args, body); | |||||
| for (int i = 0; i < n_queries; ++i) { | |||||
| uint32_t qkey = va_arg(args, uint32_t); | |||||
| const LV2_Atom** qval = va_arg(args, const LV2_Atom**); | |||||
| if (qkey == prop->key && !*qval) { | |||||
| *qval = &prop->value; | |||||
| if (++matches == n_queries) { | |||||
| return matches; | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| va_end(args); | |||||
| } | |||||
| return matches; | |||||
| } | |||||
| /** | |||||
| Variable argument version of lv2_atom_object_query(). | |||||
| This is nicer-looking in code, but a bit more error-prone since it is not | This is nicer-looking in code, but a bit more error-prone since it is not | ||||
| type safe and the argument list must be terminated. | type safe and the argument list must be terminated. | ||||
| @@ -79,12 +79,23 @@ typedef char lv2_atom_assert_double_fits_in_64_bits[ | |||||
| #define LV2_ATOM_CONTENTS(type, atom) \ | #define LV2_ATOM_CONTENTS(type, atom) \ | ||||
| ((void*)((uint8_t*)(atom) + sizeof(type))) | ((void*)((uint8_t*)(atom) + sizeof(type))) | ||||
| /** | |||||
| Const version of LV2_ATOM_CONTENTS. | |||||
| */ | |||||
| #define LV2_ATOM_CONTENTS_CONST(type, atom) \ | |||||
| ((const void*)((const uint8_t*)(atom) + sizeof(type))) | |||||
| /** | /** | ||||
| Return a pointer to the body of an Atom. The "body" of an atom is the | Return a pointer to the body of an Atom. The "body" of an atom is the | ||||
| data just past the LV2_Atom head (i.e. the same offset for all types). | data just past the LV2_Atom head (i.e. the same offset for all types). | ||||
| */ | */ | ||||
| #define LV2_ATOM_BODY(atom) LV2_ATOM_CONTENTS(LV2_Atom, atom) | #define LV2_ATOM_BODY(atom) LV2_ATOM_CONTENTS(LV2_Atom, atom) | ||||
| /** | |||||
| Const version of LV2_ATOM_BODY. | |||||
| */ | |||||
| #define LV2_ATOM_BODY_CONST(atom) LV2_ATOM_CONTENTS_CONST(LV2_Atom, atom) | |||||
| /** The header of an atom:Atom. */ | /** The header of an atom:Atom. */ | ||||
| typedef struct { | typedef struct { | ||||
| uint32_t size; /**< Size in bytes, not including type and size. */ | uint32_t size; /**< Size in bytes, not including type and size. */ | ||||
| @@ -22,13 +22,19 @@ | |||||
| #ifndef LV2_EVENT_HELPERS_H | #ifndef LV2_EVENT_HELPERS_H | ||||
| #define LV2_EVENT_HELPERS_H | #define LV2_EVENT_HELPERS_H | ||||
| #include <assert.h> | |||||
| #include <stdint.h> | #include <stdint.h> | ||||
| #include <stdbool.h> | |||||
| #include <string.h> | |||||
| #include <stdlib.h> | #include <stdlib.h> | ||||
| #include <assert.h> | |||||
| #include <string.h> | |||||
| #include "event.h" | #include "event.h" | ||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #else | |||||
| # include <stdbool.h> | |||||
| #endif | |||||
| /** @file | /** @file | ||||
| * Helper functions for the LV2 Event extension | * Helper functions for the LV2 Event extension | ||||
| * <http://lv2plug.in/ns/ext/event>. | * <http://lv2plug.in/ns/ext/event>. | ||||
| @@ -108,7 +114,7 @@ lv2_event_begin(LV2_Event_Iterator* iter, | |||||
| static inline bool | static inline bool | ||||
| lv2_event_is_valid(LV2_Event_Iterator* iter) | lv2_event_is_valid(LV2_Event_Iterator* iter) | ||||
| { | { | ||||
| return (iter->offset < iter->buf->size); | |||||
| return (iter->buf && (iter->offset < iter->buf->size)); | |||||
| } | } | ||||
| @@ -165,6 +171,9 @@ lv2_event_write(LV2_Event_Iterator* iter, | |||||
| uint16_t size, | uint16_t size, | ||||
| const uint8_t* data) | const uint8_t* data) | ||||
| { | { | ||||
| if (!iter->buf) | |||||
| return false; | |||||
| if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) | if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) | ||||
| return false; | return false; | ||||
| @@ -243,5 +252,9 @@ lv2_event_write_event(LV2_Event_Iterator* iter, | |||||
| return true; | return true; | ||||
| } | } | ||||
| #ifdef __cplusplus | |||||
| } /* extern "C" */ | |||||
| #endif | |||||
| #endif /* LV2_EVENT_HELPERS_H */ | #endif /* LV2_EVENT_HELPERS_H */ | ||||
| @@ -44,7 +44,7 @@ extern "C" { | |||||
| /** Allow type checking of printf-like functions. */ | /** Allow type checking of printf-like functions. */ | ||||
| # define LV2_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) | # define LV2_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) | ||||
| #else | #else | ||||
| # define LV2_LOG_FUNC | |||||
| # define LV2_LOG_FUNC(fmt, arg1) | |||||
| #endif | #endif | ||||
| /** | /** | ||||
| @@ -22,6 +22,14 @@ | |||||
| #ifndef LV2_MIDI_H | #ifndef LV2_MIDI_H | ||||
| #define LV2_MIDI_H | #define LV2_MIDI_H | ||||
| #include <stdint.h> | |||||
| #ifdef __cplusplus | |||||
| extern "C" { | |||||
| #else | |||||
| # include <stdbool.h> | |||||
| #endif | |||||
| #define LV2_MIDI_URI "http://lv2plug.in/ns/ext/midi" | #define LV2_MIDI_URI "http://lv2plug.in/ns/ext/midi" | ||||
| #define LV2_MIDI_PREFIX LV2_MIDI_URI "#" | #define LV2_MIDI_PREFIX LV2_MIDI_URI "#" | ||||
| @@ -51,7 +59,9 @@ | |||||
| #define LV2_MIDI__TuneRequest LV2_MIDI_PREFIX "TuneRequest" | #define LV2_MIDI__TuneRequest LV2_MIDI_PREFIX "TuneRequest" | ||||
| #define LV2_MIDI__VoiceMessage LV2_MIDI_PREFIX "VoiceMessage" | #define LV2_MIDI__VoiceMessage LV2_MIDI_PREFIX "VoiceMessage" | ||||
| #define LV2_MIDI__benderValue LV2_MIDI_PREFIX "benderValue" | #define LV2_MIDI__benderValue LV2_MIDI_PREFIX "benderValue" | ||||
| #define LV2_MIDI__binding LV2_MIDI_PREFIX "binding" | |||||
| #define LV2_MIDI__byteNumber LV2_MIDI_PREFIX "byteNumber" | #define LV2_MIDI__byteNumber LV2_MIDI_PREFIX "byteNumber" | ||||
| #define LV2_MIDI__channel LV2_MIDI_PREFIX "channel" | |||||
| #define LV2_MIDI__chunk LV2_MIDI_PREFIX "chunk" | #define LV2_MIDI__chunk LV2_MIDI_PREFIX "chunk" | ||||
| #define LV2_MIDI__controllerNumber LV2_MIDI_PREFIX "controllerNumber" | #define LV2_MIDI__controllerNumber LV2_MIDI_PREFIX "controllerNumber" | ||||
| #define LV2_MIDI__controllerValue LV2_MIDI_PREFIX "controllerValue" | #define LV2_MIDI__controllerValue LV2_MIDI_PREFIX "controllerValue" | ||||
| @@ -65,4 +75,152 @@ | |||||
| #define LV2_MIDI__statusMask LV2_MIDI_PREFIX "statusMask" | #define LV2_MIDI__statusMask LV2_MIDI_PREFIX "statusMask" | ||||
| #define LV2_MIDI__velocity LV2_MIDI_PREFIX "velocity" | #define LV2_MIDI__velocity LV2_MIDI_PREFIX "velocity" | ||||
| /** | |||||
| MIDI Message Type. | |||||
| This includes both voice messages (which have a channel) and system messages | |||||
| (which do not), as well as a sentinel value for invalid messages. To get | |||||
| the type of a message suitable for use in a switch statement, use | |||||
| lv2_midi_get_type() on the status byte. | |||||
| */ | |||||
| typedef enum { | |||||
| LV2_MIDI_MSG_INVALID = 0, /**< Invalid Message */ | |||||
| LV2_MIDI_MSG_NOTE_OFF = 0x80, /**< Note Off */ | |||||
| LV2_MIDI_MSG_NOTE_ON = 0x90, /**< Note On */ | |||||
| LV2_MIDI_MSG_NOTE_PRESSURE = 0xA0, /**< Note Pressure */ | |||||
| LV2_MIDI_MSG_CONTROLLER = 0xB0, /**< Controller */ | |||||
| LV2_MIDI_MSG_PGM_CHANGE = 0xC0, /**< Program Change */ | |||||
| LV2_MIDI_MSG_CHANNEL_PRESSURE = 0xD0, /**< Channel Pressure */ | |||||
| LV2_MIDI_MSG_BENDER = 0xE0, /**< Pitch Bender */ | |||||
| LV2_MIDI_MSG_SYSTEM_EXCLUSIVE = 0xF0, /**< System Exclusive Begin */ | |||||
| LV2_MIDI_MSG_MTC_QUARTER = 0xF1, /**< MTC Quarter Frame */ | |||||
| LV2_MIDI_MSG_SONG_POS = 0xF2, /**< Song Position */ | |||||
| LV2_MIDI_MSG_SONG_SELECT = 0xF3, /**< Song Select */ | |||||
| LV2_MIDI_MSG_TUNE_REQUEST = 0xF6, /**< Tune Request */ | |||||
| LV2_MIDI_MSG_CLOCK = 0xF8, /**< Clock */ | |||||
| LV2_MIDI_MSG_START = 0xFA, /**< Start */ | |||||
| LV2_MIDI_MSG_CONTINUE = 0xFB, /**< Continue */ | |||||
| LV2_MIDI_MSG_STOP = 0xFC, /**< Stop */ | |||||
| LV2_MIDI_MSG_ACTIVE_SENSE = 0xFE, /**< Active Sensing */ | |||||
| LV2_MIDI_MSG_RESET = 0xFF /**< Reset */ | |||||
| } LV2_Midi_Message_Type; | |||||
| /** | |||||
| Standard MIDI Controller Numbers. | |||||
| */ | |||||
| typedef enum { | |||||
| LV2_MIDI_CTL_MSB_BANK = 0x00, /**< Bank Selection */ | |||||
| LV2_MIDI_CTL_MSB_MODWHEEL = 0x01, /**< Modulation */ | |||||
| LV2_MIDI_CTL_MSB_BREATH = 0x02, /**< Breath */ | |||||
| LV2_MIDI_CTL_MSB_FOOT = 0x04, /**< Foot */ | |||||
| LV2_MIDI_CTL_MSB_PORTAMENTO_TIME = 0x05, /**< Portamento Time */ | |||||
| LV2_MIDI_CTL_MSB_DATA_ENTRY = 0x06, /**< Data Entry */ | |||||
| LV2_MIDI_CTL_MSB_MAIN_VOLUME = 0x07, /**< Main Volume */ | |||||
| LV2_MIDI_CTL_MSB_BALANCE = 0x08, /**< Balance */ | |||||
| LV2_MIDI_CTL_MSB_PAN = 0x0A, /**< Panpot */ | |||||
| LV2_MIDI_CTL_MSB_EXPRESSION = 0x0B, /**< Expression */ | |||||
| LV2_MIDI_CTL_MSB_EFFECT1 = 0x0C, /**< Effect1 */ | |||||
| LV2_MIDI_CTL_MSB_EFFECT2 = 0x0D, /**< Effect2 */ | |||||
| LV2_MIDI_CTL_MSB_GENERAL_PURPOSE1 = 0x10, /**< General Purpose 1 */ | |||||
| LV2_MIDI_CTL_MSB_GENERAL_PURPOSE2 = 0x11, /**< General Purpose 2 */ | |||||
| LV2_MIDI_CTL_MSB_GENERAL_PURPOSE3 = 0x12, /**< General Purpose 3 */ | |||||
| LV2_MIDI_CTL_MSB_GENERAL_PURPOSE4 = 0x13, /**< General Purpose 4 */ | |||||
| LV2_MIDI_CTL_LSB_BANK = 0x20, /**< Bank Selection */ | |||||
| LV2_MIDI_CTL_LSB_MODWHEEL = 0x21, /**< Modulation */ | |||||
| LV2_MIDI_CTL_LSB_BREATH = 0x22, /**< Breath */ | |||||
| LV2_MIDI_CTL_LSB_FOOT = 0x24, /**< Foot */ | |||||
| LV2_MIDI_CTL_LSB_PORTAMENTO_TIME = 0x25, /**< Portamento Time */ | |||||
| LV2_MIDI_CTL_LSB_DATA_ENTRY = 0x26, /**< Data Entry */ | |||||
| LV2_MIDI_CTL_LSB_MAIN_VOLUME = 0x27, /**< Main Volume */ | |||||
| LV2_MIDI_CTL_LSB_BALANCE = 0x28, /**< Balance */ | |||||
| LV2_MIDI_CTL_LSB_PAN = 0x2A, /**< Panpot */ | |||||
| LV2_MIDI_CTL_LSB_EXPRESSION = 0x2B, /**< Expression */ | |||||
| LV2_MIDI_CTL_LSB_EFFECT1 = 0x2C, /**< Effect1 */ | |||||
| LV2_MIDI_CTL_LSB_EFFECT2 = 0x2D, /**< Effect2 */ | |||||
| LV2_MIDI_CTL_LSB_GENERAL_PURPOSE1 = 0x30, /**< General Purpose 1 */ | |||||
| LV2_MIDI_CTL_LSB_GENERAL_PURPOSE2 = 0x31, /**< General Purpose 2 */ | |||||
| LV2_MIDI_CTL_LSB_GENERAL_PURPOSE3 = 0x32, /**< General Purpose 3 */ | |||||
| LV2_MIDI_CTL_LSB_GENERAL_PURPOSE4 = 0x33, /**< General Purpose 4 */ | |||||
| LV2_MIDI_CTL_SUSTAIN = 0x40, /**< Sustain Pedal */ | |||||
| LV2_MIDI_CTL_PORTAMENTO = 0x41, /**< Portamento */ | |||||
| LV2_MIDI_CTL_SOSTENUTO = 0x42, /**< Sostenuto */ | |||||
| LV2_MIDI_CTL_SOFT_PEDAL = 0x43, /**< Soft Pedal */ | |||||
| LV2_MIDI_CTL_LEGATO_FOOTSWITCH = 0x44, /**< Legato Foot Switch */ | |||||
| LV2_MIDI_CTL_HOLD2 = 0x45, /**< Hold2 */ | |||||
| LV2_MIDI_CTL_SC1_SOUND_VARIATION = 0x46, /**< SC1 Sound Variation */ | |||||
| LV2_MIDI_CTL_SC2_TIMBRE = 0x47, /**< SC2 Timbre */ | |||||
| LV2_MIDI_CTL_SC3_RELEASE_TIME = 0x48, /**< SC3 Release Time */ | |||||
| LV2_MIDI_CTL_SC4_ATTACK_TIME = 0x49, /**< SC4 Attack Time */ | |||||
| LV2_MIDI_CTL_SC5_BRIGHTNESS = 0x4A, /**< SC5 Brightness */ | |||||
| LV2_MIDI_CTL_SC6 = 0x4B, /**< SC6 */ | |||||
| LV2_MIDI_CTL_SC7 = 0x4C, /**< SC7 */ | |||||
| LV2_MIDI_CTL_SC8 = 0x4D, /**< SC8 */ | |||||
| LV2_MIDI_CTL_SC9 = 0x4E, /**< SC9 */ | |||||
| LV2_MIDI_CTL_SC10 = 0x4F, /**< SC10 */ | |||||
| LV2_MIDI_CTL_GENERAL_PURPOSE5 = 0x50, /**< General Purpose 5 */ | |||||
| LV2_MIDI_CTL_GENERAL_PURPOSE6 = 0x51, /**< General Purpose 6 */ | |||||
| LV2_MIDI_CTL_GENERAL_PURPOSE7 = 0x52, /**< General Purpose 7 */ | |||||
| LV2_MIDI_CTL_GENERAL_PURPOSE8 = 0x53, /**< General Purpose 8 */ | |||||
| LV2_MIDI_CTL_PORTAMENTO_CONTROL = 0x54, /**< Portamento Control */ | |||||
| LV2_MIDI_CTL_E1_REVERB_DEPTH = 0x5B, /**< E1 Reverb Depth */ | |||||
| LV2_MIDI_CTL_E2_TREMOLO_DEPTH = 0x5C, /**< E2 Tremolo Depth */ | |||||
| LV2_MIDI_CTL_E3_CHORUS_DEPTH = 0x5D, /**< E3 Chorus Depth */ | |||||
| LV2_MIDI_CTL_E4_DETUNE_DEPTH = 0x5E, /**< E4 Detune Depth */ | |||||
| LV2_MIDI_CTL_E5_PHASER_DEPTH = 0x5F, /**< E5 Phaser Depth */ | |||||
| LV2_MIDI_CTL_DATA_INCREMENT = 0x60, /**< Data Increment */ | |||||
| LV2_MIDI_CTL_DATA_DECREMENT = 0x61, /**< Data Decrement */ | |||||
| LV2_MIDI_CTL_NRPN_LSB = 0x62, /**< Non-registered Parameter Number */ | |||||
| LV2_MIDI_CTL_NRPN_MSB = 0x63, /**< Non-registered Parameter Number */ | |||||
| LV2_MIDI_CTL_RPN_LSB = 0x64, /**< Registered Parameter Number */ | |||||
| LV2_MIDI_CTL_RPN_MSB = 0x65, /**< Registered Parameter Number */ | |||||
| LV2_MIDI_CTL_ALL_SOUNDS_OFF = 0x78, /**< All Sounds Off */ | |||||
| LV2_MIDI_CTL_RESET_CONTROLLERS = 0x79, /**< Reset Controllers */ | |||||
| LV2_MIDI_CTL_LOCAL_CONTROL_SWITCH = 0x7A, /**< Local Control Switch */ | |||||
| LV2_MIDI_CTL_ALL_NOTES_OFF = 0x7B, /**< All Notes Off */ | |||||
| LV2_MIDI_CTL_OMNI_OFF = 0x7C, /**< Omni Off */ | |||||
| LV2_MIDI_CTL_OMNI_ON = 0x7D, /**< Omni On */ | |||||
| LV2_MIDI_CTL_MONO1 = 0x7E, /**< Mono1 */ | |||||
| LV2_MIDI_CTL_MONO2 = 0x7F /**< Mono2 */ | |||||
| } LV2_Midi_Controller; | |||||
| /** | |||||
| Return true iff @p msg is a MIDI voice message (which has a channel). | |||||
| */ | |||||
| static inline bool | |||||
| lv2_midi_is_voice_message(const uint8_t* msg) { | |||||
| return msg[0] >= 0x80 && msg[0] < 0xF0; | |||||
| } | |||||
| /** | |||||
| Return true iff @p msg is a MIDI system message (which has no channel). | |||||
| */ | |||||
| static inline bool | |||||
| lv2_midi_is_system_message(const uint8_t* msg) { | |||||
| switch (msg[0]) { | |||||
| case 0xF4: case 0xF5: case 0xF7: case 0xF9: case 0xFD: | |||||
| return false; | |||||
| default: | |||||
| return (msg[0] & 0xF0) == 0xF0; | |||||
| } | |||||
| } | |||||
| /** | |||||
| Return the type of a MIDI message. | |||||
| @param msg Pointer to the start (status byte) of a MIDI message. | |||||
| */ | |||||
| static inline LV2_Midi_Message_Type | |||||
| lv2_midi_message_type(const uint8_t* msg) { | |||||
| if (lv2_midi_is_voice_message(msg)) { | |||||
| return (LV2_Midi_Message_Type)(msg[0] & 0xF0); | |||||
| } else if (lv2_midi_is_system_message(msg)) { | |||||
| return (LV2_Midi_Message_Type)msg[0]; | |||||
| } else { | |||||
| return LV2_MIDI_MSG_INVALID; | |||||
| } | |||||
| } | |||||
| #ifdef __cplusplus | |||||
| } /* extern "C" */ | |||||
| #endif | |||||
| #endif /* LV2_MIDI_H */ | #endif /* LV2_MIDI_H */ | ||||
| @@ -32,6 +32,7 @@ | |||||
| #define LV2_UI_PREFIX LV2_UI_URI "#" | #define LV2_UI_PREFIX LV2_UI_URI "#" | ||||
| #define LV2_UI__CocoaUI LV2_UI_PREFIX "CocoaUI" | #define LV2_UI__CocoaUI LV2_UI_PREFIX "CocoaUI" | ||||
| #define LV2_UI__Gtk3UI LV2_UI_PREFIX "Gtk3UI" | |||||
| #define LV2_UI__GtkUI LV2_UI_PREFIX "GtkUI" | #define LV2_UI__GtkUI LV2_UI_PREFIX "GtkUI" | ||||
| #define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification" | #define LV2_UI__PortNotification LV2_UI_PREFIX "PortNotification" | ||||
| #define LV2_UI__Qt4UI LV2_UI_PREFIX "Qt4UI" | #define LV2_UI__Qt4UI LV2_UI_PREFIX "Qt4UI" | ||||
| @@ -124,94 +125,94 @@ typedef void (*LV2UI_Write_Function)(LV2UI_Controller controller, | |||||
| function. | function. | ||||
| */ | */ | ||||
| typedef struct _LV2UI_Descriptor { | typedef struct _LV2UI_Descriptor { | ||||
| /** | |||||
| The URI for this UI (not for the plugin it controls). | |||||
| */ | |||||
| const char* URI; | |||||
| /** | |||||
| Create a new UI object and return a handle to it. This function works | |||||
| similarly to the instantiate() member in LV2_Descriptor. | |||||
| @param descriptor The descriptor for the UI that you want to instantiate. | |||||
| @param plugin_uri The URI of the plugin that this UI will control. | |||||
| @param bundle_path The path to the bundle containing the RDF data file | |||||
| that references this shared object file, including the trailing '/'. | |||||
| @param write_function A function provided by the host that the UI can use | |||||
| to send data to the plugin's input ports. | |||||
| @param controller A handle for the plugin instance that should be passed | |||||
| as the first parameter of @p write_function. | |||||
| @param widget A pointer to an LV2UI_Widget. The UI will write a widget | |||||
| pointer to this location (what type of widget depends on the RDF class of | |||||
| the UI) that will be the main UI widget. | |||||
| @param features An array of LV2_Feature pointers. The host must pass all | |||||
| feature URIs that it and the UI supports and any additional data, just | |||||
| like in the LV2 plugin instantiate() function. Note that UI features and | |||||
| plugin features are NOT necessarily the same, they just share the same | |||||
| data structure - this will probably not be the same array as the one the | |||||
| plugin host passes to a plugin. | |||||
| */ | |||||
| LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor, | |||||
| const char* plugin_uri, | |||||
| const char* bundle_path, | |||||
| LV2UI_Write_Function write_function, | |||||
| LV2UI_Controller controller, | |||||
| LV2UI_Widget* widget, | |||||
| const LV2_Feature* const* features); | |||||
| /** | |||||
| Destroy the UI object and the associated widget. The host must not try | |||||
| to access the widget after calling this function. | |||||
| */ | |||||
| void (*cleanup)(LV2UI_Handle ui); | |||||
| /** | |||||
| Tell the UI that something interesting has happened at a plugin port. | |||||
| What is interesting and how it is written to the buffer passed to this | |||||
| function is defined by the @p format parameter, which has the same | |||||
| meaning as in LV2UI_Write_Function. The only exception is ports of the | |||||
| class lv2:ControlPort, for which this function should be called when the | |||||
| port value changes (it does not have to be called for every single change | |||||
| if the host's UI thread has problems keeping up with the thread the | |||||
| plugin is running in), @p buffer_size should be 4, the buffer should | |||||
| contain a single IEEE-754 float, and @p format should be 0. | |||||
| By default, the host should only call this function for input ports of | |||||
| the lv2:ControlPort class. However, this can be modified by using | |||||
| ui:portNotification in the UI data, or the ui:portSubscribe feature. | |||||
| The @p buffer is only valid during the time of this function call, so if | |||||
| the UI wants to keep it for later use it has to copy the contents to an | |||||
| internal buffer. | |||||
| This member may be set to NULL if the UI is not interested in any | |||||
| port events. | |||||
| */ | |||||
| void (*port_event)(LV2UI_Handle ui, | |||||
| uint32_t port_index, | |||||
| uint32_t buffer_size, | |||||
| uint32_t format, | |||||
| const void* buffer); | |||||
| /** | |||||
| Return a data structure associated with an extension URI, for example | |||||
| a struct containing additional function pointers. | |||||
| Avoid returning function pointers directly since standard C/C++ has no | |||||
| valid way of casting a void* to a function pointer. This member may be set | |||||
| to NULL if the UI is not interested in supporting any extensions. This is | |||||
| similar to the extension_data() member in LV2_Descriptor. | |||||
| */ | |||||
| const void* (*extension_data)(const char* uri); | |||||
| /** | |||||
| The URI for this UI (not for the plugin it controls). | |||||
| */ | |||||
| const char* URI; | |||||
| /** | |||||
| Create a new UI object and return a handle to it. This function works | |||||
| similarly to the instantiate() member in LV2_Descriptor. | |||||
| @param descriptor The descriptor for the UI that you want to instantiate. | |||||
| @param plugin_uri The URI of the plugin that this UI will control. | |||||
| @param bundle_path The path to the bundle containing the RDF data file | |||||
| that references this shared object file, including the trailing '/'. | |||||
| @param write_function A function provided by the host that the UI can use | |||||
| to send data to the plugin's input ports. | |||||
| @param controller A handle for the plugin instance that should be passed | |||||
| as the first parameter of @p write_function. | |||||
| @param widget A pointer to an LV2UI_Widget. The UI will write a widget | |||||
| pointer to this location (what type of widget depends on the RDF class of | |||||
| the UI) that will be the main UI widget. | |||||
| @param features An array of LV2_Feature pointers. The host must pass all | |||||
| feature URIs that it and the UI supports and any additional data, just | |||||
| like in the LV2 plugin instantiate() function. Note that UI features and | |||||
| plugin features are NOT necessarily the same, they just share the same | |||||
| data structure - this will probably not be the same array as the one the | |||||
| plugin host passes to a plugin. | |||||
| */ | |||||
| LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor, | |||||
| const char* plugin_uri, | |||||
| const char* bundle_path, | |||||
| LV2UI_Write_Function write_function, | |||||
| LV2UI_Controller controller, | |||||
| LV2UI_Widget* widget, | |||||
| const LV2_Feature* const* features); | |||||
| /** | |||||
| Destroy the UI object and the associated widget. The host must not try | |||||
| to access the widget after calling this function. | |||||
| */ | |||||
| void (*cleanup)(LV2UI_Handle ui); | |||||
| /** | |||||
| Tell the UI that something interesting has happened at a plugin port. | |||||
| What is interesting and how it is written to the buffer passed to this | |||||
| function is defined by the @p format parameter, which has the same | |||||
| meaning as in LV2UI_Write_Function. The only exception is ports of the | |||||
| class lv2:ControlPort, for which this function should be called when the | |||||
| port value changes (it does not have to be called for every single change | |||||
| if the host's UI thread has problems keeping up with the thread the | |||||
| plugin is running in), @p buffer_size should be 4, the buffer should | |||||
| contain a single IEEE-754 float, and @p format should be 0. | |||||
| By default, the host should only call this function for input ports of | |||||
| the lv2:ControlPort class. However, this can be modified by using | |||||
| ui:portNotification in the UI data, or the ui:portSubscribe feature. | |||||
| The @p buffer is only valid during the time of this function call, so if | |||||
| the UI wants to keep it for later use it has to copy the contents to an | |||||
| internal buffer. | |||||
| This member may be set to NULL if the UI is not interested in any | |||||
| port events. | |||||
| */ | |||||
| void (*port_event)(LV2UI_Handle ui, | |||||
| uint32_t port_index, | |||||
| uint32_t buffer_size, | |||||
| uint32_t format, | |||||
| const void* buffer); | |||||
| /** | |||||
| Return a data structure associated with an extension URI, for example | |||||
| a struct containing additional function pointers. | |||||
| Avoid returning function pointers directly since standard C/C++ has no | |||||
| valid way of casting a void* to a function pointer. This member may be set | |||||
| to NULL if the UI is not interested in supporting any extensions. This is | |||||
| similar to the extension_data() member in LV2_Descriptor. | |||||
| */ | |||||
| const void* (*extension_data)(const char* uri); | |||||
| } LV2UI_Descriptor; | } LV2UI_Descriptor; | ||||
| /** | /** | ||||
| @@ -222,23 +223,23 @@ typedef struct _LV2UI_Descriptor { | |||||
| LV2UI_Descriptor::extension_data()). | LV2UI_Descriptor::extension_data()). | ||||
| */ | */ | ||||
| typedef struct _LV2UI_Resize { | typedef struct _LV2UI_Resize { | ||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Request or advertise a size change. | |||||
| /** | |||||
| Request or advertise a size change. | |||||
| When this struct is provided by the host, the UI may call this | |||||
| function to inform the host about the size of the UI. | |||||
| When this struct is provided by the host, the UI may call this | |||||
| function to inform the host about the size of the UI. | |||||
| When this struct is provided by the UI, the host may call this | |||||
| function to notify the UI that it should change its size accordingly. | |||||
| When this struct is provided by the UI, the host may call this | |||||
| function to notify the UI that it should change its size accordingly. | |||||
| @return 0 on success. | |||||
| */ | |||||
| int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height); | |||||
| @return 0 on success. | |||||
| */ | |||||
| int (*ui_resize)(LV2UI_Feature_Handle handle, int width, int height); | |||||
| } LV2UI_Resize; | } LV2UI_Resize; | ||||
| /** | /** | ||||
| @@ -250,113 +251,113 @@ typedef struct _LV2UI_Resize { | |||||
| identifier while index is not). | identifier while index is not). | ||||
| */ | */ | ||||
| typedef struct _LV2UI_Port_Map { | typedef struct _LV2UI_Port_Map { | ||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Get the index for the port with the given @p symbol. | |||||
| @return The index of the port, or LV2_UI_INVALID_PORT_INDEX if no such | |||||
| port is found. | |||||
| */ | |||||
| uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol); | |||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Get the index for the port with the given @p symbol. | |||||
| @return The index of the port, or LV2_UI_INVALID_PORT_INDEX if no such | |||||
| port is found. | |||||
| */ | |||||
| uint32_t (*port_index)(LV2UI_Feature_Handle handle, const char* symbol); | |||||
| } LV2UI_Port_Map; | } LV2UI_Port_Map; | ||||
| /** | /** | ||||
| Port subscription feature (LV2_UI__portSubscribe); | Port subscription feature (LV2_UI__portSubscribe); | ||||
| */ | */ | ||||
| typedef struct _LV2UI_Port_Subscribe { | typedef struct _LV2UI_Port_Subscribe { | ||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Subscribe to updates for a port. | |||||
| This means that the host will call the UI's port_event() function when | |||||
| the port value changes (as defined by protocol). | |||||
| Calling this function with the same @p port_index and @p port_protocol | |||||
| as an already active subscription has no effect. | |||||
| @param handle The handle field of this struct. | |||||
| @param port_index The index of the port. | |||||
| @param port_protocol The URID of the ui:PortProtocol. | |||||
| @param features Features for this subscription. | |||||
| @return 0 on success. | |||||
| */ | |||||
| uint32_t (*subscribe)(LV2UI_Feature_Handle handle, | |||||
| uint32_t port_index, | |||||
| uint32_t port_protocol, | |||||
| const LV2_Feature* const* features); | |||||
| /** | |||||
| Unsubscribe from updates for a port. | |||||
| This means that the host will cease calling calling port_event() when | |||||
| the port value changes. | |||||
| Calling this function with a @p port_index and @p port_protocol that | |||||
| does not refer to an active port subscription has no effect. | |||||
| @param handle The handle field of this struct. | |||||
| @param port_index The index of the port. | |||||
| @param port_protocol The URID of the ui:PortProtocol. | |||||
| @param features Features for this subscription. | |||||
| @return 0 on success. | |||||
| */ | |||||
| uint32_t (*unsubscribe)(LV2UI_Feature_Handle handle, | |||||
| uint32_t port_index, | |||||
| uint32_t port_protocol, | |||||
| const LV2_Feature* const* features); | |||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Subscribe to updates for a port. | |||||
| This means that the host will call the UI's port_event() function when | |||||
| the port value changes (as defined by protocol). | |||||
| Calling this function with the same @p port_index and @p port_protocol | |||||
| as an already active subscription has no effect. | |||||
| @param handle The handle field of this struct. | |||||
| @param port_index The index of the port. | |||||
| @param port_protocol The URID of the ui:PortProtocol. | |||||
| @param features Features for this subscription. | |||||
| @return 0 on success. | |||||
| */ | |||||
| uint32_t (*subscribe)(LV2UI_Feature_Handle handle, | |||||
| uint32_t port_index, | |||||
| uint32_t port_protocol, | |||||
| const LV2_Feature* const* features); | |||||
| /** | |||||
| Unsubscribe from updates for a port. | |||||
| This means that the host will cease calling calling port_event() when | |||||
| the port value changes. | |||||
| Calling this function with a @p port_index and @p port_protocol that | |||||
| does not refer to an active port subscription has no effect. | |||||
| @param handle The handle field of this struct. | |||||
| @param port_index The index of the port. | |||||
| @param port_protocol The URID of the ui:PortProtocol. | |||||
| @param features Features for this subscription. | |||||
| @return 0 on success. | |||||
| */ | |||||
| uint32_t (*unsubscribe)(LV2UI_Feature_Handle handle, | |||||
| uint32_t port_index, | |||||
| uint32_t port_protocol, | |||||
| const LV2_Feature* const* features); | |||||
| } LV2UI_Port_Subscribe; | } LV2UI_Port_Subscribe; | ||||
| /** | /** | ||||
| A feature to notify the host the user has grabbed a UI control. | A feature to notify the host the user has grabbed a UI control. | ||||
| */ | */ | ||||
| typedef struct _LV2UI_Touch { | typedef struct _LV2UI_Touch { | ||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Notify the host that a control has been grabbed or released. | |||||
| @param handle The handle field of this struct. | |||||
| @param port_index The index of the port associated with the control. | |||||
| @param grabbed If true, the control has been grabbed, otherwise the | |||||
| control has been released. | |||||
| */ | |||||
| void (*touch)(LV2UI_Feature_Handle handle, | |||||
| uint32_t port_index, | |||||
| bool grabbed); | |||||
| /** | |||||
| Pointer to opaque data which must be passed to ui_resize(). | |||||
| */ | |||||
| LV2UI_Feature_Handle handle; | |||||
| /** | |||||
| Notify the host that a control has been grabbed or released. | |||||
| @param handle The handle field of this struct. | |||||
| @param port_index The index of the port associated with the control. | |||||
| @param grabbed If true, the control has been grabbed, otherwise the | |||||
| control has been released. | |||||
| */ | |||||
| void (*touch)(LV2UI_Feature_Handle handle, | |||||
| uint32_t port_index, | |||||
| bool grabbed); | |||||
| } LV2UI_Touch; | } LV2UI_Touch; | ||||
| /** | /** | ||||
| Peak data for a slice of time, the update format for ui:peakProtocol. | Peak data for a slice of time, the update format for ui:peakProtocol. | ||||
| */ | */ | ||||
| typedef struct _LV2UI_Peak_Data { | typedef struct _LV2UI_Peak_Data { | ||||
| /** | |||||
| The start of the measurement period. This is just a running counter | |||||
| that is only meaningful in comparison to previous values and must not be | |||||
| interpreted as an absolute time. | |||||
| */ | |||||
| uint32_t period_start; | |||||
| /** | |||||
| The size of the measurement period, in the same units as period_start. | |||||
| */ | |||||
| uint32_t period_size; | |||||
| /** | |||||
| The peak value for the measurement period. This should be the maximal | |||||
| value for abs(sample) over all the samples in the period. | |||||
| */ | |||||
| float peak; | |||||
| /** | |||||
| The start of the measurement period. This is just a running counter | |||||
| that is only meaningful in comparison to previous values and must not be | |||||
| interpreted as an absolute time. | |||||
| */ | |||||
| uint32_t period_start; | |||||
| /** | |||||
| The size of the measurement period, in the same units as period_start. | |||||
| */ | |||||
| uint32_t period_size; | |||||
| /** | |||||
| The peak value for the measurement period. This should be the maximal | |||||
| value for abs(sample) over all the samples in the period. | |||||
| */ | |||||
| float peak; | |||||
| } LV2UI_Peak_Data; | } LV2UI_Peak_Data; | ||||
| /** | /** | ||||
| @@ -372,6 +373,7 @@ typedef struct _LV2UI_Peak_Data { | |||||
| the host should just iterate from 0 and upwards until the function returns | the host should just iterate from 0 and upwards until the function returns | ||||
| NULL or a descriptor with an URI matching the one the host is looking for. | NULL or a descriptor with an URI matching the one the host is looking for. | ||||
| */ | */ | ||||
| LV2_SYMBOL_EXPORT | |||||
| const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index); | const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index); | ||||
| /** | /** | ||||