Changeset 89481 in vbox for trunk/src/VBox
- Timestamp:
- Jun 3, 2021 12:46:22 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvHostAudioAlsa.cpp
r89480 r89481 75 75 * ALSA host audio specific stream data. 76 76 */ 77 typedef struct ALSAAUDIOSTREAM77 typedef struct DRVHSTAUDALSASTREAM 78 78 { 79 79 /** Common part. */ … … 87 87 /** The stream's acquired configuration. */ 88 88 PDMAUDIOSTREAMCFG Cfg; 89 } ALSAAUDIOSTREAM;89 } DRVHSTAUDALSASTREAM; 90 90 /** Pointer to the ALSA host audio specific stream data. */ 91 typedef ALSAAUDIOSTREAM *PALSAAUDIOSTREAM;91 typedef DRVHSTAUDALSASTREAM *PDRVHSTAUDALSASTREAM; 92 92 93 93 … … 96 96 * @implements PDMIAUDIOCONNECTOR 97 97 */ 98 typedef struct DRVH OSTALSAAUDIO98 typedef struct DRVHSTAUDALSA 99 99 { 100 100 /** Pointer to the driver instance structure. */ … … 109 109 /** Default output device name. */ 110 110 char szDefaultOut[256]; 111 } DRVH OSTALSAAUDIO;111 } DRVHSTAUDALSA; 112 112 /** Pointer to the instance data of an ALSA host audio driver. */ 113 typedef DRVH OSTALSAAUDIO *PDRVHOSTALSAAUDIO;113 typedef DRVHSTAUDALSA *PDRVHSTAUDALSA; 114 114 115 115 … … 122 122 * NULL. 123 123 */ 124 static int alsaStreamClose(snd_pcm_t **phPCM)124 static int drvHstAudAlsaStreamClose(snd_pcm_t **phPCM) 125 125 { 126 126 if (!phPCM || !*phPCM) … … 146 146 147 147 #ifdef DEBUG 148 static void alsaDbgErrorHandler(const char *file, int line, const char *function,149 int err, const char *fmt, ...)148 static void drvHstAudAlsaDbgErrorHandler(const char *file, int line, const char *function, 149 int err, const char *fmt, ...) 150 150 { 151 151 /** @todo Implement me! */ … … 161 161 * @param hPCM ALSA stream handle. 162 162 */ 163 static int alsaStreamRecover(snd_pcm_t *hPCM)163 static int drvHstAudAlsaStreamRecover(snd_pcm_t *hPCM) 164 164 { 165 165 AssertPtrReturn(hPCM, VERR_INVALID_POINTER); … … 179 179 * Resumes an ALSA stream. 180 180 * 181 * Used by drvHstAudAlsaHA_StreamPlay() and drvHstAudAlsaHA_StreamCapture(). 182 * 181 183 * @returns VBox status code. 182 184 * @param hPCM ALSA stream to resume. 183 185 */ 184 static int alsaStreamResume(snd_pcm_t *hPCM)186 static int drvHstAudAlsaStreamResume(snd_pcm_t *hPCM) 185 187 { 186 188 AssertPtrReturn(hPCM, VERR_INVALID_POINTER); … … 200 202 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetConfig} 201 203 */ 202 static DECLCALLBACK(int) drvH ostAlsaAudioHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg)204 static DECLCALLBACK(int) drvHstAudAlsaHA_GetConfig(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDCFG pBackendCfg) 203 205 { 204 206 RT_NOREF(pInterface); … … 209 211 */ 210 212 RTStrCopy(pBackendCfg->szName, sizeof(pBackendCfg->szName), "ALSA"); 211 pBackendCfg->cbStream = sizeof( ALSAAUDIOSTREAM);213 pBackendCfg->cbStream = sizeof(DRVHSTAUDALSASTREAM); 212 214 pBackendCfg->fFlags = 0; 213 215 /* ALSA allows exactly one input and one output used at a time for the selected device(s). */ … … 222 224 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetDevices} 223 225 */ 224 static DECLCALLBACK(int) drvH ostAlsaAudioHA_GetDevices(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHOSTENUM pDeviceEnum)226 static DECLCALLBACK(int) drvHstAudAlsaHA_GetDevices(PPDMIHOSTAUDIO pInterface, PPDMAUDIOHOSTENUM pDeviceEnum) 225 227 { 226 228 RT_NOREF(pInterface); … … 321 323 * @interface_method_impl{PDMIHOSTAUDIO,pfnGetStatus} 322 324 */ 323 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvH ostAlsaAudioHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir)325 static DECLCALLBACK(PDMAUDIOBACKENDSTS) drvHstAudAlsaHA_GetStatus(PPDMIHOSTAUDIO pInterface, PDMAUDIODIR enmDir) 324 326 { 325 327 RT_NOREF(enmDir); … … 617 619 * @param phPCM Where to store the ALSA stream handle on success. 618 620 */ 619 static int alsaStreamOpen(PDRVH OSTALSAAUDIOpThis, snd_pcm_format_t enmAlsaFmt, PCPDMAUDIOSTREAMCFG pCfgReq,621 static int alsaStreamOpen(PDRVHSTAUDALSA pThis, snd_pcm_format_t enmAlsaFmt, PCPDMAUDIOSTREAMCFG pCfgReq, 620 622 PPDMAUDIOSTREAMCFG pCfgAcq, snd_pcm_t **phPCM) 621 623 { … … 665 667 else 666 668 LogRel(("ALSA: Error setting non-blocking mode for %s stream: %s\n", pszType, snd_strerror(err))); 667 alsaStreamClose(&hPCM);669 drvHstAudAlsaStreamClose(&hPCM); 668 670 } 669 671 else … … 677 679 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCreate} 678 680 */ 679 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,680 681 { 682 PDRVH OSTALSAAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVHOSTALSAAUDIO, IHostAudio);681 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamCreate(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 682 PPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq) 683 { 684 PDRVHSTAUDALSA pThis = RT_FROM_MEMBER(pInterface, DRVHSTAUDALSA, IHostAudio); 683 685 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 684 686 AssertPtrReturn(pStream, VERR_INVALID_POINTER); … … 686 688 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER); 687 689 688 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;690 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 689 691 PDMAudioStrmCfgCopy(&pStreamALSA->Cfg, pCfgReq); 690 692 … … 717 719 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamDestroy} 718 720 */ 719 static DECLCALLBACK(int) drvHostAlsaAudioHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 720 bool fImmediate) 721 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamDestroy(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, bool fImmediate) 721 722 { 722 723 RT_NOREF(pInterface); 723 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;724 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 724 725 AssertPtrReturn(pStreamALSA, VERR_INVALID_POINTER); 725 726 RT_NOREF(fImmediate); … … 727 728 /** @todo r=bird: It's not like we can do much with a bad status... Check 728 729 * what the caller does... */ 729 return alsaStreamClose(&pStreamALSA->hPCM);730 return drvHstAudAlsaStreamClose(&pStreamALSA->hPCM); 730 731 } 731 732 … … 734 735 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamEnable} 735 736 */ 736 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamEnable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)737 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamEnable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 737 738 { 738 739 RT_NOREF(pInterface); 739 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;740 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 740 741 741 742 /* … … 778 779 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDisable} 779 780 */ 780 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamDisable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)781 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamDisable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 781 782 { 782 783 RT_NOREF(pInterface); 783 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;784 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 784 785 785 786 int rc = snd_pcm_drop(pStreamALSA->hPCM); … … 799 800 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamPause} 800 801 */ 801 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamPause(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)802 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamPause(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 802 803 { 803 804 /* Same as disable. */ 804 805 /** @todo r=bird: Try use pause and fallback on disable/enable if it isn't 805 806 * supported or doesn't work. */ 806 return drvH ostAlsaAudioHA_StreamDisable(pInterface, pStream);807 return drvHstAudAlsaHA_StreamDisable(pInterface, pStream); 807 808 } 808 809 … … 811 812 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamResume} 812 813 */ 813 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamResume(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)814 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamResume(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 814 815 { 815 816 /* Same as enable. */ 816 return drvH ostAlsaAudioHA_StreamEnable(pInterface, pStream);817 return drvHstAudAlsaHA_StreamEnable(pInterface, pStream); 817 818 } 818 819 … … 821 822 * @ interface_method_impl{PDMIHOSTAUDIO,pfnStreamDrain} 822 823 */ 823 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamDrain(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)824 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamDrain(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 824 825 { 825 826 RT_NOREF(pInterface); 826 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;827 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 827 828 828 829 snd_pcm_state_t const enmState = snd_pcm_state(pStreamALSA->hPCM); … … 880 881 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamControl} 881 882 */ 882 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamControl(PPDMIHOSTAUDIO pInterface,883 883 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamControl(PPDMIHOSTAUDIO pInterface, 884 PPDMAUDIOBACKENDSTREAM pStream, PDMAUDIOSTREAMCMD enmStreamCmd) 884 885 { 885 886 /** @todo r=bird: I'd like to get rid of this pfnStreamControl method, … … 890 891 { 891 892 case PDMAUDIOSTREAMCMD_ENABLE: 892 return drvH ostAlsaAudioHA_StreamEnable(pInterface, pStream);893 return drvHstAudAlsaHA_StreamEnable(pInterface, pStream); 893 894 case PDMAUDIOSTREAMCMD_DISABLE: 894 return drvH ostAlsaAudioHA_StreamDisable(pInterface, pStream);895 return drvHstAudAlsaHA_StreamDisable(pInterface, pStream); 895 896 case PDMAUDIOSTREAMCMD_PAUSE: 896 return drvH ostAlsaAudioHA_StreamPause(pInterface, pStream);897 return drvHstAudAlsaHA_StreamPause(pInterface, pStream); 897 898 case PDMAUDIOSTREAMCMD_RESUME: 898 return drvH ostAlsaAudioHA_StreamResume(pInterface, pStream);899 return drvHstAudAlsaHA_StreamResume(pInterface, pStream); 899 900 case PDMAUDIOSTREAMCMD_DRAIN: 900 return drvH ostAlsaAudioHA_StreamDrain(pInterface, pStream);901 return drvHstAudAlsaHA_StreamDrain(pInterface, pStream); 901 902 902 903 case PDMAUDIOSTREAMCMD_END: … … 936 937 if (cFramesAvail == -EPIPE) 937 938 { 938 rc = alsaStreamRecover(hPCM);939 rc = drvHstAudAlsaStreamRecover(hPCM); 939 940 if (RT_SUCCESS(rc)) 940 941 { … … 964 965 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetReadable} 965 966 */ 966 static DECLCALLBACK(uint32_t) drvH ostAlsaAudioHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)967 static DECLCALLBACK(uint32_t) drvHstAudAlsaHA_StreamGetReadable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 967 968 { 968 969 RT_NOREF(pInterface); 969 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;970 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 970 971 971 972 uint32_t cbAvail = 0; … … 982 983 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetWritable} 983 984 */ 984 static DECLCALLBACK(uint32_t) drvH ostAlsaAudioHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)985 static DECLCALLBACK(uint32_t) drvHstAudAlsaHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 985 986 { 986 987 RT_NOREF(pInterface); 987 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;988 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 988 989 989 990 uint32_t cbAvail = 0; … … 1000 1001 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetPending} 1001 1002 */ 1002 static DECLCALLBACK(uint32_t) drvH ostAlsaAudioHA_StreamGetPending(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream)1003 static DECLCALLBACK(uint32_t) drvHstAudAlsaHA_StreamGetPending(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 1003 1004 { 1004 1005 RT_NOREF(pInterface); 1005 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;1006 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 1006 1007 AssertPtrReturn(pStreamALSA, 0); 1007 1008 … … 1058 1059 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamGetState} 1059 1060 */ 1060 static DECLCALLBACK(PDMHOSTAUDIOSTREAMSTATE) drvH ostAlsaAudioHA_StreamGetState(PPDMIHOSTAUDIO pInterface,1061 1061 static DECLCALLBACK(PDMHOSTAUDIOSTREAMSTATE) drvHstAudAlsaHA_StreamGetState(PPDMIHOSTAUDIO pInterface, 1062 PPDMAUDIOBACKENDSTREAM pStream) 1062 1063 { 1063 1064 RT_NOREF(pInterface); 1064 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;1065 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 1065 1066 AssertPtrReturn(pStreamALSA, PDMHOSTAUDIOSTREAMSTATE_INVALID); 1066 1067 … … 1091 1092 1092 1093 /** 1094 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay} 1095 */ 1096 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 1097 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten) 1098 { 1099 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 1100 AssertPtrReturn(pInterface, VERR_INVALID_POINTER); 1101 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 1102 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER); 1103 Log4Func(("@%#RX64: pvBuf=%p cbBuf=%#x (%u) state=%s - %s\n", pStreamALSA->offInternal, pvBuf, cbBuf, cbBuf, 1104 snd_pcm_state_name(snd_pcm_state(pStreamALSA->hPCM)), pStreamALSA->Cfg.szName)); 1105 if (cbBuf) 1106 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 1107 else 1108 { 1109 /* Fend off draining calls. */ 1110 *pcbWritten = 0; 1111 return VINF_SUCCESS; 1112 } 1113 1114 /* 1115 * Determine how much we can write (caller actually did this 1116 * already, but we repeat it just to be sure or something). 1117 */ 1118 snd_pcm_sframes_t cFramesAvail; 1119 int rc = alsaStreamGetAvail(pStreamALSA->hPCM, &cFramesAvail); 1120 if (RT_SUCCESS(rc)) 1121 { 1122 Assert(cFramesAvail); 1123 if (cFramesAvail) 1124 { 1125 PCPDMAUDIOPCMPROPS pProps = &pStreamALSA->Cfg.Props; 1126 uint32_t cbToWrite = PDMAudioPropsFramesToBytes(pProps, (uint32_t)cFramesAvail); 1127 if (cbToWrite) 1128 { 1129 if (cbToWrite > cbBuf) 1130 cbToWrite = cbBuf; 1131 1132 /* 1133 * Try write the data. 1134 */ 1135 uint32_t cFramesToWrite = PDMAudioPropsBytesToFrames(pProps, cbToWrite); 1136 snd_pcm_sframes_t cFramesWritten = snd_pcm_writei(pStreamALSA->hPCM, pvBuf, cFramesToWrite); 1137 if (cFramesWritten > 0) 1138 { 1139 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n", 1140 cbToWrite, cFramesWritten, cFramesAvail)); 1141 *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten); 1142 pStreamALSA->offInternal += *pcbWritten; 1143 return VINF_SUCCESS; 1144 } 1145 LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld]\n", cbToWrite, cFramesWritten, cFramesAvail)); 1146 1147 1148 /* 1149 * There are a couple of error we can recover from, try to do so. 1150 * Only don't try too many times. 1151 */ 1152 for (unsigned iTry = 0; 1153 (cFramesWritten == -EPIPE || cFramesWritten == -ESTRPIPE) && iTry < ALSA_RECOVERY_TRIES_MAX; 1154 iTry++) 1155 { 1156 if (cFramesWritten == -EPIPE) 1157 { 1158 /* Underrun occurred. */ 1159 rc = drvHstAudAlsaStreamRecover(pStreamALSA->hPCM); 1160 if (RT_FAILURE(rc)) 1161 break; 1162 LogFlowFunc(("Recovered from playback (iTry=%u)\n", iTry)); 1163 } 1164 else 1165 { 1166 /* An suspended event occurred, needs resuming. */ 1167 rc = drvHstAudAlsaStreamResume(pStreamALSA->hPCM); 1168 if (RT_FAILURE(rc)) 1169 { 1170 LogRel(("ALSA: Failed to resume output stream (iTry=%u, rc=%Rrc)\n", iTry, rc)); 1171 break; 1172 } 1173 LogFlowFunc(("Resumed suspended output stream (iTry=%u)\n", iTry)); 1174 } 1175 1176 cFramesWritten = snd_pcm_writei(pStreamALSA->hPCM, pvBuf, cFramesToWrite); 1177 if (cFramesWritten > 0) 1178 { 1179 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n", 1180 cbToWrite, cFramesWritten, cFramesAvail)); 1181 *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten); 1182 pStreamALSA->offInternal += *pcbWritten; 1183 return VINF_SUCCESS; 1184 } 1185 LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld, iTry=%d]\n", cbToWrite, cFramesWritten, cFramesAvail, iTry)); 1186 } 1187 1188 /* Make sure we return with an error status. */ 1189 if (RT_SUCCESS_NP(rc)) 1190 { 1191 if (cFramesWritten == 0) 1192 rc = VERR_ACCESS_DENIED; 1193 else 1194 { 1195 rc = RTErrConvertFromErrno(-(int)cFramesWritten); 1196 LogFunc(("Failed to write %RU32 bytes: %ld (%Rrc)\n", cbToWrite, cFramesWritten, rc)); 1197 } 1198 } 1199 } 1200 } 1201 } 1202 else 1203 LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc)); 1204 *pcbWritten = 0; 1205 return rc; 1206 } 1207 1208 1209 /** 1093 1210 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamCapture} 1094 1211 */ 1095 static DECLCALLBACK(int) drvH ostAlsaAudioHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,1096 1212 static DECLCALLBACK(int) drvHstAudAlsaHA_StreamCapture(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream, 1213 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) 1097 1214 { 1098 1215 RT_NOREF_PV(pInterface); 1099 P ALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;1216 PDRVHSTAUDALSASTREAM pStreamALSA = (PDRVHSTAUDALSASTREAM)pStream; 1100 1217 AssertPtrReturn(pStreamALSA, VERR_INVALID_POINTER); 1101 1218 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); … … 1124 1241 1125 1242 case SND_PCM_STATE_SUSPENDED: 1126 rc = alsaStreamResume(pStreamALSA->hPCM);1243 rc = drvHstAudAlsaStreamResume(pStreamALSA->hPCM); 1127 1244 if (RT_SUCCESS(rc)) 1128 1245 { … … 1190 1307 if (cFramesRead == -EPIPE) 1191 1308 { 1192 rc = alsaStreamRecover(pStreamALSA->hPCM);1309 rc = drvHstAudAlsaStreamRecover(pStreamALSA->hPCM); 1193 1310 if (RT_SUCCESS(rc)) 1194 1311 { … … 1224 1341 } 1225 1342 1226 /**1227 * @interface_method_impl{PDMIHOSTAUDIO,pfnStreamPlay}1228 */1229 static DECLCALLBACK(int) drvHostAlsaAudioHA_StreamPlay(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream,1230 const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten)1231 {1232 PALSAAUDIOSTREAM pStreamALSA = (PALSAAUDIOSTREAM)pStream;1233 AssertPtrReturn(pInterface, VERR_INVALID_POINTER);1234 AssertPtrReturn(pStream, VERR_INVALID_POINTER);1235 AssertPtrReturn(pcbWritten, VERR_INVALID_POINTER);1236 Log4Func(("@%#RX64: pvBuf=%p cbBuf=%#x (%u) state=%s - %s\n", pStreamALSA->offInternal, pvBuf, cbBuf, cbBuf,1237 snd_pcm_state_name(snd_pcm_state(pStreamALSA->hPCM)), pStreamALSA->Cfg.szName));1238 if (cbBuf)1239 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);1240 else1241 {1242 /* Fend off draining calls. */1243 *pcbWritten = 0;1244 return VINF_SUCCESS;1245 }1246 1247 /*1248 * Determine how much we can write (caller actually did this1249 * already, but we repeat it just to be sure or something).1250 */1251 snd_pcm_sframes_t cFramesAvail;1252 int rc = alsaStreamGetAvail(pStreamALSA->hPCM, &cFramesAvail);1253 if (RT_SUCCESS(rc))1254 {1255 Assert(cFramesAvail);1256 if (cFramesAvail)1257 {1258 PCPDMAUDIOPCMPROPS pProps = &pStreamALSA->Cfg.Props;1259 uint32_t cbToWrite = PDMAudioPropsFramesToBytes(pProps, (uint32_t)cFramesAvail);1260 if (cbToWrite)1261 {1262 if (cbToWrite > cbBuf)1263 cbToWrite = cbBuf;1264 1265 /*1266 * Try write the data.1267 */1268 uint32_t cFramesToWrite = PDMAudioPropsBytesToFrames(pProps, cbToWrite);1269 snd_pcm_sframes_t cFramesWritten = snd_pcm_writei(pStreamALSA->hPCM, pvBuf, cFramesToWrite);1270 if (cFramesWritten > 0)1271 {1272 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n",1273 cbToWrite, cFramesWritten, cFramesAvail));1274 *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten);1275 pStreamALSA->offInternal += *pcbWritten;1276 return VINF_SUCCESS;1277 }1278 LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld]\n", cbToWrite, cFramesWritten, cFramesAvail));1279 1280 1281 /*1282 * There are a couple of error we can recover from, try to do so.1283 * Only don't try too many times.1284 */1285 for (unsigned iTry = 0;1286 (cFramesWritten == -EPIPE || cFramesWritten == -ESTRPIPE) && iTry < ALSA_RECOVERY_TRIES_MAX;1287 iTry++)1288 {1289 if (cFramesWritten == -EPIPE)1290 {1291 /* Underrun occurred. */1292 rc = alsaStreamRecover(pStreamALSA->hPCM);1293 if (RT_FAILURE(rc))1294 break;1295 LogFlowFunc(("Recovered from playback (iTry=%u)\n", iTry));1296 }1297 else1298 {1299 /* An suspended event occurred, needs resuming. */1300 rc = alsaStreamResume(pStreamALSA->hPCM);1301 if (RT_FAILURE(rc))1302 {1303 LogRel(("ALSA: Failed to resume output stream (iTry=%u, rc=%Rrc)\n", iTry, rc));1304 break;1305 }1306 LogFlowFunc(("Resumed suspended output stream (iTry=%u)\n", iTry));1307 }1308 1309 cFramesWritten = snd_pcm_writei(pStreamALSA->hPCM, pvBuf, cFramesToWrite);1310 if (cFramesWritten > 0)1311 {1312 Log4Func(("snd_pcm_writei w/ cbToWrite=%u -> %ld (frames) [cFramesAvail=%ld]\n",1313 cbToWrite, cFramesWritten, cFramesAvail));1314 *pcbWritten = PDMAudioPropsFramesToBytes(pProps, cFramesWritten);1315 pStreamALSA->offInternal += *pcbWritten;1316 return VINF_SUCCESS;1317 }1318 LogFunc(("snd_pcm_writei w/ cbToWrite=%u -> %ld [cFramesAvail=%ld, iTry=%d]\n", cbToWrite, cFramesWritten, cFramesAvail, iTry));1319 }1320 1321 /* Make sure we return with an error status. */1322 if (RT_SUCCESS_NP(rc))1323 {1324 if (cFramesWritten == 0)1325 rc = VERR_ACCESS_DENIED;1326 else1327 {1328 rc = RTErrConvertFromErrno(-(int)cFramesWritten);1329 LogFunc(("Failed to write %RU32 bytes: %ld (%Rrc)\n", cbToWrite, cFramesWritten, rc));1330 }1331 }1332 }1333 }1334 }1335 else1336 LogFunc(("Error getting number of playback frames, rc=%Rrc\n", rc));1337 *pcbWritten = 0;1338 return rc;1339 }1340 1341 1343 1342 1344 /** 1343 1345 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1344 1346 */ 1345 static DECLCALLBACK(void *) drvH ostAlsaAudioQueryInterface(PPDMIBASE pInterface, const char *pszIID)1346 { 1347 PPDMDRVINS 1348 PDRVH OSTALSAAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);1347 static DECLCALLBACK(void *) drvHstAudAlsaQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1348 { 1349 PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); 1350 PDRVHSTAUDALSA pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDALSA); 1349 1351 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase); 1350 1352 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHOSTAUDIO, &pThis->IHostAudio); … … 1359 1361 * @copydoc FNPDMDRVCONSTRUCT 1360 1362 */ 1361 static DECLCALLBACK(int) drvH ostAlsaAudioConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)1363 static DECLCALLBACK(int) drvHstAudAlsaConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) 1362 1364 { 1363 1365 RT_NOREF(fFlags); 1364 1366 PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); 1365 PDRVH OSTALSAAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTALSAAUDIO);1367 PDRVHSTAUDALSA pThis = PDMINS_2_DATA(pDrvIns, PDRVHSTAUDALSA); 1366 1368 LogRel(("Audio: Initializing ALSA driver\n")); 1367 1369 … … 1371 1373 pThis->pDrvIns = pDrvIns; 1372 1374 /* IBase */ 1373 pDrvIns->IBase.pfnQueryInterface = drvH ostAlsaAudioQueryInterface;1375 pDrvIns->IBase.pfnQueryInterface = drvHstAudAlsaQueryInterface; 1374 1376 /* IHostAudio */ 1375 pThis->IHostAudio.pfnGetConfig = drvH ostAlsaAudioHA_GetConfig;1376 pThis->IHostAudio.pfnGetDevices = drvH ostAlsaAudioHA_GetDevices;1377 pThis->IHostAudio.pfnGetConfig = drvHstAudAlsaHA_GetConfig; 1378 pThis->IHostAudio.pfnGetDevices = drvHstAudAlsaHA_GetDevices; 1377 1379 pThis->IHostAudio.pfnSetDevice = NULL; 1378 pThis->IHostAudio.pfnGetStatus = drvH ostAlsaAudioHA_GetStatus;1380 pThis->IHostAudio.pfnGetStatus = drvHstAudAlsaHA_GetStatus; 1379 1381 pThis->IHostAudio.pfnDoOnWorkerThread = NULL; 1380 1382 pThis->IHostAudio.pfnStreamConfigHint = NULL; 1381 pThis->IHostAudio.pfnStreamCreate = drvH ostAlsaAudioHA_StreamCreate;1383 pThis->IHostAudio.pfnStreamCreate = drvHstAudAlsaHA_StreamCreate; 1382 1384 pThis->IHostAudio.pfnStreamInitAsync = NULL; 1383 pThis->IHostAudio.pfnStreamDestroy = drvH ostAlsaAudioHA_StreamDestroy;1385 pThis->IHostAudio.pfnStreamDestroy = drvHstAudAlsaHA_StreamDestroy; 1384 1386 pThis->IHostAudio.pfnStreamNotifyDeviceChanged = NULL; 1385 pThis->IHostAudio.pfnStreamControl = drvH ostAlsaAudioHA_StreamControl;1386 pThis->IHostAudio.pfnStreamGetReadable = drvH ostAlsaAudioHA_StreamGetReadable;1387 pThis->IHostAudio.pfnStreamGetWritable = drvH ostAlsaAudioHA_StreamGetWritable;1388 pThis->IHostAudio.pfnStreamGetPending = drvH ostAlsaAudioHA_StreamGetPending;1389 pThis->IHostAudio.pfnStreamGetState = drvH ostAlsaAudioHA_StreamGetState;1390 pThis->IHostAudio.pfnStreamPlay = drvH ostAlsaAudioHA_StreamPlay;1391 pThis->IHostAudio.pfnStreamCapture = drvH ostAlsaAudioHA_StreamCapture;1387 pThis->IHostAudio.pfnStreamControl = drvHstAudAlsaHA_StreamControl; 1388 pThis->IHostAudio.pfnStreamGetReadable = drvHstAudAlsaHA_StreamGetReadable; 1389 pThis->IHostAudio.pfnStreamGetWritable = drvHstAudAlsaHA_StreamGetWritable; 1390 pThis->IHostAudio.pfnStreamGetPending = drvHstAudAlsaHA_StreamGetPending; 1391 pThis->IHostAudio.pfnStreamGetState = drvHstAudAlsaHA_StreamGetState; 1392 pThis->IHostAudio.pfnStreamPlay = drvHstAudAlsaHA_StreamPlay; 1393 pThis->IHostAudio.pfnStreamCapture = drvHstAudAlsaHA_StreamCapture; 1392 1394 1393 1395 /* … … 1411 1413 } 1412 1414 #ifdef DEBUG 1413 snd_lib_error_set_handler( alsaDbgErrorHandler);1415 snd_lib_error_set_handler(drvHstAudAlsaDbgErrorHandler); 1414 1416 #endif 1415 1417 return VINF_SUCCESS; … … 1439 1441 ~0U, 1440 1442 /* cbInstance */ 1441 sizeof(DRVH OSTALSAAUDIO),1443 sizeof(DRVHSTAUDALSA), 1442 1444 /* pfnConstruct */ 1443 drvH ostAlsaAudioConstruct,1445 drvHstAudAlsaConstruct, 1444 1446 /* pfnDestruct */ 1445 1447 NULL,
Note:
See TracChangeset
for help on using the changeset viewer.