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 #ifndef __libardour_presentation_info_h__ 22 #define __libardour_presentation_info_h__ 23 24 #include <iostream> 25 #include <string> 26 27 #include <stdint.h> 28 29 #include "pbd/signals.h" 30 #include "pbd/stateful.h" 31 #include "pbd/properties.h" 32 #include "pbd/g_atomic_compat.h" 33 34 #include "ardour/libardour_visibility.h" 35 36 class XMLNode; 37 38 namespace ARDOUR { 39 40 namespace Properties { 41 LIBARDOUR_API extern PBD::PropertyDescriptor<uint32_t> order; 42 LIBARDOUR_API extern PBD::PropertyDescriptor<uint32_t> color; 43 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> selected; 44 /* we use this; declared in region.cc */ 45 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> hidden; 46 } 47 48 class LIBARDOUR_API PresentationInfo : public PBD::Stateful 49 { 50 public: 51 52 /* a PresentationInfo object exists to share information between 53 * different user interfaces (e.g. GUI and a Mackie Control surface) 54 * about: 55 * 56 * - ordering 57 * - selection status 58 * - visibility 59 * - object identity 60 * 61 * ORDERING 62 * 63 * One UI takes control of ordering by setting the "order" value for 64 * the PresentationInfo component of every Stripable object. In Ardour, 65 * this is done by the GUI (mostly because it is very hard for the user 66 * to re-order things on a control surface). 67 * 68 * Ordering is a complex beast, however. Different user interfaces may 69 * display things in different ways. For example, the GUI of Ardour 70 * allows the user to mix busses in between tracks. A control surface 71 * may do the same, but may also allow the user to press a button that 72 * makes it show only busses, or only MIDI tracks. At that point, the 73 * ordering on the surface differs from the ordering in the GUI. 74 * 75 * There are several pathways for the order being set: 76 * 77 * - object created during session loading from XML 78 * - numeric order will be set during ::set_state(), based on 79 * - type will be set during ctor call 80 * 81 * - object created in response to user request 82 * - numeric order will be set by Session, before adding to container. 83 * - type set during ctor call 84 * 85 * 86 * OBJECT IDENTITY 87 * 88 * Control surfaces/protocols often need to be able to get a handle on 89 * an object identified only abstractly, such as the "5th audio track" 90 * or "the master out". A PresentationInfo object uniquely identifies 91 * all objects in this way through the combination of its _order member 92 * and part of its _flags member. The _flags member identifies the type 93 * of object, as well as selection/hidden status. The type may never 94 * change after construction (not strictly the constructor itself, but 95 * a more generalized notion of construction, as in "ready to use"). 96 * 97 * VISIBILITY 98 * 99 * When an object is hidden, its _flags member will have the Hidden 100 * bit set. 101 * 102 * 103 */ 104 105 enum Flag { 106 /* Type information */ 107 AudioTrack = 0x1, 108 MidiTrack = 0x2, 109 AudioBus = 0x4, 110 MidiBus = 0x8, 111 VCA = 0x10, 112 MasterOut = 0x20, 113 MonitorOut = 0x40, 114 Auditioner = 0x80, 115 #ifdef MIXBUS 116 Mixbus = 0x1000, 117 #endif 118 /* These are for sharing Stripable states between the GUI and other 119 * user interfaces/control surfaces 120 */ 121 Hidden = 0x100, 122 #ifdef MIXBUS 123 MixbusEditorHidden = 0x800, 124 #endif 125 /* single bit indicates that the group order is set */ 126 OrderSet = 0x400, 127 128 /* bus type for monitor mixes */ 129 FoldbackBus = 0x2000, 130 131 /* special mask to delect out "state" bits */ 132 StatusMask = (Hidden), 133 /* special mask to delect select type bits */ 134 TypeMask = (AudioBus|AudioTrack|MidiTrack|MidiBus|VCA|MasterOut|MonitorOut|Auditioner|FoldbackBus) 135 }; 136 137 static const Flag AllStripables; /* mask to use for any route or VCA (but not auditioner) */ 138 static const Flag MixerStripables; /* mask to use for any route or VCA (but not auditioner or foldbackbus) */ 139 static const Flag AllRoutes; /* mask to use for any route include master+monitor, but not auditioner */ 140 static const Flag MixerRoutes; /* mask to use for any route include master+monitor, but not auditioner or foldbackbus*/ 141 static const Flag Route; /* mask for any route (bus or track */ 142 static const Flag Track; /* mask to use for any track */ 143 static const Flag Bus; /* mask to use for any bus */ 144 145 typedef uint32_t order_t; 146 typedef uint32_t color_t; 147 148 PresentationInfo (Flag f); 149 PresentationInfo (order_t o, Flag f); 150 PresentationInfo (PresentationInfo const &); 151 152 static const order_t max_order; 153 flags()154 PresentationInfo::Flag flags() const { return _flags; } order()155 order_t order() const { return _order; } color()156 color_t color() const { return _color; } 157 158 bool color_set() const; 159 160 void set_color (color_t); 161 void set_hidden (bool yn); set_flags(Flag f)162 void set_flags (Flag f) { _flags = f; } 163 order_set()164 bool order_set() const { return _flags & OrderSet; } 165 selection_cnt()166 int selection_cnt() const { return _selection_cnt; } 167 hidden()168 bool hidden() const { return _flags & Hidden; } 169 bool special(bool with_master = true) const { return _flags & ((with_master ? MasterOut : 0)|MonitorOut|Auditioner); } 170 flag_match(Flag f)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, but not master, monitor in 197 or auditioner. 198 */ 199 return true; 200 } 201 202 if (f == AllRoutes && (_flags & AllRoutes)) { 203 /* any kind of route, but not auditioner. Ask for that 204 specifically. 205 */ 206 return true; 207 } 208 209 if (f == AllStripables && (_flags & AllStripables)) { 210 /* any kind of stripable, but not auditioner. Ask for that 211 specifically. 212 */ 213 return true; 214 } 215 216 /* check for any matching type bits. 217 * 218 * Do comparisoon without status mask or order set bits - we 219 * already checked that above. 220 */ 221 222 return ((f & TypeMask) & _flags); 223 } 224 225 int set_state (XMLNode const&, int); 226 XMLNode& get_state (); 227 228 bool operator==(PresentationInfo const& other) { 229 return (_order == other.order()) && (_flags == other.flags()); 230 } 231 232 bool operator!=(PresentationInfo const& other) { 233 return (_order != other.order()) || (_flags != other.flags()); 234 } 235 236 PresentationInfo& operator= (PresentationInfo const& other); 237 238 static Flag get_flags (XMLNode const& node); 239 static Flag get_flags2X3X (XMLNode const& node); 240 static std::string state_node_name; 241 242 /* for things concerned about *any* PresentationInfo. 243 */ 244 245 static PBD::Signal1<void,PBD::PropertyChange const &> Change; 246 static void send_static_change (const PBD::PropertyChange&); 247 248 static void make_property_quarks (); 249 250 protected: 251 friend class ChangeSuspender; 252 static void suspend_change_signal (); 253 static void unsuspend_change_signal (); 254 255 public: 256 class ChangeSuspender { 257 public: ChangeSuspender()258 ChangeSuspender() { 259 PresentationInfo::suspend_change_signal (); 260 } ~ChangeSuspender()261 ~ChangeSuspender() { 262 PresentationInfo::unsuspend_change_signal (); 263 } 264 }; 265 266 protected: 267 friend class Stripable; 268 void set_order (order_t order); 269 270 private: 271 order_t _order; 272 Flag _flags; 273 color_t _color; 274 int _selection_cnt; 275 276 static PBD::PropertyChange _pending_static_changes; 277 static Glib::Threads::Mutex static_signal_lock; 278 static GATOMIC_QUAL gint _change_signal_suspended; 279 280 static int selection_counter; 281 }; 282 283 } 284 285 std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid); 286 287 #endif /* __libardour_presentation_info_h__ */ 288