Changeset 61764 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- Jun 20, 2016 9:49:55 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 108154
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r61723 r61764 559 559 # error "Implement me!" 560 560 #else 561 Log FlowFunc(("[%s]: cbReadable=%RU32\n", pSink->pszName, pSink->In.cbReadable));561 Log3Func(("[%s]: cbReadable=%RU32\n", pSink->pszName, pSink->In.cbReadable)); 562 562 return pSink->In.cbReadable; 563 563 #endif … … 580 580 # error "Implement me!" 581 581 #else 582 Log FlowFunc(("[%s]: cbWritable=%RU32\n", pSink->pszName, pSink->Out.cbWritable));582 Log3Func(("[%s]: cbWritable=%RU32\n", pSink->pszName, pSink->Out.cbWritable)); 583 583 return pSink->Out.cbWritable; 584 584 #endif … … 665 665 { 666 666 if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 667 { 668 LogFlowFunc(("%s: Stream '%s' Disabled, skipping ...\n", pMixStream->pszName, pMixStream->pStream->szName)); 667 669 continue; 670 } 668 671 669 672 uint32_t cbTotalRead = 0; … … 1071 1074 if (!(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 1072 1075 { 1073 LogFlowFunc(("%s: Disabled, skipping ...\n", pSink->pszName));1076 LogFlowFunc(("%s: Stream '%s' Disabled, skipping ...\n", pMixStream->pszName, pMixStream->pStream->szName)); 1074 1077 continue; 1075 1078 } … … 1174 1177 bool AudioMixerStreamIsActive(PAUDMIXSTREAM pMixStream) 1175 1178 { 1176 if ( !pMixStream1177 || !pMixStream->pConn)1178 {1179 return false;1180 }1181 1182 1179 bool fIsActive = 1183 RT_BOOL(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED); 1180 pMixStream 1181 && RT_BOOL(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_ENABLED); 1184 1182 1185 1183 return fIsActive; … … 1188 1186 bool AudioMixerStreamIsValid(PAUDMIXSTREAM pMixStream) 1189 1187 { 1190 if (!pMixStream) 1191 return false; 1192 1193 uint32_t fStatus = pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream); 1194 1195 return (fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED); 1196 } 1197 1188 bool fIsValid = 1189 pMixStream 1190 && RT_BOOL(pMixStream->pConn->pfnStreamGetStatus(pMixStream->pConn, pMixStream->pStream) & PDMAUDIOSTRMSTS_FLAG_INITIALIZED); 1191 1192 return fIsValid; 1193 } 1194 -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r61668 r61764 46 46 static int drvAudioStreamDestroyInternalBackend(PDRVAUDIO pThis, PPDMAUDIOSTREAM pHstStream); 47 47 static int drvAudioStreamDestroyInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 48 static int drvAudioStreamInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest); 48 49 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 50 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 49 51 50 52 #ifndef VBOX_AUDIO_TESTCASE … … 254 256 return rc; 255 257 256 LogFlowFunc((" %s: enmStreamCmd=%ld\n", pStream->szName, enmStreamCmd));258 LogFlowFunc(("[%s] enmStreamCmd=%RU32\n", pStream->szName, enmStreamCmd)); 257 259 258 260 rc = drvAudioStreamControlInternal(pThis, pStream, enmStreamCmd); … … 270 272 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 271 273 272 LogF lowFunc(("%s: enmStreamCmd=%ld\n", pStream->szName, enmStreamCmd));274 LogFunc(("[%s] enmStreamCmd=%RU32\n", pStream->szName, enmStreamCmd)); 273 275 274 276 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); … … 308 310 if (pHstStream) 309 311 { 310 LogF lowFunc(("%s:Pending disable/pause\n", pHstStream->szName));312 LogFunc(("[%s] Pending disable/pause\n", pHstStream->szName)); 311 313 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 312 314 } … … 345 347 346 348 default: 347 AssertMsgFailed(("Command % ldnot implemented\n", enmStreamCmd));349 AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd)); 348 350 rc = VERR_NOT_IMPLEMENTED; 349 351 break; … … 351 353 352 354 if (RT_FAILURE(rc)) 353 LogFunc((" %s:Failed with %Rrc\n", pStream->szName, rc));355 LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc)); 354 356 355 357 return rc; … … 361 363 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 362 364 363 LogFlowFunc((" %s: enmStreamCmd=%ld\n", pStream->szName, enmStreamCmd));365 LogFlowFunc(("[%s] enmStreamCmd=%RU32\n", pStream->szName, enmStreamCmd)); 364 366 365 367 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); … … 370 372 int rc = VINF_SUCCESS; 371 373 372 switch (enmStreamCmd) 373 { 374 case PDMAUDIOSTREAMCMD_ENABLE: 375 { 376 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 377 { 378 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 379 if (RT_SUCCESS(rc)) 380 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 381 } 382 break; 383 } 384 385 case PDMAUDIOSTREAMCMD_DISABLE: 386 { 387 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 388 { 389 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 390 if (RT_SUCCESS(rc)) 374 if (RT_SUCCESS(rc)) 375 { 376 switch (enmStreamCmd) 377 { 378 case PDMAUDIOSTREAMCMD_ENABLE: 379 { 380 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED)) 391 381 { 392 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 393 AudioMixBufReset(&pHstStream->MixBuf); 382 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 383 if (RT_SUCCESS(rc)) 384 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_ENABLED; 394 385 } 395 } 396 break; 397 } 398 399 case PDMAUDIOSTREAMCMD_PAUSE: 400 { 401 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 402 { 403 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_PAUSE); 404 if (RT_SUCCESS(rc)) 405 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 406 } 407 break; 408 } 409 410 case PDMAUDIOSTREAMCMD_RESUME: 411 { 412 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED) 413 { 414 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_RESUME); 415 if (RT_SUCCESS(rc)) 416 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 417 } 418 break; 419 } 420 421 default: 422 AssertMsgFailed(("Command %ld not implemented\n", enmStreamCmd)); 423 rc = VERR_NOT_IMPLEMENTED; 424 break; 425 } 426 427 if (RT_FAILURE(rc)) 428 LogFunc(("%s: Failed with %Rrc\n", pStream->szName, rc)); 429 386 break; 387 } 388 389 case PDMAUDIOSTREAMCMD_DISABLE: 390 { 391 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) 392 { 393 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 394 if (RT_SUCCESS(rc)) 395 { 396 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_ENABLED; 397 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_DISABLE; 398 AudioMixBufReset(&pHstStream->MixBuf); 399 } 400 } 401 break; 402 } 403 404 case PDMAUDIOSTREAMCMD_PAUSE: 405 { 406 if (!(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED)) 407 { 408 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_PAUSE); 409 if (RT_SUCCESS(rc)) 410 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PAUSED; 411 } 412 break; 413 } 414 415 case PDMAUDIOSTREAMCMD_RESUME: 416 { 417 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PAUSED) 418 { 419 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_RESUME); 420 if (RT_SUCCESS(rc)) 421 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PAUSED; 422 } 423 break; 424 } 425 426 default: 427 AssertMsgFailed(("Command %RU32 not implemented\n", enmStreamCmd)); 428 rc = VERR_NOT_IMPLEMENTED; 429 break; 430 } 431 } 432 433 if (RT_FAILURE(rc)) 434 LogFunc(("[%s] Failed with %Rrc\n", pStream->szName, rc)); 435 436 return rc; 437 } 438 439 static int drvAudioStreamInitInternal(PDRVAUDIO pThis, 440 PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfgHost, PPDMAUDIOSTREAMCFG pCfgGuest) 441 { 442 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 443 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 444 445 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 446 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream; 447 AssertPtr(pGstStream); 448 449 LogFlowFunc(("[%s]\n", pStream->szName)); 450 451 /* 452 * Init host stream. 453 */ 454 455 uint32_t cSamples = 0; 456 int rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStream, pCfgHost, &cSamples); 457 if (RT_SUCCESS(rc)) 458 { 459 /* Only set the host's stream to initialized if we were able create the stream 460 * in the host backend. This is necessary for trying to re-initialize the stream 461 * at some later point in time. */ 462 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 463 } 464 else 465 LogFlowFunc(("[%s] Initializing stream in host backend failed with rc=%Rrc\n", pStream->szName, rc)); 466 467 int rc2 = DrvAudioHlpStreamCfgToProps(pCfgHost, &pHstStream->Props); 468 AssertRC(rc2); 469 470 /* Destroy any former mixing buffer. */ 471 AudioMixBufDestroy(&pHstStream->MixBuf); 472 473 if (cSamples) 474 { 475 rc2 = AudioMixBufInit(&pHstStream->MixBuf, pHstStream->szName, &pHstStream->Props, cSamples * 4); 476 AssertRC(rc2); 477 } 478 479 /* Make a copy of the host stream configuration. */ 480 memcpy(&pHstStream->Cfg, pCfgHost, sizeof(PDMAUDIOSTREAMCFG)); 481 482 /* 483 * Init guest stream. 484 */ 485 486 rc2 = DrvAudioHlpStreamCfgToProps(pCfgGuest, &pGstStream->Props); 487 AssertRC(rc2); 488 489 /* Destroy any former mixing buffer. */ 490 AudioMixBufDestroy(&pGstStream->MixBuf); 491 492 if (cSamples) 493 { 494 rc2 = AudioMixBufInit(&pGstStream->MixBuf, pGstStream->szName, &pGstStream->Props, cSamples * 2); 495 AssertRC(rc2); 496 } 497 498 if (cSamples) 499 { 500 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 501 { 502 /* Host (Parent) -> Guest (Child). */ 503 rc2 = AudioMixBufLinkTo(&pHstStream->MixBuf, &pGstStream->MixBuf); 504 AssertRC(rc2); 505 } 506 else 507 { 508 /* Guest (Parent) -> Host (Child). */ 509 rc2 = AudioMixBufLinkTo(&pGstStream->MixBuf, &pHstStream->MixBuf); 510 AssertRC(rc2); 511 } 512 } 513 514 /* Make a copy of the host stream configuration. */ 515 memcpy(&pGstStream->Cfg, pCfgGuest, sizeof(PDMAUDIOSTREAMCFG)); 516 517 LogFlowFunc(("[%s] Returning %Rrc\n", pStream->szName, rc)); 518 return rc; 519 } 520 521 static int drvAudioStreamReInitInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream) 522 { 523 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 524 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 525 526 LogFlowFunc(("[%s]\n", pStream->szName)); 527 528 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); 529 PPDMAUDIOSTREAM pGstStream = pHstStream ? pHstStream->pPair : pStream; 530 AssertPtr(pGstStream); 531 532 int rc; 533 534 if (/* Stream initialized? */ 535 (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 536 /* Not in pending re-init before? */ 537 && !(pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_PENDING_REINIT)) 538 { 539 /* Disable first. */ 540 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_DISABLE); 541 if (RT_FAILURE(rc)) 542 { 543 LogFunc(("[%s] Error disabling stream, rc=%Rrc\n", pStream->szName, rc)); 544 return rc; 545 } 546 547 /* Give the backend the chance to clean up the old context. */ 548 rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pHstStream); 549 if (RT_FAILURE(rc)) 550 { 551 LogFunc(("[%s] Error destroying stream in backend, rc=%Rrc\n", pStream->szName, rc)); 552 return rc; 553 } 554 555 /* Set the pending re-init bit. */ 556 pHstStream->fStatus |= PDMAUDIOSTRMSTS_FLAG_PENDING_REINIT; 557 } 558 559 LogFlowFunc(("[%s] Host status is 0x%x\n", pStream->szName, pHstStream->fStatus)); 560 561 /* Try to re-initialize the stream. */ 562 rc = drvAudioStreamInitInternal(pThis, pStream, &pHstStream->Cfg, &pGstStream->Cfg); 563 if (RT_SUCCESS(rc)) 564 { 565 /* Try to restore the previous stream status, if possible. */ 566 PDMAUDIOSTREAMCMD enmCmdRestore = PDMAUDIOSTREAMCMD_UNKNOWN; 567 568 if (pHstStream->fStatus & PDMAUDIOSTRMSTS_FLAG_ENABLED) /* Stream was running before? */ 569 { 570 LogFunc(("[%s] Re-enabling host stream ...\n", pStream->szName)); 571 enmCmdRestore = PDMAUDIOSTREAMCMD_ENABLE; 572 } 573 574 if (enmCmdRestore != PDMAUDIOSTREAMCMD_UNKNOWN) 575 rc = pThis->pHostDrvAudio->pfnStreamControl(pThis->pHostDrvAudio, pHstStream, PDMAUDIOSTREAMCMD_ENABLE); 576 577 /* Re-initialization successful, remove bit again. */ 578 pHstStream->fStatus &= ~PDMAUDIOSTRMSTS_FLAG_PENDING_REINIT; 579 } 580 581 LogFunc(("[%s] Reinitialization returned %Rrc\n", pStream->szName, rc)); 430 582 return rc; 431 583 } … … 465 617 pStream->szName, pStream->enmDir)); 466 618 467 Log FlowFunc(("[%s]: cbBuf=%RU32\n", pStream->szName, cbBuf));619 Log3Func(("[%s]: cbBuf=%RU32\n", pStream->szName, cbBuf)); 468 620 469 621 int rc = RTCritSectEnter(&pThis->CritSect); … … 508 660 } 509 661 510 LogFlowFunc(("cWritten=%RU32 (%RU32 bytes), cMixed=%RU32, rc=%Rrc\n", 511 cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), 0, rc)); 662 Log3Func(("cWritten=%RU32 (%RU32 bytes), rc=%Rrc\n", cWritten, AUDIOMIXBUF_S2B(&pHstStream->MixBuf, cWritten), rc)); 512 663 513 664 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 553 704 return rc; 554 705 555 LogFlowFunc(("%s\n", pStream->szName));556 557 706 rc = drvAudioStreamIterateInternal(pThis, pStream); 558 707 … … 573 722 if (!pStream) 574 723 return VINF_SUCCESS; 575 576 LogFlowFunc(("%s\n", pStream->szName));577 724 578 725 PPDMAUDIOSTREAM pHstStream = drvAudioGetHostStream(pStream); … … 599 746 uint32_t cSamplesCaptured = AudioMixBufUsed(&pHstStream->MixBuf); 600 747 601 Log FlowFunc(("[%s] %RU32 samples captured\n", pHstStream->szName, cSamplesCaptured));748 Log3Func(("[%s] %RU32 samples captured\n", pHstStream->szName, cSamplesCaptured)); 602 749 603 750 if (cSamplesCaptured) … … 609 756 && cSamplesMixed) 610 757 { 611 Log FlowFunc(("[%s] %RU32 captured samples mixed\n", pHstStream->szName, cSamplesMixed));758 Log3Func(("[%s] %RU32 captured samples mixed\n", pHstStream->szName, cSamplesMixed)); 612 759 } 613 760 } … … 628 775 && cSamplesMixed) 629 776 { 630 Log FlowFunc(("[%s] %RU32 samples mixed\n", pHstStream->szName, cSamplesMixed));777 Log3Func(("[%s] %RU32 samples mixed\n", pHstStream->szName, cSamplesMixed)); 631 778 } 632 779 … … 635 782 } 636 783 637 Log FlowFunc(("[%s] %RU32 live samples\n", pHstStream->szName, cSamplesLive));784 Log3Func(("[%s] %RU32 live samples\n", pHstStream->szName, cSamplesLive)); 638 785 639 786 if (!cSamplesLive) /* No live samples (anymore)? */ … … 677 824 /* pcSamplesPlayed is optional. */ 678 825 826 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 827 828 int rc = RTCritSectEnter(&pThis->CritSect); 829 if (RT_FAILURE(rc)) 830 return rc; 831 679 832 AssertMsg(pStream->enmDir == PDMAUDIODIR_OUT, 680 833 ("Stream '%s' is not an output stream and therefore cannot be played back (direction is 0x%x)\n", 681 834 pStream->szName, pStream->enmDir)); 682 835 683 AssertMsg(pStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED, 684 ("Unable to play stream '%s' (status is 0x%x)\n", pStream->szName, pStream->fStatus)); 685 686 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 687 688 int rc = RTCritSectEnter(&pThis->CritSect); 689 if (RT_FAILURE(rc)) 690 return rc; 836 Log3Func(("[%s]\n", pStream->szName)); 691 837 692 838 uint32_t cSamplesPlayed = 0; … … 713 859 AssertPtr(pGstStream); 714 860 861 PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream); 862 if (!(strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)) 863 { 864 LogFunc(("[%s] Backend not initialized (anymore), re-initializing ...\n", pHstStream->szName)); 865 rc = drvAudioStreamReInitInternal(pThis, pStream); 866 break; 867 } 868 715 869 uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf); 716 870 if (cSamplesLive) 717 871 { 718 PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);719 if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)872 if ( (strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 873 && (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE)) 720 874 { 721 875 rc = pThis->pHostDrvAudio->pfnStreamPlay(pThis->pHostDrvAudio, pHstStream, &cSamplesPlayed); … … 727 881 } 728 882 729 Log FlowFunc(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesPlayed, rc));883 Log3Func(("[%s] strmSts=0x%x, cSamplesPlayed=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesPlayed, rc)); 730 884 } 731 885 … … 768 922 uint32_t *pcSamplesCaptured) 769 923 { 924 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 925 926 int rc = RTCritSectEnter(&pThis->CritSect); 927 if (RT_FAILURE(rc)) 928 return rc; 929 770 930 AssertMsg(pStream->enmDir == PDMAUDIODIR_IN, 771 931 ("Stream '%s' is not an input stream and therefore cannot be captured (direction is 0x%x)\n", 772 932 pStream->szName, pStream->enmDir)); 773 933 774 AssertMsg(pStream->fStatus & PDMAUDIOSTRMSTS_FLAG_INITIALIZED, 775 ("Unable to capture stream '%s' (status is 0x%x)\n", pStream->szName, pStream->fStatus)); 776 777 PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface); 778 779 int rc = RTCritSectEnter(&pThis->CritSect); 780 if (RT_FAILURE(rc)) 781 return rc; 782 783 LogFlowFunc(("[%s]\n", pStream->szName)); 934 Log3Func(("[%s]\n", pStream->szName)); 784 935 785 936 uint32_t cSamplesCaptured = 0; … … 806 957 AssertPtr(pGstStream); 807 958 959 PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream); 960 if (!(strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED)) 961 { 962 LogFunc(("[%s] Backend not initialized (anymore), re-initializing ...\n", pHstStream->szName)); 963 rc = drvAudioStreamReInitInternal(pThis, pStream); 964 break; 965 } 966 808 967 uint32_t cSamplesLive = AudioMixBufLive(&pGstStream->MixBuf); 809 968 if (!cSamplesLive) 810 969 { 811 PDMAUDIOSTRMSTS strmSts = pThis->pHostDrvAudio->pfnStreamGetStatus(pThis->pHostDrvAudio, pHstStream);812 if (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_READABLE)970 if ( (strmSts & PDMAUDIOSTRMSTS_FLAG_INITIALIZED) 971 && (strmSts & PDMAUDIOSTRMSTS_FLAG_DATA_READABLE)) 813 972 { 814 973 rc = pThis->pHostDrvAudio->pfnStreamCapture(pThis->pHostDrvAudio, pHstStream, &cSamplesCaptured); … … 820 979 } 821 980 822 Log FlowFunc(("[%s] strmSts=0x%x, cSamplesCaptured=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesCaptured, rc));981 Log3Func(("[%s] strmSts=0x%x, cSamplesCaptured=%RU32, rc=%Rrc\n", pHstStream->szName, strmSts, cSamplesCaptured, rc)); 823 982 } 824 983 … … 1032 1191 PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO); 1033 1192 1034 LogFlowFunc(("enmCmd=% ld\n", enmCmd));1193 LogFlowFunc(("enmCmd=%RU32\n", enmCmd)); 1035 1194 1036 1195 if (!pThis->pHostDrvAudio) … … 1120 1279 } 1121 1280 1122 LogFlowFunc(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n", 1123 cRead, AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cRead), rc)); 1281 Log3Func(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n", cRead, AUDIOMIXBUF_S2B(&pGstStream->MixBuf, cRead), rc)); 1124 1282 1125 1283 int rc2 = RTCritSectLeave(&pThis->CritSect); … … 1183 1341 { 1184 1342 if (!pThis->cStreamsFreeIn) 1185 { 1186 LogFlowFunc(("No more input streams free to use, bailing out\n")); 1187 RC_BREAK(VERR_AUDIO_NO_FREE_INPUT_STREAMS); 1188 } 1343 LogFunc(("Warning: No more input streams free to use\n")); 1189 1344 1190 1345 /* Validate backend configuration. */ 1191 1346 if (!pThis->BackendCfg.cbStreamIn) 1192 1347 { 1193 LogF lowFunc(("Backend input configuration not valid, bailing out\n"));1348 LogFunc(("Backend input configuration not valid, bailing out\n")); 1194 1349 RC_BREAK(VERR_INVALID_PARAMETER); 1195 1350 } … … 1228 1383 1229 1384 /* 1230 * Createhost stream.1385 * Init host stream. 1231 1386 */ 1232 1233 1387 RTStrPrintf(pHstStrm->szName, RT_ELEMENTS(pHstStrm->szName), "%s (Host)", 1234 1388 strlen(pCfgHost->szName) ? pCfgHost->szName : "<Untitled>"); 1235 1389 1236 /* Note: Direction is always from child -> parent. */ 1237 uint32_t cSamples = 0; 1238 rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pHstStrm, pCfgHost, &cSamples); 1239 if (RT_FAILURE(rc)) 1240 { 1241 LogFlowFunc(("Initializing host backend failed with rc=%Rrc\n", rc)); 1242 break; 1243 } 1244 1245 pHstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1246 pHstStrm->pPair = pGstStrm; 1247 1248 rc = DrvAudioHlpStreamCfgToProps(pCfgHost, &pHstStrm->Props); 1249 AssertRCBreak(rc); 1250 1251 rc = AudioMixBufInit(&pHstStrm->MixBuf, pHstStrm->szName, &pHstStrm->Props, cSamples * 4); 1252 AssertRCBreak(rc); 1390 pHstStrm->pPair = pGstStrm; 1253 1391 1254 1392 /* 1255 * Createguest stream.1393 * Init guest stream. 1256 1394 */ 1257 1258 1395 RTStrPrintf(pGstStrm->szName, RT_ELEMENTS(pGstStrm->szName), "%s (Guest)", 1259 1396 strlen(pCfgGuest->szName) ? pCfgGuest->szName : "<Untitled>"); 1260 1397 1261 rc = DrvAudioHlpStreamCfgToProps(pCfgGuest, &pGstStrm->Props); 1262 AssertRCBreak(rc); 1263 1264 rc = AudioMixBufInit(&pGstStrm->MixBuf, pGstStrm->szName, &pGstStrm->Props, cSamples * 2); 1265 if (RT_SUCCESS(rc)) 1266 { 1267 if (pCfgGuest->enmDir == PDMAUDIODIR_IN) 1268 { 1269 /* Host (Parent) -> Guest (Child). */ 1270 rc = AudioMixBufLinkTo(&pHstStrm->MixBuf, &pGstStrm->MixBuf); 1271 } 1272 else 1273 { 1274 /* Guest (Parent) -> Host (Child). */ 1275 rc = AudioMixBufLinkTo(&pGstStrm->MixBuf, &pHstStrm->MixBuf); 1276 } 1277 } 1278 1279 pGstStrm->fStatus |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED; 1280 pGstStrm->pPair = pHstStrm; 1281 1282 AssertRCBreak(rc); 1398 pGstStrm->fStatus = pHstStrm->fStatus; /* Reflect the host stream's status. */ 1399 pGstStrm->pPair = pHstStrm; 1400 1401 /* 1402 * Try to init the rest. 1403 */ 1404 rc = drvAudioStreamInitInternal(pThis, pHstStrm, pCfgHost, pCfgGuest); 1405 if (RT_FAILURE(rc)) 1406 { 1407 LogFlowFunc(("Stream not available (yet)\n")); 1408 rc = VINF_SUCCESS; 1409 } 1283 1410 1284 1411 } while (0); … … 1311 1438 if (pCfgHost->enmDir == PDMAUDIODIR_IN) 1312 1439 { 1313 Assert(pThis->cStreamsFreeIn);1314 pThis->cStreamsFreeIn--;1440 if (pThis->cStreamsFreeIn) 1441 pThis->cStreamsFreeIn--; 1315 1442 } 1316 1443 else /* Out */ 1317 1444 { 1318 Assert(pThis->cStreamsFreeOut);1319 pThis->cStreamsFreeOut--;1445 if (pThis->cStreamsFreeOut) 1446 pThis->cStreamsFreeOut--; 1320 1447 } 1321 1448 … … 1401 1528 cReadable = AudioMixBufLive(&pGstStream->MixBuf); 1402 1529 1403 Log FlowFunc(("[%s] cbReadable=%RU32\n", pHstStream->szName, cReadable));1530 Log3Func(("[%s] cbReadable=%RU32\n", pHstStream->szName, cReadable)); 1404 1531 1405 1532 rc2 = RTCritSectLeave(&pThis->CritSect); … … 1438 1565 cWritable = AudioMixBufFreeBytes(&pGstStream->MixBuf); 1439 1566 1440 Log FlowFunc(("[%s] cWritable=%RU32\n", pHstStream->szName, cWritable));1567 Log3Func(("[%s] cWritable=%RU32\n", pHstStream->szName, cWritable)); 1441 1568 1442 1569 rc2 = RTCritSectLeave(&pThis->CritSect); … … 1462 1589 PDMAUDIOSTRMSTS strmSts = pHstStream->fStatus; 1463 1590 1464 LogFlowFunc(("%s: strmSts=0x%x\n", pHstStream->szName, strmSts)); 1591 Log3Func(("%s: strmSts=0x%x\n", pHstStream->szName, strmSts)); 1592 1465 1593 rc2 = RTCritSectLeave(&pThis->CritSect); 1466 1594 AssertRC(rc2); -
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r61729 r61764 354 354 355 355 static int coreAudioInitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcSamples); 356 static int coreAudioReinitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream);357 356 static int coreAudioInitOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcSamples); 358 static int coreAudioReinitOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream);359 357 static int coreAudioControlStreamIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 360 358 static int coreAudioControlStreamOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd); 359 static int coreAudioCreateStreamIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples); 360 static int coreAudioCreateStreamOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, PPDMAUDIOSTREAMCFG pCfg, uint32_t *pcSamples); 361 361 static int coreAudioDestroyStreamIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream); 362 362 static int coreAudioDestroyStreamOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream); … … 380 380 int rc = VINF_SUCCESS; 381 381 382 uint8_t cDevs = 0; 383 382 384 do 383 385 { … … 456 458 { 457 459 LogRel2(("CoreAudio: Found %s device '%s'\n", fIn ? "recording" : "playback", pszName)); 458 459 if (pCfg) 460 { 461 if (fIn) 462 pCfg->cSources++; 463 else 464 pCfg->cSinks++; 465 } 460 cDevs++; 466 461 } 467 462 … … 477 472 478 473 } while (0); 474 475 if (fIn) 476 LogRel2(("CoreAudio: Found %RU8 capturing device(s)\n", cDevs)); 477 else 478 LogRel2(("CoreAudio: Found %RU8 playback device(s)\n", cDevs)); 479 480 if (pCfg) 481 { 482 if (fIn) 483 pCfg->cSources = cDevs; 484 else 485 pCfg->cSinks = cDevs; 486 } 479 487 480 488 LogFlowFuncLeaveRC(rc); … … 609 617 { 610 618 PCOREAUDIOSTREAMIN pStreamIn = pCbCtx->pIn; 619 AssertPtr(pStreamIn); 611 620 612 621 /* This listener is called on every change of the hardware … … 615 624 UInt32 uResp; 616 625 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, pProperty, 0, NULL, &uSize, &uResp); 617 618 626 if (err == noErr) 619 627 { 620 628 if (pStreamIn->deviceID != uResp) 621 629 { 622 LogRel (("CoreAudio: Default recording devicehas changed\n"));630 LogRel2(("CoreAudio: Default device for recording has changed\n")); 623 631 624 632 /* We move the reinitialization to the next input event. … … 634 642 { 635 643 PCOREAUDIOSTREAMOUT pStreamOut = pCbCtx->pOut; 644 AssertPtr(pStreamOut); 636 645 637 646 /* This listener is called on every change of the hardware … … 643 652 UInt32 uResp; 644 653 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &uResp); 645 646 654 if (err == noErr) 647 655 { 648 656 if (pStreamOut->deviceID != uResp) 649 657 { 650 LogRel (("CoreAudio: Default playback devicehas changed\n"));658 LogRel2(("CoreAudio: Default device for playback has changed\n")); 651 659 652 660 /* We move the reinitialization to the next input event. … … 675 683 } 676 684 677 static int coreAudioReinitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream)678 {679 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream;680 681 int rc = coreAudioDestroyStreamIn(pThis, &pStreamIn->Stream);682 if (RT_SUCCESS(rc))683 {684 rc = coreAudioInitIn(pThis, &pStreamIn->Stream, NULL /* pcSamples */);685 if (RT_SUCCESS(rc))686 rc = coreAudioControlStreamIn(pThis, &pStreamIn->Stream, PDMAUDIOSTREAMCMD_ENABLE);687 }688 689 if (RT_FAILURE(rc))690 LogRel(("CoreAudio: Unable to re-init input stream: %Rrc\n", rc));691 692 return rc;693 }694 695 static int coreAudioReinitOut(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream)696 {697 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream;698 699 int rc = coreAudioDestroyStreamOut(pThis, &pStreamOut->Stream);700 if (RT_SUCCESS(rc))701 {702 rc = coreAudioInitOut(pThis, &pStreamOut->Stream, NULL /* pcSamples */);703 if (RT_SUCCESS(rc))704 rc = coreAudioControlStreamOut(pThis, &pStreamOut->Stream, PDMAUDIOSTREAMCMD_ENABLE);705 }706 707 if (RT_FAILURE(rc))708 LogRel(("CoreAudio: Unable to re-init output stream: %Rrc\n", rc));709 710 return rc;711 }712 713 685 /* Callback for getting notified when some of the properties of an audio device has changed. */ 714 686 static DECLCALLBACK(OSStatus) coreAudioRecordingAudioDevicePropertyChanged(AudioObjectID propertyID, … … 882 854 && err != caConverterEOFDErr) 883 855 { 884 LogF lowFunc(("Failed to convert audio data (%RI32:%c%c%c%c)\n", err,885 856 LogFunc(("Failed to convert audio data (%RI32:%c%c%c%c)\n", err, 857 RT_BYTE4(err), RT_BYTE3(err), RT_BYTE2(err), RT_BYTE1(err))); 886 858 rc = VERR_IO_GEN_FAILURE; 887 859 break; … … 890 862 /* Check in any case what processed size is returned. It could be less than we expected. */ 891 863 cbToWrite = ioOutputDataPacketSize * pStreamIn->streamFormat.mBytesPerPacket; 864 865 Log3Func(("cbToWrite=%RU32\n", cbToWrite)); 892 866 893 867 /* Release the ring buffer, so the main thread could start reading this data. */ … … 932 906 size_t cbAvail = RT_MIN(cbDataSize, cbBufFree); 933 907 934 Log FlowFunc(("cbDataSize=%RU32, cbBufFree=%zu, cbAvail=%zu\n", cbDataSize, cbBufFree, cbAvail));908 Log3Func(("cbDataSize=%RU32, cbBufFree=%zu, cbAvail=%zu\n", cbDataSize, cbBufFree, cbAvail)); 935 909 936 910 /* Iterate as long as data is available. */ … … 957 931 } 958 932 959 Log FlowFunc(("cbWrittenTotal=%RU32, cbLeft=%zu\n", cbWrittenTotal, cbAvail));933 Log3Func(("cbWrittenTotal=%RU32, cbLeft=%zu\n", cbWrittenTotal, cbAvail)); 960 934 } 961 935 … … 968 942 } 969 943 970 LogFlowFuncLeaveRC(rc); 944 if (RT_FAILURE(rc)) 945 LogFunc(("Failed with rc=%Rrc\n", rc)); 946 971 947 return err; 972 948 } 949 950 # define CA_BREAK_STMT(stmt) \ 951 stmt; \ 952 break; 973 953 974 954 /** @todo Eventually split up this function, as this already is huge! */ 975 955 static int coreAudioInitIn(PDRVHOSTCOREAUDIO pThis, PPDMAUDIOSTREAM pStream, uint32_t *pcSamples) 976 956 { 977 OSStatus err = noErr;957 int rc = VINF_SUCCESS; 978 958 979 959 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 980 981 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT); 982 983 UInt32 uSize = 0; 984 if (pStreamIn->deviceID == kAudioDeviceUnknown) 985 { 986 /* Fetch the default audio recording device currently in use. */ 987 AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice, 988 kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; 989 uSize = sizeof(pStreamIn->deviceID); 990 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &pStreamIn->deviceID); 991 if (err != noErr) 992 { 993 LogRel(("CoreAudio: Unable to determine default recording device (%RI32)\n", err)); 994 return VERR_NOT_FOUND; 995 } 996 } 997 998 /* 999 * Try to get the name of the recording device and log it. It's not fatal if it fails. 1000 */ 1001 CFStringRef strTemp; 1002 1003 AudioObjectPropertyAddress propAdr = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal, 1004 kAudioObjectPropertyElementMaster }; 1005 uSize = sizeof(CFStringRef); 1006 err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp); 1007 if (err == noErr) 1008 { 1009 char *pszDevName = NULL; 1010 err = coreAudioCFStringToCString(strTemp, &pszDevName); 960 UInt32 cSamples = 0; 961 962 do 963 { 964 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_IN_INIT); 965 966 OSStatus err; 967 968 UInt32 uSize = 0; 969 if (pStreamIn->deviceID == kAudioDeviceUnknown) 970 { 971 /* Fetch the default audio recording device currently in use. */ 972 AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice, 973 kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; 974 uSize = sizeof(pStreamIn->deviceID); 975 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propAdr, 0, NULL, &uSize, &pStreamIn->deviceID); 976 if (err != noErr) 977 { 978 LogRel2(("CoreAudio: Unable to determine default recording device (%RI32)\n", err)); 979 return VERR_AUDIO_NO_FREE_INPUT_STREAMS; 980 } 981 } 982 983 if (pStreamIn->deviceID == kAudioDeviceUnknown) 984 { 985 LogFlowFunc(("No default recording device found\n")); 986 return VERR_AUDIO_NO_FREE_INPUT_STREAMS; 987 } 988 989 /* 990 * Try to get the name of the recording device and log it. It's not fatal if it fails. 991 */ 992 CFStringRef strTemp; 993 994 AudioObjectPropertyAddress propAdr = { kAudioObjectPropertyName, kAudioObjectPropertyScopeGlobal, 995 kAudioObjectPropertyElementMaster }; 996 uSize = sizeof(CFStringRef); 997 err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp); 1011 998 if (err == noErr) 1012 999 { 1013 CFRelease(strTemp); 1014 1015 /* Get the device' UUID. */ 1016 propAdr.mSelector = kAudioDevicePropertyDeviceUID; 1017 err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp); 1000 char *pszDevName = NULL; 1001 err = coreAudioCFStringToCString(strTemp, &pszDevName); 1018 1002 if (err == noErr) 1019 1003 { 1020 char *pszUID = NULL; 1021 err = coreAudioCFStringToCString(strTemp, &pszUID); 1004 CFRelease(strTemp); 1005 1006 /* Get the device' UUID. */ 1007 propAdr.mSelector = kAudioDevicePropertyDeviceUID; 1008 err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &strTemp); 1022 1009 if (err == noErr) 1023 1010 { 1024 CFRelease(strTemp); 1025 LogRel(("CoreAudio: Using recording device: %s (UID: %s)\n", pszDevName, pszUID)); 1026 1027 RTMemFree(pszUID); 1011 char *pszUID = NULL; 1012 err = coreAudioCFStringToCString(strTemp, &pszUID); 1013 if (err == noErr) 1014 { 1015 CFRelease(strTemp); 1016 LogRel(("CoreAudio: Using recording device: %s (UID: %s)\n", pszDevName, pszUID)); 1017 1018 RTMemFree(pszUID); 1019 } 1028 1020 } 1029 } 1030 1031 RTMemFree(pszDevName); 1032 } 1033 } 1034 else 1035 { 1036 /* This is not fatal, can happen for some Macs. */ 1037 LogRel2(("CoreAudio: Unable to determine recording device name (%RI32)\n", err)); 1038 } 1039 1040 /* Get the default frames buffer size, so that we can setup our internal buffers. */ 1041 UInt32 cFrames; 1042 uSize = sizeof(cFrames); 1043 propAdr.mSelector = kAudioDevicePropertyBufferFrameSize; 1044 propAdr.mScope = kAudioDevicePropertyScopeInput; 1045 err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &cFrames); 1046 if (err != noErr) 1047 { 1048 /* Can happen if no recording device is available by default. Happens on some Macs, 1049 * so don't log this by default to not scare people. */ 1050 LogRel2(("CoreAudio: Failed to determine frame buffer size of the audio recording device (%RI32)\n", err)); 1051 return VERR_AUDIO_BACKEND_INIT_FAILED; 1052 } 1053 1054 /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */ 1055 err = coreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames); 1056 if (err != noErr) 1057 { 1058 LogRel(("CoreAudio: Failed to set frame buffer size for the audio recording device (%RI32)\n", err)); 1059 return VERR_AUDIO_BACKEND_INIT_FAILED; 1060 } 1061 1062 LogFlowFunc(("cFrames=%RU32\n", cFrames)); 1063 1064 ComponentDescription cd; 1065 RT_ZERO(cd); 1066 cd.componentType = kAudioUnitType_Output; 1067 cd.componentSubType = kAudioUnitSubType_HALOutput; 1068 cd.componentManufacturer = kAudioUnitManufacturer_Apple; 1069 1070 /* Try to find the default HAL output component. */ 1071 Component cp = FindNextComponent(NULL, &cd); 1072 if (cp == 0) 1073 { 1074 LogRel(("CoreAudio: Failed to find HAL output component\n")); /** @todo Return error value? */ 1075 return VERR_AUDIO_BACKEND_INIT_FAILED; 1076 } 1077 1078 /* Open the default HAL output component. */ 1079 err = OpenAComponent(cp, &pStreamIn->audioUnit); 1080 if (err != noErr) 1081 { 1082 LogRel(("CoreAudio: Failed to open output component (%RI32)\n", err)); 1083 return VERR_AUDIO_BACKEND_INIT_FAILED; 1084 } 1085 1086 /* Switch the I/O mode for input to on. */ 1087 UInt32 uFlag = 1; 1088 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1089 1, &uFlag, sizeof(uFlag)); 1090 if (err != noErr) 1091 { 1092 LogRel(("CoreAudio: Failed to disable input I/O mode for input stream (%RI32)\n", err)); 1093 return VERR_AUDIO_BACKEND_INIT_FAILED; 1094 } 1095 1096 /* Switch the I/O mode for output to off. This is important, as this is a pure input stream. */ 1097 uFlag = 0; 1098 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 1099 0, &uFlag, sizeof(uFlag)); 1100 if (err != noErr) 1101 { 1102 LogRel(("CoreAudio: Failed to disable output I/O mode for input stream (%RI32)\n", err)); 1103 return VERR_AUDIO_BACKEND_INIT_FAILED; 1104 } 1105 1106 /* Set the default audio recording device as the device for the new AudioUnit. */ 1107 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 1108 0, &pStreamIn->deviceID, sizeof(pStreamIn->deviceID)); 1109 if (err != noErr) 1110 { 1111 LogRel(("CoreAudio: Failed to set current device (%RI32)\n", err)); 1112 return VERR_AUDIO_BACKEND_INIT_FAILED; 1113 } 1114 1115 /* 1116 * CoreAudio will inform us on a second thread for new incoming audio data. 1117 * Therefor register a callback function which will process the new data. 1118 */ 1119 AURenderCallbackStruct cb; 1120 RT_ZERO(cb); 1121 cb.inputProc = coreAudioRecordingCb; 1122 cb.inputProcRefCon = pStreamIn; 1123 1124 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1125 0, &cb, sizeof(cb)); 1126 if (err != noErr) 1127 { 1128 LogRel(("CoreAudio: Failed to register input callback (%RI32)\n", err)); 1129 return VERR_AUDIO_BACKEND_INIT_FAILED; 1130 } 1131 1132 /* Fetch the current stream format of the device. */ 1133 uSize = sizeof(pStreamIn->deviceFormat); 1134 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1135 1, &pStreamIn->deviceFormat, &uSize); 1136 if (err != noErr) 1137 { 1138 LogRel(("CoreAudio: Failed to get device format (%RI32)\n", err)); 1139 return VERR_AUDIO_BACKEND_INIT_FAILED; 1140 } 1141 1142 /* Create an AudioStreamBasicDescription based on our required audio settings. */ 1143 coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat); 1144 1145 coreAudioPrintASBDesc("CoreAudio: recording device", &pStreamIn->deviceFormat); 1146 coreAudioPrintASBDesc("CoreAudio: Input stream", &pStreamIn->streamFormat); 1147 1148 /* If the frequency of the device is different from the requested one we 1149 * need a converter. The same count if the number of channels is different. */ 1150 if ( pStreamIn->deviceFormat.mSampleRate != pStreamIn->streamFormat.mSampleRate 1151 || pStreamIn->deviceFormat.mChannelsPerFrame != pStreamIn->streamFormat.mChannelsPerFrame) 1152 { 1153 LogRel(("CoreAudio: Input converter is active\n")); 1154 1155 err = AudioConverterNew(&pStreamIn->deviceFormat, &pStreamIn->streamFormat, &pStreamIn->pConverter); 1156 if (RT_UNLIKELY(err != noErr)) 1157 { 1158 LogRel(("CoreAudio: Failed to create the audio converter (%RI32)\n", err)); 1159 return VERR_AUDIO_BACKEND_INIT_FAILED; 1160 } 1161 1162 if ( pStreamIn->deviceFormat.mChannelsPerFrame == 1 /* Mono */ 1163 && pStreamIn->streamFormat.mChannelsPerFrame == 2 /* Stereo */) 1164 { 1165 /* 1166 * If the channel count is different we have to tell this the converter 1167 * and supply a channel mapping. For now we only support mapping 1168 * from mono to stereo. For all other cases the core audio defaults 1169 * are used, which means dropping additional channels in most 1170 * cases. 1171 */ 1172 const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo, */ 1173 1174 err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterChannelMap, sizeof(channelMap), channelMap); 1021 1022 RTMemFree(pszDevName); 1023 } 1024 } 1025 else 1026 { 1027 /* This is not fatal, can happen for some Macs. */ 1028 LogRel2(("CoreAudio: Unable to determine recording device name (%RI32)\n", err)); 1029 } 1030 1031 /* Get the default frames buffer size, so that we can setup our internal buffers. */ 1032 UInt32 cFrames; 1033 uSize = sizeof(cFrames); 1034 propAdr.mSelector = kAudioDevicePropertyBufferFrameSize; 1035 propAdr.mScope = kAudioDevicePropertyScopeInput; 1036 err = AudioObjectGetPropertyData(pStreamIn->deviceID, &propAdr, 0, NULL, &uSize, &cFrames); 1037 if (err != noErr) 1038 { 1039 /* Can happen if no recording device is available by default. Happens on some Macs, 1040 * so don't log this by default to not scare people. */ 1041 LogRel2(("CoreAudio: Failed to determine frame buffer size of the audio recording device (%RI32)\n", err)); 1042 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1043 } 1044 1045 /* Set the frame buffer size and honor any minimum/maximum restrictions on the device. */ 1046 err = coreAudioSetFrameBufferSize(pStreamIn->deviceID, true /* fInput */, cFrames, &cFrames); 1047 if (err != noErr) 1048 { 1049 LogRel(("CoreAudio: Failed to set frame buffer size for the audio recording device (%RI32)\n", err)); 1050 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1051 } 1052 1053 LogFlowFunc(("cFrames=%RU32\n", cFrames)); 1054 1055 ComponentDescription cd; 1056 RT_ZERO(cd); 1057 cd.componentType = kAudioUnitType_Output; 1058 cd.componentSubType = kAudioUnitSubType_HALOutput; 1059 cd.componentManufacturer = kAudioUnitManufacturer_Apple; 1060 1061 /* Try to find the default HAL output component. */ 1062 Component cp = FindNextComponent(NULL, &cd); 1063 if (cp == 0) 1064 { 1065 LogRel(("CoreAudio: Failed to find HAL output component\n")); /** @todo Return error value? */ 1066 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1067 } 1068 1069 /* Open the default HAL output component. */ 1070 err = OpenAComponent(cp, &pStreamIn->audioUnit); 1071 if (err != noErr) 1072 { 1073 LogRel(("CoreAudio: Failed to open output component (%RI32)\n", err)); 1074 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1075 } 1076 1077 /* Switch the I/O mode for input to on. */ 1078 UInt32 uFlag = 1; 1079 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1080 1, &uFlag, sizeof(uFlag)); 1081 if (err != noErr) 1082 { 1083 LogRel(("CoreAudio: Failed to disable input I/O mode for input stream (%RI32)\n", err)); 1084 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1085 } 1086 1087 /* Switch the I/O mode for output to off. This is important, as this is a pure input stream. */ 1088 uFlag = 0; 1089 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 1090 0, &uFlag, sizeof(uFlag)); 1091 if (err != noErr) 1092 { 1093 LogRel(("CoreAudio: Failed to disable output I/O mode for input stream (%RI32)\n", err)); 1094 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1095 } 1096 1097 /* Set the default audio recording device as the device for the new AudioUnit. */ 1098 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 1099 0, &pStreamIn->deviceID, sizeof(pStreamIn->deviceID)); 1100 if (err != noErr) 1101 { 1102 LogRel(("CoreAudio: Failed to set current device (%RI32)\n", err)); 1103 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1104 } 1105 1106 /* 1107 * CoreAudio will inform us on a second thread for new incoming audio data. 1108 * Therefore register a callback function which will process the new data. 1109 */ 1110 AURenderCallbackStruct cb; 1111 RT_ZERO(cb); 1112 cb.inputProc = coreAudioRecordingCb; 1113 cb.inputProcRefCon = pStreamIn; 1114 1115 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 1116 0, &cb, sizeof(cb)); 1117 if (err != noErr) 1118 { 1119 LogRel(("CoreAudio: Failed to register input callback (%RI32)\n", err)); 1120 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1121 } 1122 1123 /* Fetch the current stream format of the device. */ 1124 uSize = sizeof(pStreamIn->deviceFormat); 1125 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1126 1, &pStreamIn->deviceFormat, &uSize); 1127 if (err != noErr) 1128 { 1129 LogRel(("CoreAudio: Failed to get device format (%RI32)\n", err)); 1130 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1131 } 1132 1133 /* Create an AudioStreamBasicDescription based on our required audio settings. */ 1134 coreAudioPCMInfoToASBDesc(&pStreamIn->Stream.Props, &pStreamIn->streamFormat); 1135 1136 coreAudioPrintASBDesc("CoreAudio: Recording device", &pStreamIn->deviceFormat); 1137 coreAudioPrintASBDesc("CoreAudio: Recording stream", &pStreamIn->streamFormat); 1138 1139 /* If the frequency of the device is different from the requested one we 1140 * need a converter. The same count if the number of channels is different. */ 1141 if ( pStreamIn->deviceFormat.mSampleRate != pStreamIn->streamFormat.mSampleRate 1142 || pStreamIn->deviceFormat.mChannelsPerFrame != pStreamIn->streamFormat.mChannelsPerFrame) 1143 { 1144 LogRel(("CoreAudio: Input converter is active\n")); 1145 1146 err = AudioConverterNew(&pStreamIn->deviceFormat, &pStreamIn->streamFormat, &pStreamIn->pConverter); 1147 if (RT_UNLIKELY(err != noErr)) 1148 { 1149 LogRel(("CoreAudio: Failed to create the audio converter (%RI32)\n", err)); 1150 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1151 } 1152 1153 if ( pStreamIn->deviceFormat.mChannelsPerFrame == 1 /* Mono */ 1154 && pStreamIn->streamFormat.mChannelsPerFrame == 2 /* Stereo */) 1155 { 1156 /* 1157 * If the channel count is different we have to tell this the converter 1158 * and supply a channel mapping. For now we only support mapping 1159 * from mono to stereo. For all other cases the core audio defaults 1160 * are used, which means dropping additional channels in most 1161 * cases. 1162 */ 1163 const SInt32 channelMap[2] = {0, 0}; /* Channel map for mono -> stereo, */ 1164 1165 err = AudioConverterSetProperty(pStreamIn->pConverter, kAudioConverterChannelMap, sizeof(channelMap), channelMap); 1166 if (err != noErr) 1167 { 1168 LogRel(("CoreAudio: Failed to set channel mapping (mono -> stereo) for the audio input converter (%RI32)\n", err)); 1169 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1170 } 1171 } 1172 #if 0 1173 /* Set sample rate converter quality to maximum. */ 1174 uFlag = kAudioConverterQuality_Max; 1175 err = AudioConverterSetProperty(pStreamIn->converter, kAudioConverterSampleRateConverterQuality, 1176 sizeof(uFlag), &uFlag); 1175 1177 if (err != noErr) 1176 { 1177 LogRel(("CoreAudio: Failed to set channel mapping (mono -> stereo) for the audio input converter (%RI32)\n", err)); 1178 return VERR_AUDIO_BACKEND_INIT_FAILED; 1179 } 1180 } 1181 #if 0 1182 /* Set sample rate converter quality to maximum */ 1183 uFlag = kAudioConverterQuality_Max; 1184 err = AudioConverterSetProperty(pStreamIn->converter, kAudioConverterSampleRateConverterQuality, 1185 sizeof(uFlag), &uFlag); 1178 LogRel(("CoreAudio: Failed to set input audio converter quality to the maximum (%RI32)\n", err)); 1179 #endif 1180 /* Set the new format description for the stream. */ 1181 err = AudioUnitSetProperty(pStreamIn->audioUnit, 1182 kAudioUnitProperty_StreamFormat, 1183 kAudioUnitScope_Output, 1184 1, 1185 &pStreamIn->deviceFormat, 1186 sizeof(pStreamIn->deviceFormat)); 1187 if (RT_UNLIKELY(err != noErr)) 1188 { 1189 LogRel(("CoreAudio: Failed to set input stream output format (%RI32)\n", err)); 1190 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1191 } 1192 1193 err = AudioUnitSetProperty(pStreamIn->audioUnit, 1194 kAudioUnitProperty_StreamFormat, 1195 kAudioUnitScope_Input, 1196 1, 1197 &pStreamIn->deviceFormat, 1198 sizeof(pStreamIn->deviceFormat)); 1199 if (RT_UNLIKELY(err != noErr)) 1200 { 1201 LogRel(("CoreAudio: Failed to set stream input format (%RI32)\n", err)); 1202 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1203 } 1204 } 1205 else 1206 { 1207 1208 /* Set the new output format description for the input stream. */ 1209 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1210 1, &pStreamIn->streamFormat, sizeof(pStreamIn->streamFormat)); 1211 if (err != noErr) 1212 { 1213 LogRel(("CoreAudio: Failed to set output format for input stream (%RI32)\n", err)); 1214 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1215 } 1216 } 1217 1218 /* 1219 * Also set the frame buffer size off the device on our AudioUnit. This 1220 * should make sure that the frames count which we receive in the render 1221 * thread is as we like. 1222 */ 1223 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1224 1, &cFrames, sizeof(cFrames)); 1186 1225 if (err != noErr) 1187 LogRel(("CoreAudio: Failed to set input audio converter quality to the maximum (%RI32)\n", err)); 1188 #endif 1189 1190 /* Set the new format description for the stream. */ 1191 err = AudioUnitSetProperty(pStreamIn->audioUnit, 1192 kAudioUnitProperty_StreamFormat, 1193 kAudioUnitScope_Output, 1194 1, 1195 &pStreamIn->deviceFormat, 1196 sizeof(pStreamIn->deviceFormat)); 1197 if (RT_UNLIKELY(err != noErr)) 1198 { 1199 LogRel(("CoreAudio: Failed to set input stream output format (%RI32)\n", err)); 1200 return VERR_AUDIO_BACKEND_INIT_FAILED; 1201 } 1202 1203 err = AudioUnitSetProperty(pStreamIn->audioUnit, 1204 kAudioUnitProperty_StreamFormat, 1205 kAudioUnitScope_Input, 1206 1, 1207 &pStreamIn->deviceFormat, 1208 sizeof(pStreamIn->deviceFormat)); 1209 if (RT_UNLIKELY(err != noErr)) 1210 { 1211 LogRel(("CoreAudio: Failed to set stream input format (%RI32)\n", err)); 1212 return VERR_AUDIO_BACKEND_INIT_FAILED; 1213 } 1214 } 1215 else 1216 { 1217 1218 /* Set the new output format description for the input stream. */ 1219 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1220 1, &pStreamIn->streamFormat, sizeof(pStreamIn->streamFormat)); 1226 { 1227 LogRel(("CoreAudio: Failed to set maximum frame buffer size for input stream (%RI32)\n", err)); 1228 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1229 } 1230 1231 /* Finally initialize the new AudioUnit. */ 1232 err = AudioUnitInitialize(pStreamIn->audioUnit); 1221 1233 if (err != noErr) 1222 1234 { 1223 LogRel(("CoreAudio: Failed to set output format for input stream (%RI32)\n", err)); 1224 return VERR_AUDIO_BACKEND_INIT_FAILED; 1225 } 1226 } 1227 1228 /* 1229 * Also set the frame buffer size off the device on our AudioUnit. This 1230 * should make sure that the frames count which we receive in the render 1231 * thread is as we like. 1232 */ 1233 err = AudioUnitSetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1234 1, &cFrames, sizeof(cFrames)); 1235 if (err != noErr) { 1236 LogRel(("CoreAudio: Failed to set maximum frame buffer size for input stream (%RI32)\n", err)); 1237 return VERR_AUDIO_BACKEND_INIT_FAILED; 1238 } 1239 1240 /* Finally initialize the new AudioUnit. */ 1241 err = AudioUnitInitialize(pStreamIn->audioUnit); 1242 if (err != noErr) 1243 { 1244 LogRel(("CoreAudio: Failed to initialize audio unit for input stream (%RI32)\n", err)); 1245 return VERR_AUDIO_BACKEND_INIT_FAILED; 1246 } 1247 1248 uSize = sizeof(pStreamIn->deviceFormat); 1249 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1250 1, &pStreamIn->deviceFormat, &uSize); 1251 if (err != noErr) 1252 { 1253 LogRel(("CoreAudio: Failed to get recording device format (%RI32)\n", err)); 1254 return VERR_AUDIO_BACKEND_INIT_FAILED; 1255 } 1256 1257 /* 1258 * There are buggy devices (e.g. my Bluetooth headset) which doesn't honor 1259 * the frame buffer size set in the previous calls. So finally get the 1260 * frame buffer size after the AudioUnit was initialized. 1261 */ 1262 uSize = sizeof(cFrames); 1263 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1264 0, &cFrames, &uSize); 1265 if (err != noErr) 1266 { 1267 LogRel(("CoreAudio: Failed to get maximum frame buffer size from input audio device (%RI32)\n", err)); 1268 return VERR_AUDIO_BACKEND_INIT_FAILED; 1269 } 1270 1271 /* Destroy any former internal ring buffer. */ 1272 if (pStreamIn->pBuf) 1273 { 1274 RTCircBufDestroy(pStreamIn->pBuf); 1275 pStreamIn->pBuf = NULL; 1276 } 1277 1278 /* Calculate the ratio between the device and the stream sample rate. */ 1279 pStreamIn->sampleRatio = pStreamIn->streamFormat.mSampleRate / pStreamIn->deviceFormat.mSampleRate; 1280 1281 /* Create the AudioBufferList structure with one buffer. */ 1282 pStreamIn->bufferList.mNumberBuffers = 1; 1283 /* Initialize the buffer to nothing. */ 1284 pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame; 1285 pStreamIn->bufferList.mBuffers[0].mDataByteSize = 0; 1286 pStreamIn->bufferList.mBuffers[0].mData = NULL; 1287 1288 int rc = VINF_SUCCESS; 1289 1290 /* 1291 * Make sure that the ring buffer is big enough to hold the recording 1292 * data. Compare the maximum frames per slice value with the frames 1293 * necessary when using the converter where the sample rate could differ. 1294 * The result is always multiplied by the channels per frame to get the 1295 * samples count. 1296 */ 1297 UInt32 cSamples = RT_MAX(cFrames, 1298 (cFrames * pStreamIn->deviceFormat.mBytesPerFrame * pStreamIn->sampleRatio) 1299 / pStreamIn->streamFormat.mBytesPerFrame) 1300 * pStreamIn->streamFormat.mChannelsPerFrame; 1301 if (!cSamples) 1302 { 1303 LogRel(("CoreAudio: Failed to determine samples buffer count input stream\n")); 1304 rc = VERR_INVALID_PARAMETER; 1305 } 1306 1307 /* Create the internal ring buffer. */ 1235 LogRel(("CoreAudio: Failed to initialize audio unit for input stream (%RI32)\n", err)); 1236 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1237 } 1238 1239 uSize = sizeof(pStreamIn->deviceFormat); 1240 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1241 1, &pStreamIn->deviceFormat, &uSize); 1242 if (err != noErr) 1243 { 1244 LogRel(("CoreAudio: Failed to get recording device format (%RI32)\n", err)); 1245 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1246 } 1247 1248 /* 1249 * There are buggy devices (e.g. my Bluetooth headset) which doesn't honor 1250 * the frame buffer size set in the previous calls. So finally get the 1251 * frame buffer size after the AudioUnit was initialized. 1252 */ 1253 uSize = sizeof(cFrames); 1254 err = AudioUnitGetProperty(pStreamIn->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1255 0, &cFrames, &uSize); 1256 if (err != noErr) 1257 { 1258 LogRel(("CoreAudio: Failed to get maximum frame buffer size from input audio device (%RI32)\n", err)); 1259 CA_BREAK_STMT(rc = VERR_AUDIO_BACKEND_INIT_FAILED); 1260 } 1261 1262 /* Destroy any former internal ring buffer. */ 1263 if (pStreamIn->pBuf) 1264 { 1265 RTCircBufDestroy(pStreamIn->pBuf); 1266 pStreamIn->pBuf = NULL; 1267 } 1268 1269 /* Calculate the ratio between the device and the stream sample rate. */ 1270 pStreamIn->sampleRatio = pStreamIn->streamFormat.mSampleRate / pStreamIn->deviceFormat.mSampleRate; 1271 1272 /* Create the AudioBufferList structure with one buffer. */ 1273 pStreamIn->bufferList.mNumberBuffers = 1; 1274 /* Initialize the buffer to nothing. */ 1275 pStreamIn->bufferList.mBuffers[0].mNumberChannels = pStreamIn->streamFormat.mChannelsPerFrame; 1276 pStreamIn->bufferList.mBuffers[0].mDataByteSize = 0; 1277 pStreamIn->bufferList.mBuffers[0].mData = NULL; 1278 1279 /* 1280 * Make sure that the ring buffer is big enough to hold the recording 1281 * data. Compare the maximum frames per slice value with the frames 1282 * necessary when using the converter where the sample rate could differ. 1283 * The result is always multiplied by the channels per frame to get the 1284 * samples count. 1285 */ 1286 cSamples = RT_MAX(cFrames, 1287 (cFrames * pStreamIn->deviceFormat.mBytesPerFrame * pStreamIn->sampleRatio) 1288 / pStreamIn->streamFormat.mBytesPerFrame) 1289 * pStreamIn->streamFormat.mChannelsPerFrame; 1290 if (!cSamples) 1291 { 1292 LogRel(("CoreAudio: Failed to determine samples buffer count input stream\n")); 1293 CA_BREAK_STMT(rc = VERR_INVALID_PARAMETER); 1294 } 1295 1296 /* Create the internal ring buffer. */ 1297 rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift); 1298 1299 } while (0); 1300 1308 1301 if (RT_SUCCESS(rc)) 1309 rc = RTCircBufCreate(&pStreamIn->pBuf, cSamples << pStream->Props.cShift); 1310 if (RT_SUCCESS(rc)) 1311 { 1312 #ifdef DEBUG 1313 propAdr.mSelector = kAudioDeviceProcessorOverload; 1314 propAdr.mScope = kAudioUnitScope_Global; 1315 err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr, 1316 coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn); 1317 if (RT_UNLIKELY(err != noErr)) 1318 LogRel(("CoreAudio: Failed to add the processor overload listener for input stream (%RI32)\n", err)); 1319 #endif /* DEBUG */ 1320 propAdr.mSelector = kAudioDevicePropertyNominalSampleRate; 1321 propAdr.mScope = kAudioUnitScope_Global; 1322 err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr, 1323 coreAudioRecordingAudioDevicePropertyChanged, (void *)pStreamIn); 1324 /* Not fatal. */ 1325 if (RT_UNLIKELY(err != noErr)) 1326 LogRel(("CoreAudio: Failed to register sample rate changed listener for input stream (%RI32)\n", err)); 1327 } 1328 1329 if (RT_SUCCESS(rc)) 1330 { 1331 /* Set callback context. */ 1332 pStreamIn->cbCtx.pThis = pThis; 1333 pStreamIn->cbCtx.enmDir = PDMAUDIODIR_IN; 1334 pStreamIn->cbCtx.pIn = pStreamIn; 1335 1302 { 1336 1303 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_INIT); 1304 1305 LogFunc(("cSamples=%RU32\n", cSamples)); 1337 1306 1338 1307 if (pcSamples) … … 1348 1317 pStreamIn->pBuf = NULL; 1349 1318 } 1350 } 1351 1352 LogFunc(("cSamples=%RU32, rc=%Rrc\n", cSamples, rc)); 1319 1320 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT); 1321 } 1322 1323 LogFunc(("rc=%Rrc\n", rc)); 1353 1324 return rc; 1354 1325 } … … 1616 1587 if (RT_SUCCESS(rc)) 1617 1588 { 1618 /* Set callback context. */1619 pStreamOut->cbCtx.pThis = pThis;1620 pStreamOut->cbCtx.enmDir = PDMAUDIODIR_OUT;1621 pStreamOut->cbCtx.pOut = pStreamOut;1622 1623 1589 ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_INIT); 1624 1590 … … 1650 1616 { 1651 1617 #ifdef DEBUG 1652 case kAudioDeviceProcessorOverload:1653 {1654 Log2(("CoreAudio: [Output] Processor overload detected!\n"));1655 break;1656 }1657 1618 #endif /* DEBUG */ 1658 1619 default: … … 1671 1632 AudioBufferList *pBufData) 1672 1633 { 1673 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser;1674 PPDMAUDIOSTREAM pStream= &pStreamOut->Stream;1634 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pvUser; 1635 PPDMAUDIOSTREAM pStream = &pStreamOut->Stream; 1675 1636 1676 1637 if (ASMAtomicReadU32(&pStreamOut->status) != CA_STATUS_INIT) … … 1681 1642 1682 1643 /* How much space is used in the ring buffer? */ 1683 size_t cb DataAvail= RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize);1684 if (!cb DataAvail)1644 size_t cbToRead = RT_MIN(RTCircBufUsed(pStreamOut->pBuf), pBufData->mBuffers[0].mDataByteSize); 1645 if (!cbToRead) 1685 1646 { 1686 1647 pBufData->mBuffers[0].mDataByteSize = 0; … … 1689 1650 1690 1651 uint8_t *pbSrc = NULL; 1691 size_t cbRead = 0; 1692 size_t cbToRead; 1693 while (cbDataAvail) 1652 size_t cbRead = 0; 1653 1654 size_t cbLeft = cbToRead; 1655 while (cbLeft) 1694 1656 { 1695 1657 /* Try to acquire the necessary block from the ring buffer. */ 1696 RTCircBufAcquireReadBlock(pStreamOut->pBuf, cb DataAvail, (void **)&pbSrc, &cbToRead);1658 RTCircBufAcquireReadBlock(pStreamOut->pBuf, cbLeft, (void **)&pbSrc, &cbToRead); 1697 1659 1698 1660 /* Break if nothing is used anymore. */ … … 1710 1672 Assert(pBufData->mBuffers[0].mDataByteSize >= cbRead); 1711 1673 1712 Assert(cbToRead <= cb DataAvail);1713 cb DataAvail-= cbToRead;1674 Assert(cbToRead <= cbLeft); 1675 cbLeft -= cbToRead; 1714 1676 } 1715 1677 … … 1717 1679 pBufData->mBuffers[0].mDataByteSize = cbRead; 1718 1680 1719 LogFlowFunc((" CoreAudio: [Output] Read %zu / %zu bytes\n", cbRead, cbDataAvail));1681 LogFlowFunc(("Read %zu / %zu bytes\n", cbRead, cbToRead)); 1720 1682 1721 1683 return noErr; … … 1743 1705 PPDMAUDIOSAMPLE psDst; 1744 1706 1745 /* Check if the audio device should be reinitialized. If so do it. */1746 if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_REINIT)1747 coreAudioReinitIn(pThis, &pStreamIn->Stream);1748 1749 1707 if (ASMAtomicReadU32(&pStreamIn->status) != CA_STATUS_INIT) 1750 1708 { … … 1766 1724 size_t cbToRead; 1767 1725 1768 Log FlowFunc(("cbBuf=%zu, cbToWrite=%zu\n", cbBuf, cbToWrite));1726 Log3Func(("cbBuf=%zu, cbToWrite=%zu\n", cbBuf, cbToWrite)); 1769 1727 1770 1728 while (cbToWrite) … … 1796 1754 } 1797 1755 1798 Log FlowFunc(("cbToWrite=%zu, cbToRead=%zu, cbWrittenTotal=%RU32, rc=%Rrc\n", cbToWrite, cbToRead, cbWrittenTotal, rc));1756 Log3Func(("cbToWrite=%zu, cbToRead=%zu, cbWrittenTotal=%RU32, rc=%Rrc\n", cbToWrite, cbToRead, cbWrittenTotal, rc)); 1799 1757 } 1800 1758 while (0); … … 1807 1765 rc = AudioMixBufMixToParent(&pStream->MixBuf, cWrittenTotal, &cCaptured); 1808 1766 1809 LogFlowFunc(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc)); 1767 Log3Func(("cWrittenTotal=%RU32 (%RU32 bytes), cCaptured=%RU32, rc=%Rrc\n", cWrittenTotal, cbWrittenTotal, cCaptured, rc)); 1768 1769 if (cCaptured) 1770 LogFlowFunc(("%RU32 samples captured\n", cCaptured)); 1810 1771 1811 1772 if (pcSamplesCaptured) … … 1813 1774 } 1814 1775 1815 LogFlowFuncLeaveRC(rc); 1776 if (RT_FAILURE(rc)) 1777 LogFunc(("Failed with rc=%Rrc\n", rc)); 1778 1816 1779 return rc; 1817 1780 } … … 1826 1789 1827 1790 int rc = VINF_SUCCESS; 1828 1829 /* Check if the audio device should be reinitialized. If so do it. */1830 if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_REINIT)1831 {1832 rc = coreAudioReinitOut(pThis, &pStreamOut->Stream);1833 if (RT_FAILURE(rc))1834 return rc;1835 }1836 1837 /* Not much else to do here. */1838 1791 1839 1792 uint32_t cLive = AudioMixBufLive(&pStream->MixBuf); … … 1908 1861 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 1909 1862 1910 LogFlowFunc(("enmStreamCmd=% ld\n", enmStreamCmd));1863 LogFlowFunc(("enmStreamCmd=%RU32\n", enmStreamCmd)); 1911 1864 1912 1865 uint32_t uStatus = ASMAtomicReadU32(&pStreamOut->status); … … 1984 1937 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 1985 1938 1986 LogFlowFunc(("enmStreamCmd=% ld\n", enmStreamCmd));1939 LogFlowFunc(("enmStreamCmd=%RU32\n", enmStreamCmd)); 1987 1940 1988 1941 uint32_t uStatus = ASMAtomicReadU32(&pStreamIn->status); … … 2083 2036 #ifdef DEBUG 2084 2037 err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr, 2085 coreAudioRecordingAudioDevicePropertyChanged, pStreamIn); 2086 /* Not Fatal */ 2087 if (RT_UNLIKELY(err != noErr)) 2038 coreAudioRecordingAudioDevicePropertyChanged, &pStreamIn->cbCtx); 2039 if ( err != noErr 2040 && err != kAudioHardwareBadObjectError) 2041 { 2088 2042 LogRel(("CoreAudio: Failed to remove the recording processor overload listener (%RI32)\n", err)); 2043 } 2089 2044 #endif /* DEBUG */ 2090 2045 2091 2046 propAdr.mSelector = kAudioDevicePropertyNominalSampleRate; 2092 2047 err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr, 2093 coreAudioRecordingAudioDevicePropertyChanged, pStreamIn); 2094 /* Not Fatal */ 2095 if (RT_UNLIKELY(err != noErr)) 2048 coreAudioRecordingAudioDevicePropertyChanged, &pStreamIn->cbCtx); 2049 if ( err != noErr 2050 && err != kAudioHardwareBadObjectError) 2051 { 2096 2052 LogRel(("CoreAudio: Failed to remove the recording sample rate changed listener (%RI32)\n", err)); 2053 } 2097 2054 2098 2055 if (pStreamIn->fDefDevChgListReg) … … 2100 2057 propAdr.mSelector = kAudioHardwarePropertyDefaultInputDevice; 2101 2058 err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr, 2102 coreAudioDefaultDeviceChanged, pStreamIn); 2103 if (RT_LIKELY(err == noErr)) 2104 { 2105 pStreamIn->fDefDevChgListReg = false; 2106 } 2107 else 2059 coreAudioDefaultDeviceChanged, &pStreamIn->cbCtx); 2060 if ( err != noErr 2061 && err != kAudioHardwareBadObjectError) 2062 { 2108 2063 LogRel(("CoreAudio: Failed to remove the default recording device changed listener (%RI32)\n", err)); 2064 } 2065 2066 pStreamIn->fDefDevChgListReg = false; 2109 2067 } 2110 2068 2111 2069 if (pStreamIn->fDevStateChgListReg) 2112 2070 { 2071 Assert(pStreamIn->deviceID != kAudioDeviceUnknown); 2072 2113 2073 AudioObjectPropertyAddress propAdr2 = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal, 2114 2074 kAudioObjectPropertyElementMaster }; 2115 2075 err = AudioObjectRemovePropertyListener(pStreamIn->deviceID, &propAdr2, 2116 2076 drvHostCoreAudioDeviceStateChanged, &pStreamIn->cbCtx); 2117 if (RT_LIKELY(err == noErr)) 2118 { 2119 pStreamIn->fDevStateChgListReg = false; 2120 } 2121 else 2077 if ( err != noErr 2078 && err != kAudioHardwareBadObjectError) 2079 { 2122 2080 LogRel(("CoreAudio: Failed to remove the recording device state changed listener (%RI32)\n", err)); 2081 } 2082 2083 pStreamIn->fDevStateChgListReg = false; 2123 2084 } 2124 2085 … … 2130 2091 2131 2092 err = AudioUnitUninitialize(pStreamIn->audioUnit); 2132 if (RT_LIKELY(err == noErr)) 2133 { 2093 if (err == noErr) 2134 2094 err = CloseComponent(pStreamIn->audioUnit); 2135 if (RT_LIKELY(err == noErr)) 2136 { 2137 pStreamIn->deviceID = kAudioDeviceUnknown; 2138 pStreamIn->audioUnit = NULL; 2139 pStreamIn->offBufferRead = 0; 2140 pStreamIn->sampleRatio = 1; 2141 if (pStreamIn->pBuf) 2142 { 2143 RTCircBufDestroy(pStreamIn->pBuf); 2144 pStreamIn->pBuf = NULL; 2145 } 2146 2147 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT); 2148 } 2149 else 2150 { 2151 LogRel(("CoreAudio: Failed to close the recording unit (%RI32)\n", err)); 2152 rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */ 2153 } 2154 } 2155 else 2156 { 2157 LogRel(("CoreAudio: Failed to uninitialize the recording unit (%RI32)\n", err)); 2158 rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */ 2159 } 2095 2096 if ( err != noErr 2097 && err != kAudioHardwareBadObjectError) 2098 { 2099 LogRel(("CoreAudio: Failed to uninit the recording device (%RI32)\n", err)); 2100 } 2101 2102 pStreamIn->deviceID = kAudioDeviceUnknown; 2103 pStreamIn->audioUnit = NULL; 2104 pStreamIn->offBufferRead = 0; 2105 pStreamIn->sampleRatio = 1; 2106 if (pStreamIn->pBuf) 2107 { 2108 RTCircBufDestroy(pStreamIn->pBuf); 2109 pStreamIn->pBuf = NULL; 2110 } 2111 2112 ASMAtomicXchgU32(&pStreamIn->status, CA_STATUS_UNINIT); 2160 2113 } 2161 2114 else 2162 { 2163 LogRel(("CoreAudio: Failed to stop recording (%RI32)\n", err)); 2164 rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */ 2165 } 2115 LogRel(("CoreAudio: Failed to stop recording on uninit, rc=%Rrc\n", rc)); 2166 2116 2167 2117 LogFlowFuncLeaveRC(rc); … … 2196 2146 #ifdef DEBUG 2197 2147 err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr, 2198 coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut); 2199 /* Not Fatal */ 2200 if (RT_UNLIKELY(err != noErr)) 2148 coreAudioPlaybackAudioDevicePropertyChanged, &pStreamOut->cbCtx); 2149 if ( err != noErr 2150 && err != kAudioHardwareBadObjectError) 2151 { 2201 2152 LogRel(("CoreAudio: Failed to remove the playback processor overload listener (%RI32)\n", err)); 2153 } 2202 2154 #endif /* DEBUG */ 2203 2155 2204 2156 propAdr.mSelector = kAudioDevicePropertyNominalSampleRate; 2205 2157 err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr, 2206 coreAudioPlaybackAudioDevicePropertyChanged, pStreamOut); 2207 /* Not Fatal */ 2208 if (RT_UNLIKELY(err != noErr)) 2158 coreAudioPlaybackAudioDevicePropertyChanged, &pStreamOut->cbCtx); 2159 if ( err != noErr 2160 && err != kAudioHardwareBadObjectError) 2161 { 2209 2162 LogRel(("CoreAudio: Failed to remove the playback sample rate changed listener (%RI32)\n", err)); 2163 } 2210 2164 2211 2165 if (pStreamOut->fDefDevChgListReg) … … 2215 2169 propAdr.mElement = kAudioObjectPropertyElementMaster; 2216 2170 err = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &propAdr, 2217 coreAudioDefaultDeviceChanged, pStreamOut); 2218 if (RT_LIKELY(err == noErr)) 2219 { 2220 pStreamOut->fDefDevChgListReg = false; 2221 } 2222 else 2171 coreAudioDefaultDeviceChanged, &pStreamOut->cbCtx); 2172 if ( err != noErr 2173 && err != kAudioHardwareBadObjectError) 2174 { 2223 2175 LogRel(("CoreAudio: Failed to remove the default playback device changed listener (%RI32)\n", err)); 2176 } 2177 2178 pStreamOut->fDefDevChgListReg = false; 2224 2179 } 2225 2180 2226 2181 if (pStreamOut->fDevStateChgListReg) 2227 2182 { 2183 Assert(pStreamOut->deviceID != kAudioDeviceUnknown); 2184 2228 2185 AudioObjectPropertyAddress propAdr2 = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal, 2229 2186 kAudioObjectPropertyElementMaster }; 2230 2187 err = AudioObjectRemovePropertyListener(pStreamOut->deviceID, &propAdr2, 2231 2188 drvHostCoreAudioDeviceStateChanged, &pStreamOut->cbCtx); 2232 if (RT_LIKELY(err == noErr)) 2233 { 2234 pStreamOut->fDevStateChgListReg = false; 2235 } 2236 else 2189 if ( err != noErr 2190 && err != kAudioHardwareBadObjectError) 2191 { 2237 2192 LogRel(("CoreAudio: Failed to remove the playback device state changed listener (%RI32)\n", err)); 2193 } 2194 2195 pStreamOut->fDevStateChgListReg = false; 2238 2196 } 2239 2197 2240 2198 err = AudioUnitUninitialize(pStreamOut->audioUnit); 2241 2199 if (err == noErr) 2242 {2243 2200 err = CloseComponent(pStreamOut->audioUnit); 2244 if (err == noErr) 2245 { 2246 pStreamOut->deviceID = kAudioDeviceUnknown; 2247 pStreamOut->audioUnit = NULL; 2248 if (pStreamOut->pBuf) 2249 { 2250 RTCircBufDestroy(pStreamOut->pBuf); 2251 pStreamOut->pBuf = NULL; 2252 } 2253 2254 ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_UNINIT); 2255 } 2256 else 2257 LogRel(("CoreAudio: Failed to close the playback unit (%RI32)\n", err)); 2258 } 2259 else 2260 LogRel(("CoreAudio: Failed to uninitialize the playback unit (%RI32)\n", err)); 2201 2202 if ( err != noErr 2203 && err != kAudioHardwareBadObjectError) 2204 { 2205 LogRel(("CoreAudio: Failed to uninit the playback device (%RI32)\n", err)); 2206 } 2207 2208 pStreamOut->deviceID = kAudioDeviceUnknown; 2209 pStreamOut->audioUnit = NULL; 2210 if (pStreamOut->pBuf) 2211 { 2212 RTCircBufDestroy(pStreamOut->pBuf); 2213 pStreamOut->pBuf = NULL; 2214 } 2215 2216 ASMAtomicXchgU32(&pStreamOut->status, CA_STATUS_UNINIT); 2261 2217 } 2262 2218 else 2263 LogRel(("CoreAudio: Failed to stop playback , rc=%Rrc\n", rc));2219 LogRel(("CoreAudio: Failed to stop playback on uninit, rc=%Rrc\n", rc)); 2264 2220 2265 2221 LogFlowFuncLeaveRC(rc); … … 2271 2227 { 2272 2228 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 2273 2274 LogFlowFunc(("enmRecSource=%ld\n", pCfg->DestSource.Source));2275 2229 2276 2230 pStreamIn->deviceID = kAudioDeviceUnknown; … … 2285 2239 pStreamIn->fDevStateChgListReg = false; 2286 2240 2241 /* Set callback context. */ 2242 pStreamIn->cbCtx.pThis = pThis; 2243 pStreamIn->cbCtx.enmDir = PDMAUDIODIR_IN; 2244 pStreamIn->cbCtx.pIn = pStreamIn; 2245 2287 2246 bool fDeviceByUser = false; /* Do we use a device which was set by the user? */ 2288 2247 2289 /* Initialize the hardware info section with the audio settings */ 2248 LogFlowFunc(("enmRecSource=%RU32\n", pCfg->DestSource.Source)); 2249 2290 2250 int rc = DrvAudioHlpStreamCfgToProps(pCfg, &pStreamIn->Stream.Props); 2291 2251 if (RT_SUCCESS(rc)) … … 2306 2266 } 2307 2267 2308 if (RT_SUCCESS(rc))2309 { 2310 OSStatus err;2311 2312 /* When the devices isn't forced by the user, we want default device change notifications. */2313 if (! fDeviceByUser)2268 OSStatus err; 2269 2270 /* When the devices isn't forced by the user, we want default device change notifications. */ 2271 if (!fDeviceByUser) 2272 { 2273 if (!pStreamIn->fDefDevChgListReg) 2314 2274 { 2315 2275 AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, … … 2317 2277 err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr, 2318 2278 coreAudioDefaultDeviceChanged, &pStreamIn->cbCtx); 2319 /* Not fatal. */2320 if (RT_LIKELY(err == noErr))2279 if ( err == noErr 2280 || err == kAudioHardwareIllegalOperationError) 2321 2281 { 2322 2282 pStreamIn->fDefDevChgListReg = true; … … 2325 2285 LogRel(("CoreAudio: Failed to add the default recording device changed listener (%RI32)\n", err)); 2326 2286 } 2327 2287 } 2288 2289 if ( !pStreamIn->fDevStateChgListReg 2290 && (pStreamIn->deviceID != kAudioDeviceUnknown)) 2291 { 2328 2292 /* Register callback for being notified if the device stops being alive. */ 2329 2293 AudioObjectPropertyAddress propAdr = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal, … … 2331 2295 err = AudioObjectAddPropertyListener(pStreamIn->deviceID, &propAdr, drvHostCoreAudioDeviceStateChanged, 2332 2296 &pStreamIn->cbCtx); 2333 /* Not fatal. */ 2334 if (RT_LIKELY(err == noErr)) 2297 if (err == noErr) 2335 2298 { 2336 2299 pStreamIn->fDevStateChgListReg = true; … … 2359 2322 pStreamOut->fDevStateChgListReg = false; 2360 2323 2324 /* Set callback context. */ 2325 pStreamOut->cbCtx.pThis = pThis; 2326 pStreamOut->cbCtx.enmDir = PDMAUDIODIR_OUT; 2327 pStreamOut->cbCtx.pOut = pStreamOut; 2328 2361 2329 bool fDeviceByUser = false; /* Do we use a device which was set by the user? */ 2362 2330 2363 /* I nitialize the hardware info section with the audio settings*/2331 /* If a stream configuration is given, apply that to the stream. */ 2364 2332 int rc = DrvAudioHlpStreamCfgToProps(pCfg, &pStreamOut->Stream.Props); 2365 2333 if (RT_SUCCESS(rc)) … … 2382 2350 } 2383 2351 2384 if (RT_SUCCESS(rc))2385 { 2386 OSStatus err;2387 2388 /* When the devices isn't forced by the user, we want default device change notifications. */2389 if (!fDeviceByUser)2390 {2391 AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal,2392 kAudioObjectPropertyElementMaster };2393 err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr,2394 coreAudioDefaultDeviceChanged, &pStreamOut->cbCtx);2395 /* Not fatal. */2396 if (RT_LIKELY(err == noErr))2397 {2398 pStreamOut->fDefDevChgListReg = true;2399 2400 else 2401 LogRel(("CoreAudio: Failed to add the default playback device changed listener (%RI32)\n", err));2402 }2403 2352 OSStatus err; 2353 2354 /* When the devices isn't forced by the user, we want default device change notifications. */ 2355 if (!fDeviceByUser) 2356 { 2357 AudioObjectPropertyAddress propAdr = { kAudioHardwarePropertyDefaultOutputDevice, kAudioObjectPropertyScopeGlobal, 2358 kAudioObjectPropertyElementMaster }; 2359 err = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &propAdr, 2360 coreAudioDefaultDeviceChanged, &pStreamOut->cbCtx); 2361 if (err == noErr) 2362 { 2363 pStreamOut->fDefDevChgListReg = true; 2364 } 2365 else 2366 LogRel(("CoreAudio: Failed to add the default playback device changed listener (%RI32)\n", err)); 2367 } 2368 2369 if ( !pStreamOut->fDevStateChgListReg 2370 && (pStreamOut->deviceID != kAudioDeviceUnknown)) 2371 { 2404 2372 /* Register callback for being notified if the device stops being alive. */ 2405 2373 AudioObjectPropertyAddress propAdr = { kAudioDevicePropertyDeviceIsAlive, kAudioObjectPropertyScopeGlobal, … … 2407 2375 err = AudioObjectAddPropertyListener(pStreamOut->deviceID, &propAdr, drvHostCoreAudioDeviceStateChanged, 2408 2376 &pStreamOut->cbCtx); 2409 /* Not fatal. */ 2410 if (RT_LIKELY(err == noErr)) 2377 if (err == noErr) 2411 2378 { 2412 2379 pStreamOut->fDevStateChgListReg = true; … … 2498 2465 { 2499 2466 NOREF(pInterface); 2500 NOREF(pStream); 2501 2502 PDMAUDIOSTRMSTS strmSts = PDMAUDIOSTRMSTS_FLAG_INITIALIZED 2503 | PDMAUDIOSTRMSTS_FLAG_ENABLED; 2467 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2468 2469 Assert(pStream->enmCtx == PDMAUDIOSTREAMCTX_HOST); 2470 2471 PDMAUDIOSTRMSTS strmSts = PDMAUDIOSTRMSTS_FLAG_NONE; 2504 2472 2505 2473 if (pStream->enmDir == PDMAUDIODIR_IN) 2506 strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_READABLE; 2474 { 2475 PCOREAUDIOSTREAMIN pStreamIn = (PCOREAUDIOSTREAMIN)pStream; 2476 2477 if (ASMAtomicReadU32(&pStreamIn->status) == CA_STATUS_INIT) 2478 strmSts |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED; 2479 2480 if (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED) 2481 strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_READABLE; 2482 } 2483 else if (pStream->enmDir == PDMAUDIODIR_OUT) 2484 { 2485 PCOREAUDIOSTREAMOUT pStreamOut = (PCOREAUDIOSTREAMOUT)pStream; 2486 2487 if (ASMAtomicReadU32(&pStreamOut->status) == CA_STATUS_INIT) 2488 strmSts |= PDMAUDIOSTRMSTS_FLAG_INITIALIZED | PDMAUDIOSTRMSTS_FLAG_ENABLED; 2489 2490 if (strmSts & PDMAUDIOSTRMSTS_FLAG_ENABLED) 2491 strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE; 2492 } 2507 2493 else 2508 strmSts |= PDMAUDIOSTRMSTS_FLAG_DATA_WRITABLE;2494 AssertFailed(); 2509 2495 2510 2496 return strmSts; … … 2515 2501 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 2516 2502 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 2517 2518 LogFlowFuncEnter();2519 2503 2520 2504 /* Nothing to do here for Core Audio. */
Note:
See TracChangeset
for help on using the changeset viewer.