cont'd work on Lua Vamp-plugin API
[ardour.git] / libs / ardour / lua_api.cc
1 /*
2  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  *
18  */
19 #include <cstring>
20 #include <vamp-hostsdk/PluginLoader.h>
21
22 #include "pbd/compose.h"
23 #include "pbd/error.h"
24 #include "pbd/failed_constructor.h"
25
26 #include "ardour/lua_api.h"
27 #include "ardour/luaproc.h"
28 #include "ardour/luascripting.h"
29 #include "ardour/plugin.h"
30 #include "ardour/plugin_insert.h"
31 #include "ardour/plugin_manager.h"
32 #include "ardour/readable.h"
33
34 #include "LuaBridge/LuaBridge.h"
35
36 #include "pbd/i18n.h"
37
38 using namespace ARDOUR;
39 using namespace PBD;
40 using namespace std;
41
42 int
43 ARDOUR::LuaAPI::datatype_ctor_null (lua_State *L)
44 {
45         DataType dt (DataType::NIL);
46         luabridge::Stack <DataType>::push (L, dt);
47         return 1;
48 }
49
50 int
51 ARDOUR::LuaAPI::datatype_ctor_audio (lua_State *L)
52 {
53         DataType dt (DataType::AUDIO);
54         // NB luabridge will copy construct the object and manage lifetime.
55         luabridge::Stack <DataType>::push (L, dt);
56         return 1;
57 }
58
59 int
60 ARDOUR::LuaAPI::datatype_ctor_midi (lua_State *L)
61 {
62         DataType dt (DataType::MIDI);
63         luabridge::Stack <DataType>::push (L, dt);
64         return 1;
65 }
66
67 boost::shared_ptr<Processor>
68 ARDOUR::LuaAPI::nil_processor ()
69 {
70         return boost::shared_ptr<Processor> ();
71 }
72
73 boost::shared_ptr<Processor>
74 ARDOUR::LuaAPI::new_luaproc (Session *s, const string& name)
75 {
76         if (!s) {
77                 return boost::shared_ptr<Processor> ();
78         }
79
80         LuaScriptInfoPtr spi;
81         ARDOUR::LuaScriptList & _scripts (LuaScripting::instance ().scripts (LuaScriptInfo::DSP));
82         for (LuaScriptList::const_iterator i = _scripts.begin (); i != _scripts.end (); ++i) {
83                 if (name == (*i)->name) {
84                         spi = *i;
85                         break;
86                 }
87         }
88
89         if (!spi) {
90                 warning << _("Script with given name was not found\n");
91                 return boost::shared_ptr<Processor> ();
92         }
93
94         PluginPtr p;
95         try {
96                 LuaPluginInfoPtr lpi (new LuaPluginInfo (spi));
97                 p = (lpi->load (*s));
98         } catch (...) {
99                 warning << _("Failed to instantiate Lua Processor\n");
100                 return boost::shared_ptr<Processor> ();
101         }
102
103         return boost::shared_ptr<Processor> (new PluginInsert (*s, p));
104 }
105
106 PluginInfoPtr
107 ARDOUR::LuaAPI::new_plugin_info (const string& name, ARDOUR::PluginType type)
108 {
109         PluginManager& manager = PluginManager::instance ();
110         PluginInfoList all_plugs;
111         all_plugs.insert (all_plugs.end (), manager.ladspa_plugin_info ().begin (), manager.ladspa_plugin_info ().end ());
112         all_plugs.insert (all_plugs.end (), manager.lua_plugin_info ().begin (), manager.lua_plugin_info ().end ());
113 #ifdef WINDOWS_VST_SUPPORT
114         all_plugs.insert (all_plugs.end (), manager.windows_vst_plugin_info ().begin (), manager.windows_vst_plugin_info ().end ());
115 #endif
116 #ifdef LXVST_SUPPORT
117         all_plugs.insert (all_plugs.end (), manager.lxvst_plugin_info ().begin (), manager.lxvst_plugin_info ().end ());
118 #endif
119 #ifdef AUDIOUNIT_SUPPORT
120         all_plugs.insert (all_plugs.end (), manager.au_plugin_info ().begin (), manager.au_plugin_info ().end ());
121 #endif
122 #ifdef LV2_SUPPORT
123         all_plugs.insert (all_plugs.end (), manager.lv2_plugin_info ().begin (), manager.lv2_plugin_info ().end ());
124 #endif
125
126         for (PluginInfoList::const_iterator i = all_plugs.begin (); i != all_plugs.end (); ++i) {
127                 if (((*i)->name == name || (*i)->unique_id == name) && (*i)->type == type) {
128                         return *i;
129                 }
130         }
131         return PluginInfoPtr ();
132 }
133
134 boost::shared_ptr<Processor>
135 ARDOUR::LuaAPI::new_plugin (Session *s, const string& name, ARDOUR::PluginType type, const string& preset)
136 {
137         if (!s) {
138                 return boost::shared_ptr<Processor> ();
139         }
140
141         PluginInfoPtr pip = new_plugin_info (name, type);
142
143         if (!pip) {
144                 return boost::shared_ptr<Processor> ();
145         }
146
147         PluginPtr p = pip->load (*s);
148         if (!p) {
149                 return boost::shared_ptr<Processor> ();
150         }
151
152         if (!preset.empty ()) {
153                 const Plugin::PresetRecord *pr = p->preset_by_label (preset);
154                 if (pr) {
155                         p->load_preset (*pr);
156                 }
157         }
158
159         return boost::shared_ptr<Processor> (new PluginInsert (*s, p));
160 }
161
162 bool
163 ARDOUR::LuaAPI::set_plugin_insert_param (boost::shared_ptr<PluginInsert> pi, uint32_t which, float val)
164 {
165         boost::shared_ptr<Plugin> plugin = pi->plugin ();
166         if (!plugin) { return false; }
167
168         bool ok=false;
169         uint32_t controlid = plugin->nth_parameter (which, ok);
170         if (!ok) { return false; }
171         if (!plugin->parameter_is_input (controlid)) { return false; }
172
173         ParameterDescriptor pd;
174         if (plugin->get_parameter_descriptor (controlid, pd) != 0) { return false; }
175         if (val < pd.lower || val > pd.upper) { return false; }
176
177         boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter (PluginAutomation, 0, controlid));
178         c->set_value (val, PBD::Controllable::NoGroup);
179         return true;
180 }
181
182 float
183 ARDOUR::LuaAPI::get_plugin_insert_param (boost::shared_ptr<PluginInsert> pi, uint32_t which, bool &ok)
184 {
185         ok=false;
186         boost::shared_ptr<Plugin> plugin = pi->plugin ();
187         if (!plugin) { return 0; }
188         uint32_t controlid = plugin->nth_parameter (which, ok);
189         if (!ok) { return 0; }
190         return plugin->get_parameter ( controlid );
191 }
192
193 bool
194 ARDOUR::LuaAPI::set_processor_param (boost::shared_ptr<Processor> proc, uint32_t which, float val)
195 {
196         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (proc);
197         if (!pi) { return false; }
198         return set_plugin_insert_param (pi, which, val);
199 }
200
201 float
202 ARDOUR::LuaAPI::get_processor_param (boost::shared_ptr<Processor> proc, uint32_t which, bool &ok)
203 {
204         ok=false;
205         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (proc);
206         if (!pi) { return false; }
207         return get_plugin_insert_param (pi, which, ok);
208 }
209
210 int
211 ARDOUR::LuaAPI::plugin_automation (lua_State *L)
212 {
213         typedef boost::shared_ptr<Processor> T;
214
215         int top = lua_gettop (L);
216         if (top < 2) {
217                 return luaL_argerror (L, 1, "invalid number of arguments, :plugin_automation (plugin, parameter_number)");
218         }
219         T* const p = luabridge::Userdata::get<T> (L, 1, false);
220         uint32_t which = luabridge::Stack<uint32_t>::get (L, 2);
221         if (!p) {
222                 return luaL_error (L, "Invalid pointer to Ardour:Processor");
223         }
224         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (*p);
225         if (!pi) {
226                 return luaL_error (L, "Given Processor is not a Plugin Insert");
227         }
228         boost::shared_ptr<Plugin> plugin = pi->plugin ();
229         if (!plugin) {
230                 return luaL_error (L, "Given Processor is not a Plugin");
231         }
232
233         bool ok=false;
234         uint32_t controlid = plugin->nth_parameter (which, ok);
235         if (!ok) {
236                 return luaL_error (L, "Invalid Parameter");
237         }
238         if (!plugin->parameter_is_input (controlid)) {
239                 return luaL_error (L, "Given Parameter is not an input");
240         }
241
242         ParameterDescriptor pd;
243         if (plugin->get_parameter_descriptor (controlid, pd) != 0) {
244                 return luaL_error (L, "Cannot describe parameter");
245         }
246
247         boost::shared_ptr<AutomationControl> c = pi->automation_control (Evoral::Parameter (PluginAutomation, 0, controlid));
248
249         luabridge::Stack<boost::shared_ptr<AutomationList> >::push (L, c->alist ());
250         luabridge::Stack<boost::shared_ptr<Evoral::ControlList> >::push (L, c->list ());
251         luabridge::Stack<ParameterDescriptor>::push (L, pd);
252         return 3;
253 }
254
255 int
256 ARDOUR::LuaOSC::Address::send (lua_State *L)
257 {
258         Address * const luaosc = luabridge::Userdata::get <Address> (L, 1, false);
259         if (!luaosc) {
260                 return luaL_error (L, "Invalid pointer to OSC.Address");
261         }
262         if (!luaosc->_addr) {
263                 return luaL_error (L, "Invalid Destination Address");
264         }
265
266         int top = lua_gettop (L);
267         if (top < 3) {
268                 return luaL_argerror (L, 1, "invalid number of arguments, :send (path, type, ...)");
269         }
270
271         const char* path = luaL_checkstring (L, 2);
272         const char* type = luaL_checkstring (L, 3);
273         assert (path && type);
274
275         if ((int) strlen (type) != top - 3) {
276                 return luaL_argerror (L, 3, "type description does not match arguments");
277         }
278
279         lo_message msg = lo_message_new ();
280
281         for (int i = 4; i <= top; ++i) {
282                 char t = type[i - 4];
283                 int lt = lua_type (L, i);
284                 int ok = -1;
285                 switch (lt) {
286                         case LUA_TSTRING:
287                                 if (t == LO_STRING) {
288                                         ok = lo_message_add_string (msg, luaL_checkstring (L, i));
289                                 } else if (t == LO_CHAR) {
290                                         char c = luaL_checkstring (L, i) [0];
291                                         ok = lo_message_add_char (msg, c);
292                                 }
293                                 break;
294                         case LUA_TBOOLEAN:
295                                 if (t == LO_TRUE || t == LO_FALSE) {
296                                         if (lua_toboolean (L, i)) {
297                                                 ok = lo_message_add_true (msg);
298                                         } else {
299                                                 ok = lo_message_add_false (msg);
300                                         }
301                                 }
302                                 break;
303                         case LUA_TNUMBER:
304                                 if (t == LO_INT32) {
305                                         ok = lo_message_add_int32 (msg, (int32_t) luaL_checkinteger (L, i));
306                                 }
307                                 else if (t == LO_FLOAT) {
308                                         ok = lo_message_add_float (msg, (float) luaL_checknumber (L, i));
309                                 }
310                                 else if (t == LO_DOUBLE) {
311                                         ok = lo_message_add_double (msg, (double) luaL_checknumber (L, i));
312                                 }
313                                 else if (t == LO_INT64) {
314                                         ok = lo_message_add_double (msg, (int64_t) luaL_checknumber (L, i));
315                                 }
316                                 break;
317                         default:
318                                 break;
319                 }
320                 if (ok != 0) {
321                         return luaL_argerror (L, i, "type description does not match parameter");
322                 }
323         }
324
325         int rv = lo_send_message (luaosc->_addr, path, msg);
326         lo_message_free (msg);
327         luabridge::Stack<bool>::push (L, (rv == 0));
328         return 1;
329 }
330
331 static double hue2rgb (const double p, const double q, double t) {
332         if (t < 0.0) t += 1.0;
333         if (t > 1.0) t -= 1.0;
334         if (t < 1.0 / 6.0) return p + (q - p) * 6.0 * t;
335         if (t < 1.0 / 2.0) return q;
336         if (t < 2.0 / 3.0) return p + (q - p) * (2.0 / 3.0 - t) * 6.0;
337         return p;
338 }
339
340 int
341 ARDOUR::LuaAPI::hsla_to_rgba (lua_State *L)
342 {
343         int top = lua_gettop (L);
344         if (top < 3) {
345                 return luaL_argerror (L, 1, "invalid number of arguments, :hsla_to_rgba (h, s, l [,a])");
346         }
347         double h = luabridge::Stack<double>::get (L, 1);
348         double s = luabridge::Stack<double>::get (L, 2);
349         double l = luabridge::Stack<double>::get (L, 3);
350         double a = 1.0;
351         if (top > 3) {
352                 a = luabridge::Stack<double>::get (L, 4);
353         }
354
355         // we can't use ArdourCanvas::hsva_to_color here
356         // besides we want HSL not HSV and without intermediate
357         // color_to_rgba (rgba_to_color ())
358         double r, g, b;
359         const double cq = l < 0.5 ? l * (1 + s) : l + s - l * s;
360         const double cp = 2.f * l - cq;
361         r = hue2rgb (cp, cq, h + 1.0 / 3.0);
362         g = hue2rgb (cp, cq, h);
363         b = hue2rgb (cp, cq, h - 1.0 / 3.0);
364
365         luabridge::Stack<double>::push (L, r);
366         luabridge::Stack<double>::push (L, g);
367         luabridge::Stack<double>::push (L, b);
368         luabridge::Stack<double>::push (L, a);
369         return 4;
370 }
371
372 int
373 ARDOUR::LuaAPI::build_filename (lua_State *L)
374 {
375         std::vector<std::string> elem;
376         int top = lua_gettop (L);
377         if (top < 1) {
378                 return luaL_argerror (L, 1, "invalid number of arguments, build_filename (path, ...)");
379         }
380         for (int i = 1; i <= top; ++i) {
381                 int lt = lua_type (L, i);
382                 if (lt != LUA_TSTRING) {
383                         return luaL_argerror (L, i, "invalid argument type, expected string");
384                 }
385                 elem.push_back (luaL_checkstring (L, i));
386         }
387
388         luabridge::Stack<std::string>::push (L, Glib::build_filename (elem));
389         return 1;
390 }
391
392 luabridge::LuaRef::Proxy&
393 luabridge::LuaRef::Proxy::clone_instance (const void* classkey, void* p) {
394         lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
395         lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
396
397         luabridge::UserdataPtr::push_raw (m_L, p, classkey);
398
399         lua_rawset (m_L, -3);
400         lua_pop (m_L, 1);
401         return *this;
402 }
403
404 LuaTableRef::LuaTableRef () {}
405 LuaTableRef::~LuaTableRef () {}
406
407 int
408 LuaTableRef::get (lua_State* L)
409 {
410         luabridge::LuaRef rv (luabridge::newTable (L));
411         for (std::vector<LuaTableEntry>::const_iterator i = _data.begin (); i != _data.end (); ++i) {
412                 switch ((*i).keytype) {
413                         case LUA_TSTRING:
414                                 assign (&rv, i->k_s, *i);
415                                 break;
416                         case LUA_TNUMBER:
417                                 assign (&rv, i->k_n, *i);
418                                 break;
419                 }
420         }
421         luabridge::push (L, rv);
422         return 1;
423 }
424
425 int
426 LuaTableRef::set (lua_State* L)
427 {
428         if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
429         _data.clear ();
430
431         lua_pushvalue (L, -1);
432         lua_pushnil (L);
433         while (lua_next (L, -2)) {
434                 lua_pushvalue (L, -2);
435
436                 LuaTableEntry s (lua_type (L, -1), lua_type (L, -2));
437                 switch (lua_type (L, -1)) {
438                         case LUA_TSTRING:
439                                 s.k_s = luabridge::Stack<std::string>::get (L, -1);
440                                 break;
441                                 ;
442                         case LUA_TNUMBER:
443                                 s.k_n = luabridge::Stack<unsigned int>::get (L, -1);
444                                 break;
445                         default:
446                                 // invalid key
447                                 lua_pop (L, 2);
448                                 continue;
449                 }
450
451                 switch (lua_type (L, -2)) {
452                         case LUA_TSTRING:
453                                 s.s = luabridge::Stack<std::string>::get (L, -2);
454                                 break;
455                         case LUA_TBOOLEAN:
456                                 s.b = lua_toboolean (L, -2);
457                                 break;
458                         case LUA_TNUMBER:
459                                 s.n = lua_tonumber (L, -2);
460                                 break;
461                         case LUA_TUSERDATA:
462                                 {
463                                         bool ok = false;
464                                         lua_getmetatable (L, -2);
465                                         lua_rawgetp (L, -1, luabridge::getIdentityKey ());
466                                         if (lua_isboolean (L, -1)) {
467                                                 lua_pop (L, 1);
468                                                 const void* key = lua_topointer (L, -1);
469                                                 lua_pop (L, 1);
470                                                 void const* classkey = findclasskey (L, key);
471
472                                                 if (classkey) {
473                                                         ok = true;
474                                                         s.c = classkey;
475                                                         s.p = luabridge::Userdata::get_ptr (L, -2);
476                                                 }
477                                         } else {
478                                                 lua_pop (L, 2);
479                                         }
480
481                                         if (ok) {
482                                                 break;
483                                         }
484                                         // invalid userdata -- fall through
485                                 }
486                                 // no break
487                         case LUA_TFUNCTION: // no support -- we could... string.format("%q", string.dump(value, true))
488                         case LUA_TTABLE: // no nested tables, sorry.
489                         case LUA_TNIL: // fallthrough
490                         default:
491                                 // invalid value
492                                 lua_pop (L, 2);
493                                 continue;
494                 }
495
496                 _data.push_back (s);
497                 lua_pop (L, 2);
498         }
499         return 0;
500 }
501
502 void*
503 LuaTableRef::findclasskey (lua_State *L, const void* key)
504 {
505         lua_pushvalue (L, LUA_REGISTRYINDEX);
506         lua_pushnil (L);
507         while (lua_next (L, -2)) {
508                 lua_pushvalue (L, -2);
509                 if (lua_topointer (L, -2) == key) {
510                         void* rv = lua_touserdata (L, -1);
511                         lua_pop (L, 4);
512                         return rv;
513                 }
514                 lua_pop (L, 2);
515         }
516         lua_pop (L, 1);
517         return NULL;
518 }
519
520 template<typename T>
521 void LuaTableRef::assign (luabridge::LuaRef* rv, T key, const LuaTableEntry& s)
522 {
523         switch (s.valuetype) {
524                 case LUA_TSTRING:
525                         (*rv)[key] = s.s;
526                         break;
527                 case LUA_TBOOLEAN:
528                         (*rv)[key] = s.b;
529                         break;
530                 case LUA_TNUMBER:
531                         (*rv)[key] = s.n;
532                         break;
533                 case LUA_TUSERDATA:
534                         (*rv)[key].clone_instance (s.c, s.p);
535                         break;
536                 default:
537                         assert (0);
538                         break;
539         }
540 }
541
542
543 LuaAPI::Vamp::Vamp (const std::string& key, float sample_rate)
544         : _plugin (0)
545         , _sample_rate (sample_rate)
546         , _bufsize (1024)
547         , _stepsize (512)
548         , _initialized (false)
549 {
550         using namespace ::Vamp::HostExt;
551
552         PluginLoader* loader (PluginLoader::getInstance());
553         _plugin = loader->loadPlugin (key, _sample_rate, PluginLoader::ADAPT_ALL_SAFE);
554
555         if (!_plugin) {
556                 PBD::error << string_compose (_("VAMP Plugin \"%1\" could not be loaded"), key) << endmsg;
557                 throw failed_constructor ();
558         }
559 }
560
561 LuaAPI::Vamp::~Vamp ()
562 {
563         delete _plugin;
564 }
565
566 void
567 LuaAPI::Vamp::reset ()
568 {
569         _initialized = false;
570         if (_plugin) {
571                 _plugin->reset ();
572         }
573 }
574
575 bool
576 LuaAPI::Vamp::initialize ()
577 {
578         if (!_plugin || _plugin->getMinChannelCount() > 1) {
579                 return false;
580         }
581         if (!_plugin->initialise (1, _stepsize, _bufsize)) {
582                 return false;
583         }
584         _initialized = true;
585         return true;
586 }
587
588 int
589 LuaAPI::Vamp::analyze (boost::shared_ptr<ARDOUR::Readable> r, uint32_t channel, luabridge::LuaRef cb)
590 {
591         if (!_initialized) {
592                 if (!initialize ()) {
593                         return -1;
594                 }
595         }
596         assert (_initialized);
597
598         ::Vamp::Plugin::FeatureSet features;
599         float* data = new float[_bufsize];
600         float* bufs[1] = { data };
601
602         framecnt_t len = r->readable_length();
603         framepos_t pos = 0;
604
605         int rv = 0;
606         while (1) {
607                 framecnt_t to_read = std::min ((len - pos), _bufsize);
608                 if (r->read (data, pos, to_read, channel) != to_read) {
609                         rv = -1;
610                         break;
611                 }
612                 if (to_read != _bufsize) {
613                         memset (data + to_read, 0, (_bufsize - to_read) * sizeof (float));
614                 }
615
616                 features = _plugin->process (bufs, ::Vamp::RealTime::fromSeconds ((double) pos / _sample_rate));
617
618                 if (cb.type () == LUA_TFUNCTION) {
619                         cb (&features, pos);
620                 }
621
622                 pos += std::min (_stepsize, to_read);
623
624                 if (pos >= len) {
625                         break;
626                 }
627         }
628
629         delete [] data;
630         return rv;
631 }