Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenstream.c
Go to the documentation of this file.
00001 /* -*- tab-width: 8; c-basic-offset: 4 -*- */ 00002 00003 /* 00004 * MSACM32 library 00005 * 00006 * Copyright 1998 Patrik Stridvall 00007 * 1999 Eric Pouech 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 /* TODO 00025 * + asynchronous conversion is not implemented 00026 * + callback/notification 00027 * * acmStreamMessage 00028 * + properly close ACM streams 00029 */ 00030 00031 #include <stdarg.h> 00032 #include <string.h> 00033 #include "windef.h" 00034 #include "winbase.h" 00035 #include "winerror.h" 00036 #include "wine/debug.h" 00037 #include "mmsystem.h" 00038 #define NOBITMAP 00039 #include "mmreg.h" 00040 #include "msacm.h" 00041 #include "msacmdrv.h" 00042 #include "wineacm.h" 00043 00044 WINE_DEFAULT_DEBUG_CHANNEL(msacm); 00045 00046 static PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has) 00047 { 00048 TRACE("(%p)\n", has); 00049 00050 return (PWINE_ACMSTREAM)has; 00051 } 00052 00053 /*********************************************************************** 00054 * acmStreamClose (MSACM32.@) 00055 */ 00056 MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose) 00057 { 00058 PWINE_ACMSTREAM was; 00059 MMRESULT ret; 00060 00061 TRACE("(%p, %d)\n", has, fdwClose); 00062 00063 if ((was = ACM_GetStream(has)) == NULL) { 00064 WARN("invalid handle\n"); 00065 return MMSYSERR_INVALHANDLE; 00066 } 00067 ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_CLOSE, (LPARAM)&was->drvInst, 0); 00068 if (ret == MMSYSERR_NOERROR) { 00069 if (was->hAcmDriver) 00070 acmDriverClose(was->hAcmDriver, 0L); 00071 HeapFree(MSACM_hHeap, 0, was); 00072 } 00073 TRACE("=> (%d)\n", ret); 00074 return ret; 00075 } 00076 00077 /*********************************************************************** 00078 * acmStreamConvert (MSACM32.@) 00079 */ 00080 MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash, 00081 DWORD fdwConvert) 00082 { 00083 PWINE_ACMSTREAM was; 00084 MMRESULT ret = MMSYSERR_NOERROR; 00085 PACMDRVSTREAMHEADER padsh; 00086 00087 TRACE("(%p, %p, %d)\n", has, pash, fdwConvert); 00088 00089 if ((was = ACM_GetStream(has)) == NULL) { 00090 WARN("invalid handle\n"); 00091 return MMSYSERR_INVALHANDLE; 00092 } 00093 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER)) { 00094 WARN("invalid parameter\n"); 00095 return MMSYSERR_INVALPARAM; 00096 } 00097 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)) { 00098 WARN("unprepared header\n"); 00099 return ACMERR_UNPREPARED; 00100 } 00101 00102 pash->cbSrcLengthUsed = 0; 00103 pash->cbDstLengthUsed = 0; 00104 00105 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same 00106 * size. some fields are private to msacm internals, and are exposed 00107 * in ACMSTREAMHEADER in the dwReservedDriver array 00108 */ 00109 padsh = (PACMDRVSTREAMHEADER)pash; 00110 00111 /* check that pointers have not been modified */ 00112 if (padsh->pbPreparedSrc != padsh->pbSrc || 00113 padsh->cbPreparedSrcLength < padsh->cbSrcLength || 00114 padsh->pbPreparedDst != padsh->pbDst || 00115 padsh->cbPreparedDstLength < padsh->cbDstLength) { 00116 WARN("invalid parameter\n"); 00117 return MMSYSERR_INVALPARAM; 00118 } 00119 00120 padsh->fdwConvert = fdwConvert; 00121 00122 ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_CONVERT, (LPARAM)&was->drvInst, (LPARAM)padsh); 00123 if (ret == MMSYSERR_NOERROR) { 00124 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE; 00125 } 00126 TRACE("=> (%d)\n", ret); 00127 return ret; 00128 } 00129 00130 /*********************************************************************** 00131 * acmStreamMessage (MSACM32.@) 00132 */ 00133 MMRESULT WINAPI acmStreamMessage(HACMSTREAM has, UINT uMsg, LPARAM lParam1, 00134 LPARAM lParam2) 00135 { 00136 FIXME("(%p, %u, %ld, %ld): stub\n", has, uMsg, lParam1, lParam2); 00137 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 00138 return MMSYSERR_ERROR; 00139 } 00140 00141 /*********************************************************************** 00142 * acmStreamOpen (MSACM32.@) 00143 */ 00144 MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, 00145 PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst, 00146 PWAVEFILTER pwfltr, DWORD_PTR dwCallback, 00147 DWORD_PTR dwInstance, DWORD fdwOpen) 00148 { 00149 PWINE_ACMSTREAM was; 00150 PWINE_ACMDRIVER wad; 00151 MMRESULT ret; 00152 int wfxSrcSize; 00153 int wfxDstSize; 00154 WAVEFORMATEX wfxSrc, wfxDst; 00155 00156 TRACE("(%p, %p, %p, %p, %p, %ld, %ld, %d)\n", 00157 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen); 00158 00159 /* NOTE: pwfxSrc and/or pwfxDst can point to a structure smaller than 00160 * WAVEFORMATEX so don't use them directly when not sure */ 00161 if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) { 00162 memcpy(&wfxSrc, pwfxSrc, sizeof(PCMWAVEFORMAT)); 00163 wfxSrc.wBitsPerSample = pwfxSrc->wBitsPerSample; 00164 wfxSrc.cbSize = 0; 00165 pwfxSrc = &wfxSrc; 00166 } 00167 00168 if (pwfxDst->wFormatTag == WAVE_FORMAT_PCM) { 00169 memcpy(&wfxDst, pwfxDst, sizeof(PCMWAVEFORMAT)); 00170 wfxDst.wBitsPerSample = pwfxDst->wBitsPerSample; 00171 wfxDst.cbSize = 0; 00172 pwfxDst = &wfxDst; 00173 } 00174 00175 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", 00176 pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec, 00177 pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize); 00178 00179 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", 00180 pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec, 00181 pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize); 00182 00183 /* (WS) In query mode, phas should be NULL. If it is not, then instead 00184 * of returning an error we are making sure it is NULL, preventing some 00185 * applications that pass garbage for phas from crashing. 00186 */ 00187 if (fdwOpen & ACM_STREAMOPENF_QUERY) phas = NULL; 00188 00189 if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) { 00190 WARN("invalid parameter\n"); 00191 return MMSYSERR_INVALPARAM; 00192 } 00193 00194 wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX); 00195 if (pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) wfxSrcSize += pwfxSrc->cbSize; 00196 if (pwfxDst->wFormatTag != WAVE_FORMAT_PCM) wfxDstSize += pwfxDst->cbSize; 00197 00198 was = HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + 00199 ((pwfltr) ? sizeof(WAVEFILTER) : 0)); 00200 if (was == NULL) { 00201 WARN("no memory\n"); 00202 return MMSYSERR_NOMEM; 00203 } 00204 00205 was->drvInst.cbStruct = sizeof(was->drvInst); 00206 was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was)); 00207 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize); 00208 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize); 00209 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize); 00210 if (pwfltr) { 00211 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize); 00212 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER)); 00213 } else { 00214 was->drvInst.pwfltr = NULL; 00215 } 00216 was->drvInst.dwCallback = dwCallback; 00217 was->drvInst.dwInstance = dwInstance; 00218 was->drvInst.fdwOpen = fdwOpen; 00219 was->drvInst.fdwDriver = 0L; 00220 was->drvInst.dwDriver = 0L; 00221 /* real value will be stored once ACMDM_STREAM_OPEN succeeds */ 00222 was->drvInst.has = 0L; 00223 00224 if (had) { 00225 if (!(wad = MSACM_GetDriver(had))) { 00226 ret = MMSYSERR_INVALPARAM; 00227 goto errCleanUp; 00228 } 00229 00230 was->obj.dwType = WINE_ACMOBJ_STREAM; 00231 was->obj.pACMDriverID = wad->obj.pACMDriverID; 00232 was->pDrv = wad; 00233 was->hAcmDriver = 0; /* not to close it in acmStreamClose */ 00234 00235 ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L); 00236 if (ret != MMSYSERR_NOERROR) 00237 goto errCleanUp; 00238 } else { 00239 PWINE_ACMDRIVERID wadi; 00240 00241 ret = ACMERR_NOTPOSSIBLE; 00242 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) { 00243 if ((wadi->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) || 00244 !MSACM_FindFormatTagInCache(wadi, pwfxSrc->wFormatTag, NULL) || 00245 !MSACM_FindFormatTagInCache(wadi, pwfxDst->wFormatTag, NULL)) 00246 continue; 00247 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L); 00248 if (ret != MMSYSERR_NOERROR) 00249 continue; 00250 if ((wad = MSACM_GetDriver(had)) != 0) { 00251 was->obj.dwType = WINE_ACMOBJ_STREAM; 00252 was->obj.pACMDriverID = wad->obj.pACMDriverID; 00253 was->pDrv = wad; 00254 was->hAcmDriver = had; 00255 00256 ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L); 00257 TRACE("%s => %08x\n", debugstr_w(wadi->pszDriverAlias), ret); 00258 if (ret == MMSYSERR_NOERROR) { 00259 if (fdwOpen & ACM_STREAMOPENF_QUERY) { 00260 acmDriverClose(had, 0L); 00261 } 00262 break; 00263 } 00264 } 00265 /* no match, close this acm driver and try next one */ 00266 acmDriverClose(had, 0L); 00267 } 00268 if (ret != MMSYSERR_NOERROR) { 00269 ret = ACMERR_NOTPOSSIBLE; 00270 goto errCleanUp; 00271 } 00272 } 00273 ret = MMSYSERR_NOERROR; 00274 was->drvInst.has = (HACMSTREAM)was; 00275 if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) { 00276 if (phas) 00277 *phas = (HACMSTREAM)was; 00278 TRACE("=> (%d)\n", ret); 00279 return ret; 00280 } 00281 errCleanUp: 00282 if (phas) 00283 *phas = NULL; 00284 HeapFree(MSACM_hHeap, 0, was); 00285 TRACE("=> (%d)\n", ret); 00286 return ret; 00287 } 00288 00289 00290 /*********************************************************************** 00291 * acmStreamPrepareHeader (MSACM32.@) 00292 */ 00293 MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash, 00294 DWORD fdwPrepare) 00295 { 00296 PWINE_ACMSTREAM was; 00297 MMRESULT ret = MMSYSERR_NOERROR; 00298 PACMDRVSTREAMHEADER padsh; 00299 00300 TRACE("(%p, %p, %d)\n", has, pash, fdwPrepare); 00301 00302 if ((was = ACM_GetStream(has)) == NULL) { 00303 WARN("invalid handle\n"); 00304 return MMSYSERR_INVALHANDLE; 00305 } 00306 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER)) { 00307 WARN("invalid parameter\n"); 00308 return MMSYSERR_INVALPARAM; 00309 } 00310 if (fdwPrepare) 00311 ret = MMSYSERR_INVALFLAG; 00312 00313 if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE) 00314 return MMSYSERR_NOERROR; 00315 00316 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same 00317 * size. some fields are private to msacm internals, and are exposed 00318 * in ACMSTREAMHEADER in the dwReservedDriver array 00319 */ 00320 padsh = (PACMDRVSTREAMHEADER)pash; 00321 00322 padsh->fdwConvert = fdwPrepare; 00323 padsh->padshNext = NULL; 00324 padsh->fdwDriver = padsh->dwDriver = 0L; 00325 00326 padsh->fdwPrepared = 0; 00327 padsh->dwPrepared = 0; 00328 padsh->pbPreparedSrc = 0; 00329 padsh->cbPreparedSrcLength = 0; 00330 padsh->pbPreparedDst = 0; 00331 padsh->cbPreparedDstLength = 0; 00332 00333 ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_PREPARE, (LPARAM)&was->drvInst, (LPARAM)padsh); 00334 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) { 00335 ret = MMSYSERR_NOERROR; 00336 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE); 00337 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED; 00338 padsh->fdwPrepared = padsh->fdwStatus; 00339 padsh->dwPrepared = 0; 00340 padsh->pbPreparedSrc = padsh->pbSrc; 00341 padsh->cbPreparedSrcLength = padsh->cbSrcLength; 00342 padsh->pbPreparedDst = padsh->pbDst; 00343 padsh->cbPreparedDstLength = padsh->cbDstLength; 00344 } else { 00345 padsh->fdwPrepared = 0; 00346 padsh->dwPrepared = 0; 00347 padsh->pbPreparedSrc = 0; 00348 padsh->cbPreparedSrcLength = 0; 00349 padsh->pbPreparedDst = 0; 00350 padsh->cbPreparedDstLength = 0; 00351 } 00352 TRACE("=> (%d)\n", ret); 00353 return ret; 00354 } 00355 00356 /*********************************************************************** 00357 * acmStreamReset (MSACM32.@) 00358 */ 00359 MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset) 00360 { 00361 PWINE_ACMSTREAM was; 00362 MMRESULT ret = MMSYSERR_NOERROR; 00363 00364 TRACE("(%p, %d)\n", has, fdwReset); 00365 00366 if (fdwReset) { 00367 WARN("invalid flag\n"); 00368 ret = MMSYSERR_INVALFLAG; 00369 } else if ((was = ACM_GetStream(has)) == NULL) { 00370 WARN("invalid handle\n"); 00371 return MMSYSERR_INVALHANDLE; 00372 } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) { 00373 ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_RESET, (LPARAM)&was->drvInst, 0); 00374 } 00375 TRACE("=> (%d)\n", ret); 00376 return ret; 00377 } 00378 00379 /*********************************************************************** 00380 * acmStreamSize (MSACM32.@) 00381 */ 00382 MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput, 00383 LPDWORD pdwOutputBytes, DWORD fdwSize) 00384 { 00385 PWINE_ACMSTREAM was; 00386 ACMDRVSTREAMSIZE adss; 00387 MMRESULT ret; 00388 00389 TRACE("(%p, %d, %p, %d)\n", has, cbInput, pdwOutputBytes, fdwSize); 00390 00391 if ((was = ACM_GetStream(has)) == NULL) { 00392 WARN("invalid handle\n"); 00393 return MMSYSERR_INVALHANDLE; 00394 } 00395 if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) { 00396 WARN("invalid flag\n"); 00397 return MMSYSERR_INVALFLAG; 00398 } 00399 00400 *pdwOutputBytes = 0L; 00401 00402 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) { 00403 case ACM_STREAMSIZEF_DESTINATION: 00404 adss.cbDstLength = cbInput; 00405 adss.cbSrcLength = 0; 00406 break; 00407 case ACM_STREAMSIZEF_SOURCE: 00408 adss.cbSrcLength = cbInput; 00409 adss.cbDstLength = 0; 00410 break; 00411 default: 00412 WARN("invalid flag\n"); 00413 return MMSYSERR_INVALFLAG; 00414 } 00415 00416 adss.cbStruct = sizeof(adss); 00417 adss.fdwSize = fdwSize; 00418 ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_SIZE, 00419 (LPARAM)&was->drvInst, (LPARAM)&adss); 00420 if (ret == MMSYSERR_NOERROR) { 00421 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) { 00422 case ACM_STREAMSIZEF_DESTINATION: 00423 *pdwOutputBytes = adss.cbSrcLength; 00424 break; 00425 case ACM_STREAMSIZEF_SOURCE: 00426 *pdwOutputBytes = adss.cbDstLength; 00427 break; 00428 } 00429 } 00430 TRACE("=> (%d) [%u]\n", ret, *pdwOutputBytes); 00431 return ret; 00432 } 00433 00434 /*********************************************************************** 00435 * acmStreamUnprepareHeader (MSACM32.@) 00436 */ 00437 MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash, 00438 DWORD fdwUnprepare) 00439 { 00440 PWINE_ACMSTREAM was; 00441 MMRESULT ret = MMSYSERR_NOERROR; 00442 PACMDRVSTREAMHEADER padsh; 00443 00444 TRACE("(%p, %p, %d)\n", has, pash, fdwUnprepare); 00445 00446 if ((was = ACM_GetStream(has)) == NULL) { 00447 WARN("invalid handle\n"); 00448 return MMSYSERR_INVALHANDLE; 00449 } 00450 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER)) { 00451 WARN("invalid parameter\n"); 00452 return MMSYSERR_INVALPARAM; 00453 } 00454 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)) { 00455 WARN("unprepared header\n"); 00456 return ACMERR_UNPREPARED; 00457 } 00458 00459 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same 00460 * size. some fields are private to msacm internals, and are exposed 00461 * in ACMSTREAMHEADER in the dwReservedDriver array 00462 */ 00463 padsh = (PACMDRVSTREAMHEADER)pash; 00464 00465 /* check that pointers have not been modified */ 00466 if (padsh->pbPreparedSrc != padsh->pbSrc || 00467 padsh->cbPreparedSrcLength < padsh->cbSrcLength || 00468 padsh->pbPreparedDst != padsh->pbDst || 00469 padsh->cbPreparedDstLength < padsh->cbDstLength) { 00470 WARN("invalid parameter\n"); 00471 return MMSYSERR_INVALPARAM; 00472 } 00473 00474 padsh->fdwConvert = fdwUnprepare; 00475 00476 ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_UNPREPARE, (LPARAM)&was->drvInst, (LPARAM)padsh); 00477 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) { 00478 ret = MMSYSERR_NOERROR; 00479 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED); 00480 } 00481 TRACE("=> (%d)\n", ret); 00482 return ret; 00483 } Generated on Fri May 25 2012 04:21:59 for ReactOS by
1.7.6.1
|