X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fbackends%2Falsa%2Falsa_audiobackend.h;h=bc2620ed9e6ce173c90967eb217c7a9fea5e8669;hb=335debfa2fed045dc80c43fb2ef62d89262fc8f8;hp=f9123875e6a371bb7994b5627114a9efacf65b53;hpb=32e05fa6403d42a034a786b8b63b27f2ec569fdf;p=ardour.git diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h index f9123875e6..bc2620ed9e 100644 --- a/libs/backends/alsa/alsa_audiobackend.h +++ b/libs/backends/alsa/alsa_audiobackend.h @@ -30,10 +30,14 @@ #include +#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" @@ -67,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; @@ -81,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); @@ -89,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; } @@ -109,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); @@ -142,13 +149,13 @@ class AlsaMidiPort : public AlsaPort { DataType type () const { return DataType::MIDI; }; void* get_buffer (pframes_t nframes); - const AlsaMidiBuffer const_buffer () const { return _buffer[_bufperiod]; } + 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 < 3) { _n_periods = n; } } + void set_n_periods(int n) { if (n > 0 && n < 4) { _n_periods = n; } } private: - AlsaMidiBuffer _buffer[2]; + AlsaMidiBuffer _buffer[3]; int _n_periods; int _bufperiod; }; // class AlsaMidiPort @@ -164,18 +171,32 @@ class AlsaAudioBackend : public AudioBackend { std::string name () const; bool is_realtime () const; + bool use_separate_input_and_output_devices () const { return true; } + bool match_input_output_devices_or_none () 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); @@ -188,8 +209,11 @@ class AlsaAudioBackend : public AudioBackend { /* 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; @@ -223,8 +247,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); @@ -245,6 +269,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; @@ -301,14 +328,22 @@ class AlsaAudioBackend : public AudioBackend { bool _run; /* keep going or stop, ardour thread */ bool _active; /* is running, process thread */ + bool _freewheel; bool _freewheeling; bool _measure_latency; + uint64_t _last_process_start; + static std::vector _midi_options; - static std::vector _audio_device_status; + 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 _audio_device; + mutable std::string _input_audio_device; + mutable std::string _output_audio_device; std::string _midi_driver_option; /* audio device reservation */ @@ -348,7 +383,8 @@ class AlsaAudioBackend : public AudioBackend { /* processing */ float _dsp_load; - uint64_t _processed_samples; + ARDOUR::DSPLoadCalculator _dsp_load_calc; + framecnt_t _processed_samples; pthread_t _main_thread; /* process threads */ @@ -367,18 +403,33 @@ 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 (); + 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; + 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; std::string b; @@ -405,18 +456,20 @@ class AlsaAudioBackend : public AudioBackend { } 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