From 9c37eddad24eb7e9bbc9aae723b3a992ec5b4c97 Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 5 Dec 2019 19:31:14 +0100 Subject: Unify midi parsing/deparsing code --- backends/winmidi.c | 89 ++++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 63 deletions(-) (limited to 'backends/winmidi.c') diff --git a/backends/winmidi.c b/backends/winmidi.c index bda5401..b274c06 100644 --- a/backends/winmidi.c +++ b/backends/winmidi.c @@ -203,35 +203,17 @@ static int winmidi_set(instance* inst, size_t num, channel** c, channel_value* v for(u = 0; u < num; u++){ ident.label = c[u]->ident; - switch(ident.fields.type){ - case note: - output.components.status = 0x90 | ident.fields.channel; - output.components.data1 = ident.fields.control; - output.components.data2 = v[u].normalised * 127.0; - break; - case cc: - output.components.status = 0xB0 | ident.fields.channel; - output.components.data1 = ident.fields.control; - output.components.data2 = v[u].normalised * 127.0; - break; - case pressure: - output.components.status = 0xA0 | ident.fields.channel; - output.components.data1 = ident.fields.control; - output.components.data2 = v[u].normalised * 127.0; - break; - case aftertouch: - output.components.status = 0xD0 | ident.fields.channel; - output.components.data1 = v[u].normalised * 127.0; - output.components.data2 = 0; - break; - case pitchbend: - output.components.status = 0xE0 | ident.fields.channel; - output.components.data1 = ((int)(v[u].normalised * 16384.0)) & 0x7F; - output.components.data2 = (((int)(v[u].normalised * 16384.0)) >> 7) & 0x7F; - break; - default: - fprintf(stderr, "Unknown winmidi channel type %d\n", ident.fields.type); - continue; + //build output message + output.components.status = ident.fields.type | ident.fields.channel; + output.components.data1 = ident.fields.control; + output.components.data2 = v[u].normalised * 127.0; + if(ident.fields.type == pitchbend){ + output.components.data1 = ((int)(v[u].normalised * 16384.0)) & 0x7F; + output.components.data2 = (((int)(v[u].normalised * 16384.0)) >> 7) & 0x7F; + } + else if(ident.fields.type == aftertouch){ + output.components.data1 = v[u].normalised * 127.0; + output.components.data2 = 0; } midiOutShortMsg(data->device_out, output.dword); @@ -330,40 +312,21 @@ static void CALLBACK winmidi_input_callback(HMIDIIN device, unsigned message, DW //param1 has the message input.dword = param1; ident.fields.channel = input.components.status & 0x0F; - switch(input.components.status & 0xF0){ - case 0x80: - ident.fields.type = note; - ident.fields.control = input.components.data1; - val.normalised = 0.0; - break; - case 0x90: - ident.fields.type = note; - ident.fields.control = input.components.data1; - val.normalised = (double) input.components.data2 / 127.0; - break; - case 0xA0: - ident.fields.type = pressure; - ident.fields.control = input.components.data1; - val.normalised = (double) input.components.data2 / 127.0; - break; - case 0xB0: - ident.fields.type = cc; - ident.fields.control = input.components.data1; - val.normalised = (double) input.components.data2 / 127.0; - break; - case 0xD0: - ident.fields.type = aftertouch; - ident.fields.control = 0; - val.normalised = (double) input.components.data1 / 127.0; - break; - case 0xE0: - ident.fields.type = pitchbend; - ident.fields.control = 0; - val.normalised = (double)((input.components.data2 << 7) | input.components.data1) / 16384.0; - break; - default: - fprintf(stderr, "winmidi unhandled status byte %02X\n", input.components.status); - return; + ident.fields.type = input.components.status & 0xF0; + ident.fields.control = input.components.data1; + val.normalised = (double) input.components.data2 / 127.0; + + if(ident.fields.type == 0x80){ + ident.fields.type = note; + val.normalised = 0; + } + else if(ident.fields.type == pitchbend){ + ident.fields.control = 0; + val.normalised = (double)((input.components.data2 << 7) | input.components.data1) / 16384.0; + } + else if(ident.fields.type == aftertouch){ + ident.fields.control = 0; + val.normalised = (double) input.components.data1 / 127.0; } break; case MIM_LONGDATA: -- cgit v1.2.3 From 3eada28582b144519e95a44ee3adc3f46d39036e Mon Sep 17 00:00:00 2001 From: cbdev Date: Thu, 5 Dec 2019 21:05:14 +0100 Subject: Add flags parameter to channel parser plugin API (Fixes #31) --- backends/winmidi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'backends/winmidi.c') diff --git a/backends/winmidi.c b/backends/winmidi.c index b274c06..790257b 100644 --- a/backends/winmidi.c +++ b/backends/winmidi.c @@ -110,7 +110,7 @@ static instance* winmidi_instance(){ return i; } -static channel* winmidi_channel(instance* inst, char* spec){ +static channel* winmidi_channel(instance* inst, char* spec, uint8_t flags){ char* next_token = NULL; winmidi_channel_ident ident = { .label = 0 -- cgit v1.2.3 From f65fb8baaba285f5ff4b02af111420ba4479f5d9 Mon Sep 17 00:00:00 2001 From: cbdev Date: Wed, 11 Dec 2019 23:02:22 +0100 Subject: Simplify plugin_start API --- backends/winmidi.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) (limited to 'backends/winmidi.c') diff --git a/backends/winmidi.c b/backends/winmidi.c index 790257b..0fc1aca 100644 --- a/backends/winmidi.c +++ b/backends/winmidi.c @@ -440,10 +440,9 @@ static int winmidi_match_output(char* prefix){ return -1; } -static int winmidi_start(){ - size_t n = 0, p; +static int winmidi_start(size_t n, instance** inst){ + size_t p; int device, rv = -1; - instance** inst = NULL; winmidi_instance_data* data = NULL; struct sockaddr_storage sockadd = { 0 @@ -453,18 +452,6 @@ static int winmidi_start(){ char* error = NULL; DBGPF("winmidi main thread ID is %ld\n", GetCurrentThreadId()); - //fetch all instances - if(mm_backend_instances(BACKEND_NAME, &n, &inst)){ - fprintf(stderr, "Failed to fetch instance list\n"); - return 1; - } - - //no instances, we're done - if(!n){ - free(inst); - return 0; - } - //output device list if requested if(backend_config.list_devices){ winmidi_match_input(NULL); @@ -552,7 +539,6 @@ static int winmidi_start(){ rv = 0; bail: - free(inst); return rv; } -- cgit v1.2.3 From f6d6eefe9bb9934f4fa3e665734d746f02471cdb Mon Sep 17 00:00:00 2001 From: cbdev Date: Wed, 11 Dec 2019 23:20:34 +0100 Subject: Simplify plugin_stop API --- backends/winmidi.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'backends/winmidi.c') diff --git a/backends/winmidi.c b/backends/winmidi.c index 0fc1aca..090e438 100644 --- a/backends/winmidi.c +++ b/backends/winmidi.c @@ -542,16 +542,10 @@ bail: return rv; } -static int winmidi_shutdown(){ - size_t n, u; - instance** inst = NULL; +static int winmidi_shutdown(size_t n, instance** inst){ + size_t u; winmidi_instance_data* data = NULL; - if(mm_backend_instances(BACKEND_NAME, &n, &inst)){ - fprintf(stderr, "Failed to fetch instance list\n"); - return 1; - } - for(u = 0; u < n; u++){ data = (winmidi_instance_data*) inst[u]->impl; free(data->read); @@ -572,7 +566,6 @@ static int winmidi_shutdown(){ } } - free(inst); closesocket(backend_config.socket_pair[0]); closesocket(backend_config.socket_pair[1]); -- cgit v1.2.3 From 763f6d6a434b6e5a9d166cb538857d0cac5fa29e Mon Sep 17 00:00:00 2001 From: cbdev Date: Wed, 11 Dec 2019 23:33:27 +0100 Subject: Release instance implementation data allocation --- backends/winmidi.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'backends/winmidi.c') diff --git a/backends/winmidi.c b/backends/winmidi.c index 090e438..c917ac6 100644 --- a/backends/winmidi.c +++ b/backends/winmidi.c @@ -564,6 +564,8 @@ static int winmidi_shutdown(size_t n, instance** inst){ midiOutClose(data->device_out); data->device_out = NULL; } + + free(inst[u]->impl); } closesocket(backend_config.socket_pair[0]); -- cgit v1.2.3 From 062c93b1f718730c71bc4d2a1e53e0107dd236ad Mon Sep 17 00:00:00 2001 From: cbdev Date: Fri, 20 Dec 2019 21:29:18 +0100 Subject: Route all backend debug logging through a macro --- backends/winmidi.c | 84 +++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'backends/winmidi.c') diff --git a/backends/winmidi.c b/backends/winmidi.c index c917ac6..0722ca2 100644 --- a/backends/winmidi.c +++ b/backends/winmidi.c @@ -1,3 +1,5 @@ +#define BACKEND_NAME "winmidi" + #include #include "libmmbackend.h" @@ -5,8 +7,6 @@ #include "winmidi.h" -#define BACKEND_NAME "winmidi" - static struct { uint8_t list_devices; uint8_t detect; @@ -37,13 +37,13 @@ MM_PLUGIN_API int init(){ }; if(sizeof(winmidi_channel_ident) != sizeof(uint64_t)){ - fprintf(stderr, "winmidi channel identification union out of bounds\n"); + LOG("Channel identification union out of bounds"); return 1; } //register backend if(mm_backend_register(winmidi)){ - fprintf(stderr, "Failed to register winmidi backend\n"); + LOG("Failed to register backend"); return 1; } @@ -68,7 +68,7 @@ static int winmidi_configure(char* option, char* value){ return 0; } - fprintf(stderr, "Unknown winmidi backend option %s\n", option); + LOGPF("Unknown backend option %s", option); return 1; } @@ -76,7 +76,7 @@ static int winmidi_configure_instance(instance* inst, char* option, char* value) winmidi_instance_data* data = (winmidi_instance_data*) inst->impl; if(!strcmp(option, "read")){ if(data->read){ - fprintf(stderr, "winmidi instance %s already connected to an input device\n", inst->name); + LOGPF("Instance %s already connected to an input device", inst->name); return 1; } data->read = strdup(value); @@ -84,14 +84,14 @@ static int winmidi_configure_instance(instance* inst, char* option, char* value) } if(!strcmp(option, "write")){ if(data->write){ - fprintf(stderr, "winmidi instance %s already connected to an output device\n", inst->name); + LOGPF("Instance %s already connected to an output device", inst->name); return 1; } data->write = strdup(value); return 0; } - fprintf(stderr, "Unknown winmidi instance option %s\n", option); + LOGPF("Unknown instance configuration option %s on instance %s", option, inst->name); return 1; } @@ -103,7 +103,7 @@ static instance* winmidi_instance(){ i->impl = calloc(1, sizeof(winmidi_instance_data)); if(!i->impl){ - fprintf(stderr, "Failed to allocate memory\n"); + LOG("Failed to allocate memory"); return NULL; } @@ -124,18 +124,18 @@ static channel* winmidi_channel(instance* inst, char* spec, uint8_t flags){ } if(!next_token){ - fprintf(stderr, "Invalid winmidi channel specification %s\n", spec); + LOGPF("Invalid channel specification %s", spec); return NULL; } ident.fields.channel = strtoul(next_token, &next_token, 10); if(ident.fields.channel > 15){ - fprintf(stderr, "MIDI channel out of range in winmidi channel spec %s\n", spec); + LOGPF("MIDI channel out of range in spec %s", spec); return NULL; } if(*next_token != '.'){ - fprintf(stderr, "winmidi channel specification %s does not conform to channel.\n", spec); + LOGPF("Channel specification %s does not conform to channel.", spec); return NULL; } @@ -160,7 +160,7 @@ static channel* winmidi_channel(instance* inst, char* spec, uint8_t flags){ ident.fields.type = aftertouch; } else{ - fprintf(stderr, "Unknown winmidi channel control type in %s\n", spec); + LOGPF("Unknown control type in %s", spec); return NULL; } @@ -196,7 +196,7 @@ static int winmidi_set(instance* inst, size_t num, channel** c, channel_value* v } if(!data->device_out){ - fprintf(stderr, "winmidi instance %s has no output device\n", inst->name); + LOGPF("Instance %s has no output device", inst->name); return 0; } @@ -259,14 +259,14 @@ static int winmidi_handle(size_t num, managed_fd* fds){ //pretty-print channel-wide events if(backend_config.event[u].channel.fields.type == pitchbend || backend_config.event[u].channel.fields.type == aftertouch){ - fprintf(stderr, "Incoming MIDI data on channel %s.ch%d.%s, value %f\n", + LOGPF("Incoming data on channel %s.ch%d.%s, value %f", backend_config.event[u].inst->name, backend_config.event[u].channel.fields.channel, winmidi_type_name(backend_config.event[u].channel.fields.type), backend_config.event[u].value); } else{ - fprintf(stderr, "Incoming MIDI data on channel %s.ch%d.%s%d, value %f\n", + LOGPF("Incoming data on channel %s.ch%d.%s%d, value %f", backend_config.event[u].inst->name, backend_config.event[u].channel.fields.channel, winmidi_type_name(backend_config.event[u].channel.fields.type), @@ -279,7 +279,7 @@ static int winmidi_handle(size_t num, managed_fd* fds){ mm_channel_event(chan, backend_config.event[u].value); } } - DBGPF("winmidi flushed %" PRIsize_t " wakeups, handled %" PRIsize_t " events\n", bytes, backend_config.events_active); + DBGPF("Flushed %" PRIsize_t " wakeups, handled %" PRIsize_t " events", bytes, backend_config.events_active); backend_config.events_active = 0; LeaveCriticalSection(&backend_config.push_events); return 0; @@ -303,7 +303,7 @@ static void CALLBACK winmidi_input_callback(HMIDIIN device, unsigned message, DW }; //callbacks may run on different threads, so we queue all events and alert the main thread via the feedback socket - DBGPF("winmidi input callback on thread %ld\n", GetCurrentThreadId()); + DBGPF("Input callback on thread %ld", GetCurrentThreadId()); switch(message){ case MIM_MOREDATA: @@ -334,7 +334,7 @@ static void CALLBACK winmidi_input_callback(HMIDIIN device, unsigned message, DW return; case MIM_ERROR: //error in input stream - fprintf(stderr, "winmidi warning: error in input stream\n"); + LOG("Error in input stream"); return; case MIM_OPEN: case MIM_CLOSE: @@ -343,14 +343,14 @@ static void CALLBACK winmidi_input_callback(HMIDIIN device, unsigned message, DW } - DBGPF("winmidi incoming message type %d channel %d control %d value %f\n", + DBGPF("Incoming message type %d channel %d control %d value %f", ident.fields.type, ident.fields.channel, ident.fields.control, val.normalised); EnterCriticalSection(&backend_config.push_events); if(backend_config.events_alloc <= backend_config.events_active){ backend_config.event = realloc((void*) backend_config.event, (backend_config.events_alloc + 1) * sizeof(winmidi_event)); if(!backend_config.event){ - fprintf(stderr, "Failed to allocate memory\n"); + LOG("Failed to allocate memory"); backend_config.events_alloc = 0; backend_config.events_active = 0; LeaveCriticalSection(&backend_config.push_events); @@ -371,7 +371,7 @@ static void CALLBACK winmidi_input_callback(HMIDIIN device, unsigned message, DW } static void CALLBACK winmidi_output_callback(HMIDIOUT device, unsigned message, DWORD_PTR inst, DWORD param1, DWORD param2){ - DBGPF("winmidi output callback on thread %ld\n", GetCurrentThreadId()); + DBGPF("Output callback on thread %ld", GetCurrentThreadId()); } static int winmidi_match_input(char* prefix){ @@ -381,13 +381,13 @@ static int winmidi_match_input(char* prefix){ size_t n; if(!prefix){ - fprintf(stderr, "winmidi detected %u input devices\n", inputs); + LOGPF("Detected %u input devices", inputs); } else{ n = strtoul(prefix, &next_token, 10); if(!(*next_token) && n < inputs){ midiInGetDevCaps(n, &input_caps, sizeof(MIDIINCAPS)); - fprintf(stderr, "winmidi selected input device %s for ID %d\n", input_caps.szPname, n); + LOGPF("Selected input device %s for ID %d", input_caps.szPname, n); return n; } } @@ -396,10 +396,10 @@ static int winmidi_match_input(char* prefix){ for(n = 0; n < inputs; n++){ midiInGetDevCaps(n, &input_caps, sizeof(MIDIINCAPS)); if(!prefix){ - printf("\tID %d: %s\n", n, input_caps.szPname); + printf("\tID %d: %s", n, input_caps.szPname); } else if(!strncmp(input_caps.szPname, prefix, strlen(prefix))){ - fprintf(stderr, "winmidi selected input device %s (ID %" PRIsize_t ") for name %s\n", input_caps.szPname, n, prefix); + LOGPF("Selected input device %s (ID %" PRIsize_t ") for name %s", input_caps.szPname, n, prefix); return n; } } @@ -414,13 +414,13 @@ static int winmidi_match_output(char* prefix){ size_t n; if(!prefix){ - fprintf(stderr, "winmidi detected %u output devices\n", outputs); + LOGPF("Detected %u output devices", outputs); } else{ n = strtoul(prefix, &next_token, 10); if(!(*next_token) && n < outputs){ midiOutGetDevCaps(n, &output_caps, sizeof(MIDIOUTCAPS)); - fprintf(stderr, "winmidi selected output device %s for ID %d\n", output_caps.szPname, n); + LOGPF("Selected output device %s for ID %d", output_caps.szPname, n); return n; } } @@ -429,10 +429,10 @@ static int winmidi_match_output(char* prefix){ for(n = 0; n < outputs; n++){ midiOutGetDevCaps(n, &output_caps, sizeof(MIDIOUTCAPS)); if(!prefix){ - printf("\tID %d: %s\n", n, output_caps.szPname); + printf("\tID %d: %s", n, output_caps.szPname); } else if(!strncmp(output_caps.szPname, prefix, strlen(prefix))){ - fprintf(stderr, "winmidi selected output device %s (ID %" PRIsize_t " for name %s\n", output_caps.szPname, n, prefix); + LOGPF("Selected output device %s (ID %" PRIsize_t " for name %s", output_caps.szPname, n, prefix); return n; } } @@ -450,7 +450,7 @@ static int winmidi_start(size_t n, instance** inst){ //this really should be a size_t but getsockname specifies int* for some reason int sockadd_len = sizeof(sockadd); char* error = NULL; - DBGPF("winmidi main thread ID is %ld\n", GetCurrentThreadId()); + DBGPF("Main thread ID is %ld", GetCurrentThreadId()); //output device list if requested if(backend_config.list_devices){ @@ -462,13 +462,13 @@ static int winmidi_start(size_t n, instance** inst){ //for some reason the feedback connection fails to work on 'real' windows with ipv6 backend_config.socket_pair[0] = mmbackend_socket("127.0.0.1", "0", SOCK_DGRAM, 1, 0); if(backend_config.socket_pair[0] < 0){ - fprintf(stderr, "winmidi failed to open feedback socket\n"); + LOG("Failed to open feedback socket"); return 1; } if(getsockname(backend_config.socket_pair[0], (struct sockaddr*) &sockadd, &sockadd_len)){ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error, 0, NULL); - fprintf(stderr, "winmidi failed to query feedback socket information: %s\n", error); + LOGPF("Failed to query feedback socket information: %s", error); LocalFree(error); return 1; } @@ -484,15 +484,15 @@ static int winmidi_start(size_t n, instance** inst){ // ((struct sockaddr_in6*) &sockadd)->sin6_addr = in6addr_any; // break; default: - fprintf(stderr, "winmidi invalid feedback socket family\n"); + LOG("Invalid feedback socket family"); return 1; } - DBGPF("winmidi feedback socket family %d port %d\n", sockadd.ss_family, be16toh(((struct sockaddr_in*)&sockadd)->sin_port)); + DBGPF("Feedback socket family %d port %d", sockadd.ss_family, be16toh(((struct sockaddr_in*)&sockadd)->sin_port)); backend_config.socket_pair[1] = socket(sockadd.ss_family, SOCK_DGRAM, IPPROTO_UDP); if(backend_config.socket_pair[1] < 0 || connect(backend_config.socket_pair[1], (struct sockaddr*) &sockadd, sockadd_len)){ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &error, 0, NULL); - fprintf(stderr, "winmidi failed to connect to feedback socket: %s\n", error); + LOGPF("Failed to connect to feedback socket: %s", error); LocalFree(error); return 1; } @@ -506,11 +506,11 @@ static int winmidi_start(size_t n, instance** inst){ if(data->read){ device = winmidi_match_input(data->read); if(device < 0){ - fprintf(stderr, "Failed to match input device %s for instance %s\n", data->read, inst[p]->name); + LOGPF("Failed to match input device %s for instance %s", data->read, inst[p]->name); goto bail; } if(midiInOpen(&(data->device_in), device, (DWORD_PTR) winmidi_input_callback, (DWORD_PTR) inst[p], CALLBACK_FUNCTION | MIDI_IO_STATUS) != MMSYSERR_NOERROR){ - fprintf(stderr, "Failed to open input device for instance %s\n", inst[p]->name); + LOGPF("Failed to open input device for instance %s", inst[p]->name); goto bail; } //start midi input callbacks @@ -521,18 +521,18 @@ static int winmidi_start(size_t n, instance** inst){ if(data->write){ device = winmidi_match_output(data->write); if(device < 0){ - fprintf(stderr, "Failed to match output device %s for instance %s\n", data->read, inst[p]->name); + LOGPF("Failed to match output device %s for instance %s", data->read, inst[p]->name); goto bail; } if(midiOutOpen(&(data->device_out), device, (DWORD_PTR) winmidi_output_callback, (DWORD_PTR) inst[p], CALLBACK_FUNCTION) != MMSYSERR_NOERROR){ - fprintf(stderr, "Failed to open output device for instance %s\n", inst[p]->name); + LOGPF("Failed to open output device for instance %s", inst[p]->name); goto bail; } } } //register the feedback socket to the core - fprintf(stderr, "winmidi backend registering 1 descriptor to core\n"); + LOG("Registering 1 descriptor to core"); if(mm_manage_fd(backend_config.socket_pair[0], BACKEND_NAME, 1, NULL)){ goto bail; } @@ -579,6 +579,6 @@ static int winmidi_shutdown(size_t n, instance** inst){ LeaveCriticalSection(&backend_config.push_events); DeleteCriticalSection(&backend_config.push_events); - fprintf(stderr, "winmidi backend shut down\n"); + LOG("Backend shut down"); return 0; } -- cgit v1.2.3