Changeset 88047 in vbox
- Timestamp:
- Mar 9, 2021 2:06:20 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143178
- Location:
- trunk
- Files:
-
- 5 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudiohostenuminline.h
r88045 r88047 1 1 /* $Id$ */ 2 2 /** @file 3 * Intermedia audio driver, common routines.4 * 5 * Th ese are also used in the drivers which are bound to Main, e.g. the VRDE6 * or the video audio recording drivers.3 * PDM - Audio Helpers, Inlined Code. (DEV,++) 4 * 5 * This is all inlined because it's too tedious to create a couple libraries to 6 * contain it all (same bad excuse as for intnetinline.h & pdmnetinline.h). 7 7 */ 8 8 … … 17 17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 18 18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 19 */ 19 * 20 * The contents of this file may alternatively be used under the terms 21 * of the Common Development and Distribution License Version 1.0 22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 23 * VirtualBox OSE distribution, in which case the provisions of the 24 * CDDL are applicable instead of those of the GPL. 25 * 26 * You may elect to license modified versions of this file under the 27 * terms and conditions of either the GPL or the CDDL or both. 28 */ 29 30 #ifndef VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h 31 #define VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h 32 #ifndef RT_WITHOUT_PRAGMA_ONCE 33 # pragma once 34 #endif 20 35 21 36 … … 23 38 * Header Files * 24 39 *********************************************************************************************************************************/ 25 #include <iprt/alloc.h> 40 #include <VBox/err.h> 41 #include <VBox/log.h> 42 #include <VBox/vmm/pdmaudioifs.h> 43 #include <VBox/vmm/pdmaudioinline.h> 44 45 #include <iprt/asm.h> 26 46 #include <iprt/asm-math.h> 27 47 #include <iprt/assert.h> 28 #include <iprt/dir.h> 29 #include <iprt/file.h> 48 #include <iprt/mem.h> 30 49 #include <iprt/string.h> 31 #include <iprt/uuid.h> 32 33 #define LOG_GROUP LOG_GROUP_DRV_AUDIO 34 #include <VBox/log.h> 35 36 #include <VBox/err.h> 37 #include <VBox/vmm/pdmdev.h> 38 #include <VBox/vmm/pdm.h> 39 #include <VBox/vmm/pdmaudioinline.h> 40 #include <VBox/vmm/mm.h> 41 42 #include <ctype.h> 43 #include <stdlib.h> 44 45 #include "DrvAudio.h" 46 #include "AudioMixBuffer.h" 47 48 49 /********************************************************************************************************************************* 50 * Structures and Typedefs * 51 *********************************************************************************************************************************/ 52 /** 53 * Structure for building up a .WAV file header. 54 */ 55 typedef struct AUDIOWAVFILEHDR 56 { 57 uint32_t u32RIFF; 58 uint32_t u32Size; 59 uint32_t u32WAVE; 60 61 uint32_t u32Fmt; 62 uint32_t u32Size1; 63 uint16_t u16AudioFormat; 64 uint16_t u16NumChannels; 65 uint32_t u32SampleRate; 66 uint32_t u32ByteRate; 67 uint16_t u16BlockAlign; 68 uint16_t u16BitsPerSample; 69 70 uint32_t u32ID2; 71 uint32_t u32Size2; 72 } AUDIOWAVFILEHDR, *PAUDIOWAVFILEHDR; 73 AssertCompileSize(AUDIOWAVFILEHDR, 11*4); 74 75 /** 76 * Structure for keeeping the internal .WAV file data 77 */ 78 typedef struct AUDIOWAVFILEDATA 79 { 80 /** The file header/footer. */ 81 AUDIOWAVFILEHDR Hdr; 82 } AUDIOWAVFILEDATA, *PAUDIOWAVFILEDATA; 83 84 85 86 #if 0 /* unused, no header prototypes */ 87 88 /** 89 * Retrieves the matching PDMAUDIOFMT for the given bits + signing flag. 90 * 91 * @return Matching PDMAUDIOFMT value. 92 * @retval PDMAUDIOFMT_INVALID if unsupported @a cBits value. 93 * 94 * @param cBits The number of bits in the audio format. 95 * @param fSigned Whether the audio format is signed @c true or not. 96 */ 97 PDMAUDIOFMT DrvAudioAudFmtBitsToFormat(uint8_t cBits, bool fSigned) 98 { 99 if (fSigned) 100 { 101 switch (cBits) 102 { 103 case 8: return PDMAUDIOFMT_S8; 104 case 16: return PDMAUDIOFMT_S16; 105 case 32: return PDMAUDIOFMT_S32; 106 default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID); 107 } 108 } 109 else 110 { 111 switch (cBits) 112 { 113 case 8: return PDMAUDIOFMT_U8; 114 case 16: return PDMAUDIOFMT_U16; 115 case 32: return PDMAUDIOFMT_U32; 116 default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID); 117 } 118 } 119 } 120 121 /** 122 * Returns an unique file name for this given audio connector instance. 123 * 124 * @return Allocated file name. Must be free'd using RTStrFree(). 125 * @param uInstance Driver / device instance. 126 * @param pszPath Path name of the file to delete. The path must exist. 127 * @param pszSuffix File name suffix to use. 128 */ 129 char *DrvAudioDbgGetFileNameA(uint8_t uInstance, const char *pszPath, const char *pszSuffix) 130 { 131 char szFileName[64]; 132 RTStrPrintf(szFileName, sizeof(szFileName), "drvAudio%RU8-%s", uInstance, pszSuffix); 133 134 char szFilePath[RTPATH_MAX]; 135 int rc2 = RTStrCopy(szFilePath, sizeof(szFilePath), pszPath); 136 AssertRC(rc2); 137 rc2 = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName); 138 AssertRC(rc2); 139 140 return RTStrDup(szFilePath); 141 } 142 143 #endif /* unused */ 50 144 51 145 52 /** … … 152 59 * after it in its private structure. 153 60 */ 154 PPDMAUDIOHOSTDEVPDMAudioDeviceAlloc(size_t cb)61 DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioDeviceAlloc(size_t cb) 155 62 { 156 63 AssertReturn(cb >= sizeof(PDMAUDIOHOSTDEV), NULL); … … 175 82 * @param pDev The device to free. NULL is ignored. 176 83 */ 177 voidPDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev)84 DECLINLINE(void) PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev) 178 85 { 179 86 if (pDev) … … 195 102 * @param fOnlyCoreData 196 103 */ 197 PPDMAUDIOHOSTDEVPDMAudioDeviceDup(PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData)104 DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioDeviceDup(PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData) 198 105 { 199 106 AssertPtrReturn(pDev, NULL); … … 220 127 * @param pDevEnm The enumeration to initialize. 221 128 */ 222 voidPDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm)129 DECLINLINE(void) PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm) 223 130 { 224 131 AssertPtr(pDevEnm); … … 237 144 * @param pDevEnm The host audio device enumeration to delete. 238 145 */ 239 voidPDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm)146 DECLINLINE(void) PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm) 240 147 { 241 148 if (pDevEnm) … … 268 175 * @param pDev Device to add. The pointer will be owned by the device enumeration then. 269 176 */ 270 voidPDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev)177 DECLINLINE(void) PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev) 271 178 { 272 179 AssertPtr(pDevEnm); … … 290 197 * backends have data that can be copied. 291 198 */ 292 intPDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,293 PDMAUDIODIR enmUsage, bool fOnlyCoreData)199 DECLINLINE(int) PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm, 200 PDMAUDIODIR enmUsage, bool fOnlyCoreData) 294 201 { 295 202 AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER); … … 327 234 * PDMAUDIOHOSTDEV_F_DEFAULT set. 328 235 */ 329 PPDMAUDIOHOSTDEVPDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)236 DECLINLINE(PPDMAUDIOHOSTDEV) PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage) 330 237 { 331 238 AssertPtrReturn(pDevEnm, NULL); … … 354 261 * Pass PDMAUDIODIR_INVALID to get the total number of devices. 355 262 */ 356 uint32_tPDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)263 DECLINLINE(uint32_t) PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage) 357 264 { 358 265 AssertPtrReturn(pDevEnm, 0); … … 373 280 } 374 281 282 /** The max string length for all PDMAUDIOHOSTDEV_F_XXX. 283 * @sa PDMAudioDeviceFlagsToString */ 284 #define PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN (7 * 8) 285 286 /** 287 * Converts an audio device flags to a string. 288 * 289 * @returns 290 * @param pszDst Destination buffer with a size of at least 291 * PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN bytes (including 292 * the string terminator). 293 * @param fFlags Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert. 294 */ 295 DECLINLINE(const char *) PDMAudioDeviceFlagsToString(char pszDst[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN], uint32_t fFlags) 296 { 297 static const struct { const char *pszMnemonic; uint32_t cchMnemonic; uint32_t fFlag; } s_aFlags[] = 298 { 299 { RT_STR_TUPLE("DEFAULT "), PDMAUDIOHOSTDEV_F_DEFAULT }, 300 { RT_STR_TUPLE("HOTPLUG "), PDMAUDIOHOSTDEV_F_HOTPLUG }, 301 { RT_STR_TUPLE("BUGGY "), PDMAUDIOHOSTDEV_F_BUGGY }, 302 { RT_STR_TUPLE("IGNORE "), PDMAUDIOHOSTDEV_F_IGNORE }, 303 { RT_STR_TUPLE("LOCKED "), PDMAUDIOHOSTDEV_F_LOCKED }, 304 { RT_STR_TUPLE("DEAD "), PDMAUDIOHOSTDEV_F_DEAD }, 305 { RT_STR_TUPLE("NO_DUP "), PDMAUDIOHOSTDEV_F_NO_DUP }, 306 }; 307 size_t offDst = 0; 308 for (uint32_t i = 0; i < RT_ELEMENTS(s_aFlags); i++) 309 if (fFlags & s_aFlags[i].fFlag) 310 { 311 fFlags &= ~s_aFlags[i].fFlag; 312 memcpy(&pszDst[offDst], s_aFlags[i].pszMnemonic, s_aFlags[i].cchMnemonic); 313 offDst += s_aFlags[i].cchMnemonic; 314 } 315 Assert(fFlags == 0); 316 Assert(offDst < PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN); 317 318 if (offDst) 319 pszDst[offDst - 1] = '\0'; 320 else 321 memcpy(pszDst, "NONE", sizeof("NONE")); 322 return pszDst; 323 } 324 375 325 /** 376 326 * Logs an audio device enumeration. … … 379 329 * @param pszDesc Logging description (prefix). 380 330 */ 381 voidPDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc)331 DECLINLINE(void) PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc) 382 332 { 383 333 AssertPtrReturnVoid(pDevEnm); … … 390 340 RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node) 391 341 { 392 char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags); 393 342 char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN]; 394 343 LogFunc(("Device '%s':\n", pDev->szName)); 395 344 LogFunc((" Usage = %s\n", PDMAudioDirGetName(pDev->enmUsage))); 396 LogFunc((" Flags = %s\n", pszFlags ? pszFlags : "<NONE>"));345 LogFunc((" Flags = %s\n", PDMAudioDeviceFlagsToString(szFlags, pDev->fFlags))); 397 346 LogFunc((" Input channels = %RU8\n", pDev->cMaxInputChannels)); 398 347 LogFunc((" Output channels = %RU8\n", pDev->cMaxOutputChannels)); 399 348 LogFunc((" cbExtra = %RU32 bytes\n", pDev->cbSelf - sizeof(PDMAUDIOHOSTDEV))); 400 401 if (pszFlags) 402 RTStrFree(pszFlags); 403 } 404 } 405 406 /** 407 * Converts an audio device flags to a string. 408 * 409 * @returns Stringified audio flags. Must be free'd with RTStrFree(). 410 * NULL if no flags set. 411 * @param fFlags Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert. 412 */ 413 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags) 414 { 415 #define APPEND_FLAG_TO_STR(_aFlag) \ 416 if (fFlags & PDMAUDIOHOSTDEV_F_##_aFlag) \ 417 { \ 418 if (pszFlags) \ 419 { \ 420 rc2 = RTStrAAppend(&pszFlags, " "); \ 421 if (RT_FAILURE(rc2)) \ 422 break; \ 423 } \ 424 \ 425 rc2 = RTStrAAppend(&pszFlags, #_aFlag); \ 426 if (RT_FAILURE(rc2)) \ 427 break; \ 428 } \ 429 430 char *pszFlags = NULL; 431 int rc2 = VINF_SUCCESS; 432 433 do 434 { 435 APPEND_FLAG_TO_STR(DEFAULT); 436 APPEND_FLAG_TO_STR(HOTPLUG); 437 APPEND_FLAG_TO_STR(BUGGY); 438 APPEND_FLAG_TO_STR(IGNORE); 439 APPEND_FLAG_TO_STR(LOCKED); 440 APPEND_FLAG_TO_STR(DEAD); 441 APPEND_FLAG_TO_STR(NO_DUP); 442 443 } while (0); 444 445 if (!pszFlags) 446 rc2 = RTStrAAppend(&pszFlags, "NONE"); 447 448 if ( RT_FAILURE(rc2) 449 && pszFlags) 450 { 451 RTStrFree(pszFlags); 452 pszFlags = NULL; 453 } 454 455 #undef APPEND_FLAG_TO_STR 456 457 return pszFlags; 458 } 459 460 /** 461 * Converts a given string to an audio format. 462 * 463 * @returns Audio format for the given string, or PDMAUDIOFMT_INVALID if not found. 464 * @param pszFmt String to convert to an audio format. 465 */ 466 PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt) 467 { 468 AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID); 469 470 if (!RTStrICmp(pszFmt, "u8")) 471 return PDMAUDIOFMT_U8; 472 if (!RTStrICmp(pszFmt, "u16")) 473 return PDMAUDIOFMT_U16; 474 if (!RTStrICmp(pszFmt, "u32")) 475 return PDMAUDIOFMT_U32; 476 if (!RTStrICmp(pszFmt, "s8")) 477 return PDMAUDIOFMT_S8; 478 if (!RTStrICmp(pszFmt, "s16")) 479 return PDMAUDIOFMT_S16; 480 if (!RTStrICmp(pszFmt, "s32")) 481 return PDMAUDIOFMT_S32; 482 483 AssertMsgFailed(("Invalid audio format '%s'\n", pszFmt)); 484 return PDMAUDIOFMT_INVALID; 485 } 486 487 /** 488 * Checks whether a given stream configuration is valid or not. 489 * 490 * @note See notes on DrvAudioHlpPcmPropsAreValid(). 491 * 492 * Returns @c true if configuration is valid, @c false if not. 493 * @param pCfg Stream configuration to check. 494 */ 495 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg) 496 { 497 AssertPtrReturn(pCfg, false); 498 499 AssertReturn(PDMAudioStrmCfgIsValid(pCfg), false); 500 501 bool fValid = ( pCfg->enmDir == PDMAUDIODIR_IN 502 || pCfg->enmDir == PDMAUDIODIR_OUT); 503 504 fValid &= ( pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED 505 || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW); 506 507 if (fValid) 508 fValid = DrvAudioHlpPcmPropsAreValid(&pCfg->Props); 509 510 return fValid; 511 } 512 513 /** 514 * Calculates the audio bit rate of the given bits per sample, the Hz and the number 515 * of audio channels. 516 * 517 * Divide the result by 8 to get the byte rate. 518 * 519 * @returns Bitrate. 520 * @param cBits Number of bits per sample. 521 * @param uHz Hz (Hertz) rate. 522 * @param cChannels Number of audio channels. 523 */ 524 uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels) 525 { 526 return cBits * uHz * cChannels; 527 } 528 529 530 /** 531 * Checks whether given PCM properties are valid or not. 532 * 533 * @note This is more of a supported than valid check. There is code for 534 * unsigned samples elsewhere (like DrvAudioHlpClearBuf()), but this 535 * function will flag such properties as not valid. 536 * 537 * @todo r=bird: See note and explain properly. 538 * 539 * @returns @c true if the properties are valid, @c false if not. 540 * @param pProps The PCM properties to check. 541 */ 542 bool DrvAudioHlpPcmPropsAreValid(PCPDMAUDIOPCMPROPS pProps) 543 { 544 AssertPtrReturn(pProps, false); 545 546 AssertReturn(PDMAudioPropsAreValid(pProps), false); 547 548 /** @todo r=bird: This code is cannot make up its mind whether to return on 549 * false, or whether to return at the end. (hint: just return 550 * immediately, duh.) */ 551 552 /* Minimum 1 channel (mono), maximum 7.1 (= 8) channels. */ 553 bool fValid = ( pProps->cChannels >= 1 554 && pProps->cChannels <= 8); 555 556 if (fValid) 557 { 558 switch (pProps->cbSample) 559 { 560 case 1: /* 8 bit */ 561 if (pProps->fSigned) 562 fValid = false; 563 break; 564 case 2: /* 16 bit */ 565 if (!pProps->fSigned) 566 fValid = false; 567 break; 568 /** @todo Do we need support for 24 bit samples? */ 569 case 4: /* 32 bit */ 570 if (!pProps->fSigned) 571 fValid = false; 572 break; 573 default: 574 fValid = false; 575 break; 576 } 577 } 578 579 if (!fValid) 580 return false; 581 582 fValid &= pProps->uHz > 0; 583 fValid &= pProps->cShift == PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSample, pProps->cChannels); 584 fValid &= pProps->fSwapEndian == false; /** @todo Handling Big Endian audio data is not supported yet. */ 585 586 return fValid; 587 } 588 589 590 /********************************************************************************************************************************* 591 * Audio File Helpers * 592 *********************************************************************************************************************************/ 593 594 /** 595 * Sanitizes the file name component so that unsupported characters 596 * will be replaced by an underscore ("_"). 597 * 598 * @return IPRT status code. 599 * @param pszPath Path to sanitize. 600 * @param cbPath Size (in bytes) of path to sanitize. 601 */ 602 int DrvAudioHlpFileNameSanitize(char *pszPath, size_t cbPath) 603 { 604 RT_NOREF(cbPath); 605 int rc = VINF_SUCCESS; 606 #ifdef RT_OS_WINDOWS 607 /* Filter out characters not allowed on Windows platforms, put in by 608 RTTimeSpecToString(). */ 609 /** @todo Use something like RTPathSanitize() if available later some time. */ 610 static RTUNICP const s_uszValidRangePairs[] = 611 { 612 ' ', ' ', 613 '(', ')', 614 '-', '.', 615 '0', '9', 616 'A', 'Z', 617 'a', 'z', 618 '_', '_', 619 0xa0, 0xd7af, 620 '\0' 621 }; 622 ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, s_uszValidRangePairs, '_' /* Replacement */); 623 if (cReplaced < 0) 624 rc = VERR_INVALID_UTF8_ENCODING; 625 #else 626 RT_NOREF(pszPath); 627 #endif 628 return rc; 629 } 630 631 /** 632 * Constructs an unique file name, based on the given path and the audio file type. 633 * 634 * @returns IPRT status code. 635 * @param pszFile Where to store the constructed file name. 636 * @param cchFile Size (in characters) of the file name buffer. 637 * @param pszPath Base path to use. 638 * If NULL or empty, the system's temporary directory will be used. 639 * @param pszName A name for better identifying the file. 640 * @param uInstance Device / driver instance which is using this file. 641 * @param enmType Audio file type to construct file name for. 642 * @param fFlags File naming flags, PDMAUDIOFILENAME_FLAGS_XXX. 643 */ 644 int DrvAudioHlpFileNameGet(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName, 645 uint32_t uInstance, PDMAUDIOFILETYPE enmType, uint32_t fFlags) 646 { 647 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 648 AssertReturn(cchFile, VERR_INVALID_PARAMETER); 649 /* pszPath can be NULL. */ 650 AssertPtrReturn(pszName, VERR_INVALID_POINTER); 651 /** @todo Validate fFlags. */ 652 653 int rc; 654 655 char *pszPathTmp = NULL; 656 657 do 658 { 659 if ( pszPath == NULL 660 || !strlen(pszPath)) 661 { 662 char szTemp[RTPATH_MAX]; 663 rc = RTPathTemp(szTemp, sizeof(szTemp)); 664 if (RT_SUCCESS(rc)) 665 { 666 pszPathTmp = RTStrDup(szTemp); 667 } 668 else 669 break; 670 } 671 else 672 pszPathTmp = RTStrDup(pszPath); 673 674 AssertPtrBreakStmt(pszPathTmp, rc = VERR_NO_MEMORY); 675 676 char szFilePath[RTPATH_MAX]; 677 rc = RTStrCopy(szFilePath, sizeof(szFilePath), pszPathTmp); 678 AssertRCBreak(rc); 679 680 /* Create it when necessary. */ 681 if (!RTDirExists(szFilePath)) 682 { 683 rc = RTDirCreateFullPath(szFilePath, RTFS_UNIX_IRWXU); 684 if (RT_FAILURE(rc)) 685 break; 686 } 687 688 char szFileName[RTPATH_MAX]; 689 szFileName[0] = '\0'; 690 691 if (fFlags & PDMAUDIOFILENAME_FLAGS_TS) 692 { 693 RTTIMESPEC time; 694 if (!RTTimeSpecToString(RTTimeNow(&time), szFileName, sizeof(szFileName))) 695 { 696 rc = VERR_BUFFER_OVERFLOW; 697 break; 698 } 699 700 rc = DrvAudioHlpFileNameSanitize(szFileName, sizeof(szFileName)); 701 if (RT_FAILURE(rc)) 702 break; 703 704 rc = RTStrCat(szFileName, sizeof(szFileName), "-"); 705 if (RT_FAILURE(rc)) 706 break; 707 } 708 709 rc = RTStrCat(szFileName, sizeof(szFileName), pszName); 710 if (RT_FAILURE(rc)) 711 break; 712 713 rc = RTStrCat(szFileName, sizeof(szFileName), "-"); 714 if (RT_FAILURE(rc)) 715 break; 716 717 char szInst[16]; 718 RTStrPrintf2(szInst, sizeof(szInst), "%RU32", uInstance); 719 rc = RTStrCat(szFileName, sizeof(szFileName), szInst); 720 if (RT_FAILURE(rc)) 721 break; 722 723 switch (enmType) 724 { 725 case PDMAUDIOFILETYPE_RAW: 726 rc = RTStrCat(szFileName, sizeof(szFileName), ".pcm"); 727 break; 728 729 case PDMAUDIOFILETYPE_WAV: 730 rc = RTStrCat(szFileName, sizeof(szFileName), ".wav"); 731 break; 732 733 default: 734 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 735 break; 736 } 737 738 if (RT_FAILURE(rc)) 739 break; 740 741 rc = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName); 742 if (RT_FAILURE(rc)) 743 break; 744 745 rc = RTStrCopy(pszFile, cchFile, szFilePath); 746 747 } while (0); 748 749 RTStrFree(pszPathTmp); 750 751 LogFlowFuncLeaveRC(rc); 752 return rc; 753 } 754 755 /** 756 * Creates an audio file. 757 * 758 * @returns IPRT status code. 759 * @param enmType Audio file type to open / create. 760 * @param pszFile File path of file to open or create. 761 * @param fFlags Audio file flags, PDMAUDIOFILE_FLAGS_XXX. 762 * @param ppFile Where to store the created audio file handle. 763 * Needs to be destroyed with DrvAudioHlpFileDestroy(). 764 */ 765 int DrvAudioHlpFileCreate(PDMAUDIOFILETYPE enmType, const char *pszFile, uint32_t fFlags, PPDMAUDIOFILE *ppFile) 766 { 767 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 768 /** @todo Validate fFlags. */ 769 770 PPDMAUDIOFILE pFile = (PPDMAUDIOFILE)RTMemAlloc(sizeof(PDMAUDIOFILE)); 771 if (!pFile) 772 return VERR_NO_MEMORY; 773 774 int rc = VINF_SUCCESS; 775 776 switch (enmType) 777 { 778 case PDMAUDIOFILETYPE_RAW: 779 case PDMAUDIOFILETYPE_WAV: 780 pFile->enmType = enmType; 781 break; 782 783 default: 784 rc = VERR_INVALID_PARAMETER; 785 break; 786 } 787 788 if (RT_SUCCESS(rc)) 789 { 790 RTStrPrintf(pFile->szName, RT_ELEMENTS(pFile->szName), "%s", pszFile); 791 pFile->hFile = NIL_RTFILE; 792 pFile->fFlags = fFlags; 793 pFile->pvData = NULL; 794 pFile->cbData = 0; 795 } 796 797 if (RT_FAILURE(rc)) 798 { 799 RTMemFree(pFile); 800 pFile = NULL; 801 } 802 else 803 *ppFile = pFile; 804 805 return rc; 806 } 807 808 /** 809 * Destroys a formerly created audio file. 810 * 811 * @param pFile Audio file (object) to destroy. 812 */ 813 void DrvAudioHlpFileDestroy(PPDMAUDIOFILE pFile) 814 { 815 if (!pFile) 816 return; 817 818 DrvAudioHlpFileClose(pFile); 819 820 RTMemFree(pFile); 821 pFile = NULL; 822 } 823 824 /** 825 * Opens or creates an audio file. 826 * 827 * @returns IPRT status code. 828 * @param pFile Pointer to audio file handle to use. 829 * @param fOpen Open flags. 830 * Use PDMAUDIOFILE_DEFAULT_OPEN_FLAGS for the default open flags. 831 * @param pProps PCM properties to use. 832 */ 833 int DrvAudioHlpFileOpen(PPDMAUDIOFILE pFile, uint32_t fOpen, PCPDMAUDIOPCMPROPS pProps) 834 { 835 AssertPtrReturn(pFile, VERR_INVALID_POINTER); 836 /** @todo Validate fOpen flags. */ 837 AssertPtrReturn(pProps, VERR_INVALID_POINTER); 838 839 int rc; 840 841 if (pFile->enmType == PDMAUDIOFILETYPE_RAW) 842 { 843 rc = RTFileOpen(&pFile->hFile, pFile->szName, fOpen); 844 } 845 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV) 846 { 847 Assert(pProps->cChannels); 848 Assert(pProps->uHz); 849 Assert(pProps->cbSample); 850 851 pFile->pvData = (PAUDIOWAVFILEDATA)RTMemAllocZ(sizeof(AUDIOWAVFILEDATA)); 852 if (pFile->pvData) 853 { 854 pFile->cbData = sizeof(PAUDIOWAVFILEDATA); 855 856 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData; 857 AssertPtr(pData); 858 859 /* Header. */ 860 pData->Hdr.u32RIFF = AUDIO_MAKE_FOURCC('R','I','F','F'); 861 pData->Hdr.u32Size = 36; 862 pData->Hdr.u32WAVE = AUDIO_MAKE_FOURCC('W','A','V','E'); 863 864 pData->Hdr.u32Fmt = AUDIO_MAKE_FOURCC('f','m','t',' '); 865 pData->Hdr.u32Size1 = 16; /* Means PCM. */ 866 pData->Hdr.u16AudioFormat = 1; /* PCM, linear quantization. */ 867 pData->Hdr.u16NumChannels = pProps->cChannels; 868 pData->Hdr.u32SampleRate = pProps->uHz; 869 pData->Hdr.u32ByteRate = PDMAudioPropsGetBitrate(pProps) / 8; 870 pData->Hdr.u16BlockAlign = pProps->cChannels * pProps->cbSample; 871 pData->Hdr.u16BitsPerSample = pProps->cbSample * 8; 872 873 /* Data chunk. */ 874 pData->Hdr.u32ID2 = AUDIO_MAKE_FOURCC('d','a','t','a'); 875 pData->Hdr.u32Size2 = 0; 876 877 rc = RTFileOpen(&pFile->hFile, pFile->szName, fOpen); 878 if (RT_SUCCESS(rc)) 879 { 880 rc = RTFileWrite(pFile->hFile, &pData->Hdr, sizeof(pData->Hdr), NULL); 881 if (RT_FAILURE(rc)) 882 { 883 RTFileClose(pFile->hFile); 884 pFile->hFile = NIL_RTFILE; 885 } 886 } 887 888 if (RT_FAILURE(rc)) 889 { 890 RTMemFree(pFile->pvData); 891 pFile->pvData = NULL; 892 pFile->cbData = 0; 893 } 894 } 895 else 896 rc = VERR_NO_MEMORY; 897 } 898 else 899 rc = VERR_INVALID_PARAMETER; 900 901 if (RT_SUCCESS(rc)) 902 { 903 LogRel2(("Audio: Opened file '%s'\n", pFile->szName)); 904 } 905 else 906 LogRel(("Audio: Failed opening file '%s', rc=%Rrc\n", pFile->szName, rc)); 907 908 return rc; 909 } 910 911 /** 912 * Closes an audio file. 913 * 914 * @returns IPRT status code. 915 * @param pFile Audio file handle to close. 916 */ 917 int DrvAudioHlpFileClose(PPDMAUDIOFILE pFile) 918 { 919 if (!pFile) 920 return VINF_SUCCESS; 921 922 size_t cbSize = DrvAudioHlpFileGetDataSize(pFile); 923 924 int rc = VINF_SUCCESS; 925 926 if (pFile->enmType == PDMAUDIOFILETYPE_RAW) 927 { 928 if (RTFileIsValid(pFile->hFile)) 929 rc = RTFileClose(pFile->hFile); 930 } 931 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV) 932 { 933 if (RTFileIsValid(pFile->hFile)) 934 { 935 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData; 936 if (pData) /* The .WAV file data only is valid when a file actually has been created. */ 937 { 938 /* Update the header with the current data size. */ 939 RTFileWriteAt(pFile->hFile, 0, &pData->Hdr, sizeof(pData->Hdr), NULL); 940 } 941 942 rc = RTFileClose(pFile->hFile); 943 } 944 945 if (pFile->pvData) 946 { 947 RTMemFree(pFile->pvData); 948 pFile->pvData = NULL; 949 } 950 } 951 else 952 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED); 953 954 if ( RT_SUCCESS(rc) 955 && !cbSize 956 && !(pFile->fFlags & PDMAUDIOFILE_FLAGS_KEEP_IF_EMPTY)) 957 { 958 rc = DrvAudioHlpFileDelete(pFile); 959 } 960 961 pFile->cbData = 0; 962 963 if (RT_SUCCESS(rc)) 964 { 965 pFile->hFile = NIL_RTFILE; 966 LogRel2(("Audio: Closed file '%s' (%zu bytes)\n", pFile->szName, cbSize)); 967 } 968 else 969 LogRel(("Audio: Failed closing file '%s', rc=%Rrc\n", pFile->szName, rc)); 970 971 return rc; 972 } 973 974 /** 975 * Deletes an audio file. 976 * 977 * @returns IPRT status code. 978 * @param pFile Audio file handle to delete. 979 */ 980 int DrvAudioHlpFileDelete(PPDMAUDIOFILE pFile) 981 { 982 AssertPtrReturn(pFile, VERR_INVALID_POINTER); 983 984 int rc = RTFileDelete(pFile->szName); 985 if (RT_SUCCESS(rc)) 986 { 987 LogRel2(("Audio: Deleted file '%s'\n", pFile->szName)); 988 } 989 else if (rc == VERR_FILE_NOT_FOUND) /* Don't bitch if the file is not around (anymore). */ 990 rc = VINF_SUCCESS; 991 992 if (RT_FAILURE(rc)) 993 LogRel(("Audio: Failed deleting file '%s', rc=%Rrc\n", pFile->szName, rc)); 994 995 return rc; 996 } 997 998 /** 999 * Returns the raw audio data size of an audio file. 1000 * 1001 * Note: This does *not* include file headers and other data which does 1002 * not belong to the actual PCM audio data. 1003 * 1004 * @returns Size (in bytes) of the raw PCM audio data. 1005 * @param pFile Audio file handle to retrieve the audio data size for. 1006 */ 1007 size_t DrvAudioHlpFileGetDataSize(PPDMAUDIOFILE pFile) 1008 { 1009 AssertPtrReturn(pFile, 0); 1010 1011 size_t cbSize = 0; 1012 1013 if (pFile->enmType == PDMAUDIOFILETYPE_RAW) 1014 { 1015 cbSize = RTFileTell(pFile->hFile); 1016 } 1017 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV) 1018 { 1019 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData; 1020 if (pData) /* The .WAV file data only is valid when a file actually has been created. */ 1021 cbSize = pData->Hdr.u32Size2; 1022 } 1023 1024 return cbSize; 1025 } 1026 1027 /** 1028 * Returns whether the given audio file is open and in use or not. 1029 * 1030 * @return bool True if open, false if not. 1031 * @param pFile Audio file handle to check open status for. 1032 */ 1033 bool DrvAudioHlpFileIsOpen(PPDMAUDIOFILE pFile) 1034 { 1035 if (!pFile) 1036 return false; 1037 1038 return RTFileIsValid(pFile->hFile); 1039 } 1040 1041 /** 1042 * Write PCM data to a wave (.WAV) file. 1043 * 1044 * @returns IPRT status code. 1045 * @param pFile Audio file handle to write PCM data to. 1046 * @param pvBuf Audio data to write. 1047 * @param cbBuf Size (in bytes) of audio data to write. 1048 * @param fFlags Additional write flags. Not being used at the moment and must be 0. 1049 */ 1050 int DrvAudioHlpFileWrite(PPDMAUDIOFILE pFile, const void *pvBuf, size_t cbBuf, uint32_t fFlags) 1051 { 1052 AssertPtrReturn(pFile, VERR_INVALID_POINTER); 1053 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1054 1055 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /** @todo fFlags are currently not implemented. */ 1056 1057 if (!cbBuf) 1058 return VINF_SUCCESS; 1059 1060 AssertReturn(RTFileIsValid(pFile->hFile), VERR_WRONG_ORDER); 1061 1062 int rc; 1063 1064 if (pFile->enmType == PDMAUDIOFILETYPE_RAW) 1065 { 1066 rc = RTFileWrite(pFile->hFile, pvBuf, cbBuf, NULL); 1067 } 1068 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV) 1069 { 1070 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData; 1071 AssertPtr(pData); 1072 1073 rc = RTFileWrite(pFile->hFile, pvBuf, cbBuf, NULL); 1074 if (RT_SUCCESS(rc)) 1075 { 1076 pData->Hdr.u32Size += (uint32_t)cbBuf; 1077 pData->Hdr.u32Size2 += (uint32_t)cbBuf; 1078 } 1079 } 1080 else 1081 rc = VERR_NOT_SUPPORTED; 1082 1083 return rc; 1084 } 1085 349 } 350 } 351 352 #endif /* VBOX_INCLUDED_vmm_pdmaudiohostenuminline_h */ -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88045 r88047 30 30 #include <VBox/vmm/pdmaudioifs.h> 31 31 #include <VBox/vmm/pdmaudioinline.h> 32 #include <VBox/vmm/pdmaudiohostenuminline.h> 32 33 33 34 #include <iprt/alloc.h> … … 2176 2177 if (fLog) 2177 2178 { 2178 char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags); 2179 2179 char szFlags[PDMAUDIOHOSTDEV_MAX_FLAGS_STRING_LEN]; 2180 2180 LogRel(("Audio: Device '%s':\n", pDev->szName)); 2181 LogRel(("Audio: \tUsage = %s\n", PDMAudioDirGetName(pDev->enmUsage))); 2182 LogRel(("Audio: \tFlags = %s\n", pszFlags ? pszFlags : "<NONE>")); 2183 LogRel(("Audio: \tInput channels = %RU8\n", pDev->cMaxInputChannels)); 2184 LogRel(("Audio: \tOutput channels = %RU8\n", pDev->cMaxOutputChannels)); 2185 2186 if (pszFlags) 2187 RTStrFree(pszFlags); 2181 LogRel(("Audio: Usage = %s\n", PDMAudioDirGetName(pDev->enmUsage))); 2182 LogRel(("Audio: Flags = %s\n", PDMAudioDeviceFlagsToString(szFlags, pDev->fFlags))); 2183 LogRel(("Audio: Input channels = %RU8\n", pDev->cMaxInputChannels)); 2184 LogRel(("Audio: Output channels = %RU8\n", pDev->cMaxOutputChannels)); 2188 2185 } 2189 2186 } -
trunk/src/VBox/Devices/Audio/DrvAudio.h
r88045 r88047 207 207 /** @} */ 208 208 209 /** @name Audio device methods.210 * @{ */211 PPDMAUDIOHOSTDEV PDMAudioDeviceAlloc(size_t cb);212 void PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev);213 PPDMAUDIOHOSTDEV PDMAudioDeviceDup(const PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData);214 /** @} */215 216 /** @name Audio device enumeration methods.217 * @{ */218 void PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm);219 void PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm);220 void PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev);221 int PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,222 PDMAUDIODIR enmUsage, bool fOnlyCoreData);223 PPDMAUDIOHOSTDEV PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmDir);224 uint32_t PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage);225 void PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc);226 /** @} */227 228 209 /** @name Audio string-ify methods. 229 210 * @{ */ 230 211 PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt); 231 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags);232 212 /** @} */ 233 213 -
trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp
r88045 r88047 142 142 143 143 #endif /* unused */ 144 145 /**146 * Allocates an audio device.147 *148 * @returns Newly allocated audio device, or NULL on failure.149 * @param cb The total device structure size. This must be at least the150 * size of PDMAUDIOHOSTDEV. The idea is that the caller extends151 * the PDMAUDIOHOSTDEV structure and appends additional data152 * after it in its private structure.153 */154 PPDMAUDIOHOSTDEV PDMAudioDeviceAlloc(size_t cb)155 {156 AssertReturn(cb >= sizeof(PDMAUDIOHOSTDEV), NULL);157 AssertReturn(cb < _4M, NULL);158 159 PPDMAUDIOHOSTDEV pDev = (PPDMAUDIOHOSTDEV)RTMemAllocZ(RT_ALIGN_Z(cb, 64));160 if (pDev)161 {162 pDev->uMagic = PDMAUDIOHOSTDEV_MAGIC;163 pDev->cbSelf = (uint32_t)cb;164 RTListInit(&pDev->Node);165 166 //pDev->cMaxInputChannels = 0;167 //pDev->cMaxOutputChannels = 0;168 }169 return pDev;170 }171 172 /**173 * Frees an audio device allocated by PDMAudioDeviceAlloc.174 *175 * @param pDev The device to free. NULL is ignored.176 */177 void PDMAudioDeviceFree(PPDMAUDIOHOSTDEV pDev)178 {179 if (pDev)180 {181 Assert(pDev->uMagic == PDMAUDIOHOSTDEV_MAGIC);182 Assert(pDev->cRefCount == 0);183 pDev->uMagic = PDMAUDIOHOSTDEV_MAGIC_DEAD;184 pDev->cbSelf = 0;185 186 RTMemFree(pDev);187 }188 }189 190 /**191 * Duplicates an audio device entry.192 *193 * @returns Duplicated audio device entry on success, or NULL on failure.194 * @param pDev The audio device enum entry to duplicate.195 * @param fOnlyCoreData196 */197 PPDMAUDIOHOSTDEV PDMAudioDeviceDup(PPDMAUDIOHOSTDEV pDev, bool fOnlyCoreData)198 {199 AssertPtrReturn(pDev, NULL);200 Assert(pDev->uMagic == PDMAUDIOHOSTDEV_MAGIC);201 Assert(fOnlyCoreData || !(pDev->fFlags & PDMAUDIOHOSTDEV_F_NO_DUP));202 203 uint32_t cbToDup = fOnlyCoreData ? sizeof(PDMAUDIOHOSTDEV) : pDev->cbSelf;204 AssertReturn(cbToDup >= sizeof(*pDev), NULL);205 206 PPDMAUDIOHOSTDEV pDevDup = PDMAudioDeviceAlloc(cbToDup);207 if (pDevDup)208 {209 memcpy(pDevDup, pDev, cbToDup);210 RTListInit(&pDevDup->Node);211 pDev->cbSelf = cbToDup;212 }213 214 return pDevDup;215 }216 217 /**218 * Initializes a host audio device enumeration.219 *220 * @param pDevEnm The enumeration to initialize.221 */222 void PDMAudioHostEnumInit(PPDMAUDIOHOSTENUM pDevEnm)223 {224 AssertPtr(pDevEnm);225 226 pDevEnm->uMagic = PDMAUDIOHOSTENUM_MAGIC;227 pDevEnm->cDevices = 0;228 RTListInit(&pDevEnm->LstDevices);229 }230 231 /**232 * Deletes the host audio device enumeration and frees all device entries233 * associated with it.234 *235 * The user must call PDMAudioHostEnumInit again to use it again.236 *237 * @param pDevEnm The host audio device enumeration to delete.238 */239 void PDMAudioHostEnumDelete(PPDMAUDIOHOSTENUM pDevEnm)240 {241 if (pDevEnm)242 {243 AssertPtr(pDevEnm);244 AssertReturnVoid(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);245 246 PPDMAUDIOHOSTDEV pDev, pDevNext;247 RTListForEachSafe(&pDevEnm->LstDevices, pDev, pDevNext, PDMAUDIOHOSTDEV, Node)248 {249 RTListNodeRemove(&pDev->Node);250 251 PDMAudioDeviceFree(pDev);252 253 pDevEnm->cDevices--;254 }255 256 /* Sanity. */257 Assert(RTListIsEmpty(&pDevEnm->LstDevices));258 Assert(pDevEnm->cDevices == 0);259 260 pDevEnm->uMagic = ~PDMAUDIOHOSTENUM_MAGIC;261 }262 }263 264 /**265 * Adds an audio device to a device enumeration.266 *267 * @param pDevEnm Device enumeration to add device to.268 * @param pDev Device to add. The pointer will be owned by the device enumeration then.269 */270 void PDMAudioHostEnumAppend(PPDMAUDIOHOSTENUM pDevEnm, PPDMAUDIOHOSTDEV pDev)271 {272 AssertPtr(pDevEnm);273 AssertPtr(pDev);274 Assert(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);275 276 RTListAppend(&pDevEnm->LstDevices, &pDev->Node);277 pDevEnm->cDevices++;278 }279 280 /**281 * Appends copies of matching host device entries from one to another enumeration.282 *283 * @returns IPRT status code.284 * @param pDstDevEnm The target to append copies of matching device to.285 * @param pSrcDevEnm The source to copy matching devices from.286 * @param enmUsage The usage to match for copying.287 * Use PDMAUDIODIR_INVALID to match all entries.288 * @param fOnlyCoreData Set this to only copy the PDMAUDIOHOSTDEV part.289 * Careful with passing @c false here as not all290 * backends have data that can be copied.291 */292 int PDMAudioHostEnumCopy(PPDMAUDIOHOSTENUM pDstDevEnm, PCPDMAUDIOHOSTENUM pSrcDevEnm,293 PDMAUDIODIR enmUsage, bool fOnlyCoreData)294 {295 AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER);296 AssertReturn(pDstDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);297 298 AssertPtrReturn(pSrcDevEnm, VERR_INVALID_POINTER);299 AssertReturn(pSrcDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, VERR_WRONG_ORDER);300 301 PPDMAUDIOHOSTDEV pSrcDev;302 RTListForEach(&pSrcDevEnm->LstDevices, pSrcDev, PDMAUDIOHOSTDEV, Node)303 {304 if ( enmUsage == pSrcDev->enmUsage305 || enmUsage == PDMAUDIODIR_INVALID /*all*/)306 {307 PPDMAUDIOHOSTDEV pDstDev = PDMAudioDeviceDup(pSrcDev, fOnlyCoreData);308 AssertReturn(pDstDev, VERR_NO_MEMORY);309 310 PDMAudioHostEnumAppend(pDstDevEnm, pDstDev);311 }312 }313 314 return VINF_SUCCESS;315 }316 317 /**318 * Get the default device with the given usage.319 *320 * This assumes that only one default device per usage is set, if there should321 * be more than one, the first one is returned.322 *323 * @returns Default device if found, or NULL if not.324 * @param pDevEnm Device enumeration to get default device for.325 * @param enmUsage Usage to get default device for.326 * Pass PDMAUDIODIR_INVALID to get the first device with327 * PDMAUDIOHOSTDEV_F_DEFAULT set.328 */329 PPDMAUDIOHOSTDEV PDMAudioHostEnumGetDefault(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)330 {331 AssertPtrReturn(pDevEnm, NULL);332 AssertReturn(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, NULL);333 334 PPDMAUDIOHOSTDEV pDev;335 RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)336 {337 if (pDev->fFlags & PDMAUDIOHOSTDEV_F_DEFAULT)338 {339 if ( enmUsage == pDev->enmUsage340 || enmUsage == PDMAUDIODIR_INVALID)341 return pDev;342 }343 }344 345 return NULL;346 }347 348 /**349 * Get the number of device with the given usage.350 *351 * @returns Number of matching devices.352 * @param pDevEnm Device enumeration to get default device for.353 * @param enmUsage Usage to count devices for.354 * Pass PDMAUDIODIR_INVALID to get the total number of devices.355 */356 uint32_t PDMAudioHostEnumCountMatching(PCPDMAUDIOHOSTENUM pDevEnm, PDMAUDIODIR enmUsage)357 {358 AssertPtrReturn(pDevEnm, 0);359 AssertReturn(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC, 0);360 361 if (enmUsage == PDMAUDIODIR_INVALID)362 return pDevEnm->cDevices;363 364 uint32_t cDevs = 0;365 PPDMAUDIOHOSTDEV pDev;366 RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)367 {368 if (enmUsage == pDev->enmUsage)369 cDevs++;370 }371 372 return cDevs;373 }374 375 /**376 * Logs an audio device enumeration.377 *378 * @param pDevEnm Device enumeration to log.379 * @param pszDesc Logging description (prefix).380 */381 void PDMAudioHostEnumLog(PCPDMAUDIOHOSTENUM pDevEnm, const char *pszDesc)382 {383 AssertPtrReturnVoid(pDevEnm);384 AssertPtrReturnVoid(pszDesc);385 AssertReturnVoid(pDevEnm->uMagic == PDMAUDIOHOSTENUM_MAGIC);386 387 LogFunc(("%s: %RU32 devices\n", pszDesc, pDevEnm->cDevices));388 389 PPDMAUDIOHOSTDEV pDev;390 RTListForEach(&pDevEnm->LstDevices, pDev, PDMAUDIOHOSTDEV, Node)391 {392 char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags);393 394 LogFunc(("Device '%s':\n", pDev->szName));395 LogFunc((" Usage = %s\n", PDMAudioDirGetName(pDev->enmUsage)));396 LogFunc((" Flags = %s\n", pszFlags ? pszFlags : "<NONE>"));397 LogFunc((" Input channels = %RU8\n", pDev->cMaxInputChannels));398 LogFunc((" Output channels = %RU8\n", pDev->cMaxOutputChannels));399 LogFunc((" cbExtra = %RU32 bytes\n", pDev->cbSelf - sizeof(PDMAUDIOHOSTDEV)));400 401 if (pszFlags)402 RTStrFree(pszFlags);403 }404 }405 406 /**407 * Converts an audio device flags to a string.408 *409 * @returns Stringified audio flags. Must be free'd with RTStrFree().410 * NULL if no flags set.411 * @param fFlags Audio flags (PDMAUDIOHOSTDEV_F_XXX) to convert.412 */413 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags)414 {415 #define APPEND_FLAG_TO_STR(_aFlag) \416 if (fFlags & PDMAUDIOHOSTDEV_F_##_aFlag) \417 { \418 if (pszFlags) \419 { \420 rc2 = RTStrAAppend(&pszFlags, " "); \421 if (RT_FAILURE(rc2)) \422 break; \423 } \424 \425 rc2 = RTStrAAppend(&pszFlags, #_aFlag); \426 if (RT_FAILURE(rc2)) \427 break; \428 } \429 430 char *pszFlags = NULL;431 int rc2 = VINF_SUCCESS;432 433 do434 {435 APPEND_FLAG_TO_STR(DEFAULT);436 APPEND_FLAG_TO_STR(HOTPLUG);437 APPEND_FLAG_TO_STR(BUGGY);438 APPEND_FLAG_TO_STR(IGNORE);439 APPEND_FLAG_TO_STR(LOCKED);440 APPEND_FLAG_TO_STR(DEAD);441 APPEND_FLAG_TO_STR(NO_DUP);442 443 } while (0);444 445 if (!pszFlags)446 rc2 = RTStrAAppend(&pszFlags, "NONE");447 448 if ( RT_FAILURE(rc2)449 && pszFlags)450 {451 RTStrFree(pszFlags);452 pszFlags = NULL;453 }454 455 #undef APPEND_FLAG_TO_STR456 457 return pszFlags;458 }459 144 460 145 /** -
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r88045 r88047 23 23 #include <VBox/log.h> 24 24 #include <VBox/vmm/pdmaudioinline.h> 25 #include <VBox/vmm/pdmaudiohostenuminline.h> 25 26 26 27 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r88045 r88047 31 31 32 32 #include <VBox/vmm/pdmaudioinline.h> 33 #include <VBox/vmm/pdmaudiohostenuminline.h> 33 34 34 35 #include "DrvAudio.h"
Note:
See TracChangeset
for help on using the changeset viewer.