|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 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: * Copyright (c) 1998 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IOAudioController.cpp ! 26: * ! 27: * HISTORY ! 28: * ! 29: */ ! 30: ! 31: #include <IOKit/assert.h> ! 32: ! 33: #include <IOKit/IOLib.h> ! 34: #include <IOKit/IOKitKeys.h> ! 35: #include <IOKit/IOSyncer.h> ! 36: #include <IOKit/IOWorkLoop.h> ! 37: #include <IOKit/IOCommandQueue.h> ! 38: #include <IOKit/IOTimerEventSource.h> ! 39: #include <IOKit/IOMemoryDescriptor.h> ! 40: #include <IOKit/audio/IOAudioController.h> ! 41: ! 42: #include <libkern/c++/OSSet.h> ! 43: ! 44: const IORegistryPlane * IOAudioController::gIOAudioPlane = NULL; ! 45: const OSSymbol * IOAudioController::gValSym = NULL; ! 46: const OSSymbol * IOAudioController::gTypeSym = NULL; ! 47: const OSSymbol * IOAudioController::gInputsSym = NULL; ! 48: const OSSymbol * IOAudioController::gControlsSym = NULL; ! 49: const OSSymbol * IOAudioController::gJackSym = NULL; ! 50: const OSSymbol * IOAudioController::gSpeakerSym = NULL; ! 51: const OSSymbol * IOAudioController::gHeadphonesSym = NULL; ! 52: const OSSymbol * IOAudioController::gLineOutSym = NULL; ! 53: const OSSymbol * IOAudioController::gMuteSym = NULL; ! 54: const OSSymbol * IOAudioController::gIdSym = NULL; ! 55: const OSSymbol * IOAudioController::gMasterSym = NULL; ! 56: ! 57: #define TIMER_INTS_PER_BUF 4 ! 58: #define MAX_POLL_INTERVAL_SEC 60 ! 59: ! 60: //************************************************************************ ! 61: // Implementation of protocol clas. ! 62: //************************************************************************ ! 63: OSDefineMetaClass( IOAudio, IOService ) ! 64: OSDefineAbstractStructors( IOAudio, IOService ) ! 65: ! 66: //************************************************************************ ! 67: // Begin implementation of IOAudioController class. ! 68: //************************************************************************ ! 69: ! 70: #undef super ! 71: #define super IOAudio ! 72: ! 73: OSDefineMetaClass( IOAudioController, IOAudio ) ! 74: OSDefineAbstractStructors( IOAudioController, IOAudio ) ! 75: ! 76: bool IOAudioController::init(OSDictionary *properties) ! 77: { ! 78: if (!super::init(properties)) { ! 79: return false; ! 80: } ! 81: ! 82: fMasterVolumeComponents = OSSet::withCapacity(1); ! 83: fNumStreamsInUse = 0; ! 84: ! 85: nanoseconds_to_absolutetime((UInt64)(MAX_POLL_INTERVAL_SEC) * (UInt64)NSEC_PER_SEC, &fMaxPollInterval); ! 86: ! 87: return true; ! 88: } ! 89: ! 90: bool IOAudioController::start( IOService *provider ) ! 91: { ! 92: if (!super::start(provider)) ! 93: return false; ! 94: ! 95: fDevice = provider; ! 96: ! 97: return true; ! 98: } ! 99: ! 100: void IOAudioController::execAndSignal(OSObject * obj, void *field0, void *field1, void *field2, void *field3) ! 101: { ! 102: IOAudioController *me = (IOAudioController *)obj; ! 103: IOSyncer *syncer = (IOSyncer *) field0; ! 104: IOAudioCmd cmd = (IOAudioCmd) (int) field1; ! 105: ! 106: me->execCommand(cmd, field2, field3); ! 107: ! 108: if(syncer) ! 109: syncer->signal(); ! 110: } ! 111: ! 112: void IOAudioController::execCommand(IOAudioCmd cmd, void *field2, void *field3) ! 113: { ! 114: switch (cmd) { ! 115: case kConnect: ! 116: getMap((AudioStreamIndex)field2, (IOAudioStreamMap *)field3); ! 117: break; ! 118: ! 119: case kDetach: ! 120: releaseMap((AudioStreamIndex)field2); ! 121: break; ! 122: ! 123: case kSetFlow: ! 124: setFlow((AudioStreamIndex)field2, (bool)field3); ! 125: break; ! 126: ! 127: case kProbeStreams: ! 128: int numStreams, i; ! 129: numStreams = probeStreams(); ! 130: fStreams = OSArray::withCapacity(numStreams); ! 131: if(fStreams) { ! 132: for(i=0; i<numStreams; i++) { ! 133: IOAudioStream *stream; ! 134: stream = createAudioStream(i); ! 135: if(stream) { ! 136: fStreams->setObject(i, stream); ! 137: stream->attach(this); ! 138: stream->registerService(); ! 139: } ! 140: } ! 141: CreateAudioTopology(fQueue); ! 142: } ! 143: // Start the timer event source, if necessary (eg polling Awacs inputs) ! 144: AbsoluteTime pollInterval, wantTick; ! 145: ! 146: pollInterval = fMaxPollInterval; ! 147: calculateTickInterval(&pollInterval); ! 148: if(CMP_ABSOLUTETIME(&pollInterval, &fMaxPollInterval) < 0) { ! 149: clock_get_uptime(&wantTick); ! 150: ADD_ABSOLUTETIME(&wantTick, &pollInterval); ! 151: fNextTick = wantTick; ! 152: fTimer->wakeAtTime(fNextTick); ! 153: fTimerInUse = true; ! 154: fWorkLoop->addEventSource(fTimer); ! 155: } ! 156: ! 157: break; ! 158: ! 159: case kSetVal: ! 160: SetControl((UInt16)field2, (UInt16)field3); ! 161: break; ! 162: ! 163: case kFlush: ! 164: flushStream((AudioStreamIndex)field2, (IOAudioStreamPosition *)field3); ! 165: break; ! 166: ! 167: case kAllocMixBuffer: ! 168: if (*(void **)field3 == NULL) { ! 169: *(void **)field3 = allocateMixBuffer((AudioStreamIndex)field2); ! 170: } ! 171: break; ! 172: ! 173: default: ! 174: IOLog("Unexpected command %d in IOAudioController::execCommand!\n", cmd); ! 175: ! 176: } ! 177: } ! 178: ! 179: void IOAudioController::clockTick(OSObject * obj, IOTimerEventSource *timer) ! 180: { ! 181: ((IOAudioController *)obj)->DoClockTick(timer); ! 182: } ! 183: ! 184: void IOAudioController::DoClockTick(IOTimerEventSource *timer) ! 185: { ! 186: AudioStreamIndex stream; ! 187: AudioStreamIndex end; ! 188: ! 189: if(fStreams) ! 190: end = fStreams->getCount(); ! 191: else ! 192: end = 0; ! 193: ! 194: for(stream = 0; stream < end; stream++) { ! 195: IOAudioStreamStatus *status = getSharedStatus(stream); ! 196: ! 197: if(status && status->fRunning) { ! 198: AbsoluteTime now; ! 199: ! 200: clock_get_uptime(&now); ! 201: ! 202: // Do buffer clearing before potentially removing the buffer! ! 203: if(status->fErases) { ! 204: UInt32 currentBlock; ! 205: ! 206: // Clear buffer behind DMA back to last erase point ! 207: char *buf = (char *)getSampleBuffer(stream); ! 208: char *mixBuf = (char *)getMixBuffer(stream); ! 209: ! 210: currentBlock = status->fCurrentBlock; ! 211: ! 212: if(currentBlock < status->fEraseHeadBlock) { ! 213: if (buf) { ! 214: bzero(buf, currentBlock * status->fBlockSize); ! 215: bzero(buf + (status->fEraseHeadBlock * status->fBlockSize), ! 216: status->fBufSize - (status->fEraseHeadBlock * status->fBlockSize)); ! 217: } ! 218: if (mixBuf) { ! 219: bzero(mixBuf, currentBlock * status->fBlockSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE); ! 220: bzero(mixBuf + (status->fEraseHeadBlock * status->fBlockSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE), ! 221: (status->fBufSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE) - (status->fEraseHeadBlock * status->fBlockSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE)); ! 222: } ! 223: } ! 224: else { ! 225: if (buf) { ! 226: bzero(buf + (status->fEraseHeadBlock * status->fBlockSize), ! 227: (currentBlock - status->fEraseHeadBlock) * status->fBlockSize); ! 228: } ! 229: if (mixBuf) { ! 230: bzero(mixBuf + (status->fEraseHeadBlock * status->fBlockSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE), ! 231: (currentBlock - status->fEraseHeadBlock) * status->fBlockSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE); ! 232: } ! 233: } ! 234: ! 235: status->fEraseHeadBlock = currentBlock; ! 236: } ! 237: if(status->fConnections == 0) { ! 238: UInt32 currentBlock, currentLoopCount; ! 239: ! 240: currentLoopCount = status->fCurrentLoopCount; ! 241: currentBlock = status->fCurrentBlock; ! 242: ! 243: // See if its time to stop (we have completed flushing output buffers) ! 244: if ((currentLoopCount > status->fFlushEnd.fLoopCount) ! 245: || ((currentLoopCount == status->fFlushEnd.fLoopCount) ! 246: && (currentBlock > status->fFlushEnd.fBlock))) { ! 247: AbsoluteTime pollInterval; ! 248: status->fRunning = 0; ! 249: stopStream(stream); ! 250: fNumStreamsInUse--; ! 251: if (fNumStreamsInUse == 0) { ! 252: pollInterval = fMaxPollInterval; ! 253: calculateTickInterval(&pollInterval); ! 254: if(CMP_ABSOLUTETIME(&pollInterval, &fMaxPollInterval) < 0) { ! 255: fWorkLoop->removeEventSource(fTimer); ! 256: fTimerInUse = false; ! 257: } ! 258: } ! 259: } ! 260: } ! 261: } ! 262: } ! 263: ! 264: if(fTimerInUse) { ! 265: fTimer->setTimeout(fTickPeriod); ! 266: } ! 267: } ! 268: ! 269: //------------------------------------------------------------------------ ! 270: /* ! 271: * startWorkLoop() ! 272: * ! 273: * Drivers call this after initializing their hardware ! 274: * We ask the device here how many initial audio channels it has, create appropriate nubs, ! 275: * and then start the work loop running ! 276: */ ! 277: void IOAudioController::startWorkLoop() ! 278: { ! 279: if(NULL == gIOAudioPlane) { ! 280: gIOAudioPlane = IORegistryEntry::makePlane( kIOAudioPlane ); ! 281: } ! 282: ! 283: if(NULL == gValSym) { ! 284: gValSym = OSSymbol::withCString("Val"); ! 285: gInputsSym = OSSymbol::withCString("Inputs"); ! 286: gControlsSym = OSSymbol::withCString("Controls"); ! 287: gJackSym = OSSymbol::withCString("Jack"); ! 288: gSpeakerSym = OSSymbol::withCString("Speaker"); ! 289: gHeadphonesSym = OSSymbol::withCString("Headphones"); ! 290: gLineOutSym = OSSymbol::withCString("LineOut"); ! 291: gTypeSym = OSSymbol::withCString("Type"); ! 292: gMuteSym = OSSymbol::withCString("Mute"); ! 293: gIdSym = OSSymbol::withCString("Id"); ! 294: gMasterSym = OSSymbol::withCString("Master"); ! 295: } ! 296: ! 297: fTimer = IOTimerEventSource::timerEventSource(this, &clockTick); ! 298: fQueue = IOCommandQueue::commandQueue(this, &execAndSignal); ! 299: ! 300: fWorkLoop = createWorkLoop(); ! 301: fWorkLoop->addEventSource(fQueue); ! 302: ! 303: fQueue->enqueueCommand(true, 0, (void *)kProbeStreams, 0); ! 304: ! 305: registerService(); ! 306: } ! 307: ! 308: IOWorkLoop *IOAudioController::getWorkLoop() const ! 309: { ! 310: return fWorkLoop; ! 311: } ! 312: ! 313: IOWorkLoop * IOAudioController::createWorkLoop() ! 314: { ! 315: IOWorkLoop *loop; ! 316: ! 317: loop = new IOWorkLoop(); ! 318: if(loop && !loop->init()) { ! 319: loop->release(); ! 320: loop = NULL; ! 321: } ! 322: return loop; ! 323: } ! 324: ! 325: IOAudioStream *IOAudioController::createAudioStream(AudioStreamIndex index) ! 326: { ! 327: OSDictionary *props = getStreamProperties(index); ! 328: IOAudioStreamImpl *stream; ! 329: SInt32 isOut; ! 330: IOReturn err; ! 331: ! 332: if(!props) ! 333: return NULL; ! 334: ! 335: stream = new IOAudioStreamImpl; ! 336: if(stream) ! 337: stream->initWithPropsIndexQueue(props, index, fQueue); ! 338: ! 339: props->release(); // Finished with this now. ! 340: ! 341: /* ! 342: * Output streams are the start of a sound chain, so put ! 343: * them at the root of the IOAudio plane. ! 344: */ ! 345: err = stream->isOutput(&isOut); ! 346: if(!err && isOut) ! 347: stream->attachToParent(getRegistryRoot(), gIOAudioPlane); ! 348: ! 349: return stream; ! 350: } ! 351: ! 352: IOAudioComponentImpl * ! 353: IOAudioController::buildComponentAndAttach(IORegistryEntry *parent, ! 354: IORegistryEntry *child, const char *serialProps, ! 355: IOCommandQueue *queue) ! 356: { ! 357: OSDictionary *dict; ! 358: OSString *errorString; ! 359: IOAudioComponentImpl * aComp; ! 360: OSNumber *masterVal; ! 361: ! 362: aComp = new IOAudioComponentImpl; ! 363: if(!aComp) ! 364: return NULL; ! 365: ! 366: dict = OSDynamicCast(OSDictionary, OSUnserialize(serialProps, &errorString)); ! 367: if (!dict && errorString) { ! 368: IOLog("%s\n", errorString->getCStringNoCopy()); ! 369: errorString->release(); ! 370: } ! 371: if(!aComp->initWithStuff(this, dict, queue)) { ! 372: aComp->release(); ! 373: return NULL; ! 374: } ! 375: ! 376: if(!parent) ! 377: parent = getRegistryRoot(); ! 378: ! 379: aComp->attachToParent(parent, gIOAudioPlane); ! 380: ! 381: if(child) ! 382: child->attachToParent(aComp, gIOAudioPlane); ! 383: ! 384: masterVal = (OSNumber *)dict->getObject(gMasterSym); ! 385: if ((masterVal != NULL) && (masterVal->unsigned32BitValue() != 0)) { ! 386: fMasterVolumeComponents->setObject(aComp); ! 387: } ! 388: ! 389: return aComp; ! 390: } ! 391: ! 392: void IOAudioController::AttachComponents(IORegistryEntry *parent, ! 393: IORegistryEntry *child) ! 394: { ! 395: child->attachToParent(parent, gIOAudioPlane); ! 396: } ! 397: ! 398: ! 399: void IOAudioController::free() ! 400: { ! 401: if (fMasterVolumeComponents) ! 402: fMasterVolumeComponents->release(); ! 403: if(fWorkLoop) ! 404: fWorkLoop->release(); ! 405: if(fQueue) ! 406: fQueue->release(); ! 407: if(fTimer) ! 408: fTimer->release(); ! 409: if(fStreams) ! 410: fStreams->release(); ! 411: super::free(); ! 412: } ! 413: ! 414: void IOAudioController::calculateTickInterval(AbsoluteTime *tickInterval) ! 415: { ! 416: AudioStreamIndex stream; ! 417: AudioStreamIndex end; ! 418: ! 419: if(fStreams) ! 420: end = fStreams->getCount(); ! 421: else ! 422: end = 0; ! 423: ! 424: for(stream = 0; stream < end; stream++) { ! 425: IOAudioStreamStatus *status = getSharedStatus(stream); ! 426: if(status) { ! 427: AbsoluteTime pollInterval; ! 428: ! 429: nanoseconds_to_absolutetime(((UInt64)NSEC_PER_SEC * (UInt64)status->fBufSize / (UInt64)status->fDataRate / (UInt64)TIMER_INTS_PER_BUF), &pollInterval); ! 430: ! 431: if (CMP_ABSOLUTETIME(&pollInterval, tickInterval) < 0) { ! 432: *tickInterval = pollInterval; ! 433: } ! 434: } ! 435: } ! 436: ! 437: // Save the minimum period ! 438: fTickPeriod = *tickInterval; ! 439: } ! 440: ! 441: /* ! 442: * Map stream data for caller. ! 443: */ ! 444: void IOAudioController::getMap(AudioStreamIndex index, IOAudioStreamMap *map) ! 445: { ! 446: IOAudioStreamStatus * status = getSharedStatus(index); ! 447: ! 448: if(!status) { ! 449: fNumStreamsInUse++; ! 450: status = startStream(index); ! 451: if(status) { ! 452: AbsoluteTime pollInterval, wantTick; ! 453: ! 454: //map->fMixBuffer = (void *)IOMallocAligned(round_page(status->fBufSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE), PAGE_SIZE); ! 455: ! 456: clock_get_uptime(&wantTick); ! 457: if(status->fErases) { ! 458: status->fEraseHeadBlock = 0; ! 459: } ! 460: ! 461: status->fFlushEnd.fBlock = 0; ! 462: status->fFlushEnd.fLoopCount = 0; ! 463: status->fMixBufferInUse = false; ! 464: ! 465: pollInterval = fMaxPollInterval; ! 466: calculateTickInterval(&pollInterval); ! 467: ! 468: ADD_ABSOLUTETIME(&wantTick, &pollInterval); ! 469: ! 470: if(!fTimerInUse || (CMP_ABSOLUTETIME(&wantTick, &fNextTick) < 0)) { ! 471: fNextTick = wantTick; ! 472: fTimer->wakeAtTime(fNextTick); ! 473: } ! 474: if(!fTimerInUse) { ! 475: fTimerInUse = true; ! 476: fWorkLoop->addEventSource(fTimer); ! 477: } ! 478: setFlow(index, true); ! 479: } ! 480: else { ! 481: map->fStatus = NULL; ! 482: map->fSampleBuffer = NULL; ! 483: //map->fMixBuffer = NULL; ! 484: fNumStreamsInUse--; ! 485: return; ! 486: } ! 487: } ! 488: status->fConnections = 1; ! 489: map->fStatus = status; ! 490: map->fSampleBuffer = getSampleBuffer(index); ! 491: } ! 492: ! 493: void IOAudioController::releaseMap(AudioStreamIndex index) ! 494: { ! 495: IOAudioStreamStatus * status = getSharedStatus(index); ! 496: ! 497: if (status) { ! 498: status->fConnections = 0; ! 499: } ! 500: } ! 501: ! 502: void IOAudioController::setFlow(AudioStreamIndex index, bool flowing) ! 503: { ! 504: IOAudioStreamStatus * status = getSharedStatus(index); ! 505: if(status) { ! 506: if(flowing) { ! 507: if(status->fRunning++ == 0) { ! 508: fNumStreamsInUse++; ! 509: resumeStream(index); ! 510: } ! 511: } ! 512: else { ! 513: if(--status->fRunning == 0) { ! 514: pauseStream(index); ! 515: fNumStreamsInUse--; ! 516: } ! 517: } ! 518: } ! 519: } ! 520: ! 521: void IOAudioController::flushStream(AudioStreamIndex index, IOAudioStreamPosition *endingPosition) ! 522: { ! 523: IOAudioStreamStatus *status = getSharedStatus(index); ! 524: ! 525: if (status) { ! 526: if ((endingPosition->fLoopCount > status->fFlushEnd.fLoopCount) || ((endingPosition->fLoopCount == status->fFlushEnd.fLoopCount) && (endingPosition->fBlock > status->fFlushEnd.fBlock))) { ! 527: status->fFlushEnd = *endingPosition; ! 528: } ! 529: } ! 530: } ! 531: ! 532: void *IOAudioController::allocateMixBuffer(AudioStreamIndex index) ! 533: { ! 534: IOAudioStreamStatus * status = getSharedStatus(index); ! 535: void *mixBuffer = NULL; ! 536: ! 537: if(status) { ! 538: mixBuffer = (void *)IOMallocAligned(round_page(status->fBufSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE), PAGE_SIZE); ! 539: bzero (mixBuffer, round_page(status->fBufSize / status->fSampleSize * MIX_BUFFER_SAMPLE_SIZE)); ! 540: status->fMixBufferInUse = true; ! 541: } ! 542: ! 543: return mixBuffer; ! 544: } ! 545: void *IOAudioController::getMixBuffer(AudioStreamIndex index) ! 546: { ! 547: void *mixBuffer = NULL; ! 548: if (fStreams) { ! 549: IOAudioStreamImpl *stream = (IOAudioStreamImpl *)fStreams->getObject(index); ! 550: if (stream) { ! 551: if (stream->getMixBuffer(&mixBuffer) != kIOReturnSuccess) { ! 552: mixBuffer = NULL; ! 553: } ! 554: } ! 555: } ! 556: ! 557: return mixBuffer; ! 558: } ! 559: ! 560: void IOAudioController::setMasterComponentsProperties(OSDictionary *properties) ! 561: { ! 562: if (properties) { ! 563: OSCollectionIterator *iter; ! 564: ! 565: iter = OSCollectionIterator::withCollection(fMasterVolumeComponents); ! 566: if (iter) { ! 567: IOAudioComponent *component; ! 568: ! 569: while ((component = OSDynamicCast(IOAudioComponent, iter->getNextObject())) != NULL) { ! 570: component->setProperties(properties); ! 571: } ! 572: } ! 573: } ! 574: } ! 575: void IOAudioController::setMasterVolumeLeft(UInt16 newMasterVolumeLeft) ! 576: { ! 577: OSDictionary *controlDict; ! 578: OSString *errorString; ! 579: char controlDictString[51]; // strlen(formatString) + 5 (max chars in 16-bit int) + 1 (terminator) ! 580: ! 581: sprintf (controlDictString, "{'Controls'={'VolumeLeft'={'Val'=%d:16;};};};", newMasterVolumeLeft); ! 582: controlDict = OSDynamicCast(OSDictionary, OSUnserialize(controlDictString, &errorString)); ! 583: ! 584: if (controlDict) { ! 585: setMasterComponentsProperties(controlDict); ! 586: controlDict->release(); ! 587: } else if (errorString) { ! 588: IOLog("IOAudioController: %s\n", errorString->getCStringNoCopy()); ! 589: errorString->release(); ! 590: } ! 591: } ! 592: ! 593: void IOAudioController::setMasterVolumeRight(UInt16 newMasterVolumeRight) ! 594: { ! 595: OSDictionary *controlDict; ! 596: OSString *errorString; ! 597: char controlDictString[52]; // strlen(formatString) + 5 (max chars in 16-bit int) + 1 (terminator) ! 598: ! 599: // FIXME - We really should scale to min/max in this control... ! 600: sprintf (controlDictString, "{'Controls'={'VolumeRight'={'Val'=%d:16;};};};", newMasterVolumeRight); ! 601: controlDict = OSDynamicCast(OSDictionary, OSUnserialize(controlDictString, &errorString)); ! 602: ! 603: if (controlDict) { ! 604: setMasterComponentsProperties(controlDict); ! 605: controlDict->release(); ! 606: } else if (errorString) { ! 607: IOLog("IOAudioController: %s\n", errorString->getCStringNoCopy()); ! 608: errorString->release(); ! 609: } ! 610: } ! 611: ! 612: void IOAudioController::setMasterMute(bool newMasterMute) ! 613: { ! 614: OSDictionary *controlDict; ! 615: OSString *errorString; ! 616: char controlDictString[43]; // strlen(formatString) + 1 (single digit) + 1 (terminator) ! 617: ! 618: sprintf (controlDictString, "{'Controls'={'MuteAll'={'Val'=%d:8;};};};", newMasterMute ? 1 : 0); ! 619: controlDict = OSDynamicCast(OSDictionary, OSUnserialize(controlDictString, &errorString)); ! 620: ! 621: if (controlDict) { ! 622: setMasterComponentsProperties(controlDict); ! 623: controlDict->release(); ! 624: } else if (errorString) { ! 625: IOLog("IOAudioController: %s\n", errorString->getCStringNoCopy()); ! 626: errorString->release(); ! 627: } ! 628: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.