mirror of
https://github.com/gmcn42/mt32-pi-control.git
synced 2026-09-22 18:37:58 +00:00
Windows version!
This commit is contained in:
1 parent
4c158d0dbc
commit
ae61234460
3 files changed
+135
-22
No files matched your search
@@ -146,6 +146,10 @@ void mididev_add_optstr(char *optstr) {
|
||||
}
|
||||
|
||||
int mididev_parse_arg(int c, const char *optarg) {
|
||||
if(c != 'p') {
|
||||
fprintf(stderr, "ERROR: Unknown option \'%c\'.\n", c);
|
||||
return -1;
|
||||
}
|
||||
size_t len = strlen(optarg);
|
||||
char *temparg = (char*) malloc(len+1);
|
||||
if(temparg == NULL) {
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ CFLAGS = $(INCLUDE) -O2 -ffunction-sections -fdata-sections -static-libgcc -stat
|
||||
|
||||
CXXFLAGS = $(INCLUDE) -O2 -ffunction-sections -fdata-sections -static-libgcc -static-libstdc++ -Wl,--gc-sections -Wall -Werror $(DEFINE)
|
||||
|
||||
LIBS =
|
||||
LIBS = -lwinmm
|
||||
|
||||
OBJ = mt32-pi.o midi_dev.o delay.o
|
||||
|
||||
|
||||
+130
-21
@@ -7,45 +7,154 @@
|
||||
* Copyright (C) 2021 Andreas Zdziarstek
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "windows.h"
|
||||
|
||||
#include "midi_dev.h"
|
||||
|
||||
int output_port = -1;
|
||||
HMIDIOUT midi_handle = NULL;
|
||||
static volatile bool port_busy = false;
|
||||
static char *dev_optstr = "lp:";
|
||||
|
||||
static void list_midi_outputs(void);
|
||||
void CALLBACK midi_out_cb(
|
||||
HMIDIOUT mh,
|
||||
UINT wMsg,
|
||||
DWORD_PTR dwInst,
|
||||
DWORD_PTR dwp1,
|
||||
DWORD_PTR dwp2
|
||||
);
|
||||
|
||||
int mididev_init(void) {
|
||||
if(output_port == -1) {
|
||||
fprintf(stderr, "ERROR: You must specify the MIDI output port number with \"-p PORT\". You can list available ports with \"-l\".\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(midiOutOpen(&midi_handle, output_port, (DWORD)(void*)midi_out_cb, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
|
||||
fprintf(stderr, "ERROR: Could not open MIDI output port %d.\n", output_port);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mididev_deinit(void) {
|
||||
midiOutClose(midi_handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int mididev_send_bytes(const unsigned char *buf, int len) {
|
||||
if(len==0) return 0;
|
||||
if(len==0) return 0;
|
||||
|
||||
if((buf[0] == 0xF0 && buf[len-1] == 0xF7) || len==3) {
|
||||
for(int i=0; i<len; i++) {
|
||||
fprintf(stderr, "%02X ", buf[i]);
|
||||
|
||||
if(buf[0] == 0xF0 && buf[len-1] == 0xF7) {
|
||||
MIDIHDR mheader;
|
||||
char *tempbuf = (char *) malloc(len);
|
||||
if(tempbuf == NULL) {
|
||||
fprintf(stderr, "Error allocating memory for MIDI output buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(tempbuf, buf, len);
|
||||
mheader.lpData = tempbuf;
|
||||
mheader.dwBufferLength = len;
|
||||
mheader.dwFlags = 0;
|
||||
mheader.dwBytesRecorded = len;
|
||||
if(midiOutPrepareHeader(midi_handle, &mheader, sizeof(mheader)) != MMSYSERR_NOERROR) {
|
||||
free(tempbuf);
|
||||
fprintf(stderr, "ERROR: Failed to prepare MIDI header.\n");
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
} else {
|
||||
fprintf(stderr, "Error: Non-SysEx message with more than 3 bytes.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//fprintf(stderr, "len:%d end:%02X\n", len, buf[len-1]);
|
||||
// for(int i=0; i<len; i++) {
|
||||
// fprintf(stderr, "%02X ", buf[i]);
|
||||
// }
|
||||
//fprintf(stderr, "\n");
|
||||
|
||||
return 0;
|
||||
port_busy = true;
|
||||
if(midiOutLongMsg(midi_handle, &mheader, sizeof(mheader)) != MMSYSERR_NOERROR) {
|
||||
midiOutUnprepareHeader(midi_handle, &mheader, sizeof(mheader));
|
||||
free(tempbuf);
|
||||
fprintf(stderr, "ERROR: Failed to send SysEx message.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Wait for message to be fully sent. port_busy is reset via callback
|
||||
while(port_busy) {
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
midiOutUnprepareHeader(midi_handle, &mheader, sizeof(mheader));
|
||||
free(tempbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(len==2) {
|
||||
DWORD out = ((DWORD)buf[1])<<8 | (DWORD)buf[0];
|
||||
if(midiOutShortMsg(midi_handle, out) != MMSYSERR_NOERROR) {
|
||||
fprintf(stderr, "Error sending MIDI message: %02X %02X\n", buf[0], buf[1]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(len==3) {
|
||||
DWORD out = ((DWORD)buf[2])<<16 | ((DWORD)buf[1])<<8 | (DWORD)buf[0];
|
||||
if(midiOutShortMsg(midi_handle, out) != MMSYSERR_NOERROR) {
|
||||
fprintf(stderr, "Error sending MIDI message: %02X %02X %02X\n", buf[0], buf[1], buf[2]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "ERROR: Invalid MIDI message.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mididev_print_usage(void) {}
|
||||
void mididev_print_usage(void) {
|
||||
printf("-p PORT : Set MIDI output port number (*MANDATORY*).\n");
|
||||
printf("-l : List available MIDI output ports and exit.\n");
|
||||
}
|
||||
|
||||
void mididev_add_optstr(char *optstr) {}
|
||||
void mididev_add_optstr(char *optstr) {
|
||||
int main_len = strlen(optstr);
|
||||
strcpy(optstr+main_len, dev_optstr);
|
||||
}
|
||||
|
||||
int mididev_parse_arg(int c, const char *optarg) {
|
||||
return 0;
|
||||
if(c=='l') {
|
||||
list_midi_outputs();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if(c=='p') {
|
||||
output_port = (int) strtoul(optarg, NULL, 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "ERROR: Unknown option \'%c\'.\n", c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void list_midi_outputs(void) {
|
||||
UINT n_outs = 0;
|
||||
MIDIOUTCAPS c;
|
||||
|
||||
n_outs = midiOutGetNumDevs();
|
||||
if (!n_outs) {
|
||||
fprintf(stderr, "ERROR: No MIDI output ports found.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("MIDI output ports:\n");
|
||||
for(UINT i=0; i < n_outs; i++) {
|
||||
midiOutGetDevCaps(i, &c, sizeof(MIDIOUTCAPS));
|
||||
fprintf(stderr, "%d: %s\n", i, c.szPname);
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK midi_out_cb( HMIDIOUT mh, UINT wMsg,
|
||||
DWORD_PTR dwInst, DWORD_PTR dwp1, DWORD_PTR dwp2 ) {
|
||||
if(wMsg == MOM_DONE) {
|
||||
port_busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user