falco/midiwire/midiwire.c

294 lines
7.5 KiB
C

#ifdef _WIN32
#include <windows.h>
#include <winuser.h>
#include <stdio.h>
#endif
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#if LUA_VERSION_NUM >= 502
# define new_lib(L, l) (luaL_newlib(L, l))
#else
# define new_lib(L, l) (lua_newtable(L), luaL_register(L, NULL, l))
#endif
#include "midiwire.h"
#include "mmsystem.h"
static int midiwire_sleep (lua_State *L) {
int ms = luaL_checkinteger(L, 1);
sleep(ms);
return 0;
}
/* DEVICES */
static int midiwire_device_count (lua_State *L) {
int devices_count = midiOutGetNumDevs();
lua_pushinteger(L, devices_count);
return 1;
}
static int midiwire_name (lua_State *L) {
MIDIOUTCAPSA moc;
int port = luaL_checkinteger(L, 1);
if (!midiOutGetDevCapsA(port, &moc, sizeof(MIDIOUTCAPSA))) {
lua_pushstring(L, moc.szPname);
} else {
lua_pushnil(L);
}
return 1;
}
/* OUTPUT */
static int midiwire_open_out (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
int port = luaL_checkinteger(L, 1);
result = midiOutOpen(&outHandle, port, 0, 0, CALLBACK_NULL);
if (result != 0)
{
luaL_error(L, "There was an error opening MIDI output!");
return 0;
}
lua_pushlightuserdata (L, outHandle);
return 1;
}
static int midiwire_close_out (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
outHandle = lua_touserdata (L, 1);
midiOutClose(outHandle);
return 0;
}
static int midiwire_reset (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
outHandle = lua_touserdata (L, 1);
midiOutReset(outHandle);
return 0;
}
static int midiwire_drum (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
int drum = luaL_checkinteger(L, 2);
outHandle = lua_touserdata (L, 1);
union { unsigned long word; unsigned char data[4]; } message;
// message.data[0] = command byte of the MIDI message, for example: 0x90
// message.data[1] = first data byte of the MIDI message, for example: 60
// message.data[2] = second data byte of the MIDI message, for example 100
// message.data[3] = not used for any MIDI messages, so set to 0
message.data[0] = 0x99; // MIDI note-on message (requires to data bytes)
message.data[1] = drum; // MIDI note-on message: Key number (60 = middle C)
message.data[2] = 127; // MIDI note-on message: Key velocity (100 = loud)
message.data[3] = 0; // Unused parameter
midiOutShortMsg(outHandle, message.word);
return 0;
}
static int midiwire_note_on (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
int note = luaL_checkinteger(L, 2);
int velocity = luaL_checkinteger(L, 3);
int channel = 0;
if (lua_gettop (L)==4) {
channel = luaL_checkinteger(L, 4) - 1;
}
outHandle = lua_touserdata (L, 1);
union { unsigned long word; unsigned char data[4]; } message;
// message.data[0] = command byte of the MIDI message, for example: 0x90
// message.data[1] = first data byte of the MIDI message, for example: 60
// message.data[2] = second data byte of the MIDI message, for example 100
// message.data[3] = not used for any MIDI messages, so set to 0
message.data[0] = 0x90 + channel; // MIDI note-on message (requires to data bytes)
message.data[1] = note; // MIDI note-on message: Key number (60 = middle C)
message.data[2] = velocity; // MIDI note-on message: Key velocity (100 = loud)
message.data[3] = 0; // Unused parameter
midiOutShortMsg(outHandle, message.word);
return 0;
}
static int midiwire_note_off (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
int note = luaL_checkinteger(L, 2);
int channel = 0;
if (lua_gettop (L)==3) {
channel = luaL_checkinteger(L, 3) - 1;
}
outHandle = lua_touserdata (L, 1);
union { unsigned long word; unsigned char data[4]; } message;
message.data[0] = 0x80 + channel; // MIDI note-on message (requires to data bytes)
message.data[1] = note; // MIDI note-on message: Key number (60 = middle C)
message.data[2] = 0; // MIDI note-on message: Key velocity (100 = loud)
message.data[3] = 0; // Unused parameter
midiOutShortMsg(outHandle, message.word);
return 0;
}
static int midiwire_program_change (lua_State *L) {
unsigned long result;
HMIDIOUT outHandle;
luaL_checktype(L, 1, LUA_TLIGHTUSERDATA);
int program = luaL_checkinteger(L, 2) - 1;
int channel = 0;
if (lua_gettop (L)==3) {
channel = luaL_checkinteger(L, 3) - 1;
}
outHandle = lua_touserdata (L, 1);
union { unsigned long word; unsigned char data[4]; } message;
message.data[0] = 0xC0 + channel; // MIDI note-on message (requires to data bytes)
message.data[1] = program; // MIDI note-on message: Key number (60 = middle C)
message.data[2] = 0; // MIDI note-on message: Key velocity (100 = loud)
message.data[3] = 0; // Unused parameter
midiOutShortMsg(outHandle, message.word);
return 0;
}
/* INPUT */
void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
switch(wMsg) {
case MIM_OPEN:
printf("wMsg=MIM_OPEN\n");
break;
case MIM_CLOSE:
printf("wMsg=MIM_CLOSE\n");
break;
case MIM_DATA:
printf("wMsg=MIM_DATA, dwInstance=%08x, dwParam1=%08x, dwParam2=%08x\n", dwInstance, dwParam1, dwParam2);
break;
case MIM_LONGDATA:
printf("wMsg=MIM_LONGDATA\n");
break;
case MIM_ERROR:
printf("wMsg=MIM_ERROR\n");
break;
case MIM_LONGERROR:
printf("wMsg=MIM_LONGERROR\n");
break;
case MIM_MOREDATA:
printf("wMsg=MIM_MOREDATA\n");
break;
default:
printf("wMsg = unknown\n");
break;
}
return;
}
void PrintMidiInDevices()
{
UINT nMidiDeviceNum;
MIDIINCAPS caps;
nMidiDeviceNum = midiInGetNumDevs();
if (nMidiDeviceNum == 0) {
fprintf(stderr, "midiInGetNumDevs() return 0...");
return;
}
printf("== PrintMidiDevices() == \n");
unsigned int i;
for (i = 0; i < nMidiDeviceNum; ++i) {
midiInGetDevCaps(i, &caps, sizeof(MIDIINCAPS));
printf("\t%d : name = %s\n", i, caps.szPname);
}
printf("=====\n");
}
// https://gist.github.com/yoggy/1485181
// TODO - inputy jsou jinak číslované
// po otevření musím zavolat midiInStart
// pro uzavření midiInStop & midiInClose
static int midiwire_open_in (lua_State *L) {
PrintMidiInDevices();
unsigned long result;
HMIDIIN inHandle;
int port = luaL_checkinteger(L, 1);
result = midiInOpen(&inHandle, port, (DWORD)(void*)MidiInProc, 0, CALLBACK_FUNCTION);
if (result != MMSYSERR_NOERROR)
{
lua_pushnil (L);
lua_pushinteger (L, result);
return 2;
}
midiInStart(inHandle);
if (result != MMSYSERR_NOERROR)
{
lua_pushnil (L);
lua_pushinteger (L, result);
return 2;
}
lua_pushlightuserdata (L, inHandle);
return 1;
}
/* FUNCS */
static const struct luaL_Reg midiwire[] = {
{"sleep", midiwire_sleep},
{"device_count", midiwire_device_count},
{"name", midiwire_name},
{"open_out", midiwire_open_out},
{"close_out", midiwire_close_out},
{"note_on", midiwire_note_on},
{"note_off", midiwire_note_off},
{"drum", midiwire_drum},
{"program_change", midiwire_program_change},
{"reset", midiwire_reset},
{"open_in", midiwire_open_in},
{NULL, NULL},
};
MIDIWIRE_EXPORT int luaopen_midiwire (lua_State *L) {
new_lib (L, midiwire);
lua_pushvalue(L, -1);
lua_setglobal(L, "midiwire");
return 1;
}