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::samplecnt_t get_current_sample_rate () const;
151 /** Get default sample rate for current backend.
153 * @return default sample rate for current backend
155 ARDOUR::samplecnt_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);
266 /** Get vector of all enabled MIDI input port names.
268 * @param[out] channel_states - vector of enabled inputs
270 void get_physical_midi_input_states (std::vector<MidiPortState>& channel_states);
271 /** Get vector of all enabled MIDI output port names.
273 * @param[out] channel_states - vector of enabled outputs
275 void get_physical_midi_output_states (std::vector<MidiPortState>& channel_states);
277 /** Get name of mtc source port
279 * return name of mtc source port
281 std::string get_mtc_source_port ();
283 /** Set ltc source port
285 * @param[in] port - name of ltc source port
287 void set_ltc_source_port (const std::string& port);
288 /** Get name of ltc source port
290 * return name of ltc source port
292 std::string get_ltc_source_port ();
294 /** Set ltc output port
296 * @param[in] port - name of ltc output port
298 void set_ltc_output_port (const std::string&);
299 /** Get name of ltc output port
301 * return name of ltc output port
303 std::string get_ltc_output_port ();
305 /** Set state of the specified MIDI input port.
307 * @param[in] port_name - input name
308 * @param[in] state - new state
310 void set_physical_midi_input_state(const std::string& port_name, bool state);
311 /** Set state of the specified MIDI output port.
313 * @param[in] port_name - output name
314 * @param[in] state - new state
316 void set_physical_midi_output_state(const std::string& port_name, bool state);
317 /** Get state of the specified MIDI input port.
319 * @param[in] port_name - input name
320 * @param[out] scene_connected - is port used as Scene In or not
321 * @return input state
323 bool get_physical_midi_input_state(const std::string& port_name, bool& scene_connected);
324 /** Get state of the specified MIDI output port.
326 * @param[in] port_name - output name
327 * @param[out] scene_connected - is port used as Scene Out or not
328 * @return output state
330 bool get_physical_midi_output_state(const std::string& port_name, bool& scene_connected);
332 /** Set state of Scene In connection for the specified MIDI input port.
334 * @param[in] port_name - input name
335 * @param[in] state - new state
337 void set_physical_midi_scene_in_connection_state(const std::string& port_name, bool state);
338 /** Set state of Scene Out connection for the specified MIDI output port.
340 * @param[in] port_name - input name
341 * @param[in] state - new state
343 void set_physical_midi_scenen_out_connection_state(const std::string&, bool);
345 /** Disocnnect all MIDI input ports from Scene In.
347 void set_all_midi_scene_inputs_disconnected();
348 /** Disocnnect all MIDI output ports from Scene Out.
350 void set_all_midi_scene_outputs_disconnected();
352 /** Set MIDI TimeCode input port
353 * @note There is a sense to choose MIDI TimeCode input only because
354 * our MIDI TimeCode is propagated to all midi output ports.
356 void set_mtc_source_port (const std::string&);
358 /** Check if AudioEngine setup is required
359 * @return true if setup is required, otherwise - false
361 bool is_setup_required() const {return ARDOUR::AudioEngine::instance()->setup_required (); }
363 ////////////////////////////////////////////////////////////////////////////////////////////////////
364 // Methods set parameters inside the controller
365 // the state of engine won't change untill we make a "push" of this state to the backend
366 // NOTE: Use push_state_to_backend() method to update backend with the most recent controller state
368 /** Set new sample rate for current device in EngineStateController database
369 * @note Use push_state_to_backend() method to update backend/device state with the most recent controller state
370 * @param sample_rate - new sample rate
372 bool set_new_sample_rate_in_controller(samplecnt_t sample_rate);
373 /** Set new buffer size for current device in EngineStateController database
374 * @note Use push_state_to_backend() method to update backend/device state with the most recent controller state
375 * @param buffer_size - new buffer size
377 bool set_new_buffer_size_in_controller(pframes_t buffer_size);
379 /** @brief push current controller state to backend.
380 * Propagate and set all current EngineStateController parameters to the backend
381 * @note Engine will be restarted if it's running when this method is called.
382 * @note If an attempt ot set parameters is unsuccessful current device will be switched to "None".
383 * @param start - start the Engine if it was not running when this function was called.
384 * @return true on success, otherwise - false
386 bool push_current_state_to_backend(bool start);
387 /** Switch to new backend
388 * @note The change will be propagated emmidiatelly as if push_current_state_to_backend () was called.
389 * @param backend_name - new backend name.
390 * @return true on success, otherwise - false
392 bool set_new_backend_as_current(const std::string& backend_name);
393 /** Switch to new device
394 * @note The change will be propagated emmidiatelly as if push_current_state_to_backend () was called.
395 * @param device_name - new device name.
396 * @return true on success, otherwise - false
398 bool set_new_device_as_current(const std::string& device_name);
401 ////////////////////////////////////////////////////////////////////////////////////////////////////
402 // Methods to save/serialize setting states
404 /** Serialize Audio/Midi settings (entire EngineStateController database) to XML
405 * @return XML note with serialized states
407 XMLNode& serialize_audio_midi_settings();
408 /** Save Audio/Midi settings (entire EngineStateController database) to config persistently
410 void save_audio_midi_settings();
412 ////////////////////////////////////////////////////////////////////////////////////////////////////
414 /** This signal is emitted if the sample rate changes */
415 PBD::Signal0<void> SampleRateChanged;
416 /** This signal is emitted if the buffer size changes */
417 PBD::Signal0<void> BufferSizeChanged;
418 /** This signal is emitted if the device list changes */
419 PBD::Signal1<void, bool> DeviceListChanged;
420 /** This signal is emitted if the device cannot operate properly */
421 PBD::Signal0<void> DeviceError;
423 ////////////////////////////////////////////////////////////////////////////////////////////////////
424 //ENGINE STATE SIGNALS
425 /** This signal is emitted when the engine is started */
426 PBD::Signal0<void> EngineRunning;
427 /** This signal is emitted when the engine is stopped */
428 PBD::Signal0<void> EngineStopped;
429 /** This signal is emitted if Engine processing is terminated */
430 PBD::Signal0<void> EngineHalted;
432 /** This signal is emitted if the AUDIO input channel configuration changes */
433 PBD::Signal0<void> InputConfigChanged;
434 /** This signal is emitted if the AUDIO output channel configuration changes */
435 PBD::Signal0<void> OutputConfigChanged;
436 /** This signal is emitted if the AUDIO output connection mode changes
437 * @note By output connection mode "Stereo Out" or "Multi Out" is meant
439 PBD::Signal0<void> OutputConnectionModeChanged;
441 /** This signals is emitted if the MIDI input channel configuration changes */
442 PBD::Signal0<void> MIDIInputConfigChanged;
443 /** This signals is emitted if the MIDI output channel configuration changes */
444 PBD::Signal0<void> MIDIOutputConfigChanged;
445 /** This signals is emitted if the MIDI Scene In connection changes */
446 PBD::Signal2<void, const std::vector<std::string>&, bool> MIDISceneInputConnectionChanged;
447 /** This signals is emitted if the MIDI Scene Out connection changes */
448 PBD::Signal2<void, const std::vector<std::string>&, bool> MIDISceneOutputConnectionChanged;
450 /** This signal is emitted if the MTC Input channel is changed */
451 PBD::Signal1<void, const std::string&> MTCInputChanged;
453 /** This signal is emitted if new Audio/MIDI ports are registered or unregistered */
454 PBD::Signal0<void> PortRegistrationChanged;
458 EngineStateController(); /// singleton
459 ~EngineStateController(); /// singleton
460 EngineStateController(const EngineStateController& ); /// prohibited
461 EngineStateController& operator=(const EngineStateController&); /// prohibited
463 ////////////////////////////////////////////////////////////////////////////////////////////
464 // private data structures
466 /** @struct Engine state
467 * @brief State structure.
468 * Contains information about single device/backend state
471 std::string backend_name; ///< state backend name
472 std::string device_name; ///< state device name
473 ARDOUR::samplecnt_t sample_rate; ///< sample rate used by the device in this state
474 ARDOUR::pframes_t buffer_size; ///< buffer size used by the device in this state
476 PortStateList input_channel_states; ///< states of device Audio inputs
477 PortStateList multi_out_channel_states; ///< states of device Audio inputs in Multi Out mode
478 PortStateList stereo_out_channel_states; ///< states of device Audio inputs in Stereo Out mode
479 bool active; ///< was this state the most recent active one
484 , input_channel_states (0)
485 , multi_out_channel_states (0)
486 , stereo_out_channel_states (0)
491 bool operator==(const State& rhs)
493 return (backend_name == rhs.backend_name) && (device_name == rhs.device_name);
496 /** Forms string name for the state
497 * @return name string
499 std::string form_state_name() {
500 return std::string("State:" + backend_name + ":" + device_name);
503 /** @struct StatepPredicate
504 * This predicate is used to identify a state during search in the list of states
506 struct StatePredicate
508 StatePredicate(const std::string& backend_name, const std::string& device_name)
509 : _backend_name (backend_name)
510 , _device_name (device_name)
513 bool operator()(boost::shared_ptr<ARDOUR::EngineStateController::State> rhs)
515 return (_backend_name == rhs->backend_name) && (_device_name == rhs->device_name);
519 std::string _backend_name;
520 std::string _device_name;
524 /// @typedef Type for the state pointer
525 typedef boost::shared_ptr<State> StatePtr;
526 /// @typedef Type for the list of states
527 typedef std::list<StatePtr> StateList;
529 ////////////////////////////////////////////////////////////////////////////////////////////////////
530 // methods to manage setting states
532 /** Deserializes and loads Engine and Audio port states from the config to EngineStateController
534 void _deserialize_and_load_engine_states();
535 /** Deserializes and loads MIDI port states from the config to EngineStateController
537 void _deserialize_and_load_midi_port_states();
538 /** Serializes Engine and Audio port states from EngineStateController to XML node
539 * @param[in,out] audio_midi_settings_node - node to serialize the satets to
541 void _serialize_engine_states(XMLNode* audio_midi_settings_node);
542 /** Serializes MIDI port states from EngineStateController to XML node
543 * @param[in,out] audio_midi_settings_node - node to serialize the satets to
545 void _serialize_midi_port_states(XMLNode* audio_midi_settings_node);
547 /** Provides initial state configuration.
548 * It loades the last active state if there is one and it is aplicable.
549 * Otherwise default state (None device with default sample rate and buffer size) is loaded.
551 void _do_initial_engine_setup();
553 /** Loades provided state.
554 * @note It's possible that provided state can't be loaded
555 * (device disconnected or reqested parameters are not supported anymore).
556 * @param state - state to apply
557 * @return true on success, otherwise - false
559 bool _apply_state(const StatePtr& state);
561 /** Gets available device channels from engine and updates internal controller state
563 void _update_device_channels_state();
565 /** Check "Stereo Out" mode channels state configuration and make it correspond Stereo Out mode requirements
567 void _refresh_stereo_out_channel_states();
569 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
570 // internal helper functions
571 /** make sure that current device parameters are supported and fit session requirements
572 * @return true if current state is valid and all parameters are supported, otherwise - false
574 bool _validate_current_device_state();
576 /** change ltc source port in case of the input ports list change
578 void _update_ltc_source_port ();
579 /** change ltc source port in case of the output ports list change
581 void _update_ltc_output_port ();
583 /** check that port is still existed in the list of input ports
584 @param[in] port - port name
585 @return true if current port is existed, otherwise - false
587 bool _audio_input_port_exists (const std::string& port);
588 /** check that port is still existed in the list of output ports
589 @param[in] port - port name
590 @return true if current port is existed, otherwise - false
592 bool _audio_output_port_exists (const std::string& port);
596 ////////////////////////////////////////
598 /** Invoked when Engine starts running
600 void _on_engine_running();
601 /** Invoked when Engine is halted
603 void _on_engine_halted();
604 /** Invoked when Engine processing is terminated
606 void _on_engine_stopped();
607 /** Invoked when Device error accured, it failed to start or didn't accept the change which should
609 void _on_device_error();
610 /** Invoked when current device changes sample rate
612 void _on_sample_rate_change(ARDOUR::samplecnt_t);
613 /** Invoked when current device changes buffer size
615 void _on_buffer_size_change(ARDOUR::pframes_t);
616 /** Invoked when the list of available devices is changed
618 void _on_device_list_change();
619 /** Invoked when the config parameter is changed
621 void _on_parameter_changed (const std::string&);
622 /** Invoked when Audio/MIDI ports are registered or unregistered
624 void _on_ports_registration_update ();
625 /** Invoked when session loading process is complete
627 void _on_session_loaded();
628 ////////////////////////////////////////
630 ////////////////////////////////////////
632 StatePtr _current_state; ///< current state pointer
633 // list of system states
634 StateList _states; ///< list of all available states
636 MidiPortStateList _midi_inputs; ///< midi input states
637 MidiPortStateList _midi_outputs; ///< midi output states
639 std::string _last_used_real_device; ///< last active non-default (real) device
641 Session* _session; ///< current session
643 // Engine connections stuff
644 PBD::ScopedConnectionList update_connections; ///< connection container for update signals
645 PBD::ScopedConnectionList session_connections; ///< connection container for session signals
646 PBD::ScopedConnection running_connection; ///< connection container for EngineRunning signal
647 PBD::ScopedConnection halt_connection; ///< connection container for EngineHalted signal
648 PBD::ScopedConnection stopped_connection; ///< connection container for EngineStopped signal
651 } // namespace ARDOUR
653 #endif /* defined(__gtk2_ardour__engine_state_controller__) */