extensive changes to PresentationInfo API
[ardour.git] / libs / ardour / ardour / presentation_info.h
1 /*
2     Copyright (C) 2016 Paul Davis
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 __libardour_presentation_info_h__
21 #define __libardour_presentation_info_h__
22
23 #include <iostream>
24 #include <string>
25
26 #include <stdint.h>
27
28 #include "pbd/signals.h"
29 #include "pbd/stateful.h"
30 #include "pbd/properties.h"
31
32 #include "ardour/libardour_visibility.h"
33
34 class XMLNode;
35
36 namespace ARDOUR {
37
38 namespace Properties {
39         LIBARDOUR_API extern PBD::PropertyDescriptor<uint32_t> order;
40         LIBARDOUR_API extern PBD::PropertyDescriptor<uint32_t> color;
41         LIBARDOUR_API extern PBD::PropertyDescriptor<bool> selected;
42         /* we use this; declared in region.cc */
43         LIBARDOUR_API extern PBD::PropertyDescriptor<bool> hidden;
44 }
45
46 class LIBARDOUR_API PresentationInfo : public PBD::Stateful
47 {
48   public:
49
50         /* a PresentationInfo object exists to share information between
51          * different user interfaces (e.g. GUI and a Mackie Control surface)
52          * about:
53          *
54          *     - ordering
55          *     - selection status
56          *     - visibility
57          *     - object identity
58          *
59          * ORDERING
60          *
61          * One UI takes control of ordering by setting the "order" value for
62          * the PresentationInfo component of every Stripable object. In Ardour,
63          * this is done by the GUI (mostly because it is very hard for the user
64          * to re-order things on a control surface).
65          *
66          * Ordering is a complex beast, however. Different user interfaces may
67          * display things in different ways. For example, the GUI of Ardour
68          * allows the user to mix busses in between tracks. A control surface
69          * may do the same, but may also allow the user to press a button that
70          * makes it show only busses, or only MIDI tracks. At that point, the
71          * ordering on the surface differs from the ordering in the GUI.
72          *
73          * There are several pathways for the order being set:
74          *
75          *   - object created during session loading from XML
76          *           - numeric order will be set during ::set_state(), based on
77          *           - type will be set during ctor call
78          *
79          *   - object created in response to user request
80          *              - numeric order will be set by Session, before adding
81          *                   to container.
82          *              - type set during ctor call
83          *
84          *
85          * OBJECT IDENTITY
86          *
87          * Control surfaces/protocols often need to be able to get a handle on
88          * an object identified only abstractly, such as the "5th audio track"
89          * or "the master out". A PresentationInfo object uniquely identifies
90          * all objects in this way through the combination of its _order member
91          * and part of its _flags member. The _flags member identifies the type
92          * of object, as well as selection/hidden status. The type may never
93          * change after construction (not strictly the constructor itself, but
94          * a more generalized notion of construction, as in "ready to use").
95          *
96          * SELECTION
97          *
98          * When an object is selected, its _flags member will have the Selected
99          * bit set.
100          *
101          * VISIBILITY
102          *
103          * When an object is hidden, its _flags member will have the Hidden
104          * bit set.
105          *
106          *
107          */
108
109         enum Flag {
110                 /* Type information */
111                 AudioTrack = 0x1,
112                 MidiTrack = 0x2,
113                 AudioBus = 0x4,
114                 MidiBus = 0x8,
115                 VCA = 0x10,
116                 MasterOut = 0x20,
117                 MonitorOut = 0x40,
118                 Auditioner = 0x80,
119                 /* These are for sharing Stripable states between the GUI and other
120                  * user interfaces/control surfaces
121                  */
122                 Selected = 0x100,
123                 Hidden = 0x200,
124                 /* single bit indicates that the group order is set */
125                 OrderSet = 0x400,
126
127                 /* special mask to delect out "state" bits */
128                 StatusMask = (Selected|Hidden)
129         };
130
131         static const Flag Route;
132         static const Flag Track;
133         static const Flag Bus;
134
135         typedef uint32_t order_t;
136         typedef uint32_t color_t;
137
138         PresentationInfo (Flag f);
139         PresentationInfo (order_t o, Flag f);
140         PresentationInfo (PresentationInfo const &);
141
142         static const order_t max_order;
143
144         order_t  order() const { return _order; }
145         color_t  color() const { return _color; }
146
147         void set_color (color_t);
148         void set_selected (bool yn);
149         void set_hidden (bool yn);
150
151         PresentationInfo::Flag flags() const { return _flags; }
152
153         bool order_set() const { return _flags & OrderSet; }
154
155         bool hidden() const { return _flags & Hidden; }
156         bool selected() const { return _flags & Selected; }
157         bool special() const { return _flags & (MasterOut|MonitorOut|Auditioner); }
158
159         void set_flag (PresentationInfo::Flag f) {
160                 _flags = PresentationInfo::Flag (_flags | f);
161         }
162
163         void unset_flag (PresentationInfo::Flag f) {
164                 _flags = PresentationInfo::Flag (_flags & ~f);
165         }
166
167         void set_flags (Flag f) {
168                 _flags = f;
169         }
170
171         bool flag_match (Flag f) const {
172                 /* no flags, match all */
173
174                 if (f == Flag (0)) {
175                         return true;
176                 }
177
178                 if (f & StatusMask) {
179                         /* status bits set, must match them */
180                         if ((_flags & StatusMask) != (f & StatusMask)) {
181                                 return false;
182                         }
183                 }
184
185                 /* Generic flags in f, match the right stuff */
186
187                 if (f == Bus && (_flags & Bus)) {
188                         /* some kind of bus */
189                         return true;
190                 }
191                 if (f == Track && (_flags & Track)) {
192                         /* some kind of track */
193                         return true;
194                 }
195                 if (f == Route && (_flags & Route)) {
196                         /* any kind of route */
197                         return true;
198                 }
199
200                 return f == _flags;
201         }
202
203         int set_state (XMLNode const&, int);
204         XMLNode& get_state ();
205
206         bool operator< (PresentationInfo const& other) const {
207                 return order() < other.order();
208         }
209
210         bool match (PresentationInfo const& other) const {
211                 return (_order == other.order()) && flag_match (other.flags());
212         }
213
214         bool operator==(PresentationInfo const& other) {
215                 return (_order == other.order()) && (_flags == other.flags());
216         }
217
218         bool operator!=(PresentationInfo const& other) {
219                 return (_order != other.order()) || (_flags != other.flags());
220         }
221
222         PresentationInfo& operator= (PresentationInfo const& other);
223
224         static Flag get_flags (XMLNode const& node);
225         static std::string state_node_name;
226
227         /* for things concerned about *any* PresentationInfo. This is emitted
228          * only at the request of another object that has finished making some
229          * changes (e.g. reordering things)
230          */
231
232         static PBD::Signal0<void> Change;
233
234         static void make_property_quarks ();
235
236   protected:
237         friend class Stripable;
238         void set_order (order_t order);
239
240   private:
241         order_t _order;
242         Flag    _flags;
243         color_t _color;
244 };
245
246 }
247
248 std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid);
249
250 #endif /* __libardour_presentation_info_h__ */