Created
June 30, 2017 13:27
-
-
Save mmalex/c5b61f824d55cf6dff8a53b451af3392 to your computer and use it in GitHub Desktop.
Revisions
-
Alex Evans created this gist
Jun 30, 2017 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,120 @@ /* quick midi 2 osc hack by @mmalex, use at your own risk etc reads midi messages, forward them to osc messages on your network. barely tested but works for me in windows 7, compiled with msvc 2015 sp2 stick a midi2osc.ini file in the same folder as the exe to configure it, with lines like these: IP=43.193.207.78 Port=9000 Log=1 Device=0 Device sets the midi device number (as enumerated by windows, sorry). Log dumps midi messages to console window IP and Port say where to send the osc messages, which are all just addressed to /midi with a single integer parameter with the 3 byte standard midi message packed into it. */ #define _WINSOCK_DEPRECATED_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #include <winsock2.h> // for sockets #include <conio.h>// for _getch #include <stdio.h> // for printf #include <ws2tcpip.h> // for getaddrinfo #pragma comment(lib,"winmm.lib") // for midi #pragma comment(lib,"ws2_32.lib") // for sockets const char *GetIniSetting(const char *key, const char *default_value); // simple ini file parser (see the end of this file) int log=0; SOCKET fd; struct addrinfo* addr=0; void CALLBACK midicb( HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { if (wMsg==MIM_DATA) { char oscmsg[16]="/midi\0\0\0,i\0\0\0\0\0"; oscmsg[15]=(unsigned char)dwParam1; oscmsg[14]=(unsigned char)(dwParam1>>8); oscmsg[13]=(unsigned char)(dwParam1>>16); if (log) printf("%02x %02x %02x\r",oscmsg[15],oscmsg[14],oscmsg[13]); if (sendto(fd,oscmsg,16,0,addr->ai_addr,addr->ai_addrlen)<0) printf("failed to send udp packet!\n"); } } int main(int argc, char **argv) { WSADATA wsadata={}; WSAStartup(MAKEWORD(2,2),&wsadata); const char *ip=GetIniSetting("IP","127.0.0.1"); const char *port=GetIniSetting("Port","9000"); UINT devid=atoi(GetIniSetting("Device","0")); log=atoi(GetIniSetting("Log","0")); printf("midi2osc - sending to %s:%s, logging=%d, device=%d\npress escape to quit\n",ip,port,log,devid); struct addrinfo hints={}; hints.ai_family=AF_UNSPEC; hints.ai_socktype=SOCK_DGRAM; hints.ai_protocol=0; hints.ai_flags=AI_ADDRCONFIG; if (getaddrinfo(ip,port,&hints,&addr)!=0) return printf("failed to resolve remote socket address"); fd=socket(addr->ai_family, addr->ai_socktype,addr->ai_protocol); if (fd<0) return printf("failed to open socket %s\n",strerror(errno)); UINT numdevs=midiInGetNumDevs(); for (UINT d=0;d<numdevs;++d) { MIDIINCAPS caps; if (midiInGetDevCaps(d,&caps, sizeof(caps))==MMSYSERR_NOERROR) { printf("%c%d: %s\n",d==devid?'*':' ',d,caps.szPname); } } HMIDIIN hmidi={}; if (midiInOpen(&hmidi, devid, (DWORD_PTR)midicb, 0, CALLBACK_FUNCTION)!=MMSYSERR_NOERROR) return printf("failed to midiInOpen\n"); if (midiInStart(hmidi)!=MMSYSERR_NOERROR) return printf("failed to midiInStart\n"); while (_getch()!=27) ; midiInStop(hmidi); midiInClose(hmidi); return 0; } ////////////////////////////// simple ini parser char *settings=0; void LoadIniSettings() { settings=""; FILE *f=fopen("midi2osc.ini","rb"); if (!f) return ; fseek(f,0,SEEK_END); int l=ftell(f); char *dst=settings=(char*)calloc(1,l+4); fseek(f,0,SEEK_SET); while (!feof(f)) { char *odst=dst; char linebuf[256]={}; if (!fgets(linebuf,255,f)) break; const char *src=linebuf; while (*src && isspace(*src)) ++src; // skip white space if (*src=='#') continue; // comment const char *ks=dst; while (*src && !isspace(*src) && *src!='=') *dst++=*src++; // copy key if (dst==ks) {dst=odst; continue; } // empty key *dst++=0; // null terminate key while (*src && isspace(*src)) ++src; // skip white space after key if (*src++!='=') {dst=odst; continue; } // no equals sign while (*src && isspace(*src)) ++src; // skip white space after = const char *vs=dst; while (*src && *src!='\r' && *src!='\n' && *src!='#') *dst++=*src++; // copy value to end of line while (dst>vs && isspace(dst[-1])) --dst; // trim trailing spaces *dst++=0; // null terminate value } fclose(f); *dst++=0; *dst++=0; // empty string to terminate settings } const char *GetIniSetting(const char *key, const char *default_value) { if (!settings) LoadIniSettings(); for (const char *s=settings;*s;) { const char *val=s+strlen(s)+1; if (strcmp(s,key)==0) return val; s=val+strlen(val)+1; } return default_value; }