abort if configuration fails
[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 "pbd/gstdio_compat.h"
22
23 #include "pbd/pthread_utils.h"
24
25 #include "ardour/audio_buffer.h"
26 #include "ardour/buffer_set.h"
27 #include "ardour/luabindings.h"
28 #include "ardour/luaproc.h"
29 #include "ardour/luascripting.h"
30 #include "ardour/midi_buffer.h"
31 #include "ardour/plugin.h"
32 #include "ardour/session.h"
33
34 #include "LuaBridge/LuaBridge.h"
35
36 #include "i18n.h"
37
38 using namespace ARDOUR;
39 using namespace PBD;
40
41 LuaProc::LuaProc (AudioEngine& engine,
42                   Session& session,
43                   const std::string &script)
44         : Plugin (engine, session)
45         , _mempool ("LuaProc", 1048576) // 1 MB is plenty. (64K would be enough)
46         , lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool))
47         , _lua_dsp (0)
48         , _script (script)
49         , _lua_does_channelmapping (false)
50         , _control_data (0)
51         , _shadow_data (0)
52         , _has_midi_input (false)
53         , _has_midi_output (false)
54 {
55         init ();
56
57         /* when loading a session, or pasing a processor,
58          * the script is set during set_state();
59          */
60         if (!_script.empty () && load_script ()) {
61                 throw failed_constructor ();
62         }
63 }
64
65 LuaProc::LuaProc (const LuaProc &other)
66         : Plugin (other)
67         , _mempool ("LuaProc", 1048576) // 1 MB is plenty. (64K would be enough)
68         , lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool))
69         , _lua_dsp (0)
70         , _script (other.script ())
71         , _lua_does_channelmapping (false)
72         , _control_data (0)
73         , _shadow_data (0)
74         , _has_midi_input (false)
75         , _has_midi_output (false)
76 {
77         init ();
78
79         if (load_script ()) {
80                 throw failed_constructor ();
81         }
82
83         for (uint32_t i = 0; i < parameter_count (); ++i) {
84                 _control_data[i] = other._shadow_data[i];
85                 _shadow_data[i]  = other._shadow_data[i];
86         }
87 }
88
89 LuaProc::~LuaProc () {
90 #ifdef WITH_LUAPROC_STATS
91         if (_info && _stats_cnt > 0) {
92                 printf ("LuaProc: '%s' run()  avg: %.3f  max: %.3f [ms]\n",
93                                 _info->name.c_str (),
94                                 0.0001f * _stats_avg[0] / (float) _stats_cnt,
95                                 0.0001f * _stats_max[0]);
96                 printf ("LuaProc: '%s' gc()   avg: %.3f  max: %.3f [ms]\n",
97                                 _info->name.c_str (),
98                                 0.0001f * _stats_avg[1] / (float) _stats_cnt,
99                                 0.0001f * _stats_max[1]);
100         }
101 #endif
102         lua.do_command ("collectgarbage();");
103         delete (_lua_dsp);
104         delete [] _control_data;
105         delete [] _shadow_data;
106 }
107
108 void
109 LuaProc::init ()
110 {
111 #ifdef WITH_LUAPROC_STATS
112         _stats_avg[0] = _stats_avg[1] = _stats_max[0] = _stats_max[1] = _stats_cnt = 0;
113 #endif
114
115 #ifndef NDEBUG
116         lua.Print.connect (sigc::mem_fun (*this, &LuaProc::lua_print));
117 #endif
118         // register session object
119         lua_State* L = lua.getState ();
120         LuaBindings::stddef (L);
121         LuaBindings::common (L);
122         LuaBindings::dsp (L);
123
124         luabridge::getGlobalNamespace (L)
125                 .beginNamespace ("Ardour")
126                 .beginClass <LuaProc> ("LuaProc")
127                 .addFunction ("queue_draw", &LuaProc::queue_draw)
128                 .addFunction ("shmem", &LuaProc::instance_shm)
129                 .endClass ()
130                 .endNamespace ();
131
132         // add session to global lua namespace
133         luabridge::push <Session *> (L, &_session);
134         lua_setglobal (L, "Session");
135
136         // instance
137         luabridge::push <LuaProc *> (L, this);
138         lua_setglobal (L, "self");
139
140         // sandbox
141         lua.do_command ("io = nil os = nil loadfile = nil require = nil dofile = nil package = nil debug = nil");
142 #if 0
143         lua.do_command ("for n in pairs(_G) do print(n) end print ('----')"); // print global env
144 #endif
145         lua.do_command ("function ardour () end");
146 }
147
148 void
149 LuaProc::lua_print (std::string s) {
150         std::cout <<"LuaProc: " << s << "\n";
151 }
152
153 bool
154 LuaProc::load_script ()
155 {
156         assert (!_lua_dsp); // don't allow to re-initialize
157
158         // TODO: refine APIs; function arguments..
159         // - perform channel-map in ardour (silent/scratch buffers) ?
160         // - control-port API (explicit get/set functions ??)
161         // - latency reporting (global var? ctrl-port? set-function ?)
162         // - MIDI -> sparse table of events
163         //     { [sample] => { Event }, .. }
164         //   or  { { sample, Event }, .. }
165
166         try {
167                 LuaScriptInfoPtr lsi = LuaScripting::script_info (_script);
168                 LuaPluginInfoPtr lpi (new LuaPluginInfo (lsi));
169                 assert (lpi);
170                 set_info (lpi);
171                 _mempool.set_name ("LuaProc: " + lsi->name);
172                 _docs = lsi->description;
173         } catch (failed_constructor& err) {
174                 return true;
175         }
176
177         lua_State* L = lua.getState ();
178         lua.do_command (_script);
179
180         // check if script has a DSP callback
181         luabridge::LuaRef lua_dsp_run = luabridge::getGlobal (L, "dsp_run");
182         luabridge::LuaRef lua_dsp_map = luabridge::getGlobal (L, "dsp_runmap");
183
184         if ((lua_dsp_run.type () != LUA_TFUNCTION) == (lua_dsp_map.type () != LUA_TFUNCTION)) {
185                 return true;
186         }
187
188         if (lua_dsp_run.type () == LUA_TFUNCTION) {
189                 _lua_dsp = new luabridge::LuaRef (lua_dsp_run);
190         }
191         else if (lua_dsp_map.type () == LUA_TFUNCTION) {
192                 _lua_dsp = new luabridge::LuaRef (lua_dsp_map);
193                 _lua_does_channelmapping = true;
194         }
195         else {
196                 assert (0);
197         }
198
199         // initialize the DSP if needed
200         luabridge::LuaRef lua_dsp_init = luabridge::getGlobal (L, "dsp_init");
201         if (lua_dsp_init.type () == LUA_TFUNCTION) {
202                 try {
203                         lua_dsp_init (_session.nominal_frame_rate ());
204                 } catch (luabridge::LuaException const& e) {
205                         ;
206                 }
207         }
208
209         luabridge::LuaRef lua_dsp_midi_in = luabridge::getGlobal (L, "dsp_midi_input");
210         if (lua_dsp_midi_in.type () == LUA_TFUNCTION) {
211                 try {
212                         _has_midi_input = lua_dsp_midi_in ();
213                 } catch (luabridge::LuaException const& e) {
214                         ;
215                 }
216         }
217
218         _ctrl_params.clear ();
219
220         luabridge::LuaRef lua_render = luabridge::getGlobal (L, "render_inline");
221         if (lua_render.isFunction ()) {
222                 _lua_has_inline_display = true;
223         }
224
225         luabridge::LuaRef lua_params = luabridge::getGlobal (L, "dsp_params");
226         if (lua_params.isFunction ()) {
227
228                 // call function // add try {} catch (luabridge::LuaException const& e)
229                 luabridge::LuaRef params = lua_params ();
230
231                 if (params.isTable ()) {
232
233                         for (luabridge::Iterator i (params); !i.isNil (); ++i) {
234                                 // required fields
235                                 if (!i.key ().isNumber ())           { return false; }
236                                 if (!i.value ().isTable ())          { return false; }
237                                 if (!i.value ()["type"].isString ()) { return false; }
238                                 if (!i.value ()["name"].isString ()) { return false; }
239                                 if (!i.value ()["min"].isNumber ())  { return false; }
240                                 if (!i.value ()["max"].isNumber ())  { return false; }
241
242                                 int pn = i.key ().cast<int> ();
243                                 std::string type = i.value ()["type"].cast<std::string> ();
244                                 if (type == "input") {
245                                         if (!i.value ()["default"].isNumber ()) { return false; }
246                                         _ctrl_params.push_back (std::make_pair (false, pn));
247                                 }
248                                 else if (type == "output") {
249                                         _ctrl_params.push_back (std::make_pair (true, pn));
250                                 } else {
251                                         return false;
252                                 }
253                                 assert (pn == (int) _ctrl_params.size ());
254
255                                 //_param_desc[pn] = boost::shared_ptr<ParameterDescriptor> (new ParameterDescriptor());
256                                 luabridge::LuaRef lr = i.value ();
257
258                                 if (type == "input") {
259                                         _param_desc[pn].normal     = lr["default"].cast<float> ();
260                                 } else {
261                                         _param_desc[pn].normal     = lr["min"].cast<float> (); // output-port, no default
262                                 }
263                                 _param_desc[pn].lower        = lr["min"].cast<float> ();
264                                 _param_desc[pn].upper        = lr["max"].cast<float> ();
265                                 _param_desc[pn].toggled      = lr["toggled"].isBoolean () && (lr["toggled"]).cast<bool> ();
266                                 _param_desc[pn].logarithmic  = lr["logarithmic"].isBoolean () && (lr["logarithmic"]).cast<bool> ();
267                                 _param_desc[pn].integer_step = lr["integer"].isBoolean () && (lr["integer"]).cast<bool> ();
268                                 _param_desc[pn].sr_dependent = lr["ratemult"].isBoolean () && (lr["ratemult"]).cast<bool> ();
269                                 _param_desc[pn].enumeration  = lr["enum"].isBoolean () && (lr["enum"]).cast<bool> ();
270
271                                 if (lr["unit"].isString ()) {
272                                         std::string unit = lr["unit"].cast<std::string> ();
273                                         if (unit == "dB")             { _param_desc[pn].unit = ParameterDescriptor::DB; }
274                                         else if (unit == "Hz")        { _param_desc[pn].unit = ParameterDescriptor::HZ; }
275                                         else if (unit == "Midi Note") { _param_desc[pn].unit = ParameterDescriptor::MIDI_NOTE; }
276                                 }
277                                 _param_desc[pn].label        = (lr["name"]).cast<std::string> ();
278                                 _param_desc[pn].scale_points = parse_scale_points (&lr);
279
280                                 luabridge::LuaRef doc = lr["doc"];
281                                 if (doc.isString ()) {
282                                         _param_doc[pn] = doc.cast<std::string> ();
283                                 } else {
284                                         _param_doc[pn] = "";
285                                 }
286                                 assert (!(_param_desc[pn].toggled && _param_desc[pn].logarithmic));
287                         }
288                 }
289         }
290
291         _control_data = new float[parameter_count ()];
292         _shadow_data  = new float[parameter_count ()];
293
294         for (uint32_t i = 0; i < parameter_count (); ++i) {
295                 if (parameter_is_input (i)) {
296                         _control_data[i] = _shadow_data[i] = default_value (i);
297                 }
298         }
299
300         // expose ctrl-ports to global lua namespace
301         luabridge::push <float *> (L, _control_data);
302         lua_setglobal (L, "CtrlPorts");
303
304         return false; // no error
305 }
306
307 bool
308 LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out)
309 {
310         if (in.n_midi() > 0 && !_has_midi_input) {
311                 return false;
312         }
313
314         lua_State* L = lua.getState ();
315         luabridge::LuaRef ioconfig = luabridge::getGlobal (L, "dsp_ioconfig");
316         if (!ioconfig.isFunction ()) {
317                 return false;
318         }
319
320         luabridge::LuaRef table = luabridge::getGlobal (L, "table"); //lua std lib
321         luabridge::LuaRef tablesort = table["sort"];
322         assert (tablesort.isFunction ());
323
324         luabridge::LuaRef *_iotable = NULL; // can't use reference :(
325         try {
326                 luabridge::LuaRef iotable = ioconfig ();
327                 tablesort (iotable);
328                 if (iotable.isTable ()) {
329                         _iotable = new luabridge::LuaRef (iotable);
330                 }
331         } catch (luabridge::LuaException const& e) {
332                 return false;
333         }
334
335         if (!_iotable) {
336                 return false;
337         }
338
339         // now we can reference it.
340         luabridge::LuaRef iotable (*_iotable);
341         delete _iotable;
342
343         if ((iotable).length () < 1) {
344                 return false;
345         }
346
347         int32_t audio_in = in.n_audio ();
348         int32_t audio_out;
349
350         if (in.n_midi() > 0 && audio_in == 0) {
351                 audio_out = 2; // prefer stereo version if available.
352         } else {
353                 audio_out = audio_in;
354         }
355
356         for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
357                 assert (i.value ().type () == LUA_TTABLE);
358                 luabridge::LuaRef io (i.value ());
359
360                 int possible_in = io["audio_in"];
361                 int possible_out = io["audio_out"];
362
363                 // exact match
364                 if ((possible_in == audio_in) && (possible_out == audio_out)) {
365                         out.set (DataType::MIDI, 0);
366                         out.set (DataType::AUDIO, audio_out);
367                         return true;
368                 }
369         }
370
371         /* now allow potentially "imprecise" matches */
372         audio_out = -1;
373         bool found = false;
374
375         for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
376                 assert (i.value ().type () == LUA_TTABLE);
377                 luabridge::LuaRef io (i.value ());
378
379                 int possible_in = io["audio_in"];
380                 int possible_out = io["audio_out"];
381
382                 if (possible_out == 0) {
383                         continue;
384                 }
385                 if (possible_in == 0) {
386                         /* no inputs, generators & instruments */
387                         if (possible_out == -1) {
388                                 /* any configuration possible, provide stereo output */
389                                 audio_out = 2;
390                                 found = true;
391                         } else if (possible_out == -2) {
392                                 /* invalid, should be (0, -1) */
393                                 audio_out = 2;
394                                 found = true;
395                         } else if (possible_out < -2) {
396                                 /* variable number of outputs. -> whatever */
397                                 audio_out = 2;
398                                 found = true;
399                         } else {
400                                 /* exact number of outputs */
401                                 audio_out = possible_out;
402                                 found = true;
403                         }
404                 }
405
406                 if (possible_in == -1) {
407                         /* wildcard for input */
408                         if (possible_out == -1) {
409                                 /* out much match in */
410                                 audio_out = audio_in;
411                                 found = true;
412                         } else if (possible_out == -2) {
413                                 /* any configuration possible, pick matching */
414                                 audio_out = audio_in;
415                                 found = true;
416                         } else if (possible_out < -2) {
417                                 /* explicitly variable number of outputs, pick maximum */
418                                 audio_out = -possible_out;
419                                 found = true;
420                         } else {
421                                 /* exact number of outputs */
422                                 audio_out = possible_out;
423                                 found = true;
424                         }
425                 }
426
427                 if (possible_in == -2) {
428
429                         if (possible_out == -1) {
430                                 /* any configuration possible, pick matching */
431                                 audio_out = audio_in;
432                                 found = true;
433                         } else if (possible_out == -2) {
434                                 /* invalid. interpret as (-1, -1) */
435                                 audio_out = audio_in;
436                                 found = true;
437                         } else if (possible_out < -2) {
438                                 /* explicitly variable number of outputs, pick maximum */
439                                 audio_out = -possible_out;
440                                 found = true;
441                         } else {
442                                 /* exact number of outputs */
443                                 audio_out = possible_out;
444                                 found = true;
445                         }
446                 }
447
448                 if (possible_in < -2) {
449                         /* explicit variable number of inputs */
450                         if (audio_in > -possible_in) {
451                                 /* request is too large */
452                         }
453                         if (possible_out == -1) {
454                                 /* any output configuration possible, provide stereo out */
455                                 audio_out = 2;
456                                 found = true;
457                         } else if (possible_out == -2) {
458                                 /* invalid. interpret as (<-2, -1) */
459                                 audio_out = 2;
460                                 found = true;
461                         } else if (possible_out < -2) {
462                                 /* explicitly variable number of outputs, pick stereo */
463                                 audio_out = 2;
464                                 found = true;
465                         } else {
466                                 /* exact number of outputs */
467                                 audio_out = possible_out;
468                                 found = true;
469                         }
470                 }
471
472                 if (possible_in && (possible_in == audio_in)) {
473                         /* exact number of inputs ... must match obviously */
474                         if (possible_out == -1) {
475                                 /* any output configuration possible, provide stereo output */
476                                 audio_out = 2;
477                                 found = true;
478                         } else if (possible_out == -2) {
479                                 /* invalid. interpret as (>0, -1) */
480                                 audio_out = 2;
481                                 found = true;
482                         } else if (possible_out < -2) {
483                                 /* explicitly variable number of outputs, pick maximum */
484                                 audio_out = -possible_out;
485                                 found = true;
486                         } else {
487                                 /* exact number of outputs */
488                                 audio_out = possible_out;
489                                 found = true;
490                         }
491                 }
492
493                 if (found) {
494                         break;
495                 }
496         }
497
498         if (!found) {
499                 return false;
500         }
501
502         out.set (DataType::MIDI, 0);
503         out.set (DataType::AUDIO, audio_out);
504         return true;
505 }
506
507 bool
508 LuaProc::configure_io (ChanCount in, ChanCount out)
509 {
510         _configured_in = in;
511         _configured_out = out;
512
513         _configured_in.set (DataType::MIDI, _has_midi_input ? 1 : 0);
514         _configured_out.set (DataType::MIDI, _has_midi_output ? 1 : 0);
515
516         // configure the DSP if needed
517         lua_State* L = lua.getState ();
518         luabridge::LuaRef lua_dsp_configure = luabridge::getGlobal (L, "dsp_configure");
519         if (lua_dsp_configure.type () == LUA_TFUNCTION) {
520                 try {
521                         lua_dsp_configure (&in, &out);
522                 } catch (luabridge::LuaException const& e) {
523                         ;
524                 }
525         }
526
527         _info->n_inputs = _configured_in;
528         _info->n_outputs = _configured_out;
529         return true;
530 }
531
532 int
533 LuaProc::connect_and_run (BufferSet& bufs,
534                 ChanMapping in, ChanMapping out,
535                 pframes_t nframes, framecnt_t offset)
536 {
537         if (!_lua_dsp) {
538                 return 0;
539         }
540
541         Plugin::connect_and_run (bufs, in, out, nframes, offset);
542
543         // This is needed for ARDOUR::Session requests :(
544         if (! SessionEvent::has_per_thread_pool ()) {
545                 char name[64];
546                 snprintf (name, 64, "Proc-%p", this);
547                 pthread_set_name (name);
548                 SessionEvent::create_per_thread_pool (name, 64);
549                 PBD::notify_event_loops_about_thread_creation (pthread_self(), name, 64);
550         }
551
552         uint32_t const n = parameter_count ();
553         for (uint32_t i = 0; i < n; ++i) {
554                 if (parameter_is_control (i) && parameter_is_input (i)) {
555                         _control_data[i] = _shadow_data[i];
556                 }
557         }
558
559 #ifdef WITH_LUAPROC_STATS
560         int64_t t0 = g_get_monotonic_time ();
561 #endif
562
563         try {
564                 if (_lua_does_channelmapping) {
565                         // run the DSP function
566                         (*_lua_dsp)(&bufs, in, out, nframes, offset);
567                 } else {
568                         // map buffers
569                         BufferSet& silent_bufs  = _session.get_silent_buffers (ChanCount (DataType::AUDIO, 1));
570                         BufferSet& scratch_bufs = _session.get_scratch_buffers (ChanCount (DataType::AUDIO, 1));
571
572                         lua_State* L = lua.getState ();
573                         luabridge::LuaRef in_map (luabridge::newTable (L));
574                         luabridge::LuaRef out_map (luabridge::newTable (L));
575
576                         const uint32_t audio_in = _configured_in.n_audio ();
577                         const uint32_t audio_out = _configured_out.n_audio ();
578                         const uint32_t midi_in = _configured_in.n_midi ();
579
580                         for (uint32_t ap = 0; ap < audio_in; ++ap) {
581                                 bool valid;
582                                 const uint32_t buf_index = in.get(DataType::AUDIO, ap, &valid);
583                                 if (valid) {
584                                         in_map[ap + 1] = bufs.get_audio (buf_index).data (offset);
585                                 } else {
586                                         in_map[ap + 1] = silent_bufs.get_audio (0).data (offset);
587                                 }
588                         }
589                         for (uint32_t ap = 0; ap < audio_out; ++ap) {
590                                 bool valid;
591                                 const uint32_t buf_index = out.get(DataType::AUDIO, ap, &valid);
592                                 if (valid) {
593                                         out_map[ap + 1] = bufs.get_audio (buf_index).data (offset);
594                                 } else {
595                                         out_map[ap + 1] = scratch_bufs.get_audio (0).data (offset);
596                                 }
597                         }
598
599                         luabridge::LuaRef lua_midi_tbl (luabridge::newTable (L));
600                         int e = 1; // > 1 port, we merge events (unsorted)
601                         for (uint32_t mp = 0; mp < midi_in; ++mp) {
602                                 bool valid;
603                                 const uint32_t idx = in.get(DataType::MIDI, mp, &valid);
604                                 if (valid) {
605                                         for (MidiBuffer::iterator m = bufs.get_midi(idx).begin();
606                                                         m != bufs.get_midi(idx).end(); ++m, ++e) {
607                                                 const Evoral::MIDIEvent<framepos_t> ev(*m, false);
608                                                 luabridge::LuaRef lua_midi_data (luabridge::newTable (L));
609                                                 const uint8_t* data = ev.buffer();
610                                                 for (uint32_t i = 0; i < ev.size(); ++i) {
611                                                         lua_midi_data [i + 1] = data[i];
612                                                 }
613                                                 luabridge::LuaRef lua_midi_event (luabridge::newTable (L));
614                                                 lua_midi_event["time"] = 1 + (*m).time();
615                                                 lua_midi_event["data"] = lua_midi_data;
616                                                 lua_midi_tbl[e] = lua_midi_event;
617                                         }
618                                 }
619                         }
620
621                         if (_has_midi_input) {
622                                 // XXX TODO This needs a better solution than global namespace
623                                 luabridge::push (L, lua_midi_tbl);
624                                 lua_setglobal (L, "mididata");
625                         }
626
627
628                         // run the DSP function
629                         (*_lua_dsp)(in_map, out_map, nframes);
630                 }
631         } catch (luabridge::LuaException const& e) {
632 #ifndef NDEBUG
633                 printf ("LuaException: %s\n", e.what ());
634 #endif
635                 return -1;
636         }
637 #ifdef WITH_LUAPROC_STATS
638         int64_t t1 = g_get_monotonic_time ();
639 #endif
640         lua.collect_garbage (); // rt-safe, slight *regular* performance overhead
641 #ifdef WITH_LUAPROC_STATS
642         ++_stats_cnt;
643         int64_t t2 = g_get_monotonic_time ();
644         int64_t ela0 = t1 - t0;
645         int64_t ela1 = t2 - t1;
646         if (ela0 > _stats_max[0]) _stats_max[0] = ela0;
647         if (ela1 > _stats_max[1]) _stats_max[1] = ela1;
648         _stats_avg[0] += ela0;
649         _stats_avg[1] += ela1;
650 #endif
651         return 0;
652 }
653
654
655 void
656 LuaProc::add_state (XMLNode* root) const
657 {
658         XMLNode*    child;
659         char        buf[32];
660         LocaleGuard lg(X_("C"));
661
662         gchar* b64 = g_base64_encode ((const guchar*)_script.c_str (), _script.size ());
663         std::string b64s (b64);
664         g_free (b64);
665         XMLNode* script_node = new XMLNode (X_("script"));
666         script_node->add_property (X_("lua"), LUA_VERSION);
667         script_node->add_content (b64s);
668         root->add_child_nocopy (*script_node);
669
670         for (uint32_t i = 0; i < parameter_count(); ++i) {
671                 if (parameter_is_input(i) && parameter_is_control(i)) {
672                         child = new XMLNode("Port");
673                         snprintf(buf, sizeof(buf), "%u", i);
674                         child->add_property("id", std::string(buf));
675                         snprintf(buf, sizeof(buf), "%+f", _shadow_data[i]);
676                         child->add_property("value", std::string(buf));
677                         root->add_child_nocopy(*child);
678                 }
679         }
680 }
681
682 int
683 LuaProc::set_script_from_state (const XMLNode& node)
684 {
685         XMLNode* child;
686         if (node.name () != state_node_name ()) {
687                 return -1;
688         }
689
690         if ((child = node.child (X_("script"))) != 0) {
691                 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
692                         if (!(*n)->is_content ()) { continue; }
693                         gsize size;
694                         guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
695                         _script = std::string ((const char*)buf, size);
696                         g_free (buf);
697                         if (load_script ()) {
698                                 PBD::error << _("Failed to load Lua script from session state.") << endmsg;
699 #ifndef NDEBUG
700                                 std::cerr << "Failed Lua Script: " << _script << std::endl;
701 #endif
702                                 _script = "";
703                         }
704                         break;
705                 }
706         }
707         if (_script.empty ()) {
708                 PBD::error << _("Session State for LuaProcessor did not include a Lua script.") << endmsg;
709                 return -1;
710         }
711         if (!_lua_dsp) {
712                 PBD::error << _("Invalid/incompatible Lua script found for LuaProcessor.") << endmsg;
713                 return -1;
714         }
715         return 0;
716 }
717
718 int
719 LuaProc::set_state (const XMLNode& node, int version)
720 {
721 #ifndef NO_PLUGIN_STATE
722         XMLNodeList nodes;
723         XMLProperty *prop;
724         XMLNodeConstIterator iter;
725         XMLNode *child;
726         const char *value;
727         const char *port;
728         uint32_t port_id;
729 #endif
730         LocaleGuard lg (X_("C"));
731
732         if (_script.empty ()) {
733                 if (set_script_from_state (node)) {
734                         return -1;
735                 }
736         }
737
738 #ifndef NO_PLUGIN_STATE
739         if (node.name() != state_node_name()) {
740                 error << _("Bad node sent to LuaProc::set_state") << endmsg;
741                 return -1;
742         }
743
744         nodes = node.children ("Port");
745         for (iter = nodes.begin(); iter != nodes.end(); ++iter) {
746                 child = *iter;
747                 if ((prop = child->property("id")) != 0) {
748                         port = prop->value().c_str();
749                 } else {
750                         warning << _("LuaProc: port has no symbol, ignored") << endmsg;
751                         continue;
752                 }
753                 if ((prop = child->property("value")) != 0) {
754                         value = prop->value().c_str();
755                 } else {
756                         warning << _("LuaProc: port has no value, ignored") << endmsg;
757                         continue;
758                 }
759                 sscanf (port, "%" PRIu32, &port_id);
760                 set_parameter (port_id, atof(value));
761         }
762 #endif
763
764         return Plugin::set_state (node, version);
765 }
766
767 uint32_t
768 LuaProc::parameter_count () const
769 {
770         return _ctrl_params.size ();
771 }
772
773 float
774 LuaProc::default_value (uint32_t port)
775 {
776         if (_ctrl_params[port].first) {
777                 assert (0);
778                 return 0;
779         }
780         int lp = _ctrl_params[port].second;
781         return _param_desc[lp].normal;
782 }
783
784 void
785 LuaProc::set_parameter (uint32_t port, float val)
786 {
787         assert (port < parameter_count ());
788         if (get_parameter (port) == val) {
789                 return;
790         }
791         _shadow_data[port] = val;
792         Plugin::set_parameter (port, val);
793 }
794
795 float
796 LuaProc::get_parameter (uint32_t port) const
797 {
798         if (parameter_is_input (port)) {
799                 return _shadow_data[port];
800         } else {
801                 return _control_data[port];
802         }
803 }
804
805 int
806 LuaProc::get_parameter_descriptor (uint32_t port, ParameterDescriptor& desc) const
807 {
808         assert (port <= parameter_count ());
809         int lp = _ctrl_params[port].second;
810         const ParameterDescriptor& d (_param_desc.find(lp)->second);
811
812         desc.lower        = d.lower;
813         desc.upper        = d.upper;
814         desc.normal       = d.normal;
815         desc.toggled      = d.toggled;
816         desc.logarithmic  = d.logarithmic;
817         desc.integer_step = d.integer_step;
818         desc.sr_dependent = d.sr_dependent;
819         desc.enumeration  = d.enumeration;
820         desc.unit         = d.unit;
821         desc.label        = d.label;
822         desc.scale_points = d.scale_points;
823
824         desc.update_steps ();
825         return 0;
826 }
827
828 std::string
829 LuaProc::get_parameter_docs (uint32_t port) const {
830         assert (port <= parameter_count ());
831         int lp = _ctrl_params[port].second;
832         return _param_doc.find(lp)->second;
833 }
834
835 uint32_t
836 LuaProc::nth_parameter (uint32_t port, bool& ok) const
837 {
838         if (port < _ctrl_params.size ()) {
839                 ok = true;
840                 return port;
841         }
842         ok = false;
843         return 0;
844 }
845
846 bool
847 LuaProc::parameter_is_input (uint32_t port) const
848 {
849         assert (port < _ctrl_params.size ());
850         return (!_ctrl_params[port].first);
851 }
852
853 bool
854 LuaProc::parameter_is_output (uint32_t port) const
855 {
856         assert (port < _ctrl_params.size ());
857         return (_ctrl_params[port].first);
858 }
859
860 std::set<Evoral::Parameter>
861 LuaProc::automatable () const
862 {
863         std::set<Evoral::Parameter> automatables;
864         for (uint32_t i = 0; i < _ctrl_params.size (); ++i) {
865                 if (parameter_is_input (i)) {
866                         automatables.insert (automatables.end (), Evoral::Parameter (PluginAutomation, 0, i));
867                 }
868         }
869         return automatables;
870 }
871
872 std::string
873 LuaProc::describe_parameter (Evoral::Parameter param)
874 {
875         if (param.type () == PluginAutomation && param.id () < parameter_count ()) {
876                 int lp = _ctrl_params[param.id ()].second;
877                 return _param_desc[lp].label;
878         }
879         return "??";
880 }
881
882 void
883 LuaProc::print_parameter (uint32_t param, char* buf, uint32_t len) const
884 {
885         if (buf && len) {
886                 if (param < parameter_count ()) {
887                         snprintf (buf, len, "%.3f", get_parameter (param));
888                 } else {
889                         strcat (buf, "0");
890                 }
891         }
892 }
893
894 boost::shared_ptr<ScalePoints>
895 LuaProc::parse_scale_points (luabridge::LuaRef* lr)
896 {
897         if (!(*lr)["scalepoints"].isTable()) {
898                 return boost::shared_ptr<ScalePoints> ();
899         }
900
901         int cnt = 0;
902         boost::shared_ptr<ScalePoints> rv = boost::shared_ptr<ScalePoints>(new ScalePoints());
903         luabridge::LuaRef scalepoints ((*lr)["scalepoints"]);
904
905         for (luabridge::Iterator i (scalepoints); !i.isNil (); ++i) {
906                 if (!i.key ().isString ())    { continue; }
907                 if (!i.value ().isNumber ())  { continue; }
908                 rv->insert(make_pair(i.key ().cast<std::string> (),
909                                         i.value ().cast<float> ()));
910                 ++cnt;
911         }
912
913         if (rv->size() > 0) {
914                 return rv;
915         }
916         return boost::shared_ptr<ScalePoints> ();
917 }
918
919 boost::shared_ptr<ScalePoints>
920 LuaProc::get_scale_points (uint32_t port) const
921 {
922         int lp = _ctrl_params[port].second;
923         return _param_desc.find(lp)->second.scale_points;
924 }
925
926 void
927 LuaProc::setup_lua_inline_gui (LuaState *lua_gui)
928 {
929         lua_State* LG = lua_gui->getState ();
930         LuaBindings::stddef (LG);
931         LuaBindings::common (LG);
932         LuaBindings::dsp (LG);
933
934 #ifndef NDEBUG
935         lua_gui->Print.connect (sigc::mem_fun (*this, &LuaProc::lua_print));
936 #endif
937
938         lua_gui->do_command ("function ardour () end");
939         lua_gui->do_command (_script);
940
941         // TODO think: use a weak-pointer here ?
942         // (the GUI itself uses a shared ptr to this plugin, so we should be good)
943         luabridge::getGlobalNamespace (LG)
944                 .beginNamespace ("Ardour")
945                 .beginClass <LuaProc> ("LuaProc")
946                 .addFunction ("shmem", &LuaProc::instance_shm)
947                 .endClass ()
948                 .endNamespace ();
949
950         luabridge::push <LuaProc *> (LG, this);
951         lua_setglobal (LG, "self");
952
953         luabridge::push <float *> (LG, _shadow_data);
954         lua_setglobal (LG, "CtrlPorts");
955 }
956
957 ////////////////////////////////////////////////////////////////////////////////
958 #include <glibmm/miscutils.h>
959 #include <glibmm/fileutils.h>
960
961 LuaPluginInfo::LuaPluginInfo (LuaScriptInfoPtr lsi) {
962         if (lsi->type != LuaScriptInfo::DSP) {
963                 throw failed_constructor ();
964         }
965
966         path = lsi->path;
967         name = lsi->name;
968         creator = lsi->author;
969         category = lsi->category;
970         unique_id = "luascript"; // the interpreter is not unique.
971
972         n_inputs.set (DataType::AUDIO, 1);
973         n_outputs.set (DataType::AUDIO, 1);
974         type = Lua;
975 }
976
977 PluginPtr
978 LuaPluginInfo::load (Session& session)
979 {
980         std::string script = "";
981         if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
982                 return PluginPtr ();
983         }
984
985         try {
986                 script = Glib::file_get_contents (path);
987         } catch (Glib::FileError err) {
988                 return PluginPtr ();
989         }
990
991         if (script.empty ()) {
992                 return PluginPtr ();
993         }
994
995         try {
996                 PluginPtr plugin (new LuaProc (session.engine (), session, script));
997                 return plugin;
998         } catch (failed_constructor& err) {
999                 ;
1000         }
1001         return PluginPtr ();
1002 }
1003
1004 std::vector<Plugin::PresetRecord>
1005 LuaPluginInfo::get_presets (bool /*user_only*/) const
1006 {
1007         std::vector<Plugin::PresetRecord> p;
1008         return p;
1009 }