I wanna be nasty, I wanna be cruel,..
[ardour.git] / libs / backends / dummy / dummy_audiobackend.h
1 /*
2  * Copyright (C) 2014 Robin Gareus <robin@gareus.org>
3  * Copyright (C) 2013 Paul Davis
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 #ifndef __libbackend_dummy_audiobackend_h__
21 #define __libbackend_dummy_audiobackend_h__
22
23 #include <string>
24 #include <vector>
25 #include <map>
26 #include <set>
27
28 #include <stdint.h>
29 #include <pthread.h>
30
31 #include <boost/shared_ptr.hpp>
32
33 #include "ardour/types.h"
34 #include "ardour/audio_backend.h"
35 #include "ardour/dsp_load_calculator.h"
36
37 namespace ARDOUR {
38
39 class DummyAudioBackend;
40
41 namespace DummyMidiData {
42         typedef struct _MIDISequence {
43                 float   beat_time;
44                 uint8_t size;
45                 uint8_t event[3];
46         } MIDISequence;
47 };
48
49
50 class DummyMidiEvent {
51         public:
52                 DummyMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size);
53                 DummyMidiEvent (const DummyMidiEvent& other);
54                 ~DummyMidiEvent ();
55                 size_t size () const { return _size; };
56                 pframes_t timestamp () const { return _timestamp; };
57                 const unsigned char* const_data () const { return _data; };
58                 unsigned char* data () { return _data; };
59                 bool operator< (const DummyMidiEvent &other) const { return timestamp () < other.timestamp (); };
60         private:
61                 size_t _size;
62                 pframes_t _timestamp;
63                 uint8_t *_data;
64 };
65
66 typedef std::vector<boost::shared_ptr<DummyMidiEvent> > DummyMidiBuffer;
67
68 class DummyPort {
69         protected:
70                 DummyPort (DummyAudioBackend &b, const std::string&, PortFlags);
71         public:
72                 virtual ~DummyPort ();
73
74                 const std::string& name () const { return _name; }
75                 const std::string& pretty_name () const { return _pretty_name; }
76                 PortFlags flags () const { return _flags; }
77
78                 int set_name (const std::string &name) { _name = name; return 0; }
79                 int set_pretty_name (const std::string &name) { _pretty_name = name; return 0; }
80
81                 virtual DataType type () const = 0;
82
83                 bool is_input ()     const { return flags () & IsInput; }
84                 bool is_output ()    const { return flags () & IsOutput; }
85                 bool is_physical ()  const { return flags () & IsPhysical; }
86                 bool is_terminal ()  const { return flags () & IsTerminal; }
87                 bool is_connected () const { return _connections.size () != 0; }
88                 bool is_connected (const DummyPort *port) const;
89                 bool is_physically_connected () const;
90
91                 const std::set<DummyPort *>& get_connections () const { return _connections; }
92
93                 int connect (DummyPort *port);
94                 int disconnect (DummyPort *port);
95                 void disconnect_all ();
96
97                 virtual void* get_buffer (pframes_t nframes) = 0;
98                 void next_period () { _gen_cycle = false; }
99
100                 const LatencyRange latency_range (bool for_playback) const
101                 {
102                         return for_playback ? _playback_latency_range : _capture_latency_range;
103                 }
104
105                 void set_latency_range (const LatencyRange &latency_range, bool for_playback)
106                 {
107                         if (for_playback)
108                         {
109                                 _playback_latency_range = latency_range;
110                         }
111                         else
112                         {
113                                 _capture_latency_range = latency_range;
114                         }
115                 }
116
117         private:
118                 DummyAudioBackend &_dummy_backend;
119                 std::string _name;
120                 std::string _pretty_name;
121                 const PortFlags _flags;
122                 LatencyRange _capture_latency_range;
123                 LatencyRange _playback_latency_range;
124                 std::set<DummyPort*> _connections;
125
126                 void _connect (DummyPort* , bool);
127                 void _disconnect (DummyPort* , bool);
128
129         protected:
130                 // random number generator
131                 void setup_random_number_generator ();
132                 inline float    randf ();
133                 inline uint32_t randi ();
134                 uint32_t _rseed;
135
136                 // signal generator
137                 volatile bool _gen_cycle;
138                 Glib::Threads::Mutex generator_lock;
139
140 }; // class DummyPort
141
142 class DummyAudioPort : public DummyPort {
143         public:
144                 DummyAudioPort (DummyAudioBackend &b, const std::string&, PortFlags);
145                 ~DummyAudioPort ();
146
147                 DataType type () const { return DataType::AUDIO; };
148
149                 Sample* buffer () { return _buffer; }
150                 const Sample* const_buffer () const { return _buffer; }
151                 void* get_buffer (pframes_t nframes);
152
153                 enum GeneratorType {
154                         Silence,
155                         DC05,
156                         Demolition,
157                         UniformWhiteNoise,
158                         GaussianWhiteNoise,
159                         PinkNoise,
160                         PonyNoise,
161                         SineWave,
162                         SquareWave,
163                         KronekerDelta,
164                         SineSweep,
165                         SineSweepSwell,
166                         SquareSweep,
167                         SquareSweepSwell,
168                         Loopback,
169                 };
170                 void setup_generator (GeneratorType const, float const);
171                 void fill_wavetable (const float* d, size_t n_samples) { assert(_wavetable != 0);  memcpy(_wavetable, d, n_samples * sizeof(float)); }
172                 void midi_to_wavetable (DummyMidiBuffer const * const src, size_t n_samples);
173
174         private:
175                 Sample _buffer[8192];
176
177                 // signal generator ('fake' physical inputs)
178                 void generate (const pframes_t n_samples);
179                 GeneratorType _gen_type;
180
181                 // generator buffers
182                 // pink-noise filters
183                 float _b0, _b1, _b2, _b3, _b4, _b5, _b6;
184                 // generated sinf() samples
185                 Sample * _wavetable;
186                 uint32_t _gen_period;
187                 uint32_t _gen_offset;
188                 uint32_t _gen_perio2;
189                 uint32_t _gen_count2;
190
191                 // gaussian noise generator
192                 float grandf ();
193                 bool _pass;
194                 float _rn1;
195
196 }; // class DummyAudioPort
197
198 class DummyMidiPort : public DummyPort {
199         public:
200                 DummyMidiPort (DummyAudioBackend &b, const std::string&, PortFlags);
201                 ~DummyMidiPort ();
202
203                 DataType type () const { return DataType::MIDI; };
204
205                 void* get_buffer (pframes_t nframes);
206                 const DummyMidiBuffer * const_buffer () const { return &_buffer; }
207
208                 void setup_generator (int, float const);
209                 void set_loopback (DummyMidiBuffer const * const src);
210
211         private:
212                 DummyMidiBuffer _buffer;
213                 DummyMidiBuffer _loopback;
214
215                 // midi event generator ('fake' physical inputs)
216                 void midi_generate (const pframes_t n_samples);
217                 float   _midi_seq_spb; // samples per beat
218                 int32_t _midi_seq_time;
219                 uint32_t _midi_seq_pos;
220                 DummyMidiData::MIDISequence const * _midi_seq_dat;
221 }; // class DummyMidiPort
222
223 class DummyAudioBackend : public AudioBackend {
224         friend class DummyPort;
225         public:
226                  DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info);
227                 ~DummyAudioBackend ();
228
229                 bool is_running () const { return _running; }
230
231                 /* AUDIOBACKEND API */
232
233                 std::string name () const;
234                 bool is_realtime () const;
235
236                 bool requires_driver_selection() const { return true; }
237                 std::string driver_name () const;
238                 std::vector<std::string> enumerate_drivers () const;
239                 int set_driver (const std::string&);
240
241                 std::vector<DeviceStatus> enumerate_devices () const;
242                 std::vector<float> available_sample_rates (const std::string& device) const;
243                 std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
244                 uint32_t available_input_channel_count (const std::string& device) const;
245                 uint32_t available_output_channel_count (const std::string& device) const;
246
247                 bool can_change_sample_rate_when_running () const;
248                 bool can_change_buffer_size_when_running () const;
249
250                 int set_device_name (const std::string&);
251                 int set_sample_rate (float);
252                 int set_buffer_size (uint32_t);
253                 int set_interleaved (bool yn);
254                 int set_input_channels (uint32_t);
255                 int set_output_channels (uint32_t);
256                 int set_systemic_input_latency (uint32_t);
257                 int set_systemic_output_latency (uint32_t);
258                 int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
259                 int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
260
261                 int reset_device () { return 0; };
262
263                 /* Retrieving parameters */
264                 std::string  device_name () const;
265                 float        sample_rate () const;
266                 uint32_t     buffer_size () const;
267                 bool         interleaved () const;
268                 uint32_t     input_channels () const;
269                 uint32_t     output_channels () const;
270                 uint32_t     systemic_input_latency () const;
271                 uint32_t     systemic_output_latency () const;
272                 uint32_t     systemic_midi_input_latency (std::string const) const { return 0; }
273                 uint32_t     systemic_midi_output_latency (std::string const) const { return 0; }
274
275                 /* External control app */
276                 std::string control_app_name () const { return std::string (); }
277                 void launch_control_app () {}
278
279                 /* MIDI */
280                 std::vector<std::string> enumerate_midi_options () const;
281                 int set_midi_option (const std::string&);
282                 std::string midi_option () const;
283
284                 std::vector<DeviceStatus> enumerate_midi_devices () const {
285                         return std::vector<AudioBackend::DeviceStatus> ();
286                 }
287                 int set_midi_device_enabled (std::string const, bool) {
288                         return 0;
289                 }
290                 bool midi_device_enabled (std::string const) const {
291                         return true;
292                 }
293                 bool can_set_systemic_midi_latencies () const {
294                         return false;
295                 }
296
297                 /* State Control */
298         protected:
299                 int _start (bool for_latency_measurement);
300         public:
301                 int stop ();
302                 int freewheel (bool);
303                 float dsp_load () const;
304                 size_t raw_buffer_size (DataType t);
305
306                 /* Process time */
307                 framepos_t sample_time ();
308                 framepos_t sample_time_at_cycle_start ();
309                 pframes_t samples_since_cycle_start ();
310
311                 int create_process_thread (boost::function<void()> func);
312                 int join_process_threads ();
313                 bool in_process_thread ();
314                 uint32_t process_thread_count ();
315
316                 void update_latencies ();
317
318                 /* PORTENGINE API */
319
320                 void* private_handle () const;
321                 const std::string& my_name () const;
322                 bool available () const;
323                 uint32_t port_name_size () const;
324
325                 int         set_port_name (PortHandle, const std::string&);
326                 std::string get_port_name (PortHandle) const;
327                 PortHandle  get_port_by_name (const std::string&) const;
328
329                 int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const;
330                 int set_port_property (PortHandle, const std::string& key, const std::string& value, const std::string& type);
331
332                 int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
333
334                 DataType port_data_type (PortHandle) const;
335
336                 PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
337                 void unregister_port (PortHandle);
338
339                 int  connect (const std::string& src, const std::string& dst);
340                 int  disconnect (const std::string& src, const std::string& dst);
341                 int  connect (PortHandle, const std::string&);
342                 int  disconnect (PortHandle, const std::string&);
343                 int  disconnect_all (PortHandle);
344
345                 bool connected (PortHandle, bool process_callback_safe);
346                 bool connected_to (PortHandle, const std::string&, bool process_callback_safe);
347                 bool physically_connected (PortHandle, bool process_callback_safe);
348                 int  get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
349
350                 /* MIDI */
351                 int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
352                 int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
353                 uint32_t get_midi_event_count (void* port_buffer);
354                 void     midi_clear (void* port_buffer);
355
356                 /* Monitoring */
357
358                 bool can_monitor_input () const;
359                 int  request_input_monitoring (PortHandle, bool);
360                 int  ensure_input_monitoring (PortHandle, bool);
361                 bool monitoring_input (PortHandle);
362
363                 /* Latency management */
364
365                 void         set_latency_range (PortHandle, bool for_playback, LatencyRange);
366                 LatencyRange get_latency_range (PortHandle, bool for_playback);
367
368                 /* Discovering physical ports */
369
370                 bool      port_is_physical (PortHandle) const;
371                 void      get_physical_outputs (DataType type, std::vector<std::string>&);
372                 void      get_physical_inputs (DataType type, std::vector<std::string>&);
373                 ChanCount n_physical_outputs () const;
374                 ChanCount n_physical_inputs () const;
375
376                 /* Getting access to the data buffer for a port */
377
378                 void* get_buffer (PortHandle, pframes_t);
379
380                 void* main_process_thread ();
381
382                 static size_t max_buffer_size() {return _max_buffer_size;}
383
384         private:
385                 enum MidiPortMode {
386                         MidiNoEvents,
387                         MidiGenerator,
388                         MidiLoopback,
389                         MidiToAudio,
390                 };
391
392                 struct DriverSpeed {
393                         std::string name;
394                         float speedup;
395                         DriverSpeed (const std::string& n, float s) : name (n), speedup (s) {}
396                 };
397
398                 std::string _instance_name;
399                 static std::vector<std::string> _midi_options;
400                 static std::vector<AudioBackend::DeviceStatus> _device_status;
401                 static std::vector<DummyAudioBackend::DriverSpeed> _driver_speed;
402
403                 bool  _running;
404                 bool  _freewheel;
405                 bool  _freewheeling;
406                 float _speedup;
407
408                 std::string _device;
409
410                 float  _samplerate;
411                 size_t _samples_per_period;
412                 float  _dsp_load;
413                 DSPLoadCalculator _dsp_load_calc;
414                 static size_t _max_buffer_size;
415
416                 uint32_t _n_inputs;
417                 uint32_t _n_outputs;
418
419                 uint32_t _n_midi_inputs;
420                 uint32_t _n_midi_outputs;
421                 MidiPortMode _midi_mode;
422
423                 uint32_t _systemic_input_latency;
424                 uint32_t _systemic_output_latency;
425
426                 framecnt_t _processed_samples;
427
428                 pthread_t _main_thread;
429
430                 /* process threads */
431                 static void* dummy_process_thread (void *);
432                 std::vector<pthread_t> _threads;
433
434                 struct ThreadData {
435                         DummyAudioBackend* engine;
436                         boost::function<void ()> f;
437                         size_t stacksize;
438
439                         ThreadData (DummyAudioBackend* e, boost::function<void ()> fp, size_t stacksz)
440                                 : engine (e) , f (fp) , stacksize (stacksz) {}
441                 };
442
443                 /* port engine */
444                 PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
445                 int register_system_ports ();
446                 void unregister_ports (bool system_only = false);
447
448                 std::vector<DummyAudioPort *> _system_inputs;
449                 std::vector<DummyAudioPort *> _system_outputs;
450                 std::vector<DummyMidiPort *> _system_midi_in;
451                 std::vector<DummyMidiPort *> _system_midi_out;
452
453                 typedef std::map<std::string, DummyPort *> PortMap; // fast lookup in _ports
454                 typedef std::set<DummyPort *> PortIndex; // fast lookup in _ports
455                 PortMap _portmap;
456                 PortIndex _ports;
457
458                 struct PortConnectData {
459                         std::string a;
460                         std::string b;
461                         bool c;
462
463                         PortConnectData (const std::string& a, const std::string& b, bool c)
464                                 : a (a) , b (b) , c (c) {}
465                 };
466
467                 std::vector<PortConnectData *> _port_connection_queue;
468                 pthread_mutex_t _port_callback_mutex;
469                 bool _port_change_flag;
470
471                 void port_connect_callback (const std::string& a, const std::string& b, bool conn) {
472                         pthread_mutex_lock (&_port_callback_mutex);
473                         _port_connection_queue.push_back(new PortConnectData(a, b, conn));
474                         pthread_mutex_unlock (&_port_callback_mutex);
475                 }
476
477                 void port_connect_add_remove_callback () {
478                         pthread_mutex_lock (&_port_callback_mutex);
479                         _port_change_flag = true;
480                         pthread_mutex_unlock (&_port_callback_mutex);
481                 }
482
483                 bool valid_port (PortHandle port) const {
484                         return _ports.find (static_cast<DummyPort*>(port)) != _ports.end ();
485                 }
486
487                 DummyPort* find_port (const std::string& port_name) const {
488                         PortMap::const_iterator it = _portmap.find (port_name);
489                         if (it == _portmap.end()) {
490                                 return NULL;
491                         }
492                         return (*it).second;
493                 }
494
495 }; // class DummyAudioBackend
496
497 } // namespace
498
499 #endif /* __libbackend_dummy_audiobackend_h__ */