1 /*
2      File: CAPropertyAddress.h
3  Abstract: Part of CoreAudio Utility Classes
4   Version: 1.1
5 
6  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
7  Inc. ("Apple") in consideration of your agreement to the following
8  terms, and your use, installation, modification or redistribution of
9  this Apple software constitutes acceptance of these terms.  If you do
10  not agree with these terms, please do not use, install, modify or
11  redistribute this Apple software.
12 
13  In consideration of your agreement to abide by the following terms, and
14  subject to these terms, Apple grants you a personal, non-exclusive
15  license, under Apple's copyrights in this original Apple software (the
16  "Apple Software"), to use, reproduce, modify and redistribute the Apple
17  Software, with or without modifications, in source and/or binary forms;
18  provided that if you redistribute the Apple Software in its entirety and
19  without modifications, you must retain this notice and the following
20  text and disclaimers in all such redistributions of the Apple Software.
21  Neither the name, trademarks, service marks or logos of Apple Inc. may
22  be used to endorse or promote products derived from the Apple Software
23  without specific prior written permission from Apple.  Except as
24  expressly stated in this notice, no other rights or licenses, express or
25  implied, are granted by Apple herein, including but not limited to any
26  patent rights that may be infringed by your derivative works or by other
27  works in which the Apple Software may be incorporated.
28 
29  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
30  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 
35  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42  POSSIBILITY OF SUCH DAMAGE.
43 
44  Copyright (C) 2014 Apple Inc. All Rights Reserved.
45 
46 */
47 #if !defined(__CAPropertyAddress_h__)
48 #define __CAPropertyAddress_h__
49 
50 //==================================================================================================
51 //	Includes
52 //==================================================================================================
53 
54 //	PublicUtility Includes
55 #include "CADebugMacros.h"
56 
57 //	System Includes
58 #include <CoreAudio/AudioHardware.h>
59 
60 //  Standard Library Includes
61 #include <algorithm>
62 #include <functional>
63 #include <vector>
64 
65 //==================================================================================================
66 //	CAPropertyAddress
67 //
68 //  CAPropertyAddress extends the AudioObjectPropertyAddress structure to C++ including constructors
69 //  and other utility operations. Note that there is no defined operator< or operator== because the
70 //  presence of wildcards for the fields make comparisons ambiguous without specifying whether or
71 //  not to take the wildcards into account. Consequently, if you want to use this struct in an STL
72 //  data structure, you'll need to specify the approriate function object explicitly in the template
73 //  declaration.
74 //==================================================================================================
75 
76 struct CAPropertyAddress
77 :
78 	public AudioObjectPropertyAddress
79 {
80 
81 //	Construction/Destruction
82 public:
CAPropertyAddressCAPropertyAddress83 						CAPropertyAddress()																													: AudioObjectPropertyAddress() { mSelector = 0; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
CAPropertyAddressCAPropertyAddress84 						CAPropertyAddress(AudioObjectPropertySelector inSelector)																			: AudioObjectPropertyAddress() { mSelector = inSelector; mScope = kAudioObjectPropertyScopeGlobal; mElement = kAudioObjectPropertyElementMaster; }
CAPropertyAddressCAPropertyAddress85 						CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope)											: AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = kAudioObjectPropertyElementMaster; }
CAPropertyAddressCAPropertyAddress86 						CAPropertyAddress(AudioObjectPropertySelector inSelector, AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement)   : AudioObjectPropertyAddress() { mSelector = inSelector; mScope = inScope; mElement = inElement; }
CAPropertyAddressCAPropertyAddress87 						CAPropertyAddress(const AudioObjectPropertyAddress& inAddress)																		: AudioObjectPropertyAddress(inAddress){}
CAPropertyAddressCAPropertyAddress88 						CAPropertyAddress(const CAPropertyAddress& inAddress)																				: AudioObjectPropertyAddress(inAddress){}
89 	CAPropertyAddress&  operator=(const AudioObjectPropertyAddress& inAddress)																				{ AudioObjectPropertyAddress::operator=(inAddress); return *this; }
90 	CAPropertyAddress&  operator=(const CAPropertyAddress& inAddress)																						{ AudioObjectPropertyAddress::operator=(inAddress); return *this; }
91 
92 //  Operations
93 public:
IsSameAddressCAPropertyAddress94 	static bool			IsSameAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)							{ return (inAddress1.mScope == inAddress2.mScope) && (inAddress1.mSelector == inAddress2.mSelector) && (inAddress1.mElement == inAddress2.mElement); }
IsLessThanAddressCAPropertyAddress95 	static bool			IsLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)						{ bool theAnswer = false; if(inAddress1.mScope != inAddress2.mScope) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(inAddress1.mSelector != inAddress2.mSelector) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
IsCongruentSelectorCAPropertyAddress96 	static bool			IsCongruentSelector(AudioObjectPropertySelector inSelector1, AudioObjectPropertySelector inSelector2)								{ return (inSelector1 == inSelector2) || (inSelector1 == kAudioObjectPropertySelectorWildcard) || (inSelector2 == kAudioObjectPropertySelectorWildcard); }
IsCongruentScopeCAPropertyAddress97 	static bool			IsCongruentScope(AudioObjectPropertyScope inScope1, AudioObjectPropertyScope inScope2)												{ return (inScope1 == inScope2) || (inScope1 == kAudioObjectPropertyScopeWildcard) || (inScope2 == kAudioObjectPropertyScopeWildcard); }
IsCongruentElementCAPropertyAddress98 	static bool			IsCongruentElement(AudioObjectPropertyElement inElement1, AudioObjectPropertyElement inElement2)									{ return (inElement1 == inElement2) || (inElement1 == kAudioObjectPropertyElementWildcard) || (inElement2 == kAudioObjectPropertyElementWildcard); }
IsCongruentAddressCAPropertyAddress99 	static bool			IsCongruentAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)						{ return IsCongruentScope(inAddress1.mScope, inAddress2.mScope) && IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector) && IsCongruentElement(inAddress1.mElement, inAddress2.mElement); }
IsCongruentLessThanAddressCAPropertyAddress100 	static bool			IsCongruentLessThanAddress(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2)				{ bool theAnswer = false; if(!IsCongruentScope(inAddress1.mScope, inAddress2.mScope)) { theAnswer = inAddress1.mScope < inAddress2.mScope; } else if(!IsCongruentSelector(inAddress1.mSelector, inAddress2.mSelector)) { theAnswer = inAddress1.mSelector < inAddress2.mSelector; } else if(!IsCongruentElement(inAddress1.mElement, inAddress2.mElement)) { theAnswer = inAddress1.mElement < inAddress2.mElement; } return theAnswer; }
101 
102 //  STL Helpers
103 public:
104 	struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
105 	{
operatorCAPropertyAddress::EqualTo106 		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsSameAddress(inAddress1, inAddress2); }
107 	};
108 
109 	struct LessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
110 	{
operatorCAPropertyAddress::LessThan111 		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsLessThanAddress(inAddress1, inAddress2); }
112 	};
113 
114 	struct CongruentEqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
115 	{
operatorCAPropertyAddress::CongruentEqualTo116 		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsCongruentAddress(inAddress1, inAddress2); }
117 	};
118 
119 	struct CongruentLessThan : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
120 	{
operatorCAPropertyAddress::CongruentLessThan121 		bool	operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const								{ return IsCongruentLessThanAddress(inAddress1, inAddress2); }
122 	};
123 
124 };
125 
126 //==================================================================================================
127 //  CAPropertyAddressList
128 //
129 //  An auto-resizing array of CAPropertyAddress structures.
130 //==================================================================================================
131 
132 class   CAPropertyAddressList
133 {
134 
135 //	Construction/Destruction
136 public:
CAPropertyAddressList()137 											CAPropertyAddressList()																	: mAddressList(), mToken(NULL) {}
CAPropertyAddressList(void * inToken)138 	explicit								CAPropertyAddressList(void* inToken)													: mAddressList(), mToken(inToken) {}
CAPropertyAddressList(uintptr_t inToken)139 	explicit								CAPropertyAddressList(uintptr_t inToken)												: mAddressList(), mToken(reinterpret_cast<void*>(inToken)) {}
CAPropertyAddressList(const CAPropertyAddressList & inAddressList)140 											CAPropertyAddressList(const CAPropertyAddressList& inAddressList)						: mAddressList(inAddressList.mAddressList), mToken(inAddressList.mToken) {}
141 	CAPropertyAddressList&					operator=(const CAPropertyAddressList& inAddressList)									{ mAddressList = inAddressList.mAddressList; mToken = inAddressList.mToken; return *this; }
~CAPropertyAddressList()142 											~CAPropertyAddressList()																{}
143 
144 //	Operations
145 public:
GetToken()146 	void*									GetToken() const																		{ return mToken; }
SetToken(void * inToken)147 	void									SetToken(void* inToken)																	{ mToken = inToken; }
148 
GetIntToken()149 	uintptr_t								GetIntToken() const																		{ return reinterpret_cast<uintptr_t>(mToken); }
SetIntToken(uintptr_t inToken)150 	void									SetIntToken(uintptr_t inToken)															{ mToken = reinterpret_cast<void*>(inToken); }
151 
GetAudioObjectIDToken()152 	AudioObjectID							GetAudioObjectIDToken() const															{ return static_cast<AudioObjectID>(reinterpret_cast<uintptr_t>(mToken)); }
153 
IsEmpty()154 	bool									IsEmpty() const																			{ return mAddressList.empty(); }
GetNumberItems()155 	UInt32									GetNumberItems() const																	{ return ToUInt32(mAddressList.size()); }
GetItemByIndex(UInt32 inIndex,AudioObjectPropertyAddress & outAddress)156 	void									GetItemByIndex(UInt32 inIndex, AudioObjectPropertyAddress& outAddress) const			{ if(inIndex < mAddressList.size()) { outAddress = mAddressList.at(inIndex); } }
GetItems()157 	const AudioObjectPropertyAddress*		GetItems() const																		{ return &(*mAddressList.begin()); }
GetItems()158 	AudioObjectPropertyAddress*				GetItems()																				{ return &(*mAddressList.begin()); }
159 
HasItem(const AudioObjectPropertyAddress & inAddress)160 	bool									HasItem(const AudioObjectPropertyAddress& inAddress) const								{ AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::CongruentEqualTo(), inAddress)); return theIterator != mAddressList.end(); }
HasExactItem(const AudioObjectPropertyAddress & inAddress)161 	bool									HasExactItem(const AudioObjectPropertyAddress& inAddress) const							{ AddressList::const_iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); return theIterator != mAddressList.end(); }
162 
AppendItem(const AudioObjectPropertyAddress & inAddress)163 	void									AppendItem(const AudioObjectPropertyAddress& inAddress)									{ mAddressList.push_back(inAddress); }
AppendUniqueItem(const AudioObjectPropertyAddress & inAddress)164 	void									AppendUniqueItem(const AudioObjectPropertyAddress& inAddress)							{ if(!HasItem(inAddress)) { mAddressList.push_back(inAddress); } }
AppendUniqueExactItem(const AudioObjectPropertyAddress & inAddress)165 	void									AppendUniqueExactItem(const AudioObjectPropertyAddress& inAddress)						{ if(!HasExactItem(inAddress)) { mAddressList.push_back(inAddress); } }
InsertItemAtIndex(UInt32 inIndex,const AudioObjectPropertyAddress & inAddress)166 	void									InsertItemAtIndex(UInt32 inIndex, const AudioObjectPropertyAddress& inAddress)			{ if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.insert(theIterator, inAddress); } else { mAddressList.push_back(inAddress); } }
EraseExactItem(const AudioObjectPropertyAddress & inAddress)167 	void									EraseExactItem(const AudioObjectPropertyAddress& inAddress)								{ AddressList::iterator theIterator = std::find_if(mAddressList.begin(), mAddressList.end(), std::bind1st(CAPropertyAddress::EqualTo(), inAddress)); if(theIterator != mAddressList.end()) { mAddressList.erase(theIterator); } }
EraseItemAtIndex(UInt32 inIndex)168 	void									EraseItemAtIndex(UInt32 inIndex)														{ if(inIndex < mAddressList.size()) { AddressList::iterator theIterator = mAddressList.begin(); std::advance(theIterator, static_cast<int>(inIndex)); mAddressList.erase(theIterator); } }
EraseAllItems()169 	void									EraseAllItems()																			{ mAddressList.clear(); }
170 
171 //  Implementation
172 private:
173 	typedef std::vector<CAPropertyAddress>  AddressList;
174 
175 	AddressList								mAddressList;
176 	void*									mToken;
177 
178 };
179 
180 //==================================================================================================
181 //  CAPropertyAddressListVector
182 //
183 //  An auto-resizing array of CAPropertyAddressList objects.
184 //==================================================================================================
185 
186 class	CAPropertyAddressListVector
187 {
188 
189 //	Construction/Destruction
190 public:
CAPropertyAddressListVector()191 												CAPropertyAddressListVector()														: mAddressListVector() {}
CAPropertyAddressListVector(const CAPropertyAddressListVector & inAddressListVector)192 												CAPropertyAddressListVector(const CAPropertyAddressListVector& inAddressListVector)	: mAddressListVector(inAddressListVector.mAddressListVector) {}
193 	CAPropertyAddressListVector&				operator=(const CAPropertyAddressListVector& inAddressListVector)					{ mAddressListVector = inAddressListVector.mAddressListVector; return *this; }
~CAPropertyAddressListVector()194 												~CAPropertyAddressListVector()														{}
195 
196 //	Operations
197 public:
IsEmpty()198 	bool										IsEmpty() const																		{ return mAddressListVector.empty(); }
199 	bool										HasAnyNonEmptyItems() const;
200 	bool										HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const;
201 	bool										HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const;
202 
GetNumberItems()203 	UInt32										GetNumberItems() const																{ return ToUInt32(mAddressListVector.size()); }
GetItemByIndex(UInt32 inIndex)204 	const CAPropertyAddressList&				GetItemByIndex(UInt32 inIndex) const												{ return mAddressListVector.at(inIndex); }
GetItemByIndex(UInt32 inIndex)205 	CAPropertyAddressList&						GetItemByIndex(UInt32 inIndex)														{ return mAddressListVector.at(inIndex); }
206 	const CAPropertyAddressList*				GetItemByToken(void* inToken) const;
207 	CAPropertyAddressList*						GetItemByToken(void* inToken);
208 	const CAPropertyAddressList*				GetItemByIntToken(uintptr_t inToken) const;
209 	CAPropertyAddressList*						GetItemByIntToken(uintptr_t inToken);
210 
AppendItem(const CAPropertyAddressList & inAddressList)211 	void										AppendItem(const CAPropertyAddressList& inAddressList)								{ mAddressListVector.push_back(inAddressList); }
EraseAllItems()212 	void										EraseAllItems()																		{ mAddressListVector.clear(); }
213 
214 //  Implementation
215 private:
216 	typedef std::vector<CAPropertyAddressList>	AddressListVector;
217 
218 	AddressListVector							mAddressListVector;
219 
220 };
221 
HasAnyNonEmptyItems()222 inline bool	CAPropertyAddressListVector::HasAnyNonEmptyItems() const
223 {
224 	bool theAnswer = false;
225 	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
226 	{
227 		theAnswer = !theIterator->IsEmpty();
228 	}
229 	return theAnswer;
230 }
231 
HasAnyItemsWithAddress(const AudioObjectPropertyAddress & inAddress)232 inline bool	CAPropertyAddressListVector::HasAnyItemsWithAddress(const AudioObjectPropertyAddress& inAddress) const
233 {
234 	bool theAnswer = false;
235 	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
236 	{
237 		theAnswer = theIterator->HasItem(inAddress);
238 	}
239 	return theAnswer;
240 }
241 
HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress & inAddress)242 inline bool	CAPropertyAddressListVector::HasAnyItemsWithExactAddress(const AudioObjectPropertyAddress& inAddress) const
243 {
244 	bool theAnswer = false;
245 	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !theAnswer && (theIterator != mAddressListVector.end()); ++theIterator)
246 	{
247 		theAnswer = theIterator->HasExactItem(inAddress);
248 	}
249 	return theAnswer;
250 }
251 
GetItemByToken(void * inToken)252 inline const CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByToken(void* inToken) const
253 {
254 	const CAPropertyAddressList* theAnswer = NULL;
255 	bool wasFound = false;
256 	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
257 	{
258 		if(theIterator->GetToken() == inToken)
259 		{
260 			wasFound = true;
261 			theAnswer = &(*theIterator);
262 		}
263 	}
264 	return theAnswer;
265 }
266 
GetItemByToken(void * inToken)267 inline CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByToken(void* inToken)
268 {
269 	CAPropertyAddressList* theAnswer = NULL;
270 	bool wasFound = false;
271 	for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
272 	{
273 		if(theIterator->GetToken() == inToken)
274 		{
275 			wasFound = true;
276 			theAnswer = &(*theIterator);
277 		}
278 	}
279 	return theAnswer;
280 }
281 
GetItemByIntToken(uintptr_t inToken)282 inline const CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken) const
283 {
284 	const CAPropertyAddressList* theAnswer = NULL;
285 	bool wasFound = false;
286 	for(AddressListVector::const_iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
287 	{
288 		if(theIterator->GetIntToken() == inToken)
289 		{
290 			wasFound = true;
291 			theAnswer = &(*theIterator);
292 		}
293 	}
294 	return theAnswer;
295 }
296 
GetItemByIntToken(uintptr_t inToken)297 inline CAPropertyAddressList*	CAPropertyAddressListVector::GetItemByIntToken(uintptr_t inToken)
298 {
299 	CAPropertyAddressList* theAnswer = NULL;
300 	bool wasFound = false;
301 	for(AddressListVector::iterator theIterator = mAddressListVector.begin(); !wasFound && (theIterator != mAddressListVector.end()); ++theIterator)
302 	{
303 		if(theIterator->GetIntToken() == inToken)
304 		{
305 			wasFound = true;
306 			theAnswer = &(*theIterator);
307 		}
308 	}
309 	return theAnswer;
310 }
311 
312 #endif
313