Guitarix
gx_modulesequencer.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3 * Copyright (C) 2011 Pete Shorthose
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * --------------------------------------------------------------------------
19 */
20
21#pragma once
22
23namespace gx_engine {
24
25/****************************************************************
26 ** class ModuleSelector
27 */
28
30protected:
32public:
34 : seq(seq_) {}
35 virtual ~ModuleSelector() {}
36 virtual void set_module() = 0;
37};
38
39
40/****************************************************************
41 ** class ProcessingChainBase
42 ** members and methods accessed by the rt thread are marked RT
43 */
44
46public:
48private:
49 sem_t sync_sem; // RT
50 list<Plugin*> to_release;
51 int ramp_value; // RT
52 int ramp_mode; // RT should be RampMode, but gcc 4.5 doesn't accept it for g_atomic_int_compare_and_exchange
53 volatile bool stopped;
54protected:
55 int steps_up; // RT; >= 1
56 int steps_up_dead; // RT; >= 0
57 int steps_down; // RT; >= 1
58 list<Plugin*> modules;
59 inline void set_ramp_value(int n) { gx_system::atomic_set(&ramp_value, n); } // RT
61 void try_set_ramp_mode(RampMode oldmode, RampMode newmode, int oldrv, int newrv); // RT
62public:
66 return static_cast<RampMode>(gx_system::atomic_get(ramp_mode)); // RT
67 }
68 inline int get_ramp_value() { return gx_system::atomic_get(ramp_value); } // RT
69 void set_samplerate(int samplerate);
70 bool set_plugin_list(const list<Plugin*> &p);
72 inline void post_rt_finished() { // RT
73 int val;
74 sem_getvalue(&sync_sem, &val);
75 if (val == 0) {
76 sem_post(&sync_sem);
77 }
78 }
80 void set_latch();
82 void sync() { set_latch(); wait_latch(); }
83 inline bool check_release() { return !to_release.empty(); }
84 void release();
89 inline bool is_down_dead() { return get_ramp_mode() == ramp_mode_down_dead; }
90 void set_stopped(bool v);
91 bool is_stopped() { return stopped; }
92#ifndef NDEBUG
93 void print_chain_state(const char *title);
94#endif
95};
96
97
98/****************************************************************
99 ** template class ThreadSafeChainPointer
100 ** members and methods accessed by the rt thread are marked RT
101 */
102
103template <class F>
105private:
106 F *rack_order_ptr[2]; // RT
107 int size[2];
110 void setsize(int n);
111 inline F get_audio(PluginDef *p);
112protected:
115public:
118 inline void empty_chain(ParamMap& pmap) {
119 list<Plugin*> p;
120 if (set_plugin_list(p)) {
121 commit(true, pmap);
122 }
123 }
124 void commit(bool clear, ParamMap& pmap);
125};
126
127typedef void (*monochainorder)(int count, float *output, float *output1,
128 PluginDef *plugin);
129typedef void (*stereochainorder)(int count, float* input, float* input1,
130 float *output, float *output1, PluginDef *plugin);
131
135 monochain_data(monochainorder func_, PluginDef *plugin_): func(func_), plugin(plugin_) {}
137};
138
142 stereochain_data(stereochainorder func_, PluginDef *plugin_): func(func_), plugin(plugin_) {}
144};
145
146template <>
148{
149 return monochain_data(p->mono_audio, p);
150}
151
152template <>
154{
155 return stereochain_data(p->stereo_audio, p);
156}
157
158template <class F>
160 rack_order_ptr(),
161 size(),
162 current_index(0),
163 current_pointer(),
164 processing_pointer() {
165 setsize(1);
166 current_pointer[0].func = 0;
168 current_index = 1;
170}
171
172template <class F>
174 delete[] rack_order_ptr[0];
175 delete[] rack_order_ptr[1];
176}
177
178template <class F>
180{
181 if (n <= size[current_index]) {
182 return;
183 }
184 delete[] rack_order_ptr[current_index];
185 rack_order_ptr[current_index] = new F[n];
186 size[current_index] = n;
187 current_pointer = rack_order_ptr[current_index];
188}
189
190template <class F>
192 setsize(modules.size()+1); // leave one slot for 0 marker
193 int active_counter = 0;
194 for (list<Plugin*>::const_iterator p = modules.begin(); p != modules.end(); p++) {
195 PluginDef* pd = (*p)->get_pdef();
196 if (pd->activate_plugin) {
197 if (pd->activate_plugin(true, pd) != 0) {
198 (*p)->set_on_off(false);
199 continue;
200 }
201 } else if (pd->clear_state && clear) {
202 pd->clear_state(pd);
203 }
204 F f = get_audio(pd);
205 assert(f.func);
206 current_pointer[active_counter++] = f;
207 }
208 current_pointer[active_counter].func = 0;
209 gx_system::atomic_set(&processing_pointer, current_pointer);
210 set_latch();
211 current_index = (current_index+1) % 2;
212 current_pointer = rack_order_ptr[current_index];
213}
214
215/****************************************************************
216 ** class MonoModuleChain, class StereoModuleChain
217 */
218
219class MonoModuleChain: public ThreadSafeChainPointer<monochain_data> {
220public:
222 void process(int count, float *input, float *output);
223 inline void print() { printlist("Mono", modules); }
224};
225
226class StereoModuleChain: public ThreadSafeChainPointer<stereochain_data> {
227public:
229 void process(int count, float *input1, float *input2, float *output1, float *output2);
230 inline void print() { printlist("Stereo", modules); }
231};
232
233
234/****************************************************************
235 ** class EngineControl
236 */
237
239protected:
240 list<ModuleSelector*> selectors; // selectors that modify the on/off state of
241 // modules at start of reconfiguration
242 sigc::connection rack_changed; // idle signal for reconfiguration of module chains
244 int policy; // jack realtime policy,
245 int priority; // and priority, for internal modules
246 // signal anyone who needs to be synchronously notified
247 // BE CAREFUL: executed by RT thread (though not concurrent with audio
248 // modules, and timing requirements are relaxed)
249 sigc::signal<void, unsigned int> buffersize_change;
250 sigc::signal<void, unsigned int> samplerate_change;
251 unsigned int buffersize;
252 unsigned int samplerate;
253public:
254 enum OverloadType { // type of overload condition
255 ov_User = 0x1, // idle thread probe starved
256 ov_Convolver = 0x2, // convolver overload
257 ov_XRun = 0x4, // jack audio loop overload
258 ov_NoWarn = 0x8 // disable overlaod warning
259 };
263 void init(unsigned int samplerate, unsigned int buffersize,
264 int policy, int priority);
265 virtual void wait_ramp_down_finished() = 0;
266 virtual bool update_module_lists() = 0;
267 virtual void start_ramp_up() = 0;
268 virtual void start_ramp_down() = 0;
269 virtual void overload(OverloadType tp, const char *reason) = 0; // RT
270 void set_samplerate(unsigned int samplerate_);
271 unsigned int get_samplerate() { return samplerate; }
272 void set_buffersize(unsigned int buffersize_);
273 unsigned int get_buffersize() { return buffersize; }
274 virtual void set_rack_changed() = 0;
277 sigc::signal<void, unsigned int>& signal_buffersize_change() { return buffersize_change; }
278 sigc::signal<void, unsigned int>& signal_samplerate_change() { return samplerate_change; }
281 void get_sched_priority(int &policy, int &priority, int prio_dim = 0);
282 ParamMap& get_param() { return pmap; }
283};
284
285
286/****************************************************************
287 ** class ModuleSequencer
288 */
289
290enum GxEngineState { // engine states set by user (ModuleSequencer set_state/get_state)
291 kEngineOff = 0, // mute, no output (but tuner or something might run)
292 kEngineOn = 1, // normal operation
293 kEngineBypass = 2 // just some balance or level control
295
296
298protected:
299 int audio_mode; // GxEngineState coded as PGN_MODE_XX flags
300 boost::mutex stateflags_mutex;
302 sigc::signal<void, GxEngineState> state_change;
303 Glib::Dispatcher overload_detected;
304 const char *overload_reason; // name of unit which detected overload
305 int ov_disabled; // bitmask of OverloadType
306 static int sporadic_interval; // seconds; overload if at least 2 events in the timespan
307protected:
309public:
310 MonoModuleChain mono_chain; // active modules (amp chain, input to insert output)
311 StereoModuleChain stereo_chain; // active stereo modules (effect chain, after insert input)
312 enum StateFlag { // engine is off if one of these flags is set
313 SF_NO_CONNECTION = 0x01, // no jack connection at amp input
314 SF_JACK_RECONFIG = 0x02, // jack buffersize reconfiguration in progress
315 SF_INITIALIZING = 0x04, // jack or engine not ready
316 SF_OVERLOAD = 0x08, // engine overload
317 };
318public:
324 }
325 virtual void set_samplerate(unsigned int samplerate);
326 virtual void start_ramp_up();
327 virtual void start_ramp_down();
329 void ramp_down() {
332 }
336 }
339 virtual void set_rack_changed();
340 virtual bool update_module_lists();
342 virtual void overload(OverloadType tp, const char *reason); // RT
343 void set_stateflag(StateFlag flag); // RT
344 void clear_stateflag(StateFlag flag); // RT
347 sigc::signal<void, GxEngineState>& signal_state_change() { return state_change; }
348 static void set_overload_interval(int i) { sporadic_interval = i; }
349#ifndef NDEBUG
351#endif
352};
353
354} /* end of gx_engine namespace */
virtual void overload(OverloadType tp, const char *reason)=0
void get_sched_priority(int &policy, int &priority, int prio_dim=0)
void add_selector(ModuleSelector &sel)
sigc::signal< void, unsigned int > & signal_buffersize_change()
void init(unsigned int samplerate, unsigned int buffersize, int policy, int priority)
list< ModuleSelector * > selectors
sigc::signal< void, unsigned int > & signal_samplerate_change()
void registerParameter(ParameterGroups &groups)
virtual bool update_module_lists()=0
virtual void set_rack_changed()=0
void set_buffersize(unsigned int buffersize_)
virtual void wait_ramp_down_finished()=0
sigc::signal< void, unsigned int > samplerate_change
virtual void start_ramp_down()=0
sigc::signal< void, unsigned int > buffersize_change
void set_samplerate(unsigned int samplerate_)
virtual void start_ramp_up()=0
ModuleSelector(EngineControl &seq_)
virtual void set_module()=0
virtual void overload(OverloadType tp, const char *reason)
sigc::signal< void, GxEngineState > state_change
virtual void set_samplerate(unsigned int samplerate)
virtual void start_ramp_up()
virtual void start_ramp_down()
GxEngineState get_state()
virtual void set_rack_changed()
void set_stateflag(StateFlag flag)
sigc::signal< void, GxEngineState > & signal_state_change()
void set_state(GxEngineState state)
void clear_stateflag(StateFlag flag)
static void set_overload_interval(int i)
virtual void wait_ramp_down_finished()
Glib::Dispatcher overload_detected
virtual bool update_module_lists()
void process(int count, float *input, float *output)
void set_samplerate(int samplerate)
void try_set_ramp_mode(RampMode oldmode, RampMode newmode, int oldrv, int newrv)
void print_chain_state(const char *title)
bool set_plugin_list(const list< Plugin * > &p)
void process(int count, float *input1, float *input2, float *output1, float *output2)
void commit(bool clear, ParamMap &pmap)
void printlist(const char *title, const list< Plugin * > &modules, bool header=true)
void(* monochainorder)(int count, float *output, float *output1, PluginDef *plugin)
void(* stereochainorder)(int count, float *input, float *input1, float *output, float *output1, PluginDef *plugin)
int atomic_get(volatile int &p)
Definition: gx_system.h:98
void atomic_set(volatile int *p, int v)
Definition: gx_system.h:90
clearstatefunc clear_state
Definition: gx_plugin.h:216
process_mono_audio mono_audio
Definition: gx_plugin.h:209
process_stereo_audio stereo_audio
Definition: gx_plugin.h:210
activatefunc activate_plugin
Definition: gx_plugin.h:213
monochain_data(monochainorder func_, PluginDef *plugin_)
stereochain_data(stereochainorder func_, PluginDef *plugin_)