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