2 * Copyright (C) 2015-2017 Paul Davis <paul@linuxaudiosystems.com>
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 along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #ifndef __gtk2_ardour__engine_state_controller__
20 #define __gtk2_ardour__engine_state_controller__
25 #include "ardour/types.h"
26 #include "ardour/audio_backend.h"
30 class AudioBackendInfo;
33 * @class EngineStateController
34 * @brief EngineStateController class.
36 * Implements usecases for Audio devices and Audio/Midi ports.
37 * Persistantly saves to the config device configuration settings and audio/midi port states
39 class EngineStateController
47 * Structure which represents AudioPort state
50 std::string name; ///< Audio Port name
51 bool active; ///< Audio Port state
59 PortState (const std::string& name)
65 bool operator==(const PortState& rhs) {return rhs.name == name; }
69 /// @typedef Type for the list of all available audio ports
70 typedef std::list<PortState> PortStateList;
73 * @struct MidiPortState
74 * Structure which represents MidiPort state.
78 std::string name; ///< Midi Port name
79 bool active; ///< Midi Port state
80 bool available; ///< Midi Port availability - if it is physicaly available or not
81 bool scene_connected; ///< Is midi port used for scene MIDI marker in/out
82 bool mtc_in; ///< Is midi port used as MTC in
84 MidiPortState(const std::string& name)
88 , scene_connected(false)
92 bool operator==(const MidiPortState& rhs)
94 return name == rhs.name;
98 /// @typedef Type for the list of MidiPorts ever registered in the system
99 typedef std::list<MidiPortState> MidiPortStateList;
104 /** Get an instance of EngineStateController singleton.
105 * @return EngineStateController instance pointer
107 static EngineStateController* instance ();
109 /** Associate session with EngineStateController instance.
111 void set_session (Session* session);
113 /** Remove link to the associated session.
115 void remove_session ();
117 //////////////////////////////////////////////////////////////////////////////////////////////////////////
118 // General backend/device information methods
120 /** Provides names of all available backends.
122 * @param[out] available_backends - vector of available backends
124 void available_backends (std::vector<const AudioBackendInfo*>& available_backends);
126 /** Provides the name of currently used backend.
128 * @return the name of currently used backend
130 const std::string& get_current_backend_name() const;
132 /** Provides the name of currently used device.
134 * @return the name of currently used device
136 const std::string& get_current_device_name () const;
138 /** Provides names for all available devices.
140 * @param[out] device_vector - vector of available devices
142 void enumerate_devices (std::vector<ARDOUR::AudioBackend::DeviceStatus>& device_vector) const;
144 /** Get sample rate used by current device.
146 * @return current sample rate
148 ARDOUR::samplecnt_t get_current_sample_rate () const;
150 /** Get default sample rate for current backend.
152 * @return default sample rate for current backend
154 ARDOUR::samplecnt_t get_default_sample_rate () const;
156 /** Get sample rates which are supported by current device and current backend.
158 * @param[out] sample_rates - vector of supported sample rates
160 void available_sample_rates_for_current_device (std::vector<float>& sample_rates) const;
162 /** Get buffer size used by current device.
164 * @return current buffer size
166 ARDOUR::pframes_t get_current_buffer_size () const;
168 /** Get default buffer size for current backend.
170 * @return default buffer size for current backend
172 ARDOUR::pframes_t get_default_buffer_size () const;
174 /** Get buffer sizes which are supported by current device and current backend.
176 * @param[out] buffer_sizes - vector of supported buffer_sizes
178 void available_buffer_sizes_for_current_device (std::vector<ARDOUR::pframes_t>& buffer_sizes) const;
180 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181 // device state control methods
183 /** Get the number of all enabled Audio inputs.
185 * @return number of all enabled Audio inputs
187 uint32_t get_available_inputs_count() const;
188 /** Get the number of all enabled Audio outputs.
190 * @return number of all enabled Audio outputs
192 uint32_t get_available_outputs_count () const;
194 /** Get vector of all enabled physical Audio input port names.
196 * @param[out] port_names - vector of all enabled Audio input names
198 void get_physical_audio_inputs (std::vector<std::string>& port_names);
199 /** Get vector of all enabled physical Audio input port names.
201 * @param[out] port_names - vector of all enabled Audio input names
203 void get_physical_audio_outputs (std::vector<std::string>& port_names);
205 /** Get vector of all enabled physical MIDI input port names.
207 * @param[out] port_names - vector of all enabled MIDI input names
209 void get_physical_midi_inputs (std::vector<std::string>& port_names);
210 /** Get vector of all enabled physical MIDI output port names.
212 * @param[out] port_names - vector of all enabled MIDI output names
214 void get_physical_midi_outputs (std::vector<std::string>& port_names);
216 /** Sets new state to all Audio inputs.
218 * @param[in] state - new state
220 void set_state_to_all_inputs(bool state);
221 /** Sets new state to all Audio outputs.
222 * @note Does nothing in Stereo Out mode
223 * @param[in] state - new state
225 void set_state_to_all_outputs(bool state);
227 /** Get vector of states for all physical Audio input ports.
229 * @param[out] channel_states - vector of input port states
231 void get_physical_audio_input_states(std::vector<PortState>& channel_states);
232 /** Get vector of states for all physical Audio output ports.
234 * @param[out] channel_states - vector of output port states
236 void get_physical_audio_output_states(std::vector<PortState>& channel_states);
238 /** Set state of the specified Audio input port.
240 * @param[in] port_name - input name
241 * @param[in] state - new state
243 void set_physical_audio_input_state(const std::string& port_name, bool state);
244 /** Set state of the specified Audio output port.
246 * @param[in] port_name - output name
247 * @param[in] state - new state
249 void set_physical_audio_output_state(const std::string& port_name, bool state);
251 /** Get state of the specified Audio input port.
253 * @param[in] port_name - input name
254 * @return input state
256 bool get_physical_audio_input_state(const std::string& port_name);
257 /** Get state of the specified Audi output port.
259 * @param[in] port_name - output name
260 * @return output state
262 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 /** Get name of mtc source port
278 * return name of mtc source port
280 std::string get_mtc_source_port ();
282 /** Set ltc source port
284 * @param[in] port - name of ltc source port
286 void set_ltc_source_port (const std::string& port);
287 /** Get name of ltc source port
289 * return name of ltc source port
291 std::string get_ltc_source_port ();
293 /** Set ltc output port
295 * @param[in] port - name of ltc output port
297 void set_ltc_output_port (const std::string&);
298 /** Get name of ltc output port
300 * return name of ltc output port
302 std::string get_ltc_output_port ();
304 /** Set state of the specified MIDI input port.
306 * @param[in] port_name - input name
307 * @param[in] state - new state
309 void set_physical_midi_input_state(const std::string& port_name, bool state);
310 /** Set state of the specified MIDI output port.
312 * @param[in] port_name - output name
313 * @param[in] state - new state
315 void set_physical_midi_output_state(const std::string& port_name, bool state);
316 /** Get state of the specified MIDI input port.
318 * @param[in] port_name - input name
319 * @param[out] scene_connected - is port used as Scene In or not
320 * @return input state
322 bool get_physical_midi_input_state(const std::string& port_name, bool& scene_connected);
323 /** Get state of the specified MIDI output port.
325 * @param[in] port_name - output name
326 * @param[out] scene_connected - is port used as Scene Out or not
327 * @return output state
329 bool get_physical_midi_output_state(const std::string& port_name, bool& scene_connected);
331 /** Set state of Scene In connection for the specified MIDI input port.
333 * @param[in] port_name - input name
334 * @param[in] state - new state
336 void set_physical_midi_scene_in_connection_state(const std::string& port_name, bool state);
337 /** Set state of Scene Out connection for the specified MIDI output port.
339 * @param[in] port_name - input name
340 * @param[in] state - new state
342 void set_physical_midi_scenen_out_connection_state(const std::string&, bool);
344 /** Disocnnect all MIDI input ports from Scene In.
346 void set_all_midi_scene_inputs_disconnected();
347 /** Disocnnect all MIDI output ports from Scene Out.
349 void set_all_midi_scene_outputs_disconnected();
351 /** Set MIDI TimeCode input port
352 * @note There is a sense to choose MIDI TimeCode input only because
353 * our MIDI TimeCode is propagated to all midi output ports.
355 void set_mtc_source_port (const std::string&);
357 /** Check if AudioEngine setup is required
358 * @return true if setup is required, otherwise - false
360 bool is_setup_required() const {return ARDOUR::AudioEngine::instance()->setup_required (); }
362 ////////////////////////////////////////////////////////////////////////////////////////////////////
363 // Methods set parameters inside the controller
364 // the state of engine won't change untill we make a "push" of this state to the backend
365 // NOTE: Use push_state_to_backend() method to update backend with the most recent controller state
367 /** Set new sample rate for current device in EngineStateController database
368 * @note Use push_state_to_backend() method to update backend/device state with the most recent controller state
369 * @param sample_rate - new sample rate
371 bool set_new_sample_rate_in_controller(samplecnt_t sample_rate);
372 /** Set new buffer size for current device in EngineStateController database
373 * @note Use push_state_to_backend() method to update backend/device state with the most recent controller state
374 * @param buffer_size - new buffer size
376 bool set_new_buffer_size_in_controller(pframes_t buffer_size);
378 /** @brief push current controller state to backend.
379 * Propagate and set all current EngineStateController parameters to the backend
380 * @note Engine will be restarted if it's running when this method is called.
381 * @note If an attempt ot set parameters is unsuccessful current device will be switched to "None".
382 * @param start - start the Engine if it was not running when this function was called.
383 * @return true on success, otherwise - false
385 bool push_current_state_to_backend(bool start);
386 /** Switch to new backend
387 * @note The change will be propagated emmidiatelly as if push_current_state_to_backend () was called.
388 * @param backend_name - new backend name.
389 * @return true on success, otherwise - false
391 bool set_new_backend_as_current(const std::string& backend_name);
392 /** Switch to new device
393 * @note The change will be propagated emmidiatelly as if push_current_state_to_backend () was called.
394 * @param device_name - new device name.
395 * @return true on success, otherwise - false
397 bool set_new_device_as_current(const std::string& device_name);
400 ////////////////////////////////////////////////////////////////////////////////////////////////////
401 // Methods to save/serialize setting states
403 /** Serialize Audio/Midi settings (entire EngineStateController database) to XML
404 * @return XML note with serialized states
406 XMLNode& serialize_audio_midi_settings();
407 /** Save Audio/Midi settings (entire EngineStateController database) to config persistently
409 void save_audio_midi_settings();
411 ////////////////////////////////////////////////////////////////////////////////////////////////////
413 /** This signal is emitted if the sample rate changes */
414 PBD::Signal0<void> SampleRateChanged;
415 /** This signal is emitted if the buffer size changes */
416 PBD::Signal0<void> BufferSizeChanged;
417 /** This signal is emitted if the device list changes */
418 PBD::Signal1<void, bool> DeviceListChanged;
419 /** This signal is emitted if the device cannot operate properly */
420 PBD::Signal0<void> DeviceError;
422 ////////////////////////////////////////////////////////////////////////////////////////////////////
423 //ENGINE STATE SIGNALS
424 /** This signal is emitted when the engine is started */
425 PBD::Signal0<void> EngineRunning;
426 /** This signal is emitted when the engine is stopped */
427 PBD::Signal0<void> EngineStopped;
428 /** This signal is emitted if Engine processing is terminated */
429 PBD::Signal0<void> EngineHalted;
431 /** This signal is emitted if the AUDIO input channel configuration changes */
432 PBD::Signal0<void> InputConfigChanged;
433 /** This signal is emitted if the AUDIO output channel configuration changes */
434 PBD::Signal0<void> OutputConfigChanged;
435 /** This signal is emitted if the AUDIO output connection mode changes
436 * @note By output connection mode "Stereo Out" or "Multi Out" is meant
438 PBD::Signal0<void> OutputConnectionModeChanged;
440 /** This signals is emitted if the MIDI input channel configuration changes */
441 PBD::Signal0<void> MIDIInputConfigChanged;
442 /** This signals is emitted if the MIDI output channel configuration changes */
443 PBD::Signal0<void> MIDIOutputConfigChanged;
444 /** This signals is emitted if the MIDI Scene In connection changes */
445 PBD::Signal2<void, const std::vector<std::string>&, bool> MIDISceneInputConnectionChanged;
446 /** This signals is emitted if the MIDI Scene Out connection changes */
447 PBD::Signal2<void, const std::vector<std::string>&, bool> MIDISceneOutputConnectionChanged;
449 /** This signal is emitted if the MTC Input channel is changed */
450 PBD::Signal1<void, const std::string&> MTCInputChanged;
452 /** This signal is emitted if new Audio/MIDI ports are registered or unregistered */
453 PBD::Signal0<void> PortRegistrationChanged;
457 EngineStateController(); /// singleton
458 ~EngineStateController(); /// singleton
459 EngineStateController(const EngineStateController& ); /// prohibited
460 EngineStateController& operator=(const EngineStateController&); /// prohibited
462 ////////////////////////////////////////////////////////////////////////////////////////////
463 // private data structures
465 /** @struct Engine state
466 * @brief State structure.
467 * Contains information about single device/backend state
470 std::string backend_name; ///< state backend name
471 std::string device_name; ///< state device name
472 ARDOUR::samplecnt_t sample_rate; ///< sample rate used by the device in this state
473 ARDOUR::pframes_t buffer_size; ///< buffer size used by the device in this state
475 PortStateList input_channel_states; ///< states of device Audio inputs
476 PortStateList multi_out_channel_states; ///< states of device Audio inputs in Multi Out mode
477 PortStateList stereo_out_channel_states; ///< states of device Audio inputs in Stereo Out mode
478 bool active; ///< was this state the most recent active one
483 , input_channel_states (0)
484 , multi_out_channel_states (0)
485 , stereo_out_channel_states (0)
490 bool operator==(const State& rhs)
492 return (backend_name == rhs.backend_name) && (device_name == rhs.device_name);
495 /** Forms string name for the state
496 * @return name string
498 std::string form_state_name() {
499 return std::string("State:" + backend_name + ":" + device_name);
502 /** @struct StatepPredicate
503 * This predicate is used to identify a state during search in the list of states
505 struct StatePredicate
507 StatePredicate(const std::string& backend_name, const std::string& device_name)
508 : _backend_name (backend_name)
509 , _device_name (device_name)
512 bool operator()(boost::shared_ptr<ARDOUR::EngineStateController::State> rhs)
514 return (_backend_name == rhs->backend_name) && (_device_name == rhs->device_name);
518 std::string _backend_name;
519 std::string _device_name;
523 /// @typedef Type for the state pointer
524 typedef boost::shared_ptr<State> StatePtr;
525 /// @typedef Type for the list of states
526 typedef std::list<StatePtr> StateList;
528 ////////////////////////////////////////////////////////////////////////////////////////////////////
529 // methods to manage setting states
531 /** Deserializes and loads Engine and Audio port states from the config to EngineStateController
533 void _deserialize_and_load_engine_states();
534 /** Deserializes and loads MIDI port states from the config to EngineStateController
536 void _deserialize_and_load_midi_port_states();
537 /** Serializes Engine and Audio port states from EngineStateController to XML node
538 * @param[in,out] audio_midi_settings_node - node to serialize the satets to
540 void _serialize_engine_states(XMLNode* audio_midi_settings_node);
541 /** Serializes MIDI port states from EngineStateController to XML node
542 * @param[in,out] audio_midi_settings_node - node to serialize the satets to
544 void _serialize_midi_port_states(XMLNode* audio_midi_settings_node);
546 /** Provides initial state configuration.
547 * It loades the last active state if there is one and it is aplicable.
548 * Otherwise default state (None device with default sample rate and buffer size) is loaded.
550 void _do_initial_engine_setup();
552 /** Loades provided state.
553 * @note It's possible that provided state can't be loaded
554 * (device disconnected or reqested parameters are not supported anymore).
555 * @param state - state to apply
556 * @return true on success, otherwise - false
558 bool _apply_state(const StatePtr& state);
560 /** Gets available device channels from engine and updates internal controller state
562 void _update_device_channels_state();
564 /** Check "Stereo Out" mode channels state configuration and make it correspond Stereo Out mode requirements
566 void _refresh_stereo_out_channel_states();
568 ////////////////////////////////////////////////////////////////////////////////////////////////////////////
569 // internal helper functions
570 /** make sure that current device parameters are supported and fit session requirements
571 * @return true if current state is valid and all parameters are supported, otherwise - false
573 bool _validate_current_device_state();
575 /** change ltc source port in case of the input ports list change
577 void _update_ltc_source_port ();
578 /** change ltc source port in case of the output ports list change
580 void _update_ltc_output_port ();
582 /** check that port is still existed in the list of input ports
583 @param[in] port - port name
584 @return true if current port is existed, otherwise - false
586 bool _audio_input_port_exists (const std::string& port);
587 /** check that port is still existed in the list of output ports
588 @param[in] port - port name
589 @return true if current port is existed, otherwise - false
591 bool _audio_output_port_exists (const std::string& port);
595 ////////////////////////////////////////
597 /** Invoked when Engine starts running
599 void _on_engine_running();
600 /** Invoked when Engine is halted
602 void _on_engine_halted();
603 /** Invoked when Engine processing is terminated
605 void _on_engine_stopped();
606 /** Invoked when Device error accured, it failed to start or didn't accept the change which should
608 void _on_device_error();
609 /** Invoked when current device changes sample rate
611 void _on_sample_rate_change(ARDOUR::samplecnt_t);
612 /** Invoked when current device changes buffer size
614 void _on_buffer_size_change(ARDOUR::pframes_t);
615 /** Invoked when the list of available devices is changed
617 void _on_device_list_change();
618 /** Invoked when the config parameter is changed
620 void _on_parameter_changed (const std::string&);
621 /** Invoked when Audio/MIDI ports are registered or unregistered
623 void _on_ports_registration_update ();
624 /** Invoked when session loading process is complete
626 void _on_session_loaded();
627 ////////////////////////////////////////
629 ////////////////////////////////////////
631 StatePtr _current_state; ///< current state pointer
632 // list of system states
633 StateList _states; ///< list of all available states
635 MidiPortStateList _midi_inputs; ///< midi input states
636 MidiPortStateList _midi_outputs; ///< midi output states
638 std::string _last_used_real_device; ///< last active non-default (real) device
640 Session* _session; ///< current session
642 // Engine connections stuff
643 PBD::ScopedConnectionList update_connections; ///< connection container for update signals
644 PBD::ScopedConnectionList session_connections; ///< connection container for session signals
645 PBD::ScopedConnection running_connection; ///< connection container for EngineRunning signal
646 PBD::ScopedConnection halt_connection; ///< connection container for EngineHalted signal
647 PBD::ScopedConnection stopped_connection; ///< connection container for EngineStopped signal
650 } // namespace ARDOUR
652 #endif /* defined(__gtk2_ardour__engine_state_controller__) */