1 /*
2      File: CAHALAudioObject.cpp
3  Abstract: CAHALAudioObject.h
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 //==================================================================================================
48 //	Includes
49 //==================================================================================================
50 
51 //	Self Include
52 #include "CAHALAudioObject.h"
53 
54 //	PublicUtility Includes
55 #include "CAAutoDisposer.h"
56 #include "CADebugMacros.h"
57 #include "CAException.h"
58 #include "CAPropertyAddress.h"
59 
60 //==================================================================================================
61 //	CAHALAudioObject
62 //==================================================================================================
63 
CAHALAudioObject(AudioObjectID inObjectID)64 CAHALAudioObject::CAHALAudioObject(AudioObjectID inObjectID)
65 :
66 	mObjectID(inObjectID)
67 {
68 }
69 
~CAHALAudioObject()70 CAHALAudioObject::~CAHALAudioObject()
71 {
72 }
73 
GetObjectID() const74 AudioObjectID	CAHALAudioObject::GetObjectID() const
75 {
76 	return mObjectID;
77 }
78 
SetObjectID(AudioObjectID inObjectID)79 void	CAHALAudioObject::SetObjectID(AudioObjectID inObjectID)
80 {
81 	mObjectID = inObjectID;
82 }
83 
GetClassID() const84 AudioClassID	CAHALAudioObject::GetClassID() const
85 {
86 	//	set up the return value
87 	AudioClassID theAnswer = 0;
88 
89 	//	set up the property address
90 	CAPropertyAddress theAddress(kAudioObjectPropertyClass);
91 
92 	//	make sure the property exists
93 	if(HasProperty(theAddress))
94 	{
95 		UInt32 theSize = sizeof(AudioClassID);
96 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
97 	}
98 
99 	return theAnswer;
100 }
101 
GetOwnerObjectID() const102 AudioObjectID	CAHALAudioObject::GetOwnerObjectID() const
103 {
104 	//	set up the return value
105 	AudioObjectID theAnswer = 0;
106 
107 	//	set up the property address
108 	CAPropertyAddress theAddress(kAudioObjectPropertyOwner);
109 
110 	//	make sure the property exists
111 	if(HasProperty(theAddress))
112 	{
113 		//	get the property data
114 		UInt32 theSize = sizeof(AudioObjectID);
115 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
116 	}
117 
118 	return theAnswer;
119 }
120 
CopyOwningPlugInBundleID() const121 CFStringRef	CAHALAudioObject::CopyOwningPlugInBundleID() const
122 {
123 	//	set up the return value
124 	CFStringRef theAnswer = NULL;
125 
126 	//	set up the property address
127 	CAPropertyAddress theAddress(kAudioObjectPropertyCreator);
128 
129 	//	make sure the property exists
130 	if(HasProperty(theAddress))
131 	{
132 		//	get the property data
133 		UInt32 theSize = sizeof(CFStringRef);
134 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
135 	}
136 
137 	return theAnswer;
138 }
139 
CopyName() const140 CFStringRef	CAHALAudioObject::CopyName() const
141 {
142 	//	set up the return value
143 	CFStringRef theAnswer = NULL;
144 
145 	//	set up the property address
146 	CAPropertyAddress theAddress(kAudioObjectPropertyName);
147 
148 	//	make sure the property exists
149 	if(HasProperty(theAddress))
150 	{
151 		//	get the property data
152 		UInt32 theSize = sizeof(CFStringRef);
153 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
154 	}
155 
156 	return theAnswer;
157 }
158 
CopyManufacturer() const159 CFStringRef	CAHALAudioObject::CopyManufacturer() const
160 {
161 	//	set up the return value
162 	CFStringRef theAnswer = NULL;
163 
164 	//	set up the property address
165 	CAPropertyAddress theAddress(kAudioObjectPropertyManufacturer);
166 
167 	//	make sure the property exists
168 	if(HasProperty(theAddress))
169 	{
170 		//	get the property data
171 		UInt32 theSize = sizeof(CFStringRef);
172 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
173 	}
174 
175 	return theAnswer;
176 }
177 
CopyNameForElement(AudioObjectPropertyScope inScope,AudioObjectPropertyElement inElement) const178 CFStringRef	CAHALAudioObject::CopyNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
179 {
180 	//	set up the return value
181 	CFStringRef theAnswer = NULL;
182 
183 	//	set up the property address
184 	CAPropertyAddress theAddress(kAudioObjectPropertyElementName, inScope, inElement);
185 
186 	//	make sure the property exists
187 	if(HasProperty(theAddress))
188 	{
189 		//	get the property data
190 		UInt32 theSize = sizeof(CFStringRef);
191 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
192 	}
193 
194 	return theAnswer;
195 }
196 
CopyCategoryNameForElement(AudioObjectPropertyScope inScope,AudioObjectPropertyElement inElement) const197 CFStringRef	CAHALAudioObject::CopyCategoryNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
198 {
199 	//	set up the return value
200 	CFStringRef theAnswer = NULL;
201 
202 	//	set up the property address
203 	CAPropertyAddress theAddress(kAudioObjectPropertyElementCategoryName, inScope, inElement);
204 
205 	//	make sure the property exists
206 	if(HasProperty(theAddress))
207 	{
208 		//	get the property data
209 		UInt32 theSize = sizeof(CFStringRef);
210 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
211 	}
212 
213 	return theAnswer;
214 }
215 
CopyNumberNameForElement(AudioObjectPropertyScope inScope,AudioObjectPropertyElement inElement) const216 CFStringRef	CAHALAudioObject::CopyNumberNameForElement(AudioObjectPropertyScope inScope, AudioObjectPropertyElement inElement) const
217 {
218 	//	set up the return value
219 	CFStringRef theAnswer = NULL;
220 
221 	//	set up the property address
222 	CAPropertyAddress theAddress(kAudioObjectPropertyElementNumberName, inScope, inElement);
223 
224 	//	make sure the property exists
225 	if(HasProperty(theAddress))
226 	{
227 		//	get the property data
228 		UInt32 theSize = sizeof(CFStringRef);
229 		GetPropertyData(theAddress, 0, NULL, theSize, &theAnswer);
230 	}
231 
232 	return theAnswer;
233 }
234 
ObjectExists(AudioObjectID inObjectID)235 bool	CAHALAudioObject::ObjectExists(AudioObjectID inObjectID)
236 {
237 	Boolean isSettable;
238 	CAPropertyAddress theAddress(kAudioObjectPropertyClass);
239 	return (inObjectID == 0) || (AudioObjectIsPropertySettable(inObjectID, &theAddress, &isSettable) != 0);
240 }
241 
GetNumberOwnedObjects(AudioClassID inClass) const242 UInt32	CAHALAudioObject::GetNumberOwnedObjects(AudioClassID inClass) const
243 {
244 	//	set up the return value
245 	UInt32 theAnswer = 0;
246 
247 	//	set up the property address
248 	CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
249 
250 	//	figure out the qualifier
251 	UInt32 theQualifierSize = 0;
252 	void* theQualifierData = NULL;
253 	if(inClass != 0)
254 	{
255 		theQualifierSize = sizeof(AudioObjectID);
256 		theQualifierData = &inClass;
257 	}
258 
259 	//	get the property data size
260 	theAnswer = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData);
261 
262 	//	calculate the number of object IDs
263 	theAnswer /= SizeOf32(AudioObjectID);
264 
265 	return theAnswer;
266 }
267 
GetAllOwnedObjects(AudioClassID inClass,UInt32 & ioNumberObjects,AudioObjectID * ioObjectIDs) const268 void	CAHALAudioObject::GetAllOwnedObjects(AudioClassID inClass, UInt32& ioNumberObjects, AudioObjectID* ioObjectIDs) const
269 {
270 	//	set up the property address
271 	CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
272 
273 	//	figure out the qualifier
274 	UInt32 theQualifierSize = 0;
275 	void* theQualifierData = NULL;
276 	if(inClass != 0)
277 	{
278 		theQualifierSize = sizeof(AudioObjectID);
279 		theQualifierData = &inClass;
280 	}
281 
282 	//	get the property data
283 	UInt32 theDataSize = ioNumberObjects * SizeOf32(AudioClassID);
284 	GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, ioObjectIDs);
285 
286 	//	set the number of object IDs being returned
287 	ioNumberObjects = theDataSize / SizeOf32(AudioObjectID);
288 }
289 
GetOwnedObjectByIndex(AudioClassID inClass,UInt32 inIndex)290 AudioObjectID	CAHALAudioObject::GetOwnedObjectByIndex(AudioClassID inClass, UInt32 inIndex)
291 {
292 	//	set up the property address
293 	CAPropertyAddress theAddress(kAudioObjectPropertyOwnedObjects);
294 
295 	//	figure out the qualifier
296 	UInt32 theQualifierSize = 0;
297 	void* theQualifierData = NULL;
298 	if(inClass != 0)
299 	{
300 		theQualifierSize = sizeof(AudioObjectID);
301 		theQualifierData = &inClass;
302 	}
303 
304 	//	figure out how much space to allocate
305 	UInt32 theDataSize = GetPropertyDataSize(theAddress, theQualifierSize, theQualifierData);
306 	UInt32 theNumberObjectIDs = theDataSize / SizeOf32(AudioObjectID);
307 
308 	//	set up the return value
309 	AudioObjectID theAnswer = 0;
310 
311 	//	maker sure the index is in range
312 	if(inIndex < theNumberObjectIDs)
313 	{
314 		//	allocate it
315 		CAAutoArrayDelete<AudioObjectID> theObjectList(theDataSize / sizeof(AudioObjectID));
316 
317 		//	get the property data
318 		GetPropertyData(theAddress, theQualifierSize, theQualifierData, theDataSize, theObjectList);
319 
320 		//	get the return value
321 		theAnswer = theObjectList[inIndex];
322 	}
323 
324 	return theAnswer;
325 }
326 
HasProperty(const AudioObjectPropertyAddress & inAddress) const327 bool	CAHALAudioObject::HasProperty(const AudioObjectPropertyAddress& inAddress) const
328 {
329 	return AudioObjectHasProperty(mObjectID, &inAddress);
330 }
331 
IsPropertySettable(const AudioObjectPropertyAddress & inAddress) const332 bool	CAHALAudioObject::IsPropertySettable(const AudioObjectPropertyAddress& inAddress) const
333 {
334 	Boolean isSettable = false;
335 	OSStatus theError = AudioObjectIsPropertySettable(mObjectID, &inAddress, &isSettable);
336 	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::IsPropertySettable: got an error getting info about a property");
337 	return isSettable != 0;
338 }
339 
GetPropertyDataSize(const AudioObjectPropertyAddress & inAddress,UInt32 inQualifierDataSize,const void * inQualifierData) const340 UInt32	CAHALAudioObject::GetPropertyDataSize(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData) const
341 {
342 	UInt32 theDataSize = 0;
343 	OSStatus theError = AudioObjectGetPropertyDataSize(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &theDataSize);
344 	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyDataSize: got an error getting the property data size");
345 	return theDataSize;
346 }
347 
GetPropertyData(const AudioObjectPropertyAddress & inAddress,UInt32 inQualifierDataSize,const void * inQualifierData,UInt32 & ioDataSize,void * outData) const348 void	CAHALAudioObject::GetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32& ioDataSize, void* outData) const
349 {
350 	OSStatus theError = AudioObjectGetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, &ioDataSize, outData);
351 	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::GetPropertyData: got an error getting the property data");
352 }
353 
SetPropertyData(const AudioObjectPropertyAddress & inAddress,UInt32 inQualifierDataSize,const void * inQualifierData,UInt32 inDataSize,const void * inData)354 void	CAHALAudioObject::SetPropertyData(const AudioObjectPropertyAddress& inAddress, UInt32 inQualifierDataSize, const void* inQualifierData, UInt32 inDataSize, const void* inData)
355 {
356 	OSStatus theError = AudioObjectSetPropertyData(mObjectID, &inAddress, inQualifierDataSize, inQualifierData, inDataSize, inData);
357 	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::SetPropertyData: got an error setting the property data");
358 }
359 
AddPropertyListener(const AudioObjectPropertyAddress & inAddress,AudioObjectPropertyListenerProc inListenerProc,void * inClientData)360 void	CAHALAudioObject::AddPropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
361 {
362 	OSStatus theError = AudioObjectAddPropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
363 	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::AddPropertyListener: got an error adding a property listener");
364 }
365 
RemovePropertyListener(const AudioObjectPropertyAddress & inAddress,AudioObjectPropertyListenerProc inListenerProc,void * inClientData)366 void	CAHALAudioObject::RemovePropertyListener(const AudioObjectPropertyAddress& inAddress, AudioObjectPropertyListenerProc inListenerProc, void* inClientData)
367 {
368 	OSStatus theError = AudioObjectRemovePropertyListener(mObjectID, &inAddress, inListenerProc, inClientData);
369 	ThrowIfError(theError, CAException(theError), "CAHALAudioObject::RemovePropertyListener: got an error removing a property listener");
370 }
371