X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Faudioengine.h;h=f297e993b3c03cf30f9f2d5d3f63a3d6e16ffb41;hb=79abf3dfa6d649fbf1fb6fd16cd489f434d0b909;hp=75954e6ca9eb58337f3018611ff49e4facd8ed5e;hpb=37b1f5017e904005fae6b815b1519b3fa595d8d3;p=ardour.git diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 75954e6ca9..f297e993b3 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -1,19 +1,19 @@ /* - Copyright (C) 2002-2004 Paul Davis + Copyright (C) 2002-2004 Paul Davis - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ @@ -44,207 +44,276 @@ #include "ardour/chan_count.h" #include "ardour/port_manager.h" -#ifdef HAVE_JACK_SESSION -#include -#endif - class MTDM; namespace ARDOUR { class InternalPort; class MidiPort; +class MIDIDM; class Port; class Session; class ProcessThread; class AudioBackend; -class AudioBackendInfo; +struct AudioBackendInfo; -class LIBARDOUR_API AudioEngine : public SessionHandlePtr, public PortManager +class LIBARDOUR_API AudioEngine : public PortManager, public SessionHandlePtr { -public: - - static AudioEngine* create (); - - virtual ~AudioEngine (); - - int discover_backends(); - std::vector available_backends() const; - std::string current_backend_name () const; - boost::shared_ptr set_default_backend (); - boost::shared_ptr set_backend (const std::string&, const std::string& arg1, const std::string& arg2); - boost::shared_ptr current_backend() const { return _backend; } - bool setup_required () const; - - ProcessThread* main_thread() const { return _main_thread; } - - /* START BACKEND PROXY API - * - * See audio_backend.h for full documentation and semantics. These wrappers - * just forward to a backend implementation. - */ - - int start (bool for_latency_measurement=false); - int stop (bool for_latency_measurement=false); - int freewheel (bool start_stop); - float get_dsp_load() const ; - void transport_start (); - void transport_stop (); - TransportState transport_state (); - void transport_locate (framepos_t pos); - framepos_t transport_frame(); - framecnt_t sample_rate () const; - pframes_t samples_per_cycle () const; - int usecs_per_cycle () const; - size_t raw_buffer_size (DataType t); - pframes_t sample_time (); - pframes_t sample_time_at_cycle_start (); - pframes_t samples_since_cycle_start (); - bool get_sync_offset (pframes_t& offset) const; - - int create_process_thread (boost::function func); - int join_process_threads (); - bool in_process_thread (); - uint32_t process_thread_count (); - - bool is_realtime() const; - bool connected() const; - - int set_device_name (const std::string&); - int set_sample_rate (float); - int set_buffer_size (uint32_t); - int set_sample_format (SampleFormat); - 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); - - /* END BACKEND PROXY API */ - - bool freewheeling() const { return _freewheeling; } - bool running() const { return _running; } - - Glib::Threads::Mutex& process_lock() { return _process_lock; } - - int request_buffer_size (pframes_t samples) { - return set_buffer_size (samples); - } - - framecnt_t processed_frames() const { return _processed_frames; } - - void set_session (Session *); - void remove_session (); // not a replacement for SessionHandle::session_going_away() - Session* session() const { return _session; } - - class NoBackendAvailable : public std::exception { - public: - virtual const char *what() const throw() { return "could not connect to engine backend"; } - }; - - void split_cycle (pframes_t offset); - - int reset_timebase (); - - void update_latencies (); - - /* this signal is sent for every process() cycle while freewheeling. - (the regular process() call to session->process() is not made) - */ - - PBD::Signal1 Freewheel; - - PBD::Signal0 Xrun; - - /* this signal is emitted if the sample rate changes */ - - PBD::Signal1 SampleRateChanged; - - /* this signal is sent if the backend ever disconnects us */ - - PBD::Signal1 Halted; - - /* these two are emitted when the engine itself is - started and stopped - */ - - PBD::Signal0 Running; - PBD::Signal0 Stopped; - - static AudioEngine* instance() { return _instance; } - static void destroy(); - void died (); - - /* The backend will cause these at the appropriate time(s) - */ - int process_callback (pframes_t nframes); - int buffer_size_change (pframes_t nframes); - int sample_rate_change (pframes_t nframes); - void freewheel_callback (bool); - void timebase_callback (TransportState state, pframes_t nframes, framepos_t pos, int new_position); - int sync_callback (TransportState state, framepos_t position); - int port_registration_callback (); - void latency_callback (bool for_playback); - void halted_callback (const char* reason); - - /* sets up the process callback thread */ - static void thread_init_callback (void *); - - /* latency measurement */ - - MTDM* mtdm(); - int prepare_for_latency_measurement (); - int start_latency_detection (); - void stop_latency_detection (); - void set_latency_input_port (const std::string&); - void set_latency_output_port (const std::string&); - uint32_t latency_signal_delay () const { return _latency_signal_latency; } + public: + + static AudioEngine* create (); + + virtual ~AudioEngine (); + + int discover_backends(); + std::vector available_backends() const; + std::string current_backend_name () const; + boost::shared_ptr set_default_backend (); + boost::shared_ptr set_backend (const std::string&, const std::string& arg1, const std::string& arg2); + boost::shared_ptr current_backend() const { return _backend; } + bool setup_required () const; + + ProcessThread* main_thread() const { return _main_thread; } + + /* START BACKEND PROXY API + * + * See audio_backend.h for full documentation and semantics. These wrappers + * just forward to a backend implementation. + */ + + int start (bool for_latency_measurement=false); + int stop (bool for_latency_measurement=false); + int freewheel (bool start_stop); + float get_dsp_load() const ; + void transport_start (); + void transport_stop (); + TransportState transport_state (); + void transport_locate (framepos_t pos); + framepos_t transport_frame(); + framecnt_t sample_rate () const; + pframes_t samples_per_cycle () const; + int usecs_per_cycle () const; + size_t raw_buffer_size (DataType t); + framepos_t sample_time (); + framepos_t sample_time_at_cycle_start (); + pframes_t samples_since_cycle_start (); + bool get_sync_offset (pframes_t& offset) const; + + std::string get_last_backend_error () const { return _last_backend_error_string; } + + int create_process_thread (boost::function func); + int join_process_threads (); + bool in_process_thread (); + uint32_t process_thread_count (); + + int backend_reset_requested(); + void request_backend_reset(); + void request_device_list_update(); + void launch_device_control_app(); + + bool is_realtime() const; + bool connected() const; + + // for the user which hold state_lock to check if reset operation is pending + bool is_reset_requested() const { return g_atomic_int_get(const_cast(&_hw_reset_request_count)); } + + int set_device_name (const std::string&); + int set_sample_rate (float); + int set_buffer_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); + + /* END BACKEND PROXY API */ + + bool freewheeling() const { return _freewheeling; } + bool running() const { return _running; } + + Glib::Threads::Mutex& process_lock() { return _process_lock; } + Glib::Threads::RecMutex& state_lock() { return _state_lock; } + + int request_buffer_size (pframes_t samples) { + return set_buffer_size (samples); + } + + framecnt_t processed_frames() const { return _processed_frames; } + + void set_session (Session *); + void remove_session (); // not a replacement for SessionHandle::session_going_away() + Session* session() const { return _session; } + + void reconnect_session_routes (bool reconnect_inputs = true, bool reconnect_outputs = true); + + class NoBackendAvailable : public std::exception { + public: + virtual const char *what() const throw() { return "could not connect to engine backend"; } + }; + + void split_cycle (pframes_t offset); + + int reset_timebase (); + + void update_latencies (); + + /* this signal is sent for every process() cycle while freewheeling. + (the regular process() call to session->process() is not made) + */ + + PBD::Signal1 Freewheel; + + PBD::Signal0 Xrun; + + /** this signal is emitted if the sample rate changes */ + PBD::Signal1 SampleRateChanged; + + /** this signal is emitted if the buffer size changes */ + PBD::Signal1 BufferSizeChanged; + + /** this signal is emitted if the device cannot operate properly */ + PBD::Signal0 DeviceError; + + /* this signal is emitted if the device list changed */ + + PBD::Signal0 DeviceListChanged; + + /* this signal is sent if the backend ever disconnects us */ + + PBD::Signal1 Halted; + + /* these two are emitted when the engine itself is + started and stopped + */ + + PBD::Signal0 Running; + PBD::Signal0 Stopped; + + /* these two are emitted when a device reset is initiated/finished + */ + + PBD::Signal0 DeviceResetStarted; + PBD::Signal0 DeviceResetFinished; + + static AudioEngine* instance() { return _instance; } + static void destroy(); + void died (); + + /* The backend will cause these at the appropriate time(s) + */ + int process_callback (pframes_t nframes); + int buffer_size_change (pframes_t nframes); + int sample_rate_change (pframes_t nframes); + void freewheel_callback (bool); + void timebase_callback (TransportState state, pframes_t nframes, framepos_t pos, int new_position); + int sync_callback (TransportState state, framepos_t position); + int port_registration_callback (); + void latency_callback (bool for_playback); + void halted_callback (const char* reason); + + /* checks if current thread is properly set up for audio processing */ + static bool thread_initialised_for_audio_processing (); + + /* sets up the process callback thread */ + static void thread_init_callback (void *); + + /* latency measurement */ + + MTDM* mtdm() { return _mtdm; } + MIDIDM* mididm() { return _mididm; } + + int prepare_for_latency_measurement (); + int start_latency_detection (bool); + void stop_latency_detection (); + void set_latency_input_port (const std::string&); + void set_latency_output_port (const std::string&); + uint32_t latency_signal_delay () const { return _latency_signal_latency; } + + enum LatencyMeasurement { + MeasureNone, + MeasureAudio, + MeasureMIDI + }; + + LatencyMeasurement measuring_latency () const { return _measuring_latency; } + + /* These two are used only in builds where SILENCE_AFTER_SECONDS was + * set. BecameSilent will be emitted when the audioengine goes silent. + * reset_silence_countdown() can be used to reset the silence + * countdown, whose duration will be reduced to half of its previous + * value. + */ + + PBD::Signal0 BecameSilent; + void reset_silence_countdown (); + + void add_pending_port_deletion (Port*); private: - AudioEngine (); - - static AudioEngine* _instance; - - Glib::Threads::Mutex _process_lock; - Glib::Threads::Cond session_removed; - bool session_remove_pending; - frameoffset_t session_removal_countdown; - gain_t session_removal_gain; - gain_t session_removal_gain_step; - bool _running; - bool _freewheeling; - /// number of frames between each check for changes in monitor input - framecnt_t monitor_check_interval; - /// time of the last monitor check in frames - framecnt_t last_monitor_check; - /// the number of frames processed since start() was called - framecnt_t _processed_frames; - Glib::Threads::Thread* m_meter_thread; - ProcessThread* _main_thread; - MTDM* _mtdm; - bool _measuring_latency; - PortEngine::PortHandle _latency_input_port; - PortEngine::PortHandle _latency_output_port; - framecnt_t _latency_flush_frames; - std::string _latency_input_name; - std::string _latency_output_name; - framecnt_t _latency_signal_latency; - bool _stopped_for_latency; - bool _started_for_latency; - bool _in_destructor; - - void meter_thread (); - void start_metering_thread (); - void stop_metering_thread (); - - static gint m_meter_exit; - - typedef std::map BackendMap; - BackendMap _backends; - AudioBackendInfo* backend_discover (const std::string&); - void drop_backend (); + AudioEngine (); + + static AudioEngine* _instance; + + Glib::Threads::Mutex _process_lock; + Glib::Threads::RecMutex _state_lock; + Glib::Threads::Cond session_removed; + bool session_remove_pending; + frameoffset_t session_removal_countdown; + gain_t session_removal_gain; + gain_t session_removal_gain_step; + bool _running; + bool _freewheeling; + /// number of frames between each check for changes in monitor input + framecnt_t monitor_check_interval; + /// time of the last monitor check in frames + framecnt_t last_monitor_check; + /// the number of frames processed since start() was called + framecnt_t _processed_frames; + Glib::Threads::Thread* m_meter_thread; + ProcessThread* _main_thread; + MTDM* _mtdm; + MIDIDM* _mididm; + LatencyMeasurement _measuring_latency; + PortEngine::PortHandle _latency_input_port; + PortEngine::PortHandle _latency_output_port; + framecnt_t _latency_flush_frames; + std::string _latency_input_name; + std::string _latency_output_name; + framecnt_t _latency_signal_latency; + bool _stopped_for_latency; + bool _started_for_latency; + bool _in_destructor; + + std::string _last_backend_error_string; + + Glib::Threads::Thread* _hw_reset_event_thread; + gint _hw_reset_request_count; + Glib::Threads::Cond _hw_reset_condition; + Glib::Threads::Mutex _reset_request_lock; + gint _stop_hw_reset_processing; + Glib::Threads::Thread* _hw_devicelist_update_thread; + gint _hw_devicelist_update_count; + Glib::Threads::Cond _hw_devicelist_update_condition; + Glib::Threads::Mutex _devicelist_update_lock; + gint _stop_hw_devicelist_processing; + + void start_hw_event_processing(); + void stop_hw_event_processing(); + void do_reset_backend(); + void do_devicelist_update(); + + typedef std::map BackendMap; + BackendMap _backends; + AudioBackendInfo* backend_discover (const std::string&); + void drop_backend (); + +#ifdef SILENCE_AFTER + framecnt_t _silence_countdown; + uint32_t _silence_hit_cnt; +#endif + }; - + } // namespace ARDOUR #endif /* __ardour_audioengine_h__ */