1 /**************************************************************************
2
3
4 This file will contain an interface to ACM drivers.
5 Its content will be based mainly on wine/dlls/msacm32
6 actually, for audio decompression only the following functions
7 are needed:
8
9 acmStreamOpen ( takes formats of src and dest, returns stream handle )
10 acmStreamPrepareHeader ( takes stream handler and info on data )
11 acmStreamConvert ( the same as PrepareHeader )
12 acmStreamUnprepareHeader
13 acmStreamClose
14 acmStreamSize
15 maybe acmStreamReset
16
17 In future I'll also add functions for format enumeration,
18 but not right now.
19
20 Modified for use with MPlayer, detailed changelog at
21 http://svn.mplayerhq.hu/mplayer/trunk/
22
23 ***************************************************************************/
24 #include "config.h"
25 #include "debug.h"
26
27 #include "wine/winbase.h"
28 #include "wine/windef.h"
29 #include "wine/winuser.h"
30 #include "wine/vfw.h"
31 #include "wine/winestring.h"
32 #include "wine/driver.h"
33 #include "wine/winerror.h"
34 #include "wine/msacm.h"
35 #include "wine/msacmdrv.h"
36 #include "wineacm.h"
37 #ifndef __MINGW32__
38 #include "ext.h"
39 #endif
40 #include "drv.h"
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #pragma pack(1)
46 #define OpenDriverA DrvOpen
47 #define CloseDriver DrvClose
48
ACM_GetStream(HACMSTREAM has)49 static inline PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
50 {
51 return (PWINE_ACMSTREAM)has;
52 }
53
54 /***********************************************************************
55 * acmDriverAddA (MSACM32.2)
56 */
acmDriverAddA(PHACMDRIVERID phadid,HINSTANCE hinstModule,LPARAM lParam,DWORD dwPriority,DWORD fdwAdd)57 MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
58 LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
59 {
60 if (!phadid)
61 return MMSYSERR_INVALPARAM;
62
63 /* Check if any unknown flags */
64 if (fdwAdd &
65 ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
66 ACM_DRIVERADDF_GLOBAL))
67 return MMSYSERR_INVALFLAG;
68
69 /* Check if any incompatible flags */
70 if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
71 (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
72 return MMSYSERR_INVALFLAG;
73
74 /* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
75 * LoadDriver on it, to be sure we can call SendDriverMessage on the
76 * hDrvr handle.
77 */
78 *phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, 0, hinstModule);
79
80 /* FIXME: lParam, dwPriority and fdwAdd ignored */
81
82 return MMSYSERR_NOERROR;
83 }
84
85 /***********************************************************************
86 * acmDriverClose (MSACM32.4)
87 */
acmDriverClose(HACMDRIVER had,DWORD fdwClose)88 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
89 {
90 PWINE_ACMDRIVER p;
91 PWINE_ACMDRIVER* tp;
92
93 if (fdwClose)
94 return MMSYSERR_INVALFLAG;
95
96 p = MSACM_GetDriver(had);
97 if (!p)
98 return MMSYSERR_INVALHANDLE;
99
100 for (tp = &(p->obj.pACMDriverID->pACMDriverList); *tp; *tp = (*tp)->pNextACMDriver) {
101 if (*tp == p) {
102 *tp = (*tp)->pNextACMDriver;
103 break;
104 }
105 }
106
107 if (p->hDrvr && !p->obj.pACMDriverID->pACMDriverList)
108 CloseDriver(p->hDrvr);
109
110 HeapFree(MSACM_hHeap, 0, p);
111
112 return MMSYSERR_NOERROR;
113 }
114
115 /***********************************************************************
116 * acmDriverEnum (MSACM32.7)
117 */
acmDriverEnum(ACMDRIVERENUMCB fnCallback,DWORD dwInstance,DWORD fdwEnum)118 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
119 {
120 PWINE_ACMDRIVERID p;
121 DWORD fdwSupport;
122
123 if (!fnCallback) {
124 return MMSYSERR_INVALPARAM;
125 }
126
127 if (fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED)) {
128 return MMSYSERR_INVALFLAG;
129 }
130
131 for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
132 fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
133 if (!p->bEnabled) {
134 if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
135 fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
136 else
137 continue;
138 }
139 (*fnCallback)((HACMDRIVERID) p, dwInstance, fdwSupport);
140 }
141
142 return MMSYSERR_NOERROR;
143 }
144
145 /***********************************************************************
146 * acmDriverID (MSACM32.8)
147 */
acmDriverID(HACMOBJ hao,PHACMDRIVERID phadid,DWORD fdwDriverID)148 MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
149 {
150 PWINE_ACMOBJ pao;
151
152 pao = MSACM_GetObj(hao);
153 if (!pao)
154 return MMSYSERR_INVALHANDLE;
155
156 if (!phadid)
157 return MMSYSERR_INVALPARAM;
158
159 if (fdwDriverID)
160 return MMSYSERR_INVALFLAG;
161
162 *phadid = (HACMDRIVERID) pao->pACMDriverID;
163
164 return MMSYSERR_NOERROR;
165 }
166
167 /***********************************************************************
168 * acmDriverMessage (MSACM32.9)
169 * FIXME
170 * Not implemented
171 */
acmDriverMessage(HACMDRIVER had,UINT uMsg,LPARAM lParam1,LPARAM lParam2)172 LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
173 {
174 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
175 if (!pad)
176 return MMSYSERR_INVALPARAM;
177
178 /* FIXME: Check if uMsg legal */
179
180 if (!SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2))
181 return MMSYSERR_NOTSUPPORTED;
182
183 return MMSYSERR_NOERROR;
184 }
185
186
187 /***********************************************************************
188 * acmDriverOpen (MSACM32.10)
189 */
acmDriverOpen(PHACMDRIVER phad,HACMDRIVERID hadid,DWORD fdwOpen)190 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
191 {
192 PWINE_ACMDRIVERID padid;
193 PWINE_ACMDRIVER pad;
194 ICOPEN icopen;
195
196
197 TRACE("(%p, %x, %08lu)\n", phad, hadid, fdwOpen);
198
199 if (!phad)
200 return MMSYSERR_INVALPARAM;
201
202 padid = MSACM_GetDriverID(hadid);
203 if (!padid)
204 return MMSYSERR_INVALHANDLE;
205
206 if (fdwOpen)
207 return MMSYSERR_INVALFLAG;
208
209 pad = (PWINE_ACMDRIVER) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
210 if (!pad)
211 return MMSYSERR_NOMEM;
212
213 pad->obj.pACMDriverID = padid;
214 icopen.fccType = mmioFOURCC('a', 'u', 'd', 'c');
215 icopen.fccHandler = (long)padid->pszFileName;
216 icopen.dwSize = sizeof(ICOPEN);
217 icopen.dwFlags = 0;
218
219 icopen.pV1Reserved = padid->pszFileName;
220 if (!padid->hInstModule)
221 pad->hDrvr = OpenDriverA((long)&icopen);
222 else
223 pad->hDrvr = padid->hInstModule;
224
225 if (!pad->hDrvr) {
226 HeapFree(MSACM_hHeap, 0, pad);
227 return MMSYSERR_ERROR;
228 }
229
230 pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc");
231
232 /* insert new pad at beg of list */
233 pad->pNextACMDriver = padid->pACMDriverList;
234 padid->pACMDriverList = pad;
235
236 /* FIXME: Create a WINE_ACMDRIVER32 */
237 *phad = (HACMDRIVER)pad;
238
239 return MMSYSERR_NOERROR;
240 }
241
242 /***********************************************************************
243 * acmDriverRemove (MSACM32.12)
244 */
acmDriverRemove(HACMDRIVERID hadid,DWORD fdwRemove)245 MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
246 {
247 PWINE_ACMDRIVERID padid;
248
249 padid = MSACM_GetDriverID(hadid);
250 if (!padid)
251 return MMSYSERR_INVALHANDLE;
252
253 if (fdwRemove)
254 return MMSYSERR_INVALFLAG;
255
256 MSACM_UnregisterDriver(padid);
257
258 return MMSYSERR_NOERROR;
259 }
260
261
262
263 /**********************************************************************/
264
265 HANDLE MSACM_hHeap = (HANDLE) NULL;
266 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
267 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
268
269 /***********************************************************************
270 * MSACM_RegisterDriver32()
271 */
MSACM_RegisterDriver(const char * pszFileName,WORD wFormatTag,HINSTANCE hinstModule)272 PWINE_ACMDRIVERID MSACM_RegisterDriver(const char* pszFileName,
273 WORD wFormatTag,
274 HINSTANCE hinstModule)
275 {
276 PWINE_ACMDRIVERID padid;
277
278 TRACE("('%s', '%x', 0x%08x)\n", pszFileName, wFormatTag, hinstModule);
279
280 #ifndef WIN32_LOADER
281 MSACM_hHeap = GetProcessHeap();
282 #endif
283 padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
284 padid->pszFileName = malloc(strlen(pszFileName)+1);
285 strcpy(padid->pszFileName, pszFileName);
286 // 1~strdup(pszDriverAlias);
287 padid->wFormatTag = wFormatTag;
288 padid->hInstModule = hinstModule;
289 padid->bEnabled = TRUE;
290 padid->pACMDriverList = NULL;
291 padid->pNextACMDriverID = NULL;
292 padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
293 if (MSACM_pLastACMDriverID)
294 MSACM_pLastACMDriverID->pNextACMDriverID = padid;
295 MSACM_pLastACMDriverID = padid;
296 if (!MSACM_pFirstACMDriverID)
297 MSACM_pFirstACMDriverID = padid;
298
299 return padid;
300 }
301
302
303 /***********************************************************************
304 * MSACM_UnregisterDriver32()
305 */
MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)306 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
307 {
308 PWINE_ACMDRIVERID pNextACMDriverID;
309
310 while (p->pACMDriverList)
311 acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
312
313 free(p->pszFileName);
314
315 if (p == MSACM_pFirstACMDriverID)
316 MSACM_pFirstACMDriverID = p->pNextACMDriverID;
317 if (p == MSACM_pLastACMDriverID)
318 MSACM_pLastACMDriverID = p->pPrevACMDriverID;
319
320 if (p->pPrevACMDriverID)
321 p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
322 if (p->pNextACMDriverID)
323 p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
324
325 pNextACMDriverID = p->pNextACMDriverID;
326
327 HeapFree(MSACM_hHeap, 0, p);
328
329 return pNextACMDriverID;
330 }
331
332 /***********************************************************************
333 * MSACM_UnregisterAllDrivers32()
334 * FIXME
335 * Where should this function be called?
336 */
MSACM_UnregisterAllDrivers(void)337 void MSACM_UnregisterAllDrivers(void)
338 {
339 PWINE_ACMDRIVERID p;
340
341 for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
342 }
343
344 /***********************************************************************
345 * MSACM_GetDriverID32()
346 */
MSACM_GetDriverID(HACMDRIVERID hDriverID)347 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
348 {
349 return (PWINE_ACMDRIVERID)hDriverID;
350 }
351
352 /***********************************************************************
353 * MSACM_GetDriver32()
354 */
MSACM_GetDriver(HACMDRIVER hDriver)355 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
356 {
357 return (PWINE_ACMDRIVER)hDriver;
358 }
359
360 /***********************************************************************
361 * MSACM_GetObj32()
362 */
MSACM_GetObj(HACMOBJ hObj)363 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj)
364 {
365 return (PWINE_ACMOBJ)hObj;
366 }
367
368
369
370 /***********************************************************************
371 * acmStreamOpen (MSACM32.40)
372 */
acmStreamOpen(PHACMSTREAM phas,HACMDRIVER had,PWAVEFORMATEX pwfxSrc,PWAVEFORMATEX pwfxDst,PWAVEFILTER pwfltr,DWORD dwCallback,DWORD dwInstance,DWORD fdwOpen)373 MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
374 PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
375 DWORD dwInstance, DWORD fdwOpen)
376 {
377 PWINE_ACMSTREAM was;
378 PWINE_ACMDRIVER wad;
379 MMRESULT ret;
380 int wfxSrcSize;
381 int wfxDstSize;
382
383 TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
384 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
385
386 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
387 pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
388 pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize);
389
390 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
391 pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
392 pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
393
394 #define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize))
395 wfxSrcSize = SIZEOF_WFX(pwfxSrc);
396 wfxDstSize = SIZEOF_WFX(pwfxDst);
397 #undef SIZEOF_WFX
398
399 was = (PWINE_ACMSTREAM) HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0));
400 if (was == NULL)
401 return MMSYSERR_NOMEM;
402 was->drvInst.cbStruct = sizeof(was->drvInst);
403 was->drvInst.pwfxSrc = (PWAVEFORMATEX)(was + 1);
404 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
405 // LHACM is checking for 0x1
406 // but if this will not help
407 // was->drvInst.pwfxSrc->wFormatTag = 1;
408 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)(was + 1) + wfxSrcSize);
409 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
410 if (pwfltr) {
411 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)(was + 1) + wfxSrcSize + wfxDstSize);
412 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
413 } else {
414 was->drvInst.pwfltr = NULL;
415 }
416 was->drvInst.dwCallback = dwCallback;
417 was->drvInst.dwInstance = dwInstance;
418 was->drvInst.fdwOpen = fdwOpen;
419 was->drvInst.fdwDriver = 0L;
420 was->drvInst.dwDriver = 0L;
421 was->drvInst.has = (HACMSTREAM)was;
422
423 if (had) {
424 if (!(wad = MSACM_GetDriver(had))) {
425 ret = MMSYSERR_INVALPARAM;
426 goto errCleanUp;
427 }
428
429 was->obj.pACMDriverID = wad->obj.pACMDriverID;
430 was->pDrv = wad;
431 was->hAcmDriver = 0; /* not to close it in acmStreamClose */
432
433 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
434 if (ret != MMSYSERR_NOERROR)
435 goto errCleanUp;
436 } else {
437 PWINE_ACMDRIVERID wadi;
438 //short drv_tag;
439 ret = ACMERR_NOTPOSSIBLE;
440 /* if(pwfxSrc->wFormatTag==1)//compression
441 drv_tag=pwfxDst->wFormatTag;
442 else
443 if(pwfxDst->wFormatTag==1)//decompression
444 drv_tag=pwfxSrc->wFormatTag;
445 else
446 goto errCleanUp;
447
448 ret=acmDriverOpen2(drv_tag);
449 if (ret == MMSYSERR_NOERROR) {
450 if ((wad = MSACM_GetDriver(had)) != 0) {
451 was->obj.pACMDriverID = wad->obj.pACMDriverID;
452 was->pDrv = wad;
453 was->hAcmDriver = had;
454
455 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
456 if (ret == MMSYSERR_NOERROR) {
457 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
458 acmDriverClose(had, 0L);
459 }
460 break;
461 }
462 }
463 acmDriverClose(had, 0L);*/
464 //if(MSACM_pFirstACMDriverID==NULL)
465 // MSACM_RegisterAllDrivers();
466
467 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID)
468 {
469 /* Check Format */
470 if ((int)wadi->wFormatTag != (int)pwfxSrc->wFormatTag) continue;
471
472 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
473 if (ret == MMSYSERR_NOERROR) {
474 if ((wad = MSACM_GetDriver(had)) != 0) {
475 was->obj.pACMDriverID = wad->obj.pACMDriverID;
476 was->pDrv = wad;
477 was->hAcmDriver = had;
478
479 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
480 //lhacm - crash printf("RETOPEN %d\n", ret);
481 //ret = 0;
482 if (ret == MMSYSERR_NOERROR) {
483 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
484 acmDriverClose(had, 0L);
485 }
486 break;
487 }
488 }
489 // no match, close this acm driver and try next one
490 acmDriverClose(had, 0L);
491 }
492 }
493 if (ret != MMSYSERR_NOERROR) {
494 ret = ACMERR_NOTPOSSIBLE;
495 goto errCleanUp;
496 }
497 }
498 ret = MMSYSERR_NOERROR;
499 if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
500 if (phas)
501 *phas = (HACMSTREAM)was;
502 TRACE("=> (%d)\n", ret);
503 #ifdef WIN32_LOADER
504 CodecAlloc();
505 #endif
506 return ret;
507 }
508 errCleanUp:
509 if (phas)
510 *phas = (HACMSTREAM)0;
511 HeapFree(MSACM_hHeap, 0, was);
512 TRACE("=> (%d)\n", ret);
513 return ret;
514 }
515
516
acmStreamClose(HACMSTREAM has,DWORD fdwClose)517 MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
518 {
519 PWINE_ACMSTREAM was;
520 MMRESULT ret;
521
522 TRACE("(0x%08x, %ld)\n", has, fdwClose);
523
524 if ((was = ACM_GetStream(has)) == NULL) {
525 return MMSYSERR_INVALHANDLE;
526 }
527 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
528 if (ret == MMSYSERR_NOERROR) {
529 if (was->hAcmDriver)
530 acmDriverClose(was->hAcmDriver, 0L);
531 HeapFree(MSACM_hHeap, 0, was);
532 #ifdef WIN32_LOADER
533 CodecRelease();
534 #endif
535 }
536 TRACE("=> (%d)\n", ret);
537 return ret;
538 }
539
540 /***********************************************************************
541 * acmStreamConvert (MSACM32.38)
542 */
acmStreamConvert(HACMSTREAM has,PACMSTREAMHEADER pash,DWORD fdwConvert)543 MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash,
544 DWORD fdwConvert)
545 {
546 PWINE_ACMSTREAM was;
547 MMRESULT ret = MMSYSERR_NOERROR;
548 PACMDRVSTREAMHEADER padsh;
549
550 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwConvert);
551
552 if ((was = ACM_GetStream(has)) == NULL)
553 return MMSYSERR_INVALHANDLE;
554 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
555 return MMSYSERR_INVALPARAM;
556
557 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
558 return ACMERR_UNPREPARED;
559
560 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
561 * size. some fields are private to msacm internals, and are exposed
562 * in ACMSTREAMHEADER in the dwReservedDriver array
563 */
564 padsh = (PACMDRVSTREAMHEADER)pash;
565
566 /* check that pointers have not been modified */
567 if (padsh->pbPreparedSrc != padsh->pbSrc ||
568 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
569 padsh->pbPreparedDst != padsh->pbDst ||
570 padsh->cbPreparedDstLength < padsh->cbDstLength) {
571 return MMSYSERR_INVALPARAM;
572 }
573
574 padsh->fdwConvert = fdwConvert;
575
576 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CONVERT, (DWORD)&was->drvInst, (DWORD)padsh);
577 if (ret == MMSYSERR_NOERROR) {
578 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE;
579 }
580 TRACE("=> (%d)\n", ret);
581 return ret;
582 }
583
584
585 /***********************************************************************
586 * acmStreamPrepareHeader (MSACM32.41)
587 */
acmStreamPrepareHeader(HACMSTREAM has,PACMSTREAMHEADER pash,DWORD fdwPrepare)588 MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
589 DWORD fdwPrepare)
590 {
591 PWINE_ACMSTREAM was;
592 MMRESULT ret = MMSYSERR_NOERROR;
593 PACMDRVSTREAMHEADER padsh;
594
595 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwPrepare);
596
597 if ((was = ACM_GetStream(has)) == NULL)
598 return MMSYSERR_INVALHANDLE;
599 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
600 return MMSYSERR_INVALPARAM;
601 if (fdwPrepare)
602 ret = MMSYSERR_INVALFLAG;
603
604 if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
605 return MMSYSERR_NOERROR;
606
607 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
608 * size. some fields are private to msacm internals, and are exposed
609 * in ACMSTREAMHEADER in the dwReservedDriver array
610 */
611 padsh = (PACMDRVSTREAMHEADER)pash;
612
613 padsh->fdwConvert = fdwPrepare;
614 padsh->padshNext = NULL;
615 padsh->fdwDriver = padsh->dwDriver = 0L;
616
617 padsh->fdwPrepared = 0;
618 padsh->dwPrepared = 0;
619 padsh->pbPreparedSrc = 0;
620 padsh->cbPreparedSrcLength = 0;
621 padsh->pbPreparedDst = 0;
622 padsh->cbPreparedDstLength = 0;
623
624 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_PREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
625 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
626 ret = MMSYSERR_NOERROR;
627 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
628 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
629 padsh->fdwPrepared = padsh->fdwStatus;
630 padsh->dwPrepared = 0;
631 padsh->pbPreparedSrc = padsh->pbSrc;
632 padsh->cbPreparedSrcLength = padsh->cbSrcLength;
633 padsh->pbPreparedDst = padsh->pbDst;
634 padsh->cbPreparedDstLength = padsh->cbDstLength;
635 } else {
636 padsh->fdwPrepared = 0;
637 padsh->dwPrepared = 0;
638 padsh->pbPreparedSrc = 0;
639 padsh->cbPreparedSrcLength = 0;
640 padsh->pbPreparedDst = 0;
641 padsh->cbPreparedDstLength = 0;
642 }
643 TRACE("=> (%d)\n", ret);
644 return ret;
645 }
646
647 /***********************************************************************
648 * acmStreamReset (MSACM32.42)
649 */
acmStreamReset(HACMSTREAM has,DWORD fdwReset)650 MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
651 {
652 PWINE_ACMSTREAM was;
653 MMRESULT ret = MMSYSERR_NOERROR;
654
655 TRACE("(0x%08x, %ld)\n", has, fdwReset);
656
657 if (fdwReset) {
658 ret = MMSYSERR_INVALFLAG;
659 } else if ((was = ACM_GetStream(has)) == NULL) {
660 return MMSYSERR_INVALHANDLE;
661 } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
662 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_RESET, (DWORD)&was->drvInst, 0);
663 }
664 TRACE("=> (%d)\n", ret);
665 return ret;
666 }
667
668 /***********************************************************************
669 * acmStreamSize (MSACM32.43)
670 */
acmStreamSize(HACMSTREAM has,DWORD cbInput,LPDWORD pdwOutputBytes,DWORD fdwSize)671 MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
672 LPDWORD pdwOutputBytes, DWORD fdwSize)
673 {
674 PWINE_ACMSTREAM was;
675 ACMDRVSTREAMSIZE adss;
676 MMRESULT ret;
677
678 TRACE("(0x%08x, %ld, %p, %ld)\n", has, cbInput, pdwOutputBytes, fdwSize);
679
680 if ((was = ACM_GetStream(has)) == NULL) {
681 return MMSYSERR_INVALHANDLE;
682 }
683 if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
684 return MMSYSERR_INVALFLAG;
685 }
686
687 *pdwOutputBytes = 0L;
688
689 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
690 case ACM_STREAMSIZEF_DESTINATION:
691 adss.cbDstLength = cbInput;
692 adss.cbSrcLength = 0;
693 break;
694 case ACM_STREAMSIZEF_SOURCE:
695 adss.cbSrcLength = cbInput;
696 adss.cbDstLength = 0;
697 break;
698 default:
699 return MMSYSERR_INVALFLAG;
700 }
701
702 adss.cbStruct = sizeof(adss);
703 adss.fdwSize = fdwSize;
704 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_SIZE,
705 (DWORD)&was->drvInst, (DWORD)&adss);
706 if (ret == MMSYSERR_NOERROR) {
707 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
708 case ACM_STREAMSIZEF_DESTINATION:
709 *pdwOutputBytes = adss.cbSrcLength;
710 break;
711 case ACM_STREAMSIZEF_SOURCE:
712 *pdwOutputBytes = adss.cbDstLength;
713 break;
714 }
715 }
716 TRACE("=> (%d) [%lu]\n", ret, *pdwOutputBytes);
717 return ret;
718 }
719
720 /***********************************************************************
721 * acmStreamUnprepareHeader (MSACM32.44)
722 */
acmStreamUnprepareHeader(HACMSTREAM has,PACMSTREAMHEADER pash,DWORD fdwUnprepare)723 MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
724 DWORD fdwUnprepare)
725 {
726 PWINE_ACMSTREAM was;
727 MMRESULT ret = MMSYSERR_NOERROR;
728 PACMDRVSTREAMHEADER padsh;
729
730 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwUnprepare);
731
732 if ((was = ACM_GetStream(has)) == NULL)
733 return MMSYSERR_INVALHANDLE;
734 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
735 return MMSYSERR_INVALPARAM;
736
737 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
738 return ACMERR_UNPREPARED;
739
740 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
741 * size. some fields are private to msacm internals, and are exposed
742 * in ACMSTREAMHEADER in the dwReservedDriver array
743 */
744 padsh = (PACMDRVSTREAMHEADER)pash;
745
746 /* check that pointers have not been modified */
747 if (padsh->pbPreparedSrc != padsh->pbSrc ||
748 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
749 padsh->pbPreparedDst != padsh->pbDst ||
750 padsh->cbPreparedDstLength < padsh->cbDstLength) {
751 return MMSYSERR_INVALPARAM;
752 }
753
754 padsh->fdwConvert = fdwUnprepare;
755
756 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_UNPREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
757 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
758 ret = MMSYSERR_NOERROR;
759 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
760 }
761 TRACE("=> (%d)\n", ret);
762 return ret;
763 }
764