add OSC Lua bindings
authorRobin Gareus <robin@gareus.org>
Sat, 19 Mar 2016 11:47:37 +0000 (12:47 +0100)
committerRobin Gareus <robin@gareus.org>
Sat, 19 Mar 2016 11:47:37 +0000 (12:47 +0100)
libs/ardour/ardour/lua_api.h
libs/ardour/ardour/luabindings.h
libs/ardour/lua_api.cc
libs/ardour/luabindings.cc
libs/ardour/wscript

index c69469f184f735724a15bcc160c9b6494af8c536..3aab2f937da05047e9d7dcfde9d1b01ec77ac69a 100644 (file)
@@ -20,6 +20,7 @@
 #define _ardour_lua_api_h_
 
 #include <string>
+#include <lo/lo.h>
 #include <boost/shared_ptr.hpp>
 
 #include "ardour/libardour_visibility.h"
@@ -31,6 +32,20 @@ namespace ARDOUR { namespace LuaAPI {
 
        boost::shared_ptr<ARDOUR::Processor> 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_
index 65f4c23bf71e4c8af6c1c338a8cdabfcf8072046..4650858dff23a6402fb202809a6ea21acbe8900c 100644 (file)
@@ -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);
 
index 99a9b1b49337e9bc0da9761eee6dec8b0d6ae953..78b95bec0ae9593d5119f73166cc3777e2fbc1a0 100644 (file)
@@ -65,3 +65,79 @@ ARDOUR::LuaAPI::new_luaproc (Session *s, const string& name)
 
        return boost::shared_ptr<Processor> (new PluginInsert (*s, p));
 }
+
+int
+ARDOUR::LuaAPI::LuaOSCAddress::send (lua_State *L)
+{
+       LuaOSCAddress * const luaosc = luabridge::Userdata::get <LuaOSCAddress> (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<int>::push (L, rv);
+       return 1;
+}
index ef7d450debd0f397bd05c9b3c1880d05482c5f85..4f11c66980a0f95983fd4d58f657c05c6ada8779 100644 (file)
@@ -637,6 +637,18 @@ LuaBindings::session (lua_State* L)
                .endNamespace (); // ARDOUR
 }
 
+void
+LuaBindings::osc (lua_State* L)
+{
+       luabridge::getGlobalNamespace (L)
+               .beginNamespace ("OSC")
+               .beginClass<LuaAPI::LuaOSCAddress> ("Address")
+               .addConstructor<void (*) (std::string)> ()
+               .addCFunction ("send", &LuaAPI::LuaOSCAddress::send)
+               .endClass ()
+               .endNamespace ();
+}
+
 void
 LuaBindings::set_session (lua_State* L, Session *s)
 {
index 5b7abaa9c848359d30f61e203746b53561a576b4..070f24ef46db7de7d92dcd6bc8e289d8f85fa3d8 100644 (file)
@@ -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',