aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorcbdev <cb@cbcdn.com>2020-01-12 17:34:14 +0100
committercbdev <cb@cbcdn.com>2020-01-12 17:34:14 +0100
commit78b21a9ac3f975f35ec7b61108531e1495eb91c0 (patch)
treef41cfc78f3392d501293c3afdd7b42111c863615
parent0a696be5af7db63c1c7354518c839d8543f1ba25 (diff)
downloadmidimonster-78b21a9ac3f975f35ec7b61108531e1495eb91c0.tar.gz
midimonster-78b21a9ac3f975f35ec7b61108531e1495eb91c0.tar.bz2
midimonster-78b21a9ac3f975f35ec7b61108531e1495eb91c0.zip
Rework instance creation
-rw-r--r--README.md6
-rw-r--r--backend.c6
-rw-r--r--backend.h2
-rw-r--r--backends/artnet.c14
-rw-r--r--backends/artnet.h2
-rw-r--r--backends/evdev.c13
-rw-r--r--backends/evdev.h2
-rw-r--r--backends/jack.c12
-rw-r--r--backends/jack.h2
-rw-r--r--backends/loopback.c15
-rw-r--r--backends/loopback.h2
-rw-r--r--backends/lua.c13
-rw-r--r--backends/lua.h2
-rw-r--r--backends/maweb.c13
-rw-r--r--backends/maweb.h2
-rw-r--r--backends/midi.c11
-rw-r--r--backends/midi.h2
-rw-r--r--backends/ola.cpp16
-rw-r--r--backends/ola.h2
-rw-r--r--backends/osc.c11
-rw-r--r--backends/osc.h2
-rw-r--r--backends/sacn.c11
-rw-r--r--backends/sacn.h2
-rw-r--r--backends/winmidi.c15
-rw-r--r--backends/winmidi.h2
-rw-r--r--config.c14
-rw-r--r--midimonster.c2
-rw-r--r--midimonster.h21
28 files changed, 75 insertions, 142 deletions
diff --git a/README.md b/README.md
index b9be3cf..725390f 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# The MIDIMonster
-Named for its scary math, the MIDIMonster is a universal translation
-tool between multi-channel absolute-value-based control and/or bus protocols.
+Named for its scary math, the MIDIMonster is a universal control and translation
+tool for multi-channel absolute-value-based control and/or bus protocols.
Currently, the MIDIMonster supports the following protocols:
@@ -18,7 +18,7 @@ Currently, the MIDIMonster supports the following protocols:
with additional flexibility provided by a [Lua scripting environment](backends/lua.md).
-The MIDIMonster allows the user to translate any channel on one protocol into channel(s)
+With these features, the MIDIMonster allows the user to translate any channel on one protocol into channel(s)
on any other (or the same) supported protocol, for example to:
* Translate MIDI Control Changes into Notes ([Example configuration](configs/unifest-17.cfg))
diff --git a/backend.c b/backend.c
index a2b120f..e9c3829 100644
--- a/backend.c
+++ b/backend.c
@@ -54,7 +54,7 @@ int backends_notify(size_t nev, channel** c, channel_value* v){
if(c[p]->instance == instances[u]){
xval = v[n];
xchnl = c[n];
-
+
v[n] = v[p];
c[n] = c[p];
@@ -105,7 +105,7 @@ MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create){
return channels[nchannels++];
}
-MM_API instance* mm_instance(){
+instance* mm_instance(){
instance** new_inst = realloc(instances, (ninstances + 1) * sizeof(instance*));
if(!new_inst){
//TODO free
@@ -274,7 +274,7 @@ int backends_start(){
if(p == ninstances){
continue;
}
-
+
//fetch list of instances
if(mm_backend_instances(backends[u].name, &n, &inst)){
fprintf(stderr, "Failed to fetch instance list for initialization of backend %s\n", backends[u].name);
diff --git a/backend.h b/backend.h
index 6573e17..de9b5dc 100644
--- a/backend.h
+++ b/backend.h
@@ -10,10 +10,10 @@ int backends_start();
int backends_stop();
void instances_free();
void channels_free();
+instance* mm_instance();
/* Backend API */
MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create);
-MM_API instance* mm_instance();
MM_API instance* mm_instance_find(char* name, uint64_t ident);
MM_API int mm_backend_instances(char* name, size_t* ninst, instance*** inst);
MM_API int mm_backend_register(backend b);
diff --git a/backends/artnet.c b/backends/artnet.c
index 0bd1a32..ed426b0 100644
--- a/backends/artnet.c
+++ b/backends/artnet.c
@@ -94,23 +94,17 @@ static int artnet_configure(char* option, char* value){
return 1;
}
-static instance* artnet_instance(){
- artnet_instance_data* data = NULL;
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
- data = calloc(1, sizeof(artnet_instance_data));
+static int artnet_instance(instance* inst){
+ artnet_instance_data* data = calloc(1, sizeof(artnet_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
data->net = default_net;
inst->impl = data;
- return inst;
+ return 0;
}
static int artnet_configure_instance(instance* inst, char* option, char* value){
diff --git a/backends/artnet.h b/backends/artnet.h
index 59bd53f..1efdee6 100644
--- a/backends/artnet.h
+++ b/backends/artnet.h
@@ -6,7 +6,7 @@
MM_PLUGIN_API int init();
static int artnet_configure(char* option, char* value);
static int artnet_configure_instance(instance* instance, char* option, char* value);
-static instance* artnet_instance();
+static int artnet_instance(instance* inst);
static channel* artnet_channel(instance* instance, char* spec, uint8_t flags);
static int artnet_set(instance* inst, size_t num, channel** c, channel_value* v);
static int artnet_handle(size_t num, managed_fd* fds);
diff --git a/backends/evdev.c b/backends/evdev.c
index 4725ef7..af5ec74 100644
--- a/backends/evdev.c
+++ b/backends/evdev.c
@@ -63,16 +63,11 @@ static int evdev_configure(char* option, char* value) {
return 1;
}
-static instance* evdev_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int evdev_instance(instance* inst){
evdev_instance_data* data = calloc(1, sizeof(evdev_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
data->input_fd = -1;
@@ -81,12 +76,12 @@ static instance* evdev_instance(){
if(!data->output_proto){
LOG("Failed to initialize libevdev output prototype device");
free(data);
- return NULL;
+ return 1;
}
#endif
inst->impl = data;
- return inst;
+ return 0;
}
static int evdev_attach(instance* inst, evdev_instance_data* data, char* node){
diff --git a/backends/evdev.h b/backends/evdev.h
index 0c877fc..e896d2d 100644
--- a/backends/evdev.h
+++ b/backends/evdev.h
@@ -11,7 +11,7 @@
MM_PLUGIN_API int init();
static int evdev_configure(char* option, char* value);
static int evdev_configure_instance(instance* instance, char* option, char* value);
-static instance* evdev_instance();
+static int evdev_instance(instance* inst);
static channel* evdev_channel(instance* instance, char* spec, uint8_t flags);
static int evdev_set(instance* inst, size_t num, channel** c, channel_value* v);
static int evdev_handle(size_t num, managed_fd* fds);
diff --git a/backends/jack.c b/backends/jack.c
index d7f68c4..c862096 100644
--- a/backends/jack.c
+++ b/backends/jack.c
@@ -334,19 +334,13 @@ static int mmjack_configure_instance(instance* inst, char* option, char* value){
return 0;
}
-static instance* mmjack_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int mmjack_instance(instance* inst){
inst->impl = calloc(1, sizeof(mmjack_instance_data));
if(!inst->impl){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
-
- return inst;
+ return 0;
}
static int mmjack_parse_midispec(mmjack_channel_ident* ident, char* spec){
diff --git a/backends/jack.h b/backends/jack.h
index 66c66db..03ce052 100644
--- a/backends/jack.h
+++ b/backends/jack.h
@@ -5,7 +5,7 @@
MM_PLUGIN_API int init();
static int mmjack_configure(char* option, char* value);
static int mmjack_configure_instance(instance* inst, char* option, char* value);
-static instance* mmjack_instance();
+static int mmjack_instance(instance* inst);
static channel* mmjack_channel(instance* inst, char* spec, uint8_t flags);
static int mmjack_set(instance* inst, size_t num, channel** c, channel_value* v);
static int mmjack_handle(size_t num, managed_fd* fds);
diff --git a/backends/loopback.c b/backends/loopback.c
index 085d1df..eaecdb4 100644
--- a/backends/loopback.c
+++ b/backends/loopback.c
@@ -34,19 +34,14 @@ static int loopback_configure_instance(instance* inst, char* option, char* value
return 0;
}
-static instance* loopback_instance(){
- instance* i = mm_instance();
- if(!i){
- return NULL;
- }
-
- i->impl = calloc(1, sizeof(loopback_instance_data));
- if(!i->impl){
+static int loopback_instance(instance* inst){
+ inst->impl = calloc(1, sizeof(loopback_instance_data));
+ if(!inst->impl){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
- return i;
+ return 0;
}
static channel* loopback_channel(instance* inst, char* spec, uint8_t flags){
diff --git a/backends/loopback.h b/backends/loopback.h
index c508d72..cfb2e19 100644
--- a/backends/loopback.h
+++ b/backends/loopback.h
@@ -3,7 +3,7 @@
MM_PLUGIN_API int init();
static int loopback_configure(char* option, char* value);
static int loopback_configure_instance(instance* inst, char* option, char* value);
-static instance* loopback_instance();
+static int loopback_instance(instance* inst);
static channel* loopback_channel(instance* inst, char* spec, uint8_t flags);
static int loopback_set(instance* inst, size_t num, channel** c, channel_value* v);
static int loopback_handle(size_t num, managed_fd* fds);
diff --git a/backends/lua.c b/backends/lua.c
index 510fc72..7d20fb1 100644
--- a/backends/lua.c
+++ b/backends/lua.c
@@ -304,16 +304,11 @@ static int lua_configure_instance(instance* inst, char* option, char* value){
return 1;
}
-static instance* lua_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int lua_instance(instance* inst){
lua_instance_data* data = calloc(1, sizeof(lua_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
//load the interpreter
@@ -321,7 +316,7 @@ static instance* lua_instance(){
if(!data->interpreter){
LOG("Failed to initialize interpreter");
free(data);
- return NULL;
+ return 1;
}
luaL_openlibs(data->interpreter);
@@ -338,7 +333,7 @@ static instance* lua_instance(){
lua_settable(data->interpreter, LUA_REGISTRYINDEX);
inst->impl = data;
- return inst;
+ return 0;
}
static channel* lua_channel(instance* inst, char* spec, uint8_t flags){
diff --git a/backends/lua.h b/backends/lua.h
index 75f03c4..ebe2046 100644
--- a/backends/lua.h
+++ b/backends/lua.h
@@ -12,7 +12,7 @@
MM_PLUGIN_API int init();
static int lua_configure(char* option, char* value);
static int lua_configure_instance(instance* inst, char* option, char* value);
-static instance* lua_instance();
+static int lua_instance(instance* inst);
static channel* lua_channel(instance* inst, char* spec, uint8_t flags);
static int lua_set(instance* inst, size_t num, channel** c, channel_value* v);
static int lua_handle(size_t num, managed_fd* fds);
diff --git a/backends/maweb.c b/backends/maweb.c
index f81ab46..6a006bd 100644
--- a/backends/maweb.c
+++ b/backends/maweb.c
@@ -205,16 +205,11 @@ static int maweb_configure_instance(instance* inst, char* option, char* value){
return 1;
}
-static instance* maweb_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int maweb_instance(instance* inst){
maweb_instance_data* data = calloc(1, sizeof(maweb_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
data->fd = -1;
@@ -222,12 +217,12 @@ static instance* maweb_instance(){
if(!data->buffer){
LOG("Failed to allocate memory");
free(data);
- return NULL;
+ return 1;
}
data->allocated = MAWEB_RECV_CHUNK;
inst->impl = data;
- return inst;
+ return 0;
}
static channel* maweb_channel(instance* inst, char* spec, uint8_t flags){
diff --git a/backends/maweb.h b/backends/maweb.h
index 50b777a..80835d9 100644
--- a/backends/maweb.h
+++ b/backends/maweb.h
@@ -3,7 +3,7 @@
MM_PLUGIN_API int init();
static int maweb_configure(char* option, char* value);
static int maweb_configure_instance(instance* inst, char* option, char* value);
-static instance* maweb_instance();
+static int maweb_instance(instance* inst);
static channel* maweb_channel(instance* inst, char* spec, uint8_t flags);
static int maweb_set(instance* inst, size_t num, channel** c, channel_value* v);
static int maweb_handle(size_t num, managed_fd* fds);
diff --git a/backends/midi.c b/backends/midi.c
index 11d759d..f73ebb4 100644
--- a/backends/midi.c
+++ b/backends/midi.c
@@ -69,19 +69,14 @@ static int midi_configure(char* option, char* value){
return 1;
}
-static instance* midi_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int midi_instance(instance* inst){
inst->impl = calloc(1, sizeof(midi_instance_data));
if(!inst->impl){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
- return inst;
+ return 0;
}
static int midi_configure_instance(instance* inst, char* option, char* value){
diff --git a/backends/midi.h b/backends/midi.h
index 66a02bc..dcee010 100644
--- a/backends/midi.h
+++ b/backends/midi.h
@@ -3,7 +3,7 @@
MM_PLUGIN_API int init();
static int midi_configure(char* option, char* value);
static int midi_configure_instance(instance* instance, char* option, char* value);
-static instance* midi_instance();
+static int midi_instance(instance* inst);
static channel* midi_channel(instance* instance, char* spec, uint8_t flags);
static int midi_set(instance* inst, size_t num, channel** c, channel_value* v);
static int midi_handle(size_t num, managed_fd* fds);
diff --git a/backends/ola.cpp b/backends/ola.cpp
index 09d68c9..106dbd5 100644
--- a/backends/ola.cpp
+++ b/backends/ola.cpp
@@ -40,21 +40,15 @@ static int ola_configure(char* option, char* value){
return 1;
}
-static instance* ola_instance(){
- ola_instance_data* data = NULL;
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
- data = (ola_instance_data*)calloc(1, sizeof(ola_instance_data));
+static int ola_instance(instance* inst){
+ ola_instance_data* data = (ola_instance_data*) calloc(1, sizeof(ola_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
inst->impl = data;
- return inst;
+ return 0;
}
static int ola_configure_instance(instance* inst, char* option, char* value){
@@ -188,7 +182,7 @@ static void ola_data_receive(unsigned int universe, const ola::DmxBuffer& ola_dm
else{
chan = mm_channel(inst, p, 0);
}
-
+
if(!chan){
LOGPF("Active channel %" PRIsize_t " on %s not known to core", p, inst->name);
return;
diff --git a/backends/ola.h b/backends/ola.h
index 083e971..68244ec 100644
--- a/backends/ola.h
+++ b/backends/ola.h
@@ -7,7 +7,7 @@ extern "C" {
MM_PLUGIN_API int init();
static int ola_configure(char* option, char* value);
static int ola_configure_instance(instance* instance, char* option, char* value);
- static instance* ola_instance();
+ static int ola_instance(instance* inst);
static channel* ola_channel(instance* instance, char* spec, uint8_t flags);
static int ola_set(instance* inst, size_t num, channel** c, channel_value* v);
static int ola_handle(size_t num, managed_fd* fds);
diff --git a/backends/osc.c b/backends/osc.c
index 7b9a5a5..754c290 100644
--- a/backends/osc.c
+++ b/backends/osc.c
@@ -562,21 +562,16 @@ static int osc_configure_instance(instance* inst, char* option, char* value){
return 1;
}
-static instance* osc_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int osc_instance(instance* inst){
osc_instance_data* data = calloc(1, sizeof(osc_instance_data));
if(!data){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
data->fd = -1;
inst->impl = data;
- return inst;
+ return 0;
}
static channel* osc_map_channel(instance* inst, char* spec, uint8_t flags){
diff --git a/backends/osc.h b/backends/osc.h
index f8ff3ff..ec75e3f 100644
--- a/backends/osc.h
+++ b/backends/osc.h
@@ -10,7 +10,7 @@
MM_PLUGIN_API int init();
static int osc_configure(char* option, char* value);
static int osc_configure_instance(instance* inst, char* option, char* value);
-static instance* osc_instance();
+static int osc_instance(instance* inst);
static channel* osc_map_channel(instance* inst, char* spec, uint8_t flags);
static int osc_set(instance* inst, size_t num, channel** c, channel_value* v);
static int osc_handle(size_t num, managed_fd* fds);
diff --git a/backends/sacn.c b/backends/sacn.c
index ff2b61e..5096123 100644
--- a/backends/sacn.c
+++ b/backends/sacn.c
@@ -195,19 +195,14 @@ static int sacn_configure_instance(instance* inst, char* option, char* value){
return 1;
}
-static instance* sacn_instance(){
- instance* inst = mm_instance();
- if(!inst){
- return NULL;
- }
-
+static int sacn_instance(instance* inst){
inst->impl = calloc(1, sizeof(sacn_instance_data));
if(!inst->impl){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
- return inst;
+ return 0;
}
static channel* sacn_channel(instance* inst, char* spec, uint8_t flags){
diff --git a/backends/sacn.h b/backends/sacn.h
index c8d11e9..ac59441 100644
--- a/backends/sacn.h
+++ b/backends/sacn.h
@@ -3,7 +3,7 @@
MM_PLUGIN_API int init();
static int sacn_configure(char* option, char* value);
static int sacn_configure_instance(instance* instance, char* option, char* value);
-static instance* sacn_instance();
+static int sacn_instance(instance* inst);
static channel* sacn_channel(instance* instance, char* spec, uint8_t flags);
static int sacn_set(instance* inst, size_t num, channel** c, channel_value* v);
static int sacn_handle(size_t num, managed_fd* fds);
diff --git a/backends/winmidi.c b/backends/winmidi.c
index c2aee2f..ad9b02d 100644
--- a/backends/winmidi.c
+++ b/backends/winmidi.c
@@ -95,19 +95,14 @@ static int winmidi_configure_instance(instance* inst, char* option, char* value)
return 1;
}
-static instance* winmidi_instance(){
- instance* i = mm_instance();
- if(!i){
- return NULL;
- }
-
- i->impl = calloc(1, sizeof(winmidi_instance_data));
- if(!i->impl){
+static int winmidi_instance(instance* inst){
+ inst->impl = calloc(1, sizeof(winmidi_instance_data));
+ if(!inst->impl){
LOG("Failed to allocate memory");
- return NULL;
+ return 1;
}
- return i;
+ return 0;
}
static channel* winmidi_channel(instance* inst, char* spec, uint8_t flags){
diff --git a/backends/winmidi.h b/backends/winmidi.h
index 81e7439..4c740ea 100644
--- a/backends/winmidi.h
+++ b/backends/winmidi.h
@@ -3,7 +3,7 @@
MM_PLUGIN_API int init();
static int winmidi_configure(char* option, char* value);
static int winmidi_configure_instance(instance* inst, char* option, char* value);
-static instance* winmidi_instance();
+static int winmidi_instance(instance* inst);
static channel* winmidi_channel(instance* inst, char* spec, uint8_t flags);
static int winmidi_set(instance* inst, size_t num, channel** c, channel_value* v);
static int winmidi_handle(size_t num, managed_fd* fds);
diff --git a/config.c b/config.c
index d2b65d4..920e161 100644
--- a/config.c
+++ b/config.c
@@ -279,7 +279,7 @@ static int config_map(char* to_raw, char* from_raw){
|| config_glob_scan(instance_from, &spec_from)){
goto done;
}
-
+
if((spec_to.channels != spec_from.channels && spec_from.channels != 1 && spec_to.channels != 1)
|| spec_to.channels == 0
|| spec_from.channels == 0){
@@ -298,7 +298,7 @@ static int config_map(char* to_raw, char* from_raw){
for(n = 0; !rv && n < max(spec_from.channels, spec_to.channels); n++){
channel_from = config_glob_resolve(instance_from, &spec_from, min(n, spec_from.channels), mmchannel_input);
channel_to = config_glob_resolve(instance_to, &spec_to, min(n, spec_to.channels), mmchannel_output);
-
+
if(!channel_from || !channel_to){
rv = 1;
goto done;
@@ -356,7 +356,7 @@ static int config_line(char* line){
else{
//backend instance configuration
parser_state = instance_cfg;
-
+
//trim braces
line[strlen(line) - 1] = 0;
line++;
@@ -388,9 +388,13 @@ static int config_line(char* line){
return 1;
}
- current_instance = current_backend->create();
+ current_instance = mm_instance();
if(!current_instance){
- fprintf(stderr, "Failed to instantiate backend %s\n", line);
+ return 1;
+ }
+
+ if(current_backend->create(current_instance)){
+ fprintf(stderr, "Failed to create %s instance %s\n", line, separator);
return 1;
}
diff --git a/midimonster.c b/midimonster.c
index 583601e..b6f7758 100644
--- a/midimonster.c
+++ b/midimonster.c
@@ -341,7 +341,7 @@ int main(int argc, char** argv){
config_free();
return usage(argv[0]);
}
-
+
//load an initial timestamp
update_timestamp();
diff --git a/midimonster.h b/midimonster.h
index d6f04e7..bb1eb24 100644
--- a/midimonster.h
+++ b/midimonster.h
@@ -93,8 +93,9 @@ struct _managed_fd;
* Parse backend-global configuration options from the user-supplied
* configuration file. Returning a non-zero value fails config parsing.
* * mmbackend_instance
- * Allocate space for a backend instance. Returning NULL signals an out-of-memory
- * condition and terminates the program.
+ * Allocate the backend-specific data parts of the supplied instance
+ * structure. Returning non-zero signals an error condition and
+ * terminates the program.
* * mmbackend_configure_instance
* Parse instance configuration from the user-supplied configuration
* file. Returning a non-zero value fails config parsing.
@@ -135,7 +136,7 @@ struct _managed_fd;
* 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 int (*mmbackend_create_instance)(struct _backend_instance* inst);
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);
@@ -223,20 +224,6 @@ typedef struct /*_mm_channel_mapping*/ {
MM_API int mm_backend_register(backend b);
/*
- * Provides a pointer to a newly (zero-)allocated instance.
- * All instance pointers need to be allocated via this API
- * in order to be assignable from the configuration parser.
- * This API should be called from the mmbackend_create_instance
- * call of your backend.
- *
- * Instances returned from this call are freed by midimonster.
- * The contents of the impl members should be freed in the
- * mmbackend_shutdown procedure of the backend, eg. by querying
- * all instances for the backend.
- */
-MM_API instance* mm_instance();
-
-/*
* Finds an instance matching the specified backend and identifier.
* Since setting an identifier for an instance is optional,
* this may not work depending on the backend.