1/* 2 * Copyright (c) 1998-2010 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#include "IOAudioLevelControl.h" 24#include "IOAudioTypes.h" 25#include "IOAudioDefines.h" 26#include "IOAudioDebug.h" 27 28#define super IOAudioControl 29 30OSDefineMetaClassAndStructors(IOAudioLevelControl, IOAudioControl) 31 32OSMetaClassDefineReservedUsed(IOAudioLevelControl, 0); 33 34OSMetaClassDefineReservedUnused(IOAudioLevelControl, 1); 35OSMetaClassDefineReservedUnused(IOAudioLevelControl, 2); 36OSMetaClassDefineReservedUnused(IOAudioLevelControl, 3); 37OSMetaClassDefineReservedUnused(IOAudioLevelControl, 4); 38OSMetaClassDefineReservedUnused(IOAudioLevelControl, 5); 39OSMetaClassDefineReservedUnused(IOAudioLevelControl, 6); 40OSMetaClassDefineReservedUnused(IOAudioLevelControl, 7); 41OSMetaClassDefineReservedUnused(IOAudioLevelControl, 8); 42OSMetaClassDefineReservedUnused(IOAudioLevelControl, 9); 43OSMetaClassDefineReservedUnused(IOAudioLevelControl, 10); 44OSMetaClassDefineReservedUnused(IOAudioLevelControl, 11); 45OSMetaClassDefineReservedUnused(IOAudioLevelControl, 12); 46OSMetaClassDefineReservedUnused(IOAudioLevelControl, 13); 47OSMetaClassDefineReservedUnused(IOAudioLevelControl, 14); 48OSMetaClassDefineReservedUnused(IOAudioLevelControl, 15); 49 50// New code added here 51IOAudioLevelControl *IOAudioLevelControl::createPassThruVolumeControl (SInt32 initialValue, 52 SInt32 minValue, 53 SInt32 maxValue, 54 IOFixed minDB, 55 IOFixed maxDB, 56 UInt32 channelID, 57 const char *channelName, 58 UInt32 cntrlID) 59{ 60 return IOAudioLevelControl::create(initialValue, 61 minValue, 62 maxValue, 63 minDB, 64 maxDB, 65 channelID, 66 channelName, 67 cntrlID, 68 kIOAudioLevelControlSubTypeVolume, 69 kIOAudioControlUsagePassThru); 70} 71 72// OSMetaClassDefineReservedUnused(IOAudioLevelControl, 0); 73void IOAudioLevelControl::setLinearScale(bool useLinearScale) 74{ 75 setProperty(kIOAudioLevelControlUseLinearScale, useLinearScale, sizeof(bool)*8); 76} 77 78// Original code... 79IOAudioLevelControl *IOAudioLevelControl::create(SInt32 initialValue, 80 SInt32 minValue, 81 SInt32 maxValue, 82 IOFixed minDB, 83 IOFixed maxDB, 84 UInt32 channelID, 85 const char *channelName, 86 UInt32 cntrlID, 87 UInt32 subType, 88 UInt32 usage) 89{ 90 IOAudioLevelControl *control; 91 92 control = new IOAudioLevelControl; 93 94 if (control) { 95 if (!control->init(initialValue, 96 minValue, 97 maxValue, 98 minDB, 99 maxDB, 100 channelID, 101 channelName, 102 cntrlID, 103 subType, 104 usage)) { 105 control->release(); 106 control = 0; 107 } 108 } 109 110 return control; 111} 112 113IOAudioLevelControl *IOAudioLevelControl::createVolumeControl(SInt32 initialValue, 114 SInt32 minValue, 115 SInt32 maxValue, 116 IOFixed minDB, 117 IOFixed maxDB, 118 UInt32 channelID, 119 const char *channelName, 120 UInt32 cntrlID, 121 UInt32 usage) 122{ 123 return IOAudioLevelControl::create(initialValue, 124 minValue, 125 maxValue, 126 minDB, 127 maxDB, 128 channelID, 129 channelName, 130 cntrlID, 131 kIOAudioLevelControlSubTypeVolume, 132 usage); 133} 134 135bool IOAudioLevelControl::init(SInt32 initialValue, 136 SInt32 minValue, 137 SInt32 maxValue, 138 IOFixed minDB, 139 IOFixed maxDB, 140 UInt32 channelID, 141 const char *channelName, 142 UInt32 cntrlID, 143 UInt32 subType, 144 UInt32 usage, 145 OSDictionary *properties) 146{ 147 bool result = true; 148 OSNumber *number; 149 150 number = OSNumber::withNumber(initialValue, sizeof(SInt32)*8); 151 152 if ((number == NULL) || !super::init(kIOAudioControlTypeLevel, number, channelID, channelName, cntrlID, subType, usage, properties)) { 153 result = false; 154 goto Done; 155 } 156 157 setMinValue(minValue); 158 setMaxValue(maxValue); 159 setMinDB(minDB); 160 setMaxDB(maxDB); 161 162Done: 163 if (number) { 164 number->release(); 165 } 166 167 return result; 168} 169 170void IOAudioLevelControl::free() 171{ 172 if (ranges) { 173 ranges->release(); 174 ranges = NULL; 175 } 176 177 super::free(); 178} 179 180void IOAudioLevelControl::setMinValue(SInt32 newMinValue) 181{ 182 minValue = newMinValue; 183 setProperty(kIOAudioLevelControlMinValueKey, newMinValue, sizeof(SInt32)*8); 184 sendChangeNotification(kIOAudioControlRangeChangeNotification); 185} 186 187SInt32 IOAudioLevelControl::getMinValue() 188{ 189 return minValue; 190} 191 192void IOAudioLevelControl::setMaxValue(SInt32 newMaxValue) 193{ 194 maxValue = newMaxValue; 195 setProperty(kIOAudioLevelControlMaxValueKey, newMaxValue, sizeof(SInt32)*8); 196 sendChangeNotification(kIOAudioControlRangeChangeNotification); 197} 198 199SInt32 IOAudioLevelControl::getMaxValue() 200{ 201 return maxValue; 202} 203 204void IOAudioLevelControl::setMinDB(IOFixed newMinDB) 205{ 206 minDB = newMinDB; 207 setProperty(kIOAudioLevelControlMinDBKey, newMinDB, sizeof(IOFixed)*8); 208 sendChangeNotification(kIOAudioControlRangeChangeNotification); 209} 210 211IOFixed IOAudioLevelControl::getMinDB() 212{ 213 return minDB; 214} 215 216void IOAudioLevelControl::setMaxDB(IOFixed newMaxDB) 217{ 218 setProperty(kIOAudioLevelControlMaxDBKey, newMaxDB, sizeof(IOFixed)*8); 219 sendChangeNotification(kIOAudioControlRangeChangeNotification); 220} 221 222IOFixed IOAudioLevelControl::getMaxDB() 223{ 224 return maxDB; 225} 226 227// Should only be done during init time - this is not thread safe 228IOReturn IOAudioLevelControl::addRange(SInt32 minRangeValue, 229 SInt32 maxRangeValue, 230 IOFixed minRangeDB, 231 IOFixed maxRangeDB) 232{ 233 IOReturn result = kIOReturnSuccess; 234 235 // We should verify the new range doesn't overlap any others here 236 237 if (ranges == NULL) { 238 ranges = OSArray::withCapacity(1); 239 if (ranges) { 240 setProperty(kIOAudioLevelControlRangesKey, ranges); 241 } 242 } 243 244 if (ranges) { 245 OSDictionary *newRange; 246 OSArray *newRanges; 247 OSArray *oldRanges; 248 249 oldRanges = ranges; 250 newRanges = OSArray::withArray(ranges); 251 if (!newRanges) 252 return kIOReturnNoMemory; 253 254 newRange = OSDictionary::withCapacity(4); 255 if (newRange) { 256 OSNumber *number; 257 258 number = OSNumber::withNumber(minRangeValue, sizeof(SInt32)*8); 259 newRange->setObject(kIOAudioLevelControlMinValueKey, number); 260 number->release(); 261 262 number = OSNumber::withNumber(maxRangeValue, sizeof(SInt32)*8); 263 newRange->setObject(kIOAudioLevelControlMaxValueKey, number); 264 number->release(); 265 266 number = OSNumber::withNumber(minRangeDB, sizeof(IOFixed)*8); 267 newRange->setObject(kIOAudioLevelControlMinDBKey, number); 268 number->release(); 269 270 number = OSNumber::withNumber(maxRangeDB, sizeof(IOFixed)*8); 271 newRange->setObject(kIOAudioLevelControlMaxDBKey, number); 272 number->release(); 273 274 newRanges->setObject(newRange); 275 setProperty(kIOAudioLevelControlRangesKey, newRanges); 276 ranges = newRanges; 277 oldRanges->release(); 278 279 newRange->release(); 280 } else { 281 result = kIOReturnError; 282 } 283 } else { 284 result = kIOReturnError; 285 } 286 287 return result; 288} 289 290IOReturn IOAudioLevelControl::addNegativeInfinity(SInt32 negativeInfinityValue) 291{ 292 return addRange(negativeInfinityValue, negativeInfinityValue, kIOAudioLevelControlNegativeInfinity, kIOAudioLevelControlNegativeInfinity); 293} 294 295IOReturn IOAudioLevelControl::validateValue(OSObject *newValue) 296{ 297 IOReturn result = kIOReturnBadArgument; 298 OSNumber *number; 299 300 number = OSDynamicCast(OSNumber, newValue); 301 302 audioDebugIOLog(3, "+ IOAudioLevelControl::validateValue[%p] (%p)\n", this, newValue); 303 304 if (number) { 305 SInt32 newIntValue; 306 307 newIntValue = (SInt32)number->unsigned32BitValue(); 308 309 audioDebugIOLog(3, " IOAudioLevelControl::validateValue[%p] - newIntValue = %ld, min = %ld, max = %ld\n", this, (long int)newIntValue, (long int)minValue, (long int)maxValue); 310 311 if ((newIntValue >= minValue) && (newIntValue <= maxValue)) { 312 result = kIOReturnSuccess; 313 } else { 314 result = kIOReturnError; 315 } 316 } 317 318 audioDebugIOLog(3, "- IOAudioLevelControl::validateValue[%p] (%p) returns 0x%lX\n", this, newValue, (long unsigned int)result ); 319 return result; 320} 321 322 323