X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Falsa%2Falsa_audiobackend.h;h=d8dfb31725453f1e6490e26be51f94b697fb040d;hb=69cbcb84a66cfc48d734692ae0f2f8d8bee4f5b5;hp=7ff172efbb15b9d427810184faf8065853b109ca;hpb=5cd2010c790875fc10eb7728f6f73462bf0a2198;p=ardour.git diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h index 7ff172efbb..d8dfb31725 100644 --- a/libs/backends/alsa/alsa_audiobackend.h +++ b/libs/backends/alsa/alsa_audiobackend.h @@ -30,11 +30,17 @@ #include -#include "ardour/types.h" +#include "pbd/natsort.h" #include "ardour/audio_backend.h" +#include "ardour/dsp_load_calculator.h" +#include "ardour/system_exec.h" +#include "ardour/types.h" + +#include "ardouralsautil/deviceinfo.h" #include "zita-alsa-pcmi.h" #include "alsa_rawmidi.h" +#include "alsa_sequencer.h" namespace ARDOUR { @@ -65,9 +71,11 @@ class AlsaPort { virtual ~AlsaPort (); const std::string& name () const { return _name; } + const std::string& pretty_name () const { return _pretty_name; } PortFlags flags () const { return _flags; } int set_name (const std::string &name) { _name = name; return 0; } + int set_pretty_name (const std::string &name) { _pretty_name = name; return 0; } virtual DataType type () const = 0; @@ -79,7 +87,7 @@ class AlsaPort { bool is_connected (const AlsaPort *port) const; bool is_physically_connected () const; - const std::vector& get_connections () const { return _connections; } + const std::set& get_connections () const { return _connections; } int connect (AlsaPort *port); int disconnect (AlsaPort *port); @@ -87,7 +95,7 @@ class AlsaPort { virtual void* get_buffer (pframes_t nframes) = 0; - const LatencyRange& latency_range (bool for_playback) const + const LatencyRange latency_range (bool for_playback) const { return for_playback ? _playback_latency_range : _capture_latency_range; } @@ -107,10 +115,11 @@ class AlsaPort { private: AlsaAudioBackend &_alsa_backend; std::string _name; + std::string _pretty_name; const PortFlags _flags; LatencyRange _capture_latency_range; LatencyRange _playback_latency_range; - std::vector _connections; + std::set _connections; void _connect (AlsaPort* , bool); void _disconnect (AlsaPort* , bool); @@ -140,10 +149,15 @@ class AlsaMidiPort : public AlsaPort { DataType type () const { return DataType::MIDI; }; void* get_buffer (pframes_t nframes); - const AlsaMidiBuffer const_buffer () const { return _buffer; } + const AlsaMidiBuffer * const_buffer () const { return & _buffer[_bufperiod]; } + + void next_period() { if (_n_periods > 1) { get_buffer(0); _bufperiod = (_bufperiod + 1) % _n_periods; } } + void set_n_periods(int n) { if (n > 0 && n < 4) { _n_periods = n; } } private: - AlsaMidiBuffer _buffer; + AlsaMidiBuffer _buffer[3]; + int _n_periods; + int _bufperiod; }; // class AlsaMidiPort class AlsaAudioBackend : public AudioBackend { @@ -157,33 +171,57 @@ class AlsaAudioBackend : public AudioBackend { std::string name () const; bool is_realtime () const; + bool use_separate_input_and_output_devices () const { return true; } + bool can_set_period_size () const { return true; } + std::vector enumerate_devices () const; + std::vector enumerate_input_devices () const; + std::vector enumerate_output_devices () const; std::vector available_sample_rates (const std::string& device) const; + std::vector available_sample_rates2 (const std::string&, const std::string&) const; std::vector available_buffer_sizes (const std::string& device) const; + std::vector available_buffer_sizes2 (const std::string&, const std::string&) const; + std::vector available_period_sizes (const std::string& driver) const; uint32_t available_input_channel_count (const std::string& device) const; uint32_t available_output_channel_count (const std::string& device) const; bool can_change_sample_rate_when_running () const; bool can_change_buffer_size_when_running () const; + bool can_change_systemic_latency_when_running () const { return true; } + int set_device_name (const std::string&); + int set_input_device_name (const std::string&); + int set_output_device_name (const std::string&); int set_sample_rate (float); int set_buffer_size (uint32_t); + int set_peridod_size (uint32_t); int set_interleaved (bool yn); int set_input_channels (uint32_t); int set_output_channels (uint32_t); int set_systemic_input_latency (uint32_t); int set_systemic_output_latency (uint32_t); + int set_systemic_midi_input_latency (std::string const, uint32_t); + int set_systemic_midi_output_latency (std::string const, uint32_t); + + int reset_device () { return 0; }; /* Retrieving parameters */ std::string device_name () const; + std::string input_device_name () const; + std::string output_device_name () const; float sample_rate () const; uint32_t buffer_size () const; + uint32_t period_size () const; bool interleaved () const; uint32_t input_channels () const; uint32_t output_channels () const; uint32_t systemic_input_latency () const; uint32_t systemic_output_latency () const; + uint32_t systemic_midi_input_latency (std::string const) const; + uint32_t systemic_midi_output_latency (std::string const) const; + + bool can_set_systemic_midi_latencies () const { return true; } /* External control app */ std::string control_app_name () const { return std::string (); } @@ -194,6 +232,10 @@ class AlsaAudioBackend : public AudioBackend { int set_midi_option (const std::string&); std::string midi_option () const; + std::vector enumerate_midi_devices () const; + int set_midi_device_enabled (std::string const, bool); + bool midi_device_enabled (std::string const) const; + /* State Control */ protected: int _start (bool for_latency_measurement); @@ -204,8 +246,8 @@ class AlsaAudioBackend : public AudioBackend { size_t raw_buffer_size (DataType t); /* Process time */ - pframes_t sample_time (); - pframes_t sample_time_at_cycle_start (); + framepos_t sample_time (); + framepos_t sample_time_at_cycle_start (); pframes_t samples_since_cycle_start (); int create_process_thread (boost::function func); @@ -226,6 +268,9 @@ class AlsaAudioBackend : public AudioBackend { std::string get_port_name (PortHandle) const; PortHandle get_port_by_name (const std::string&) const; + int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const; + int set_port_property (PortHandle, const std::string& key, const std::string& value, const std::string& type); + int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector&) const; DataType port_data_type (PortHandle) const; @@ -280,28 +325,65 @@ class AlsaAudioBackend : public AudioBackend { std::string _instance_name; Alsa_pcmi *_pcmi; - bool _running; + bool _run; /* keep going or stop, ardour thread */ + bool _active; /* is running, process thread */ + bool _freewheel; bool _freewheeling; - - void enumerate_midi_devices (std::vector &) const; - std::string _capture_device; - std::string _playback_device; - std::string _midi_device; - + bool _measure_latency; + + uint64_t _last_process_start; + + static std::vector _midi_options; + static std::vector _input_audio_device_status; + static std::vector _output_audio_device_status; + static std::vector _duplex_audio_device_status; + static std::vector _midi_device_status; + static ARDOUR::ALSADeviceInfo _input_audio_device_info; + static ARDOUR::ALSADeviceInfo _output_audio_device_info; + + mutable std::string _input_audio_device; + mutable std::string _output_audio_device; + std::string _midi_driver_option; + + /* audio device reservation */ + ARDOUR::SystemExec *_device_reservation; + PBD::ScopedConnectionList _reservation_connection; + void reservation_stdout (std::string, size_t); + bool acquire_device(const char* device_name); + void release_device(); + bool _reservation_succeeded; + + /* audio settings */ float _samplerate; size_t _samples_per_period; size_t _periods_per_cycle; - float _dsp_load; static size_t _max_buffer_size; uint32_t _n_inputs; uint32_t _n_outputs; - uint32_t _systemic_input_latency; - uint32_t _systemic_output_latency; + uint32_t _systemic_audio_input_latency; + uint32_t _systemic_audio_output_latency; + + /* midi settings */ + struct AlsaMidiDeviceInfo { + bool enabled; + uint32_t systemic_input_latency; + uint32_t systemic_output_latency; + AlsaMidiDeviceInfo() + : enabled (true) + , systemic_input_latency (0) + , systemic_output_latency (0) + {} + }; - uint64_t _processed_samples; + mutable std::map _midi_devices; + struct AlsaMidiDeviceInfo * midi_device_info(std::string const) const; + /* processing */ + float _dsp_load; + ARDOUR::DSPLoadCalculator _dsp_load_calc; + framecnt_t _processed_samples; pthread_t _main_thread; /* process threads */ @@ -320,17 +402,32 @@ class AlsaAudioBackend : public AudioBackend { /* port engine */ PortHandle add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); int register_system_audio_ports (); - int register_system_midi_ports (); - void unregister_system_ports (); + int register_system_midi_ports (const std::string device = ""); + void unregister_ports (bool system_only = false); - std::vector _ports; std::vector _system_inputs; std::vector _system_outputs; std::vector _system_midi_in; std::vector _system_midi_out; - std::vector _rmidi_out; - std::vector _rmidi_in; + struct SortByPortName + { + bool operator ()(const AlsaPort* lhs, const AlsaPort* rhs) const + { + return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ()); + } + }; + + typedef std::map PortMap; // fast lookup in _ports + typedef std::set PortIndex; // fast lookup in _ports + PortMap _portmap; + PortIndex _ports; + + std::vector _rmidi_out; + std::vector _rmidi_in; + + unsigned _midi_ins; + unsigned _midi_outs; struct PortConnectData { std::string a; @@ -343,6 +440,7 @@ class AlsaAudioBackend : public AudioBackend { std::vector _port_connection_queue; pthread_mutex_t _port_callback_mutex; + bool _port_change_flag; void port_connect_callback (const std::string& a, const std::string& b, bool conn) { pthread_mutex_lock (&_port_callback_mutex); @@ -350,19 +448,27 @@ class AlsaAudioBackend : public AudioBackend { pthread_mutex_unlock (&_port_callback_mutex); } + void port_connect_add_remove_callback () { + pthread_mutex_lock (&_port_callback_mutex); + _port_change_flag = true; + pthread_mutex_unlock (&_port_callback_mutex); + } + bool valid_port (PortHandle port) const { - return std::find (_ports.begin (), _ports.end (), (AlsaPort*)port) != _ports.end (); + return std::find (_ports.begin(), _ports.end(), static_cast(port)) != _ports.end (); } - AlsaPort * find_port (const std::string& port_name) const { - for (std::vector::const_iterator it = _ports.begin (); it != _ports.end (); ++it) { - if ((*it)->name () == port_name) { - return *it; - } + AlsaPort* find_port (const std::string& port_name) const { + PortMap::const_iterator it = _portmap.find (port_name); + if (it == _portmap.end()) { + return NULL; } - return NULL; + return (*it).second; } + void update_systemic_audio_latencies (); + void update_systemic_midi_latencies (); + }; // class AlsaAudioBackend } // namespace