summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2016-01-30 17:26:14 +0100
committerRobin Gareus <robin@gareus.org>2016-02-23 15:43:03 +0100
commit942471d21f0acbb833849873bba2eb8254c4d28d (patch)
tree3dc3bd3d2ccdab10dd272bc48b3293c7ca89378c
parent44ce56a9e172b9b6e979a9951fe4c29f594731cf (diff)
add lua-session commandline tool
-rwxr-xr-xgtk2_ardour/arlua21
-rw-r--r--tools/luadevel/ardour-lua.sh.in9
-rw-r--r--tools/luadevel/devel.cc296
-rw-r--r--tools/luadevel/luasession.cc345
-rwxr-xr-xtools/luadevel/wscript92
-rw-r--r--wscript1
6 files changed, 764 insertions, 0 deletions
diff --git a/gtk2_ardour/arlua b/gtk2_ardour/arlua
new file mode 100755
index 0000000000..d8cec780ec
--- /dev/null
+++ b/gtk2_ardour/arlua
@@ -0,0 +1,21 @@
+#!/bin/sh
+TOP=`dirname "$0"`/..
+. $TOP/build/gtk2_ardour/ardev_common_waf.sh
+export UBUNTU_MENUPROXY=""
+
+if [ $# -gt 0 ] ; then
+ case $1 in
+ -g|--gdb) GDB=gdb; shift ;;
+ esac
+fi
+
+if test -z "$GDB"; then
+ exec $TOP/build/tools/luadevel/luasession "$@"
+fi
+
+if test -n "`which gdb`"; then
+ exec gdb --args $TOP/build/tools/luadevel/luasession "$@"
+fi
+if test -n "`which lldb`"; then
+ exec lldb -- $TOP/build/tools/luadevel/luasession "$@"
+fi
diff --git a/tools/luadevel/ardour-lua.sh.in b/tools/luadevel/ardour-lua.sh.in
new file mode 100644
index 0000000000..50d6e6e0c2
--- /dev/null
+++ b/tools/luadevel/ardour-lua.sh.in
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+export LD_LIBRARY_PATH=@LIBDIR@${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
+export ARDOUR_DATA_PATH=@DATADIR@
+export ARDOUR_CONFIG_PATH=@CONFDIR@
+export ARDOUR_DLL_PATH=@LIBDIR@
+export VAMP_PATH=@LIBDIR@/vamp
+
+exec @LIBDIR@/luasession "$@"
diff --git a/tools/luadevel/devel.cc b/tools/luadevel/devel.cc
new file mode 100644
index 0000000000..3caa0513f3
--- /dev/null
+++ b/tools/luadevel/devel.cc
@@ -0,0 +1,296 @@
+#include <stdint.h>
+#include <cstdio>
+#include <iostream>
+#include <string>
+#include <list>
+#include <vector>
+
+#define LIBPBD_API
+#include "../../libs/pbd/pbd/reallocpool.h"
+#include "../../libs/pbd/reallocpool.cc"
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "lua/luastate.h"
+#include "LuaBridge/LuaBridge.h"
+
+static void my_lua_print (std::string s) {
+ std::cout << s << "\n";
+}
+
+
+class A {
+ public:
+ A() { printf ("CTOR\n"); _int = 4; for (int i = 0; i < 256; ++i) {arr[i] = i; ar2[i] = i/256.0; ar3[i] = i;} }
+ ~A() { printf ("DTOR\n"); }
+
+ void set_int (int a) { _int = a; }
+ int get_int () const { return _int; }
+
+ int& get_ref () { return _int; }
+ int get_arg (int &a) { printf ("a = %d\n", a); a = _int; printf ("a = %d\n", a); return 1; }
+ void get_arg2 (int &a, int& b) { a = _int; b = 100; }
+ void get_args (std::string &a) { a = "hello"; }
+ void set_ref (int const &a) { _int = a; }
+
+ float * get_arr () { return arr; }
+ float * get_ar2 () { return ar2; }
+ int * get_ar3 () { return ar3; }
+
+ void set_list (std::list<std::string> sl) { _sl = sl; }
+ std::list<std::string>& get_list () { return _sl; }
+
+ uint32_t minone() { return -1; }
+
+ enum EN {
+ RV1 = 1, RV2, RV3
+ };
+
+ enum EN ret_enum () { return _en;}
+ void set_enum (enum EN en) { _en = en; }
+
+ private:
+ std::list<std::string> _sl;
+ int _int;
+ enum EN _en;
+ float arr[256];
+ float ar2[256];
+ int ar3[256];
+};
+
+int main (int argc, char **argv)
+{
+#if 0
+ LuaState lua;
+#else
+ PBD::ReallocPool _mempool ("Devel", 1048576);
+ LuaState lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool));
+#endif
+ lua.Print.connect (&my_lua_print);
+ lua_State* L = lua.getState();
+
+
+#if 1
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("Test")
+ .beginStdList <std::string> ("StringList")
+ .endClass ()
+ .endNamespace ();
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("Test")
+ .beginStdVector <std::string> ("StringVector")
+ .endClass ()
+ .endNamespace ();
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("Test")
+ .beginStdMap <std::string,std::string> ("StringStringMap")
+ .endClass ()
+ .endNamespace ();
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("Test")
+ .beginStdSet <std::string> ("StringSet")
+ .endClass ()
+ .endNamespace ();
+
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("Test")
+ .registerArray <float> ("FloatArray")
+ .registerArray <int> ("IntArray")
+ .beginClass <A> ("A")
+ .addConstructor <void (*) ()> ()
+ .addFunction ("set_int", &A::set_int)
+ .addFunction ("get_int", &A::get_int)
+ .addRefFunction ("get_arg", &A::get_arg)
+ .addRefFunction ("get_arg2", &A::get_arg2)
+ .addRefFunction ("get_args", &A::get_args)
+ .addFunction ("set_ref", &A::set_ref)
+ .addFunction ("get_list", &A::get_list)
+ .addFunction ("set_list", &A::set_list)
+ .addFunction ("ret_enum", &A::ret_enum)
+ .addFunction ("set_enum", &A::set_enum)
+ .addFunction ("get_arr", &A::get_arr)
+ .addFunction ("get_ar2", &A::get_ar2)
+ .addFunction ("get_ar3", &A::get_ar3)
+ .endClass ()
+ .endNamespace ();
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("Test")
+ .beginClass <A> ("A")
+ .addFunction ("minone", &A::minone)
+ .addConst ("cologne", 4711)
+ .endClass ()
+ .addConst ("koln", 4711)
+ .endNamespace ();
+#endif
+#if 0 // session script test
+ lua.do_command (
+ "function ArdourSession ()"
+ " local self = { scripts = {}, instances = {} }"
+ ""
+ " local foreach = function (fn)"
+ " for n, s in pairs (self.scripts) do"
+ " fn (n, s)"
+ " end"
+ " end"
+ ""
+ " local run = function ()"
+ " for n, s in pairs (self.instances) do"
+ " local status, err = pcall (s)"
+ " if not status then print ('fn \"'.. n .. '\": ', err) end"
+ " end"
+ " collectgarbage()"
+ " end"
+ ""
+ " local add = function (n, f, a)"
+ " assert(type(n) == 'string', 'function-name must be string')"
+ " assert(type(f) == 'function', 'Given script is a not a function')"
+ " assert(type(a) == 'table' or type(a) == 'nil', 'Given argument is invalid')"
+ " assert(self.scripts[n] == nil, 'Callback \"'.. n ..'\" already exists.')"
+ " self.scripts[n] = { ['f'] = f, ['a'] = a }"
+ " local env = { print = print, Session = Session, tostring = tostring, assert = assert, ipairs = ipairs, error = error, string = string, type = type, tonumber = tonumber, collectgarbage = collectgarbage, pairs = pairs, math = math, table = table, pcall = pcall }"
+ " self.instances[n] = load (string.dump(f), nil, nil, env)(a)"
+ " end"
+ ""
+ " local remove = function (n)"
+ " self.scripts[n] = nil"
+ " end"
+ ""
+ " local list = function ()"
+ " local rv = {}"
+ " foreach (function (n) rv[n] = true end)"
+ " return rv"
+ " end"
+ ""
+ " local function basic_serialize (o)"
+ " if type(o) == \"number\" then"
+ " return tostring(o)"
+ " else"
+ " return string.format(\"%q\", o)"
+ " end"
+ " end"
+ ""
+ " local function serialize (name, value)"
+ " local rv = name .. ' = '"
+ " if type(value) == \"number\" or type(value) == \"string\" or type(value) == \"nil\" then"
+ " return rv .. basic_serialize(value) .. ' '"
+ " elseif type(value) == \"table\" then"
+ " rv = rv .. '{} '"
+ " for k,v in pairs(value) do"
+ " local fieldname = string.format(\"%s[%s]\", name, basic_serialize(k))"
+ " rv = rv .. serialize(fieldname, v) .. ' '"
+ " end"
+ " return rv;"
+ " elseif type(value) == \"function\" then"
+ " return rv .. string.format(\"%q\", string.dump(value))"
+ " else"
+ " error('cannot save a ' .. type(value))"
+ " end"
+ " end"
+ ""
+ ""
+ " local save = function ()"
+ " return (serialize('scripts', self.scripts))"
+ " end"
+ ""
+ " local restore = function (state)"
+ " self.scripts = {}"
+ " load (state)()"
+ " print (scripts)"
+ " for n, s in pairs (scripts) do"
+ " add (n, load(s['f']), s['a'])"
+ " end"
+ " end"
+ ""
+ " return { run = run, add = add, remove = remove,"
+ " list = list, foreach = foreach,"
+ " restore = restore, save = save}"
+ " end"
+ " "
+ " sess = ArdourSession ()"
+ " ArdourSession = nil"
+ );
+
+ luabridge::LuaRef *lua_run;
+ luabridge::LuaRef *lua_add;
+ luabridge::LuaRef *lua_del;
+ luabridge::LuaRef *lua_save;
+ luabridge::LuaRef *lua_load;
+ {
+ luabridge::LuaRef lua_sess = luabridge::getGlobal (L, "sess");
+ lua.do_command ("sess = nil"); // hide it.
+ lua.do_command ("collectgarbage()");
+
+ lua_run = new luabridge::LuaRef(lua_sess["run"]);
+ lua_add = new luabridge::LuaRef(lua_sess["add"]);
+ lua_del = new luabridge::LuaRef(lua_sess["remove"]);
+ lua_save = new luabridge::LuaRef(lua_sess["save"]);
+ lua_load = new luabridge::LuaRef(lua_sess["restore"]);
+ }
+ lua.do_command ("collectgarbage()");
+
+#if 1
+ lua.do_command ("function factory (t) return function () local p = t or { } local a = t[1] or 'Nibor' print ('Hello ' .. a) end end");
+ luabridge::LuaRef lua_fact = luabridge::getGlobal (L, "factory");
+ luabridge::LuaRef tbl_arg (luabridge::newTable(L));
+ //tbl_arg[1] = "Robin";
+ (*lua_add)("t2", lua_fact, tbl_arg);
+#else
+ lua.do_command ("function factory (t) return function () print ('Boo') end end");
+ luabridge::LuaRef lua_fact = luabridge::getGlobal (L, "factory");
+ (*lua_add)("t2", lua_fact());
+#endif
+
+ lua.do_command ("function factory (t) return function () print ('Ahoy') end end");
+ luabridge::LuaRef lua_fact2 = luabridge::getGlobal (L, "factory");
+ (*lua_add)("t1", lua_fact2);
+
+ luabridge::LuaRef savedstate ((*lua_save)());
+ std::string saved = savedstate.cast<std::string>();
+
+ (*lua_del)("t2");
+
+ try {
+ (*lua_run)();
+ } catch (luabridge::LuaException const& e) { printf ("LuaException: %s\n", e.what ()); }
+
+ (*lua_load)(saved);
+
+ for (int i = 0; i < 2; ++i) {
+ lua.do_command ("collectgarbage()");
+ lua.collect_garbage ();
+ try {
+ (*lua_run)();
+ } catch (luabridge::LuaException const& e) { printf ("LuaException: %s\n", e.what ()); }
+ }
+
+#endif
+
+ add_history("a = Test:A() b = 2 c = 3 d = 'a'");
+ add_history("x = a:get_arg(b) y = a:get_arg2(b, c) z = a:get_args(d) ");
+ add_history("for i,n in ipairs(y) do print (i, n); end");
+
+ /////////////////////////////////////////////////////////////////////////////
+ char *line;
+ while ((line = readline ("> "))) {
+ if (!strcmp (line, "quit")) {
+ break;
+ }
+ if (strlen(line) == 0) {
+ //lua.do_command("collectgarbage();");
+ continue;
+ }
+ if (!lua.do_command (line)) {
+ add_history(line); // OK
+ } else {
+ add_history(line); // :)
+ }
+ }
+ printf("\n");
+ return 0;
+}
diff --git a/tools/luadevel/luasession.cc b/tools/luadevel/luasession.cc
new file mode 100644
index 0000000000..5ddea9015e
--- /dev/null
+++ b/tools/luadevel/luasession.cc
@@ -0,0 +1,345 @@
+#include <stdint.h>
+#include <assert.h>
+
+#include <cstdio>
+#include <iostream>
+#include <string>
+#include <list>
+#include <vector>
+
+#include <glibmm.h>
+
+#include "pbd/debug.h"
+#include "pbd/event_loop.h"
+#include "pbd/error.h"
+#include "pbd/failed_constructor.h"
+#include "pbd/pthread_utils.h"
+#include "pbd/reallocpool.h"
+#include "pbd/receiver.h"
+#include "pbd/transmitter.h"
+
+#include "ardour/ardour.h"
+#include "ardour/audioengine.h"
+#include "ardour/filename_extensions.h"
+#include "ardour/filesystem_paths.h"
+#include "ardour/luabindings.h"
+#include "ardour/session.h"
+#include "ardour/types.h"
+#include "ardour/vst_types.h"
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "lua/luastate.h"
+#include "LuaBridge/LuaBridge.h"
+
+using namespace std;
+using namespace ARDOUR;
+using namespace PBD;
+
+static const char* localedir = LOCALEDIR;
+static PBD::ScopedConnectionList engine_connections;
+static PBD::ScopedConnectionList session_connections;
+static Session *_session = NULL;
+static LuaState *lua;
+
+class LuaReceiver : public Receiver
+{
+ protected:
+ void receive (Transmitter::Channel chn, const char * str)
+ {
+ const char *prefix = "";
+
+ switch (chn) {
+ case Transmitter::Error:
+ prefix = "[ERROR]: ";
+ break;
+ case Transmitter::Info:
+ /* ignore */
+ return;
+ case Transmitter::Warning:
+ prefix = "[WARNING]: ";
+ break;
+ case Transmitter::Fatal:
+ prefix = "[FATAL]: ";
+ break;
+ case Transmitter::Throw:
+ /* this isn't supposed to happen */
+ abort ();
+ }
+
+ /* note: iostreams are already thread-safe: no external
+ lock required.
+ */
+
+ std::cout << prefix << str << std::endl;
+
+ if (chn == Transmitter::Fatal) {
+ ::exit (9);
+ }
+ }
+};
+
+class MyEventLoop : public sigc::trackable, public EventLoop
+{
+ public:
+ MyEventLoop (std::string const& name) : EventLoop (name) {
+ run_loop_thread = Glib::Threads::Thread::self ();
+ }
+
+ void call_slot (InvalidationRecord* ir, const boost::function<void()>& f) {
+ if (Glib::Threads::Thread::self () == run_loop_thread) {
+ //cout << string_compose ("%1/%2 direct dispatch of call slot via functor @ %3, invalidation %4\n", event_loop_name(), pthread_name(), &f, ir);
+ f ();
+ } else {
+ //cout << string_compose ("%1/%2 queue call-slot using functor @ %3, invalidation %4\n", event_loop_name(), pthread_name(), &f, ir);
+ assert (!ir);
+ f (); // XXX TODO, queue and process during run ()
+ }
+ }
+
+ void run () {
+ ; // TODO process Events, if any
+ }
+
+ Glib::Threads::Mutex& slot_invalidation_mutex () { return request_buffer_map_lock; }
+
+ private:
+ Glib::Threads::Thread* run_loop_thread;
+ Glib::Threads::Mutex request_buffer_map_lock;
+};
+
+static int do_audio_midi_setup (uint32_t desired_sample_rate)
+{
+ return AudioEngine::instance ()->start ();
+}
+
+static MyEventLoop *event_loop = NULL;
+
+static void init ()
+{
+ if (!ARDOUR::init (false, true, localedir)) {
+ cerr << "Ardour failed to initialize\n" << endl;
+ ::exit (EXIT_FAILURE);
+ }
+
+ assert (!event_loop);
+ event_loop = new MyEventLoop ("lua");
+ EventLoop::set_event_loop_for_thread (event_loop);
+ SessionEvent::create_per_thread_pool ("lua", 512);
+
+ static LuaReceiver lua_receiver;
+
+ lua_receiver.listen_to (error);
+ lua_receiver.listen_to (info);
+ lua_receiver.listen_to (fatal);
+ lua_receiver.listen_to (warning);
+
+ ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (engine_connections, &do_audio_midi_setup);
+}
+
+static void set_session (ARDOUR::Session *s)
+{
+ _session = s;
+ assert (lua);
+ lua_State* L = lua->getState ();
+ LuaBindings::set_session (L, _session);
+ lua->collect_garbage (); // drop references
+}
+
+static void unset_session ()
+{
+ session_connections.drop_connections ();
+ set_session (NULL);
+}
+
+static Session * _load_session (string dir, string state)
+{
+ AudioEngine* engine = AudioEngine::instance ();
+
+ if (!engine->current_backend ()) {
+ if (!engine->set_backend ("None (Dummy)", "Unit-Test", "")) {
+ std::cerr << "Cannot create Audio/MIDI engine\n";
+ return 0;
+ }
+ }
+
+ if (!engine->current_backend ()) {
+ std::cerr << "Cannot create Audio/MIDI engine\n";
+ return 0;
+ }
+
+ if (engine->running ()) {
+ engine->stop ();
+ }
+
+ float sr;
+ SampleFormat sf;
+
+ std::string s = Glib::build_filename (dir, state + statefile_suffix);
+ if (!Glib::file_test (dir, Glib::FILE_TEST_EXISTS)) {
+ std::cerr << "Cannot find session: " << s << "\n";
+ return 0;
+ }
+
+ if (Session::get_info_from_path (s, sr, sf) == 0) {
+ if (engine->set_sample_rate (sr)) {
+ std::cerr << "Cannot set session's samplerate.\n";
+ return 0;
+ }
+ } else {
+ std::cerr << "Cannot get samplerate from session.\n";
+ return 0;
+ }
+
+ init_post_engine ();
+
+ if (engine->start () != 0) {
+ std::cerr << "Cannot start Audio/MIDI engine\n";
+ return 0;
+ }
+
+ Session* session = new Session (*engine, dir, state);
+ return session;
+}
+
+static Session* load_session (string dir, string state)
+{
+ Session* s = 0;
+ if (_session) {
+ cerr << "Session already open" << "\n";
+ return 0;
+ }
+ try {
+ s = _load_session (dir, state);
+ } catch (failed_constructor& e) {
+ cerr << "failed_constructor: " << e.what () << "\n";
+ return 0;
+ } catch (AudioEngine::PortRegistrationFailure& e) {
+ cerr << "PortRegistrationFailure: " << e.what () << "\n";
+ return 0;
+ } catch (exception& e) {
+ cerr << "exception: " << e.what () << "\n";
+ return 0;
+ } catch (...) {
+ cerr << "unknown exception.\n";
+ return 0;
+ }
+ Glib::usleep (1000000); // allo signal propagation, callback/thread-pool setup
+ assert (s);
+ set_session (s);
+ s->DropReferences.connect_same_thread (session_connections, &unset_session);
+ return s;
+}
+
+static void close_session ()
+{
+ delete _session;
+ assert (!_session);
+}
+
+static int close_session_lua (lua_State *L)
+{
+ if (!_session) {
+ cerr << "No open session" << "\n";
+ return 0;
+ }
+ close_session ();
+ return 0;
+}
+
+/* extern VST functions */
+int vstfx_init (void*) { return 0; }
+void vstfx_exit () {}
+void vstfx_destroy_editor (VSTState*) {}
+
+static void my_lua_print (std::string s) {
+ std::cout << s << "\n";
+}
+
+static void delay (float d) {
+ if (d > 0) {
+ Glib::usleep (d * 1000000);
+ }
+}
+
+static void setup_lua ()
+{
+ assert (!lua);
+
+ lua = new LuaState ();
+ lua->Print.connect (&my_lua_print);
+ lua_State* L = lua->getState ();
+
+ LuaBindings::stddef (L);
+ LuaBindings::common (L);
+ LuaBindings::session (L);
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("_G")
+ .addFunction ("load_session", &load_session)
+ .addFunction ("close_session", &close_session)
+ .addFunction ("sleep", &delay)
+ .endNamespace ();
+
+ luabridge::getGlobalNamespace (L)
+ .beginNamespace ("ARDOUR")
+ .beginClass <Session> ("Session")
+ .addExtCFunction ("close", &close_session_lua)
+ .endClass ()
+ .endNamespace ();
+
+ // push instance to global namespace (C++ lifetime)
+ luabridge::push <AudioEngine *> (L, AudioEngine::create ());
+ lua_setglobal (L, "AudioEngine");
+}
+
+int main (int argc, char **argv)
+{
+ init ();
+ setup_lua ();
+
+ using_history ();
+ std::string histfile = Glib::build_filename (user_config_directory(), "/luahist");
+
+ read_history (histfile.c_str());
+
+ char *line;
+ while ((line = readline ("> "))) {
+ event_loop->run();
+ if (!strcmp (line, "quit")) {
+ break;
+ }
+ if (strlen (line) == 0) {
+ continue;
+ }
+ if (!lua->do_command (line)) {
+ add_history (line); // OK
+ } else {
+ add_history (line); // :)
+ }
+ event_loop->run();
+ free (line);
+ }
+ printf ("\n");
+
+ if (_session) {
+ close_session ();
+ }
+
+ engine_connections.drop_connections ();
+
+ delete lua;
+ lua = NULL;
+
+ write_history (histfile.c_str());
+
+ AudioEngine::instance ()->stop ();
+ AudioEngine::destroy ();
+
+ // cleanup
+ ARDOUR::cleanup ();
+ delete event_loop;
+ pthread_cancel_all ();
+ return 0;
+}
diff --git a/tools/luadevel/wscript b/tools/luadevel/wscript
new file mode 100755
index 0000000000..730f08a7fd
--- /dev/null
+++ b/tools/luadevel/wscript
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+from waflib.extras import autowaf as autowaf
+from waflib import Options, TaskGen
+import waflib.Logs as Logs, waflib.Utils as Utils
+import os
+import shutil
+import sys
+import re
+import time
+from waflib.Task import Task
+
+top = '.'
+out = 'build'
+
+def options(opt):
+ autowaf.set_options(opt)
+
+def configure(conf):
+ conf.load('misc')
+ conf.load('compiler_cxx')
+ conf.check_cc(function_name='readline',
+ header_name='stdio.h readline/readline.h',
+ lib='readline',
+ uselib_store='READLINE',
+ mandatory=False)
+ autowaf.configure(conf)
+
+def build(bld):
+ VERSION = "%s.%s" % (bld.env['MAJOR'], bld.env['MINOR'])
+ if not bld.is_defined('HAVE_READLINE'):
+ return;
+ # no wine
+ if bld.is_defined('WINDOWS_VST_SUPPORT') and bld.env['build_target'] != 'mingw':
+ return
+
+ # TEST/DEVEL TOOL #######################
+ obj = bld (features = 'cxx c cxxprogram')
+ obj.source = 'devel.cc'
+ obj.target = 'devel'
+ obj.uselib = ['SIGCPP', 'READLINE']
+ obj.use = ['liblua']
+ obj.install_path = None
+ #########################################
+
+ # commandline luasession wrapper
+ obj = bld(features = 'subst')
+ obj.source = 'ardour-lua.sh.in'
+ obj.target = 'ardour' + str (bld.env['MAJOR']) + '-lua'
+ obj.chmod = Utils.O755
+ obj.install_path = bld.env['BINDIR']
+ obj.LIBDIR = os.path.normpath(bld.env['DLLDIR'])
+ obj.DATADIR = os.path.normpath(bld.env['DATADIR'])
+ obj.CONFDIR = os.path.normpath(bld.env['CONFDIR'])
+
+ # commandline luasession
+ obj = bld (features = 'cxx c cxxprogram')
+ obj.source = 'luasession.cc'
+ obj.target = 'luasession'
+ obj.includes = ['../libs']
+ obj.use = ['liblua'
+ 'libpbd',
+ 'libardour',
+ 'libardour_cp',
+ 'libtimecode',
+ 'libmidipp',
+ ]
+ obj.defines = [
+ 'VERSIONSTRING="' + str(bld.env['VERSION']) + '"',
+ 'DATA_DIR="' + os.path.normpath(bld.env['DATADIR']) + '"',
+ 'CONFIG_DIR="' + os.path.normpath(bld.env['SYSCONFDIR']) + '"',
+ 'LOCALEDIR="' + os.path.join(os.path.normpath(bld.env['DATADIR']), 'locale') + '"',
+ 'PACKAGE="' + "ARDOURUTILS" + '"',
+ ]
+
+ obj.uselib = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD OGG CURL DL'
+ obj.uselib += ' FFTW3F'
+ obj.uselib += ' AUDIOUNITS OSX LO '
+ obj.uselib += ' TAGLIB '
+ obj.uselib += ' READLINE '
+
+ if sys.platform == 'darwin':
+ obj.uselib += ' AUDIOUNITS OSX'
+ obj.use += ' libappleutility'
+
+ #if bld.env['build_target'] == 'mingw':
+ # if bld.env['DEBUG'] == False:
+ # obj.linkflags = ['-mwindows']
+
+ if bld.is_defined('NEED_INTL'):
+ obj.linkflags = ' -lintl'
+
+ obj.install_path = bld.env['DLLDIR']
diff --git a/wscript b/wscript
index 69ea9b3220..30a710afe6 100644
--- a/wscript
+++ b/wscript
@@ -230,6 +230,7 @@ children = [
'libs/vfork',
'libs/ardouralsautil',
'cfgtool',
+ 'tools/luadevel',
]
i18n_children = [