move ever close to working master/slave logic, this time with audio testing
[ardour.git] / libs / ardour / ardour / solo_control.h
1 /*
2     Copyright (C) 2016 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify it
5     under the terms of the GNU General Public License as published by the Free
6     Software Foundation; either version 2 of the License, or (at your option)
7     any later version.
8
9     This program is distributed in the hope that it will be useful, but WITHOUT
10     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12     for more details.
13
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     675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 #ifndef __ardour_solo_control_h__
20 #define __ardour_solo_control_h__
21
22 #include <string>
23
24 #include <boost/shared_ptr.hpp>
25
26 #include "ardour/slavable_automation_control.h"
27 #include "ardour/libardour_visibility.h"
28
29 namespace ARDOUR {
30
31 class Session;
32 class Soloable;
33 class Muteable;
34
35 class LIBARDOUR_API SoloControl : public SlavableAutomationControl
36 {
37   public:
38         SoloControl (Session& session, std::string const & name, Soloable& soloable, Muteable& m);
39
40         double get_value () const;
41
42         /* Export additional API so that objects that only get access
43          * to a Controllable/AutomationControl can do more fine-grained
44          * operations with respect to solo. Obviously, they would need
45          * to dynamic_cast<SoloControl> first.
46          *
47          * Solo state is not representable by a single scalar value,
48          * so set_value() and get_value() is not enough.
49          *
50          * This means that the Controllable is technically
51          * asymmetric. It is possible to call ::set_value (0.0) to
52          * disable (self)solo, and then call ::get_value() and get a
53          * return of 1.0 because the control is soloed by
54          * upstream/downstream or a master.
55          */
56
57         void mod_solo_by_others_upstream (int32_t delta);
58         void mod_solo_by_others_downstream (int32_t delta);
59
60         /* API to check different aspects of solo substate
61          */
62
63         bool soloed_by_others () const {
64                 return _soloed_by_others_downstream || _soloed_by_others_downstream || get_masters_value ();
65         }
66         uint32_t soloed_by_others_upstream () const {
67                 return _soloed_by_others_upstream;
68         }
69         uint32_t soloed_by_others_downstream () const {
70                 return _soloed_by_others_downstream;
71         }
72         bool self_soloed () const {
73                 return _self_solo;
74         }
75         bool soloed() const { return self_soloed() || soloed_by_others(); }
76
77         /* The session object needs to respond to solo
78            changes, but to do so accurately it needs to know if we transition
79            into or out of solo. The normal Changed signal doesn't make that
80            possible.
81         */
82
83         int32_t transitioned_into_solo () const { return _transition_into_solo; }
84
85         void clear_all_solo_state ();
86
87         int set_state (XMLNode const&, int);
88         XMLNode& get_state ();
89
90   protected:
91         void actually_set_value (double, PBD::Controllable::GroupControlDisposition group_override);
92         void master_changed (bool from_self, GroupControlDisposition, boost::shared_ptr<AutomationControl> m);
93         void pre_remove_master (boost::shared_ptr<AutomationControl>);
94         void post_add_master (boost::shared_ptr<AutomationControl>);
95
96   private:
97         Soloable& _soloable;
98         Muteable& _muteable;
99         bool      _self_solo;
100         uint32_t  _soloed_by_others_upstream;
101         uint32_t  _soloed_by_others_downstream;
102         int32_t   _transition_into_solo;
103
104         void set_self_solo (bool yn);
105         void set_mute_master_solo ();
106 };
107
108 } /* namespace */
109
110 #endif /* __libardour_solo_control_h__ */