diff options
Diffstat (limited to 'midimonster.c')
-rw-r--r-- | midimonster.c | 106 |
1 files changed, 77 insertions, 29 deletions
diff --git a/midimonster.c b/midimonster.c index 629a0d9..e6c0842 100644 --- a/midimonster.c +++ b/midimonster.c @@ -1,9 +1,14 @@ #include <string.h> #include <signal.h> -#include <sys/select.h> #include <unistd.h> #include <errno.h> #include <time.h> +#ifndef _WIN32 +#include <sys/select.h> +#define MM_API __attribute__((visibility("default"))) +#else +#define MM_API __attribute__((dllexport)) +#endif #include "midimonster.h" #include "config.h" #include "backend.h" @@ -20,6 +25,7 @@ static size_t mappings = 0; static channel_mapping* map = NULL; static size_t fds = 0; static managed_fd* fd = NULL; +static volatile sig_atomic_t fd_set_dirty = 1; static uint64_t global_timestamp = 0; static event_collection event_pool[2] = { @@ -34,11 +40,14 @@ static void signal_handler(int signum){ shutdown_requested = 1; } -uint64_t mm_timestamp(){ +MM_API uint64_t mm_timestamp(){ return global_timestamp; } static void update_timestamp(){ + #ifdef _WIN32 + global_timestamp = GetTickCount(); + #else struct timespec current; if(clock_gettime(CLOCK_MONOTONIC_COARSE, ¤t)){ fprintf(stderr, "Failed to update global timestamp, time-based processing for some backends may be impaired: %s\n", strerror(errno)); @@ -46,6 +55,7 @@ static void update_timestamp(){ } global_timestamp = current.tv_sec * 1000 + current.tv_nsec / 1000000; + #endif } int mm_map_channel(channel* from, channel* to){ @@ -88,7 +98,7 @@ int mm_map_channel(channel* from, channel* to){ return 0; } -void map_free(){ +static void map_free(){ size_t u; for(u = 0; u < mappings; u++){ free(map[u].to); @@ -98,7 +108,7 @@ void map_free(){ map = NULL; } -int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ +MM_API int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ backend* b = backend_match(back); size_t u; @@ -114,6 +124,7 @@ int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ fd[u].fd = -1; fd[u].backend = NULL; fd[u].impl = NULL; + fd_set_dirty = 1; } return 0; } @@ -143,10 +154,11 @@ int mm_manage_fd(int new_fd, char* back, int manage, void* impl){ fd[u].fd = new_fd; fd[u].backend = b; fd[u].impl = impl; + fd_set_dirty = 1; return 0; } -void fds_free(){ +static void fds_free(){ size_t u; for(u = 0; u < fds; u++){ //TODO free impl @@ -160,7 +172,7 @@ void fds_free(){ fd = NULL; } -int mm_channel_event(channel* c, channel_value v){ +MM_API int mm_channel_event(channel* c, channel_value v){ size_t u, p; //find mapped channels @@ -201,7 +213,7 @@ int mm_channel_event(channel* c, channel_value v){ return 0; } -void event_free(){ +static void event_free(){ size_t u; for(u = 0; u < sizeof(event_pool) / sizeof(event_collection); u++){ @@ -211,13 +223,46 @@ void event_free(){ } } -int usage(char* fn){ - fprintf(stderr, "MIDIMonster v0.1\n"); +static int usage(char* fn){ + fprintf(stderr, "MIDIMonster v0.3\n"); fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t%s <configfile>\n", fn); return EXIT_FAILURE; } +static fd_set fds_collect(int* max_fd){ + size_t u = 0; + fd_set rv_fds; + + if(max_fd){ + *max_fd = -1; + } + + DBGPF("Building selector set from %lu FDs registered to core\n", fds); + FD_ZERO(&rv_fds); + for(u = 0; u < fds; u++){ + if(fd[u].fd >= 0){ + FD_SET(fd[u].fd, &rv_fds); + if(max_fd){ + *max_fd = max(*max_fd, fd[u].fd); + } + } + } + + return rv_fds; +} + +static int platform_initialize(){ +#ifdef _WIN32 + WSADATA wsa; + WORD version = MAKEWORD(2, 2); + if(WSAStartup(version, &wsa)){ + return 1; + } +#endif + return 0; +} + int main(int argc, char** argv){ fd_set all_fds, read_fds; event_collection* secondary = NULL; @@ -230,6 +275,12 @@ int main(int argc, char** argv){ cfg_file = argv[1]; } + if(platform_initialize()){ + fprintf(stderr, "Failed to perform platform-specific initialization\n"); + return EXIT_FAILURE; + } + + FD_ZERO(&all_fds); //initialize backends if(plugins_load(PLUGINS)){ fprintf(stderr, "Failed to initialize a backend\n"); @@ -247,6 +298,9 @@ int main(int argc, char** argv){ plugins_close(); return usage(argv[0]); } + + //load an initial timestamp + update_timestamp(); //start backends if(backends_start()){ @@ -255,25 +309,19 @@ int main(int argc, char** argv){ signal(SIGINT, signal_handler); - //allocate data buffers - signaled_fds = calloc(fds, sizeof(managed_fd)); - if(!signaled_fds){ - fprintf(stderr, "Failed to allocate memory\n"); - goto bail; - } - - //create initial fd set - DBGPF("Building selector set from %zu FDs registered to core\n", fds); - FD_ZERO(&all_fds); - for(u = 0; u < fds; u++){ - if(fd[u].fd >= 0){ - FD_SET(fd[u].fd, &all_fds); - maxfd = max(maxfd, fd[u].fd); - } - } - //process events while(!shutdown_requested){ + //rebuild fd set if necessary + if(fd_set_dirty){ + all_fds = fds_collect(&maxfd); + signaled_fds = realloc(signaled_fds, fds * sizeof(managed_fd)); + if(!signaled_fds){ + fprintf(stderr, "Failed to allocate memory\n"); + goto bail; + } + fd_set_dirty = 0; + } + //wait for & translate events read_fds = all_fds; tv = backend_timeout(); @@ -296,15 +344,15 @@ int main(int argc, char** argv){ update_timestamp(); //run backend processing, collect events - DBGPF("%zu backend FDs signaled\n", n); + DBGPF("%lu backend FDs signaled\n", n); if(backends_handle(n, signaled_fds)){ goto bail; } while(primary->n){ //swap primary and secondary event collectors - DBGPF("Swapping event collectors, %zu events in primary\n", primary->n); - for(u = 0; u < sizeof(event_pool)/sizeof(event_collection); u++){ + DBGPF("Swapping event collectors, %lu events in primary\n", primary->n); + for(u = 0; u < sizeof(event_pool) / sizeof(event_collection); u++){ if(primary != event_pool + u){ secondary = primary; primary = event_pool + u; |