diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2016-05-16 07:30:28 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2016-05-31 15:30:42 -0400 |
commit | e0ff70cf86c01c42f98faf8b0eaf1a8ccf867946 (patch) | |
tree | dcb5ac7037e3b41d850930ea0a1759d79f8ca82a /libs/ardour/ardour/presentation_info.h | |
parent | bae9474e9f04e324b1a2776b0fa9faefb5e6f0c2 (diff) |
first vaguely working version using PresentationInfo
remote control ID and "order keys" have been removed.
Diffstat (limited to 'libs/ardour/ardour/presentation_info.h')
-rw-r--r-- | libs/ardour/ardour/presentation_info.h | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/libs/ardour/ardour/presentation_info.h b/libs/ardour/ardour/presentation_info.h new file mode 100644 index 0000000000..f7446a7713 --- /dev/null +++ b/libs/ardour/ardour/presentation_info.h @@ -0,0 +1,303 @@ +/* + Copyright (C) 2016 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __libardour_presentation_info_h__ +#define __libardour_presentation_info_h__ + +#include <iostream> +#include <string> + +#include <stdint.h> + +#include "ardour/libardour_visibility.h" + +class XMLNode; + +namespace ARDOUR { + +class LIBARDOUR_API PresentationInfo +{ + public: + + /* a PresentationInfo object exists to share information between + * different user interfaces (e.g. GUI and a Mackie Control surface) + * about: + * + * - ordering + * - selection status + * - visibility + * - object identity + * + * ORDERING + * + * One UI takes control of ordering by setting the "order" value for + * the PresentationInfo component of every Stripable object. In Ardour, + * this is done by the GUI (mostly because it is very hard for the user + * to re-order things on a control surface). + * + * Ordering is a complex beast, however. Different user interfaces may + * display things in different ways. For example, the GUI of Ardour + * allows the user to mix busses in between tracks. A control surface + * may do the same, but may also allow the user to press a button that + * makes it show only busses, or only MIDI tracks. At that point, the + * ordering on the surface differs from the ordering in the GUI. + * + * The ordering is given via a combination of an object type and a + * simple numeric position within that type. The object types at this + * time are: + * + * Route + * - object has inputs and outputs; processes data + * Output + * - Route used to connect to outside the application (MasterOut, MonitorOut) + * Special + * - special type of Route (e.g. Auditioner) + * VCA + * - no data flows through; control only + * + * Objects with a numeric order of zero are considered unsorted. This + * applies (for now) to special objects such as the master out, + * auditioner and monitor out. The rationale here is that the GUI + * presents these objects in special ways, rather than as part of some + * (potentially) re-orderable container. The same is true for hardware + * surfaces, where the master fader (for instance) is typically + * separate and distinct from anything else. + * + * There are several pathways for the order being set: + * + * - object created during session loading from XML + * - numeric order will be set during ::set_state(), based on + * - type will be set during ctor call + * + * - object created in response to user request + * - numeric order will be set by Session, before adding + * to container. + * - type set during ctor call + * + * + * OBJECT IDENTITY + * + * Control surfaces/protocols often need to be able to get a handle on + * an object identified only abstractly, such as the "5th audio track" + * or "the master out". A PresentationInfo object uniquely identifies + * all objects in this way through the combination of its _order member + * and part of its _flags member. The _flags member identifies the type + * of object, as well as selection/hidden status. The type may never + * change after construction (not strictly the constructor itself, but + * a more generalized notion of construction, as in "ready to use"). + * + * SELECTION + * + * When an object is selected, its _flags member will have the Selected + * bit set. + * + * VISIBILITY + * + * When an object is hidden, its _flags member will have the Hidden + * bit set. + * + * + */ + + + enum Flag { + /* Type information */ + AudioTrack = 0x1, + MidiTrack = 0x2, + AudioBus = 0x4, + MidiBus = 0x8, + VCA = 0x10, + + /* These need to be at the high end */ + MasterOut = 0x800, + MonitorOut = 0x1000, + Auditioner = 0x2000, + + /* These are for sharing Stripable states between the GUI and other + * user interfaces/control surfaces + */ + Selected = 0x4000, + Hidden = 0x8000, + + /* single bit indicates that the group order is set */ + GroupOrderSet = 0x100000000, + + /* Masks */ + + GroupMask = (AudioTrack|MidiTrack|AudioBus|MidiBus|VCA), + SpecialMask = (MasterOut|MonitorOut|Auditioner), + StatusMask = (Selected|Hidden), + }; + + static const Flag Route; + static const Flag Track; + static const Flag Bus; + + typedef uint32_t order_t; + typedef uint64_t global_order_t; + + PresentationInfo (Flag f) : _order (0), _flags (Flag (f & ~GroupOrderSet)) { /* GroupOrderSet is not set */ } + PresentationInfo (order_t o, Flag f) : _order (o), _flags (Flag (f | GroupOrderSet)) { /* GroupOrderSet is set */ } + + static const order_t max_order; + + order_t group_order() const { return _order; } + global_order_t global_order () const { + if (_flags & Route) { + + /* set all bits related to Route so that all Routes + sort together, with order() in the range of + 64424509440..68719476735 + + Consider the following arrangement: + + Track 1 + Bus 1 + Track 2 + --------- + VCA 1 + --------- + Master + --------- + Monitor + + these translate into the following + + _order | _flags | order() + -------------------------------------- + 1 | 0x1 AudioTrack | ((0x1|0x2|0x4|0x8)<<32)|1 = 64424509441 + 2 | 0x2 AudioBus | ((0x1|0x2|0x4|0x8)<<32)|2 = 64424509442 + 3 | 0x1 AudioTrack | ((0x1|0x2|0x4|0x8)<<32)|3 = 64424509443 + + 1 | 0x10 VCA | ((0x10)<<32)|1 = 68719476737 + + 0 | 0x800 Master | (0x800<<32) = 8796093022208 + + 0 | 0x1000 Monitor | (0x1000<<32) = 17592186044416 + + */ + + return (((global_order_t) (_flags | Route)) << sizeof(order_t)) | _order; + } else { + return (((global_order_t) _flags) << sizeof(order_t)) | _order; + } + } + + PresentationInfo::Flag flags() const { return _flags; } + + bool order_set() const { return _order != 0; } + + /* these objects have no defined order */ + bool special () const { return _flags & SpecialMask; } + + /* detect group order set/not set */ + bool unordered() const { return !(_flags & GroupOrderSet); } + bool ordered() const { return _flags & GroupOrderSet; } + + void set_flag (PresentationInfo::Flag f) { + _flags = PresentationInfo::Flag (_flags | f); + } + + void unset_flag (PresentationInfo::Flag f) { + _flags = PresentationInfo::Flag (_flags & ~f); + } + + void set_flags (Flag f) { + _flags = f; + } + + bool flag_match (Flag f) const { + /* no flags, match all */ + + if (f == Flag (0)) { + return true; + } + + if (f & StatusMask) { + /* status bits set, must match them */ + if ((_flags & StatusMask) != (f & StatusMask)) { + return false; + } + } + + /* Generic flags in f, match the right stuff */ + + if (f == Bus && (_flags & Bus)) { + /* some kind of bus */ + return true; + } + if (f == Track && (_flags & Track)) { + /* some kind of track */ + return true; + } + if (f == Route && (_flags & Route)) { + /* any kind of route */ + return true; + } + + return f == _flags; + } + + std::string to_string () const; + + uint64_t to_integer () const { + return ((uint64_t) _flags << sizeof(order_t)) | _order; + } + + bool operator< (PresentationInfo const& other) const { + return global_order() < other.global_order(); + } + + PresentationInfo& operator= (std::string const& str) { + parse (str); + return *this; + } + + bool match (PresentationInfo const& other) const { + return (_order == other.group_order()) && flag_match (other.flags()); + } + + bool operator==(PresentationInfo const& other) { + return (_order == other.group_order()) && (_flags == other.flags()); + } + + bool operator!=(PresentationInfo const& other) { + return (_order != other.group_order()) || (_flags != other.flags()); + } + + static Flag get_flags (XMLNode const& node); + + protected: + friend class Stripable; + void set_group_order (order_t order) { _order = order; _flags = Flag (_flags|GroupOrderSet); } + + private: + order_t _order; + Flag _flags; + + PresentationInfo (std::string const & str); + int parse (std::string const&); + int parse (order_t, Flag f); +}; + +} + +std::ostream& operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid); + +#endif /* __libardour_presentation_info_h__ */ |