4 * Copyright (C) 1998 Patrick Stridvall
5 * Copyright (C) 1999 Eric Pouech
7 * Originally distributed under LPGL 2.1 (or later) by the Wine project.
9 * Modified for use with MPlayer, detailed CVS changelog at
10 * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
12 * File now distributed as part of VLC media player with no modifications.
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
29 /**************************************************************************
32 This file will contain an interface to ACM drivers.
33 Its content will be based mainly on wine/dlls/msacm32
34 actually, for audio decompression only the following functions
37 acmStreamOpen ( takes formats of src and dest, returns stream handle )
38 acmStreamPrepareHeader ( takes stream handler and info on data )
39 acmStreamConvert ( the same as PrepareHeader )
40 acmStreamUnprepareHeader
45 In future I'll also add functions for format enumeration,
48 Modified for use with MPlayer, detailed CVS changelog at
49 http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
51 ***************************************************************************/
54 #include "wine/winbase.h"
55 #include "wine/windef.h"
56 #include "wine/winuser.h"
58 #include "wine/winestring.h"
59 #include "wine/driver.h"
60 #include "wine/winerror.h"
61 #include "wine/msacm.h"
62 #include "wine/msacmdrv.h"
73 #define OpenDriverA DrvOpen
74 #define CloseDriver DrvClose
76 static inline PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
78 return (PWINE_ACMSTREAM)has;
81 /***********************************************************************
82 * acmDriverAddA (MSACM32.2)
84 MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
85 LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
88 return MMSYSERR_INVALPARAM;
90 /* Check if any unknown flags */
92 ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
93 ACM_DRIVERADDF_GLOBAL))
94 return MMSYSERR_INVALFLAG;
96 /* Check if any incompatible flags */
97 if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
98 (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
99 return MMSYSERR_INVALFLAG;
101 /* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
102 * LoadDriver on it, to be sure we can call SendDriverMessage on the
105 *phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, 0, hinstModule);
107 /* FIXME: lParam, dwPriority and fdwAdd ignored */
109 return MMSYSERR_NOERROR;
112 /***********************************************************************
113 * acmDriverClose (MSACM32.4)
115 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
121 return MMSYSERR_INVALFLAG;
123 p = MSACM_GetDriver(had);
125 return MMSYSERR_INVALHANDLE;
127 for (tp = &(p->obj.pACMDriverID->pACMDriverList); *tp; *tp = (*tp)->pNextACMDriver) {
129 *tp = (*tp)->pNextACMDriver;
134 if (p->hDrvr && !p->obj.pACMDriverID->pACMDriverList)
135 CloseDriver(p->hDrvr);
137 HeapFree(MSACM_hHeap, 0, p);
139 return MMSYSERR_NOERROR;
142 /***********************************************************************
143 * acmDriverEnum (MSACM32.7)
145 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
151 return MMSYSERR_INVALPARAM;
154 if (fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED)) {
155 return MMSYSERR_INVALFLAG;
158 for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
159 fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
161 if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
162 fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
166 (*fnCallback)((HACMDRIVERID) p, dwInstance, fdwSupport);
169 return MMSYSERR_NOERROR;
172 /***********************************************************************
173 * acmDriverID (MSACM32.8)
175 MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
179 pao = MSACM_GetObj(hao);
181 return MMSYSERR_INVALHANDLE;
184 return MMSYSERR_INVALPARAM;
187 return MMSYSERR_INVALFLAG;
189 *phadid = (HACMDRIVERID) pao->pACMDriverID;
191 return MMSYSERR_NOERROR;
194 /***********************************************************************
195 * acmDriverMessage (MSACM32.9)
199 LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
201 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
203 return MMSYSERR_INVALPARAM;
205 /* FIXME: Check if uMsg legal */
207 if (!SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2))
208 return MMSYSERR_NOTSUPPORTED;
210 return MMSYSERR_NOERROR;
214 /***********************************************************************
215 * acmDriverOpen (MSACM32.10)
217 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
219 PWINE_ACMDRIVERID padid;
225 TRACE("(%p, %x, %08lu)\n", phad, hadid, fdwOpen);
228 return MMSYSERR_INVALPARAM;
230 padid = MSACM_GetDriverID(hadid);
232 return MMSYSERR_INVALHANDLE;
235 return MMSYSERR_INVALFLAG;
237 pad = (PWINE_ACMDRIVER) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
239 return MMSYSERR_NOMEM;
241 pad->obj.pACMDriverID = padid;
242 icopen.fccType = mmioFOURCC('a', 'u', 'd', 'c');
243 icopen.fccHandler = (long)padid->pszFileName;
244 icopen.dwSize = sizeof(ICOPEN);
247 icopen.pV1Reserved = padid->pszFileName;
248 if (!padid->hInstModule)
249 pad->hDrvr = OpenDriverA((long)&icopen);
251 pad->hDrvr = padid->hInstModule;
254 HeapFree(MSACM_hHeap, 0, pad);
255 return MMSYSERR_ERROR;
258 pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc");
260 /* insert new pad at beg of list */
261 pad->pNextACMDriver = padid->pACMDriverList;
262 padid->pACMDriverList = pad;
264 /* FIXME: Create a WINE_ACMDRIVER32 */
265 *phad = (HACMDRIVER)pad;
267 return MMSYSERR_NOERROR;
270 /***********************************************************************
271 * acmDriverRemove (MSACM32.12)
273 MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
275 PWINE_ACMDRIVERID padid;
277 padid = MSACM_GetDriverID(hadid);
279 return MMSYSERR_INVALHANDLE;
282 return MMSYSERR_INVALFLAG;
284 MSACM_UnregisterDriver(padid);
286 return MMSYSERR_NOERROR;
291 /**********************************************************************/
293 HANDLE MSACM_hHeap = (HANDLE) NULL;
294 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
295 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
297 /***********************************************************************
298 * MSACM_RegisterDriver32()
300 PWINE_ACMDRIVERID MSACM_RegisterDriver(const char* pszFileName,
302 HINSTANCE hinstModule)
304 PWINE_ACMDRIVERID padid;
306 TRACE("('%s', '%x', 0x%08x)\n", pszFileName, wFormatTag, hinstModule);
309 MSACM_hHeap = GetProcessHeap();
311 padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
312 padid->pszFileName = (char*)malloc(strlen(pszFileName)+1);
313 strcpy(padid->pszFileName, pszFileName);
314 // 1~strdup(pszDriverAlias);
315 padid->wFormatTag = wFormatTag;
316 padid->hInstModule = hinstModule;
317 padid->bEnabled = TRUE;
318 padid->pACMDriverList = NULL;
319 padid->pNextACMDriverID = NULL;
320 padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
321 if (MSACM_pLastACMDriverID)
322 MSACM_pLastACMDriverID->pNextACMDriverID = padid;
323 MSACM_pLastACMDriverID = padid;
324 if (!MSACM_pFirstACMDriverID)
325 MSACM_pFirstACMDriverID = padid;
331 /***********************************************************************
332 * MSACM_UnregisterDriver32()
334 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
336 PWINE_ACMDRIVERID pNextACMDriverID;
338 while (p->pACMDriverList)
339 acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
341 free( p->pszFileName );
343 if (p == MSACM_pFirstACMDriverID)
344 MSACM_pFirstACMDriverID = p->pNextACMDriverID;
345 if (p == MSACM_pLastACMDriverID)
346 MSACM_pLastACMDriverID = p->pPrevACMDriverID;
348 if (p->pPrevACMDriverID)
349 p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
350 if (p->pNextACMDriverID)
351 p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
353 pNextACMDriverID = p->pNextACMDriverID;
355 HeapFree(MSACM_hHeap, 0, p);
357 return pNextACMDriverID;
360 /***********************************************************************
361 * MSACM_UnregisterAllDrivers32()
363 * Where should this function be called?
365 void MSACM_UnregisterAllDrivers(void)
369 for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
372 /***********************************************************************
373 * MSACM_GetDriverID32()
375 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
377 return (PWINE_ACMDRIVERID)hDriverID;
380 /***********************************************************************
381 * MSACM_GetDriver32()
383 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
385 return (PWINE_ACMDRIVER)hDriver;
388 /***********************************************************************
391 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj)
393 return (PWINE_ACMOBJ)hObj;
398 /***********************************************************************
399 * acmStreamOpen (MSACM32.40)
401 MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
402 PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
403 DWORD dwInstance, DWORD fdwOpen)
411 TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
412 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
414 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
415 pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
416 pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize);
418 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
419 pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
420 pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
422 #define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize))
423 wfxSrcSize = SIZEOF_WFX(pwfxSrc);
424 wfxDstSize = SIZEOF_WFX(pwfxDst);
427 was = (PWINE_ACMSTREAM) HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0));
429 return MMSYSERR_NOMEM;
430 was->drvInst.cbStruct = sizeof(was->drvInst);
431 was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
432 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
433 // LHACM is checking for 0x1
434 // but if this will not help
435 // was->drvInst.pwfxSrc->wFormatTag = 1;
436 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
437 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
439 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
440 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
442 was->drvInst.pwfltr = NULL;
444 was->drvInst.dwCallback = dwCallback;
445 was->drvInst.dwInstance = dwInstance;
446 was->drvInst.fdwOpen = fdwOpen;
447 was->drvInst.fdwDriver = 0L;
448 was->drvInst.dwDriver = 0L;
449 was->drvInst.has = (HACMSTREAM)was;
452 if (!(wad = MSACM_GetDriver(had))) {
453 ret = MMSYSERR_INVALPARAM;
457 was->obj.pACMDriverID = wad->obj.pACMDriverID;
459 was->hAcmDriver = 0; /* not to close it in acmStreamClose */
461 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
462 if (ret != MMSYSERR_NOERROR)
465 PWINE_ACMDRIVERID wadi;
467 ret = ACMERR_NOTPOSSIBLE;
468 /* if(pwfxSrc->wFormatTag==1)//compression
469 drv_tag=pwfxDst->wFormatTag;
471 if(pwfxDst->wFormatTag==1)//decompression
472 drv_tag=pwfxSrc->wFormatTag;
476 ret=acmDriverOpen2(drv_tag);
477 if (ret == MMSYSERR_NOERROR) {
478 if ((wad = MSACM_GetDriver(had)) != 0) {
479 was->obj.pACMDriverID = wad->obj.pACMDriverID;
481 was->hAcmDriver = had;
483 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
484 if (ret == MMSYSERR_NOERROR) {
485 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
486 acmDriverClose(had, 0L);
491 acmDriverClose(had, 0L);*/
492 //if(MSACM_pFirstACMDriverID==NULL)
493 // MSACM_RegisterAllDrivers();
495 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID)
498 if ((int)wadi->wFormatTag != (int)pwfxSrc->wFormatTag) continue;
500 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
501 if (ret == MMSYSERR_NOERROR) {
502 if ((wad = MSACM_GetDriver(had)) != NULL) {
503 was->obj.pACMDriverID = wad->obj.pACMDriverID;
505 was->hAcmDriver = had;
507 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
508 //lhacm - crash printf("RETOPEN %d\n", ret);
510 if (ret == MMSYSERR_NOERROR) {
511 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
512 acmDriverClose(had, 0L);
517 // no match, close this acm driver and try next one
518 acmDriverClose(had, 0L);
521 if (ret != MMSYSERR_NOERROR) {
522 ret = ACMERR_NOTPOSSIBLE;
526 ret = MMSYSERR_NOERROR;
527 if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
529 *phas = (HACMSTREAM)was;
530 TRACE("=> (%d)\n", ret);
538 *phas = (HACMSTREAM)0;
539 HeapFree(MSACM_hHeap, 0, was);
540 TRACE("=> (%d)\n", ret);
545 MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
550 TRACE("(0x%08x, %ld)\n", has, fdwClose);
552 if ((was = ACM_GetStream(has)) == NULL) {
553 return MMSYSERR_INVALHANDLE;
555 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
556 if (ret == MMSYSERR_NOERROR) {
558 acmDriverClose(was->hAcmDriver, 0L);
559 HeapFree(MSACM_hHeap, 0, was);
564 TRACE("=> (%d)\n", ret);
568 /***********************************************************************
569 * acmStreamConvert (MSACM32.38)
571 MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash,
575 MMRESULT ret = MMSYSERR_NOERROR;
576 PACMDRVSTREAMHEADER padsh;
578 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwConvert);
580 if ((was = ACM_GetStream(has)) == NULL)
581 return MMSYSERR_INVALHANDLE;
582 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
583 return MMSYSERR_INVALPARAM;
585 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
586 return ACMERR_UNPREPARED;
588 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
589 * size. some fields are private to msacm internals, and are exposed
590 * in ACMSTREAMHEADER in the dwReservedDriver array
592 padsh = (PACMDRVSTREAMHEADER)pash;
594 /* check that pointers have not been modified */
595 if (padsh->pbPreparedSrc != padsh->pbSrc ||
596 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
597 padsh->pbPreparedDst != padsh->pbDst ||
598 padsh->cbPreparedDstLength < padsh->cbDstLength) {
599 return MMSYSERR_INVALPARAM;
602 padsh->fdwConvert = fdwConvert;
604 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CONVERT, (DWORD)&was->drvInst, (DWORD)padsh);
605 if (ret == MMSYSERR_NOERROR) {
606 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE;
608 TRACE("=> (%d)\n", ret);
613 /***********************************************************************
614 * acmStreamPrepareHeader (MSACM32.41)
616 MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
620 MMRESULT ret = MMSYSERR_NOERROR;
621 PACMDRVSTREAMHEADER padsh;
623 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwPrepare);
625 if ((was = ACM_GetStream(has)) == NULL)
626 return MMSYSERR_INVALHANDLE;
627 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
628 return MMSYSERR_INVALPARAM;
630 ret = MMSYSERR_INVALFLAG;
632 if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
633 return MMSYSERR_NOERROR;
635 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
636 * size. some fields are private to msacm internals, and are exposed
637 * in ACMSTREAMHEADER in the dwReservedDriver array
639 padsh = (PACMDRVSTREAMHEADER)pash;
641 padsh->fdwConvert = fdwPrepare;
642 padsh->padshNext = NULL;
643 padsh->fdwDriver = padsh->dwDriver = 0L;
645 padsh->fdwPrepared = 0;
646 padsh->dwPrepared = 0;
647 padsh->pbPreparedSrc = 0;
648 padsh->cbPreparedSrcLength = 0;
649 padsh->pbPreparedDst = 0;
650 padsh->cbPreparedDstLength = 0;
652 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_PREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
653 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
654 ret = MMSYSERR_NOERROR;
655 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
656 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
657 padsh->fdwPrepared = padsh->fdwStatus;
658 padsh->dwPrepared = 0;
659 padsh->pbPreparedSrc = padsh->pbSrc;
660 padsh->cbPreparedSrcLength = padsh->cbSrcLength;
661 padsh->pbPreparedDst = padsh->pbDst;
662 padsh->cbPreparedDstLength = padsh->cbDstLength;
664 padsh->fdwPrepared = 0;
665 padsh->dwPrepared = 0;
666 padsh->pbPreparedSrc = 0;
667 padsh->cbPreparedSrcLength = 0;
668 padsh->pbPreparedDst = 0;
669 padsh->cbPreparedDstLength = 0;
671 TRACE("=> (%d)\n", ret);
675 /***********************************************************************
676 * acmStreamReset (MSACM32.42)
678 MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
681 MMRESULT ret = MMSYSERR_NOERROR;
683 TRACE("(0x%08x, %ld)\n", has, fdwReset);
686 ret = MMSYSERR_INVALFLAG;
687 } else if ((was = ACM_GetStream(has)) == NULL) {
688 return MMSYSERR_INVALHANDLE;
689 } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
690 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_RESET, (DWORD)&was->drvInst, 0);
692 TRACE("=> (%d)\n", ret);
696 /***********************************************************************
697 * acmStreamSize (MSACM32.43)
699 MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
700 LPDWORD pdwOutputBytes, DWORD fdwSize)
703 ACMDRVSTREAMSIZE adss;
706 TRACE("(0x%08x, %ld, %p, %ld)\n", has, cbInput, pdwOutputBytes, fdwSize);
708 if ((was = ACM_GetStream(has)) == NULL) {
709 return MMSYSERR_INVALHANDLE;
711 if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
712 return MMSYSERR_INVALFLAG;
715 *pdwOutputBytes = 0L;
717 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
718 case ACM_STREAMSIZEF_DESTINATION:
719 adss.cbDstLength = cbInput;
720 adss.cbSrcLength = 0;
722 case ACM_STREAMSIZEF_SOURCE:
723 adss.cbSrcLength = cbInput;
724 adss.cbDstLength = 0;
727 return MMSYSERR_INVALFLAG;
730 adss.cbStruct = sizeof(adss);
731 adss.fdwSize = fdwSize;
732 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_SIZE,
733 (DWORD)&was->drvInst, (DWORD)&adss);
734 if (ret == MMSYSERR_NOERROR) {
735 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
736 case ACM_STREAMSIZEF_DESTINATION:
737 *pdwOutputBytes = adss.cbSrcLength;
739 case ACM_STREAMSIZEF_SOURCE:
740 *pdwOutputBytes = adss.cbDstLength;
744 TRACE("=> (%d) [%lu]\n", ret, *pdwOutputBytes);
748 /***********************************************************************
749 * acmStreamUnprepareHeader (MSACM32.44)
751 MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
755 MMRESULT ret = MMSYSERR_NOERROR;
756 PACMDRVSTREAMHEADER padsh;
758 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwUnprepare);
760 if ((was = ACM_GetStream(has)) == NULL)
761 return MMSYSERR_INVALHANDLE;
762 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
763 return MMSYSERR_INVALPARAM;
765 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
766 return ACMERR_UNPREPARED;
768 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
769 * size. some fields are private to msacm internals, and are exposed
770 * in ACMSTREAMHEADER in the dwReservedDriver array
772 padsh = (PACMDRVSTREAMHEADER)pash;
774 /* check that pointers have not been modified */
775 if (padsh->pbPreparedSrc != padsh->pbSrc ||
776 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
777 padsh->pbPreparedDst != padsh->pbDst ||
778 padsh->cbPreparedDstLength < padsh->cbDstLength) {
779 return MMSYSERR_INVALPARAM;
782 padsh->fdwConvert = fdwUnprepare;
784 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_UNPREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
785 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
786 ret = MMSYSERR_NOERROR;
787 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
789 TRACE("=> (%d)\n", ret);