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 
23 namespace gx_engine {
24 
25 /****************************************************************
26  ** class ModuleSelector
27  */
28 
30 protected:
32 public:
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 
46 public:
48 private:
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;
54 protected:
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
60  inline void set_ramp_mode(RampMode n) { gx_system::atomic_set(&ramp_mode, n); } // RT
61  void try_set_ramp_mode(RampMode oldmode, RampMode newmode, int oldrv, int newrv); // RT
62 public:
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();
85 #ifdef GUITARIX_AS_PLUGIN
86  void process_ramp(int count);
87 #endif
89  void start_ramp_up();
92  inline bool is_down_dead() { return get_ramp_mode() == ramp_mode_down_dead; }
93  void set_stopped(bool v);
94  bool is_stopped() { return stopped; }
95 #ifndef NDEBUG
96  void print_chain_state(const char *title);
97 #endif
98 };
99 
100 
101 /****************************************************************
102  ** template class ThreadSafeChainPointer
103  ** members and methods accessed by the rt thread are marked RT
104  */
105 
106 template <class F>
108 private:
109  F *rack_order_ptr[2]; // RT
110  int size[2];
113  void setsize(int n);
114  inline F get_audio(PluginDef *p);
115 protected:
118 public:
121  inline void empty_chain(ParamMap& pmap) {
122  list<Plugin*> p;
123  if (set_plugin_list(p)) {
124  commit(true, pmap);
125  }
126  }
127  void commit(bool clear, ParamMap& pmap);
128 };
129 
130 typedef void (*monochainorder)(int count, float *output, float *output1,
131  PluginDef *plugin);
132 typedef void (*stereochainorder)(int count, float* input, float* input1,
133  float *output, float *output1, PluginDef *plugin);
134 
138  monochain_data(monochainorder func_, PluginDef *plugin_): func(func_), plugin(plugin_) {}
140 };
141 
145  stereochain_data(stereochainorder func_, PluginDef *plugin_): func(func_), plugin(plugin_) {}
147 };
148 
149 template <>
151 {
152  return monochain_data(p->mono_audio, p);
153 }
154 
155 template <>
157 {
158  return stereochain_data(p->stereo_audio, p);
159 }
160 
161 template <class F>
163  rack_order_ptr(),
164  size(),
165  current_index(0),
166  current_pointer(),
167  processing_pointer() {
168  setsize(1);
169  current_pointer[0].func = 0;
171  current_index = 1;
173 }
174 
175 template <class F>
177  delete[] rack_order_ptr[0];
178  delete[] rack_order_ptr[1];
179 }
180 
181 template <class F>
183 {
184  if (n <= size[current_index]) {
185  return;
186  }
187  delete[] rack_order_ptr[current_index];
188  rack_order_ptr[current_index] = new F[n];
189  size[current_index] = n;
190  current_pointer = rack_order_ptr[current_index];
191 }
192 
193 template <class F>
195  setsize(modules.size()+1); // leave one slot for 0 marker
196  int active_counter = 0;
197  for (list<Plugin*>::const_iterator p = modules.begin(); p != modules.end(); p++) {
198  PluginDef* pd = (*p)->get_pdef();
199  if (pd->activate_plugin) {
200  if (pd->activate_plugin(true, pd) != 0) {
201  (*p)->set_on_off(false);
202  continue;
203  }
204  } else if (pd->clear_state && clear) {
205  pd->clear_state(pd);
206  }
207  F f = get_audio(pd);
208  assert(f.func);
209  current_pointer[active_counter++] = f;
210  }
211  current_pointer[active_counter].func = 0;
212  gx_system::atomic_set(&processing_pointer, current_pointer);
213  set_latch();
214  current_index = (current_index+1) % 2;
215  current_pointer = rack_order_ptr[current_index];
216 }
217 
218 /****************************************************************
219  ** class MonoModuleChain, class StereoModuleChain
220  */
221 
222 class MonoModuleChain: public ThreadSafeChainPointer<monochain_data> {
223 public:
225  void process(int count, float *input, float *output);
226  inline void print() { printlist("Mono", modules); }
227 };
228 
229 class StereoModuleChain: public ThreadSafeChainPointer<stereochain_data> {
230 public:
232 #ifndef GUITARIX_AS_PLUGIN
233  void process(int count, float *input1, float *input2, float *output1, float *output2);
234 #else
235  void process(int count, float *input1, float *input2, float *output1, float *output2, bool feed=true);
236 #endif
237  inline void print() { printlist("Stereo", modules); }
238 };
239 
240 
241 /****************************************************************
242  ** class EngineControl
243  */
244 
246 protected:
247  list<ModuleSelector*> selectors; // selectors that modify the on/off state of
248  // modules at start of reconfiguration
249  sigc::connection rack_changed; // idle signal for reconfiguration of module chains
251  int policy; // jack realtime policy,
252  int priority; // and priority, for internal modules
253  // signal anyone who needs to be synchronously notified
254  // BE CAREFUL: executed by RT thread (though not concurrent with audio
255  // modules, and timing requirements are relaxed)
256  sigc::signal<void, unsigned int> buffersize_change;
257  sigc::signal<void, unsigned int> samplerate_change;
258  unsigned int buffersize;
259  unsigned int samplerate;
260 public:
261  enum OverloadType { // type of overload condition
262  ov_User = 0x1, // idle thread probe starved
263  ov_Convolver = 0x2, // convolver overload
264  ov_XRun = 0x4, // jack audio loop overload
265  ov_NoWarn = 0x8 // disable overlaod warning
266  };
270  void init(unsigned int samplerate, unsigned int buffersize,
271  int policy, int priority);
272  virtual void wait_ramp_down_finished() = 0;
273  virtual bool update_module_lists() = 0;
274  virtual void start_ramp_up() = 0;
275  virtual void start_ramp_down() = 0;
276  virtual void overload(OverloadType tp, const char *reason) = 0; // RT
277  void set_samplerate(unsigned int samplerate_);
278  unsigned int get_samplerate() { return samplerate; }
279  void set_buffersize(unsigned int buffersize_);
280  unsigned int get_buffersize() { return buffersize; }
281  virtual void set_rack_changed() = 0;
284  sigc::signal<void, unsigned int>& signal_buffersize_change() { return buffersize_change; }
285  sigc::signal<void, unsigned int>& signal_samplerate_change() { return samplerate_change; }
288  void get_sched_priority(int &policy, int &priority, int prio_dim = 0);
289  ParamMap& get_param() { return pmap; }
290 #ifdef GUITARIX_AS_PLUGIN
291  virtual sigc::signal<bool ()>& signal_timeout()=0;
292 #endif
293 };
294 
295 
296 /****************************************************************
297  ** class ModuleSequencer
298  */
299 
300 enum GxEngineState { // engine states set by user (ModuleSequencer set_state/get_state)
301  kEngineOff = 0, // mute, no output (but tuner or something might run)
302  kEngineOn = 1, // normal operation
303  kEngineBypass = 2 // just some balance or level control
304 };
305 
306 
308 protected:
309  int audio_mode; // GxEngineState coded as PGN_MODE_XX flags
310  boost::mutex stateflags_mutex;
312  sigc::signal<void, GxEngineState> state_change;
313  Glib::Dispatcher overload_detected;
314  const char *overload_reason; // name of unit which detected overload
315  int ov_disabled; // bitmask of OverloadType
316  static int sporadic_interval; // seconds; overload if at least 2 events in the timespan
317 #ifdef GUITARIX_AS_PLUGIN
318  sigc::signal<bool ()> _signal_timeout;
319  sigc::connection clearoverride_conn;
320 #endif
321 protected:
323 public:
324  MonoModuleChain mono_chain; // active modules (amp chain, input to insert output)
325  StereoModuleChain stereo_chain; // active stereo modules (effect chain, after insert input)
326  enum StateFlag { // engine is off if one of these flags is set
327  SF_NO_CONNECTION = 0x01, // no jack connection at amp input
328  SF_JACK_RECONFIG = 0x02, // jack buffersize reconfiguration in progress
329  SF_INITIALIZING = 0x04, // jack or engine not ready
330  SF_OVERLOAD = 0x08, // engine overload
331  };
332 public:
338  }
339  virtual void set_samplerate(unsigned int samplerate);
340  virtual void start_ramp_up();
341  virtual void start_ramp_down();
342  virtual void wait_ramp_down_finished();
343  void ramp_down() {
344  start_ramp_down();
346  }
347  void set_down_dead() {
350  }
353  virtual void set_rack_changed();
354  virtual bool update_module_lists();
356  virtual void overload(OverloadType tp, const char *reason); // RT
357  void set_stateflag(StateFlag flag); // RT
358  void clear_stateflag(StateFlag flag); // RT
361  sigc::signal<void, GxEngineState>& signal_state_change() { return state_change; }
362  static void set_overload_interval(int i) { sporadic_interval = i; }
363 #ifdef GUITARIX_AS_PLUGIN
364  sigc::signal<bool ()>& signal_timeout() override { return _signal_timeout; }
365 #endif
366 #ifndef NDEBUG
368 #endif
369 };
370 
371 } /* end of gx_engine namespace */
sigc::signal< void, unsigned int > & signal_samplerate_change()
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)
void init(unsigned int samplerate, unsigned int buffersize, int policy, int priority)
list< ModuleSelector * > selectors
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 > & signal_buffersize_change()
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
sigc::signal< void, GxEngineState > & signal_state_change()
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)
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_)