1 /* 2 * Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org> 3 * Copyright (C) 2015-2018 Paul Davis <paul@linuxaudiosystems.com> 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 along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #ifndef __libbackend_alsa_audiobackend_h__ 21 #define __libbackend_alsa_audiobackend_h__ 22 23 #include <map> 24 #include <set> 25 #include <string> 26 #include <vector> 27 28 #include <pthread.h> 29 #include <stdint.h> 30 31 #include <boost/shared_ptr.hpp> 32 33 #include "pbd/natsort.h" 34 #include "pbd/rcu.h" 35 36 #include "ardour/audio_backend.h" 37 #include "ardour/dsp_load_calculator.h" 38 #include "ardour/port_engine_shared.h" 39 #include "ardour/system_exec.h" 40 #include "ardour/types.h" 41 42 #include "ardouralsautil/deviceinfo.h" 43 44 #include "alsa_rawmidi.h" 45 #include "alsa_sequencer.h" 46 #include "alsa_slave.h" 47 #include "zita-alsa-pcmi.h" 48 49 namespace ARDOUR { 50 51 class AlsaAudioBackend; 52 53 class AlsaMidiEvent { 54 public: 55 AlsaMidiEvent (const pframes_t timestamp, const uint8_t* data, size_t size); 56 AlsaMidiEvent (const AlsaMidiEvent& other); size()57 size_t size () const { return _size; }; timestamp()58 pframes_t timestamp () const { return _timestamp; }; data()59 const uint8_t* data () const { return _data; }; 60 bool operator< (const AlsaMidiEvent &other) const { return timestamp () < other.timestamp (); }; 61 private: 62 size_t _size; 63 pframes_t _timestamp; 64 uint8_t _data[MaxAlsaMidiEventSize]; 65 }; 66 67 typedef std::vector<AlsaMidiEvent> AlsaMidiBuffer; 68 69 class AlsaAudioPort : public BackendPort { 70 public: 71 AlsaAudioPort (AlsaAudioBackend &b, const std::string&, PortFlags); 72 ~AlsaAudioPort (); 73 type()74 DataType type () const { return DataType::AUDIO; }; 75 buffer()76 Sample* buffer () { return _buffer; } const_buffer()77 const Sample* const_buffer () const { return _buffer; } 78 void* get_buffer (pframes_t nframes); 79 80 private: 81 Sample _buffer[8192]; 82 }; // class AlsaAudioPort 83 84 class AlsaMidiPort : public BackendPort { 85 public: 86 AlsaMidiPort (AlsaAudioBackend &b, const std::string&, PortFlags); 87 ~AlsaMidiPort (); 88 type()89 DataType type () const { return DataType::MIDI; }; 90 91 void* get_buffer (pframes_t nframes); const_buffer()92 const AlsaMidiBuffer * const_buffer () const { return & _buffer[_bufperiod]; } 93 next_period()94 void next_period() { if (_n_periods > 1) { get_buffer(0); _bufperiod = (_bufperiod + 1) % _n_periods; } } set_n_periods(int n)95 void set_n_periods(int n) { if (n > 0 && n < 4) { _n_periods = n; } } 96 97 private: 98 AlsaMidiBuffer _buffer[3]; 99 int _n_periods; 100 int _bufperiod; 101 }; // class AlsaMidiPort 102 103 class AlsaDeviceReservation 104 { 105 public: 106 AlsaDeviceReservation (); 107 AlsaDeviceReservation (const char* device_name); 108 ~AlsaDeviceReservation (); 109 110 bool acquire_device (const char* device_name); 111 void release_device (); 112 113 private: 114 ARDOUR::SystemExec* _device_reservation; 115 PBD::ScopedConnectionList _reservation_connection; 116 void reservation_stdout (std::string, size_t); 117 bool _reservation_succeeded; 118 }; 119 120 class AlsaAudioBackend : public AudioBackend, public PortEngineSharedImpl 121 { 122 public: 123 AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info); 124 ~AlsaAudioBackend (); 125 126 /* AUDIOBACKEND API */ 127 128 std::string name () const; 129 bool is_realtime () const; 130 use_separate_input_and_output_devices()131 bool use_separate_input_and_output_devices () const { return true; } match_input_output_devices_or_none()132 bool match_input_output_devices_or_none () const { return false; } can_set_period_size()133 bool can_set_period_size () const { return true; } 134 135 std::vector<DeviceStatus> enumerate_devices () const; 136 std::vector<DeviceStatus> enumerate_input_devices () const; 137 std::vector<DeviceStatus> enumerate_output_devices () const; 138 std::vector<float> available_sample_rates (const std::string& device) const; 139 std::vector<float> available_sample_rates2 (const std::string&, const std::string&) const; 140 std::vector<uint32_t> available_buffer_sizes (const std::string& device) const; 141 std::vector<uint32_t> available_buffer_sizes2 (const std::string&, const std::string&) const; 142 std::vector<uint32_t> available_period_sizes (const std::string& driver, const std::string& device) const; 143 uint32_t available_input_channel_count (const std::string& device) const; 144 uint32_t available_output_channel_count (const std::string& device) const; 145 146 bool can_change_sample_rate_when_running () const; 147 bool can_change_buffer_size_when_running () const; 148 149 bool can_measure_systemic_latency () const; can_change_systemic_latency_when_running()150 bool can_change_systemic_latency_when_running () const { return true; } 151 can_request_update_devices()152 bool can_request_update_devices () { return true; } update_devices()153 bool update_devices () { return true; } 154 155 int set_device_name (const std::string&); 156 int set_input_device_name (const std::string&); 157 int set_output_device_name (const std::string&); 158 int set_sample_rate (float); 159 int set_buffer_size (uint32_t); 160 int set_peridod_size (uint32_t); 161 int set_interleaved (bool yn); 162 int set_input_channels (uint32_t); 163 int set_output_channels (uint32_t); 164 int set_systemic_input_latency (uint32_t); 165 int set_systemic_output_latency (uint32_t); 166 int set_systemic_midi_input_latency (std::string const, uint32_t); 167 int set_systemic_midi_output_latency (std::string const, uint32_t); 168 reset_device()169 int reset_device () { return 0; }; 170 171 /* Retrieving parameters */ 172 std::string device_name () const; 173 std::string input_device_name () const; 174 std::string output_device_name () const; 175 float sample_rate () const; 176 uint32_t buffer_size () const; 177 uint32_t period_size () const; 178 bool interleaved () const; 179 uint32_t input_channels () const; 180 uint32_t output_channels () const; 181 uint32_t systemic_input_latency () const; 182 uint32_t systemic_output_latency () const; 183 uint32_t systemic_midi_input_latency (std::string const) const; 184 uint32_t systemic_midi_output_latency (std::string const) const; 185 can_set_systemic_midi_latencies()186 bool can_set_systemic_midi_latencies () const { return true; } 187 188 /* External control app */ control_app_name()189 std::string control_app_name () const { return std::string (); } launch_control_app()190 void launch_control_app () {} 191 192 /* MIDI */ 193 std::vector<std::string> enumerate_midi_options () const; 194 int set_midi_option (const std::string&); 195 std::string midi_option () const; 196 197 std::vector<DeviceStatus> enumerate_midi_devices () const; 198 int set_midi_device_enabled (std::string const, bool); 199 bool midi_device_enabled (std::string const) const; 200 201 /* State Control */ 202 protected: 203 int _start (bool for_latency_measurement); 204 public: 205 int stop (); 206 int freewheel (bool); 207 float dsp_load () const; 208 size_t raw_buffer_size (DataType t); 209 210 /* Process time */ 211 samplepos_t sample_time (); 212 samplepos_t sample_time_at_cycle_start (); 213 pframes_t samples_since_cycle_start (); 214 215 int create_process_thread (boost::function<void()> func); 216 int join_process_threads (); 217 bool in_process_thread (); 218 uint32_t process_thread_count (); 219 220 void update_latencies (); 221 222 /* PORTENGINE API */ 223 224 void* private_handle () const; 225 const std::string& my_name () const; 226 227 /* PortEngine API - forwarded to PortEngineSharedImpl */ 228 port_is_physical(PortEngine::PortHandle ph)229 bool port_is_physical (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_is_physical (ph); } get_physical_outputs(DataType type,std::vector<std::string> & results)230 void get_physical_outputs (DataType type, std::vector<std::string>& results) { PortEngineSharedImpl::get_physical_outputs (type, results); } get_physical_inputs(DataType type,std::vector<std::string> & results)231 void get_physical_inputs (DataType type, std::vector<std::string>& results) { PortEngineSharedImpl::get_physical_inputs (type, results); } n_physical_outputs()232 ChanCount n_physical_outputs () const { return PortEngineSharedImpl::n_physical_outputs (); } n_physical_inputs()233 ChanCount n_physical_inputs () const { return PortEngineSharedImpl::n_physical_inputs (); } port_name_size()234 uint32_t port_name_size () const { return PortEngineSharedImpl::port_name_size(); } set_port_name(PortEngine::PortHandle ph,const std::string & name)235 int set_port_name (PortEngine::PortHandle ph, const std::string& name) { return PortEngineSharedImpl::set_port_name (ph, name); } get_port_name(PortEngine::PortHandle ph)236 std::string get_port_name (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_name (ph); } get_port_flags(PortEngine::PortHandle ph)237 PortFlags get_port_flags (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::get_port_flags (ph); } get_port_by_name(std::string const & name)238 PortEngine::PortPtr get_port_by_name (std::string const & name) const { return PortEngineSharedImpl::get_port_by_name (name); } get_port_property(PortEngine::PortHandle ph,const std::string & key,std::string & value,std::string & type)239 int get_port_property (PortEngine::PortHandle ph, const std::string& key, std::string& value, std::string& type) const { return PortEngineSharedImpl::get_port_property (ph, key, value, type); } set_port_property(PortEngine::PortHandle ph,const std::string & key,const std::string & value,const std::string & type)240 int set_port_property (PortEngine::PortHandle ph, const std::string& key, const std::string& value, const std::string& type) { return PortEngineSharedImpl::set_port_property (ph, key, value, type); } get_ports(const std::string & port_name_pattern,DataType type,PortFlags flags,std::vector<std::string> & results)241 int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& results) const { return PortEngineSharedImpl::get_ports (port_name_pattern, type, flags, results); } port_data_type(PortEngine::PortHandle ph)242 DataType port_data_type (PortEngine::PortHandle ph) const { return PortEngineSharedImpl::port_data_type (ph); } register_port(const std::string & shortname,ARDOUR::DataType type,ARDOUR::PortFlags flags)243 PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) { return PortEngineSharedImpl::register_port (shortname, type, flags); } unregister_port(PortHandle ph)244 void unregister_port (PortHandle ph) { if (!_run) return; PortEngineSharedImpl::unregister_port (ph); } connect(const std::string & src,const std::string & dst)245 int connect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::connect (src, dst); } disconnect(const std::string & src,const std::string & dst)246 int disconnect (const std::string& src, const std::string& dst) { return PortEngineSharedImpl::disconnect (src, dst); } connect(PortEngine::PortHandle ph,const std::string & other)247 int connect (PortEngine::PortHandle ph, const std::string& other) { return PortEngineSharedImpl::connect (ph, other); } disconnect(PortEngine::PortHandle ph,const std::string & other)248 int disconnect (PortEngine::PortHandle ph, const std::string& other) { return PortEngineSharedImpl::disconnect (ph, other); } disconnect_all(PortEngine::PortHandle ph)249 int disconnect_all (PortEngine::PortHandle ph) { return PortEngineSharedImpl::disconnect_all (ph); } connected(PortEngine::PortHandle ph,bool process_callback_safe)250 bool connected (PortEngine::PortHandle ph, bool process_callback_safe) { return PortEngineSharedImpl::connected (ph, process_callback_safe); } connected_to(PortEngine::PortHandle ph,const std::string & other,bool process_callback_safe)251 bool connected_to (PortEngine::PortHandle ph, const std::string& other, bool process_callback_safe) { return PortEngineSharedImpl::connected_to (ph, other, process_callback_safe); } physically_connected(PortEngine::PortHandle ph,bool process_callback_safe)252 bool physically_connected (PortEngine::PortHandle ph, bool process_callback_safe) { return PortEngineSharedImpl::physically_connected (ph, process_callback_safe); } get_connections(PortEngine::PortHandle ph,std::vector<std::string> & results,bool process_callback_safe)253 int get_connections (PortEngine::PortHandle ph, std::vector<std::string>& results, bool process_callback_safe) { return PortEngineSharedImpl::get_connections (ph, results, process_callback_safe); } 254 255 /* MIDI */ 256 int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t const** buf, void* port_buffer, uint32_t event_index); 257 int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size); 258 uint32_t get_midi_event_count (void* port_buffer); 259 void midi_clear (void* port_buffer); 260 261 /* Monitoring */ 262 263 bool can_monitor_input () const; 264 int request_input_monitoring (PortHandle, bool); 265 int ensure_input_monitoring (PortHandle, bool); 266 bool monitoring_input (PortHandle); 267 268 /* Latency management */ 269 270 void set_latency_range (PortHandle, bool for_playback, LatencyRange); 271 LatencyRange get_latency_range (PortHandle, bool for_playback); 272 273 /* Getting access to the data buffer for a port */ 274 275 void* get_buffer (PortHandle, pframes_t); 276 277 void* main_process_thread (); 278 279 private: 280 std::string _instance_name; 281 Alsa_pcmi *_pcmi; 282 283 bool _run; /* keep going or stop, ardour thread */ 284 bool _active; /* is running, process thread */ 285 bool _freewheel; 286 bool _freewheeling; 287 bool _measure_latency; 288 289 uint64_t _last_process_start; 290 291 static std::vector<std::string> _midi_options; 292 static std::vector<AudioBackend::DeviceStatus> _input_audio_device_status; 293 static std::vector<AudioBackend::DeviceStatus> _output_audio_device_status; 294 static std::vector<AudioBackend::DeviceStatus> _duplex_audio_device_status; 295 static std::vector<AudioBackend::DeviceStatus> _midi_device_status; 296 static ARDOUR::ALSADeviceInfo _input_audio_device_info; 297 static ARDOUR::ALSADeviceInfo _output_audio_device_info; 298 299 mutable std::string _input_audio_device; 300 mutable std::string _output_audio_device; 301 std::string _midi_driver_option; 302 303 /* audio device reservation */ 304 AlsaDeviceReservation _device_reservation; 305 306 /* audio settings */ 307 float _samplerate; 308 size_t _samples_per_period; 309 size_t _periods_per_cycle; 310 static size_t _max_buffer_size; 311 312 uint32_t _n_inputs; 313 uint32_t _n_outputs; 314 315 uint32_t _systemic_audio_input_latency; 316 uint32_t _systemic_audio_output_latency; 317 318 /* midi settings */ 319 struct AlsaMidiDeviceInfo { 320 bool enabled; 321 uint32_t systemic_input_latency; 322 uint32_t systemic_output_latency; 323 AlsaMidiDeviceInfo (bool en = true) enabledAlsaMidiDeviceInfo324 : enabled (en) 325 , systemic_input_latency (0) 326 , systemic_output_latency (0) 327 {} 328 }; 329 330 mutable std::map<std::string, struct AlsaMidiDeviceInfo *> _midi_devices; 331 struct AlsaMidiDeviceInfo * midi_device_info(std::string const) const; 332 333 /* midi device changes */ 334 void auto_update_midi_devices(); 335 bool listen_for_midi_device_changes (); 336 void stop_listen_for_midi_device_changes (); 337 void midi_device_thread (); 338 static void* _midi_device_thread (void *arg); 339 pthread_t _midi_device_thread_id; 340 bool _midi_device_thread_active; 341 342 pthread_mutex_t _device_port_mutex; 343 344 /* processing */ 345 float _dsp_load; 346 ARDOUR::DSPLoadCalculator _dsp_load_calc; 347 samplecnt_t _processed_samples; 348 pthread_t _main_thread; 349 350 /* DLL, track main process callback timing */ 351 double _t0, _t1; 352 353 /* process threads */ 354 static void* alsa_process_thread (void *); 355 std::vector<pthread_t> _threads; 356 357 struct ThreadData { 358 AlsaAudioBackend* engine; 359 boost::function<void ()> f; 360 size_t stacksize; 361 ThreadDataThreadData362 ThreadData (AlsaAudioBackend* e, boost::function<void ()> fp, size_t stacksz) 363 : engine (e) , f (fp) , stacksize (stacksz) {} 364 }; 365 366 /* port engine */ 367 368 BackendPort* port_factory (std::string const & name, ARDOUR::DataType dt, ARDOUR::PortFlags flags); 369 370 int register_system_audio_ports (); 371 int register_system_midi_ports (const std::string device = ""); 372 void update_system_port_latencies (); 373 374 std::vector<AlsaMidiOut *> _rmidi_out; 375 std::vector<AlsaMidiIn *> _rmidi_in; 376 377 void update_systemic_audio_latencies (); 378 void update_systemic_midi_latencies (); 379 380 class AudioSlave : public AlsaDeviceReservation, public AlsaAudioSlave { 381 public: 382 enum DuplexMode { 383 HalfDuplexIn = 1, 384 HalfDuplexOut = 2, 385 FullDuplex = 3 386 }; 387 388 AudioSlave ( 389 const char* device, 390 DuplexMode duplex, 391 unsigned int master_rate, 392 unsigned int master_samples_per_period, 393 unsigned int slave_rate, 394 unsigned int slave_samples_per_period, 395 unsigned int periods_per_cycle); 396 397 ~AudioSlave (); 398 399 bool active; // set in sync with process-cb 400 bool halt; 401 bool dead; 402 403 std::vector<BackendPortPtr> inputs; 404 std::vector<BackendPortPtr> outputs; 405 406 PBD::Signal0<void> UpdateLatency; 407 PBD::ScopedConnection latency_connection; 408 409 protected: 410 void update_latencies (uint32_t, uint32_t); 411 412 private: 413 PBD::ScopedConnection _halted_connection; 414 void halted (); 415 }; 416 417 /* additional re-sampled I/O */ 418 bool add_slave (const char* slave_device, 419 unsigned int slave_rate, 420 unsigned int slave_spp, 421 unsigned int slave_ppc, 422 AudioSlave::DuplexMode); 423 424 typedef std::vector<AudioSlave*> AudioSlaves; 425 AudioSlaves _slaves; 426 427 }; // class AlsaAudioBackend 428 429 } // namespace 430 431 #endif /* __libbackend_alsa_audiobackend_h__ */ 432