Add automatable click-free bypass/enable feature to a-eq
[ardour.git] / libs / ardour / luaproc.cc
1 /*
2     Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3     Copyright (C) 2006 Paul Davis
4
5     This program is free software; you can redistribute it and/or modify it
6     under the terms of the GNU General Public License as published by the Free
7     Software Foundation; either version 2 of the License, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful, but WITHOUT
11     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13     for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <glib.h>
21 #include <glibmm/miscutils.h>
22 #include <glibmm/fileutils.h>
23
24 #include "pbd/gstdio_compat.h"
25 #include "pbd/locale_guard.h"
26 #include "pbd/pthread_utils.h"
27
28 #include "ardour/audio_buffer.h"
29 #include "ardour/buffer_set.h"
30 #include "ardour/filesystem_paths.h"
31 #include "ardour/luabindings.h"
32 #include "ardour/luaproc.h"
33 #include "ardour/luascripting.h"
34 #include "ardour/midi_buffer.h"
35 #include "ardour/plugin.h"
36 #include "ardour/session.h"
37
38 #include "LuaBridge/LuaBridge.h"
39
40 #include "pbd/i18n.h"
41
42 using namespace ARDOUR;
43 using namespace PBD;
44
45 LuaProc::LuaProc (AudioEngine& engine,
46                   Session& session,
47                   const std::string &script)
48         : Plugin (engine, session)
49         , _mempool ("LuaProc", 3145728)
50 #ifdef USE_TLSF
51         , lua (lua_newstate (&PBD::TLSF::lalloc, &_mempool))
52 #elif defined USE_MALLOC
53         , lua ()
54 #else
55         , lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool))
56 #endif
57         , _lua_dsp (0)
58         , _script (script)
59         , _lua_does_channelmapping (false)
60         , _lua_has_inline_display (false)
61         , _designated_bypass_port (UINT32_MAX)
62         , _control_data (0)
63         , _shadow_data (0)
64         , _has_midi_input (false)
65         , _has_midi_output (false)
66 {
67         init ();
68
69         /* when loading a session, or pasing a processor,
70          * the script is set during set_state();
71          */
72         if (!_script.empty () && load_script ()) {
73                 throw failed_constructor ();
74         }
75 }
76
77 LuaProc::LuaProc (const LuaProc &other)
78         : Plugin (other)
79         , _mempool ("LuaProc", 3145728)
80 #ifdef USE_TLSF
81         , lua (lua_newstate (&PBD::TLSF::lalloc, &_mempool))
82 #elif defined USE_MALLOC
83         , lua ()
84 #else
85         , lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool))
86 #endif
87         , _lua_dsp (0)
88         , _script (other.script ())
89         , _lua_does_channelmapping (false)
90         , _lua_has_inline_display (false)
91         , _designated_bypass_port (UINT32_MAX)
92         , _control_data (0)
93         , _shadow_data (0)
94         , _has_midi_input (false)
95         , _has_midi_output (false)
96 {
97         init ();
98
99         if (load_script ()) {
100                 throw failed_constructor ();
101         }
102
103         for (uint32_t i = 0; i < parameter_count (); ++i) {
104                 _control_data[i] = other._shadow_data[i];
105                 _shadow_data[i]  = other._shadow_data[i];
106         }
107 }
108
109 LuaProc::~LuaProc () {
110 #ifdef WITH_LUAPROC_STATS
111         if (_info && _stats_cnt > 0) {
112                 printf ("LuaProc: '%s' run()  avg: %.3f  max: %.3f [ms]\n",
113                                 _info->name.c_str (),
114                                 0.0001f * _stats_avg[0] / (float) _stats_cnt,
115                                 0.0001f * _stats_max[0]);
116                 printf ("LuaProc: '%s' gc()   avg: %.3f  max: %.3f [ms]\n",
117                                 _info->name.c_str (),
118                                 0.0001f * _stats_avg[1] / (float) _stats_cnt,
119                                 0.0001f * _stats_max[1]);
120         }
121 #endif
122         lua.do_command ("collectgarbage();");
123         delete (_lua_dsp);
124         delete [] _control_data;
125         delete [] _shadow_data;
126 }
127
128 void
129 LuaProc::init ()
130 {
131 #ifdef WITH_LUAPROC_STATS
132         _stats_avg[0] = _stats_avg[1] = _stats_max[0] = _stats_max[1] = _stats_cnt = 0;
133 #endif
134
135         lua.tweak_rt_gc ();
136         lua.Print.connect (sigc::mem_fun (*this, &LuaProc::lua_print));
137         // register session object
138         lua_State* L = lua.getState ();
139         LuaBindings::stddef (L);
140         LuaBindings::common (L);
141         LuaBindings::dsp (L);
142
143         luabridge::getGlobalNamespace (L)
144                 .beginNamespace ("Ardour")
145                 .beginClass <LuaProc> ("LuaProc")
146                 .addFunction ("queue_draw", &LuaProc::queue_draw)
147                 .addFunction ("shmem", &LuaProc::instance_shm)
148                 .addFunction ("table", &LuaProc::instance_ref)
149                 .endClass ()
150                 .endNamespace ();
151
152         // add session to global lua namespace
153         luabridge::push <Session *> (L, &_session);
154         lua_setglobal (L, "Session");
155
156         // instance
157         luabridge::push <LuaProc *> (L, this);
158         lua_setglobal (L, "self");
159
160         // sandbox
161         lua.do_command ("io = nil os = nil loadfile = nil require = nil dofile = nil package = nil debug = nil");
162 #if 0
163         lua.do_command ("for n in pairs(_G) do print(n) end print ('----')"); // print global env
164 #endif
165         lua.do_command ("function ardour () end");
166 }
167
168 void
169 LuaProc::lua_print (std::string s) {
170         std::cout <<"LuaProc: " << s << "\n";
171         PBD::error << "LuaProc: " << s << "\n";
172 }
173
174 bool
175 LuaProc::load_script ()
176 {
177         assert (!_lua_dsp); // don't allow to re-initialize
178         LuaPluginInfoPtr lpi;
179
180         // TODO: refine APIs; function arguments..
181         // - perform channel-map in ardour (silent/scratch buffers) ?
182         // - control-port API (explicit get/set functions ??)
183         // - latency reporting (global var? ctrl-port? set-function ?)
184         // - MIDI -> sparse table of events
185         //     { [sample] => { Event }, .. }
186         //   or  { { sample, Event }, .. }
187
188         try {
189                 LuaScriptInfoPtr lsi = LuaScripting::script_info (_script);
190                 lpi = LuaPluginInfoPtr (new LuaPluginInfo (lsi));
191                 assert (lpi);
192                 set_info (lpi);
193                 _mempool.set_name ("LuaProc: " + lsi->name);
194                 _docs = lsi->description;
195         } catch (failed_constructor& err) {
196                 return true;
197         }
198
199         lua_State* L = lua.getState ();
200         lua.do_command (_script);
201
202         // check if script has a DSP callback
203         luabridge::LuaRef lua_dsp_run = luabridge::getGlobal (L, "dsp_run");
204         luabridge::LuaRef lua_dsp_map = luabridge::getGlobal (L, "dsp_runmap");
205
206         if ((lua_dsp_run.type () != LUA_TFUNCTION) == (lua_dsp_map.type () != LUA_TFUNCTION)) {
207                 return true;
208         }
209
210         if (lua_dsp_run.type () == LUA_TFUNCTION) {
211                 _lua_dsp = new luabridge::LuaRef (lua_dsp_run);
212         }
213         else if (lua_dsp_map.type () == LUA_TFUNCTION) {
214                 _lua_dsp = new luabridge::LuaRef (lua_dsp_map);
215                 _lua_does_channelmapping = true;
216         }
217         else {
218                 assert (0);
219         }
220
221         // initialize the DSP if needed
222         luabridge::LuaRef lua_dsp_init = luabridge::getGlobal (L, "dsp_init");
223         if (lua_dsp_init.type () == LUA_TFUNCTION) {
224                 try {
225                         lua_dsp_init (_session.nominal_frame_rate ());
226                 } catch (luabridge::LuaException const& e) {
227                         ;
228                 }
229         }
230
231         _ctrl_params.clear ();
232
233         luabridge::LuaRef lua_render = luabridge::getGlobal (L, "render_inline");
234         if (lua_render.isFunction ()) {
235                 _lua_has_inline_display = true;
236         }
237
238         luabridge::LuaRef lua_params = luabridge::getGlobal (L, "dsp_params");
239         if (lua_params.isFunction ()) {
240
241                 // call function // add try {} catch (luabridge::LuaException const& e)
242                 luabridge::LuaRef params = lua_params ();
243
244                 if (params.isTable ()) {
245
246                         for (luabridge::Iterator i (params); !i.isNil (); ++i) {
247                                 // required fields
248                                 if (!i.key ().isNumber ())           { return false; }
249                                 if (!i.value ().isTable ())          { return false; }
250                                 if (!i.value ()["type"].isString ()) { return false; }
251                                 if (!i.value ()["name"].isString ()) { return false; }
252                                 if (!i.value ()["min"].isNumber ())  { return false; }
253                                 if (!i.value ()["max"].isNumber ())  { return false; }
254
255                                 int pn = i.key ().cast<int> ();
256                                 std::string type = i.value ()["type"].cast<std::string> ();
257                                 if (type == "input") {
258                                         if (!i.value ()["default"].isNumber ()) { return false; }
259                                         _ctrl_params.push_back (std::make_pair (false, pn));
260                                 }
261                                 else if (type == "output") {
262                                         _ctrl_params.push_back (std::make_pair (true, pn));
263                                 } else {
264                                         return false;
265                                 }
266                                 assert (pn == (int) _ctrl_params.size ());
267
268                                 //_param_desc[pn] = boost::shared_ptr<ParameterDescriptor> (new ParameterDescriptor());
269                                 luabridge::LuaRef lr = i.value ();
270
271                                 if (type == "input") {
272                                         _param_desc[pn].normal     = lr["default"].cast<float> ();
273                                 } else {
274                                         _param_desc[pn].normal     = lr["min"].cast<float> (); // output-port, no default
275                                 }
276                                 _param_desc[pn].lower        = lr["min"].cast<float> ();
277                                 _param_desc[pn].upper        = lr["max"].cast<float> ();
278                                 _param_desc[pn].toggled      = lr["toggled"].isBoolean () && (lr["toggled"]).cast<bool> ();
279                                 _param_desc[pn].logarithmic  = lr["logarithmic"].isBoolean () && (lr["logarithmic"]).cast<bool> ();
280                                 _param_desc[pn].integer_step = lr["integer"].isBoolean () && (lr["integer"]).cast<bool> ();
281                                 _param_desc[pn].sr_dependent = lr["ratemult"].isBoolean () && (lr["ratemult"]).cast<bool> ();
282                                 _param_desc[pn].enumeration  = lr["enum"].isBoolean () && (lr["enum"]).cast<bool> ();
283
284                                 if (lr["bypass"].isBoolean () && (lr["bypass"]).cast<bool> ()) {
285                                         _designated_bypass_port = pn - 1; // lua table starts at 1.
286                                 }
287
288                                 if (lr["unit"].isString ()) {
289                                         std::string unit = lr["unit"].cast<std::string> ();
290                                         if (unit == "dB")             { _param_desc[pn].unit = ParameterDescriptor::DB; }
291                                         else if (unit == "Hz")        { _param_desc[pn].unit = ParameterDescriptor::HZ; }
292                                         else if (unit == "Midi Note") { _param_desc[pn].unit = ParameterDescriptor::MIDI_NOTE; }
293                                 }
294                                 _param_desc[pn].label        = (lr["name"]).cast<std::string> ();
295                                 _param_desc[pn].scale_points = parse_scale_points (&lr);
296
297                                 luabridge::LuaRef doc = lr["doc"];
298                                 if (doc.isString ()) {
299                                         _param_doc[pn] = doc.cast<std::string> ();
300                                 } else {
301                                         _param_doc[pn] = "";
302                                 }
303                                 assert (!(_param_desc[pn].toggled && _param_desc[pn].logarithmic));
304                         }
305                 }
306         }
307
308         _control_data = new float[parameter_count ()];
309         _shadow_data  = new float[parameter_count ()];
310
311         for (uint32_t i = 0; i < parameter_count (); ++i) {
312                 if (parameter_is_input (i)) {
313                         _control_data[i] = _shadow_data[i] = default_value (i);
314                 }
315         }
316
317         // expose ctrl-ports to global lua namespace
318         luabridge::push <float *> (L, _control_data);
319         lua_setglobal (L, "CtrlPorts");
320
321         return false; // no error
322 }
323
324 bool
325 LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
326 {
327         // caller must hold process lock (no concurrent calls to interpreter
328         _output_configs.clear ();
329
330         lua_State* L = lua.getState ();
331         luabridge::LuaRef ioconfig = luabridge::getGlobal (L, "dsp_ioconfig");
332
333         luabridge::LuaRef *_iotable = NULL; // can't use reference :(
334
335         if (ioconfig.isFunction ()) {
336                 try {
337                         luabridge::LuaRef iotable = ioconfig ();
338                         if (iotable.isTable ()) {
339                                 _iotable = new luabridge::LuaRef (iotable);
340                         }
341                 } catch (luabridge::LuaException const& e) {
342                         _iotable = NULL;
343                 }
344         }
345
346         if (!_iotable) {
347                 /* empty table as default */
348                 luabridge::LuaRef iotable = luabridge::newTable(L);
349                 _iotable = new luabridge::LuaRef (iotable);
350         }
351
352         // now we can reference it.
353         luabridge::LuaRef iotable (*_iotable);
354         delete _iotable;
355
356         if ((iotable).length () < 1) {
357                 /* empty table as only config, to get default values */
358                 luabridge::LuaRef ioconf = luabridge::newTable(L);
359                 iotable[1] = ioconf;
360         }
361
362         const int audio_in = in.n_audio ();
363         const int midi_in = in.n_midi ();
364
365         // preferred setting (provided by plugin_insert)
366         const int preferred_out = out.n_audio ();
367         const int preferred_midiout = out.n_midi ();
368
369         int midi_out = -1;
370         int audio_out = -1;
371         float penalty = 9999;
372         bool found = false;
373
374 #define FOUNDCFG_PENALTY(in, out, p) {                              \
375   _output_configs.insert (out);                                     \
376   if (p < penalty) {                                                \
377     audio_out = (out);                                              \
378     midi_out = possible_midiout;                                    \
379     if (imprecise) {                                                \
380       imprecise->set (DataType::AUDIO, (in));                       \
381       imprecise->set (DataType::MIDI, possible_midiin);             \
382     }                                                               \
383     _has_midi_input = (possible_midiin > 0);                        \
384     _has_midi_output = (possible_midiout > 0);                      \
385     penalty = p;                                                    \
386     found = true;                                                   \
387   }                                                                 \
388 }
389
390 #define FOUNDCFG_IMPRECISE(in, out) {                               \
391   const float p = fabsf ((float)(out) - preferred_out) *            \
392                       (((out) > preferred_out) ? 1.1 : 1)           \
393                 + fabsf ((float)possible_midiout - preferred_midiout) *    \
394                       ((possible_midiout - preferred_midiout) ? 0.6 : 0.5) \
395                 + fabsf ((float)(in) - audio_in) *                  \
396                       (((in) > audio_in) ? 275 : 250)               \
397                 + fabsf ((float)possible_midiin - midi_in) *        \
398                       ((possible_midiin - midi_in) ? 100 : 110);    \
399   FOUNDCFG_PENALTY(in, out, p);                                     \
400 }
401
402 #define FOUNDCFG(out)                                               \
403   FOUNDCFG_IMPRECISE(audio_in, out)
404
405 #define ANYTHINGGOES                                                \
406   _output_configs.insert (0);
407
408 #define UPTO(nch) {                                                 \
409   for (int n = 1; n < nch; ++n) {                                   \
410     _output_configs.insert (n);                                     \
411   }                                                                 \
412 }
413
414         if (imprecise) {
415                 *imprecise = in;
416         }
417
418         for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
419                 luabridge::LuaRef io (i.value ());
420                 if (!io.isTable()) {
421                         continue;
422                 }
423
424                 int possible_in = io["audio_in"].isNumber() ? io["audio_in"] : -1;
425                 int possible_out = io["audio_out"].isNumber() ? io["audio_out"] : -1;
426                 int possible_midiin = io["midi_in"].isNumber() ? io["midi_in"] : 0;
427                 int possible_midiout = io["midi_out"].isNumber() ? io["midi_out"] : 0;
428
429                 if (midi_in != possible_midiin && !imprecise) {
430                         continue;
431                 }
432
433                 // exact match
434                 if ((possible_in == audio_in) && (possible_out == preferred_out)) {
435                         /* Set penalty so low that this output configuration
436                          * will trump any other one */
437                         FOUNDCFG_PENALTY(audio_in, preferred_out, -1);
438                 }
439
440                 if (possible_out == 0 && possible_midiout == 0) {
441                         /* skip configurations with no output at all */
442                         continue;
443                 }
444
445                 if (possible_in == -1 || possible_in == -2) {
446                         /* wildcard for input */
447                         if (possible_out == possible_in) {
448                                 /* either both -1 or both -2 (invalid and
449                                  * interpreted as both -1): out must match in */
450                                 FOUNDCFG (audio_in);
451                         } else if (possible_out == -3 - possible_in) {
452                                 /* one is -1, the other is -2: any output configuration
453                                  * possible, pick what the insert prefers */
454                                 FOUNDCFG (preferred_out);
455                                 ANYTHINGGOES;
456                         } else if (possible_out < -2) {
457                                 /* variable number of outputs up to -N,
458                                  * invalid if in == -2 but we accept it anyway */
459                                 FOUNDCFG (min (-possible_out, preferred_out));
460                                 UPTO (-possible_out)
461                         } else {
462                                 /* exact number of outputs */
463                                 FOUNDCFG (possible_out);
464                         }
465                 }
466
467                 if (possible_in < -2 || possible_in >= 0) {
468                         /* specified number, exact or up to */
469                         int desired_in;
470                         if (possible_in >= 0) {
471                                 /* configuration can only match possible_in */
472                                 desired_in = possible_in;
473                         } else {
474                                 /* configuration can match up to -possible_in */
475                                 desired_in = min (-possible_in, audio_in);
476                         }
477                         if (!imprecise && audio_in != desired_in) {
478                                 /* skip that configuration, it cannot match
479                                  * the required audio input count, and we
480                                  * cannot ask for change via \imprecise */
481                         } else if (possible_out == -1 || possible_out == -2) {
482                                 /* any output configuration possible
483                                  * out == -2 is invalid, interpreted as out == -1.
484                                  * Really imprecise only if desired_in != audio_in */
485                                 FOUNDCFG_IMPRECISE (desired_in, preferred_out);
486                                 ANYTHINGGOES;
487                         } else if (possible_out < -2) {
488                                 /* variable number of outputs up to -N
489                                  * not specified if in > 0, but we accept it anyway.
490                                  * Really imprecise only if desired_in != audio_in */
491                                 FOUNDCFG_IMPRECISE (desired_in, min (-possible_out, preferred_out));
492                                 UPTO (-possible_out)
493                         } else {
494                                 /* exact number of outputs
495                                  * Really imprecise only if desired_in != audio_in */
496                                 FOUNDCFG_IMPRECISE (desired_in, possible_out);
497                         }
498                 }
499
500         }
501
502         if (!found) {
503                 return false;
504         }
505
506         if (imprecise) {
507                 _selected_in = *imprecise;
508         } else {
509                 _selected_in = in;
510         }
511
512         out.set (DataType::MIDI, midi_out);
513         out.set (DataType::AUDIO, audio_out);
514         _selected_out = out;
515
516         return true;
517 }
518
519 bool
520 LuaProc::configure_io (ChanCount in, ChanCount out)
521 {
522         in.set (DataType::MIDI, _has_midi_input ? 1 : 0);
523         out.set (DataType::MIDI, _has_midi_output ? 1 : 0);
524
525         _info->n_inputs = _selected_in;
526         _info->n_outputs = _selected_out;
527
528         // configure the DSP if needed
529         if (in != _configured_in || out != _configured_out) {
530                 lua_State* L = lua.getState ();
531                 luabridge::LuaRef lua_dsp_configure = luabridge::getGlobal (L, "dsp_configure");
532                 if (lua_dsp_configure.type () == LUA_TFUNCTION) {
533                         try {
534                                 luabridge::LuaRef io = lua_dsp_configure (&in, &out);
535                                 if (io.isTable ()) {
536                                         ChanCount lin (_selected_in);
537                                         ChanCount lout (_selected_out);
538
539                                         if (io["audio_in"].type() == LUA_TNUMBER) {
540                                                 const int c = io["audio_in"].cast<int> ();
541                                                 if (c >= 0) {
542                                                         lin.set (DataType::AUDIO, c);
543                                                 }
544                                         }
545                                         if (io["audio_out"].type() == LUA_TNUMBER) {
546                                                 const int c = io["audio_out"].cast<int> ();
547                                                 if (c >= 0) {
548                                                         lout.set (DataType::AUDIO, c);
549                                                 }
550                                         }
551                                         if (io["midi_in"].type() == LUA_TNUMBER) {
552                                                 const int c = io["midi_in"].cast<int> ();
553                                                 if (c >= 0) {
554                                                         lin.set (DataType::MIDI, c);
555                                                 }
556                                         }
557                                         if (io["midi_out"].type() == LUA_TNUMBER) {
558                                                 const int c = io["midi_out"].cast<int> ();
559                                                 if (c >= 0) {
560                                                         lout.set (DataType::MIDI, c);
561                                                 }
562                                         }
563                                         _info->n_inputs = lin;
564                                         _info->n_outputs = lout;
565                                 }
566                         } catch (luabridge::LuaException const& e) {
567                                 PBD::error << "LuaException: " << e.what () << "\n";
568 #ifndef NDEBUG
569                                 std::cerr << "LuaException: " << e.what () << "\n";
570 #endif
571                                 return false;
572                         }
573                 }
574         }
575
576         _configured_in = in;
577         _configured_out = out;
578
579         return true;
580 }
581
582 int
583 LuaProc::connect_and_run (BufferSet& bufs,
584                 framepos_t start, framepos_t end, double speed,
585                 ChanMapping in, ChanMapping out,
586                 pframes_t nframes, framecnt_t offset)
587 {
588         if (!_lua_dsp) {
589                 return 0;
590         }
591
592         Plugin::connect_and_run (bufs, start, end, speed, in, out, nframes, offset);
593
594         // This is needed for ARDOUR::Session requests :(
595         if (! SessionEvent::has_per_thread_pool ()) {
596                 char name[64];
597                 snprintf (name, 64, "Proc-%p", this);
598                 pthread_set_name (name);
599                 SessionEvent::create_per_thread_pool (name, 64);
600                 PBD::notify_event_loops_about_thread_creation (pthread_self(), name, 64);
601         }
602
603         uint32_t const n = parameter_count ();
604         for (uint32_t i = 0; i < n; ++i) {
605                 if (parameter_is_control (i) && parameter_is_input (i)) {
606                         _control_data[i] = _shadow_data[i];
607                 }
608         }
609
610 #ifdef WITH_LUAPROC_STATS
611         int64_t t0 = g_get_monotonic_time ();
612 #endif
613
614         try {
615                 if (_lua_does_channelmapping) {
616                         // run the DSP function
617                         (*_lua_dsp)(&bufs, in, out, nframes, offset);
618                 } else {
619                         // map buffers
620                         BufferSet& silent_bufs  = _session.get_silent_buffers (ChanCount (DataType::AUDIO, 1));
621                         BufferSet& scratch_bufs = _session.get_scratch_buffers (ChanCount (DataType::AUDIO, 1));
622
623                         lua_State* L = lua.getState ();
624                         luabridge::LuaRef in_map (luabridge::newTable (L));
625                         luabridge::LuaRef out_map (luabridge::newTable (L));
626
627                         const uint32_t audio_in = _configured_in.n_audio ();
628                         const uint32_t audio_out = _configured_out.n_audio ();
629                         const uint32_t midi_in = _configured_in.n_midi ();
630
631                         for (uint32_t ap = 0; ap < audio_in; ++ap) {
632                                 bool valid;
633                                 const uint32_t buf_index = in.get(DataType::AUDIO, ap, &valid);
634                                 if (valid) {
635                                         in_map[ap + 1] = bufs.get_audio (buf_index).data (offset);
636                                 } else {
637                                         in_map[ap + 1] = silent_bufs.get_audio (0).data (offset);
638                                 }
639                         }
640                         for (uint32_t ap = 0; ap < audio_out; ++ap) {
641                                 bool valid;
642                                 const uint32_t buf_index = out.get(DataType::AUDIO, ap, &valid);
643                                 if (valid) {
644                                         out_map[ap + 1] = bufs.get_audio (buf_index).data (offset);
645                                 } else {
646                                         out_map[ap + 1] = scratch_bufs.get_audio (0).data (offset);
647                                 }
648                         }
649
650                         luabridge::LuaRef lua_midi_src_tbl (luabridge::newTable (L));
651                         int e = 1; // > 1 port, we merge events (unsorted)
652                         for (uint32_t mp = 0; mp < midi_in; ++mp) {
653                                 bool valid;
654                                 const uint32_t idx = in.get(DataType::MIDI, mp, &valid);
655                                 if (valid) {
656                                         for (MidiBuffer::iterator m = bufs.get_midi(idx).begin();
657                                                         m != bufs.get_midi(idx).end(); ++m, ++e) {
658                                                 const Evoral::MIDIEvent<framepos_t> ev(*m, false);
659                                                 luabridge::LuaRef lua_midi_data (luabridge::newTable (L));
660                                                 const uint8_t* data = ev.buffer();
661                                                 for (uint32_t i = 0; i < ev.size(); ++i) {
662                                                         lua_midi_data [i + 1] = data[i];
663                                                 }
664                                                 luabridge::LuaRef lua_midi_event (luabridge::newTable (L));
665                                                 lua_midi_event["time"] = 1 + (*m).time();
666                                                 lua_midi_event["data"] = lua_midi_data;
667                                                 lua_midi_event["bytes"] = data;
668                                                 lua_midi_event["size"] = ev.size();
669                                                 lua_midi_src_tbl[e] = lua_midi_event;
670                                         }
671                                 }
672                         }
673
674                         if (_has_midi_input) {
675                                 // XXX TODO This needs a better solution than global namespace
676                                 luabridge::push (L, lua_midi_src_tbl);
677                                 lua_setglobal (L, "midiin");
678                         }
679
680                         luabridge::LuaRef lua_midi_sink_tbl (luabridge::newTable (L));
681                         if (_has_midi_output) {
682                                 luabridge::push (L, lua_midi_sink_tbl);
683                                 lua_setglobal (L, "midiout");
684                         }
685
686                         // run the DSP function
687                         (*_lua_dsp)(in_map, out_map, nframes);
688
689                         // copy back midi events
690                         if (_has_midi_output && lua_midi_sink_tbl.isTable ()) {
691                                 bool valid;
692                                 const uint32_t idx = out.get(DataType::MIDI, 0, &valid);
693                                 if (valid && bufs.count().n_midi() > idx) {
694                                         MidiBuffer& mbuf = bufs.get_midi(idx);
695                                         mbuf.silence(0, 0);
696                                         for (luabridge::Iterator i (lua_midi_sink_tbl); !i.isNil (); ++i) {
697                                                 if (!i.key ().isNumber ()) { continue; }
698                                                 if (!i.value ()["time"].isNumber ()) { continue; }
699                                                 if (!i.value ()["data"].isTable ()) { continue; }
700                                                 luabridge::LuaRef data_tbl (i.value ()["data"]);
701                                                 framepos_t tme = i.value ()["time"];
702                                                 if (tme < 1 || tme > nframes) { continue; }
703                                                 uint8_t data[64];
704                                                 size_t size = 0;
705                                                 for (luabridge::Iterator di (data_tbl); !di.isNil () && size < sizeof(data); ++di, ++size) {
706                                                         data[size] = di.value ();
707                                                 }
708                                                 if (size > 0 && size < 64) {
709                                                         mbuf.push_back(tme - 1, size, data);
710                                                 }
711                                         }
712
713                                 }
714                         }
715                 }
716         } catch (luabridge::LuaException const& e) {
717                 PBD::error << "LuaException: " << e.what () << "\n";
718 #ifndef NDEBUG
719                 std::cerr << "LuaException: " << e.what () << "\n";
720 #endif
721                 return -1;
722         }
723 #ifdef WITH_LUAPROC_STATS
724         int64_t t1 = g_get_monotonic_time ();
725 #endif
726
727         lua.collect_garbage_step ();
728 #ifdef WITH_LUAPROC_STATS
729         ++_stats_cnt;
730         int64_t t2 = g_get_monotonic_time ();
731         int64_t ela0 = t1 - t0;
732         int64_t ela1 = t2 - t1;
733         if (ela0 > _stats_max[0]) _stats_max[0] = ela0;
734         if (ela1 > _stats_max[1]) _stats_max[1] = ela1;
735         _stats_avg[0] += ela0;
736         _stats_avg[1] += ela1;
737 #endif
738         return 0;
739 }
740
741
742 void
743 LuaProc::add_state (XMLNode* root) const
744 {
745         XMLNode*    child;
746         char        buf[32];
747         LocaleGuard lg;
748
749         gchar* b64 = g_base64_encode ((const guchar*)_script.c_str (), _script.size ());
750         std::string b64s (b64);
751         g_free (b64);
752         XMLNode* script_node = new XMLNode (X_("script"));
753         script_node->add_property (X_("lua"), LUA_VERSION);
754         script_node->add_content (b64s);
755         root->add_child_nocopy (*script_node);
756
757         for (uint32_t i = 0; i < parameter_count(); ++i) {
758                 if (parameter_is_input(i) && parameter_is_control(i)) {
759                         child = new XMLNode("Port");
760                         snprintf(buf, sizeof(buf), "%u", i);
761                         child->add_property("id", std::string(buf));
762                         snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
763                         child->add_property("value", std::string(buf));
764                         root->add_child_nocopy(*child);
765                 }
766         }
767 }
768
769 int
770 LuaProc::set_script_from_state (const XMLNode& node)
771 {
772         XMLNode* child;
773         if (node.name () != state_node_name ()) {
774                 return -1;
775         }
776
777         if ((child = node.child (X_("script"))) != 0) {
778                 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
779                         if (!(*n)->is_content ()) { continue; }
780                         gsize size;
781                         guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
782                         _script = std::string ((const char*)buf, size);
783                         g_free (buf);
784                         if (load_script ()) {
785                                 PBD::error << _("Failed to load Lua script from session state.") << endmsg;
786 #ifndef NDEBUG
787                                 std::cerr << "Failed Lua Script: " << _script << std::endl;
788 #endif
789                                 _script = "";
790                         }
791                         break;
792                 }
793         }
794         if (_script.empty ()) {
795                 PBD::error << _("Session State for LuaProcessor did not include a Lua script.") << endmsg;
796                 return -1;
797         }
798         if (!_lua_dsp) {
799                 PBD::error << _("Invalid/incompatible Lua script found for LuaProcessor.") << endmsg;
800                 return -1;
801         }
802         return 0;
803 }
804
805 int
806 LuaProc::set_state (const XMLNode& node, int version)
807 {
808 #ifndef NO_PLUGIN_STATE
809         XMLNodeList nodes;
810         XMLProperty const * prop;
811         XMLNodeConstIterator iter;
812         XMLNode *child;
813         const char *value;
814         const char *port;
815         uint32_t port_id;
816 #endif
817         LocaleGuard lg;
818
819         if (_script.empty ()) {
820                 if (set_script_from_state (node)) {
821                         return -1;
822                 }
823         }
824
825 #ifndef NO_PLUGIN_STATE
826         if (node.name() != state_node_name()) {
827                 error << _("Bad node sent to LuaProc::set_state") << endmsg;
828                 return -1;
829         }
830
831         nodes = node.children ("Port");
832         for (iter = nodes.begin(); iter != nodes.end(); ++iter) {
833                 child = *iter;
834                 if ((prop = child->property("id")) != 0) {
835                         port = prop->value().c_str();
836                 } else {
837                         warning << _("LuaProc: port has no symbol, ignored") << endmsg;
838                         continue;
839                 }
840                 if ((prop = child->property("value")) != 0) {
841                         value = prop->value().c_str();
842                 } else {
843                         warning << _("LuaProc: port has no value, ignored") << endmsg;
844                         continue;
845                 }
846                 sscanf (port, "%" PRIu32, &port_id);
847                 set_parameter (port_id, atof(value));
848         }
849 #endif
850
851         return Plugin::set_state (node, version);
852 }
853
854 uint32_t
855 LuaProc::parameter_count () const
856 {
857         return _ctrl_params.size ();
858 }
859
860 float
861 LuaProc::default_value (uint32_t port)
862 {
863         if (_ctrl_params[port].first) {
864                 assert (0);
865                 return 0;
866         }
867         int lp = _ctrl_params[port].second;
868         return _param_desc[lp].normal;
869 }
870
871 void
872 LuaProc::set_parameter (uint32_t port, float val)
873 {
874         assert (port < parameter_count ());
875         if (get_parameter (port) == val) {
876                 return;
877         }
878         _shadow_data[port] = val;
879         Plugin::set_parameter (port, val);
880 }
881
882 float
883 LuaProc::get_parameter (uint32_t port) const
884 {
885         if (parameter_is_input (port)) {
886                 return _shadow_data[port];
887         } else {
888                 return _control_data[port];
889         }
890 }
891
892 int
893 LuaProc::get_parameter_descriptor (uint32_t port, ParameterDescriptor& desc) const
894 {
895         assert (port <= parameter_count ());
896         int lp = _ctrl_params[port].second;
897         const ParameterDescriptor& d (_param_desc.find(lp)->second);
898
899         desc.lower        = d.lower;
900         desc.upper        = d.upper;
901         desc.normal       = d.normal;
902         desc.toggled      = d.toggled;
903         desc.logarithmic  = d.logarithmic;
904         desc.integer_step = d.integer_step;
905         desc.sr_dependent = d.sr_dependent;
906         desc.enumeration  = d.enumeration;
907         desc.unit         = d.unit;
908         desc.label        = d.label;
909         desc.scale_points = d.scale_points;
910
911         desc.update_steps ();
912         return 0;
913 }
914
915 std::string
916 LuaProc::get_parameter_docs (uint32_t port) const {
917         assert (port <= parameter_count ());
918         int lp = _ctrl_params[port].second;
919         return _param_doc.find(lp)->second;
920 }
921
922 uint32_t
923 LuaProc::nth_parameter (uint32_t port, bool& ok) const
924 {
925         if (port < _ctrl_params.size ()) {
926                 ok = true;
927                 return port;
928         }
929         ok = false;
930         return 0;
931 }
932
933 bool
934 LuaProc::parameter_is_input (uint32_t port) const
935 {
936         assert (port < _ctrl_params.size ());
937         return (!_ctrl_params[port].first);
938 }
939
940 bool
941 LuaProc::parameter_is_output (uint32_t port) const
942 {
943         assert (port < _ctrl_params.size ());
944         return (_ctrl_params[port].first);
945 }
946
947 std::set<Evoral::Parameter>
948 LuaProc::automatable () const
949 {
950         std::set<Evoral::Parameter> automatables;
951         for (uint32_t i = 0; i < _ctrl_params.size (); ++i) {
952                 if (parameter_is_input (i)) {
953                         automatables.insert (automatables.end (), Evoral::Parameter (PluginAutomation, 0, i));
954                 }
955         }
956         return automatables;
957 }
958
959 std::string
960 LuaProc::describe_parameter (Evoral::Parameter param)
961 {
962         if (param.type () == PluginAutomation && param.id () < parameter_count ()) {
963                 int lp = _ctrl_params[param.id ()].second;
964                 return _param_desc[lp].label;
965         }
966         return "??";
967 }
968
969 void
970 LuaProc::print_parameter (uint32_t param, char* buf, uint32_t len) const
971 {
972         if (buf && len) {
973                 if (param < parameter_count ()) {
974                         snprintf (buf, len, "%.3f", get_parameter (param));
975                 } else {
976                         strcat (buf, "0");
977                 }
978         }
979 }
980
981 boost::shared_ptr<ScalePoints>
982 LuaProc::parse_scale_points (luabridge::LuaRef* lr)
983 {
984         if (!(*lr)["scalepoints"].isTable()) {
985                 return boost::shared_ptr<ScalePoints> ();
986         }
987
988         int cnt = 0;
989         boost::shared_ptr<ScalePoints> rv = boost::shared_ptr<ScalePoints>(new ScalePoints());
990         luabridge::LuaRef scalepoints ((*lr)["scalepoints"]);
991
992         for (luabridge::Iterator i (scalepoints); !i.isNil (); ++i) {
993                 if (!i.key ().isString ())    { continue; }
994                 if (!i.value ().isNumber ())  { continue; }
995                 rv->insert(make_pair(i.key ().cast<std::string> (),
996                                         i.value ().cast<float> ()));
997                 ++cnt;
998         }
999
1000         if (rv->size() > 0) {
1001                 return rv;
1002         }
1003         return boost::shared_ptr<ScalePoints> ();
1004 }
1005
1006 boost::shared_ptr<ScalePoints>
1007 LuaProc::get_scale_points (uint32_t port) const
1008 {
1009         int lp = _ctrl_params[port].second;
1010         return _param_desc.find(lp)->second.scale_points;
1011 }
1012
1013 void
1014 LuaProc::setup_lua_inline_gui (LuaState *lua_gui)
1015 {
1016         lua_State* LG = lua_gui->getState ();
1017         LuaBindings::stddef (LG);
1018         LuaBindings::common (LG);
1019         LuaBindings::dsp (LG);
1020
1021         lua_gui->Print.connect (sigc::mem_fun (*this, &LuaProc::lua_print));
1022         lua_gui->do_command ("function ardour () end");
1023         lua_gui->do_command (_script);
1024
1025         // TODO think: use a weak-pointer here ?
1026         // (the GUI itself uses a shared ptr to this plugin, so we should be good)
1027         luabridge::getGlobalNamespace (LG)
1028                 .beginNamespace ("Ardour")
1029                 .beginClass <LuaProc> ("LuaProc")
1030                 .addFunction ("shmem", &LuaProc::instance_shm)
1031                 .addFunction ("table", &LuaProc::instance_ref)
1032                 .endClass ()
1033                 .endNamespace ();
1034
1035         luabridge::push <LuaProc *> (LG, this);
1036         lua_setglobal (LG, "self");
1037
1038         luabridge::push <float *> (LG, _shadow_data);
1039         lua_setglobal (LG, "CtrlPorts");
1040 }
1041 ////////////////////////////////////////////////////////////////////////////////
1042
1043 #include "ardour/search_paths.h"
1044 #include "sha1.c"
1045
1046 std::string
1047 LuaProc::preset_name_to_uri (const std::string& name) const
1048 {
1049         std::string uri ("urn:lua:");
1050         char hash[41];
1051         Sha1Digest s;
1052         sha1_init (&s);
1053         sha1_write (&s, (const uint8_t *) name.c_str(), name.size ());
1054         sha1_write (&s, (const uint8_t *) _script.c_str(), _script.size ());
1055         sha1_result_hash (&s, hash);
1056         return uri + hash;
1057 }
1058
1059 std::string
1060 LuaProc::presets_file () const
1061 {
1062         return string_compose ("lua-%1", _info->unique_id);
1063 }
1064
1065 XMLTree*
1066 LuaProc::presets_tree () const
1067 {
1068         XMLTree* t = new XMLTree;
1069         std::string p = Glib::build_filename (ARDOUR::user_config_directory (), "presets");
1070
1071         if (!Glib::file_test (p, Glib::FILE_TEST_IS_DIR)) {
1072                 if (g_mkdir_with_parents (p.c_str(), 0755) != 0) {
1073                         error << _("Unable to create LuaProc presets directory") << endmsg;
1074                 };
1075         }
1076
1077         p = Glib::build_filename (p, presets_file ());
1078
1079         if (!Glib::file_test (p, Glib::FILE_TEST_EXISTS)) {
1080                 t->set_root (new XMLNode (X_("LuaPresets")));
1081                 return t;
1082         }
1083
1084         t->set_filename (p);
1085         if (!t->read ()) {
1086                 delete t;
1087                 return 0;
1088         }
1089         return t;
1090 }
1091
1092 bool
1093 LuaProc::load_preset (PresetRecord r)
1094 {
1095         boost::shared_ptr<XMLTree> t (presets_tree ());
1096         if (t == 0) {
1097                 return false;
1098         }
1099
1100         XMLNode* root = t->root ();
1101         for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
1102                 XMLProperty const * label = (*i)->property (X_("label"));
1103                 assert (label);
1104                 if (label->value() != r.label) {
1105                         continue;
1106                 }
1107
1108                 for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j) {
1109                         if ((*j)->name() == X_("Parameter")) {
1110                                 XMLProperty const * index = (*j)->property (X_("index"));
1111                                 XMLProperty const * value = (*j)->property (X_("value"));
1112                                 assert (index);
1113                                 assert (value);
1114                                 LocaleGuard lg;
1115                                 set_parameter (atoi (index->value().c_str()), atof (value->value().c_str ()));
1116                         }
1117                 }
1118                 return Plugin::load_preset(r);
1119         }
1120         return false;
1121 }
1122
1123 std::string
1124 LuaProc::do_save_preset (std::string name) {
1125
1126         boost::shared_ptr<XMLTree> t (presets_tree ());
1127         if (t == 0) {
1128                 return "";
1129         }
1130
1131         std::string uri (preset_name_to_uri (name));
1132
1133         XMLNode* p = new XMLNode (X_("Preset"));
1134         p->add_property (X_("uri"), uri);
1135         p->add_property (X_("label"), name);
1136
1137         for (uint32_t i = 0; i < parameter_count(); ++i) {
1138                 if (parameter_is_input (i)) {
1139                         XMLNode* c = new XMLNode (X_("Parameter"));
1140                         c->add_property (X_("index"), string_compose ("%1", i));
1141                         c->add_property (X_("value"), string_compose ("%1", get_parameter (i)));
1142                         p->add_child_nocopy (*c);
1143                 }
1144         }
1145         t->root()->add_child_nocopy (*p);
1146
1147         std::string f = Glib::build_filename (ARDOUR::user_config_directory (), "presets");
1148         f = Glib::build_filename (f, presets_file ());
1149
1150         t->write (f);
1151         return uri;
1152 }
1153
1154 void
1155 LuaProc::do_remove_preset (std::string name)
1156 {
1157         boost::shared_ptr<XMLTree> t (presets_tree ());
1158         if (t == 0) {
1159                 return;
1160         }
1161         t->root()->remove_nodes_and_delete (X_("label"), name);
1162         std::string f = Glib::build_filename (ARDOUR::user_config_directory (), "presets");
1163         f = Glib::build_filename (f, presets_file ());
1164         t->write (f);
1165 }
1166
1167 void
1168 LuaProc::find_presets ()
1169 {
1170         boost::shared_ptr<XMLTree> t (presets_tree ());
1171         if (t) {
1172                 XMLNode* root = t->root ();
1173                 for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
1174
1175                         XMLProperty const * uri = (*i)->property (X_("uri"));
1176                         XMLProperty const * label = (*i)->property (X_("label"));
1177
1178                         assert (uri);
1179                         assert (label);
1180
1181                         PresetRecord r (uri->value(), label->value(), true);
1182                         _presets.insert (make_pair (r.uri, r));
1183                 }
1184         }
1185 }
1186
1187 ////////////////////////////////////////////////////////////////////////////////
1188
1189 LuaPluginInfo::LuaPluginInfo (LuaScriptInfoPtr lsi) {
1190         if (lsi->type != LuaScriptInfo::DSP) {
1191                 throw failed_constructor ();
1192         }
1193
1194         path = lsi->path;
1195         name = lsi->name;
1196         creator = lsi->author;
1197         category = lsi->category;
1198         unique_id = lsi->unique_id;
1199
1200         n_inputs.set (DataType::AUDIO, 1);
1201         n_outputs.set (DataType::AUDIO, 1);
1202         type = Lua;
1203
1204         _is_instrument = category == "Instrument";
1205 }
1206
1207 PluginPtr
1208 LuaPluginInfo::load (Session& session)
1209 {
1210         std::string script = "";
1211         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1212                 return PluginPtr ();
1213         }
1214
1215         try {
1216                 script = Glib::file_get_contents (path);
1217         } catch (Glib::FileError err) {
1218                 return PluginPtr ();
1219         }
1220
1221         if (script.empty ()) {
1222                 return PluginPtr ();
1223         }
1224
1225         try {
1226                 PluginPtr plugin (new LuaProc (session.engine (), session, script));
1227                 return plugin;
1228         } catch (failed_constructor& err) {
1229                 ;
1230         }
1231         return PluginPtr ();
1232 }
1233
1234 std::vector<Plugin::PresetRecord>
1235 LuaPluginInfo::get_presets (bool /*user_only*/) const
1236 {
1237         std::vector<Plugin::PresetRecord> p;
1238         XMLTree* t = new XMLTree;
1239         std::string pf = Glib::build_filename (ARDOUR::user_config_directory (), "presets", string_compose ("lua-%1", unique_id));
1240         if (Glib::file_test (pf, Glib::FILE_TEST_EXISTS)) {
1241                 t->set_filename (pf);
1242                 if (t->read ()) {
1243                         XMLNode* root = t->root ();
1244                         for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
1245                                 XMLProperty const * uri = (*i)->property (X_("uri"));
1246                                 XMLProperty const * label = (*i)->property (X_("label"));
1247                                 p.push_back (Plugin::PresetRecord (uri->value(), label->value(), true));
1248                         }
1249                 }
1250         }
1251         delete t;
1252         return p;
1253 }