12abe7be92a2a627b77fe1bcea617c8144df6dfd
[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                         SineWaveOctaves,
163                         SquareWave,
164                         KronekerDelta,
165                         SineSweep,
166                         SineSweepSwell,
167                         SquareSweep,
168                         SquareSweepSwell,
169                         Loopback,
170                 };
171                 std::string setup_generator (GeneratorType const, float const, int, int);
172                 void fill_wavetable (const float* d, size_t n_samples) { assert(_wavetable != 0);  memcpy(_wavetable, d, n_samples * sizeof(float)); }
173                 void midi_to_wavetable (DummyMidiBuffer const * const src, size_t n_samples);
174
175         private:
176                 Sample _buffer[8192];
177
178                 // signal generator ('fake' physical inputs)
179                 void generate (const pframes_t n_samples);
180                 GeneratorType _gen_type;
181
182                 // generator buffers
183                 // pink-noise filters
184                 float _b0, _b1, _b2, _b3, _b4, _b5, _b6;
185                 // generated sinf() samples
186                 Sample * _wavetable;
187                 uint32_t _gen_period;
188                 uint32_t _gen_offset;
189                 uint32_t _gen_perio2;
190                 uint32_t _gen_count2;
191
192                 // gaussian noise generator
193                 float grandf ();
194                 bool _pass;
195                 float _rn1;
196
197 }; // class DummyAudioPort
198
199 class DummyMidiPort : public DummyPort {
200         public:
201                 DummyMidiPort (DummyAudioBackend &b, const std::string&, PortFlags);
202                 ~DummyMidiPort ();
203
204                 DataType type () const { return DataType::MIDI; };
205
206                 void* get_buffer (pframes_t nframes);
207                 const DummyMidiBuffer * const_buffer () const { return &_buffer; }
208
209                 std::string setup_generator (int, float const);
210                 void set_loopback (DummyMidiBuffer const * const src);
211
212         private:
213                 DummyMidiBuffer _buffer;
214                 DummyMidiBuffer _loopback;
215
216                 // midi event generator ('fake' physical inputs)
217                 void midi_generate (const pframes_t n_samples);
218                 float   _midi_seq_spb; // samples per beat
219                 int32_t _midi_seq_time;
220                 uint32_t _midi_seq_pos;
221                 DummyMidiData::MIDISequence const * _midi_seq_dat;
222 }; // class DummyMidiPort
223
224 class DummyAudioBackend : public AudioBackend {
225         friend class DummyPort;
226         public:
227                  DummyAudioBackend (AudioEngine& e, AudioBackendInfo& info);
228                 ~DummyAudioBackend ();
229
230                 bool is_running () const { return _running; }
231
232                 /* AUDIOBACKEND API */
233
234                 std::string name () const;
235                 bool is_realtime () const;
236
237                 bool requires_driver_selection() const { return true; }
238                 std::string driver_name () const;
239                 std::vector<std::string> enumerate_drivers () const;
240                 int set_driver (const std::string&);
241
242                 std::vector<DeviceStatus> enumerate_devices () const;
243                 std::vector<float> available_sample_rates (const std::string& device) const;
244                 std::vector<uint32_t> available_buffer_sizes (const std::string& device) const;
245                 uint32_t available_input_channel_count (const std::string& device) const;
246                 uint32_t available_output_channel_count (const std::string& device) const;
247
248                 bool can_change_sample_rate_when_running () const;
249                 bool can_change_buffer_size_when_running () const;
250
251                 int set_device_name (const std::string&);
252                 int set_sample_rate (float);
253                 int set_buffer_size (uint32_t);
254                 int set_interleaved (bool yn);
255                 int set_input_channels (uint32_t);
256                 int set_output_channels (uint32_t);
257                 int set_systemic_input_latency (uint32_t);
258                 int set_systemic_output_latency (uint32_t);
259                 int set_systemic_midi_input_latency (std::string const, uint32_t) { return 0; }
260                 int set_systemic_midi_output_latency (std::string const, uint32_t) { return 0; }
261
262                 int reset_device () { return 0; };
263
264                 /* Retrieving parameters */
265                 std::string  device_name () const;
266                 float        sample_rate () const;
267                 uint32_t     buffer_size () const;
268                 bool         interleaved () const;
269                 uint32_t     input_channels () const;
270                 uint32_t     output_channels () const;
271                 uint32_t     systemic_input_latency () const;
272                 uint32_t     systemic_output_latency () const;
273                 uint32_t     systemic_midi_input_latency (std::string const) const { return 0; }
274                 uint32_t     systemic_midi_output_latency (std::string const) const { return 0; }
275
276                 /* External control app */
277                 std::string control_app_name () const { return std::string (); }
278                 void launch_control_app () {}
279
280                 /* MIDI */
281                 std::vector<std::string> enumerate_midi_options () const;
282                 int set_midi_option (const std::string&);
283                 std::string midi_option () const;
284
285                 std::vector<DeviceStatus> enumerate_midi_devices () const {
286                         return std::vector<AudioBackend::DeviceStatus> ();
287                 }
288                 int set_midi_device_enabled (std::string const, bool) {
289                         return 0;
290                 }
291                 bool midi_device_enabled (std::string const) const {
292                         return true;
293                 }
294                 bool can_set_systemic_midi_latencies () const {
295                         return false;
296                 }
297
298                 /* State Control */
299         protected:
300                 int _start (bool for_latency_measurement);
301         public:
302                 int stop ();
303                 int freewheel (bool);
304                 float dsp_load () const;
305                 size_t raw_buffer_size (DataType t);
306
307                 /* Process time */
308                 framepos_t sample_time ();
309                 framepos_t sample_time_at_cycle_start ();
310                 pframes_t samples_since_cycle_start ();
311
312                 int create_process_thread (boost::function<void()> func);
313                 int join_process_threads ();
314                 bool in_process_thread ();
315                 uint32_t process_thread_count ();
316
317                 void update_latencies ();
318
319                 /* PORTENGINE API */
320
321                 void* private_handle () const;
322                 const std::string& my_name () const;
323                 bool available () const;
324                 uint32_t port_name_size () const;
325
326                 int         set_port_name (PortHandle, const std::string&);
327                 std::string get_port_name (PortHandle) const;
328                 PortHandle  get_port_by_name (const std::string&) const;
329
330                 int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const;
331                 int set_port_property (PortHandle, const std::string& key, const std::string& value, const std::string& type);
332
333                 int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
334
335                 DataType port_data_type (PortHandle) const;
336
337                 PortHandle register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
338                 void unregister_port (PortHandle);
339
340                 int  connect (const std::string& src, const std::string& dst);
341                 int  disconnect (const std::string& src, const std::string& dst);
342                 int  connect (PortHandle, const std::string&);
343                 int  disconnect (PortHandle, const std::string&);
344                 int  disconnect_all (PortHandle);
345
346                 bool connected (PortHandle, bool process_callback_safe);
347                 bool connected_to (PortHandle, const std::string&, bool process_callback_safe);
348                 bool physically_connected (PortHandle, bool process_callback_safe);
349                 int  get_connections (PortHandle, std::vector<std::string>&, bool process_callback_safe);
350
351                 /* MIDI */
352                 int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index);
353                 int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size);
354                 uint32_t get_midi_event_count (void* port_buffer);
355                 void     midi_clear (void* port_buffer);
356
357                 /* Monitoring */
358
359                 bool can_monitor_input () const;
360                 int  request_input_monitoring (PortHandle, bool);
361                 int  ensure_input_monitoring (PortHandle, bool);
362                 bool monitoring_input (PortHandle);
363
364                 /* Latency management */
365
366                 void         set_latency_range (PortHandle, bool for_playback, LatencyRange);
367                 LatencyRange get_latency_range (PortHandle, bool for_playback);
368
369                 /* Discovering physical ports */
370
371                 bool      port_is_physical (PortHandle) const;
372                 void      get_physical_outputs (DataType type, std::vector<std::string>&);
373                 void      get_physical_inputs (DataType type, std::vector<std::string>&);
374                 ChanCount n_physical_outputs () const;
375                 ChanCount n_physical_inputs () const;
376
377                 /* Getting access to the data buffer for a port */
378
379                 void* get_buffer (PortHandle, pframes_t);
380
381                 void* main_process_thread ();
382
383                 static size_t max_buffer_size() {return _max_buffer_size;}
384
385         private:
386                 enum MidiPortMode {
387                         MidiNoEvents,
388                         MidiGenerator,
389                         MidiLoopback,
390                         MidiToAudio,
391                 };
392
393                 struct DriverSpeed {
394                         std::string name;
395                         float speedup;
396                         DriverSpeed (const std::string& n, float s) : name (n), speedup (s) {}
397                 };
398
399                 std::string _instance_name;
400                 static std::vector<std::string> _midi_options;
401                 static std::vector<AudioBackend::DeviceStatus> _device_status;
402                 static std::vector<DummyAudioBackend::DriverSpeed> _driver_speed;
403
404                 bool  _running;
405                 bool  _freewheel;
406                 bool  _freewheeling;
407                 float _speedup;
408
409                 std::string _device;
410
411                 float  _samplerate;
412                 size_t _samples_per_period;
413                 float  _dsp_load;
414                 DSPLoadCalculator _dsp_load_calc;
415                 static size_t _max_buffer_size;
416
417                 uint32_t _n_inputs;
418                 uint32_t _n_outputs;
419
420                 uint32_t _n_midi_inputs;
421                 uint32_t _n_midi_outputs;
422                 MidiPortMode _midi_mode;
423
424                 uint32_t _systemic_input_latency;
425                 uint32_t _systemic_output_latency;
426
427                 framecnt_t _processed_samples;
428
429                 pthread_t _main_thread;
430
431                 /* process threads */
432                 static void* dummy_process_thread (void *);
433                 std::vector<pthread_t> _threads;
434
435                 struct ThreadData {
436                         DummyAudioBackend* engine;
437                         boost::function<void ()> f;
438                         size_t stacksize;
439
440                         ThreadData (DummyAudioBackend* e, boost::function<void ()> fp, size_t stacksz)
441                                 : engine (e) , f (fp) , stacksize (stacksz) {}
442                 };
443
444                 /* port engine */
445                 PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
446                 int register_system_ports ();
447                 void unregister_ports (bool system_only = false);
448
449                 std::vector<DummyAudioPort *> _system_inputs;
450                 std::vector<DummyAudioPort *> _system_outputs;
451                 std::vector<DummyMidiPort *> _system_midi_in;
452                 std::vector<DummyMidiPort *> _system_midi_out;
453
454                 struct SortByPortName
455                 {
456                         bool operator ()(const DummyPort* lhs, const DummyPort* rhs) const
457                         {
458                                 return lhs->name () < rhs->name ();
459                         }
460                 };
461
462                 typedef std::map<std::string, DummyPort *> PortMap; // fast lookup in _ports
463                 typedef std::set<DummyPort *, SortByPortName> PortIndex; // fast lookup in _ports
464                 PortMap _portmap;
465                 PortIndex _ports;
466
467                 struct PortConnectData {
468                         std::string a;
469                         std::string b;
470                         bool c;
471
472                         PortConnectData (const std::string& a, const std::string& b, bool c)
473                                 : a (a) , b (b) , c (c) {}
474                 };
475
476                 std::vector<PortConnectData *> _port_connection_queue;
477                 pthread_mutex_t _port_callback_mutex;
478                 bool _port_change_flag;
479
480                 void port_connect_callback (const std::string& a, const std::string& b, bool conn) {
481                         pthread_mutex_lock (&_port_callback_mutex);
482                         _port_connection_queue.push_back(new PortConnectData(a, b, conn));
483                         pthread_mutex_unlock (&_port_callback_mutex);
484                 }
485
486                 void port_connect_add_remove_callback () {
487                         pthread_mutex_lock (&_port_callback_mutex);
488                         _port_change_flag = true;
489                         pthread_mutex_unlock (&_port_callback_mutex);
490                 }
491
492                 bool valid_port (PortHandle port) const {
493                         return _ports.find (static_cast<DummyPort*>(port)) != _ports.end ();
494                 }
495
496                 DummyPort* find_port (const std::string& port_name) const {
497                         PortMap::const_iterator it = _portmap.find (port_name);
498                         if (it == _portmap.end()) {
499                                 return NULL;
500                         }
501                         return (*it).second;
502                 }
503
504 }; // class DummyAudioBackend
505
506 } // namespace
507
508 #endif /* __libbackend_dummy_audiobackend_h__ */