From 5b347e92587513bfb7d6321e6bd67195db9c0ad5 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sat, 19 Mar 2016 12:47:37 +0100 Subject: [PATCH] add OSC Lua bindings --- libs/ardour/ardour/lua_api.h | 15 +++++++ libs/ardour/ardour/luabindings.h | 1 + libs/ardour/lua_api.cc | 76 ++++++++++++++++++++++++++++++++ libs/ardour/luabindings.cc | 12 +++++ libs/ardour/wscript | 2 +- 5 files changed, 105 insertions(+), 1 deletion(-) diff --git a/libs/ardour/ardour/lua_api.h b/libs/ardour/ardour/lua_api.h index c69469f184..3aab2f937d 100644 --- a/libs/ardour/ardour/lua_api.h +++ b/libs/ardour/ardour/lua_api.h @@ -20,6 +20,7 @@ #define _ardour_lua_api_h_ #include +#include #include #include "ardour/libardour_visibility.h" @@ -31,6 +32,20 @@ namespace ARDOUR { namespace LuaAPI { boost::shared_ptr new_luaproc (ARDOUR::Session *s, const std::string&); + /** + * OSC is kinda special, lo_address is a void* and lo_send() has varags + * and typed arguments which makes it hard to bind, even lo_cpp. + */ + class LuaOSCAddress { + public: + LuaOSCAddress (std::string uri) { + _addr = lo_address_new_from_url (uri.c_str()); + } + ~LuaOSCAddress () { if (_addr) { lo_address_free (_addr); } } + int send (lua_State *L); + lo_address _addr; + }; + } } /* namespace */ #endif // _ardour_lua_api_h_ diff --git a/libs/ardour/ardour/luabindings.h b/libs/ardour/ardour/luabindings.h index 65f4c23bf7..4650858dff 100644 --- a/libs/ardour/ardour/luabindings.h +++ b/libs/ardour/ardour/luabindings.h @@ -30,6 +30,7 @@ namespace ARDOUR { LIBARDOUR_API extern void common (lua_State* L); LIBARDOUR_API extern void dsp (lua_State* L); LIBARDOUR_API extern void session (lua_State* L); + LIBARDOUR_API extern void osc (lua_State* L); LIBARDOUR_API extern void set_session (lua_State* L, Session *s); diff --git a/libs/ardour/lua_api.cc b/libs/ardour/lua_api.cc index 99a9b1b493..78b95bec0a 100644 --- a/libs/ardour/lua_api.cc +++ b/libs/ardour/lua_api.cc @@ -65,3 +65,79 @@ ARDOUR::LuaAPI::new_luaproc (Session *s, const string& name) return boost::shared_ptr (new PluginInsert (*s, p)); } + +int +ARDOUR::LuaAPI::LuaOSCAddress::send (lua_State *L) +{ + LuaOSCAddress * const luaosc = luabridge::Userdata::get (L, 1, false); + if (!luaosc) { + return luaL_error (L, "Invalid pointer to OSC.Address"); + } + if (!luaosc->_addr) { + return luaL_error (L, "Invalid Destination Address"); + } + + int top = lua_gettop(L); + if (top < 3) { + return luaL_argerror (L, 1, "invalid number of arguments, :send (path, type, ...)"); + } + + const char* path = luaL_checkstring (L, 2); + const char* type = luaL_checkstring (L, 3); + assert (path && type); + + if ((int) strlen(type) != top - 3) { + return luaL_argerror (L, 3, "type description does not match arguments"); + } + + lo_message msg = lo_message_new (); + + for (int i = 4; i <= top; ++i) { + char t = type[i - 4]; + int lt = lua_type(L, i); + int ok = -1; + switch(lt) { + case LUA_TSTRING: + if (t == LO_STRING) { + ok = lo_message_add_string (msg, luaL_checkstring(L, i)); + } else if (t == LO_CHAR) { + char c = luaL_checkstring (L, i) [0]; + ok = lo_message_add_char (msg, c); + } + break; + case LUA_TBOOLEAN: + if (t == LO_TRUE || t == LO_FALSE) { + if (lua_toboolean (L, i)) { + ok = lo_message_add_true (msg); + } else { + ok = lo_message_add_false (msg); + } + } + break; + case LUA_TNUMBER: + if (t == LO_INT32) { + ok = lo_message_add_int32 (msg, (int32_t) luaL_checkinteger(L, i)); + } + else if (t == LO_FLOAT) { + ok = lo_message_add_float (msg, (float) luaL_checknumber(L, i)); + } + else if (t == LO_DOUBLE) { + ok = lo_message_add_double (msg, (double) luaL_checknumber(L, i)); + } + else if (t == LO_INT64) { + ok = lo_message_add_double (msg, (int64_t) luaL_checknumber(L, i)); + } + break; + default: + break; + } + if (ok != 0) { + return luaL_argerror (L, i, "type description does not match parameter"); + } + } + + int rv = lo_send_message (luaosc->_addr, path, msg); + lo_message_free (msg); + luabridge::Stack::push (L, rv); + return 1; +} diff --git a/libs/ardour/luabindings.cc b/libs/ardour/luabindings.cc index ef7d450deb..4f11c66980 100644 --- a/libs/ardour/luabindings.cc +++ b/libs/ardour/luabindings.cc @@ -637,6 +637,18 @@ LuaBindings::session (lua_State* L) .endNamespace (); // ARDOUR } +void +LuaBindings::osc (lua_State* L) +{ + luabridge::getGlobalNamespace (L) + .beginNamespace ("OSC") + .beginClass ("Address") + .addConstructor () + .addCFunction ("send", &LuaAPI::LuaOSCAddress::send) + .endClass () + .endNamespace (); +} + void LuaBindings::set_session (lua_State* L, Session *s) { diff --git a/libs/ardour/wscript b/libs/ardour/wscript index 5b7abaa9c8..070f24ef46 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -367,7 +367,7 @@ def build(bld): obj.includes = ['.', '../surfaces/control_protocol', '..'] obj.name = 'libardour' obj.target = 'ardour' - obj.uselib = ['GLIBMM','GTHREAD','AUBIO','SIGCPP','XML','UUID', + obj.uselib = ['GLIBMM','GTHREAD','AUBIO','SIGCPP','XML','UUID', 'LO', 'SNDFILE','SAMPLERATE','LRDF','AUDIOUNITS', 'GIOMM', 'OSX','BOOST','CURL','TAGLIB','VAMPSDK','VAMPHOSTSDK','RUBBERBAND'] obj.use = ['libpbd','libmidipp','libevoral', -- 2.30.2