aboutsummaryrefslogtreecommitdiffhomepage
path: root/midimonster.c
diff options
context:
space:
mode:
Diffstat (limited to 'midimonster.c')
-rw-r--r--midimonster.c106
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, &current)){
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;