Ardour  9.8-93-g460ea8c013
presentation_info.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2017 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2016-2019 Robin Gareus <robin@gareus.org>
4  * Copyright (C) 2018 Len Ovens <len@ovenwerks.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #pragma once
22 
23 #include <iostream>
24 #include <string>
25 
26 #include <atomic>
27 #include <cstdint>
28 
29 #include "pbd/signals.h"
30 #include "pbd/stateful.h"
31 #include "pbd/properties.h"
32 
34 
35 class XMLNode;
36 
37 namespace ARDOUR {
38 
39 namespace Properties {
45  /* we use this; declared in region.cc */
47 }
48 
50 {
51  public:
52 
53  /* a PresentationInfo object exists to share information between
54  * different user interfaces (e.g. GUI and a Mackie Control surface)
55  * about:
56  *
57  * - ordering
58  * - selection status
59  * - visibility
60  * - object identity
61  *
62  * ORDERING
63  *
64  * One UI takes control of ordering by setting the "order" value for
65  * the PresentationInfo component of every Stripable object. In Ardour,
66  * this is done by the GUI (mostly because it is very hard for the user
67  * to re-order things on a control surface).
68  *
69  * Ordering is a complex beast, however. Different user interfaces may
70  * display things in different ways. For example, the GUI of Ardour
71  * allows the user to mix busses in between tracks. A control surface
72  * may do the same, but may also allow the user to press a button that
73  * makes it show only busses, or only MIDI tracks. At that point, the
74  * ordering on the surface differs from the ordering in the GUI.
75  *
76  * There are several pathways for the order being set:
77  *
78  * - object created during session loading from XML
79  * - numeric order will be set during ::set_state(), based on
80  * - type will be set during ctor call
81  *
82  * - object created in response to user request
83  * - numeric order will be set by Session, before adding to container.
84  * - type set during ctor call
85  *
86  *
87  * OBJECT IDENTITY
88  *
89  * Control surfaces/protocols often need to be able to get a handle on
90  * an object identified only abstractly, such as the "5th audio track"
91  * or "the master out". A PresentationInfo object uniquely identifies
92  * all objects in this way through the combination of its _order member
93  * and part of its _flags member. The _flags member identifies the type
94  * of object, as well as selection/hidden status. The type may never
95  * change after construction (not strictly the constructor itself, but
96  * a more generalized notion of construction, as in "ready to use").
97  *
98  * VISIBILITY
99  *
100  * When an object is hidden, its _flags member will have the Hidden
101  * bit set.
102  *
103  *
104  */
105 
106  enum Flag {
107  /* Type information */
108  AudioTrack = 0x1,
109  MidiTrack = 0x2,
110  AudioBus = 0x4,
111  MidiBus = 0x8,
112  VCA = 0x10,
113  MasterOut = 0x20,
114  MonitorOut = 0x40,
115  Auditioner = 0x80,
116  /* These are for sharing Stripable states between the GUI and other
117  * user interfaces/control surfaces
118  */
119  Hidden = 0x100,
120  /* single bit indicates that the group order is set */
121  OrderSet = 0x400,
122 
123  /* Mixbus specific */
124  MixbusEditorHidden = 0x800,
125  Mixbus = 0x1000,
126 
127  /* bus type for monitor mixes */
128  FoldbackBus = 0x2000,
129 
130  /* has TriggerBox, show on TriggerUI page */
131  TriggerTrack = 0x4000,
132 
133 #ifndef VBM
134  /* bus is the surround master */
135  SurroundMaster = 0x8000,
136 #else
137  SurroundMaster = 0, // for compatibility
138 #endif
139 
140  /* VBM */
141  Program = 0x4000, // deprecated (conflicts with TriggerTrack)
142  MixMinus = 0x8000, // deprecated (conflicts with SurroundMaster)
143  VBMProgram = 0x10000,
144  VBMMixMinus = 0x20000,
145 #ifdef VBM
146  VBMAny = 0x3c000,
147 #else
148  VBMAny = 0x30000,
149 #endif
150 
151  Transient = 0x60000,
152 
153  /* special mask to detect out "state" bits */
154  StatusMask = (Hidden | MixbusEditorHidden | TriggerTrack),
155 
156  /* dedicated [output] busses */
157  MainBus = (MasterOut|MonitorOut|FoldbackBus|SurroundMaster),
158 
159  /* These can exist only once and require special attention to be removed */
160  Singleton = (MasterOut|MonitorOut|SurroundMaster),
161 
162  /* special mask to detect select type bits */
163  TypeMask = (AudioBus|AudioTrack|MidiTrack|MidiBus|Mixbus|VCA|MasterOut|MonitorOut|Auditioner|FoldbackBus|SurroundMaster|VBMAny)
164  };
165 
166  static const Flag AllStripables; /* mask to use for any route or VCA (but not auditioner) */
167  static const Flag MixerStripables; /* mask to use for any route or VCA (but not auditioner or foldbackbus) */
168  static const Flag AllRoutes; /* mask to use for any route include master+monitor, but not auditioner */
169  static const Flag MixerRoutes; /* mask to use for any route include master+monitor, but not auditioner or foldbackbus*/
170  static const Flag Route; /* mask for any route (bus or track */
171  static const Flag Track; /* mask to use for any track */
172  static const Flag Bus; /* mask to use for any bus */
173  static const Flag MidiIndicatingFlags; /* MidiTrack or MidiBus */
174 
175  typedef uint32_t order_t;
176  typedef uint32_t color_t;
177 
181 
182  static const order_t max_order;
183 
184  PresentationInfo::Flag flags() const { return _flags; }
185  order_t order() const { return _order; }
186  color_t color() const { return _color; }
187 
188  bool color_set() const;
189 
191  void set_hidden (bool yn);
192  void set_transient (bool yn);
193  void set_trigger_track (bool yn);
194  /* dangerous: does not send property change */
195  void set_flags (Flag f) { _flags = f; }
196 
197  bool order_set() const { return _flags & OrderSet; }
198 
199  int selection_cnt() const { return _selection_cnt; }
200 
201  bool hidden() const { return _flags & Hidden; }
202  bool transient() const { return _flags & Transient; }
203  bool trigger_track () const { return _flags & TriggerTrack; }
204  bool special(bool with_master = true) const { return _flags & ((with_master ? MasterOut : 0)|SurroundMaster|MonitorOut|Auditioner); }
205 
206  bool flag_match (Flag f) const {
207  /* no flags, match all */
208 
209  if (f == Flag (0)) {
210  return true;
211  }
212 
213  if (f & StatusMask) {
214  /* status bits set, must match them */
215  if ((_flags & StatusMask) != (f & StatusMask)) {
216  return false;
217  }
218  }
219 
220  /* Generic flags in f, match the right stuff */
221 
222  if (f == Bus && (_flags & Bus)) {
223  /* some kind of bus */
224  return true;
225  }
226  if (f == Track && (_flags & Track)) {
227  /* some kind of track */
228  return true;
229  }
230  if (f == Route && (_flags & Route)) {
231  /* any kind of route, but not master, monitor in
232  or auditioner.
233  */
234  return true;
235  }
236 
237  if (f == AllRoutes && (_flags & AllRoutes)) {
238  /* any kind of route, but not auditioner. Ask for that
239  specifically.
240  */
241  return true;
242  }
243 
244  if (f == AllStripables && (_flags & AllStripables)) {
245  /* any kind of stripable, but not auditioner. Ask for that
246  specifically.
247  */
248  return true;
249  }
250 
251  /* check for any matching type bits.
252  *
253  * Do comparisoon without status mask or order set bits - we
254  * already checked that above.
255  */
256 
257  return ((f & TypeMask) & _flags);
258  }
259 
260  int set_state (XMLNode const&, int);
261  XMLNode& get_state () const;
262 
263  bool operator==(PresentationInfo const& other) {
264  return (_order == other.order()) && (_flags == other.flags());
265  }
266 
267  bool operator!=(PresentationInfo const& other) {
268  return (_order != other.order()) || (_flags != other.flags());
269  }
270 
271  PresentationInfo& operator= (PresentationInfo const& other);
272 
273  static Flag get_flags (XMLNode const& node);
274  static Flag get_flags2X3X (XMLNode const& node);
275  static std::string state_node_name;
276 
277  /* for things concerned about *any* PresentationInfo.
278  */
279 
280  static PBD::Signal<void(PBD::PropertyChange const &)> Change;
282 
283  static void make_property_quarks ();
284 
285  protected:
286  friend class ChangeSuspender;
287  static void suspend_change_signal ();
288  static void unsuspend_change_signal ();
289 
290  public:
292  public:
295  }
298  }
299  };
300 
301  protected:
302  friend class Stripable;
304 
305  private:
310 
313  static std::atomic<int> _change_signal_suspended;
314 
315  static int selection_counter;
316 };
317 
318 }
319 
320 namespace std {
321 std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid);
322 }
323 
std::ostream & operator<<(std::ostream &o, ARDOUR::Bundle const &)
void set_transient(bool yn)
static PBD::PropertyChange _pending_static_changes
static Flag get_flags2X3X(XMLNode const &node)
static void suspend_change_signal()
void set_order(order_t order)
void set_trigger_track(bool yn)
static void make_property_quarks()
int set_state(XMLNode const &, int)
static PBD::Mutex static_signal_lock
bool operator!=(PresentationInfo const &other)
static PBD::Signal< void(PBD::PropertyChange const &)> Change
static const Flag AllStripables
static const Flag MixerStripables
static Flag get_flags(XMLNode const &node)
PresentationInfo(order_t o, Flag f)
static std::string state_node_name
bool flag_match(Flag f) const
static std::atomic< int > _change_signal_suspended
PresentationInfo::Flag flags() const
static void send_static_change(const PBD::PropertyChange &)
PresentationInfo(PresentationInfo const &)
bool operator==(PresentationInfo const &other)
bool special(bool with_master=true) const
static const Flag AllRoutes
void set_hidden(bool yn)
XMLNode & get_state() const
static const order_t max_order
static const Flag MixerRoutes
static void unsuspend_change_signal()
static const Flag MidiIndicatingFlags
Definition: xml++.h:114
#define LIBARDOUR_API
PBD::PropertyDescriptor< bool > hidden
PBD::PropertyDescriptor< uint32_t > order
PBD::PropertyDescriptor< bool > trigger_track
PBD::PropertyDescriptor< uint32_t > color
PBD::PropertyDescriptor< bool > selected
DebugBits Properties