2 Copyright (C) 2014 Waves Audio Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __gtk2_ardour__engine_state_controller__
21 #define __gtk2_ardour__engine_state_controller__
26 #include "ardour/types.h"
27 #include "ardour/audio_backend.h"
31 class AudioBackendInfo;
34 * @class EngineStateController
35 * @brief EngineStateController class.
37 * Implements usecases for Audio devices and Audio/Midi ports.
38 * Persistantly saves to the config device configuration settings and audio/midi port states
40 class EngineStateController
48 * Structure which represents AudioPort state
51 std::string name; ///< Audio Port name
52 bool active; ///< Audio Port state
60 PortState (const std::string& name)
66 bool operator==(const PortState& rhs) {return rhs.name == name; }
70 /// @typedef Type for the list of all available audio ports
71 typedef std::list<PortState> PortStateList;
74 * @struct MidiPortState
75 * Structure which represents MidiPort state.
79 std::string name; ///< Midi Port name
80 bool active; ///< Midi Port state
81 bool available; ///< Midi Port availability - if it is physicaly available or not
82 bool scene_connected; ///< Is midi port used for scene MIDI marker in/out
83 bool mtc_in; ///< Is midi port used as MTC in
85 MidiPortState(const std::string& name):
89 scene_connected(false),
93 bool operator==(const MidiPortState& rhs)
95 return name == rhs.name;
99 /// @typedef Type for the list of MidiPorts ever registered in the system
100 typedef std::list<MidiPortState> MidiPortStateList;
105 /** Get an instance of EngineStateController singleton.
106 * @return EngineStateController instance pointer
108 static EngineStateController* instance ();
110 /** Associate session with EngineStateController instance.
112 void set_session (Session* session);
114 /** Remove link to the associated session.
116 void remove_session ();
118 //////////////////////////////////////////////////////////////////////////////////////////////////////////
119 // General backend/device information methods
121 /** Provides names of all available backends.
123 * @param[out] available_backends - vector of available backends
125 void available_backends (std::vector<const AudioBackendInfo*>& available_backends);
127 /** Provides the name of currently used backend.
129 * @return the name of currently used backend
131 const std::string& get_current_backend_name() const;
133 /** Provides the name of currently used device.
135 * @return the name of currently used device
137 const std::string& get_current_device_name () const;
139 /** Provides names for all available devices.
141 * @param[out] device_vector - vector of available devices
143 void enumerate_devices (std::vector<ARDOUR::AudioBackend::DeviceStatus>& device_vector) const;
145 /** Get sample rate used by current device.
147 * @return current sample rate
149 ARDOUR::framecnt_t get_current_sample_rate () const;
151 /** Get default sample rate for current backend.
153 * @return default sample rate for current backend
155 ARDOUR::framecnt_t get_default_sample_rate () const;
157 /** Get sample rates which are supported by current device and current backend.
159 * @param[out] sample_rates - vector of supported sample rates
161 void available_sample_rates_for_current_device (std::vector<float>& sample_rates) const;
163 /** Get buffer size used by current device.
165 * @return current buffer size
167 ARDOUR::pframes_t get_current_buffer_size () const;
169 /** Get default buffer size for current backend.
171 * @return default buffer size for current backend
173 ARDOUR::pframes_t get_default_buffer_size () const;
175 /** Get buffer sizes which are supported by current device and current backend.
177 * @param[out] buffer_sizes - vector of supported buffer_sizes
179 void available_buffer_sizes_for_current_device (std::vector<ARDOUR::pframes_t>& buffer_sizes) const;
181 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182 // device state control methods
184 /** Get the number of all enabled Audio inputs.
186 * @return number of all enabled Audio inputs
188 uint32_t get_available_inputs_count() const;
189 /** Get the number of all enabled Audio outputs.
191 * @return number of all enabled Audio outputs
193 uint32_t get_available_outputs_count () const;
195 /** Get vector of all enabled physical Audio input port names.
197 * @param[out] port_names - vector of all enabled Audio input names
199 void get_physical_audio_inputs (std::vector<std::string>& port_names);
200 /** Get vector of all enabled physical Audio input port names.
202 * @param[out] port_names - vector of all enabled Audio input names
204 void get_physical_audio_outputs (std::vector<std::string>& port_names);
206 /** Get vector of all enabled physical MIDI input port names.
208 * @param[out] port_names - vector of all enabled MIDI input names
210 void get_physical_midi_inputs (std::vector<std::string>& port_names);
211 /** Get vector of all enabled physical MIDI output port names.
213 * @param[out] port_names - vector of all enabled MIDI output names
215 void get_physical_midi_outputs (std::vector<std::string>& port_names);
217 /** Sets new state to all Audio inputs.
219 * @param[in] state - new state
221 void set_state_to_all_inputs(bool state);
222 /** Sets new state to all Audio outputs.
223 * @note Does nothing in Stereo Out mode
224 * @param[in] state - new state
226 void set_state_to_all_outputs(bool state);
228 /** Get vector of states for all physical Audio input ports.
230 * @param[out] channel_states - vector of input port states
232 void get_physical_audio_input_states(std::vector<PortState>& channel_states);
233 /** Get vector of states for all physical Audio output ports.
235 * @param[out] channel_states - vector of output port states
237 void get_physical_audio_output_states(std::vector<PortState>& channel_states);
239 /** Set state of the specified Audio input port.
241 * @param[in] port_name - input name
242 * @param[in] state - new state
244 void set_physical_audio_input_state(const std::string& port_name, bool state);
245 /** Set state of the specified Audio output port.
247 * @param[in] port_name - output name
248 * @param[in] state - new state
250 void set_physical_audio_output_state(const std::string& port_name, bool state);
252 /** Get state of the specified Audio input port.
254 * @param[in] port_name - input name
255 * @return input state
257 bool get_physical_audio_input_state(const std::string& port_name);
258 /** Get state of the specified Audi output port.
260 * @param[in] port_name - output name
261 * @return output state
263 bool get_physical_audio_output_state(const std::string& port_name);
265 /** Get vector of all enabled MIDI input port names.
267 * @param[out] channel_states - vector of enabled inputs
269 void get_physical_midi_input_states (std::vector<MidiPortState>& channel_states);
270 /** Get vector of all enabled MIDI output port names.
272 * @param[out] channel_states - vector of enabled outputs
274 void get_physical_midi_output_states (std::vector<MidiPortState>& channel_states);
276 /** Set state of the specified MIDI input port.
278 * @param[in] port_name - input name
279 * @param[in] state - new state
281 void set_physical_midi_input_state(const std::string& port_name, bool state);
282 /** Set state of the specified MIDI output port.
284 * @param[in] port_name - output name
285 * @param[in] state - new state
287 void set_physical_midi_output_state(const std::string& port_name, bool state);
288 /** Get state of the specified MIDI input port.
290 * @param[in] port_name - input name
291 * @param[out] scene_connected - is port used as Scene In or not
292 * @return input state
294 bool get_physical_midi_input_state(const std::string& port_name, bool& scene_connected);
295 /** Get state of the specified MIDI output port.
297 * @param[in] port_name - output name
298 * @param[out] scene_connected - is port used as Scene Out or not
299 * @return output state
301 bool get_physical_midi_output_state(const std::string& port_name, bool& scene_connected);
303 /** Set state of Scene In connection for the specified MIDI input port.
305 * @param[in] port_name - input name
306 * @param[in] state - new state
308 void set_physical_midi_scene_in_connection_state(const std::string& port_name, bool state);
309 /** Set state of Scene Out connection for the specified MIDI output port.
311 * @param[in] port_name - input name
312 * @param[in] state - new state
314 void set_physical_midi_scenen_out_connection_state(const std::string&, bool);
316 /** Disocnnect all MIDI input ports from Scene In.
318 void set_all_midi_scene_inputs_disconnected();
319 /** Disocnnect all MIDI output ports from Scene Out.
321 void set_all_midi_scene_outputs_disconnected();
323 /** Set MIDI TimeCode input port
324 * @note There is a sense to choose MIDI TimeCode input only because
325 * our MIDI TimeCode is propagated to all midi output ports.
327 void set_mtc_input(const std::string&);
329 /** Check if AudioEngine setup is required
330 * @return true if setup is required, otherwise - false
332 bool is_setup_required() const {return ARDOUR::AudioEngine::instance()->setup_required (); }
334 ////////////////////////////////////////////////////////////////////////////////////////////////////
335 // Methods set parameters inside the controller
336 // the state of engine won't change untill we make a "push" of this state to the backend
337 // NOTE: Use push_state_to_backend() method to update backend with the most recent controller state
339 /** Set new sample rate for current device in EngineStateController database
340 * @note Use push_state_to_backend() method to update backend/device state with the most recent controller state
341 * @param sample_rate - new sample rate
343 bool set_new_sample_rate_in_controller(framecnt_t sample_rate);
344 /** Set new buffer size for current device in EngineStateController database
345 * @note Use push_state_to_backend() method to update backend/device state with the most recent controller state
346 * @param buffer_size - new buffer size
348 bool set_new_buffer_size_in_controller(pframes_t buffer_size);
350 /** @brief push current controller state to backend.
351 * Propagate and set all current EngineStateController parameters to the backend
352 * @note Engine will be restarted if it's running when this method is called.
353 * @note If an attempt ot set parameters is unsuccessful current device will be switched to "None".
354 * @param start - start the Engine if it was not running when this function was called.
355 * @return true on success, otherwise - false
357 bool push_current_state_to_backend(bool start);
358 /** Switch to new backend
359 * @note The change will be propagated emmidiatelly as if push_current_state_to_backend () was called.
360 * @param backend_name - new backend name.
361 * @return true on success, otherwise - false
363 bool set_new_backend_as_current(const std::string& backend_name);
364 /** Switch to new device
365 * @note The change will be propagated emmidiatelly as if push_current_state_to_backend () was called.
366 * @param device_name - new device name.
367 * @return true on success, otherwise - false
369 bool set_new_device_as_current(const std::string& device_name);
372 ////////////////////////////////////////////////////////////////////////////////////////////////////
373 // Methods to save/serialize setting states
375 /** Serialize Audio/Midi settings (entire EngineStateController database) to XML
376 * @return XML note with serialized states
378 XMLNode& serialize_audio_midi_settings();
379 /** Save Audio/Midi settings (entire EngineStateController database) to config persistently
381 void save_audio_midi_settings();
383 ////////////////////////////////////////////////////////////////////////////////////////////////////
385 /** This signal is emitted if the sample rate changes */
386 PBD::Signal0<void> SampleRateChanged;
387 /** This signal is emitted if the buffer size changes */
388 PBD::Signal0<void> BufferSizeChanged;
389 /** This signal is emitted if the device list changes */
390 PBD::Signal1<void, bool> DeviceListChanged;
391 /** This signal is emitted if the device cannot operate properly */
392 PBD::Signal0<void> DeviceError;
394 ////////////////////////////////////////////////////////////////////////////////////////////////////
395 //ENGINE STATE SIGNALS
396 /** This signal is emitted when the engine is started */
397 PBD::Signal0<void> EngineRunning;
398 /** This signal is emitted when the engine is stopped */
399 PBD::Signal0<void> EngineStopped;
400 /** This signal is emitted if Engine processing is terminated */
401 PBD::Signal0<void> EngineHalted;
403 /** This signal is emitted if the AUDIO input channel configuration changes */
404 PBD::Signal0<void> InputConfigChanged;
405 /** This signal is emitted if the AUDIO output channel configuration changes */
406 PBD::Signal0<void> OutputConfigChanged;
407 /** This signal is emitted if the AUDIO output connection mode changes
408 * @note By output connection mode "Stereo Out" or "Multi Out" is meant
410 PBD::Signal0<void> OutputConnectionModeChanged;
412 /** This signals is emitted if the MIDI input channel configuration changes */
413 PBD::Signal0<void> MIDIInputConfigChanged;
414 /** This signals is emitted if the MIDI output channel configuration changes */
415 PBD::Signal0<void> MIDIOutputConfigChanged;
416 /** This signals is emitted if the MIDI Scene In connection changes */
417 PBD::Signal2<void, const std::vector<std::string>&, bool> MIDISceneInputConnectionChanged;
418 /** This signals is emitted if the MIDI Scene Out connection changes */
419 PBD::Signal2<void, const std::vector<std::string>&, bool> MIDISceneOutputConnectionChanged;
421 /** This signal is emitted if the MTC Input channel is changed */
422 PBD::Signal1<void, const std::string&> MTCInputChanged;
424 /** This signal is emitted if new Audio/MIDI ports are registered or unregistered */
425 PBD::Signal0<void> PortRegistrationChanged;
429 EngineStateController(); /// singleton
430 ~EngineStateController(); /// singleton
431 EngineStateController(const EngineStateController& ); /// prohibited
432 EngineStateController& operator=(const EngineStateController&); /// prohibited
434 ////////////////////////////////////////////////////////////////////////////////////////////
435 // private data structures
437 /** @struct Engine state
438 * @brief State structure.
439 * Contains information about single device/backend state
442 std::string backend_name; ///< state backend name
443 std::string device_name; ///< state device name
444 ARDOUR::framecnt_t sample_rate; ///< sample rate used by the device in this state
445 ARDOUR::pframes_t buffer_size; ///< buffer size used by the device in this state
447 PortStateList input_channel_states; ///< states of device Audio inputs
448 PortStateList multi_out_channel_states; ///< states of device Audio inputs in Multi Out mode
449 PortStateList stereo_out_channel_states; ///< states of device Audio inputs in Stereo Out mode
450 bool active; ///< was this state the most recent active one
455 , input_channel_states (0)
456 , multi_out_channel_states (0)
457 , stereo_out_channel_states (0)
462 bool operator==(const State& rhs)
464 return (backend_name == rhs.backend_name) && (device_name == rhs.device_name);
467 /** Forms string name for the state
468 * @return name string
470 std::string form_state_name() {
471 return std::string("State:" + backend_name + ":" + device_name);
474 /** @struct StatepPredicate
475 * This predicate is used to identify a state during search in the list of states
477 struct StatePredicate
479 StatePredicate(const std::string& backend_name, const std::string& device_name)
480 : _backend_name (backend_name)
481 , _device_name (device_name)
484 bool operator()(boost::shared_ptr<ARDOUR::EngineStateController::State> rhs)
486 return (_backend_name == rhs->backend_name) && (_device_name == rhs->device_name);
490 std::string _backend_name;
491 std::string _device_name;
495 /// @typedef Type for the state pointer
496 typedef boost::shared_ptr<State> StatePtr;
497 /// @typedef Type for the list of states
498 typedef std::list<StatePtr> StateList;
500 ////////////////////////////////////////////////////////////////////////////////////////////////////
501 // methods to manage setting states
503 /** Deserializes and loads Engine and Audio port states from the config to EngineStateController
505 void _deserialize_and_load_engine_states();
506 /** Deserializes and loads MIDI port states from the config to EngineStateController
508 void _deserialize_and_load_midi_port_states();
509 /** Serializes Engine and Audio port states from EngineStateController to XML node
510 * @param[in,out] audio_midi_settings_node - node to serialize the satets to
512 void _serialize_engine_states(XMLNode* audio_midi_settings_node);
513 /** Serializes MIDI port states from EngineStateController to XML node
514 * @param[in,out] audio_midi_settings_node - node to serialize the satets to
516 void _serialize_midi_port_states(XMLNode* audio_midi_settings_node);
518 /** Provides initial state configuration.
519 * It loades the last active state if there is one and it is aplicable.
520 * Otherwise default state (None device with default sample rate and buffer size) is loaded.
522 void _do_initial_engine_setup();
524 /** Loades provided state.
525 * @note It's possible that provided state can't be loaded
526 * (device disconnected or reqested parameters are not supported anymore).
527 * @param state - state to apply
528 * @return true on success, otherwise - false
530 bool _apply_state(const StatePtr& state);
532 /** Gets available device channels from engine and updates internal controller state
534 void _update_device_channels_state();
536 /** Check "Stereo Out" mode channels state configuration and make it correspond Stereo Out mode requirements
538 void _refresh_stereo_out_channel_states();
540 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
541 // internal helper functions
542 /** make sure that current device parameters are supported and fit session requirements
543 * @return true if current state is valid and all parameters are supported, otherwise - false
545 bool _validate_current_device_state();
546 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
548 ////////////////////////////////////////
550 /** Invoked when Engine starts running
552 void _on_engine_running();
553 /** Invoked when Engine is halted
555 void _on_engine_halted();
556 /** Invoked when Engine processing is terminated
558 void _on_engine_stopped();
559 /** Invoked when Device error accured, it failed to start or didn't accept the change which should
561 void _on_device_error();
562 /** Invoked when current device changes sample rate
564 void _on_sample_rate_change(ARDOUR::framecnt_t);
565 /** Invoked when current device changes buffer size
567 void _on_buffer_size_change(ARDOUR::pframes_t);
568 /** Invoked when the list of available devices is changed
570 void _on_device_list_change();
571 /** Invoked when the config parameter is changed
573 void _on_parameter_changed (const std::string&);
574 /** Invoked when Audio/MIDI ports are registered or unregistered
576 void _on_ports_registration_update ();
577 /** Invoked when session loading process is complete
579 void _on_session_loaded();
580 ////////////////////////////////////////
582 ////////////////////////////////////////
584 StatePtr _current_state; ///< current state pointer
585 // list of system states
586 StateList _states; ///< list of all available states
588 MidiPortStateList _midi_inputs; ///< midi input states
589 MidiPortStateList _midi_outputs; ///< midi output states
591 std::string _last_used_real_device; ///< last active non-default (real) device
593 Session* _session; ///< current session
595 // Engine connections stuff
596 PBD::ScopedConnectionList update_connections; ///< connection container for update signals
597 PBD::ScopedConnectionList session_connections; ///< connection container for session signals
598 PBD::ScopedConnection running_connection; ///< connection container for EngineRunning signal
599 PBD::ScopedConnection halt_connection; ///< connection container for EngineHalted signal
600 PBD::ScopedConnection stopped_connection; ///< connection container for EngineStopped signal
603 } // namespace ARDOUR
605 #endif /* defined(__gtk2_ardour__engine_state_controller__) */