Changeset 89357 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- May 28, 2021 1:25:07 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144706
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r89355 r89357 100 100 * Internal Functions * 101 101 *********************************************************************************************************************************/ 102 static int audioMixerAddSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);103 102 static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink); 104 103 105 static int audioMixerSinkInit(PAUDMIXSINK pSink, PAUDIOMIXER pMixer, const char *pcszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns);106 104 static void audioMixerSinkDestroyInternal(PAUDMIXSINK pSink, PPDMDEVINS pDevIns); 107 105 static int audioMixerSinkUpdateVolume(PAUDMIXSINK pSink, PCPDMAUDIOVOLUME pVolMaster); … … 228 226 int rc2 = RTCritSectEnter(&pMixer->CritSect); 229 227 AssertRCReturnVoid(rc2); 228 Assert(pMixer->uMagic == AUDIOMIXER_MAGIC); 230 229 231 230 LogFlowFunc(("Destroying %s ...\n", pMixer->pszName)); … … 260 259 { 261 260 RT_NOREF(pszArgs); 262 Assert (pMixer->uMagic == AUDIOMIXER_MAGIC);261 AssertReturnVoid(pMixer->uMagic == AUDIOMIXER_MAGIC); 263 262 264 263 int rc2 = RTCritSectEnter(&pMixer->CritSect); … … 281 280 } 282 281 283 /** 284 * Invalidates all internal data, internal version. 282 283 /** 284 * Sets the mixer's master volume. 285 285 * 286 286 * @returns VBox status code. 287 * @param pMixer Mixer to invalidate data for. 288 */ 289 static int audioMixerInvalidateInternal(PAUDIOMIXER pMixer) 287 * @param pMixer Mixer to set master volume for. 288 * @param pVol Volume to set. 289 */ 290 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PCPDMAUDIOVOLUME pVol) 290 291 { 291 292 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 292 LogFlowFunc(("[%s]\n", pMixer->pszName)); 293 294 /* Propagate new master volume to all connected sinks. */ 293 AssertReturn(pMixer->uMagic == AUDIOMIXER_MAGIC, VERR_INVALID_MAGIC); 294 AssertPtrReturn(pVol, VERR_INVALID_POINTER); 295 296 int rc = RTCritSectEnter(&pMixer->CritSect); 297 AssertRCReturn(rc, rc); 298 299 /* 300 * Make a copy. 301 */ 302 memcpy(&pMixer->VolMaster, pVol, sizeof(PDMAUDIOVOLUME)); 303 LogFlowFunc(("[%s] lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n", 304 pMixer->pszName, pVol->uLeft, pVol->uRight, 305 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight)); 306 307 /* 308 * Propagate new master volume to all sinks. 309 */ 295 310 PAUDMIXSINK pSink; 296 311 RTListForEach(&pMixer->lstSinks, pSink, AUDMIXSINK, Node) … … 300 315 } 301 316 302 return VINF_SUCCESS; 303 } 304 305 #if 0 /* unused */ 306 /** 307 * Invalidates all internal data. 308 * 309 * @returns VBox status code. 310 * @param pMixer Mixer to invalidate data for. 311 */ 312 void AudioMixerInvalidate(PAUDIOMIXER pMixer) 313 { 314 AssertPtrReturnVoid(pMixer); 315 Assert(pMixer->uMagic == AUDIOMIXER_MAGIC); 316 317 int rc2 = RTCritSectEnter(&pMixer->CritSect); 318 AssertRC(rc2); 319 320 LogFlowFunc(("[%s]\n", pMixer->pszName)); 321 322 rc2 = audioMixerInvalidateInternal(pMixer); 323 AssertRC(rc2); 324 325 rc2 = RTCritSectLeave(&pMixer->CritSect); 326 AssertRC(rc2); 327 } 328 #endif 329 330 /** 331 * Adds sink to an existing mixer. 332 * 333 * @returns VBox status code. 334 * @param pMixer Mixer to add sink to. 335 * @param pSink Sink to add. 336 */ 337 static int audioMixerAddSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 338 { 339 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 340 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 341 342 /** @todo Check upper sink limit? */ 343 /** @todo Check for double-inserted sinks? */ 344 345 RTListAppend(&pMixer->lstSinks, &pSink->Node); 346 pMixer->cSinks++; 347 348 LogFlowFunc(("pMixer=%p, pSink=%p, cSinks=%RU8\n", 349 pMixer, pSink, pMixer->cSinks)); 350 351 return VINF_SUCCESS; 352 } 353 354 /** 355 * Removes a formerly attached audio sink for an audio mixer, internal version. 317 RTCritSectLeave(&pMixer->CritSect); 318 return rc; 319 } 320 321 322 /** 323 * Removes an audio sink from the given audio mixer, internal version. 324 * 325 * Used by AudioMixerDestroy and AudioMixerSinkDestroy. 326 * 327 * Caller must hold the mixer lock. 356 328 * 357 329 * @returns VBox status code. … … 361 333 static int audioMixerRemoveSinkInternal(PAUDIOMIXER pMixer, PAUDMIXSINK pSink) 362 334 { 363 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 364 if (!pSink) 365 return VERR_NOT_FOUND; 366 367 AssertMsgReturn(pSink->pParent == pMixer, ("%s: Is not part of mixer '%s'\n", 368 pSink->pszName, pMixer->pszName), VERR_NOT_FOUND); 369 370 LogFlowFunc(("[%s] pSink=%s, cSinks=%RU8\n", 371 pMixer->pszName, pSink->pszName, pMixer->cSinks)); 335 LogFlowFunc(("[%s] pSink=%s, cSinks=%RU8\n", pMixer->pszName, pSink->pszName, pMixer->cSinks)); 336 Assert(RTCritSectIsOwner(&pMixer->CritSect)); 337 AssertMsgReturn(pSink->pParent == pMixer, 338 ("%s: Is not part of mixer '%s'\n", pSink->pszName, pMixer->pszName), VERR_INTERNAL_ERROR_4); 372 339 373 340 /* Remove sink from mixer. */ … … 381 348 382 349 return VINF_SUCCESS; 383 }384 385 /**386 * Sets the mixer's master volume.387 *388 * @returns VBox status code.389 * @param pMixer Mixer to set master volume for.390 * @param pVol Volume to set.391 */392 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol)393 {394 AssertPtrReturn(pMixer, VERR_INVALID_POINTER);395 Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);396 AssertPtrReturn(pVol, VERR_INVALID_POINTER);397 398 int rc = RTCritSectEnter(&pMixer->CritSect);399 AssertRCReturn(rc, rc);400 401 memcpy(&pMixer->VolMaster, pVol, sizeof(PDMAUDIOVOLUME));402 403 LogFlowFunc(("[%s] lVol=%RU32, rVol=%RU32 => fMuted=%RTbool, lVol=%RU32, rVol=%RU32\n",404 pMixer->pszName, pVol->uLeft, pVol->uRight,405 pMixer->VolMaster.fMuted, pMixer->VolMaster.uLeft, pMixer->VolMaster.uRight));406 407 rc = audioMixerInvalidateInternal(pMixer);408 409 int rc2 = RTCritSectLeave(&pMixer->CritSect);410 AssertRC(rc2);411 412 return rc;413 350 } 414 351 … … 432 369 AssertPtrReturn(pMixer, VERR_INVALID_POINTER); 433 370 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 434 /* ppSink is optional. */ 371 size_t const cchName = strlen(pszName); 372 AssertReturn(cchName > 0 && cchName < 64, VERR_INVALID_NAME); 373 AssertPtrNullReturn(ppSink, VERR_INVALID_POINTER); 435 374 436 375 int rc = RTCritSectEnter(&pMixer->CritSect); 437 376 AssertRCReturn(rc, rc); 438 377 439 PAUDMIXSINK pSink = (PAUDMIXSINK)RTMemAllocZ(sizeof(AUDMIXSINK)); 378 /** @todo limit the number of sinks? */ 379 380 /* 381 * Allocate the data and initialize the critsect. 382 */ 383 PAUDMIXSINK pSink = (PAUDMIXSINK)RTMemAllocZ(sizeof(AUDMIXSINK) + cchName + 1); 440 384 if (pSink) 441 385 { 442 rc = audioMixerSinkInit(pSink, pMixer, pszName, enmDir, pDevIns);386 rc = RTCritSectInit(&pSink->CritSect); 443 387 if (RT_SUCCESS(rc)) 444 388 { 445 rc = audioMixerAddSinkInternal(pMixer, pSink); 446 if (RT_SUCCESS(rc)) 447 { 448 RTCritSectLeave(&pMixer->CritSect); 449 450 char szPrefix[128]; 451 RTStrPrintf(szPrefix, sizeof(szPrefix), "MixerSink-%s/", pSink->pszName); 452 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 453 "Sink mixer buffer size in frames.", "%sMixBufSize", szPrefix); 454 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 455 "Sink mixer buffer fill size in frames.", "%sMixBufUsed", szPrefix); 456 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->cStreams, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_NONE, 457 "Number of streams attached to the sink.", "%sStreams", szPrefix); 458 459 if (ppSink) 460 *ppSink = pSink; 461 return VINF_SUCCESS; 462 } 463 } 464 465 audioMixerSinkDestroyInternal(pSink, pDevIns); 389 /* 390 * Initialize it. 391 */ 392 pSink->uMagic = AUDMIXSINK_MAGIC; 393 pSink->pParent = NULL; 394 pSink->enmDir = enmDir; 395 pSink->pszName = (const char *)memcpy(pSink + 1, pszName, cchName + 1); 396 RTListInit(&pSink->lstStreams); 397 398 /* Set initial volume to max. */ 399 pSink->Volume.fMuted = false; 400 pSink->Volume.uLeft = PDMAUDIO_VOLUME_MAX; 401 pSink->Volume.uRight = PDMAUDIO_VOLUME_MAX; 402 403 /* Ditto for the combined volume. */ 404 pSink->VolumeCombined.fMuted = false; 405 pSink->VolumeCombined.uLeft = PDMAUDIO_VOLUME_MAX; 406 pSink->VolumeCombined.uRight = PDMAUDIO_VOLUME_MAX; 407 408 /* AIO */ 409 AssertPtr(pDevIns); 410 pSink->AIO.pDevIns = pDevIns; 411 pSink->AIO.hThread = NIL_RTTHREAD; 412 pSink->AIO.hEvent = NIL_RTSEMEVENT; 413 pSink->AIO.fStarted = false; 414 pSink->AIO.fShutdown = false; 415 pSink->AIO.cUpdateJobs = 0; 416 417 /* 418 * Add it to the mixer. 419 */ 420 RTListAppend(&pMixer->lstSinks, &pSink->Node); 421 pMixer->cSinks++; 422 pSink->pParent = pMixer; 423 424 RTCritSectLeave(&pMixer->CritSect); 425 426 /* 427 * Register stats and return. 428 */ 429 char szPrefix[128]; 430 RTStrPrintf(szPrefix, sizeof(szPrefix), "MixerSink-%s/", pSink->pszName); 431 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cFrames, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 432 "Sink mixer buffer size in frames.", "%sMixBufSize", szPrefix); 433 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->MixBuf.cUsed, STAMTYPE_U32, STAMVISIBILITY_USED, STAMUNIT_NONE, 434 "Sink mixer buffer fill size in frames.", "%sMixBufUsed", szPrefix); 435 PDMDevHlpSTAMRegisterF(pDevIns, &pSink->cStreams, STAMTYPE_U8, STAMVISIBILITY_USED, STAMUNIT_NONE, 436 "Number of streams attached to the sink.", "%sStreams", szPrefix); 437 438 if (ppSink) 439 *ppSink = pSink; 440 return VINF_SUCCESS; 441 } 466 442 467 443 RTMemFree(pSink); 468 pSink = NULL;469 444 } 470 445 else … … 472 447 473 448 RTCritSectLeave(&pMixer->CritSect); 449 if (ppSink) 450 *ppSink = NULL; 474 451 return rc; 475 452 } … … 858 835 859 836 860 861 /**862 * Initializes a sink.863 *864 * @returns VBox status code.865 * @param pSink Sink to initialize.866 * @param pMixer Mixer the sink is assigned to.867 * @param pszName Name of the sink.868 * @param enmDir Direction of the sink.869 * @param pDevIns The device instance.870 */871 static int audioMixerSinkInit(PAUDMIXSINK pSink, PAUDIOMIXER pMixer, const char *pszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns)872 {873 pSink->pszName = RTStrDup(pszName);874 if (!pSink->pszName)875 return VERR_NO_MEMORY;876 877 int rc = RTCritSectInit(&pSink->CritSect);878 if (RT_SUCCESS(rc))879 {880 pSink->uMagic = AUDMIXSINK_MAGIC;881 pSink->pParent = pMixer;882 pSink->enmDir = enmDir;883 884 RTListInit(&pSink->lstStreams);885 886 /* Set initial volume to max. */887 pSink->Volume.fMuted = false;888 pSink->Volume.uLeft = PDMAUDIO_VOLUME_MAX;889 pSink->Volume.uRight = PDMAUDIO_VOLUME_MAX;890 891 /* Ditto for the combined volume. */892 pSink->VolumeCombined.fMuted = false;893 pSink->VolumeCombined.uLeft = PDMAUDIO_VOLUME_MAX;894 pSink->VolumeCombined.uRight = PDMAUDIO_VOLUME_MAX;895 896 /* AIO */897 AssertPtr(pDevIns);898 pSink->AIO.pDevIns = pDevIns;899 pSink->AIO.hThread = NIL_RTTHREAD;900 pSink->AIO.hEvent = NIL_RTSEMEVENT;901 pSink->AIO.fStarted = false;902 pSink->AIO.fShutdown = false;903 pSink->AIO.cUpdateJobs = 0;904 }905 906 LogFlowFuncLeaveRC(rc);907 return rc;908 }909 910 /**911 * Destroys a mixer sink and removes it from the attached mixer (if any).912 *913 * @param pSink Mixer sink to destroy.914 * @param pDevIns The device instance that statistics are registered with.915 */916 void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns)917 {918 if (!pSink)919 return;920 921 /** @todo wrong critsect for audioMixerRemoveSinkInternal... */922 int rc2 = RTCritSectEnter(&pSink->CritSect);923 AssertRC(rc2);924 925 if (pSink->pParent)926 {927 /* Save mixer pointer, as after audioMixerRemoveSinkInternal() the928 * pointer will be gone from the stream. */929 PAUDIOMIXER pMixer = pSink->pParent;930 AssertPtr(pMixer);931 Assert(pMixer->uMagic == AUDIOMIXER_MAGIC);932 933 audioMixerRemoveSinkInternal(pMixer, pSink);934 }935 936 rc2 = RTCritSectLeave(&pSink->CritSect);937 AssertRC(rc2);938 939 audioMixerSinkDestroyInternal(pSink, pDevIns);940 941 RTMemFree(pSink);942 pSink = NULL;943 }944 945 837 /** 946 838 * Destroys a mixer sink. 839 * 840 * Worker for AudioMixerSinkDestroy(), AudioMixerCreateSink() and 841 * AudioMixerDestroy(). 947 842 * 948 843 * @param pSink Mixer sink to destroy. … … 965 860 } 966 861 862 /** @todo r=bird: this looks wrong for the AudioMixerSinkDestroy case ... */ 967 863 if ( pSink->pParent 968 864 && pSink->pParent->fFlags & AUDMIXER_FLAGS_DEBUG) … … 997 893 } 998 894 999 RTStrFree(pSink->pszName);1000 pSink->pszName = NULL;1001 1002 895 AudioMixBufDestroy(&pSink->MixBuf); 1003 896 RTCritSectDelete(&pSink->CritSect); 897 } 898 899 900 /** 901 * Destroys a mixer sink and removes it from the attached mixer (if any). 902 * 903 * @param pSink Mixer sink to destroy. 904 * @param pDevIns The device instance that statistics are registered with. 905 */ 906 void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns) 907 { 908 if (!pSink) 909 return; 910 911 /* 912 * Serializing paranoia. 913 */ 914 int rc = RTCritSectEnter(&pSink->CritSect); 915 AssertRCReturnVoid(rc); 916 RTCritSectLeave(&pSink->CritSect); 917 918 /* 919 * Unlink from parent. 920 */ 921 PAUDIOMIXER pMixer = pSink->pParent; 922 if ( RT_VALID_PTR(pMixer) 923 && pMixer->uMagic == AUDIOMIXER_MAGIC) 924 { 925 RTCritSectEnter(&pMixer->CritSect); 926 audioMixerRemoveSinkInternal(pMixer, pSink); 927 RTCritSectLeave(&pMixer->CritSect); 928 } 929 else if (pMixer) 930 AssertFailed(); 931 932 audioMixerSinkDestroyInternal(pSink, pDevIns); 933 934 RTMemFree(pSink); 935 pSink = NULL; 1004 936 } 1005 937 -
trunk/src/VBox/Devices/Audio/AudioMixer.h
r89355 r89357 161 161 /** Pointer to mixer object this sink is bound to. */ 162 162 PAUDIOMIXER pParent; 163 /** Name of this sink . */164 char 163 /** Name of this sink (allocated after this structure). */ 164 char const *pszName; 165 165 /** The sink's PCM format (i.e. the guest device side). */ 166 166 PDMAUDIOPCMPROPS PCMProps; … … 279 279 * @{ */ 280 280 int AudioMixerCreate(const char *pszName, uint32_t fFlags, PAUDIOMIXER *ppMixer); 281 void AudioMixerDestroy(PAUDIOMIXER pMixer, PPDMDEVINS pDevIns); 282 void AudioMixerInvalidate(PAUDIOMIXER pMixer); 283 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol); 284 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs); 281 void AudioMixerDestroy(PAUDIOMIXER pMixer, PPDMDEVINS pDevIns); 282 void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs); 283 int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PCPDMAUDIOVOLUME pVol); 285 284 int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns, PAUDMIXSINK *ppSink); 286 285 /** @} */
Note:
See TracChangeset
for help on using the changeset viewer.