1/* 2 * Copyright (c) 1998-2013 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 "IOAudioDebug.h" 24#include "IOAudioStream.h" 25#include "IOAudioEngine.h" 26#include "IOAudioEngineUserClient.h" 27#include "IOAudioControl.h" 28#include "IOAudioTypes.h" 29#include "IOAudioDefines.h" 30 31#include <IOKit/IOLib.h> 32#include <IOKit/IOWorkLoop.h> 33#include <IOKit/IOCommandGate.h> 34 35#include <libkern/c++/OSSymbol.h> 36#include <libkern/c++/OSNumber.h> 37#include <libkern/c++/OSArray.h> 38#include <libkern/c++/OSDictionary.h> 39 40typedef struct IOAudioStreamFormatExtensionDesc { 41 UInt32 version; 42 UInt32 flags; 43 UInt32 framesPerPacket; 44 UInt32 bytesPerPacket; 45} IOAudioStreamFormatExtensionDesc; 46 47typedef struct IOAudioStreamFormatDesc { 48 IOAudioStreamFormat format; 49 IOAudioSampleRate minimumSampleRate; 50 IOAudioSampleRate maximumSampleRate; 51 IOAudioStream::AudioIOFunction *ioFunctionList; 52 UInt32 numIOFunctions; 53 IOAudioStreamFormatExtensionDesc formatExtension; 54} IOAudioStreamFormatDesc; 55 56#define super IOService 57OSDefineMetaClassAndStructors(IOAudioStream, IOService) 58 59OSMetaClassDefineReservedUsed(IOAudioStream, 0); 60OSMetaClassDefineReservedUsed(IOAudioStream, 1); 61OSMetaClassDefineReservedUsed(IOAudioStream, 2); 62OSMetaClassDefineReservedUsed(IOAudioStream, 3); 63OSMetaClassDefineReservedUsed(IOAudioStream, 4); 64OSMetaClassDefineReservedUsed(IOAudioStream, 5); 65OSMetaClassDefineReservedUsed(IOAudioStream, 6); 66OSMetaClassDefineReservedUsed(IOAudioStream, 7); 67OSMetaClassDefineReservedUsed(IOAudioStream, 8); 68OSMetaClassDefineReservedUsed(IOAudioStream, 9); 69OSMetaClassDefineReservedUsed(IOAudioStream, 10); 70OSMetaClassDefineReservedUsed(IOAudioStream, 11); 71 72OSMetaClassDefineReservedUnused(IOAudioStream, 12); 73OSMetaClassDefineReservedUnused(IOAudioStream, 13); 74OSMetaClassDefineReservedUnused(IOAudioStream, 14); 75OSMetaClassDefineReservedUnused(IOAudioStream, 15); 76OSMetaClassDefineReservedUnused(IOAudioStream, 16); 77OSMetaClassDefineReservedUnused(IOAudioStream, 17); 78OSMetaClassDefineReservedUnused(IOAudioStream, 18); 79OSMetaClassDefineReservedUnused(IOAudioStream, 19); 80OSMetaClassDefineReservedUnused(IOAudioStream, 20); 81OSMetaClassDefineReservedUnused(IOAudioStream, 21); 82OSMetaClassDefineReservedUnused(IOAudioStream, 22); 83OSMetaClassDefineReservedUnused(IOAudioStream, 23); 84OSMetaClassDefineReservedUnused(IOAudioStream, 24); 85OSMetaClassDefineReservedUnused(IOAudioStream, 25); 86OSMetaClassDefineReservedUnused(IOAudioStream, 26); 87OSMetaClassDefineReservedUnused(IOAudioStream, 27); 88OSMetaClassDefineReservedUnused(IOAudioStream, 28); 89OSMetaClassDefineReservedUnused(IOAudioStream, 29); 90OSMetaClassDefineReservedUnused(IOAudioStream, 30); 91OSMetaClassDefineReservedUnused(IOAudioStream, 31); 92OSMetaClassDefineReservedUnused(IOAudioStream, 32); 93OSMetaClassDefineReservedUnused(IOAudioStream, 33); 94OSMetaClassDefineReservedUnused(IOAudioStream, 34); 95OSMetaClassDefineReservedUnused(IOAudioStream, 35); 96OSMetaClassDefineReservedUnused(IOAudioStream, 36); 97OSMetaClassDefineReservedUnused(IOAudioStream, 37); 98OSMetaClassDefineReservedUnused(IOAudioStream, 38); 99OSMetaClassDefineReservedUnused(IOAudioStream, 39); 100OSMetaClassDefineReservedUnused(IOAudioStream, 40); 101OSMetaClassDefineReservedUnused(IOAudioStream, 41); 102OSMetaClassDefineReservedUnused(IOAudioStream, 42); 103OSMetaClassDefineReservedUnused(IOAudioStream, 43); 104OSMetaClassDefineReservedUnused(IOAudioStream, 44); 105OSMetaClassDefineReservedUnused(IOAudioStream, 45); 106OSMetaClassDefineReservedUnused(IOAudioStream, 46); 107OSMetaClassDefineReservedUnused(IOAudioStream, 47); 108 109// New code added here: 110 111#define CMPSAMPLERATE(left, right) ((left.whole < right->whole) ? -1 : (left.whole == right->whole) ? (left.fraction < right->fraction) ? -1 : 0 : 1) 112 113// <rdar://problem/5994776> Amount of frames allowed to go over the pseudo mix buffer size. We use the source buffer as a mix buffer in encoded format mode. 114// But we can't clip an arbitrary amount of data. We need to limit it to what the size of the source buffer is. The problem seems to 115// be that the source buffer size is hidden by some VBR change. The true size of the source buffer is saved off an then readded after we can use it. 116// So through imperical testing it looks like the source buffer size is 4 times the IOBufferSize. We set it to 3 times to be safe. 117 118#define kMixBufferMaxSize ( 2043 ) // Limit to 2 pages but there is 16 bytes taken out of the sample buffer for VBR stuff 119 120// <rdar://problem/10305944> function to log streaming errors safely. On production builds it will increment error counters. For Debug builds it will still log via kprintf 121void IOAudioStream::safeLogError(int error , long unsigned int arg1 , long unsigned int arg2 , long unsigned int arg3 , long unsigned int arg4 , void * arg5, void *arg6) 122{ 123 if (reserved) 124 { 125 switch (error) 126 { 127 case kErrorLogClipMoreThanOneBufferAhead: 128 //arg1 = clippedPosition.fLoopCount, 129 //arg2 = clippedPosition.fSampleFrame, 130 //arg3 = clientBufferListStart->mixedPosition.fLoopCount, 131 //arg4 = clientBufferListStart->mixedPosition.fSampleFrame 132 133 reserved->mStreamErrorCounts[kErrorLogClipMoreThanOneBufferAhead]++; 134 reserved->mStreamErrorCountsUpdated = true; 135 audioDebugIOLog(1,"+-IOAudioStream[%p]:: clipIfNecessary() - Error: attempting to clip to a position more than one buffer ahead of last clip position (%lx,%lx)->(%lx,%lx).\n", this, arg1, arg2, arg3, arg4); 136 break; 137 case kErrorLogClipMoreThanOneBufferAheadPart2: 138 //arg1 = clippedPosition.fLoopCount, 139 //arg2 = clippedPosition.fSampleFrame, 140 reserved->mStreamErrorCounts[kErrorLogClipMoreThanOneBufferAheadPart2]++; 141 reserved->mStreamErrorCountsUpdated = true; 142 143 audioDebugIOLog(1,"+-IOAudioStream[%p]::safeLogError clipIfNecessary() - adjusting clipped position to (%lx,%lx)\n", this, arg1 , arg2); 144 break; 145 case kErrorLogClipPositionIsOff: 146 //arg1 = clientBufferListStart->numSampleFrames 147 //arg2 = audioEngine->getNumSampleFramesPerBuffer() 148 //arg3 = clippedPosition.fSampleFrame 149 reserved->mStreamErrorCounts[kErrorLogClipPositionIsOff]++; 150 reserved->mStreamErrorCountsUpdated = true; 151 152 audioDebugIOLog (1,"+-IOAudioStream[%p]:: clipIfNecessary() - clip position is off %ld < %ld - %ld \n",this, arg1 , arg2, arg3); 153 break; 154 case kErrorLogAlreadyClipped: 155 //arg1 = clippedPosition.fLoopCount 156 //arg2 = clippedPosition.fSampleFrame 157 //arg3 = clientBufferListStart->mixedPosition.fLoopCount 158 //arg4 = clientBufferListStart->mixedPosition.fSampleFrame 159 160 reserved->mStreamErrorCounts[kErrorLogAlreadyClipped]++; 161 reserved->mStreamErrorCountsUpdated = true; 162 audioDebugIOLog(1,"+-IOAudioStream[%p]::safeLogError clipIfNecessary() - Error: already clipped to a position (0x%lx,0x%lx) past data to be clipped (0x%lx, 0x%lx) - data ignored.\n", this, arg1 , arg2 ,arg3 ,arg4); 163 break; 164 case kErrorLogClipBuffersAreNULL: 165 //arg1 = firstSampleFrame 166 //arg2 = numSampleFrames 167 //arg3 = 0 168 //arg4 = 0 169 //arg5 = mixBuffer 170 //arg6 = sampleBuffer 171 172 reserved->mStreamErrorCounts[kErrorLogClipBuffersAreNULL]++; 173 reserved->mStreamErrorCountsUpdated = true; 174 audioDebugIOLog(1,"+-IOAudioStream[%p]::safeLogError clipOutputSamples(0x%lx, 0x%lx) - Internal Error: mixBuffer = %p - sampleBuffer = %p\n", this ,arg1, arg2, arg5 , arg6); 175 break; 176 case kErrorLogClipReturnsAnError: 177 //arg1 = firstSampleFrame 178 //arg2 = numSampleFrames 179 //arg3 = result 180 181 reserved->mStreamErrorCounts[kErrorLogClipReturnsAnError]++; 182 reserved->mStreamErrorCountsUpdated = true; 183 audioDebugIOLog(1,"+-IOAudioStream[%p]::safeLogError clipOutputSamples(0x%lx, 0x%lx) - clipping function returned error: 0x%lx\n", this, arg1 , arg2 , arg3); 184 break; 185 case kErrorLogDumpCounters: 186 audioDebugIOLog(1,"+-IOAudioStream[%p]::safeLogError kErrorLogDumpCounters mStreamErrorCountsUpdated=%d\n", this,reserved->mStreamErrorCountsUpdated); 187 188 if ( reserved->mStreamErrorCounts[kErrorLogClipMoreThanOneBufferAhead] ) 189 { 190 IOLog("IOAudioStream[%p]::clipIfNecessary() - Error: counted %u clip more than one buffer ahead errors.\n", this, reserved->mStreamErrorCounts[kErrorLogClipMoreThanOneBufferAhead] ); 191 reserved->mStreamErrorCounts[kErrorLogClipMoreThanOneBufferAhead] = 0; 192 } 193 194 //if ( reserved->mStreamErrorCounts[kErrorLogClipMoreThanOneBufferAheadPart2] ) 195 // Do not need to log this error as it is redundant with the first part 196 197 if ( reserved->mStreamErrorCounts[kErrorLogClipPositionIsOff] ) 198 { 199 IOLog("IOAudioStream[%p]::clipIfNecessary() - Error: counted %u clip position is off errors.\n", this, reserved->mStreamErrorCounts[kErrorLogClipPositionIsOff] ); 200 reserved->mStreamErrorCounts[kErrorLogClipPositionIsOff] = 0; 201 } 202 203 if ( reserved->mStreamErrorCounts[kErrorLogAlreadyClipped] ) 204 { 205 IOLog("IOAudioStream[%p]::clipIfNecessary() - Error: counted %u already clipped errors.\n", this, reserved->mStreamErrorCounts[kErrorLogAlreadyClipped] ); 206 reserved->mStreamErrorCounts[kErrorLogAlreadyClipped] = 0; 207 } 208 209 if ( reserved->mStreamErrorCounts[kErrorLogClipBuffersAreNULL] ) 210 { 211 IOLog("IOAudioStream[%p]::clipIfNecessary() - Error: counted %u clip buffers are NULL errors.\n", this, reserved->mStreamErrorCounts[kErrorLogClipBuffersAreNULL] ); 212 reserved->mStreamErrorCounts[kErrorLogClipBuffersAreNULL] = 0; 213 } 214 215 if ( reserved->mStreamErrorCounts[kErrorLogClipReturnsAnError] ) 216 { 217 IOLog("IOAudioStream[%p]::clipIfNecessary() - Error: counted %u clip returns an error conditions.\n", this, reserved->mStreamErrorCounts[kErrorLogClipReturnsAnError] ); 218 reserved->mStreamErrorCounts[kErrorLogClipReturnsAnError] = 0; 219 } 220 221 break; 222 default: 223 224 break; 225 } 226 } 227 228 return; 229} 230 231bool IOAudioStream::validateFormat(IOAudioStreamFormat *streamFormat, IOAudioStreamFormatExtension *formatExtension, IOAudioStreamFormatDesc *formatDesc, const IOAudioSampleRate *sampleRate) 232{ 233 bool foundFormat = false; 234 235 audioDebugIOLog(3, "+ IOAudioStream[%p]::validateFormat(%p, %p, %p)\n", this, streamFormat, formatExtension, formatDesc); 236 237 238 if (streamFormat && availableFormats && (numAvailableFormats > 0) && sampleRate) { 239 UInt32 formatIndex; 240 241 for (formatIndex = 0; formatIndex < numAvailableFormats; formatIndex++) { 242 audioDebugIOLog(3, " %ld: streamFormat->fNumChannels = %ld\n", (long int)availableFormats[formatIndex].format.fNumChannels, (long int)streamFormat->fNumChannels); 243 audioDebugIOLog(3, " 0x%lx: streamFormat->fSampleFormat = 0x%lx\n", (long unsigned int)availableFormats[formatIndex].format.fSampleFormat, (long unsigned int)streamFormat->fSampleFormat); 244 audioDebugIOLog(3, " 0x%lx: streamFormat->fNumericRepresentation = 0x%lx\n", (long unsigned int)availableFormats[formatIndex].format.fNumericRepresentation, (long unsigned int)streamFormat->fNumericRepresentation); 245 audioDebugIOLog(3, " %d: streamFormat->fBitDepth = %d\n", availableFormats[formatIndex].format.fBitDepth, streamFormat->fBitDepth); 246 audioDebugIOLog(3, " %d: streamFormat->fBitWidth = %d\n", availableFormats[formatIndex].format.fBitWidth, streamFormat->fBitWidth); 247 audioDebugIOLog(3, " %d: streamFormat->fAlignment = %d\n", availableFormats[formatIndex].format.fAlignment, streamFormat->fAlignment); 248 audioDebugIOLog(3, " %d: streamFormat->fByteOrder = %d\n", availableFormats[formatIndex].format.fByteOrder, streamFormat->fByteOrder); 249 if ((availableFormats[formatIndex].format.fNumChannels == streamFormat->fNumChannels) 250 && (availableFormats[formatIndex].format.fSampleFormat == streamFormat->fSampleFormat) 251 && (availableFormats[formatIndex].format.fNumericRepresentation == streamFormat->fNumericRepresentation) 252 && (availableFormats[formatIndex].format.fBitDepth == streamFormat->fBitDepth) 253 && (availableFormats[formatIndex].format.fBitWidth == streamFormat->fBitWidth) 254 && (availableFormats[formatIndex].format.fAlignment == streamFormat->fAlignment) 255 && (availableFormats[formatIndex].format.fByteOrder == streamFormat->fByteOrder) 256 && (availableFormats[formatIndex].format.fIsMixable == streamFormat->fIsMixable)) { 257 258 bool passSRCheck = true; 259 if (0 != sampleRate->whole) { 260 if ((CMPSAMPLERATE (availableFormats[formatIndex].minimumSampleRate, sampleRate) > 0) || (CMPSAMPLERATE (availableFormats[formatIndex].maximumSampleRate, sampleRate) < 0)) { 261 passSRCheck = false; 262 } 263 } 264 if (passSRCheck) { 265 // <rdar://10957396> Only update the tag if required 266 if ( streamFormat->fDriverTag != availableFormats[formatIndex].format.fDriverTag ) { 267 streamFormat->fDriverTag = availableFormats[formatIndex].format.fDriverTag; 268 } 269 270 // streamFormat->fIsMixable = availableFormats[formatIndex].format.fIsMixable; 271 if (formatDesc) { 272 memcpy(formatDesc, &availableFormats[formatIndex], sizeof(IOAudioStreamFormatDesc)); 273 } 274 foundFormat = true; 275 break; 276 } 277 } 278 } 279 } 280 281 audioDebugIOLog(3, "- IOAudioStream[%p]::validateFormat(%p, %p, %p) returns %d\n", this, streamFormat, formatExtension, formatDesc, foundFormat ); 282 return foundFormat; 283} 284 285const IOAudioStreamFormatExtension *IOAudioStream::getFormatExtension() 286{ 287 assert(reserved); 288 return &reserved->streamFormatExtension; 289} 290 291IOReturn IOAudioStream::setFormat(const IOAudioStreamFormat *streamFormat, const IOAudioStreamFormatExtension *formatExtension, bool callDriver) 292{ 293 IOReturn result = kIOReturnSuccess; 294 OSDictionary *formatDict = NULL; 295 IOAudioStreamFormatExtension validFormatExtension; 296 297 if (streamFormat) { 298 if (!formatExtension) { 299 IOAudioStreamFormatDesc formatDesc; 300 validateFormat((IOAudioStreamFormat *)streamFormat, NULL, &formatDesc); 301 memcpy (&validFormatExtension, &formatDesc.formatExtension, sizeof (validFormatExtension)); 302 } else { 303 validFormatExtension = *formatExtension; 304 } 305 if ( (formatDict = createDictionaryFromFormat(streamFormat, &validFormatExtension)) ) { 306 result = setFormat(streamFormat, &validFormatExtension, formatDict, callDriver); 307 formatDict->release(); 308 } else { 309 result = kIOReturnError; 310 } 311 } else { 312 result = kIOReturnBadArgument; 313 } 314 315 return result; 316} 317 318// <rdar://8121989> Restructured for single point of entry and single point of exit so that 319// the indentifier post processing tool can properly insert scope when post processing a log file 320// obtained via fwkpfv. 321 322IOReturn IOAudioStream::setFormat(const IOAudioStreamFormat *streamFormat, const IOAudioStreamFormatExtension *formatExtension, OSDictionary *formatDict, bool callDriver) 323{ 324 IOReturn result = kIOReturnSuccess; 325 IOAudioStreamFormat validFormat; 326 IOAudioStreamFormatDesc formatDesc; 327 IOAudioStreamFormatExtension validFormatExtension; 328 const IOAudioSampleRate *requestedSampleRate = NULL; 329 OSDictionary *sampleRateDict; 330 331 audioDebugIOLog(3, "+ IOAudioStream[%p]::setFormat(%p, %p)\n", this, streamFormat, formatDict); 332 333 if (!streamFormat || !formatDict) 334 { 335 result = kIOReturnBadArgument; 336 } 337 else 338 { 339 #ifdef DEBUG 340 setProperty("IOAudioStreamPendingFormat", formatDict); 341 #endif 342 343 validFormat = *streamFormat; 344 if (NULL != formatExtension) { 345 validFormatExtension = *formatExtension; 346 } else { 347 validFormatExtension.fVersion = kFormatExtensionCurrentVersion; 348 validFormatExtension.fFlags = 0; 349 validFormatExtension.fFramesPerPacket = 1; 350 validFormatExtension.fBytesPerPacket = streamFormat->fNumChannels * (streamFormat->fBitWidth / 8); 351 } 352 353 sampleRateDict = OSDynamicCast(OSDictionary, formatDict->getObject(kIOAudioSampleRateKey)); 354 if (sampleRateDict) { 355 requestedSampleRate = IOAudioEngine::createSampleRateFromDictionary(sampleRateDict); 356 } else { 357 requestedSampleRate = audioEngine->getSampleRate(); 358 } 359 360 if (validateFormat(&validFormat, &validFormatExtension, &formatDesc, requestedSampleRate)) { 361 // OSDictionary *sampleRateDict; 362 IOAudioSampleRate *newSampleRate = NULL; 363 OSSet *userClientsToLock; 364 365 sampleRateDict = OSDynamicCast(OSDictionary, formatDict->getObject(kIOAudioSampleRateKey)); 366 if (sampleRateDict) { 367 const IOAudioSampleRate *currentSampleRate; 368 369 newSampleRate = IOAudioEngine::createSampleRateFromDictionary(sampleRateDict); 370 currentSampleRate = audioEngine->getSampleRate(); 371 if (newSampleRate && (newSampleRate->whole == currentSampleRate->whole) && (newSampleRate->fraction == currentSampleRate->fraction)) { 372 newSampleRate = NULL; 373 } 374 } 375 376 // In order to avoid deadlocks, we need to ensure we hold all of the user client locks 377 // before making calls while holding our IO lock. Everything works fine as long 378 // as the order of the locks is workLoop -> user client -> stream. 379 // Any other order is sure to cause trouble. 380 381 // Because we pause the engine while doing the format change, the user clients will be removed 382 // from our list before we complete. Therefore, we must make a copy of the list to allow 383 // all of the clients to be unlocked when we are done. 384 userClientsToLock = OSSet::withCapacity(numClients); 385 if (userClientsToLock) { 386 OSCollectionIterator *clientIterator; 387 IOAudioClientBuffer *clientBuf; 388 IOAudioEngineUserClient *userClient; 389 390 lockStreamForIO(); // <rdar://13186726> 391 392 clientBuf = userClientList; 393 while (clientBuf) { 394 assert(clientBuf->userClient); 395 396 userClientsToLock->setObject(clientBuf->userClient); 397 clientBuf = clientBuf->nextClient; 398 } 399 400 unlockStreamForIO(); // <rdar://13186726> 401 402 clientIterator = OSCollectionIterator::withCollection(userClientsToLock); 403 if (!clientIterator) { 404 userClientsToLock->release(); 405 result = kIOReturnNoMemory; 406 goto Done; 407 } 408 409 while ( (userClient = (IOAudioEngineUserClient *)clientIterator->getNextObject()) ) { 410 userClient->lockBuffers(); 411 } 412 413 clientIterator->release(); 414 415 lockStreamForIO(); 416 417 audioEngine->pauseAudioEngine(); 418 419 if (callDriver) { 420 result = audioEngine->performFormatChange(this, &validFormat, &validFormatExtension, newSampleRate); 421 if ( result == kIOReturnUnsupported ) 422 { 423 result = audioEngine->performFormatChange(this, &validFormat, newSampleRate); 424 } 425 } 426 427 if (result == kIOReturnSuccess) { 428 OSDictionary *newFormatDict; 429 430 if (formatDesc.ioFunctionList && (formatDesc.numIOFunctions > 0)) { 431 setIOFunctionList(formatDesc.ioFunctionList, formatDesc.numIOFunctions); 432 } 433 434 newFormatDict = createDictionaryFromFormat(&validFormat, &validFormatExtension); 435 if (newFormatDict) { 436 UInt32 oldNumChannels; 437 438 if (mixBuffer != NULL) { 439 // If we have a mix buffer and the new format is not mixable, free the mix buffer 440 if (!validFormat.fIsMixable) { 441 setMixBuffer(NULL, 0); 442 } else if (streamAllocatedMixBuffer && (format.fNumChannels != validFormat.fNumChannels)) { // We need to reallocate the mix buffer 443 UInt32 newMixBufSize; 444 445 assert(audioEngine); 446 newMixBufSize = validFormat.fNumChannels * kIOAudioEngineDefaultMixBufferSampleSize * audioEngine->numSampleFramesPerBuffer; 447 448 if (newMixBufSize > 0) { 449 void *newMixBuf = IOMallocAligned(newMixBufSize, 32); 450 if (newMixBuf) { 451 setMixBuffer(newMixBuf, newMixBufSize); 452 streamAllocatedMixBuffer = true; 453 } 454 } 455 } 456 } 457 458 oldNumChannels = format.fNumChannels; 459 460 format = validFormat; 461 setProperty(kIOAudioStreamFormatKey, newFormatDict); 462 newFormatDict->release(); 463 464 if (format.fNumChannels != oldNumChannels) { 465 audioEngine->updateChannelNumbers(); 466 } 467 468 if (newSampleRate) { 469 audioEngine->setSampleRate(newSampleRate); 470 } 471 } else { 472 result = kIOReturnError; 473 } 474 } else { 475 if ( kIOReturnNotReady != result ) { // <rdar://8094567> 476 IOLog("IOAudioStream<%p>::setFormat(0x%p, 0x%p) - audio engine unable to change format\n", this, streamFormat, formatDict); 477 } 478 } 479 480 if (result == kIOReturnSuccess) { 481 audioEngine->sendFormatChangeNotification(this); 482 } 483 484 audioEngine->resumeAudioEngine(); 485 486 unlockStreamForIO(); 487 488 // Unlock all of the user clients we originally locked 489 assert(userClientsToLock); 490 clientIterator = OSCollectionIterator::withCollection(userClientsToLock); 491 if (clientIterator) { 492 while ( (userClient = (IOAudioEngineUserClient *)clientIterator->getNextObject()) ) { 493 userClient->unlockBuffers(); 494 } 495 clientIterator->release(); 496 } else { 497 // Uh oh... we're in trouble now! 498 // We have to unlock the clients, but we can't get an iterator on the collection. 499 // All existing clients will now hang trying to play audio 500 result = kIOReturnNoMemory; 501 } 502 503 userClientsToLock->release(); 504 } else { 505 result = kIOReturnNoMemory; 506 } 507 } else { 508 IOLog("IOAudioStream<0x%p>::setFormat(0x%p, 0x%p) - invalid format.\n", this, streamFormat, formatDict); 509 result = kIOReturnBadArgument; 510 } 511 } 512 513Done: 514 515 audioDebugIOLog(3, "IOAudioStream[%p]::setFormat(%p, %p) returns 0x%lx", this, streamFormat, formatDict, (long unsigned int)result); 516 517 return result; 518} 519 520void IOAudioStream::addAvailableFormat(const IOAudioStreamFormat *streamFormat, const IOAudioStreamFormatExtension *formatExtension, const IOAudioSampleRate *minRate, const IOAudioSampleRate *maxRate, const AudioIOFunction *ioFunctionList, UInt32 numFunctions) 521{ 522 assert(availableFormatDictionaries); 523 524 if (streamFormat && minRate && maxRate) { 525 IOAudioStreamFormatDesc *newAvailableFormatList; 526 IOAudioStreamFormatExtension localFormatExtension; 527 528 newAvailableFormatList = (IOAudioStreamFormatDesc *)IOMallocAligned((numAvailableFormats+1) * sizeof(IOAudioStreamFormatDesc), sizeof (IOAudioStreamFormatDesc *)); 529 if (newAvailableFormatList) { 530 if (availableFormats && (numAvailableFormats > 0)) { 531 memcpy(newAvailableFormatList, availableFormats, numAvailableFormats * sizeof(IOAudioStreamFormatDesc)); 532 } 533 newAvailableFormatList[numAvailableFormats].format = *streamFormat; 534 newAvailableFormatList[numAvailableFormats].minimumSampleRate = *minRate; 535 newAvailableFormatList[numAvailableFormats].maximumSampleRate = *maxRate; 536 if (formatExtension) { 537 localFormatExtension = *formatExtension; 538 newAvailableFormatList[numAvailableFormats].formatExtension.flags = formatExtension->fFlags; 539 newAvailableFormatList[numAvailableFormats].formatExtension.framesPerPacket = formatExtension->fFramesPerPacket; 540 newAvailableFormatList[numAvailableFormats].formatExtension.bytesPerPacket = formatExtension->fBytesPerPacket; 541 } else { 542 newAvailableFormatList[numAvailableFormats].formatExtension.flags = localFormatExtension.fFlags = 0; 543 newAvailableFormatList[numAvailableFormats].formatExtension.framesPerPacket = localFormatExtension.fFramesPerPacket = 1; 544 newAvailableFormatList[numAvailableFormats].formatExtension.bytesPerPacket = localFormatExtension.fBytesPerPacket = streamFormat->fNumChannels * (streamFormat->fBitWidth / 8); 545 } 546 547 if (ioFunctionList && (numFunctions > 0)) { 548 newAvailableFormatList[numAvailableFormats].ioFunctionList = (AudioIOFunction *)IOMallocAligned(numFunctions * sizeof(AudioIOFunction), sizeof (AudioIOFunction *)); 549 newAvailableFormatList[numAvailableFormats].numIOFunctions = numFunctions; 550 memcpy(newAvailableFormatList[numAvailableFormats].ioFunctionList, ioFunctionList, numFunctions * sizeof(AudioIOFunction)); 551 } else { 552 newAvailableFormatList[numAvailableFormats].ioFunctionList = NULL; 553 newAvailableFormatList[numAvailableFormats].numIOFunctions = 0; 554 } 555 556 IOFreeAligned(availableFormats, numAvailableFormats * sizeof(IOAudioStreamFormatDesc)); 557 availableFormats = newAvailableFormatList; 558 numAvailableFormats++; 559 } 560 561 OSDictionary *formatDict = createDictionaryFromFormat(streamFormat, &localFormatExtension); 562 if (formatDict) { 563 OSDictionary *sampleRateDict; 564 565 sampleRateDict = IOAudioEngine::createDictionaryFromSampleRate(minRate); 566 if (sampleRateDict) { 567 formatDict->setObject(gMinimumSampleRateKey, sampleRateDict); 568 sampleRateDict->release(); 569 570 sampleRateDict = IOAudioEngine::createDictionaryFromSampleRate(maxRate); 571 if (sampleRateDict) { 572 OSArray *newAvailableFormats; 573 OSArray *oldAvailableFormats; 574 575 oldAvailableFormats = availableFormatDictionaries; 576 newAvailableFormats = OSDynamicCast(OSArray, availableFormatDictionaries->copyCollection()); // copyCollection() does a deep copy 577 578 if (newAvailableFormats) { 579 formatDict->setObject(gMaximumSampleRateKey, sampleRateDict); 580 newAvailableFormats->setObject(formatDict); 581 availableFormatDictionaries = newAvailableFormats; 582 setProperty(kIOAudioStreamAvailableFormatsKey, availableFormatDictionaries); 583 oldAvailableFormats->release(); 584 if (streamFormat->fNumChannels > maxNumChannels) { 585 maxNumChannels = streamFormat->fNumChannels; 586 } 587 } 588 589 sampleRateDict->release(); 590 } 591 } 592 formatDict->release(); 593 } 594 } 595} 596 597void IOAudioStream::addAvailableFormat(const IOAudioStreamFormat *streamFormat, const IOAudioStreamFormatExtension *formatExtension, const IOAudioSampleRate *minRate, const IOAudioSampleRate *maxRate, AudioIOFunction ioFunction) 598{ 599 addAvailableFormat(streamFormat, formatExtension, minRate, maxRate, &ioFunction, 1); 600} 601 602bool IOAudioStream::validateFormat(IOAudioStreamFormat *streamFormat, IOAudioStreamFormatExtension *formatExtension, IOAudioStreamFormatDesc *formatDesc) 603{ 604 return validateFormat(streamFormat, formatExtension, formatDesc, audioEngine->getSampleRate()); 605} 606 607void IOAudioStream::setTerminalType(const UInt32 terminalType) 608{ 609 if (terminalType) { 610 setProperty(kIOAudioStreamTerminalTypeKey, terminalType, 32); 611 } 612} 613 614IOReturn IOAudioStream::mixOutputSamples(const void *sourceBuf, void *mixBuf, UInt32 firstSampleFrame, UInt32 numSampleFrames, const IOAudioStreamFormat *streamFormat, IOAudioStream *audioStream) 615{ 616 bcopy (sourceBuf, (float *)mixBuf + (firstSampleFrame * streamFormat->fNumChannels), numSampleFrames * sizeof (float) * streamFormat->fNumChannels); 617 618 return kIOReturnSuccess; 619} 620 621void IOAudioStream::setSampleLatency(UInt32 numSamples) 622{ 623 audioDebugIOLog(3, "+-IOAudioStream[%p]::setSampleLatency(0x%lx)\n", this, (long unsigned int)numSamples); 624 setProperty(kIOAudioStreamSampleLatencyKey, numSamples, sizeof(UInt32)*8); 625} 626 627UInt32 IOAudioStream::getNumSampleFramesRead() 628{ 629 assert(reserved); 630 audioDebugIOLog(4, "+-IOAudioStream[%p]::getNumSampleFramesRead() returns %ld\n", this, (long unsigned int)reserved->mSampleFramesReadByEngine); 631 return reserved->mSampleFramesReadByEngine; 632} 633 634void IOAudioStream::setDefaultNumSampleFramesRead(UInt32 inDefaultNumFramesRead) 635{ 636 assert(reserved); 637 audioDebugIOLog(4, "+-IOAudioStream[%p]::setDefaultNumSampleFramesRead(%ld)\n", this, (long unsigned int)inDefaultNumFramesRead); 638 reserved->mSampleFramesReadByEngine = inDefaultNumFramesRead; 639} 640 641// Original code from here on: 642const OSSymbol *IOAudioStream::gDirectionKey = NULL; 643const OSSymbol *IOAudioStream::gNumChannelsKey = NULL; 644const OSSymbol *IOAudioStream::gSampleFormatKey = NULL; 645const OSSymbol *IOAudioStream::gNumericRepresentationKey = NULL; 646const OSSymbol *IOAudioStream::gBitDepthKey = NULL; 647const OSSymbol *IOAudioStream::gBitWidthKey = NULL; 648const OSSymbol *IOAudioStream::gAlignmentKey = NULL; 649const OSSymbol *IOAudioStream::gByteOrderKey = NULL; 650const OSSymbol *IOAudioStream::gIsMixableKey = NULL; 651const OSSymbol *IOAudioStream::gDriverTagKey = NULL; 652const OSSymbol *IOAudioStream::gMinimumSampleRateKey = NULL; 653const OSSymbol *IOAudioStream::gMaximumSampleRateKey = NULL; 654 655void IOAudioStream::initKeys() 656{ 657 if (!gNumChannelsKey) { 658 gNumChannelsKey = OSSymbol::withCString(kIOAudioStreamNumChannelsKey); 659 gSampleFormatKey = OSSymbol::withCString(kIOAudioStreamSampleFormatKey); 660 gNumericRepresentationKey = OSSymbol::withCString(kIOAudioStreamNumericRepresentationKey); 661 gBitDepthKey = OSSymbol::withCString(kIOAudioStreamBitDepthKey); 662 gBitWidthKey = OSSymbol::withCString(kIOAudioStreamBitWidthKey); 663 gAlignmentKey = OSSymbol::withCString(kIOAudioStreamAlignmentKey); 664 gByteOrderKey = OSSymbol::withCString(kIOAudioStreamByteOrderKey); 665 gIsMixableKey = OSSymbol::withCString(kIOAudioStreamIsMixableKey); 666 gDriverTagKey = OSSymbol::withCString(kIOAudioStreamDriverTagKey); 667 668 gDirectionKey = OSSymbol::withCString(kIOAudioStreamDirectionKey); 669 670 gMinimumSampleRateKey = OSSymbol::withCString(kIOAudioStreamMinimumSampleRateKey); 671 gMaximumSampleRateKey = OSSymbol::withCString(kIOAudioStreamMaximumSampleRateKey); 672 } 673} 674 675OSDictionary *IOAudioStream::createDictionaryFromFormat(const IOAudioStreamFormat *streamFormat, const IOAudioStreamFormatExtension *formatExtension, OSDictionary *formatDict) 676{ 677 OSDictionary *newDict = NULL; 678 679 if (streamFormat) { 680 if (formatDict) { 681 newDict = formatDict; 682 } else { 683 newDict = OSDictionary::withCapacity(7); 684 } 685 686 if (newDict) { 687 OSNumber *num; 688 689 if (!gNumChannelsKey) { 690 initKeys(); 691 } 692 693 num = OSNumber::withNumber(streamFormat->fNumChannels, 32); 694 newDict->setObject(gNumChannelsKey, num); 695 num->release(); 696 697 num = OSNumber::withNumber(streamFormat->fSampleFormat, 32); 698 newDict->setObject(gSampleFormatKey, num); 699 num->release(); 700 701 num = OSNumber::withNumber(streamFormat->fNumericRepresentation, 32); 702 newDict->setObject(gNumericRepresentationKey, num); 703 num->release(); 704 705 num = OSNumber::withNumber(streamFormat->fBitDepth, 8); 706 newDict->setObject(gBitDepthKey, num); 707 num->release(); 708 709 num = OSNumber::withNumber(streamFormat->fBitWidth, 8); 710 newDict->setObject(gBitWidthKey, num); 711 num->release(); 712 713 num = OSNumber::withNumber(streamFormat->fAlignment, 8); 714 newDict->setObject(gAlignmentKey, num); 715 num->release(); 716 717 num = OSNumber::withNumber(streamFormat->fByteOrder, 8); 718 newDict->setObject(gByteOrderKey, num); 719 num->release(); 720 721 num = OSNumber::withNumber(streamFormat->fIsMixable, 8); 722 newDict->setObject(gIsMixableKey, num); 723 num->release(); 724 725 num = OSNumber::withNumber(streamFormat->fDriverTag, 32); 726 newDict->setObject(gDriverTagKey, num); 727 num->release(); 728 729 if (formatExtension && formatExtension->fVersion >= kFormatExtensionCurrentVersion) { 730 num = OSNumber::withNumber(formatExtension->fFlags, 32); 731 newDict->setObject(kIOAudioStreamFormatFlagsKey, num); 732 num->release(); 733 734 num = OSNumber::withNumber(formatExtension->fFramesPerPacket, 32); 735 newDict->setObject(kIOAudioStreamFramesPerPacketKey, num); 736 num->release(); 737 738 num = OSNumber::withNumber(formatExtension->fBytesPerPacket, 32); 739 newDict->setObject(kIOAudioStreamBytesPerPacketKey, num); 740 num->release(); 741 } 742 } 743 } 744 745 746 return newDict; 747} 748 749IOAudioStreamFormat *IOAudioStream::createFormatFromDictionary(const OSDictionary *formatDict, IOAudioStreamFormat *streamFormat, IOAudioStreamFormatExtension *formatExtension) 750{ 751 IOAudioStreamFormat *format = NULL; 752 static IOAudioStreamFormat staticFormat; 753 754 if (formatDict) { 755 if (streamFormat) { 756 format = streamFormat; 757 } else { 758 format = &staticFormat; 759 } 760 761 if (format) { 762 OSNumber *num; 763 764 if (!gNumChannelsKey) { 765 initKeys(); 766 } 767 768 bzero(format, sizeof(IOAudioStreamFormat)); 769 770 num = OSDynamicCast(OSNumber, formatDict->getObject(gNumChannelsKey)); 771 if (num) { 772 format->fNumChannels = num->unsigned32BitValue(); 773 } 774 775 num = OSDynamicCast(OSNumber, formatDict->getObject(gSampleFormatKey)); 776 if (num) { 777 format->fSampleFormat = num->unsigned32BitValue(); 778 } 779 780 num = OSDynamicCast(OSNumber, formatDict->getObject(gNumericRepresentationKey)); 781 if (num) { 782 format->fNumericRepresentation = num->unsigned32BitValue(); 783 } 784 785 num = OSDynamicCast(OSNumber, formatDict->getObject(gBitDepthKey)); 786 if (num) { 787 format->fBitDepth = num->unsigned8BitValue(); 788 } 789 790 num = OSDynamicCast(OSNumber, formatDict->getObject(gBitWidthKey)); 791 if (num) { 792 format->fBitWidth = num->unsigned8BitValue(); 793 } 794 795 num = OSDynamicCast(OSNumber, formatDict->getObject(gAlignmentKey)); 796 if (num) { 797 format->fAlignment = num->unsigned8BitValue(); 798 } 799 800 num = OSDynamicCast(OSNumber, formatDict->getObject(gByteOrderKey)); 801 if (num) { 802 format->fByteOrder = num->unsigned8BitValue(); 803 } 804 805 num = OSDynamicCast(OSNumber, formatDict->getObject(gIsMixableKey)); 806 if (num) { 807 format->fIsMixable = num->unsigned8BitValue(); 808 } 809 810 num = OSDynamicCast(OSNumber, formatDict->getObject(gDriverTagKey)); 811 if (num) { 812 format->fDriverTag = num->unsigned32BitValue(); 813 } 814 815 if (formatExtension) { 816 formatExtension->fVersion = kFormatExtensionCurrentVersion; 817 818 num = OSDynamicCast(OSNumber, formatDict->getObject(kIOAudioStreamFormatFlagsKey)); 819 if (num) { 820 formatExtension->fFlags = num->unsigned32BitValue(); 821 } 822 823 num = OSDynamicCast(OSNumber, formatDict->getObject(kIOAudioStreamFramesPerPacketKey)); 824 if (num) { 825 formatExtension->fFramesPerPacket = num->unsigned32BitValue(); 826 } 827 828 num = OSDynamicCast(OSNumber, formatDict->getObject(kIOAudioStreamBytesPerPacketKey)); 829 if (num) { 830 formatExtension->fBytesPerPacket = num->unsigned32BitValue(); 831 } 832 833 } 834 } 835 } 836 837 return format; 838} 839 840 841bool IOAudioStream::initWithAudioEngine(IOAudioEngine *engine, IOAudioStreamDirection dir, UInt32 startChannelID, const char *streamDescription, OSDictionary *properties) 842{ 843 UInt32 streamID; 844 845 if (!gNumChannelsKey) { 846 initKeys(); 847 } 848 849 if (!engine) { 850 return false; 851 } 852 853 if (!super::init(properties)) { 854 return false; 855 } 856 857 audioEngine = engine; 858 859 reserved = (ExpansionData *)IOMalloc (sizeof(struct ExpansionData)); 860 if (!reserved) { 861 return false; 862 } 863 864 // <rdar://problem/10305944> make sure error counters are zero 865 bzero( reserved , sizeof(struct ExpansionData)); 866 867 workLoop = audioEngine->getWorkLoop(); 868 if (!workLoop) { 869 return false; 870 } 871 872 workLoop->retain(); 873 874 commandGate = IOCommandGate::commandGate(this); 875 if (!commandGate) { 876 return false; 877 } 878 879 streamIOLock = IORecursiveLockAlloc(); 880 if (!streamIOLock) { 881 return false; 882 } 883 884 setDirection(dir); 885 886 startingChannelID = startChannelID; 887 setProperty(kIOAudioStreamStartingChannelIDKey, startingChannelID, sizeof(UInt32)*8); 888 889 maxNumChannels = 0; 890 891 if (streamDescription) { 892 setProperty(kIOAudioStreamDescriptionKey, streamDescription); 893 } 894 895 availableFormatDictionaries = OSArray::withCapacity(1); 896 if (!availableFormatDictionaries) { 897 return false; 898 } 899 setProperty(kIOAudioStreamAvailableFormatsKey, availableFormatDictionaries); 900 901 // This needs to change to passing up a token rather than the "this" pointer. 902 streamID = engine->getNextStreamID (this); 903 setProperty(kIOAudioStreamIDKey, streamID, sizeof(UInt32)*8); 904// setProperty(kIOAudioStreamIDKey, (UInt32)this, sizeof(UInt32)*8); 905 906 streamAvailable = true; 907 setProperty(kIOAudioStreamAvailableKey, (UInt8)1, sizeof(UInt8)*8); 908 909 numClients = 0; 910 updateNumClients(); 911 912 resetClipInfo(); 913 914 clientBufferListStart = NULL; 915 clientBufferListEnd = NULL; 916 917 userClientList = NULL; 918 919 audioIOFunctions = NULL; 920 numIOFunctions = false; 921 922 streamAllocatedMixBuffer = false; 923 924 workLoop->addEventSource(commandGate); 925 926 return true; 927} 928 929void IOAudioStream::free() 930{ 931 if (availableFormatDictionaries) { 932 availableFormatDictionaries->release(); 933 availableFormatDictionaries = NULL; 934 } 935 936 if (mixBuffer && streamAllocatedMixBuffer) { 937 IOFreeAligned(mixBuffer, mixBufferSize); 938 mixBuffer = NULL; 939 mixBufferSize = 0; 940 } 941 942 if (defaultAudioControls) { 943 removeDefaultAudioControls(); 944 defaultAudioControls->release(); 945 defaultAudioControls = NULL; 946 } 947 948 if (commandGate) { 949 if (workLoop) { 950 workLoop->removeEventSource(commandGate); 951 } 952 953 commandGate->release(); 954 commandGate = NULL; 955 } 956 957 if (workLoop) { 958 workLoop->release(); 959 workLoop = NULL; 960 } 961 962 if (streamIOLock) { 963 IORecursiveLockFree(streamIOLock); 964 streamIOLock = NULL; 965 } 966 967 if (audioIOFunctions && (numIOFunctions > 0)) { 968 IOFreeAligned(audioIOFunctions, numIOFunctions * sizeof(AudioIOFunction)); 969 audioIOFunctions = NULL; 970 numIOFunctions = 0; 971 } 972 973 if (availableFormats && (numAvailableFormats > 0)) { 974 UInt32 formatNum; 975 976 for (formatNum = 0; formatNum < numAvailableFormats; formatNum++) { 977 if (availableFormats[formatNum].ioFunctionList && (availableFormats[formatNum].numIOFunctions > 0)) { 978 IOFreeAligned(availableFormats[formatNum].ioFunctionList, availableFormats[formatNum].numIOFunctions * sizeof(AudioIOFunction)); 979 } 980 } 981 982 IOFreeAligned(availableFormats, numAvailableFormats * sizeof(IOAudioStreamFormatDesc)); 983 availableFormats = NULL; 984 numAvailableFormats = 0; 985 } 986 987 if (reserved) { 988 IOFree (reserved, sizeof(struct ExpansionData)); 989 } 990 991 super::free(); 992} 993 994void IOAudioStream::stop(IOService *provider) 995{ 996 if (commandGate) { 997 if (workLoop) { 998 workLoop->removeEventSource(commandGate); 999 } 1000 1001 commandGate->release(); 1002 commandGate = NULL; 1003 } 1004 1005 super::stop(provider); 1006} 1007 1008IOWorkLoop *IOAudioStream::getWorkLoop() const 1009{ 1010 return workLoop; 1011} 1012 1013IOReturn IOAudioStream::setProperties(OSObject *properties) 1014{ 1015 OSDictionary *props; 1016 IOReturn result = kIOReturnSuccess; 1017 1018 audioDebugIOLog(3, "+ IOAudioStream[%p]::setProperties(%p)\n", this, properties); 1019 1020 if (properties && (props = OSDynamicCast(OSDictionary, properties))) { 1021 OSCollectionIterator *iterator; 1022 OSObject *iteratorKey; 1023 1024 iterator = OSCollectionIterator::withCollection(props); 1025 if (iterator) { 1026 while ( (iteratorKey = iterator->getNextObject()) ) { 1027 OSSymbol *key; 1028 1029 key = OSDynamicCast(OSSymbol, iteratorKey); 1030 if (key && key->isEqualTo(kIOAudioStreamFormatKey)) { 1031 OSDictionary *formatDict = OSDynamicCast(OSDictionary, props->getObject(key)); 1032 if (formatDict) { 1033 assert(workLoop); // <rdar://8568040,8691669> 1034 result = workLoop->runAction(_setFormatAction, this, formatDict); // <rdar://8568040,8691669> 1035 } 1036 } 1037 } 1038 iterator->release(); 1039 } else { 1040 result = kIOReturnError; 1041 } 1042 } else { 1043 result = kIOReturnBadArgument; 1044 } 1045 1046 audioDebugIOLog(3, "- IOAudioStream[%p]::setProperties(%p) returns 0x%lX\n", this, properties, (long unsigned int)result ); 1047 return result; 1048} 1049 1050void IOAudioStream::setDirection(IOAudioStreamDirection dir) 1051{ 1052 direction = dir; 1053 setProperty(kIOAudioStreamDirectionKey, direction, 8); 1054} 1055 1056IOAudioStreamDirection IOAudioStream::getDirection() 1057{ 1058 return direction; 1059} 1060 1061void IOAudioStream::setSampleBuffer(void *buffer, UInt32 size) 1062{ 1063 lockStreamForIO(); 1064 1065 sampleBuffer = buffer; 1066 1067 if (sampleBuffer) { 1068 sampleBufferSize = size; 1069 bzero(sampleBuffer, sampleBufferSize); 1070 } else { 1071 sampleBufferSize = 0; 1072 } 1073 1074 unlockStreamForIO(); 1075} 1076 1077void *IOAudioStream::getSampleBuffer() 1078{ 1079 return sampleBuffer; 1080} 1081 1082UInt32 IOAudioStream::getSampleBufferSize() 1083{ 1084 return sampleBufferSize; 1085} 1086 1087void IOAudioStream::setMixBuffer(void *buffer, UInt32 size) 1088{ 1089 lockStreamForIO(); 1090 1091 if (mixBuffer && streamAllocatedMixBuffer) { 1092 IOFreeAligned(mixBuffer, mixBufferSize); 1093 mixBuffer = NULL; 1094 mixBufferSize = 0; 1095 streamAllocatedMixBuffer = false; 1096 } 1097 1098 mixBuffer = buffer; 1099 1100 if (mixBuffer) { 1101 mixBufferSize = size; 1102 bzero(mixBuffer, mixBufferSize); 1103 } else { 1104 mixBufferSize = 0; 1105 } 1106 1107 unlockStreamForIO(); 1108} 1109 1110void *IOAudioStream::getMixBuffer() 1111{ 1112 return mixBuffer; 1113} 1114 1115UInt32 IOAudioStream::getMixBufferSize() 1116{ 1117 return mixBufferSize; 1118} 1119 1120void IOAudioStream::numSampleFramesPerBufferChanged() 1121{ 1122 if (mixBuffer && streamAllocatedMixBuffer) { 1123 setMixBuffer(NULL, 0); 1124 } 1125} 1126 1127void IOAudioStream::clearSampleBuffer() 1128{ 1129 if (sampleBuffer && (sampleBufferSize > 0)) { 1130 bzero(sampleBuffer, sampleBufferSize); 1131 } 1132 1133 if (mixBuffer && (mixBufferSize > 0)) { 1134 bzero(mixBuffer, mixBufferSize); 1135 } 1136} 1137 1138void IOAudioStream::setIOFunction(AudioIOFunction ioFunction) 1139{ 1140 setIOFunctionList(&ioFunction, 1); 1141} 1142 1143void IOAudioStream::setIOFunctionList(const AudioIOFunction *ioFunctionList, UInt32 numFunctions) 1144{ 1145 lockStreamForIO(); 1146 1147 if (audioIOFunctions && (numIOFunctions > 0)) { 1148 IOFreeAligned(audioIOFunctions, numIOFunctions * sizeof(AudioIOFunction)); 1149 audioIOFunctions = NULL; 1150 numIOFunctions = 0; 1151 } 1152 1153 if (ioFunctionList && (numFunctions != 0)) { 1154 audioIOFunctions = (AudioIOFunction *)IOMallocAligned(numFunctions * sizeof(AudioIOFunction), sizeof (AudioIOFunction *)); 1155 if (audioIOFunctions) { 1156 memcpy(audioIOFunctions, ioFunctionList, numFunctions * sizeof(AudioIOFunction)); 1157 numIOFunctions = numFunctions; 1158 } 1159 } 1160 1161 unlockStreamForIO(); 1162} 1163 1164const IOAudioStreamFormat *IOAudioStream::getFormat() 1165{ 1166 return &format; 1167} 1168 1169// <rdar://8568040,8691669> 1170IOReturn IOAudioStream::_setFormatAction(OSObject *target, void *arg0, void *arg1, void *arg2, void *arg3) 1171{ 1172 IOReturn result = kIOReturnBadArgument; 1173 1174 if (target) { 1175 IOAudioStream *stream = OSDynamicCast(IOAudioStream, target); 1176 if (stream) { 1177 if (stream->commandGate) { 1178 result = stream->commandGate->runAction(setFormatAction, arg0, arg1, arg2, arg3); 1179 } else { 1180 result = kIOReturnError; 1181 } 1182 } 1183 } 1184 1185 return result; 1186} 1187 1188IOReturn IOAudioStream::setFormatAction(OSObject *owner, void *arg1, void *arg2, void *arg3, void *arg4) 1189{ 1190 IOReturn result = kIOReturnBadArgument; 1191 1192 if (owner) { 1193 IOAudioStream *audioStream = OSDynamicCast(IOAudioStream, owner); 1194 if (audioStream) { 1195 result = audioStream->setFormat((OSDictionary *)arg1); 1196 } 1197 } 1198 1199 return result; 1200} 1201 1202IOReturn IOAudioStream::setFormat(const IOAudioStreamFormat *streamFormat, bool callDriver) 1203{ 1204 return setFormat(streamFormat, (IOAudioStreamFormatExtension *)NULL, callDriver); 1205} 1206 1207IOReturn IOAudioStream::setFormat(OSDictionary *formatDict) 1208{ 1209 IOReturn result = kIOReturnSuccess; 1210 1211 if (formatDict) { 1212 IOAudioStreamFormat streamFormat; 1213 IOAudioStreamFormatExtension formatExtension; 1214 if (createFormatFromDictionary(formatDict, &streamFormat, &formatExtension)) { 1215 result = setFormat(&streamFormat, &formatExtension, formatDict); 1216 } else { 1217 result = kIOReturnBadArgument; 1218 } 1219 } else { 1220 result = kIOReturnBadArgument; 1221 } 1222 1223 return result; 1224} 1225 1226IOReturn IOAudioStream::setFormat(const IOAudioStreamFormat *streamFormat, OSDictionary *formatDict, bool callDriver) 1227{ 1228 return setFormat(streamFormat, NULL, formatDict, callDriver); 1229} 1230 1231IOReturn IOAudioStream::hardwareFormatChanged(const IOAudioStreamFormat *streamFormat) 1232{ 1233 assert(reserved); 1234 return setFormat(streamFormat, &reserved->streamFormatExtension, false); 1235} 1236 1237void IOAudioStream::addAvailableFormat(const IOAudioStreamFormat *streamFormat, const IOAudioSampleRate *minRate, const IOAudioSampleRate *maxRate, AudioIOFunction ioFunction) 1238{ 1239 addAvailableFormat(streamFormat, NULL, minRate, maxRate, &ioFunction, 1); 1240} 1241 1242void IOAudioStream::addAvailableFormat(const IOAudioStreamFormat *streamFormat, const IOAudioSampleRate *minRate, const IOAudioSampleRate *maxRate, const AudioIOFunction *ioFunctionList, UInt32 numFunctions) 1243{ 1244 addAvailableFormat(streamFormat, NULL, minRate, maxRate, ioFunctionList, numFunctions); 1245} 1246 1247void IOAudioStream::clearAvailableFormats() 1248{ 1249 OSArray* oldAvailableFormats; 1250 OSArray* clearedAvailableFormats; 1251 1252 assert(availableFormatDictionaries); 1253 1254 oldAvailableFormats = availableFormatDictionaries; 1255 1256 clearedAvailableFormats = OSArray::withCapacity(1); 1257 if (!clearedAvailableFormats) { 1258 return; 1259 } 1260 availableFormatDictionaries = clearedAvailableFormats; 1261 setProperty(kIOAudioStreamAvailableFormatsKey, availableFormatDictionaries); 1262 1263 oldAvailableFormats->release(); 1264 1265 // <rdar://9059646> Clean up the available formats array. 1266 if (availableFormats && (numAvailableFormats > 0)) { 1267 IOFreeAligned(availableFormats, numAvailableFormats * sizeof(IOAudioStreamFormatDesc)); 1268 } 1269 availableFormats = NULL; 1270 numAvailableFormats = 0; 1271} 1272 1273bool IOAudioStream::validateFormat(IOAudioStreamFormat *streamFormat, IOAudioStreamFormatDesc *formatDesc) 1274{ 1275 return validateFormat(streamFormat, NULL, formatDesc); 1276} 1277 1278UInt32 IOAudioStream::getStartingChannelID() 1279{ 1280 return startingChannelID; 1281} 1282 1283UInt32 IOAudioStream::getMaxNumChannels() 1284{ 1285 return maxNumChannels; 1286} 1287 1288void IOAudioStream::setStartingChannelNumber(UInt32 channelNumber) 1289{ 1290 setProperty(kIOAudioStreamStartingChannelNumberKey, channelNumber, sizeof(UInt32)*8); 1291} 1292 1293void IOAudioStream::updateNumClients() 1294{ 1295 setProperty(kIOAudioStreamNumClientsKey, numClients, sizeof(UInt32)*8); 1296} 1297 1298IOReturn IOAudioStream::addClient(IOAudioClientBuffer *clientBuffer) 1299{ 1300 IOReturn result = kIOReturnBadArgument; 1301 1302 audioDebugIOLog(3, "+ IOAudioStream[%p]::addClient(%p)\n", this, clientBuffer); 1303 1304 if (clientBuffer) { 1305 assert(clientBuffer->audioStream == this); 1306 1307 lockStreamForIO(); 1308 1309 // <rdar://11731381> Make sure this buffer is not in the list 1310 bool bufferInList = false; 1311 if ((clientBuffer->nextClip == NULL) && (clientBuffer->previousClip == NULL) && (clientBuffer != clientBufferListStart) && (clientBuffer->nextClient == NULL) && (clientBuffer != userClientList)) { 1312 1313 // <rdar://11731381> Make sure that the clientBuffer is not at the end of the list. 1314 IOAudioClientBuffer *tmpClientBuffer = userClientList; 1315 while (tmpClientBuffer && (tmpClientBuffer != clientBuffer)) { 1316 tmpClientBuffer = tmpClientBuffer->nextClient; 1317 } 1318 if (tmpClientBuffer) { 1319 audioDebugIOLog(3, " clientBuffer %p is already in the list.\n", tmpClientBuffer); 1320 bufferInList = true; 1321 } 1322 } 1323 else { 1324 audioDebugIOLog(3, " unexpected clientBuffer values (%p, %p, %p, %p, %p, %p)\n", clientBuffer->nextClip, clientBuffer->previousClip, clientBuffer, clientBufferListStart, clientBuffer->nextClient, userClientList ); 1325 bufferInList = true; 1326 } 1327 1328 if (!bufferInList) { // <rdar://11731381> 1329 1330 // It's OK to allow a new client if this is a mixable format 1331 // or if its not mixable but we don't have any clients 1332 // or if we are an input stream 1333 if (format.fIsMixable || (numClients == 0) || (getDirection() == kIOAudioStreamDirectionInput)) { 1334 numClients++; 1335 updateNumClients(); 1336 1337 clientBuffer->nextClient = userClientList; 1338 userClientList = clientBuffer; 1339 1340 if (getDirection() == kIOAudioStreamDirectionOutput) { 1341 1342 clientBuffer->mixedPosition.fLoopCount = 0; 1343 clientBuffer->mixedPosition.fSampleFrame = 0; 1344 1345 clientBuffer->previousClip = NULL; 1346 clientBuffer->nextClip = NULL; 1347 1348 if (!mixBuffer && format.fIsMixable && sampleBuffer && (sampleBufferSize > 0)) { 1349 assert(audioEngine); 1350 1351 UInt32 mixBufSize = format.fNumChannels * kIOAudioEngineDefaultMixBufferSampleSize * audioEngine->numSampleFramesPerBuffer; 1352 1353 if (mixBufSize > 0) { 1354 void *mixBuf = IOMallocAligned(mixBufSize, 32); 1355 if (mixBuf) { 1356 setMixBuffer(mixBuf, mixBufSize); 1357 streamAllocatedMixBuffer = true; 1358 } 1359 } 1360 } 1361 } 1362 1363 result = kIOReturnSuccess; 1364 } else { 1365 audioDebugIOLog(3, " clientBuffer invalid (%d, %d, %d).\n", format.fIsMixable, numClients, getDirection()); 1366 result = kIOReturnExclusiveAccess; 1367 } 1368 } 1369 else { 1370 // <rdar://13412666> Return success if the buffers are already registered 1371 result = kIOReturnSuccess; 1372 } 1373 1374 unlockStreamForIO(); 1375 } 1376 1377 audioDebugIOLog(3, "- IOAudioStream[%p]::addClient(%p) returns 0x%lX\n", this, clientBuffer, (long unsigned int)result ); 1378 return result; 1379} 1380 1381void IOAudioStream::removeClient(IOAudioClientBuffer *clientBuffer) 1382{ 1383 audioDebugIOLog(3, "+ IOAudioStream[%p]::removeClient(%p)\n", this, clientBuffer); 1384 1385 if (clientBuffer) { 1386 IOAudioClientBuffer *tmpClientBuffer, *previousClientBuffer = NULL; 1387 1388 assert(clientBuffer->audioStream == this); 1389 1390 lockStreamForIO(); 1391 1392 tmpClientBuffer = userClientList; 1393 while (tmpClientBuffer && (tmpClientBuffer != clientBuffer)) { 1394 previousClientBuffer = tmpClientBuffer; 1395 tmpClientBuffer = tmpClientBuffer->nextClient; 1396 } 1397 1398 if (tmpClientBuffer) { 1399 if (previousClientBuffer) { 1400 previousClientBuffer->nextClient = tmpClientBuffer->nextClient; 1401 } else { 1402 assert(tmpClientBuffer == userClientList); 1403 userClientList = tmpClientBuffer->nextClient; 1404 } 1405 1406 tmpClientBuffer->nextClient = NULL; 1407 1408 numClients--; 1409 updateNumClients(); 1410 } 1411 1412 // Make sure the buffer is in the list 1413 if ((clientBuffer->nextClip != NULL) || (clientBuffer->previousClip != NULL) || (clientBuffer == clientBufferListStart)) { 1414 if (getDirection() == kIOAudioStreamDirectionOutput) { 1415 if (numClients == 0) { 1416 resetClipInfo(); 1417 } 1418 1419 if (clientBuffer->previousClip != NULL) { 1420 clientBuffer->previousClip->nextClip = clientBuffer->nextClip; 1421 } 1422 1423 if (clientBuffer->nextClip != NULL) { 1424 clientBuffer->nextClip->previousClip = clientBuffer->previousClip; 1425 } 1426 1427 if (clientBufferListEnd == clientBuffer) { 1428 assert(clientBuffer->nextClip == NULL); 1429 clientBufferListEnd = clientBuffer->previousClip; 1430 } 1431 1432 if (clientBufferListStart == clientBuffer) { 1433 assert(clientBuffer->previousClip == NULL); 1434 clientBufferListStart = clientBuffer->nextClip; 1435 if (clientBufferListStart != NULL) { 1436 clipIfNecessary(); 1437 } 1438 } 1439 } 1440 } 1441 1442 // clear these values for bug 2851917 1443 clientBuffer->previousClip = NULL; 1444 clientBuffer->nextClip = NULL; 1445 clientBuffer->nextClient = NULL; 1446 unlockStreamForIO(); 1447 1448 //<rdar://problem/10305944> dump any streaming errors 1449 safeLogError(kErrorLogDumpCounters,0,0,0,0,0,0); // dump the counters 1450 } 1451 1452 audioDebugIOLog(3, "- IOAudioStream[%p]::removeClient(%p)\n", this, clientBuffer); 1453 return; 1454} 1455 1456UInt32 IOAudioStream::getNumClients() 1457{ 1458 return numClients; 1459} 1460 1461void dumpList(IOAudioClientBuffer *start) 1462{ 1463 IOAudioClientBuffer *tmp; 1464 1465 tmp = start; 1466 while (tmp) { 1467 audioDebugIOLog(3, " (%lx,%lx)\n", (long unsigned int)tmp->mixedPosition.fLoopCount, (long unsigned int)tmp->mixedPosition.fSampleFrame); 1468 tmp = tmp->nextClip; 1469 } 1470} 1471 1472void validateList(IOAudioClientBuffer *start) 1473{ 1474 IOAudioClientBuffer *tmp; 1475 1476 tmp = start; 1477 while (tmp) { 1478 if (tmp->nextClip && (CMP_IOAUDIOENGINEPOSITION(&tmp->mixedPosition, &tmp->nextClip->mixedPosition) > 0)) { 1479 audioDebugIOLog(3, "+-IOAudioStream: ERROR - client buffer list not sorted!\n"); 1480 dumpList(start); 1481 break; 1482 } 1483 tmp = tmp->nextClip; 1484 } 1485} 1486 1487IOReturn IOAudioStream::readInputSamples(IOAudioClientBuffer *clientBuffer, UInt32 firstSampleFrame) 1488{ 1489 IOReturn result = kIOReturnError; 1490 1491 assert(audioEngine); 1492 assert(getDirection() == kIOAudioStreamDirectionInput); 1493 assert(reserved); 1494 1495 if (clientBuffer) { 1496 UInt32 numWrappedFrames = 0; 1497 UInt32 numReadFrames = 0; 1498 UInt32 numSampleFramesPerBuffer; 1499 1500 numSampleFramesPerBuffer = audioEngine->getNumSampleFramesPerBuffer(); 1501 1502 if ((firstSampleFrame + clientBuffer->numSampleFrames) > numSampleFramesPerBuffer) { 1503 numWrappedFrames = clientBuffer->numSampleFrames - (numSampleFramesPerBuffer - firstSampleFrame); 1504 } 1505 1506 if (audioIOFunctions && (numIOFunctions != 0)) { 1507 UInt32 functionNum; 1508 1509 for (functionNum = 0; functionNum < numIOFunctions; functionNum++) { 1510 if (audioIOFunctions[functionNum]) { 1511 result = audioIOFunctions[functionNum](sampleBuffer, clientBuffer->sourceBuffer, firstSampleFrame, clientBuffer->numSampleFrames - numWrappedFrames, &format, this); 1512 if (result != kIOReturnSuccess) { 1513 break; 1514 } 1515 } 1516 } 1517 1518 if (numWrappedFrames > 0) { 1519 for (functionNum = 0; functionNum < numIOFunctions; functionNum++) { 1520 if (audioIOFunctions[functionNum]) { 1521 result = audioIOFunctions[functionNum](sampleBuffer, &((float *)clientBuffer->sourceBuffer)[(numSampleFramesPerBuffer - firstSampleFrame) * format.fNumChannels], 0, numWrappedFrames, &format, this); 1522 if (result != kIOReturnSuccess) { 1523 break; 1524 } 1525 } 1526 } 1527 } 1528 } else { 1529 numReadFrames = clientBuffer->numSampleFrames - numWrappedFrames; 1530 // numReadFrames passed by reference, value may or may not be modified by the engine. 1531 result = audioEngine->convertInputSamplesVBR(sampleBuffer, clientBuffer->sourceBuffer, firstSampleFrame, numReadFrames, &format, this); 1532 // override the default value set before this call with driver actual value 1533 reserved->mSampleFramesReadByEngine = numReadFrames; 1534 1535 if ((result == kIOReturnSuccess) && (numWrappedFrames > 0)) { 1536 numReadFrames = numWrappedFrames; 1537 if (format.fIsMixable) { // <rdar://8572755> 1538 // Use float format to compute offset for destination buffer 1539 result = audioEngine->convertInputSamplesVBR(sampleBuffer, &((float *)clientBuffer->sourceBuffer)[(numSampleFramesPerBuffer - firstSampleFrame) * format.fNumChannels], 0, numReadFrames, &format, this); 1540 } else { 1541 // Use native format to compute offset for destination buffer 1542 result = audioEngine->convertInputSamplesVBR(sampleBuffer, ((UInt8 *)clientBuffer->sourceBuffer) + ((numSampleFramesPerBuffer - firstSampleFrame) * format.fNumChannels * (format.fBitWidth / 8)), 0, numReadFrames, &format, this); 1543 } 1544 reserved->mSampleFramesReadByEngine += numReadFrames; 1545 } 1546 } 1547 } else { 1548 result = kIOReturnBadArgument; 1549 } 1550 1551 return result; 1552} 1553 1554IOReturn IOAudioStream::processOutputSamples(IOAudioClientBuffer *clientBuffer, UInt32 firstSampleFrame, UInt32 loopCount, bool samplesAvailable) 1555{ 1556 IOReturn result = kIOReturnSuccess; 1557 1558 //audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p, 0x%lx)\n", this, clientBuffer, firstSampleFrame); 1559 //audioDebugIOLog(6, "m(%lx,%lx,%lx)\n", loopCount, firstSampleFrame, clientBuffer->numSampleFrames); 1560 1561 assert(direction == kIOAudioStreamDirectionOutput); 1562 if (clientBuffer) { 1563 // We can go ahead if we have a mix buffer or if the format is not mixable 1564 if (mixBuffer || !format.fIsMixable) { 1565 UInt32 numSampleFramesPerBuffer = audioEngine->getNumSampleFramesPerBuffer(); 1566 UInt32 nextSampleFrame = 0; 1567 UInt32 mixBufferWrapped = false; 1568 UInt32 numSamplesToMix = 0; 1569 IOAudioClientBuffer *tmpBuf = NULL; 1570 1571 assert(audioEngine); 1572 1573 1574 1575 // If we haven't mixed any samples for this client yet, 1576 // we have to figure out which loop those samples belong to 1577 if (IOAUDIOENGINEPOSITION_IS_ZERO(&clientBuffer->mixedPosition)) { 1578 clientBuffer->mixedPosition.fSampleFrame = firstSampleFrame; 1579 clientBuffer->mixedPosition.fLoopCount = loopCount; 1580 } else { 1581 // If firstSampleFrame is not the same as the previous mixed position sample frame, 1582 // then adjust it to the firstSampleFrame - looping if necessary 1583 if ((clientBuffer->mixedPosition.fSampleFrame != firstSampleFrame) || (clientBuffer->mixedPosition.fLoopCount != loopCount)) { 1584 audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p) - Mix start position (%lx,%lx) is not previous mixed position (%lx,%lx)\n", 1585 this, 1586 clientBuffer, 1587 (long unsigned int)loopCount, 1588 (long unsigned int)firstSampleFrame, 1589 (long unsigned int)clientBuffer->mixedPosition.fLoopCount, 1590 (long unsigned int)clientBuffer->mixedPosition.fSampleFrame); 1591 clientBuffer->mixedPosition.fLoopCount = loopCount; 1592 clientBuffer->mixedPosition.fSampleFrame = firstSampleFrame; 1593 } 1594 1595 // Check to see if the first sample frame is more than one buffer behind the last mixed position 1596 // of all of the buffers. We need to deal with the case where we didn't get any samples 1597 // for this buffer for more than a buffer cycle. In that case, we need to jump to 1598 // the loop that the last buffer is on. This assumes that a client never gets more than one 1599 // buffer cycle ahead of the playback head 1600 if ((clientBuffer != clientBufferListEnd) && 1601 (clientBufferListEnd != NULL) && 1602 ((clientBufferListEnd->mixedPosition.fLoopCount > (clientBuffer->mixedPosition.fLoopCount + 1)) || 1603 ((clientBufferListEnd->mixedPosition.fLoopCount == (clientBuffer->mixedPosition.fLoopCount + 1)) && 1604 (clientBufferListEnd->mixedPosition.fSampleFrame > clientBuffer->mixedPosition.fSampleFrame)))) { 1605 // Adjust the loop count to be on the loop before the last mixed position 1606 if (clientBuffer->mixedPosition.fSampleFrame > clientBufferListEnd->mixedPosition.fSampleFrame) { 1607 clientBuffer->mixedPosition.fLoopCount = clientBufferListEnd->mixedPosition.fLoopCount - 1; 1608 } else { 1609 clientBuffer->mixedPosition.fLoopCount = clientBufferListEnd->mixedPosition.fLoopCount; 1610 } 1611 audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p) - more than one buffer behind (%lx,%lx) adjusting to (%lx,%lx)\n", 1612 this, 1613 clientBuffer, 1614 (long unsigned int)clientBufferListEnd->mixedPosition.fLoopCount, 1615 (long unsigned int)clientBufferListEnd->mixedPosition.fSampleFrame, 1616 (long unsigned int)clientBuffer->mixedPosition.fLoopCount, 1617 (long unsigned int)firstSampleFrame); 1618 //dumpList(clientBufferListStart); 1619 } 1620 } 1621 1622 // If we've already clipped, we need to verify all of the samples are after the clipped position 1623 // Those that are not will be discarded - they can't be played 1624 if (!IOAUDIOENGINEPOSITION_IS_ZERO(&clippedPosition)) { 1625 if (clientBuffer->mixedPosition.fLoopCount == clippedPosition.fLoopCount) { 1626 if (clientBuffer->mixedPosition.fSampleFrame < clippedPosition.fSampleFrame) { 1627 audioEngine->resetClipPosition(this, clientBuffer->mixedPosition.fSampleFrame); 1628 1629#ifdef DEBUG 1630 UInt32 samplesMissed; 1631 samplesMissed = clippedPosition.fSampleFrame - clientBuffer->mixedPosition.fSampleFrame; 1632 audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p) - Reset clip position (%lx,%lx)->(%lx,%lx) - %lx samples.\n", 1633 this, 1634 clientBuffer, 1635 (long unsigned int)clippedPosition.fLoopCount, 1636 (long unsigned int)clippedPosition.fSampleFrame, 1637 (long unsigned int)clientBuffer->mixedPosition.fLoopCount, 1638 (long unsigned int)clientBuffer->mixedPosition.fSampleFrame, 1639 (long unsigned int)samplesMissed); 1640#endif 1641 1642 clippedPosition = clientBuffer->mixedPosition; 1643 } 1644 } else if (clientBuffer->mixedPosition.fLoopCount < clippedPosition.fLoopCount) { 1645 audioEngine->resetClipPosition(this, clientBuffer->mixedPosition.fSampleFrame); 1646 1647#ifdef DEBUG 1648 UInt32 samplesMissed; 1649 samplesMissed = (clippedPosition.fLoopCount - clientBuffer->mixedPosition.fLoopCount - 1) * numSampleFramesPerBuffer; 1650 samplesMissed += clippedPosition.fSampleFrame + numSampleFramesPerBuffer - clientBuffer->mixedPosition.fSampleFrame; 1651 audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p) - Reset clip position (%lx,%lx)->(%lx,%lx) - %lx samples.\n", 1652 this, 1653 clientBuffer, 1654 (long unsigned int)clippedPosition.fLoopCount, 1655 (long unsigned int)clippedPosition.fSampleFrame, 1656 (long unsigned int)clientBuffer->mixedPosition.fLoopCount, 1657 (long unsigned int)clientBuffer->mixedPosition.fSampleFrame, 1658 (long unsigned int)samplesMissed); 1659#endif 1660 1661 clippedPosition = clientBuffer->mixedPosition; 1662 } 1663 } 1664 1665 // We only need to mix samples if there are samples available 1666 // If the watchdog timer was responsible for this call, then 1667 // there won't be any samples, so there's no point in mixing 1668 // or resetting the clip position 1669 if (samplesAvailable) { 1670 numSamplesToMix = clientBuffer->numSampleFrames; 1671 } 1672 1673 if (numSamplesToMix > 0) { 1674/* 1675#ifdef DEBUG 1676 UInt32 currentSampleFrame = audioEngine->getCurrentSampleFrame(); 1677 if (currentSampleFrame > firstSampleFrame) { 1678 if ((firstSampleFrame + clientBuffer->numSampleFrames) > currentSampleFrame) { 1679 //audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p) - Error: Some samples already played: first=%lx num=%lx curr=%lx\n", this, clientBuffer, firstSampleFrame, clientBuffer->numSampleFrames, currentSampleFrame); 1680 audioDebugIOLog(6, "mix() missed first=%lx num=%lx curr=%lx\n", firstSampleFrame, clientBuffer->numSampleFrames, currentSampleFrame); 1681 } 1682 } else { 1683 if ((clientBuffer->numSampleFrames + firstSampleFrame) > (currentSampleFrame + numSampleFramesPerBuffer)) { 1684 //audioDebugIOLog(6, "IOAudioStream[%p]::processOutputSamples(%p) - Error: Some samples already played: first=%lx num=%lx curr=%lx\n", this, clientBuffer, firstSampleFrame, clientBuffer->numSampleFrames, currentSampleFrame); 1685 audioDebugIOLog(6, "mix() missed first=%lx num=%lx curr=%lx\n", firstSampleFrame, clientBuffer->numSampleFrames, currentSampleFrame); 1686 } 1687 } 1688#endif 1689*/ 1690 1691 // Check if the buffer wraps 1692 if (numSampleFramesPerBuffer > (firstSampleFrame + numSamplesToMix)) { // No wrap 1693 if (format.fIsMixable) { 1694 if (numClients == 1) { 1695 result = mixOutputSamples (clientBuffer->sourceBuffer, mixBuffer, firstSampleFrame, numSamplesToMix, &format, this); 1696 } else { 1697 result = audioEngine->mixOutputSamples(clientBuffer->sourceBuffer, mixBuffer, firstSampleFrame, numSamplesToMix, &format, this); 1698 } 1699 } else { 1700 result = kIOReturnSuccess; 1701 } 1702 nextSampleFrame = firstSampleFrame + numSamplesToMix; 1703 } else { // Buffer wraps around 1704 mixBufferWrapped = true; 1705 if (format.fIsMixable) { 1706 if (numClients == 1) { 1707 result = mixOutputSamples (clientBuffer->sourceBuffer, mixBuffer, firstSampleFrame, numSampleFramesPerBuffer - firstSampleFrame, &format, this); 1708 } else { 1709 result = audioEngine->mixOutputSamples(clientBuffer->sourceBuffer, mixBuffer, firstSampleFrame, numSampleFramesPerBuffer - firstSampleFrame, &format, this); 1710 } 1711 } else { 1712 result = kIOReturnSuccess; 1713 } 1714 if (result != kIOReturnSuccess) { 1715 IOLog("IOAudioStream[%p]::processOutputSamples(%p) - Error: 0x%x returned from audioEngine->mixOutputSamples(%p, %p, 0x%lx, 0x%lx, %p, %p)\n", this, clientBuffer, result, clientBuffer->sourceBuffer, mixBuffer, (long unsigned int)firstSampleFrame,(long unsigned int) numSampleFramesPerBuffer - firstSampleFrame, &format, this); 1716 } 1717 nextSampleFrame = numSamplesToMix - (numSampleFramesPerBuffer - firstSampleFrame); 1718 if (format.fIsMixable) { 1719 if (numClients == 1) { 1720 result = mixOutputSamples (((float *)clientBuffer->sourceBuffer) + ((numSampleFramesPerBuffer - firstSampleFrame) * format.fNumChannels), mixBuffer, 0, nextSampleFrame, &format, this); 1721 } else { 1722 result = audioEngine->mixOutputSamples(((float *)clientBuffer->sourceBuffer) + ((numSampleFramesPerBuffer - firstSampleFrame) * format.fNumChannels), mixBuffer, 0, nextSampleFrame, &format, this); 1723 } 1724 } else { 1725 result = kIOReturnSuccess; 1726 } 1727 } 1728 1729 if (result == kIOReturnSuccess) { 1730 // Reset startingSampleFrame and startingLoopCount if we haven't clipped 1731 // anything yet and this buffer mixed samples before the previous 1732 // starting frame 1733 if (IOAUDIOENGINEPOSITION_IS_ZERO(&clippedPosition)) { 1734 if (IOAUDIOENGINEPOSITION_IS_ZERO(&startingPosition) || 1735 (clientBuffer->mixedPosition.fLoopCount < startingPosition.fLoopCount) || 1736 ((clientBuffer->mixedPosition.fLoopCount == startingPosition.fLoopCount) && (firstSampleFrame < startingPosition.fSampleFrame))) { 1737 1738 startingPosition.fLoopCount = clientBuffer->mixedPosition.fLoopCount; 1739 startingPosition.fSampleFrame = firstSampleFrame; 1740 } 1741 } 1742 } else { 1743 IOLog("IOAudioStream[%p]::processOutputSamples(%p) - Error: 0x%lx returned from audioEngine->mixOutputSamples(%p, %p, 0x%lx, 0x%lx, %p, %p)\n", this, clientBuffer, (long unsigned int)result, clientBuffer->sourceBuffer, mixBuffer, (long unsigned int)firstSampleFrame,(long unsigned int) numSampleFramesPerBuffer - firstSampleFrame, &format, this); 1744 } 1745 1746 if (mixBufferWrapped) { 1747 clientBuffer->mixedPosition.fLoopCount++; 1748 } 1749 clientBuffer->mixedPosition.fSampleFrame = nextSampleFrame; 1750 1751 } else { // We missed all of the samples 1752 clientBuffer->mixedPosition.fSampleFrame += clientBuffer->numSampleFrames; 1753 if (clientBuffer->mixedPosition.fSampleFrame >= numSampleFramesPerBuffer) { 1754 clientBuffer->mixedPosition.fSampleFrame -= numSampleFramesPerBuffer; 1755 clientBuffer->mixedPosition.fLoopCount++; 1756 } 1757 } 1758 1759 // If this buffer isn't in the list yet, then we look at the beginning of the list 1760 if ((clientBuffer->nextClip == NULL) && (clientBuffer->previousClip == NULL) && (clientBuffer != clientBufferListStart)) { 1761 // If the buffer has mixed past the first buffer in the list, then we can start at the beginning 1762 // If not, then tmpBuf is just NULL and we insert at the beginning 1763 if ((clientBufferListStart != NULL) && (CMP_IOAUDIOENGINEPOSITION(&clientBuffer->mixedPosition, &clientBufferListStart->mixedPosition) > 0)) { 1764 tmpBuf = clientBufferListStart; 1765 } 1766 } else { // Otherwise, we look forward from the current position 1767 tmpBuf = clientBuffer; 1768 } 1769 1770 // Add it to the beginning if the buffer is new and has not mixed past any other buffers 1771 if (tmpBuf == NULL) { 1772 assert(clientBuffer->nextClip == NULL); 1773 assert(clientBuffer->previousClip == NULL); 1774 1775 clientBuffer->nextClip = clientBufferListStart; 1776 clientBufferListStart = clientBuffer; 1777 1778 if (clientBuffer->nextClip == NULL) { 1779 clientBufferListEnd = clientBuffer; 1780 } else { 1781 clientBuffer->nextClip->previousClip = clientBuffer; 1782 } 1783 } else { 1784 //Find the insertion point for the new location for this buffer 1785 while ((tmpBuf->nextClip != NULL) && (CMP_IOAUDIOENGINEPOSITION(&clientBuffer->mixedPosition, &tmpBuf->nextClip->mixedPosition) > 0)) { 1786 tmpBuf = tmpBuf->nextClip; 1787 } 1788 1789 if (tmpBuf != clientBuffer) { 1790 // If the buffer is to change position, move updated client buffer to its new sorted position 1791 // First remove the client buffer from its current position 1792 if (clientBuffer->previousClip != NULL) { 1793 clientBuffer->previousClip->nextClip = clientBuffer->nextClip; 1794 } else if (clientBuffer == clientBufferListStart) { // If we don't have a previous clip set, we may be the starting entry 1795 clientBufferListStart = clientBuffer->nextClip; 1796 } // If we have don't have a previousClip set and are not the start, then this is the first time this buffer is being mixed 1797 1798 if (clientBuffer->nextClip != NULL) { 1799 clientBuffer->nextClip->previousClip = clientBuffer->previousClip; 1800 } else if (clientBuffer == clientBufferListEnd) { // If we don't have a next clip set, we may be the last entry 1801 // We should never get here, because we only are moving this buffer forward 1802 // and that is impossible if it is the last one 1803 clientBufferListEnd = clientBuffer->previousClip; 1804 } // If we don't have a next clip and are not the end, then this is the first time this buffer is being mixed 1805 1806 // Insert it after tmpBuf 1807 clientBuffer->nextClip = tmpBuf->nextClip; 1808 clientBuffer->previousClip= tmpBuf; 1809 tmpBuf->nextClip = clientBuffer; 1810 if (clientBuffer->nextClip) { 1811 clientBuffer->nextClip->previousClip = clientBuffer; 1812 } 1813 if (clientBuffer->nextClip == NULL) { 1814 assert(clientBufferListEnd == tmpBuf); 1815 clientBufferListEnd = clientBuffer; 1816 } 1817 1818#ifdef DEBUG 1819 validateList(clientBufferListStart); 1820#endif 1821 } 1822 } 1823 1824 // We should attempt to clip if we mixed some samples of if we 1825 // were called as a result of the watchdog timer (indicated 1826 // by samplesAvailable being false) 1827 if ((numSamplesToMix > 0) || !samplesAvailable) { 1828 if (!format.fIsMixable) { 1829 mixBuffer = clientBuffer->sourceBuffer; 1830 } 1831 1832 reserved->mClipOutputStatus = kIOReturnSuccess; 1833 1834 clipIfNecessary(); 1835 if (!format.fIsMixable) { 1836 mixBuffer = NULL; 1837 } 1838 1839 // gets set based on IOAudioEngine::clipOutputSamples return value inside IOAudioStream::clipOutputSamples 1840 result = reserved->mClipOutputStatus; 1841 } 1842 } else { 1843 IOLog("IOAudioStream[%p]::processOutputSamples(%p) - Internal Error: No mix buffer\n", this, clientBuffer); 1844 result = kIOReturnError; 1845 } 1846 } else { 1847 result = kIOReturnBadArgument; 1848 } 1849 1850 return result; 1851} 1852 1853void IOAudioStream::resetClipInfo() 1854{ 1855 startingPosition.fLoopCount = 0; 1856 startingPosition.fSampleFrame = 0; 1857 clippedPosition.fLoopCount = 0; 1858 clippedPosition.fSampleFrame = 0; 1859} 1860 1861void IOAudioStream::clipIfNecessary() 1862{ 1863 //audioDebugIOLog(6, "IOAudioStream[%p]::clipIfNecessary()\n", this); 1864 1865 if (clientBufferListStart != NULL) { 1866 // Only try to clip if there is not an unmixed buffer 1867 if (!IOAUDIOENGINEPOSITION_IS_ZERO(&clientBufferListStart->mixedPosition)) { 1868 1869 // Check to see if we've clipped any samples yet 1870 if (IOAUDIOENGINEPOSITION_IS_ZERO(&clippedPosition)) { 1871 clippedPosition = startingPosition; 1872 } 1873 1874#ifdef DEBUG 1875 IOAudioClientBuffer *tmp; 1876 1877 tmp = clientBufferListStart->nextClip; 1878 while (tmp) { 1879 if ((tmp->mixedPosition.fLoopCount > (clippedPosition.fLoopCount + 1)) || 1880 ((tmp->mixedPosition.fLoopCount == clippedPosition.fLoopCount) && 1881 (tmp->mixedPosition.fSampleFrame > clippedPosition.fSampleFrame))) { 1882 1883 if (clientBufferListStart->mixedPosition.fSampleFrame > clippedPosition.fSampleFrame) { 1884 if ((tmp->mixedPosition.fSampleFrame > clippedPosition.fSampleFrame) && 1885 (clientBufferListStart->mixedPosition.fSampleFrame > tmp->mixedPosition.fSampleFrame)) { 1886 audioDebugIOLog(6, "IOAudioStream[%p]::clipIfNecessary() - Error: Clipping across future buffer boundary - glitching! (%lx,%lx)->(%lx,%lx) buf=(%lx,%lx)\n", 1887 this, 1888 (long unsigned int)clippedPosition.fLoopCount, 1889 (long unsigned int)clippedPosition.fSampleFrame, 1890 (long unsigned int)clientBufferListStart->mixedPosition.fLoopCount, 1891 (long unsigned int)clientBufferListStart->mixedPosition.fSampleFrame, 1892 (long unsigned int)tmp->mixedPosition.fLoopCount, 1893 (long unsigned int)tmp->mixedPosition.fSampleFrame); 1894 dumpList(clientBufferListStart); 1895 break; 1896 } 1897 } else if (clippedPosition.fSampleFrame > clientBufferListStart->mixedPosition.fSampleFrame) { 1898 if ((tmp->mixedPosition.fSampleFrame < clientBufferListStart->mixedPosition.fSampleFrame) || 1899 (tmp->mixedPosition.fSampleFrame > clippedPosition.fSampleFrame)) { 1900 audioDebugIOLog(6, "IOAudioStream[%p]::clipIfNecessary() - Error: Clipping across future buffer boundary - glitching! (%lx,%lx)->(%lx,%lx) buf=(%lx,%lx)\n", 1901 this, 1902 (long unsigned int)clippedPosition.fLoopCount, 1903 (long unsigned int)clippedPosition.fSampleFrame, 1904 (long unsigned int)clientBufferListStart->mixedPosition.fLoopCount, 1905 (long unsigned int)clientBufferListStart->mixedPosition.fSampleFrame, 1906 (long unsigned int)tmp->mixedPosition.fLoopCount, 1907 (long unsigned int)tmp->mixedPosition.fSampleFrame); 1908 dumpList(clientBufferListStart); 1909 break; 1910 } 1911 } 1912 } 1913 tmp = tmp->nextClip; 1914 } 1915#endif 1916 1917 // Check to see if it is on the same loop as the starting position 1918 // If not, adjust it to the same loop 1919 if (((clientBufferListStart->mixedPosition.fLoopCount == (clippedPosition.fLoopCount + 1)) && 1920 (clientBufferListStart->mixedPosition.fSampleFrame >= clippedPosition.fSampleFrame)) || 1921 (clientBufferListStart->mixedPosition.fLoopCount > (clippedPosition.fLoopCount + 1))) { 1922 safeLogError(kErrorLogClipMoreThanOneBufferAhead,clippedPosition.fLoopCount,(long unsigned int)clippedPosition.fSampleFrame,(long unsigned int) clientBufferListStart->mixedPosition.fLoopCount,(long unsigned int) clientBufferListStart->mixedPosition.fSampleFrame,0,0); //<rdar://problem/10305944> 1923 if (clientBufferListStart->mixedPosition.fSampleFrame >= clippedPosition.fSampleFrame) { 1924 clippedPosition.fLoopCount = clientBufferListStart->mixedPosition.fLoopCount; 1925 } else { 1926 clippedPosition.fLoopCount = clientBufferListStart->mixedPosition.fLoopCount - 1; 1927 } 1928 safeLogError(kErrorLogClipMoreThanOneBufferAheadPart2,clippedPosition.fLoopCount,(long unsigned int)clippedPosition.fSampleFrame,0,0,0,0); //<rdar://problem/10305944> 1929 } 1930 1931 // Add a test to see if we'd be clipping more samples than delivered because the HAL might skip some samples around a loop increment 1932 // If the HAL skipped samples around a loop increment, then just start from where it wants to 1933 if (clientBufferListStart->mixedPosition.fLoopCount + 1 == clippedPosition.fLoopCount && (clientBufferListStart->numSampleFrames < audioEngine->getNumSampleFramesPerBuffer() - clippedPosition.fSampleFrame)) { 1934 clientBufferListStart->mixedPosition.fLoopCount = clippedPosition.fLoopCount; 1935 safeLogError(kErrorLogClipPositionIsOff,clientBufferListStart->numSampleFrames,(long int) audioEngine->getNumSampleFramesPerBuffer(),(long int) clippedPosition.fSampleFrame,0,0,0); 1936 } 1937/* 1938 static UInt32 lastSampleFrame; 1939 if (clippedPosition.fSampleFrame != lastSampleFrame) { 1940 audioDebugIOLog(3, "Family sample frames wrong %ld %ld\n", clippedPosition.fSampleFrame, lastSampleFrame); 1941 } 1942 lastSampleFrame = clippedPosition.fSampleFrame + (clientBufferListStart->mixedPosition.fSampleFrame - clippedPosition.fSampleFrame); 1943*/ 1944 UInt32 numSamplesToClip; //<rdar://problem/5994776> 1945 1946 if (clientBufferListStart->mixedPosition.fLoopCount == clippedPosition.fLoopCount) { 1947 if (clientBufferListStart->mixedPosition.fSampleFrame > clippedPosition.fSampleFrame) { 1948 numSamplesToClip = clientBufferListStart->mixedPosition.fSampleFrame - clippedPosition.fSampleFrame; 1949 if (!format.fIsMixable) { 1950 if ( numSamplesToClip <= kMixBufferMaxSize ) { // <rdar://problem/5994776> 1951 clipOutputSamples(clippedPosition.fSampleFrame, numSamplesToClip ); 1952 } else { 1953 reserved->mClipOutputStatus = kIOReturnOverrun; 1954#ifdef DEBUG 1955 audioDebugIOLog(6,"IOAudioStream[%p]::clipIfNecessary() clipOutputSamples clip too large for source buffer numSamplesToClip=%lu clientBufferListStart->numSampleFrames %lu\n", 1956 this, (long unsigned int)numSamplesToClip, (long unsigned int)clientBufferListStart->numSampleFrames ); 1957 IOLog("IOAudioStream[%p]::clipIfNecessary() clipOutputSamples clip too large for source buffer numSamplesToClip=%lu clientBufferListStart->numSampleFrames %lu\n", 1958 this, (long unsigned int)numSamplesToClip, (long unsigned int)clientBufferListStart->numSampleFrames ); 1959#endif 1960 } 1961 } else { 1962 clipOutputSamples(clippedPosition.fSampleFrame, numSamplesToClip); 1963 } 1964 clippedPosition.fSampleFrame = clientBufferListStart->mixedPosition.fSampleFrame; 1965 } else if (clientBufferListStart->mixedPosition.fSampleFrame < clippedPosition.fSampleFrame) { 1966 safeLogError(kErrorLogAlreadyClipped,(long unsigned int) clippedPosition.fLoopCount,(long unsigned int) clippedPosition.fSampleFrame,(long unsigned int) clientBufferListStart->mixedPosition.fLoopCount,(long unsigned int) clientBufferListStart->mixedPosition.fSampleFrame,0,0); //<rdar://problem/10305944> 1967 } 1968 } else { // Clip wraps around 1969 UInt32 numSampleFramesPerBuffer; 1970 1971 assert(audioEngine); 1972 1973 numSampleFramesPerBuffer = audioEngine->getNumSampleFramesPerBuffer(); 1974 numSamplesToClip = numSampleFramesPerBuffer - clippedPosition.fSampleFrame; 1975 1976 if (!format.fIsMixable) { 1977 if ( numSamplesToClip <= kMixBufferMaxSize) { // <rdar://problem/5994776> 1978 clipOutputSamples(clippedPosition.fSampleFrame, numSamplesToClip ); 1979 } else { 1980 reserved->mClipOutputStatus = kIOReturnOverrun; 1981#ifdef DEBUG 1982 audioDebugIOLog(6,"IOAudioStream[%p]::clipIfNecessary() clipOutputSamples wrap clip too large for source buffer numSamplesToClip=%lu clientBufferListStart->numSampleFrames %lu\n", 1983 this, (long unsigned int)numSamplesToClip, (long unsigned int)clientBufferListStart->numSampleFrames ); 1984 IOLog("IOAudioStream[%p]::clipIfNecessary() clipOutputSamples wrap clip too large for source buffer numSamplesToClip=%lu clientBufferListStart->numSampleFrames %lu\n", 1985 this, (long unsigned int)numSamplesToClip, (long unsigned int)clientBufferListStart->numSampleFrames ); 1986#endif 1987 } 1988 } else { 1989 clipOutputSamples(clippedPosition.fSampleFrame, numSamplesToClip ); 1990 } 1991 1992 if (!format.fIsMixable) { 1993 UInt32 remainingSamplesToClip = (numSampleFramesPerBuffer - clippedPosition.fSampleFrame); //<rdar://problem/5994776> 1994 1995 // Move the mix buffer to where we left off because the clip routine always starts at the beginning of the source buffer, 1996 // but that's not the right place when we don't have a source buffer and are using the mixbuffer as a pseduo-source buffer. 1997 audioDebugIOLog(6,"IOAudioStream[%p]::clipIfNecessary() clipOutputSamples wrap mixBuffer=%p remainingSamplesToClip=0x%lu clientBufferListStart->mixedPosition.fSampleFrame=%lu\n", 1998 this, mixBuffer, (long unsigned int)remainingSamplesToClip, (long unsigned int)clientBufferListStart->mixedPosition.fSampleFrame ); 1999 if ( remainingSamplesToClip + clientBufferListStart->mixedPosition.fSampleFrame <= kMixBufferMaxSize) // <rdar://problem/5994776> 2000 { 2001 mixBuffer = (char *)mixBuffer + (remainingSamplesToClip * format.fNumChannels * (format.fBitWidth / 8)); 2002 clipOutputSamples(0, clientBufferListStart->mixedPosition.fSampleFrame); 2003 } else { 2004 reserved->mClipOutputStatus = kIOReturnOverrun; 2005#ifdef DEBUG 2006 audioDebugIOLog(6,"IOAudioStream[%p]::clipIfNecessary() clipOutputSamples mixBufferOffset too large for source buffer numSamplesToClip=%lu clientBufferListStart->numSampleFrames=%lu remainingSamplesToClip=%lu\n", 2007 this, (long unsigned int)clientBufferListStart->mixedPosition.fSampleFrame, (long unsigned int)clientBufferListStart->numSampleFrames, (long unsigned int)remainingSamplesToClip ); 2008 IOLog("IOAudioStream[%p]::clipIfNecessary() clipOutputSamples mixBufferOffset too large for source buffer numSamplesToClip=%lu clientBufferListStart->numSampleFrames=%lu remainingSamplesToClip=%lu\n", 2009 this, (long unsigned int)clientBufferListStart->mixedPosition.fSampleFrame, (long unsigned int)clientBufferListStart->numSampleFrames, (long unsigned int)remainingSamplesToClip ); 2010#endif 2011 } 2012 } else { 2013 clipOutputSamples(0, clientBufferListStart->mixedPosition.fSampleFrame); 2014 } 2015 clippedPosition = clientBufferListStart->mixedPosition; 2016 } 2017 } 2018 } 2019} 2020 2021void IOAudioStream::clipOutputSamples(UInt32 firstSampleFrame, UInt32 numSampleFrames) 2022{ 2023 IOReturn result = kIOReturnSuccess; 2024 2025 //audioDebugIOLog(6, "IOAudioStream[%p]::clipOutputSamples(0x%lx, 0x%lx)\n", this, firstSampleFrame, numSampleFrames); 2026 //audioDebugIOLog(6, "c(%lx,%lx) %lx\n", firstSampleFrame, numSampleFrames, audioEngine->getCurrentSampleFrame()); 2027 2028 assert(direction == kIOAudioStreamDirectionOutput); 2029 assert(audioEngine); 2030 assert(reserved); 2031 2032 if (!mixBuffer || !sampleBuffer) { 2033 safeLogError(kErrorLogClipBuffersAreNULL,(long unsigned int) firstSampleFrame,(long unsigned int) numSampleFrames,0,0,mixBuffer,sampleBuffer); //<rdar://problem/10305944> 2034 return; 2035 } 2036 2037/* 2038#ifdef DEBUG 2039 UInt32 currentSampleFrame = audioEngine->getCurrentSampleFrame(); 2040 2041 if (currentSampleFrame > firstSampleFrame) { 2042 if ((firstSampleFrame + numSampleFrames) > currentSampleFrame) { 2043 //audioDebugIOLog(6, "IOAudioStream[%p]::clipOutputSamples(0x%lx, 0x%lx) - too late for some samples - current position = 0x%lx.\n", this, firstSampleFrame, numSampleFrames, currentSampleFrame); 2044 audioDebugIOLog(6, "clip(%lx,%lx) missed curr=%lx.\n", firstSampleFrame, numSampleFrames, currentSampleFrame); 2045 } 2046 } else { 2047 if ((numSampleFrames + firstSampleFrame) > (currentSampleFrame + audioEngine->getNumSampleFramesPerBuffer())) { 2048 //audioDebugIOLog(6, "IOAudioStream[%p]::clipOutputSamples(0x%lx, 0x%lx) - too late for some samples - current position = 0x%lx.\n", this, firstSampleFrame, numSampleFrames, currentSampleFrame); 2049 audioDebugIOLog(6, "clip(%lx,%lx) missed curr=%lx.\n", firstSampleFrame, numSampleFrames, currentSampleFrame); 2050 } 2051 } 2052#endif 2053*/ 2054 2055 if (audioIOFunctions && (numIOFunctions != 0)) { 2056 UInt32 functionNum; 2057 2058 for (functionNum = 0; functionNum < numIOFunctions; functionNum++) { 2059 if (audioIOFunctions[functionNum]) { 2060 result = audioIOFunctions[functionNum](mixBuffer, sampleBuffer, firstSampleFrame, numSampleFrames, &format, this); 2061 if (result != kIOReturnSuccess) { 2062 break; 2063 } 2064 } 2065 } 2066 } else { 2067 result = audioEngine->clipOutputSamples(mixBuffer, sampleBuffer, firstSampleFrame, numSampleFrames, &format, this); 2068 } 2069 2070 if (result != kIOReturnSuccess) { 2071 safeLogError(kErrorLogClipReturnsAnError,(long unsigned int) firstSampleFrame,(long unsigned int) numSampleFrames,result,0,0,0); //<rdar://problem/10305944> 2072 } 2073 reserved->mClipOutputStatus = result; 2074} 2075 2076void IOAudioStream::lockStreamForIO() 2077{ 2078 assert(streamIOLock); 2079 2080 IORecursiveLockLock(streamIOLock); 2081} 2082 2083void IOAudioStream::unlockStreamForIO() 2084{ 2085 assert(streamIOLock); 2086 2087 IORecursiveLockUnlock(streamIOLock); 2088} 2089 2090void IOAudioStream::setStreamAvailable(bool available) 2091{ 2092 if (streamAvailable != available) { 2093 streamAvailable = available; 2094 setProperty(kIOAudioStreamAvailableKey, available ? 1 : 0, sizeof(UInt8)*8); 2095 2096 assert(audioEngine); 2097 audioEngine->updateChannelNumbers(); 2098 } 2099} 2100 2101bool IOAudioStream::getStreamAvailable() 2102{ 2103 return streamAvailable; 2104} 2105 2106IOReturn IOAudioStream::addDefaultAudioControl(IOAudioControl *defaultAudioControl) 2107{ 2108 IOReturn result = kIOReturnBadArgument; 2109 2110 if (defaultAudioControl) { 2111 UInt32 controlChannelID; 2112 2113 if (defaultAudioControl->getChannelID() == kIOAudioControlChannelIDAll) { 2114 if (((getDirection() == kIOAudioStreamDirectionOutput) && (defaultAudioControl->getUsage() == kIOAudioControlUsageInput)) || 2115 ((getDirection() == kIOAudioStreamDirectionInput) && (defaultAudioControl->getUsage() == kIOAudioControlUsageOutput))) { 2116 result = kIOReturnError; 2117 IOLog("IOAudioStream[%p]::addDefaultAudioControl() - Error: invalid audio control - stream direction is opposite of control usage.\n", this); 2118 goto Done; 2119 } 2120 2121 controlChannelID = defaultAudioControl->getChannelID(); 2122 2123 if ((controlChannelID != 0) && ((controlChannelID < startingChannelID) || (controlChannelID >= (startingChannelID + maxNumChannels)))) { 2124 result = kIOReturnError; 2125 IOLog("IOAudioStream[%p]::addDefaultAudioControl() - Error: audio control channel is not in this stream.\n", this); 2126 goto Done; 2127 } 2128 2129 if (defaultAudioControl->attachAndStart(this)) { 2130 if (!defaultAudioControls) { 2131 defaultAudioControls = OSSet::withObjects((const OSObject **)&defaultAudioControl, 1, 1); 2132 } else { 2133 defaultAudioControls->setObject(defaultAudioControl); 2134 } 2135 } else { 2136 result = kIOReturnError; 2137 } 2138 } else { // Control for an individual channel - attach to audio engine instead 2139 assert(audioEngine); 2140 result = audioEngine->addDefaultAudioControl(defaultAudioControl); 2141 } 2142 } 2143 2144Done: 2145 2146 return result; 2147} 2148 2149void IOAudioStream::removeDefaultAudioControls() 2150{ 2151 if (defaultAudioControls) { 2152 if (!isInactive()) { 2153 OSCollectionIterator *controlIterator; 2154 2155 controlIterator = OSCollectionIterator::withCollection(defaultAudioControls); 2156 2157 if (controlIterator) { 2158 IOAudioControl *control; 2159 2160 while ( (control = (IOAudioControl *)controlIterator->getNextObject()) ) { 2161 control->detach(this); // <rdar://14773236> 2162 2163 if (control->getProvider() == this) { 2164 control->terminate(); 2165 } 2166 } 2167 2168 controlIterator->release(); 2169 } 2170 } 2171 2172 defaultAudioControls->flushCollection(); 2173 } 2174} 2175