X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fardour%2Faudioengine.h;h=4412faca2212fe1ae95b14b213b1c18e6ba1e954;hb=1c4d00e8b70785ce58f868645dad93afa1855193;hp=cf0eafe2884f1df799e1cb4f3a7ae039b416b2d6;hpb=dde0848a984e06cbc1d4117d9cffa75c191f3b39;p=ardour.git diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index cf0eafe288..4412faca22 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -20,25 +20,38 @@ #ifndef __ardour_audioengine_h__ #define __ardour_audioengine_h__ +#ifdef WAF_BUILD +#include "libardour-config.h" +#endif + +#include #include #include #include #include #include +#include -#include - -#include "pbd/rcu.h" #include "pbd/signals.h" +#include "pbd/stacktrace.h" -#include "ardour/ardour.h" +#include #include #include +#include + +#include "ardour/ardour.h" #include "ardour/data_type.h" #include "ardour/session_handle.h" #include "ardour/types.h" +#include "ardour/chan_count.h" +#include "ardour/port_manager.h" + +#ifdef HAVE_JACK_SESSION +#include +#endif namespace ARDOUR { @@ -46,244 +59,190 @@ class InternalPort; class MidiPort; class Port; class Session; +class ProcessThread; +class AudioBackend; +class AudioBackendInfo; -class AudioEngine : public SessionHandlePtr +class AudioEngine : public SessionHandlePtr, public PortManager { - public: - typedef std::set Ports; - - AudioEngine (std::string client_name); - virtual ~AudioEngine (); - - jack_client_t* jack() const; - bool connected() const { return _jack != 0; } - - bool is_realtime () const; - - std::string client_name() const { return jack_client_name; } - - int reconnect_to_jack (); - int disconnect_from_jack(); - - bool will_reconnect_at_halt (); - void set_reconnect_at_halt (bool); - - int stop (bool forever = false); - int start (); - bool running() const { return _running; } - - Glib::Mutex& process_lock() { return _process_lock; } - - nframes_t frame_rate() const; - nframes_t frames_per_cycle() const; - - size_t raw_buffer_size(DataType t); - - int usecs_per_cycle () const { return _usecs_per_cycle; } - - bool get_sync_offset (nframes_t& offset) const; - - nframes_t frames_since_cycle_start () { - jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) return 0; - return jack_frames_since_cycle_start (_priv_jack); - } - nframes_t frame_time () { - jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) return 0; - return jack_frame_time (_priv_jack); - } - - nframes_t transport_frame () const { - const jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) return 0; - return jack_get_current_transport_frame (_priv_jack); - } - - int request_buffer_size (nframes_t); - - nframes_t set_monitor_check_interval (nframes_t); - nframes_t processed_frames() const { return _processed_frames; } - - float get_cpu_load() { - jack_client_t* _priv_jack = _jack; - if (!_running || !_priv_jack) return 0; - return jack_cpu_load (_priv_jack); - } - - void set_session (Session *); - void remove_session (); // not a replacement for SessionHandle::session_going_away() - - class PortRegistrationFailure : public std::exception { - public: - PortRegistrationFailure (const char* why = "") { - reason = why; - } - virtual const char *what() const throw() { return reason; } - - private: - const char* reason; - }; - - class NoBackendAvailable : public std::exception { - public: - virtual const char *what() const throw() { return "could not connect to engine backend"; } - }; - - Port *register_input_port (DataType, const std::string& portname); - Port *register_output_port (DataType, const std::string& portname); - int unregister_port (Port &); - - void split_cycle (nframes_t offset); - - int connect (const std::string& source, const std::string& destination); - int disconnect (const std::string& source, const std::string& destination); - int disconnect (Port &); - - const char ** get_ports (const std::string& port_name_pattern, const std::string& type_name_pattern, uint32_t flags); - - bool can_request_hardware_monitoring (); - - uint32_t n_physical_outputs (DataType type) const; - uint32_t n_physical_inputs (DataType type) const; - - void get_physical_outputs (DataType type, std::vector&); - void get_physical_inputs (DataType type, std::vector&); - - std::string get_nth_physical_output (DataType type, uint32_t n) { - return get_nth_physical (type, n, JackPortIsInput); - } - - std::string get_nth_physical_input (DataType type, uint32_t n) { - return get_nth_physical (type, n, JackPortIsOutput); - } - - void update_total_latencies (); - void update_total_latency (const Port&); - - Port *get_port_by_name (const std::string &); - Port *get_port_by_name_locked (const std::string &); - - enum TransportState { - TransportStopped = JackTransportStopped, - TransportRolling = JackTransportRolling, - TransportLooping = JackTransportLooping, - TransportStarting = JackTransportStarting - }; - - void transport_start (); - void transport_stop (); - void transport_locate (nframes_t); - TransportState transport_state (); - - int reset_timebase (); - - /* start/stop freewheeling */ - - int freewheel (bool onoff); - bool freewheeling() const { return _freewheeling; } - - /* 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 if JACK notifies us of a graph order event */ - - PBD::Signal0 GraphReordered; - - /* this signal is emitted if the sample rate changes */ - - PBD::Signal1 SampleRateChanged; - - /* this signal is sent if JACK ever disconnects us */ - - PBD::Signal0 Halted; - - /* these two are emitted when the engine itself is - started and stopped - */ - - PBD::Signal0 Running; - PBD::Signal0 Stopped; - - /* this signal is emitted if a JACK port is registered or unregistered */ - - PBD::Signal0 PortRegisteredOrUnregistered; - - std::string make_port_name_relative (std::string); - std::string make_port_name_non_relative (std::string); - - static AudioEngine* instance() { return _instance; } - void died (); +public: + + static AudioEngine* create (); + + virtual ~AudioEngine (); + + int discover_backends(); + std::vector available_backends() const; + std::string current_backend_name () const; + int set_backend (const std::string&, const std::string& arg1, const std::string& arg2); + + 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 (); + int stop (); + int pause (); + int freewheel (bool start_stop); + float get_cpu_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, pthread_t*, size_t stacksize); + 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() + + 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; + + +#ifdef HAVE_JACK_SESSION + PBD::Signal1 JackSessionEvent; +#endif + + /* 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; + + /* these two are emitted as we create backends that + can actually be used to do stuff (e.g. register ports) + */ + + PBD::Signal0 BackendAvailable; + PBD::Signal0 BackendRemoved; + + 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 *); private: - static AudioEngine* _instance; - - jack_client_t* volatile _jack; /* could be reset to null by SIGPIPE or another thread */ - std::string jack_client_name; - Glib::Mutex _process_lock; - Glib::Cond session_removed; - bool session_remove_pending; - bool _running; - bool _has_run; - mutable nframes_t _buffer_size; - std::map _raw_buffer_sizes; - mutable nframes_t _frame_rate; - /// number of frames between each check for changes in monitor input - nframes_t monitor_check_interval; - /// time of the last monitor check in frames - nframes_t last_monitor_check; - /// the number of frames processed since start() was called - nframes_t _processed_frames; - bool _freewheeling; - bool _freewheel_pending; - bool _freewheel_thread_registered; - boost::function freewheel_action; - bool reconnect_on_halt; - int _usecs_per_cycle; - - SerializedRCUManager ports; - - Port *register_port (DataType type, const std::string& portname, bool input); - - int process_callback (nframes_t nframes); - void remove_all_ports (); - - std::string get_nth_physical (DataType type, uint32_t n, int flags); - - void port_registration_failure (const std::string& portname); - - static int _xrun_callback (void *arg); - static int _graph_order_callback (void *arg); - static int _process_callback (nframes_t nframes, void *arg); - static int _sample_rate_callback (nframes_t nframes, void *arg); - static int _bufsize_callback (nframes_t nframes, void *arg); - static void _jack_timebase_callback (jack_transport_state_t, nframes_t, jack_position_t*, int, void*); - static int _jack_sync_callback (jack_transport_state_t, jack_position_t*, void *arg); - static void _freewheel_callback (int , void *arg); - static void _registration_callback (jack_port_id_t, int, void *); - - void jack_timebase_callback (jack_transport_state_t, nframes_t, jack_position_t*, int); - int jack_sync_callback (jack_transport_state_t, jack_position_t*); - int jack_bufsize_callback (nframes_t); - int jack_sample_rate_callback (nframes_t); - - int connect_to_jack (std::string client_name); - - static void halted (void *); - - void meter_thread (); - void start_metering_thread (); - void stop_metering_thread (); - - Glib::Thread* m_meter_thread; - static gint m_meter_exit; + AudioEngine (); + + static AudioEngine* _instance; + + boost::shared_ptr _backend; + + 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 _has_run; + mutable framecnt_t _buffer_size; + std::map _raw_buffer_sizes; + mutable framecnt_t _frame_rate; + /// 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; + bool _freewheeling; + bool _pre_freewheel_mmc_enabled; + int _usecs_per_cycle; + bool port_remove_in_progress; + Glib::Threads::Thread* m_meter_thread; + ProcessThread* _main_thread; + + void meter_thread (); + void start_metering_thread (); + void stop_metering_thread (); + + static gint m_meter_exit; + + void parameter_changed (const std::string&); + PBD::ScopedConnection config_connection; + + typedef std::map BackendMap; + BackendMap _backends; + AudioBackendInfo* backend_discover (const std::string&); + void drop_backend (); }; - + } // namespace ARDOUR #endif /* __ardour_audioengine_h__ */