noop: fix indentation to match style guide
[ardour.git] / libs / ardour / ardour / engine_state_controller.h
1 /*
2   Copyright (C) 2014 Waves Audio Ltd.
3  
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.
8  
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.
13  
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.
17  
18 */
19
20 #ifndef __gtk2_ardour__engine_state_controller__
21 #define __gtk2_ardour__engine_state_controller__
22
23 #include <vector>
24 #include <list>
25
26 #include "ardour/types.h"
27 #include "ardour/audio_backend.h"
28
29 namespace ARDOUR {
30
31 class AudioBackendInfo;
32     
33 /**
34  * @class EngineStateController
35  * @brief EngineStateController class.
36  *
37  * Implements usecases for Audio devices and Audio/Midi ports.
38  * Persistantly saves to the config device configuration settings and audio/midi port states
39  */
40 class EngineStateController
41 {
42    public:
43     
44         // public data types:
45     
46         /** 
47          * @struct PortState
48          * Structure which represents AudioPort state
49          */
50         struct PortState {
51                 std::string name; ///< Audio Port name
52                 bool active;      ///< Audio Port state
53         
54                 PortState ()
55                         : name(""),
56                           active(false)
57                 {
58                 }
59         
60                 PortState (const std::string& name)
61                         : name(name),
62                           active(false)
63                 {
64                 }
65         
66                 bool operator==(const PortState& rhs) {return rhs.name == name; }
67         
68         };
69     
70         /// @typedef Type for the list of all available audio ports
71         typedef std::list<PortState> PortStateList;
72
73         /**
74          * @struct MidiPortState
75          * Structure which represents MidiPort state.
76          */
77         struct MidiPortState
78         {
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
84         
85                 MidiPortState(const std::string& name):
86                         name(name),
87                         active(false),
88                         available(false),
89                         scene_connected(false),
90                         mtc_in(false)
91                 {}
92         
93                 bool operator==(const MidiPortState& rhs)
94                 {
95                         return name == rhs.name;
96                 }
97         };
98     
99         /// @typedef Type for the list of MidiPorts ever registered in the system
100         typedef std::list<MidiPortState> MidiPortStateList;
101     
102
103         //Interfaces
104     
105         /** Get an instance of EngineStateController singleton.
106          * @return EngineStateController instance pointer
107          */
108         static EngineStateController* instance ();
109     
110         /** Associate session with EngineStateController instance.
111          */
112         void set_session (Session* session);
113     
114         /** Remove link to the associated session.
115          */
116         void remove_session ();
117     
118         //////////////////////////////////////////////////////////////////////////////////////////////////////////
119         // General backend/device information methods
120     
121         /** Provides names of all available backends.
122          *
123          * @param[out] available_backends - vector of available backends
124          */
125         void available_backends (std::vector<const AudioBackendInfo*>& available_backends);
126     
127         /** Provides the name of currently used backend.
128          *
129          * @return the name of currently used backend
130          */
131         const std::string& get_current_backend_name() const;
132     
133         /** Provides the name of currently used device.
134          *
135          * @return the name of currently used device
136          */
137         const std::string& get_current_device_name () const;
138     
139         /** Provides names for all available devices.
140          *
141          * @param[out] device_vector - vector of available devices
142          */
143         void enumerate_devices (std::vector<ARDOUR::AudioBackend::DeviceStatus>& device_vector) const;
144     
145         /** Get sample rate used by current device.
146          *
147          * @return current sample rate
148          */
149         ARDOUR::framecnt_t get_current_sample_rate () const;
150     
151         /** Get default sample rate for current backend.
152          *
153          * @return default sample rate for current backend
154          */
155         ARDOUR::framecnt_t get_default_sample_rate () const;
156     
157         /** Get sample rates which are supported by current device and current backend.
158          *
159          * @param[out] sample_rates - vector of supported sample rates
160          */
161         void available_sample_rates_for_current_device (std::vector<float>& sample_rates) const;
162     
163         /** Get buffer size used by current device.
164          *
165          * @return current buffer size
166          */
167         ARDOUR::pframes_t get_current_buffer_size () const;
168     
169         /** Get default buffer size for current backend.
170          *
171          * @return default buffer size for current backend
172          */
173         ARDOUR::pframes_t get_default_buffer_size () const;
174     
175         /** Get buffer sizes which are supported by current device and current backend.
176          *
177          * @param[out] buffer_sizes - vector of supported buffer_sizes
178          */
179         void available_buffer_sizes_for_current_device (std::vector<ARDOUR::pframes_t>& buffer_sizes) const;
180
181         /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182         // device state control methods
183     
184         /** Get the number of all enabled Audio inputs.
185          *
186          * @return number of all enabled Audio inputs
187          */
188         uint32_t            get_available_inputs_count() const;
189         /** Get the number of all enabled Audio outputs.
190          *
191          * @return number of all enabled Audio outputs
192          */
193         uint32_t            get_available_outputs_count () const;
194     
195         /** Get vector of all enabled physical Audio input port names.
196          *
197          * @param[out] port_names - vector of all enabled Audio input names
198          */
199         void                get_physical_audio_inputs (std::vector<std::string>& port_names);
200         /** Get vector of all enabled physical Audio input port names.
201          *
202          * @param[out] port_names - vector of all enabled Audio input names
203          */
204         void                get_physical_audio_outputs (std::vector<std::string>& port_names);
205     
206         /** Get vector of all enabled physical MIDI input port names.
207          *
208          * @param[out] port_names - vector of all enabled MIDI input names
209          */
210         void                get_physical_midi_inputs (std::vector<std::string>& port_names);
211         /** Get vector of all enabled physical MIDI output port names.
212          *
213          * @param[out] port_names - vector of all enabled MIDI output names
214          */
215         void                get_physical_midi_outputs (std::vector<std::string>& port_names);
216     
217         /** Sets new state to all Audio inputs.
218          *
219          * @param[in] state - new state
220          */
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
225          */
226         void                set_state_to_all_outputs(bool state);
227     
228         /** Get vector of states for all physical Audio input ports.
229          *
230          * @param[out] channel_states - vector of input port states
231          */
232         void                get_physical_audio_input_states(std::vector<PortState>& channel_states);
233         /** Get vector of states for all physical Audio output ports.
234          *
235          * @param[out] channel_states - vector of output port states
236          */
237         void                get_physical_audio_output_states(std::vector<PortState>& channel_states);
238     
239         /** Set state of the specified Audio input port.
240          *
241          * @param[in] port_name - input name
242          * @param[in] state - new state
243          */
244         void                set_physical_audio_input_state(const std::string& port_name, bool state);
245         /** Set state of the specified Audio output port.
246          *
247          * @param[in] port_name - output name
248          * @param[in] state - new state
249          */
250         void                set_physical_audio_output_state(const std::string& port_name, bool state);
251     
252         /** Get state of the specified Audio input port.
253          *
254          * @param[in] port_name - input name
255          * @return input state
256          */
257         bool                get_physical_audio_input_state(const std::string& port_name);
258         /** Get state of the specified Audi output port.
259          *
260          * @param[in] port_name - output name
261          * @return output state
262          */
263         bool                get_physical_audio_output_state(const std::string& port_name);
264     
265         /** Get vector of all enabled MIDI input port names.
266          *
267          * @param[out] channel_states - vector of enabled inputs
268          */
269         void                get_physical_midi_input_states (std::vector<MidiPortState>& channel_states);
270         /** Get vector of all enabled MIDI output port names.
271          *
272          * @param[out] channel_states - vector of enabled outputs
273          */
274         void                get_physical_midi_output_states (std::vector<MidiPortState>& channel_states);
275     
276         /** Set state of the specified MIDI input port.
277          *
278          * @param[in] port_name - input name
279          * @param[in] state - new state
280          */
281         void                set_physical_midi_input_state(const std::string& port_name, bool state);
282         /** Set state of the specified MIDI output port.
283          *
284          * @param[in] port_name - output name
285          * @param[in] state - new state
286          */
287         void                set_physical_midi_output_state(const std::string& port_name, bool state);
288         /** Get state of the specified MIDI input port.
289          *
290          * @param[in] port_name - input name
291          * @param[out] scene_connected - is port used as Scene In or not
292          * @return input state
293          */
294         bool                get_physical_midi_input_state(const std::string& port_name, bool& scene_connected);
295         /** Get state of the specified MIDI output port.
296          *
297          * @param[in] port_name - output name
298          * @param[out] scene_connected - is port used as Scene Out or not
299          * @return output state
300          */
301         bool                get_physical_midi_output_state(const std::string& port_name, bool& scene_connected);
302     
303         /** Set state of Scene In connection for the specified MIDI input port.
304          *
305          * @param[in] port_name - input name
306          * @param[in] state - new state
307          */
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.
310          *
311          * @param[in] port_name - input name
312          * @param[in] state - new state
313          */
314         void                set_physical_midi_scenen_out_connection_state(const std::string&, bool);
315     
316         /** Disocnnect all MIDI input ports from Scene In.
317          */
318         void                set_all_midi_scene_inputs_disconnected();
319         /** Disocnnect all MIDI output ports from Scene Out.
320          */
321         void                set_all_midi_scene_outputs_disconnected();
322     
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.
326          */
327         void                set_mtc_input(const std::string&);
328     
329         /** Check if AudioEngine setup is required
330          * @return true if setup is required, otherwise - false
331          */
332         bool                is_setup_required() const {return ARDOUR::AudioEngine::instance()->setup_required (); }
333     
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
338     
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
342          */
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
347          */
348         bool        set_new_buffer_size_in_controller(pframes_t buffer_size);
349     
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
356          */
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
362          */
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
368          */
369         bool        set_new_device_as_current(const std::string& device_name);
370
371     
372         ////////////////////////////////////////////////////////////////////////////////////////////////////
373         // Methods to save/serialize setting states
374
375         /** Serialize Audio/Midi settings (entire EngineStateController database) to XML
376          * @return XML note with serialized states
377          */
378         XMLNode&    serialize_audio_midi_settings();
379         /** Save Audio/Midi settings (entire EngineStateController database) to config persistently
380          */
381         void        save_audio_midi_settings();
382     
383         ////////////////////////////////////////////////////////////////////////////////////////////////////
384         //UPDATE SIGNALS
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;
393
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;
402     
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
409          */
410         PBD::Signal0<void> OutputConnectionModeChanged;
411     
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;
420     
421         /** This signal is emitted if the MTC Input channel is changed */
422         PBD::Signal1<void, const std::string&> MTCInputChanged;
423     
424         /** This signal is emitted if new Audio/MIDI ports are registered or unregistered */
425         PBD::Signal0<void> PortRegistrationChanged;
426     
427    private:
428
429         EngineStateController(); /// singleton
430         ~EngineStateController(); /// singleton
431         EngineStateController(const EngineStateController& ); /// prohibited
432         EngineStateController& operator=(const EngineStateController&); /// prohibited
433     
434         ////////////////////////////////////////////////////////////////////////////////////////////
435         // private data structures
436     
437         /** @struct Engine state
438          * @brief State structure.
439          * Contains information about single device/backend state
440          */
441         struct 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
446                 
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
451         
452                 State()
453                         : sample_rate(0)
454                         , buffer_size(0)
455                         , input_channel_states (0)
456                         , multi_out_channel_states (0)
457                         , stereo_out_channel_states (0)
458                         , active (false)
459                 {
460                 }
461         
462                 bool operator==(const State& rhs)
463                 {
464                         return (backend_name == rhs.backend_name) && (device_name == rhs.device_name);
465                 }
466         
467                 /** Forms string name for the state
468                  * @return name string
469                  */
470                 std::string form_state_name() {
471                         return std::string("State:" + backend_name + ":" + device_name);
472                 }
473         
474                 /** @struct StatepPredicate
475                  * This predicate is used to identify a state during search in the list of states
476                  */
477                 struct StatePredicate
478                 {
479                         StatePredicate(const std::string& backend_name, const std::string& device_name)
480                                 : _backend_name (backend_name)
481                                 , _device_name (device_name)
482                         {}
483             
484                         bool operator()(boost::shared_ptr<ARDOUR::EngineStateController::State> rhs)
485                         {
486                                 return (_backend_name == rhs->backend_name) && (_device_name == rhs->device_name);
487                         }
488             
489                                                         private:
490                         std::string _backend_name;
491                         std::string _device_name;
492                 };
493         };
494     
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;
499     
500         ////////////////////////////////////////////////////////////////////////////////////////////////////
501         // methods to manage setting states
502     
503         /** Deserializes and loads Engine and Audio port states from the config to EngineStateController
504          */
505         void _deserialize_and_load_engine_states();
506         /** Deserializes and loads MIDI port states from the config to EngineStateController
507          */
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
511          */
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
515          */
516         void _serialize_midi_port_states(XMLNode* audio_midi_settings_node);
517     
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.
521          */
522         void _do_initial_engine_setup();
523     
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
529          */
530         bool _apply_state(const StatePtr& state);
531     
532         /** Gets available device channels from engine and updates internal controller state
533          */
534         void _update_device_channels_state();
535     
536         /** Check "Stereo Out" mode channels state configuration and make it correspond Stereo Out mode requirements
537          */
538         void _refresh_stereo_out_channel_states();
539     
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
544          */
545         bool _validate_current_device_state();
546         ////////////////////////////////////////////////////////////////////////////////////////////////////////////
547
548         ////////////////////////////////////////
549         // callbacks
550         /** Invoked when Engine starts running
551          */
552         void _on_engine_running();
553         /** Invoked when Engine is halted
554          */
555         void _on_engine_halted();
556         /** Invoked when Engine processing is terminated
557          */
558         void _on_engine_stopped();
559         /** Invoked when Device error accured, it failed to start or didn't accept the change which should
560          */
561         void _on_device_error();
562         /** Invoked when current device changes sample rate
563          */
564         void _on_sample_rate_change(ARDOUR::framecnt_t);
565         /** Invoked when current device changes buffer size
566          */
567         void _on_buffer_size_change(ARDOUR::pframes_t);
568         /** Invoked when the list of available devices is changed
569          */
570         void _on_device_list_change();
571         /** Invoked when the config parameter is changed
572          */
573         void _on_parameter_changed (const std::string&);
574         /** Invoked when Audio/MIDI ports are registered or unregistered
575          */
576         void _on_ports_registration_update ();
577         /** Invoked when session loading process is complete
578          */
579         void _on_session_loaded();
580         ////////////////////////////////////////
581         
582         ////////////////////////////////////////
583         // attributes
584         StatePtr _current_state; ///< current state pointer
585         // list of system states
586         StateList _states; ///< list of all available states
587     
588         MidiPortStateList _midi_inputs; ///< midi input states
589         MidiPortStateList _midi_outputs; ///< midi output states
590     
591         std::string _last_used_real_device; ///< last active non-default (real) device
592     
593         Session* _session; ///< current session
594
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
601 };
602
603 } // namespace ARDOUR
604     
605 #endif /* defined(__gtk2_ardour__engine_state_controller__) */