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 "IOAudioSelectorControl.h" 24#include "IOAudioTypes.h" 25#include "IOAudioDefines.h" 26 27#include <libkern/c++/OSString.h> 28#include <libkern/c++/OSArray.h> 29#include <libkern/c++/OSDictionary.h> 30 31#define super IOAudioControl 32 33OSDefineMetaClassAndStructors(IOAudioSelectorControl, IOAudioControl) 34OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 0); 35OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 1); 36OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 2); 37OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 3); // <rdar://8202424> 38 39OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 4); // <rdar://8202424> 40OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 5); 41OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 6); 42OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 7); 43OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 8); 44OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 9); 45OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 10); 46OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 11); 47OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 12); 48OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 13); 49OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 14); 50OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 15); 51 52// New code 53IOAudioSelectorControl *IOAudioSelectorControl::createOutputClockSelector(SInt32 initialValue, 54 UInt32 channelID, 55 UInt32 clockSource, 56 const char *channelName, 57 UInt32 cntrlID) 58{ 59 IOAudioSelectorControl *clockControl; 60 61 if ((clockControl = create (initialValue, 62 channelID, 63 channelName, 64 cntrlID, 65 kIOAudioSelectorControlSubTypeClockSource, 66 kIOAudioControlUsageOutput))) { 67 clockControl->setProperty(kIOAudioSelectorControlClockSourceKey, clockSource); 68 } 69 70 return clockControl; 71} 72 73IOAudioSelectorControl *IOAudioSelectorControl::createInputClockSelector(SInt32 initialValue, 74 UInt32 channelID, 75 UInt32 clockSource, 76 const char *channelName, 77 UInt32 cntrlID) 78{ 79 IOAudioSelectorControl *clockControl; 80 81 if ((clockControl = create (initialValue, 82 channelID, 83 channelName, 84 cntrlID, 85 kIOAudioSelectorControlSubTypeClockSource, 86 kIOAudioControlUsageInput))) { 87 clockControl->setProperty(kIOAudioSelectorControlClockSourceKey, clockSource); 88 } 89 90 return clockControl; 91} 92 93IOAudioSelectorControl *IOAudioSelectorControl::createOutputSelector(SInt32 initialValue, 94 UInt32 channelID, 95 const char *channelName, 96 UInt32 cntrlID) 97{ 98 return create(initialValue, 99 channelID, 100 channelName, 101 cntrlID, 102 kIOAudioSelectorControlSubTypeOutput, 103 kIOAudioControlUsageOutput); 104} 105 106IOReturn IOAudioSelectorControl::removeAvailableSelection(SInt32 selectionValue) 107{ 108 OSCollectionIterator *iterator; 109 OSArray *newSelections; 110 OSArray *oldAvailableSelections; 111 IOReturn result = kIOReturnNotFound; 112 113 assert(availableSelections); 114 115 oldAvailableSelections = availableSelections; 116 newSelections = OSArray::withArray(availableSelections); 117 if (!newSelections) 118 return kIOReturnNoMemory; 119 120 iterator = OSCollectionIterator::withCollection(newSelections); 121 if (iterator) { 122 OSDictionary * selection; 123 UInt32 index; 124 125 index = 0; 126 while ( (selection = (OSDictionary *)iterator->getNextObject()) ) { 127 OSNumber * sValue; 128 129 sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey); 130 131 if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) { 132 // Remove the selected dictionary from the array 133 newSelections->removeObject(index); 134 result = kIOReturnSuccess; 135 break; 136 } 137 index++; 138 } 139 availableSelections = newSelections; 140 setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections); 141 oldAvailableSelections->release(); 142 143 iterator->release(); 144 } 145 146 if (kIOReturnSuccess == result) { 147 sendChangeNotification(kIOAudioControlRangeChangeNotification); 148 } 149 150 return result; 151} 152 153IOReturn IOAudioSelectorControl::replaceAvailableSelection(SInt32 selectionValue, const char *selectionDescription) 154{ 155 IOReturn result = kIOReturnBadArgument; 156 157 if (selectionDescription != NULL) { 158 OSString *selDesc; 159 160 selDesc = OSString::withCString(selectionDescription); 161 if (selDesc) { 162 result = replaceAvailableSelection(selectionValue, selDesc); 163 } else { 164 result = kIOReturnNoMemory; 165 } 166 } 167 168 return result; 169} 170 171IOReturn IOAudioSelectorControl::replaceAvailableSelection(SInt32 selectionValue, OSString *selectionDescription) 172{ 173 OSCollectionIterator *iterator; 174 OSArray *newSelections; 175 OSArray *oldAvailableSelections; 176 IOReturn result = kIOReturnSuccess; 177 178 assert(availableSelections); 179 180 oldAvailableSelections = availableSelections; 181 newSelections = OSArray::withArray(availableSelections); 182 if (!newSelections) 183 return kIOReturnNoMemory; 184 185 iterator = OSCollectionIterator::withCollection(newSelections); 186 if (iterator) { 187 OSDictionary * selection; 188 UInt32 index; 189 190 index = 0; 191 while ( (selection = (OSDictionary *)iterator->getNextObject() )) { 192 OSNumber * sValue; 193 194 sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey); 195 196 if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) { 197 // Replace the selected dictionary in the array 198 newSelections->replaceObject(index, selectionDescription); 199 result = kIOReturnSuccess; 200 break; 201 } 202 index++; 203 } 204 availableSelections = newSelections; 205 setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections); 206 oldAvailableSelections->release(); 207 208 iterator->release(); 209 } 210 211 if (kIOReturnSuccess == result) { 212 sendChangeNotification(kIOAudioControlRangeChangeNotification); 213 } 214 215 return result; 216} 217 218// Original code... 219IOAudioSelectorControl *IOAudioSelectorControl::create(SInt32 initialValue, 220 UInt32 channelID, 221 const char *channelName, 222 UInt32 cntrlID, 223 UInt32 subType, 224 UInt32 usage) 225{ 226 IOAudioSelectorControl *control; 227 228 control = new IOAudioSelectorControl; 229 230 if (control) { 231 if (!control->init(initialValue, 232 channelID, 233 channelName, 234 cntrlID, 235 subType, 236 usage)) { 237 control->release(); 238 control = NULL; 239 } 240 } 241 242 return control; 243} 244 245IOAudioSelectorControl *IOAudioSelectorControl::createInputSelector(SInt32 initialValue, 246 UInt32 channelID, 247 const char *channelName, 248 UInt32 cntrlID) 249{ 250 return create(initialValue, 251 channelID, 252 channelName, 253 cntrlID, 254 kIOAudioSelectorControlSubTypeInput, 255 kIOAudioControlUsageInput); 256} 257 258bool IOAudioSelectorControl::init(SInt32 initialValue, 259 UInt32 channelID, 260 const char *channelName, 261 UInt32 cntrlID, 262 UInt32 subType, 263 UInt32 usage, 264 OSDictionary *properties) 265{ 266 bool result = false; 267 OSNumber *number; 268 269 number = OSNumber::withNumber(initialValue, sizeof(SInt32)*8); 270 271 if (number) { 272 result = super::init(kIOAudioControlTypeSelector, 273 number, 274 channelID, 275 channelName, 276 cntrlID, 277 subType, 278 usage, 279 properties); 280 281 number->release(); 282 } 283 284 if (result) { 285 availableSelections = OSArray::withCapacity(2); 286 setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections); 287 } 288 289 return result; 290} 291 292void IOAudioSelectorControl::free() 293{ 294 if (availableSelections) { 295 availableSelections->release(); 296 availableSelections = NULL; 297 } 298 299 super::free(); 300} 301 302IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, const char *selectionDescription) 303{ 304 IOReturn result = kIOReturnBadArgument; 305 306 if (selectionDescription != NULL) { 307 OSString *selDesc; 308 309 selDesc = OSString::withCString(selectionDescription); 310 if (selDesc) { 311 result = addAvailableSelection(selectionValue, selDesc); 312 } else { 313 result = kIOReturnNoMemory; 314 } 315 } 316 317 return result; 318} 319 320IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, OSString *selectionDescription) 321{ 322 OSArray *newSelections; 323 OSArray *oldAvailableSelections; 324 IOReturn result = kIOReturnSuccess; 325 326 oldAvailableSelections = availableSelections; 327 newSelections = OSArray::withArray(availableSelections); 328 if (!newSelections) 329 return kIOReturnNoMemory; 330 331 if (selectionDescription == NULL) { 332 result = kIOReturnBadArgument; 333 } else { 334 if (valueExists(selectionValue)) { 335 result = kIOReturnError; 336 } else { 337 OSDictionary *newSelection; 338 339 newSelection = OSDictionary::withCapacity(2); 340 341 if (newSelection) { 342 OSNumber *number; 343 344 number = OSNumber::withNumber(selectionValue, sizeof(SInt32)*8); 345 346 if (number) { 347 newSelection->setObject(kIOAudioSelectorControlSelectionValueKey, number); 348 newSelection->setObject(kIOAudioSelectorControlSelectionDescriptionKey, selectionDescription); 349 newSelections->setObject(newSelection); 350 351 number->release(); 352 } else { 353 result = kIOReturnError; 354 } 355 availableSelections = newSelections; 356 setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections); 357 oldAvailableSelections->release(); 358 359 newSelection->release(); 360 } else { 361 result = kIOReturnError; 362 } 363 } 364 } 365 366 if (kIOReturnSuccess == result) { 367 sendChangeNotification(kIOAudioControlRangeChangeNotification); 368 } 369 370 return result; 371} 372 373// <rdar://8202424> 374IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, OSString *selectionDescription, const char* tagName, OSObject* tag) 375{ 376 OSArray *newSelections; 377 OSArray *oldAvailableSelections; 378 IOReturn result = kIOReturnSuccess; 379 380 oldAvailableSelections = availableSelections; 381 newSelections = OSArray::withArray(availableSelections); 382 if (!newSelections) 383 return kIOReturnNoMemory; 384 385 if (selectionDescription == NULL) { 386 result = kIOReturnBadArgument; 387 } else { 388 if (valueExists(selectionValue)) { 389 result = kIOReturnError; 390 } else { 391 OSDictionary *newSelection; 392 393 newSelection = OSDictionary::withCapacity(2); 394 395 if (newSelection) { 396 OSNumber *number; 397 398 number = OSNumber::withNumber(selectionValue, sizeof(SInt32)*8); 399 400 if (number) { 401 newSelection->setObject(kIOAudioSelectorControlSelectionValueKey, number); 402 newSelection->setObject(kIOAudioSelectorControlSelectionDescriptionKey, selectionDescription); 403 newSelections->setObject(newSelection); 404 405 number->release(); 406 } else { 407 result = kIOReturnError; 408 } 409 410 if ( tagName && tag ) { 411 newSelection->setObject(tagName, tag); 412 } 413 414 availableSelections = newSelections; 415 setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections); 416 oldAvailableSelections->release(); 417 418 newSelection->release(); 419 } else { 420 result = kIOReturnError; 421 } 422 } 423 } 424 425 if (kIOReturnSuccess == result) { 426 sendChangeNotification(kIOAudioControlRangeChangeNotification); 427 } 428 429 return result; 430} 431 432bool IOAudioSelectorControl::valueExists(SInt32 selectionValue) 433{ 434 bool found = false; 435 OSCollectionIterator *iterator; 436 437 assert(availableSelections); 438 439 iterator = OSCollectionIterator::withCollection(availableSelections); 440 if (iterator) { 441 OSDictionary *selection; 442 443 while ( (selection = (OSDictionary *)iterator->getNextObject()) ) { 444 OSNumber *sValue; 445 446 sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey); 447 448 if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) { 449 found = true; 450 break; 451 } 452 } 453 454 iterator->release(); 455 } 456 457 return found; 458} 459 460IOReturn IOAudioSelectorControl::validateValue(OSObject *newValue) 461{ 462 IOReturn result = kIOReturnBadArgument; 463 OSNumber *number; 464 465 number = OSDynamicCast(OSNumber, newValue); 466 467 if (number) { 468 result = super::validateValue(newValue); 469 470 if (result == kIOReturnSuccess) { 471 if (valueExists((SInt32)number->unsigned32BitValue())) { 472 result = kIOReturnSuccess; 473 } else { 474 result = kIOReturnNotFound; 475 } 476 } 477 } 478 479 return result; 480} 481 482