1 /*
2  * Copyright (C) 2016-2019 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (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 along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 /* print runtime and garbage-collection timing statistics */
20 //#define WITH_LUAPROC_STATS
21 
22 /* memory allocation system, default: ReallocPool */
23 //#define USE_TLSF // use TLSF instead of ReallocPool
24 //#define USE_MALLOC // or plain OS provided realloc (no mlock) -- if USE_TLSF isn't defined
25 
26 #ifndef __ardour_luaproc_h__
27 #define __ardour_luaproc_h__
28 
29 #include <set>
30 #include <vector>
31 #include <string>
32 
33 #define USE_TLSF
34 #ifdef USE_TLSF
35 #  include "pbd/tlsf.h"
36 #else
37 #  include "pbd/reallocpool.h"
38 #endif
39 
40 #include "pbd/stateful.h"
41 
42 #include "ardour/types.h"
43 #include "ardour/plugin.h"
44 #include "ardour/luascripting.h"
45 #include "ardour/dsp_filter.h"
46 #include "ardour/lua_api.h"
47 
48 #include "lua/luastate.h"
49 
50 namespace luabridge {
51 	class LuaRef;
52 }
53 
54 namespace ARDOUR {
55 
56 class LIBARDOUR_API LuaProc : public ARDOUR::Plugin {
57 public:
58 	LuaProc (AudioEngine&, Session&, const std::string&);
59 	LuaProc (const LuaProc &);
60 	~LuaProc ();
61 
62 	/* Plugin interface */
63 
unique_id()64 	std::string unique_id() const { return get_info()->unique_id; }
name()65 	const char* name()  const { return get_info()->name.c_str(); }
label()66 	const char* label() const { return get_info()->name.c_str(); }
maker()67 	const char* maker() const { return get_info()->creator.c_str(); }
68 
69 	uint32_t    parameter_count() const;
70 	float       default_value (uint32_t port);
71 	void        set_parameter (uint32_t port, float val, sampleoffset_t);
72 	float       get_parameter (uint32_t port) const;
73 	int         get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
74 	uint32_t    nth_parameter (uint32_t port, bool& ok) const;
75 
get_docs()76 	std::string get_docs () const { return _docs; }
77 	std::string get_parameter_docs (uint32_t) const;
78 
possible_output()79 	PluginOutputConfiguration possible_output () const { return _output_configs; }
80 
81 	void drop_references ();
82 
83 	std::set<Evoral::Parameter> automatable() const;
84 
activate()85 	void activate () { }
deactivate()86 	void deactivate () { }
cleanup()87 	void cleanup () { }
88 
set_block_size(pframes_t)89 	int set_block_size (pframes_t /*nframes*/) { return 0; }
connect_all_audio_outputs()90 	bool connect_all_audio_outputs () const { return _connect_all_audio_outputs; }
91 
92 	int connect_and_run (BufferSet& bufs,
93 			samplepos_t start, samplepos_t end, double speed,
94 			ChanMapping const& in, ChanMapping const& out,
95 			pframes_t nframes, samplecnt_t offset);
96 
97 	std::string describe_parameter (Evoral::Parameter);
98 	boost::shared_ptr<ScalePoints> get_scale_points(uint32_t port_index) const;
99 
parameter_is_audio(uint32_t)100 	bool parameter_is_audio (uint32_t) const { return false; }
parameter_is_control(uint32_t)101 	bool parameter_is_control (uint32_t) const { return true; }
102 	bool parameter_is_input (uint32_t) const;
103 	bool parameter_is_output (uint32_t) const;
104 
designated_bypass_port()105 	uint32_t designated_bypass_port () {
106 		return _designated_bypass_port;
107 	}
108 
state_node_name()109 	std::string state_node_name() const { return "luaproc"; }
110 	void add_state (XMLNode *) const;
111 	int set_state (const XMLNode&, int version);
112 	int set_script_from_state (const XMLNode&);
113 
114 	bool load_preset (PresetRecord);
115 	std::string do_save_preset (std::string);
116 	void do_remove_preset (std::string);
117 
has_editor()118 	bool has_editor() const { return false; }
119 
120 	bool match_variable_io (ChanCount& in, ChanCount& aux_in, ChanCount& out);
121 	bool reconfigure_io (ChanCount in, ChanCount aux_in, ChanCount out);
122 
output_streams()123 	ChanCount output_streams() const { return _configured_out; }
input_streams()124 	ChanCount input_streams() const { return _configured_in; }
125 
has_inline_display()126 	bool has_inline_display () { return _lua_has_inline_display; }
127 	void setup_lua_inline_gui (LuaState *lua_gui);
128 
instance_shm()129 	DSP::DspShm* instance_shm () { return &lshm; }
instance_ref()130 	LuaTableRef* instance_ref () { return &lref; }
131 
132 private:
plugin_latency()133 	samplecnt_t plugin_latency() const { return _signal_latency; }
134 	void find_presets ();
135 
136 	/* END Plugin interface */
137 
138 public:
set_origin(std::string & path)139 	void set_origin (std::string& path) { _origin = path; }
140 
141 protected:
script()142 	const std::string& script() const { return _script; }
origin()143 	const std::string& origin() const { return _origin; }
144 
145 private:
146 #ifdef USE_TLSF
147 	PBD::TLSF _mempool;
148 #else
149 	PBD::ReallocPool _mempool;
150 #endif
151 	LuaState lua;
152 	luabridge::LuaRef * _lua_dsp;
153 	luabridge::LuaRef * _lua_latency;
154 	std::string _script;
155 	std::string _origin;
156 	std::string _docs;
157 	bool _lua_does_channelmapping;
158 	bool _lua_has_inline_display;
159 	bool _connect_all_audio_outputs;
160 
queue_draw()161 	void queue_draw () { QueueDraw(); /* EMIT SIGNAL */ }
162 	DSP::DspShm lshm;
163 
164 	LuaTableRef lref;
165 
166 	boost::weak_ptr<Route> route () const;
167 
168 	void init ();
169 	bool load_script ();
170 	void lua_print (std::string s);
171 
172 	std::string preset_name_to_uri (const std::string&) const;
173 	std::string presets_file () const;
174 	XMLTree* presets_tree () const;
175 
176 	boost::shared_ptr<ScalePoints> parse_scale_points (luabridge::LuaRef*);
177 
178 	std::vector<std::pair<bool, int> > _ctrl_params;
179 	std::map<int, ARDOUR::ParameterDescriptor> _param_desc;
180 	std::map<int, std::string> _param_doc;
181 	uint32_t _designated_bypass_port;
182 
183 	samplecnt_t _signal_latency;
184 
185 	float* _control_data;
186 	float* _shadow_data;
187 
188 	ChanCount _configured_in;
189 	ChanCount _configured_out;
190 
191 	bool      _configured;
192 
193 	ChanCount _selected_in;
194 	ChanCount _selected_out;
195 
196 	PluginOutputConfiguration _output_configs;
197 
198 	bool _has_midi_input;
199 	bool _has_midi_output;
200 
201 
202 #ifdef WITH_LUAPROC_STATS
203 	int64_t _stats_avg[2];
204 	int64_t _stats_max[2];
205 	int64_t _stats_cnt;
206 #endif
207 };
208 
209 class LIBARDOUR_API LuaPluginInfo : public PluginInfo
210 {
211   public:
212 	LuaPluginInfo (LuaScriptInfoPtr lsi);
~LuaPluginInfo()213 	~LuaPluginInfo () { };
214 
215 	PluginPtr load (Session& session);
216 	std::vector<Plugin::PresetRecord> get_presets (bool user_only) const;
217 
reconfigurable_io()218 	bool reconfigurable_io() const { return true; }
max_configurable_ouputs()219 	uint32_t max_configurable_ouputs () const {
220 		return _max_outputs;
221 	}
222 
223 	private:
224 	uint32_t _max_outputs;
225 };
226 
227 typedef boost::shared_ptr<LuaPluginInfo> LuaPluginInfoPtr;
228 
229 } // namespace ARDOUR
230 
231 #endif // __ardour_luaproc_h__
232