2 Copyright (C) 2016 Paul Davis
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 __libardour_presentation_info_h__
21 #define __libardour_presentation_info_h__
28 #include "ardour/libardour_visibility.h"
34 class LIBARDOUR_API PresentationInfo
38 /* a PresentationInfo object exists to share information between
39 * different user interfaces (e.g. GUI and a Mackie Control surface)
49 * One UI takes control of ordering by setting the "order" value for
50 * the PresentationInfo component of every Stripable object. In Ardour,
51 * this is done by the GUI (mostly because it is very hard for the user
52 * to re-order things on a control surface).
54 * Ordering is a complex beast, however. Different user interfaces may
55 * display things in different ways. For example, the GUI of Ardour
56 * allows the user to mix busses in between tracks. A control surface
57 * may do the same, but may also allow the user to press a button that
58 * makes it show only busses, or only MIDI tracks. At that point, the
59 * ordering on the surface differs from the ordering in the GUI.
61 * The ordering is given via a combination of an object type and a
62 * simple numeric position within that type. The object types at this
66 * - object has inputs and outputs; processes data
68 * - Route used to connect to outside the application (MasterOut, MonitorOut)
70 * - special type of Route (e.g. Auditioner)
72 * - no data flows through; control only
74 * Objects with a numeric order of zero are considered unsorted. This
75 * applies (for now) to special objects such as the master out,
76 * auditioner and monitor out. The rationale here is that the GUI
77 * presents these objects in special ways, rather than as part of some
78 * (potentially) re-orderable container. The same is true for hardware
79 * surfaces, where the master fader (for instance) is typically
80 * separate and distinct from anything else.
82 * There are several pathways for the order being set:
84 * - object created during session loading from XML
85 * - numeric order will be set during ::set_state(), based on
86 * - type will be set during ctor call
88 * - object created in response to user request
89 * - numeric order will be set by Session, before adding
91 * - type set during ctor call
96 * Control surfaces/protocols often need to be able to get a handle on
97 * an object identified only abstractly, such as the "5th audio track"
98 * or "the master out". A PresentationInfo object uniquely identifies
99 * all objects in this way through the combination of its _order member
100 * and part of its _flags member. The _flags member identifies the type
101 * of object, as well as selection/hidden status. The type may never
102 * change after construction (not strictly the constructor itself, but
103 * a more generalized notion of construction, as in "ready to use").
107 * When an object is selected, its _flags member will have the Selected
112 * When an object is hidden, its _flags member will have the Hidden
120 /* Type information */
127 /* These need to be at the high end */
132 /* These are for sharing Stripable states between the GUI and other
133 * user interfaces/control surfaces
138 /* single bit indicates that the group order is set */
139 GroupOrderSet = 0x100000000,
143 GroupMask = (AudioTrack|MidiTrack|AudioBus|MidiBus|VCA),
144 SpecialMask = (MasterOut|MonitorOut|Auditioner),
145 StatusMask = (Selected|Hidden),
148 static const Flag Route;
149 static const Flag Track;
150 static const Flag Bus;
152 typedef uint32_t order_t;
153 typedef uint64_t global_order_t;
155 PresentationInfo (Flag f) : _order (0), _flags (Flag (f & ~GroupOrderSet)) { /* GroupOrderSet is not set */ }
156 PresentationInfo (order_t o, Flag f) : _order (o), _flags (Flag (f | GroupOrderSet)) { /* GroupOrderSet is set */ }
158 static const order_t max_order;
160 order_t group_order() const { return _order; }
161 global_order_t global_order () const {
162 if (_flags & Route) {
164 /* set all bits related to Route so that all Routes
165 sort together, with order() in the range of
166 64424509440..68719476735
168 Consider the following arrangement:
180 these translate into the following
182 _order | _flags | order()
183 --------------------------------------
184 1 | 0x1 AudioTrack | ((0x1|0x2|0x4|0x8)<<32)|1 = 64424509441
185 2 | 0x2 AudioBus | ((0x1|0x2|0x4|0x8)<<32)|2 = 64424509442
186 3 | 0x1 AudioTrack | ((0x1|0x2|0x4|0x8)<<32)|3 = 64424509443
188 1 | 0x10 VCA | ((0x10)<<32)|1 = 68719476737
190 0 | 0x800 Master | (0x800<<32) = 8796093022208
192 0 | 0x1000 Monitor | (0x1000<<32) = 17592186044416
196 return (((global_order_t) (_flags | Route)) << sizeof(order_t)) | _order;
198 return (((global_order_t) _flags) << sizeof(order_t)) | _order;
202 PresentationInfo::Flag flags() const { return _flags; }
204 bool order_set() const { return _order != 0; }
206 /* these objects have no defined order */
207 bool special () const { return _flags & SpecialMask; }
209 /* detect group order set/not set */
210 bool unordered() const { return !(_flags & GroupOrderSet); }
211 bool ordered() const { return _flags & GroupOrderSet; }
213 void set_flag (PresentationInfo::Flag f) {
214 _flags = PresentationInfo::Flag (_flags | f);
217 void unset_flag (PresentationInfo::Flag f) {
218 _flags = PresentationInfo::Flag (_flags & ~f);
221 void set_flags (Flag f) {
225 bool flag_match (Flag f) const {
226 /* no flags, match all */
232 if (f & StatusMask) {
233 /* status bits set, must match them */
234 if ((_flags & StatusMask) != (f & StatusMask)) {
239 /* Generic flags in f, match the right stuff */
241 if (f == Bus && (_flags & Bus)) {
242 /* some kind of bus */
245 if (f == Track && (_flags & Track)) {
246 /* some kind of track */
249 if (f == Route && (_flags & Route)) {
250 /* any kind of route */
257 std::string to_string () const;
259 uint64_t to_integer () const {
260 return ((uint64_t) _flags << sizeof(order_t)) | _order;
263 bool operator< (PresentationInfo const& other) const {
264 return global_order() < other.global_order();
267 PresentationInfo& operator= (std::string const& str) {
272 bool match (PresentationInfo const& other) const {
273 return (_order == other.group_order()) && flag_match (other.flags());
276 bool operator==(PresentationInfo const& other) {
277 return (_order == other.group_order()) && (_flags == other.flags());
280 bool operator!=(PresentationInfo const& other) {
281 return (_order != other.group_order()) || (_flags != other.flags());
284 static Flag get_flags (XMLNode const& node);
287 friend class Stripable;
288 void set_group_order (order_t order) { _order = order; _flags = Flag (_flags|GroupOrderSet); }
294 PresentationInfo (std::string const & str);
295 int parse (std::string const&);
296 int parse (order_t, Flag f);
301 std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid);
303 #endif /* __libardour_presentation_info_h__ */