diff options
author | cbdev <cb@cbcdn.com> | 2019-12-07 20:22:03 +0100 |
---|---|---|
committer | cbdev <cb@cbcdn.com> | 2019-12-07 20:22:03 +0100 |
commit | f95dae04478b32fccaf7c6ebe1ecfd4e2fef1358 (patch) | |
tree | 6f545dc81166ee1a0f1b21b5245a70bcbf05751d /midimonster.h | |
parent | 534207d16314a4f6a69d36cf2305a3fe435a769b (diff) | |
parent | 1bb3b9a3eaf94af045c39a1ff1ee8bf9b8e5b8ec (diff) | |
download | midimonster-f95dae04478b32fccaf7c6ebe1ecfd4e2fef1358.tar.gz midimonster-f95dae04478b32fccaf7c6ebe1ecfd4e2fef1358.tar.bz2 midimonster-f95dae04478b32fccaf7c6ebe1ecfd4e2fef1358.zip |
Merge current master
Diffstat (limited to 'midimonster.h')
-rw-r--r-- | midimonster.h | 147 |
1 files changed, 125 insertions, 22 deletions
diff --git a/midimonster.h b/midimonster.h index 98d8459..5ce0c73 100644 --- a/midimonster.h +++ b/midimonster.h @@ -3,8 +3,34 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <inttypes.h> + +/* API call attributes and visibilities */ +#ifndef MM_API + #ifdef _WIN32 + #define MM_API __attribute__((dllimport)) + #else + #define MM_API + #endif +#endif + +/* Some build systems may apply the -fvisibility=hidden parameter from the core build to the backends, so mark the init function visible */ +#ifndef MM_PLUGIN_API + #ifdef _WIN32 + #define MM_PLUGIN_API __attribute__((dllexport)) + #else + #define MM_PLUGIN_API __attribute__((visibility ("default"))) + #endif +#endif + +/* Straight-forward min / max macros */ #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) + +/* Clamp a value to a range */ +#define clamp(val,max,min) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val))) + +/* Debug messages only compile in when DEBUG is set */ #ifdef DEBUG #define DBGPF(format, ...) fprintf(stderr, (format), __VA_ARGS__) #define DBG(message) fprintf(stderr, "%s", (message)) @@ -13,10 +39,29 @@ #define DBG(message) #endif +/* Stop compilation if the build system reports an error */ +#ifdef BUILD_ERROR + #error The build system reported an error, compilation stopped. Refer to the invocation for this compilation unit for more information. +#endif + +/* Pull in additional defines for non-linux platforms */ #include "portability.h" -#define DEFAULT_CFG "monster.cfg" +/* Default configuration file name to read when no other is specified */ +#ifndef DEFAULT_CFG + #define DEFAULT_CFG "monster.cfg" +#endif + +/* Default backend plugin location */ +#ifndef PLUGINS + #ifndef _WIN32 + #define PLUGINS "./backends/" + #else + #define PLUGINS "backends\\" + #endif +#endif +/* Forward declare some of the structs so we can use them in each other */ struct _channel_value; struct _backend_channel; struct _backend_instance; @@ -29,7 +74,7 @@ struct _managed_fd; * * int init() * The only function that should be exported by the shared object. * Called when the shared object is attached. Should register - * a backend structure with the core. + * a backend structure containing callable entry points with the core. * Returning anything other than zero causes midimonster to fail the * startup checks. * * mmbackend_configure @@ -42,11 +87,15 @@ struct _managed_fd; * Parse instance configuration from the user-supplied configuration * file. Returning a non-zero value fails config parsing. * * mmbackend_channel - * Parse a channel-spec to be mapped to/from. Returning NULL signals an - * out-of-memory condition and terminates the program. + * Parse a channel-spec to be mapped to/from. The `falgs` parameter supplies + * additional information to the parser, such as whether the channel is being + * queried for use as input (to the MIDIMonster core) and/or output + * (from the MIDIMonster core) channel (on a per-query basis). + * Returning NULL signals an out-of-memory condition and terminates the program. * * mmbackend_start * Called after all instances have been created and all mappings - * have been set up. May be used to connect to backing hardware + * have been set up. Only backends for which instances have been configured + * receive the start call. May be used to connect to backing hardware * or to update runtime-specific data in the various data structures. * Returning a non-zero value signals an error starting the backend * and stops further progress. @@ -68,12 +117,14 @@ struct _managed_fd; * Return the maximum sleep interval for this backend in milliseconds. * If not implemented, a maximum interval of one second is used. * * mmbackend_shutdown - * Clean up all allocations, finalize all hardware connections. + * Clean up all allocations, finalize all hardware connections. All registered + * backends receive the shutdown call, regardless of whether they have been + * started previously. * Return value is currently ignored. */ typedef int (*mmbackend_handle_event)(struct _backend_instance* inst, size_t channels, struct _backend_channel** c, struct _channel_value* v); typedef struct _backend_instance* (*mmbackend_create_instance)(); -typedef struct _backend_channel* (*mmbackend_parse_channel)(struct _backend_instance* instance, char* spec); +typedef struct _backend_channel* (*mmbackend_parse_channel)(struct _backend_instance* instance, char* spec, uint8_t flags); typedef void (*mmbackend_free_channel)(struct _backend_channel* c); typedef int (*mmbackend_configure)(char* option, char* value); typedef int (*mmbackend_configure_instance)(struct _backend_instance* instance, char* option, char* value); @@ -82,6 +133,13 @@ typedef int (*mmbackend_start)(); typedef uint32_t (*mmbackend_interval)(); typedef int (*mmbackend_shutdown)(); +/* Bit masks for the `flags` parameter to mmbackend_parse_channel */ +typedef enum { + mmchannel_input = 0x1, + mmchannel_output = 0x2 +} mmbe_channel_flags; + +/* Channel event value, .normalised is used by backends to determine channel values */ typedef struct _channel_value { union { double dbl; @@ -90,6 +148,10 @@ typedef struct _channel_value { double normalised; } channel_value; +/* + * Backend callback structure + * Used to register a backend with the core using mm_backend_register() + */ typedef struct /*_mm_backend*/ { char* name; mmbackend_configure conf; @@ -104,6 +166,10 @@ typedef struct /*_mm_backend*/ { mmbackend_interval interval; } backend; +/* + * Backend instance structure - do not allocate directly! + * Use the memory returned by mm_instance() + */ typedef struct _backend_instance { backend* backend; uint64_t ident; @@ -111,20 +177,51 @@ typedef struct _backend_instance { char* name; } instance; +/* + * Channel specification glob + */ +typedef struct /*_mm_channel_glob*/ { + size_t offset[2]; + union { + void* impl; + uint64_t u64[2]; + } limits; + uint64_t values; +} channel_glob; + +/* + * (Multi-)Channel specification + */ +typedef struct /*_mm_channel_spec*/ { + char* spec; + uint8_t internal; + size_t channels; + size_t globs; + channel_glob* glob; +} channel_spec; + +/* + * Instance channel structure + * Backends may either manage their own channel registry + * or use the memory returned by mm_channel() + */ typedef struct _backend_channel { instance* instance; uint64_t ident; void* impl; } channel; -//FIXME might be replaced by struct pollfd -//FIXME who frees impl +/* + * File descriptor management structure + * Register for the core event loop using mm_manage_fd() + */ typedef struct _managed_fd { int fd; backend* backend; void* impl; } managed_fd; +/* Internal channel mapping structure - Core use only */ typedef struct /*_mm_channel_mapping*/ { channel* from; size_t destinations; @@ -134,7 +231,7 @@ typedef struct /*_mm_channel_mapping*/ { /* * Register a new backend. */ -int mm_backend_register(backend b); +MM_API int mm_backend_register(backend b); /* * Provides a pointer to a newly (zero-)allocated instance. @@ -148,7 +245,8 @@ int mm_backend_register(backend b); * mmbackend_shutdown procedure of the backend, eg. by querying * all instances for the backend. */ -instance* mm_instance(); +MM_API instance* mm_instance(); + /* * Finds an instance matching the specified backend and identifier. * Since setting an identifier for an instance is optional, @@ -156,7 +254,8 @@ instance* mm_instance(); * Instance identifiers may for example be set in the backends * mmbackend_start call. */ -instance* mm_instance_find(char* backend, uint64_t ident); +MM_API instance* mm_instance_find(char* backend, uint64_t ident); + /* * Provides a pointer to a channel structure, pre-filled with * the provided instance reference and identifier. @@ -171,31 +270,35 @@ instance* mm_instance_find(char* backend, uint64_t ident); * this function, the backend will receive a call to its channel_free * function. */ -channel* mm_channel(instance* i, uint64_t ident, uint8_t create); +MM_API channel* mm_channel(instance* i, uint64_t ident, uint8_t create); //TODO channel* mm_channel_find() + /* - * Register a file descriptor to be selected on. The backend - * will be notified via the mmbackend_process_fd call. - * This function may only be called from within the mmbackend_start - * procedure. + * Register (manage = 1) or unregister (manage = 0) a file descriptor + * to be selected on. The backend will be notified when the descriptor + * becomes ready to read via its registered mmbackend_process_fd call. */ -int mm_manage_fd(int fd, char* backend, int manage, void* impl); +MM_API int mm_manage_fd(int fd, char* backend, int manage, void* impl); + /* - * Notifies the core of a channel event. Used by backends to + * Notifies the core of a channel event. Called by backends to * inject events gathered from their backing implementation. */ -int mm_channel_event(channel* c, channel_value v); +MM_API int mm_channel_event(channel* c, channel_value v); + /* * Query all active instances for a given backend. * *i will need to be freed by the caller. */ -int mm_backend_instances(char* backend, size_t* n, instance*** i); +MM_API int mm_backend_instances(char* backend, size_t* n, instance*** i); + /* * Query an internal timestamp, which is updated every core iteration. * This timestamp should not be used as a performance counter, but can be * used for timeouting. Resolution is milliseconds. */ -uint64_t mm_timestamp(); +MM_API uint64_t mm_timestamp(); + /* * Create a channel-to-channel mapping. This API should not * be used by backends. It is only exported for core modules. |