294 lines
7.5 KiB
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;
|
|
}
|