


#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

#define SUNVOX_MAIN
#include "sunvox.h"
#include "sunvoxlua.h"

static int lsv_sleep (lua_State *L) {
	int ms = luaL_checkinteger(L, 1);
	sleep(ms);
	return 0;
}

static int lsv_open_slot (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int result = sv_open_slot(slot);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_close_slot (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int result = sv_close_slot(slot);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_load (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	const char * fname = luaL_checkstring(L, 2);
	int result = sv_load(slot, fname);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_play (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int result = sv_play(slot);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_stop (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int result = sv_stop(slot);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_end_of_song (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int result = sv_end_of_song(slot);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_set_autostop (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int stop = lua_toboolean(L, 2);
	int result = sv_set_autostop(slot, stop);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_rewind (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int line = luaL_checkinteger(L, 2);
	int result = sv_rewind(slot, line);
	lua_pushboolean(L, result == 0);
	return 1;
}

static int lsv_volume (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int vol = luaL_checkinteger(L, 2);
	int result = sv_volume(slot, vol);
	lua_pushboolean(L, result == 0);
	return 1;
}

// Tradá:

/*
   sv_send_event() - send some event (note ON, note OFF, controller change, etc.)
   Parameters:
     slot;
     track_num - track number within the pattern;
     note: 0 - nothing; 1..127 - note num; 128 - note off; 129, 130... - see NOTECMD_xxx defines;
     vel: velocity 1..129; 0 - default;
     module: 0 - nothing; 1..255 - module number + 1;
     ctl: 0xCCEE. CC - number of a controller (1..255). EE - effect;
     ctl_val: value of controller or effect.
*/
static int lsv_send_event (lua_State *L) {
	int slot = luaL_checkinteger(L, 1);
	int track_num = luaL_checkinteger(L, 2);
	int note = luaL_checkinteger(L, 3);
	int velocity = luaL_checkinteger(L, 4);
	int modul = luaL_checkinteger(L, 5);
	int ctl = luaL_checkinteger(L, 6);
	int ctl_val = luaL_checkinteger(L, 6);
	int result = sv_send_event(slot, track_num, note, velocity, modul, ctl, ctl_val);
	lua_pushboolean(L, result == 0);
	return 1;
}


/*
** Assumes the table is on top of the stack.
*/
static void set_info (lua_State *L, int ver) {
	int major = ( ver >> 16 ) & 255;
	int minor1 = ( ver >> 8 ) & 255;
	int minor2 = ( ver ) & 255;
	char version[50];
	
	lua_pushliteral(L, "Copyright (c) 2008 - 2018, Alexander Zolotov <nightradio@gmail.com>, WarmPlace.ru");
	lua_setfield(L, -2, "_COPYRIGHT");
	lua_pushliteral(L, "SunVox modular synthesizer");
	lua_setfield(L, -2, "_DESCRIPTION");
	sprintf(version, "%d.%d.%d", major, minor1, minor2);
	lua_pushstring(L, version);
	lua_setfield(L, -2, "_VERSION");
}

static const struct luaL_Reg sunvoxlua[] = {
	{"sleep", lsv_sleep},
	{"open_slot", lsv_open_slot},
	{"close_slot", lsv_close_slot},
	{"load", lsv_load},
	{"play", lsv_play},
	{"stop", lsv_stop},
	{"rewind", lsv_rewind},
	{"end_of_song", lsv_end_of_song},
	{"set_autostop", lsv_set_autostop},
	{"volume", lsv_volume},
	{"send_event", lsv_send_event},
	{NULL, NULL},
};

SUNVOXLUA_EXPORT int luaopen_sunvoxlua (lua_State *L) {
	if (sv_load_dll() ) {
		luaL_error(L, "Cannot find sunvox.dll");
		return 0;
	}
	int ver = sv_init( 0, 44100, 2, 0 );
	if (ver==0) {
		luaL_error(L, "Error opening sound device.");
		return 0;
	}
	atexit(sv_deinit);
	new_lib (L, sunvoxlua);
	lua_pushvalue(L, -1);
	lua_setglobal(L, "sunvox");
	set_info (L, ver);
	return 1;
}
