Changeset 88287 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Mar 25, 2021 10:34:19 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostAudioOss.cpp
r88269 r88287 16 16 */ 17 17 18 19 /********************************************************************************************************************************* 20 * Header Files * 21 *********************************************************************************************************************************/ 18 22 #include <errno.h> 19 23 #include <fcntl.h> … … 37 41 * Defines * 38 42 *********************************************************************************************************************************/ 39 40 43 #if ((SOUND_VERSION > 360) && (defined(OSS_SYSINFO))) 41 44 /* OSS > 3.6 has a new syscall available for querying a bit more detailed information … … 52 55 * Structures * 53 56 *********************************************************************************************************************************/ 54 55 57 /** 56 58 * OSS host audio driver instance data. … … 210 212 static int ossStreamOpen(const char *pszDev, int fOpen, POSSAUDIOSTREAMCFG pOSSReq, POSSAUDIOSTREAMCFG pOSSAcq, int *phFile) 211 213 { 212 int rc = V ERR_AUDIO_STREAM_COULD_NOT_CREATE;214 int rc = VINF_SUCCESS; 213 215 214 216 int fdFile = -1; … … 230 232 231 233 case 2: 232 /** @todo r=bird: You're ASSUMING stuff about pOSSReq->Props.fSwapEndian and 233 * the host endian here. */ 234 iFormat = pOSSReq->Props.fSigned ? AFMT_S16_LE : AFMT_U16_LE; 234 if (PDMAudioPropsIsLittleEndian(&pOSSReq->Props)) 235 iFormat = pOSSReq->Props.fSigned ? AFMT_S16_LE : AFMT_U16_LE; 236 else 237 iFormat = pOSSReq->Props.fSigned ? AFMT_S16_BE : AFMT_U16_BE; 235 238 break; 236 239 … … 290 293 if (ioctl(fdFile, fIn ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &abinfo)) 291 294 { 292 LogRel(("OSS: Failed to retrieve %s buffer length: %s (%d)\n", fIn ? "input" : "output", strerror(errno), errno)); 295 LogRel(("OSS: Failed to retrieve %c" 296 "s buffer length: %s (%d)\n", fIn ? "input" : "output", strerror(errno), errno)); 293 297 break; 294 298 } … … 508 512 } 509 513 else 510 { 511 #endif 514 #endif 515 { 512 516 if (pStreamOSS->pvBuf) 513 517 { … … 519 523 520 524 pStreamOSS->cbBuf = 0; 521 #ifndef RT_OS_L4 522 } 523 #endif 525 } 524 526 525 527 ossStreamClose(&pStreamOSS->hFile); … … 688 690 } 689 691 690 if (RT_SUCCESS(rc)) 692 if (RT_SUCCESS(rc)) /** @todo r=bird: great code structure ... */ 691 693 { 692 694 pStreamOSS->Out.fMMIO = false; … … 778 780 */ 779 781 static DECLCALLBACK(int) drvHostOssAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 780 const void *pvBuf, uint32_t uBufSize, uint32_t *puWritten) 781 { 782 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 783 { 784 POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream; 785 AssertPtrReturn(pStreamOSS, VERR_INVALID_POINTER); 782 786 RT_NOREF(pInterface); 783 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 784 785 POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream; 786 787 int rc = VINF_SUCCESS; 788 uint32_t cbWrittenTotal = 0; 789 787 788 /* 789 * Figure out now much to write. 790 */ 791 uint32_t cbToWrite; 790 792 #ifndef RT_OS_L4 791 count_info cntinfo; 792 #endif 793 794 do 795 { 796 uint32_t cbAvail = uBufSize; 797 uint32_t cbToWrite; 793 count_info CountInfo = {0,0,0}; 794 if (pStreamOSS->Out.fMMIO) 795 { 796 /* Get current playback pointer. */ 797 int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOPTR, &CountInfo); 798 AssertLogRelMsgReturn(rc2 >= 0, ("OSS: Failed to retrieve current playback pointer: %s (%d)\n", strerror(errno), errno), 799 RTErrConvertFromErrno(errno)); 800 801 int cbData; 802 if (CountInfo.ptr >= pStreamOSS->old_optr) 803 cbData = CountInfo.ptr - pStreamOSS->old_optr; 804 else 805 cbData = pStreamOSS->cbBuf + CountInfo.ptr - pStreamOSS->old_optr; 806 Assert(cbData >= 0); 807 cbToWrite = (unsigned)cbData; 808 } 809 else 810 #endif 811 { 812 audio_buf_info abinfo; 813 int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo); 814 AssertLogRelMsgReturn(rc2 >= 0, ("OSS: Failed to retrieve current playback buffer: %s (%d)\n", strerror(errno), errno), 815 RTErrConvertFromErrno(errno)); 816 817 #if 0 /** @todo r=bird: WTF do we make a fuss over abinfo.bytes for when we don't even use it?!? */ 818 AssertLogRelMsgReturn(abinfo.bytes >= 0, ("OSS: Warning: Invalid available size: %d\n", abinfo.bytes), VERR_INTERNAL_ERROR_3); 819 if ((unsigned)abinfo.bytes > cbBuf) 820 { 821 LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, cbBuf, cbBuf)); 822 abinfo.bytes = cbBuf; 823 /* Keep going. */ 824 } 825 #endif 826 cbToWrite = (unsigned)(abinfo.fragments * abinfo.fragsize); 827 } 828 cbToWrite = RT_MIN(cbToWrite, cbBuf); 829 cbToWrite = RT_MIN(cbToWrite, pStreamOSS->cbBuf); 830 831 /* 832 * This is probably for the mmap functionality and not needed in the no-mmap case. 833 */ 834 /** @todo skip for non-mmap? */ 835 uint8_t *pbBuf = (uint8_t *)memcpy(pStreamOSS->pvBuf, pvBuf, cbToWrite); 836 837 /* 838 * Write. 839 */ 840 uint32_t cbChunk = cbToWrite; 841 uint32_t offChunk = 0; 842 while (cbChunk > 0) 843 { 844 ssize_t cbWritten = write(pStreamOSS->hFile, &pbBuf[offChunk], RT_MIN(cbChunk, (unsigned)s_OSSConf.fragsize)); 845 if (cbWritten >= 0) 846 { 847 AssertLogRelMsg(!(cbWritten & pStreamOSS->uAlign), 848 ("OSS: Misaligned write (written %#zx, alignment %#x)\n", cbWritten, pStreamOSS->uAlign)); 849 850 Assert((uint32_t)cbWritten <= cbChunk); 851 offChunk += (uint32_t)cbWritten; 852 cbChunk -= (uint32_t)cbWritten; 853 } 854 else 855 { 856 LogRel(("OSS: Failed writing output data: %s (%d)\n", strerror(errno), errno)); 857 return RTErrConvertFromErrno(errno); 858 } 859 } 798 860 799 861 #ifndef RT_OS_L4 800 if (pStreamOSS->Out.fMMIO) 801 { 802 /* Get current playback pointer. */ 803 int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOPTR, &cntinfo); 804 if (!rc2) 805 { 806 LogRel(("OSS: Failed to retrieve current playback pointer: %s\n", strerror(errno))); 807 rc = RTErrConvertFromErrno(errno); 808 break; 809 } 810 811 /* Nothing to play? */ 812 if (cntinfo.ptr == pStreamOSS->old_optr) 813 break; 814 815 int cbData; 816 if (cntinfo.ptr > pStreamOSS->old_optr) 817 cbData = cntinfo.ptr - pStreamOSS->old_optr; 818 else 819 cbData = uBufSize + cntinfo.ptr - pStreamOSS->old_optr; 820 Assert(cbData >= 0); 821 822 cbToWrite = RT_MIN((unsigned)cbData, cbAvail); 823 } 824 else 825 { 826 #endif 827 audio_buf_info abinfo; 828 int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo); 829 if (rc2 < 0) 830 { 831 LogRel(("OSS: Failed to retrieve current playback buffer: %s\n", strerror(errno))); 832 rc = RTErrConvertFromErrno(errno); 833 break; 834 } 835 836 if ((size_t)abinfo.bytes > uBufSize) 837 { 838 LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, uBufSize, uBufSize)); 839 abinfo.bytes = uBufSize; 840 /* Keep going. */ 841 } 842 843 if (abinfo.bytes < 0) 844 { 845 LogRel2(("OSS: Warning: Invalid available size (%d vs. %RU32)\n", abinfo.bytes, uBufSize)); 846 rc = VERR_INVALID_PARAMETER; 847 break; 848 } 849 850 cbToWrite = RT_MIN(unsigned(abinfo.fragments * abinfo.fragsize), cbAvail); 851 #ifndef RT_OS_L4 852 } 853 #endif 854 cbToWrite = RT_MIN(cbToWrite, pStreamOSS->cbBuf); 855 856 while (cbToWrite) 857 { 858 uint32_t cbWritten = cbToWrite; 859 860 memcpy(pStreamOSS->pvBuf, pvBuf, cbWritten); 861 862 uint32_t cbChunk = cbWritten; 863 uint32_t cbChunkOff = 0; 864 while (cbChunk) 865 { 866 ssize_t cbChunkWritten = write(pStreamOSS->hFile, (uint8_t *)pStreamOSS->pvBuf + cbChunkOff, 867 RT_MIN(cbChunk, (unsigned)s_OSSConf.fragsize)); 868 if (cbChunkWritten < 0) 869 { 870 LogRel(("OSS: Failed writing output data: %s\n", strerror(errno))); 871 rc = RTErrConvertFromErrno(errno); 872 break; 873 } 874 875 if (cbChunkWritten & pStreamOSS->uAlign) 876 { 877 LogRel(("OSS: Misaligned write (written %z, expected %RU32)\n", cbChunkWritten, cbChunk)); 878 break; 879 } 880 881 cbChunkOff += (uint32_t)cbChunkWritten; 882 Assert(cbChunkOff <= cbWritten); 883 Assert(cbChunk >= (uint32_t)cbChunkWritten); 884 cbChunk -= (uint32_t)cbChunkWritten; 885 } 886 887 Assert(cbToWrite >= cbWritten); 888 cbToWrite -= cbWritten; 889 cbWrittenTotal += cbWritten; 890 } 891 892 #ifndef RT_OS_L4 893 /* Update read pointer. */ 894 if (pStreamOSS->Out.fMMIO) 895 pStreamOSS->old_optr = cntinfo.ptr; 896 #endif 897 898 } while(0); 899 900 if (RT_SUCCESS(rc)) 901 { 902 if (puWritten) 903 *puWritten = cbWrittenTotal; 904 } 905 906 return rc; 862 /* Update read pointer. */ 863 if (pStreamOSS->Out.fMMIO) 864 pStreamOSS->old_optr = CountInfo.ptr; 865 #endif 866 867 *pcbWritten = cbToWrite; 868 return VINF_SUCCESS; 907 869 } 908 870 … … 1042 1004 static DECLCALLBACK(uint32_t) drvHostOssAudioHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 1043 1005 { 1044 RT_NOREF(pInterface, pStream); 1045 return UINT32_MAX; 1006 POSSAUDIOSTREAM pStreamOSS = (POSSAUDIOSTREAM)pStream; 1007 AssertPtr(pStreamOSS); 1008 RT_NOREF(pInterface); 1009 1010 /* 1011 * Note! This logic was found in StreamPlay and corrected a little. 1012 * 1013 * The logic here must match what StreamPlay does. 1014 */ 1015 uint32_t cbWritable; 1016 #ifndef RT_OS_L4 1017 count_info CountInfo = {0,0,0}; 1018 if (pStreamOSS->Out.fMMIO) 1019 { 1020 /* Get current playback pointer. */ 1021 int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOPTR, &CountInfo); 1022 AssertMsgReturn(rc2 >= 0, ("SNDCTL_DSP_GETOPTR failed: %s (%d)\n", strerror(errno), errno), 0); 1023 1024 int cbData; 1025 if (CountInfo.ptr >= pStreamOSS->old_optr) 1026 cbData = CountInfo.ptr - pStreamOSS->old_optr; 1027 else 1028 cbData = pStreamOSS->cbBuf + CountInfo.ptr - pStreamOSS->old_optr; 1029 Assert(cbData >= 0); 1030 cbWritable = (unsigned)cbData; 1031 } 1032 else 1033 #endif 1034 { 1035 audio_buf_info abinfo = { 0, 0, 0, 0 }; 1036 int rc2 = ioctl(pStreamOSS->hFile, SNDCTL_DSP_GETOSPACE, &abinfo); 1037 AssertMsgReturn(rc2 >= 0, ("SNDCTL_DSP_GETOSPACE failed: %s (%d)\n", strerror(errno), errno), 0); 1038 1039 #if 0 /** @todo we could return abinfo.bytes here iff StreamPlay didn't use the fragmented approach */ 1040 /** @todo r=bird: WTF do we make a fuss over abinfo.bytes for when we don't even use it?!? */ 1041 AssertLogRelMsgReturn(abinfo.bytes >= 0, ("OSS: Warning: Invalid available size: %d\n", abinfo.bytes), VERR_INTERNAL_ERROR_3); 1042 if ((unsigned)abinfo.bytes > cbBuf) 1043 { 1044 LogRel2(("OSS: Warning: Too big output size (%d > %RU32), limiting to %RU32\n", abinfo.bytes, cbBuf, cbBuf)); 1045 abinfo.bytes = cbBuf; 1046 /* Keep going. */ 1047 } 1048 #endif 1049 1050 cbWritable = (uint32_t)(abinfo.fragments * abinfo.fragsize); 1051 } 1052 cbWritable = RT_MIN(cbWritable, pStreamOSS->cbBuf); 1053 return cbWritable; 1046 1054 } 1047 1055
Note:
See TracChangeset
for help on using the changeset viewer.