From 4f467a30f88a628e0e49858986d9278e12a92ce5 Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 1 May 2020 16:49:49 +0200 Subject: Implement wininput skeleton and mouse output --- midimonster.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'midimonster.h') diff --git a/midimonster.h b/midimonster.h index 75eb30a..a5de60e 100644 --- a/midimonster.h +++ b/midimonster.h @@ -7,7 +7,7 @@ /* Core version unless set by the build process */ #ifndef MIDIMONSTER_VERSION - #define MIDIMONSTER_VERSION "v0.5-dist" + #define MIDIMONSTER_VERSION "v0.6-dist" #endif /* Set backend name if unset */ -- cgit v1.2.3 From c2248f6bee6b3eef770b557d9be7659dae586222 Mon Sep 17 00:00:00 2001 From: cbdev Date: Sun, 3 May 2020 19:23:45 +0200 Subject: Strip Windows binaries, update semantics for _interval callback --- .travis-ci.sh | 2 ++ backend.c | 4 ++-- midimonster.h | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'midimonster.h') diff --git a/.travis-ci.sh b/.travis-ci.sh index 8f6a5ca..8d5d42d 100644 --- a/.travis-ci.sh +++ b/.travis-ci.sh @@ -78,6 +78,8 @@ elif [ "$TASK" = "windows" ]; then mkdir ./deployment mkdir ./deployment/backends mkdir ./deployment/docs + # Strip the Windows binaries as they become huge quickly + strip midimonster.exe backends/*.dll cp ./midimonster.exe ./deployment/ cp ./backends/*.dll ./deployment/backends/ cp ./backends/*.dll.disabled ./deployment/backends/ diff --git a/backend.c b/backend.c index 003980f..0fb6679 100644 --- a/backend.c +++ b/backend.c @@ -234,12 +234,12 @@ struct timeval backend_timeout(){ //only call interval if backend has instances if(registry.instances[u] && registry.backends[u].interval){ res = registry.backends[u].interval(); - if((res / 1000) < secs){ + if(res && (res / 1000) < secs){ DBGPF("Updating interval to %" PRIu32 " msecs by request from %s", res, registry.backends[u].name); secs = res / 1000; msecs = res % 1000; } - else if(res / 1000 == secs && (res % 1000) < msecs){ + else if(res && res / 1000 == secs && (res % 1000) < msecs){ DBGPF("Updating interval to %" PRIu32 " msecs by request from %s", res, registry.backends[u].name); msecs = res % 1000; } diff --git a/midimonster.h b/midimonster.h index a5de60e..9552b7e 100644 --- a/midimonster.h +++ b/midimonster.h @@ -129,6 +129,8 @@ struct _managed_fd; * * (optional) mmbackend_interval * Return the maximum sleep interval for this backend in milliseconds. * If not implemented, a maximum interval of one second is used. + * Returning 0 signals that the backend does not have a minimum + * interval. * * mmbackend_shutdown * Clean up all allocations, finalize all hardware connections. All registered * backends receive the shutdown call, regardless of whether they have been -- cgit v1.2.3 From ca055614db57386f0e43d65bb10e501bdde699ef Mon Sep 17 00:00:00 2001 From: cbdev Date: Tue, 22 Jun 2021 03:29:08 +0200 Subject: Keep channel registry map in sync when updating identifiers (#76) --- backends/maweb.c | 2 +- core/backend.c | 47 +++++++++++++++++++++++++++++++++++++++++++++-- core/backend.h | 1 + midimonster.c | 4 ++-- midimonster.h | 25 ++++++++++++++++++++----- 5 files changed, 69 insertions(+), 10 deletions(-) (limited to 'midimonster.h') diff --git a/backends/maweb.c b/backends/maweb.c index 39ef7a6..8b878b0 100644 --- a/backends/maweb.c +++ b/backends/maweb.c @@ -1111,7 +1111,7 @@ static int maweb_start(size_t n, instance** inst){ //re-set channel identifiers for(p = 0; p < data->channels; p++){ - data->channel[p].chan->ident = p; + mm_channel_update(data->channel[p].chan, p); } //try to connect to any available host diff --git a/core/backend.c b/core/backend.c index 16e095c..8a8588f 100644 --- a/core/backend.c +++ b/core/backend.c @@ -94,9 +94,9 @@ int backends_notify(size_t nev, channel** c, channel_value* v){ MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create){ size_t u, bucket = channelstore_hash(inst, ident); - DBGPF("\tSearching for inst %" PRIu64 " ident %" PRIu64, inst, ident); + DBGPF("\tSearching for inst %" PRIu64 " ident %" PRIu64, (uint64_t) inst, ident); for(u = 0; u < channels.n[bucket]; u++){ - DBGPF("\tBucket %" PRIsize_t " entry %" PRIsize_t " inst %" PRIu64 " ident %" PRIu64, bucket, u, channels.entry[bucket][u]->instance, channels.entry[bucket][u]->ident); + DBGPF("\tBucket %" PRIsize_t " entry %" PRIsize_t " inst %" PRIu64 " ident %" PRIu64, bucket, u, (uint64_t) channels.entry[bucket][u]->instance, channels.entry[bucket][u]->ident); if(channels.entry[bucket][u]->instance == inst && channels.entry[bucket][u]->ident == ident){ DBGPF("Requested channel %" PRIu64 " on instance %s already exists, reusing (bucket %" PRIsize_t ", %" PRIsize_t " search steps)\n", ident, inst->name, bucket, u); @@ -128,6 +128,49 @@ MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create){ return channels.entry[bucket][(channels.n[bucket]++)]; } +MM_API void mm_channel_update(channel* chan, uint64_t ident){ + size_t bucket = channelstore_hash(chan->instance, chan->ident), new_bucket = channelstore_hash(chan->instance, ident); + size_t u; + + DBGPF("Updating identifier for inst %" PRIu64 " ident %" PRIu64 " (bucket %" PRIsize_t " to %" PRIsize_t ") to %" PRIu64, (uint64_t) chan->instance, chan->ident, bucket, new_bucket, ident); + + if(bucket == new_bucket){ + chan->ident = ident; + return; + } + + for(u = 0; u < channels.n[bucket]; u++){ + if(channels.entry[bucket][u]->instance == chan->instance + && channels.entry[bucket][u]->ident == chan->ident){ + break; + } + } + + if(u == channels.n[bucket]){ + DBGPF("Failed to find channel to update in bucket %" PRIsize_t, bucket); + return; + } + + DBGPF("Removing channel from slot %" PRIsize_t " of %" PRIsize_t " of bucket %" PRIsize_t, u, channels.n[bucket], bucket); + //remove channel from old bucket + for(; u < channels.n[bucket] - 1; u++){ + channels.entry[bucket][u] = channels.entry[bucket][u + 1]; + } + + //add to new bucket + channels.entry[new_bucket] = realloc(channels.entry[new_bucket], (channels.n[new_bucket] + 1) * sizeof(channel*)); + if(!channels.entry[new_bucket]){ + fprintf(stderr, "Failed to allocate memory\n"); + channels.n[new_bucket] = 0; + return; + } + + channels.entry[new_bucket][channels.n[new_bucket]] = chan; + chan->ident = ident; + channels.n[bucket]--; + channels.n[new_bucket]++; +} + instance* mm_instance(backend* b){ size_t u = 0, n = 0; diff --git a/core/backend.h b/core/backend.h index 6a69508..46c6c3a 100644 --- a/core/backend.h +++ b/core/backend.h @@ -12,6 +12,7 @@ instance* mm_instance(backend* b); /* Backend API */ MM_API channel* mm_channel(instance* inst, uint64_t ident, uint8_t create); +MM_API void mm_channel_update(channel* chan, uint64_t ident); 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/midimonster.c b/midimonster.c index 51fe7ad..5817ac7 100644 --- a/midimonster.c +++ b/midimonster.c @@ -346,7 +346,7 @@ static int core_process(size_t nfds, managed_fd* signaled_fds){ size_t u, swaps = 0; //run backend processing, collect events - DBGPF("%lu backend FDs signaled\n", nfds); + DBGPF("%lu backend FDs signaled", nfds); if(backends_handle(nfds, signaled_fds)){ return 1; } @@ -354,7 +354,7 @@ static int core_process(size_t nfds, managed_fd* signaled_fds){ //limit number of collector swaps per iteration to prevent complete deadlock while(routing.events->n && swaps < MM_SWAP_LIMIT){ //swap primary and secondary event collectors - DBGPF("Swapping event collectors, %lu events in primary\n", routing.events->n); + DBGPF("Swapping event collectors, %lu events in primary", routing.events->n); for(u = 0; u < sizeof(routing.pool) / sizeof(routing.pool[0]); u++){ if(routing.events != routing.pool + u){ secondary = routing.events; diff --git a/midimonster.h b/midimonster.h index 9552b7e..89688c4 100644 --- a/midimonster.h +++ b/midimonster.h @@ -227,15 +227,21 @@ MM_API int mm_backend_register(backend b); 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. + * This function is the main interface to the core-provided channel registry. + * This API is just a convenience function. Creating and managing a + * backend-internal channel store is possible (and encouraged for performance + * reasons). + * + * Channels are identified by the (instance, ident) tuple within the registry. + * + * This API provides a pointer to a channel structure, pre-filled with the + * provided instance reference and identifier. * The `create` parameter is a boolean flag indicating whether a channel * matching the `ident` parameter should be created in the global channel store * if none exists yet. If the instance already registered a channel matching * `ident`, a pointer to the existing channel is returned. - * This API is just a convenience function. Creating and managing a - * backend-internal channel store is possible (and encouraged for performance - * reasons). When returning pointers from a backend-local channel store, the + * + * When returning pointers from a backend-local channel store, the * returned pointers must stay valid over the lifetime of the instance and * provide valid `instance` members, as they are used for callbacks. * For each channel with a non-NULL `impl` field registered using @@ -244,6 +250,15 @@ MM_API instance* mm_instance_find(char* backend, uint64_t ident); */ MM_API channel* mm_channel(instance* i, uint64_t ident, uint8_t create); +/* + * When using the core-provided channel registry, the identification + * member of the structure must only be updated using this API. + * The tuple of (instance, ident) is used as key to the backing + * storage of the channel registry, thus the registry must be notified + * of changes. + */ +MM_API void mm_channel_update(channel* c, uint64_t ident); + /* * Register (manage = 1) or unregister (manage = 0) a file descriptor to be * selected on. The backend will be notified when the descriptor becomes ready -- cgit v1.2.3