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
21 ***************************************************************************/
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "winbase.h"
29 #include "windef.h"
30 #include "winuser.h"
31 #include "vfw.h"
32 #include "winestring.h"
33 #include "driver.h"
34 #include "winerror.h"
35 #include "msacm.h"
36 #include "msacmdrv.h"
37 #include "wineacm.h"
38 #include "ext.h"
39 #include "debugtools.h"
40
41 #include "driver.h"
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #pragma pack(1)
47 #define OpenDriverA DrvOpen
48 #define CloseDriver DrvClose
49
50 #pragma pack(1)
51
ACM_GetStream(HACMSTREAM has)52 static PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
53 {
54 return (PWINE_ACMSTREAM)has;
55 }
56
57 /***********************************************************************
58 * acmDriverAddA (MSACM32.2)
59 */
acmDriverAddA(PHACMDRIVERID phadid,HINSTANCE hinstModule,LPARAM lParam,DWORD dwPriority,DWORD fdwAdd)60 MMRESULT WINAPI acmDriverAddA(PHACMDRIVERID phadid, HINSTANCE hinstModule,
61 LPARAM lParam, DWORD dwPriority, DWORD fdwAdd)
62 {
63 if (!phadid)
64 return MMSYSERR_INVALPARAM;
65
66 /* Check if any unknown flags */
67 if (fdwAdd &
68 ~(ACM_DRIVERADDF_FUNCTION|ACM_DRIVERADDF_NOTIFYHWND|
69 ACM_DRIVERADDF_GLOBAL))
70 return MMSYSERR_INVALFLAG;
71
72 /* Check if any incompatible flags */
73 if ((fdwAdd & ACM_DRIVERADDF_FUNCTION) &&
74 (fdwAdd & ACM_DRIVERADDF_NOTIFYHWND))
75 return MMSYSERR_INVALFLAG;
76
77 /* FIXME: in fact, should GetModuleFileName(hinstModule) and do a
78 * LoadDriver on it, to be sure we can call SendDriverMessage on the
79 * hDrvr handle.
80 */
81 *phadid = (HACMDRIVERID) MSACM_RegisterDriver(NULL, NULL, hinstModule);
82
83 /* FIXME: lParam, dwPriority and fdwAdd ignored */
84 (void)lParam;
85 (void)dwPriority;
86
87 return MMSYSERR_NOERROR;
88 }
89
90 /***********************************************************************
91 * acmDriverClose (MSACM32.4)
92 */
acmDriverClose(HACMDRIVER had,DWORD fdwClose)93 MMRESULT WINAPI acmDriverClose(HACMDRIVER had, DWORD fdwClose)
94 {
95 PWINE_ACMDRIVER p;
96 PWINE_ACMDRIVER* tp;
97
98 if (fdwClose)
99 return MMSYSERR_INVALFLAG;
100
101 p = MSACM_GetDriver(had);
102 if (!p)
103 return MMSYSERR_INVALHANDLE;
104
105 for (tp = &(p->obj.pACMDriverID->pACMDriverList); *tp; *tp = (*tp)->pNextACMDriver) {
106 if (*tp == p) {
107 *tp = (*tp)->pNextACMDriver;
108 break;
109 }
110 }
111
112 if (p->hDrvr && !p->obj.pACMDriverID->pACMDriverList)
113 CloseDriver(p->hDrvr);
114
115 HeapFree(MSACM_hHeap, 0, p);
116
117 return MMSYSERR_NOERROR;
118 }
119
120 /***********************************************************************
121 * acmDriverEnum (MSACM32.7)
122 */
acmDriverEnum(ACMDRIVERENUMCB fnCallback,DWORD dwInstance,DWORD fdwEnum)123 MMRESULT WINAPI acmDriverEnum(ACMDRIVERENUMCB fnCallback, DWORD dwInstance, DWORD fdwEnum)
124 {
125 PWINE_ACMDRIVERID p;
126 DWORD fdwSupport;
127
128 if (!fnCallback) {
129 return MMSYSERR_INVALPARAM;
130 }
131
132 if (fdwEnum && ~(ACM_DRIVERENUMF_NOLOCAL|ACM_DRIVERENUMF_DISABLED)) {
133 return MMSYSERR_INVALFLAG;
134 }
135
136 for (p = MSACM_pFirstACMDriverID; p; p = p->pNextACMDriverID) {
137 fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
138 if (!p->bEnabled) {
139 if (fdwEnum & ACM_DRIVERENUMF_DISABLED)
140 fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
141 else
142 continue;
143 }
144 (*fnCallback)((HACMDRIVERID) p, dwInstance, fdwSupport);
145 }
146
147 return MMSYSERR_NOERROR;
148 }
149
150 /***********************************************************************
151 * acmDriverID (MSACM32.8)
152 */
acmDriverID(HACMOBJ hao,PHACMDRIVERID phadid,DWORD fdwDriverID)153 MMRESULT WINAPI acmDriverID(HACMOBJ hao, PHACMDRIVERID phadid, DWORD fdwDriverID)
154 {
155 PWINE_ACMOBJ pao;
156
157 pao = MSACM_GetObj(hao);
158 if (!pao)
159 return MMSYSERR_INVALHANDLE;
160
161 if (!phadid)
162 return MMSYSERR_INVALPARAM;
163
164 if (fdwDriverID)
165 return MMSYSERR_INVALFLAG;
166
167 *phadid = (HACMDRIVERID) pao->pACMDriverID;
168
169 return MMSYSERR_NOERROR;
170 }
171
172 /***********************************************************************
173 * acmDriverMessage (MSACM32.9)
174 * FIXME
175 * Not implemented
176 */
acmDriverMessage(HACMDRIVER had,UINT uMsg,LPARAM lParam1,LPARAM lParam2)177 LRESULT WINAPI acmDriverMessage(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
178 {
179 PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
180 if (!pad)
181 return MMSYSERR_INVALPARAM;
182
183 /* FIXME: Check if uMsg legal */
184
185 if (!SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2))
186 return MMSYSERR_NOTSUPPORTED;
187
188 return MMSYSERR_NOERROR;
189 }
190
191
192 /***********************************************************************
193 * acmDriverOpen (MSACM32.10)
194 */
acmDriverOpen(PHACMDRIVER phad,HACMDRIVERID hadid,DWORD fdwOpen)195 MMRESULT WINAPI acmDriverOpen(PHACMDRIVER phad, HACMDRIVERID hadid, DWORD fdwOpen)
196 {
197 PWINE_ACMDRIVERID padid;
198 PWINE_ACMDRIVER pad;
199 ICOPEN icopen;
200 /* HDRVR hdrv; -- not used */
201
202
203
204 TRACE("(%p, %x, %08lu)\n", phad, hadid, fdwOpen);
205
206 if (!phad)
207 return MMSYSERR_INVALPARAM;
208
209 padid = MSACM_GetDriverID(hadid);
210 if (!padid)
211 return MMSYSERR_INVALHANDLE;
212
213 if (fdwOpen)
214 return MMSYSERR_INVALFLAG;
215
216 pad = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVER));
217 if (!pad) return MMSYSERR_NOMEM;
218
219 pad->obj.pACMDriverID = padid;
220 icopen.fccType = mmioFOURCC('a', 'u', 'd', 'c');
221 icopen.fccHandler = (long)padid->pszFileName;
222 icopen.dwSize = sizeof(ICOPEN);
223 icopen.dwFlags = 0;
224
225 icopen.pV1Reserved = padid->pszFileName;
226 if (!padid->hInstModule)
227 pad->hDrvr = OpenDriverA((long)&icopen);
228 else
229 pad->hDrvr = padid->hInstModule;
230
231 if (!pad->hDrvr) {
232 HeapFree(MSACM_hHeap, 0, pad);
233 return MMSYSERR_ERROR;
234 }
235
236 pad->pfnDriverProc = GetProcAddress(pad->hDrvr, "DriverProc");
237
238 /* insert new pad at beg of list */
239 pad->pNextACMDriver = padid->pACMDriverList;
240 padid->pACMDriverList = pad;
241
242 /* FIXME: Create a WINE_ACMDRIVER32 */
243 *phad = (HACMDRIVER)pad;
244
245 return MMSYSERR_NOERROR;
246 }
247
248 /***********************************************************************
249 * acmDriverRemove (MSACM32.12)
250 */
acmDriverRemove(HACMDRIVERID hadid,DWORD fdwRemove)251 MMRESULT WINAPI acmDriverRemove(HACMDRIVERID hadid, DWORD fdwRemove)
252 {
253 PWINE_ACMDRIVERID padid;
254
255 padid = MSACM_GetDriverID(hadid);
256 if (!padid)
257 return MMSYSERR_INVALHANDLE;
258
259 if (fdwRemove)
260 return MMSYSERR_INVALFLAG;
261
262 MSACM_UnregisterDriver(padid);
263
264 return MMSYSERR_NOERROR;
265 }
266
267
268
269 /**********************************************************************/
270
271 HANDLE MSACM_hHeap = (HANDLE) NULL;
272 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
273 PWINE_ACMDRIVERID MSACM_pLastACMDriverID = NULL;
274
275 /***********************************************************************
276 * MSACM_RegisterDriver32()
277 */
MSACM_RegisterDriver(const char * pszFileName,WORD wFormatTag,HINSTANCE hinstModule)278 PWINE_ACMDRIVERID MSACM_RegisterDriver(const char* pszFileName,
279 WORD wFormatTag,
280 HINSTANCE hinstModule)
281 {
282 PWINE_ACMDRIVERID padid;
283
284 TRACE("('%s', '%x', 0x%08x)\n", pszFileName, wFormatTag, hinstModule);
285
286 padid = (PWINE_ACMDRIVERID) HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
287 padid->pszFileName = (char*)malloc(strlen(pszFileName)+1);
288 strcpy(padid->pszFileName, pszFileName);
289 // 1~strdup(pszDriverAlias);
290 padid->wFormatTag = wFormatTag;
291 padid->hInstModule = hinstModule;
292 padid->bEnabled = TRUE;
293 padid->pACMDriverList = NULL;
294 padid->pNextACMDriverID = NULL;
295 padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
296 if (MSACM_pLastACMDriverID)
297 MSACM_pLastACMDriverID->pNextACMDriverID = padid;
298 MSACM_pLastACMDriverID = padid;
299 if (!MSACM_pFirstACMDriverID)
300 MSACM_pFirstACMDriverID = padid;
301
302 return padid;
303 }
304
305
306 /***********************************************************************
307 * MSACM_UnregisterDriver32()
308 */
MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)309 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
310 {
311 PWINE_ACMDRIVERID pNextACMDriverID;
312
313 while (p->pACMDriverList)
314 acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
315
316 if (p->pszFileName)
317 free(p->pszFileName);
318
319 if (p == MSACM_pFirstACMDriverID)
320 MSACM_pFirstACMDriverID = p->pNextACMDriverID;
321 if (p == MSACM_pLastACMDriverID)
322 MSACM_pLastACMDriverID = p->pPrevACMDriverID;
323
324 if (p->pPrevACMDriverID)
325 p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
326 if (p->pNextACMDriverID)
327 p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
328
329 pNextACMDriverID = p->pNextACMDriverID;
330
331 HeapFree(MSACM_hHeap, 0, p);
332
333 return pNextACMDriverID;
334 }
335
336 /***********************************************************************
337 * MSACM_UnregisterAllDrivers32()
338 * FIXME
339 * Where should this function be called?
340 */
MSACM_UnregisterAllDrivers(void)341 void MSACM_UnregisterAllDrivers(void)
342 {
343 PWINE_ACMDRIVERID p;
344
345 for (p = MSACM_pFirstACMDriverID; p; p = MSACM_UnregisterDriver(p));
346 }
347
348 /***********************************************************************
349 * MSACM_GetDriverID32()
350 */
MSACM_GetDriverID(HACMDRIVERID hDriverID)351 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
352 {
353 return (PWINE_ACMDRIVERID)hDriverID;
354 }
355
356 /***********************************************************************
357 * MSACM_GetDriver32()
358 */
MSACM_GetDriver(HACMDRIVER hDriver)359 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
360 {
361 return (PWINE_ACMDRIVER)hDriver;
362 }
363
364 /***********************************************************************
365 * MSACM_GetObj32()
366 */
MSACM_GetObj(HACMOBJ hObj)367 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj)
368 {
369 return (PWINE_ACMOBJ)hObj;
370 }
371
372
373
374 /***********************************************************************
375 * acmStreamOpen (MSACM32.40)
376 */
acmStreamOpen(PHACMSTREAM phas,HACMDRIVER had,PWAVEFORMATEX pwfxSrc,PWAVEFORMATEX pwfxDst,PWAVEFILTER pwfltr,DWORD dwCallback,DWORD dwInstance,DWORD fdwOpen)377 MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
378 PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
379 DWORD dwInstance, DWORD fdwOpen)
380 {
381 PWINE_ACMSTREAM was;
382 PWINE_ACMDRIVER wad;
383 MMRESULT ret;
384 int wfxSrcSize;
385 int wfxDstSize;
386
387 TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
388 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
389
390 TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
391 pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
392 pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize);
393
394 TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
395 pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
396 pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
397
398 #define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize))
399 wfxSrcSize = SIZEOF_WFX(pwfxSrc);
400 wfxDstSize = SIZEOF_WFX(pwfxDst);
401 #undef SIZEOF_WFX
402
403 was = (PWINE_ACMSTREAM) HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0));
404 if (was == NULL)
405 return MMSYSERR_NOMEM;
406 was->drvInst.cbStruct = sizeof(was->drvInst);
407 was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
408 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
409 // LHACM is checking for 0x1
410 // but if this will not help
411 // was->drvInst.pwfxSrc->wFormatTag = 1;
412 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
413 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
414 if (pwfltr) {
415 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
416 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
417 } else {
418 was->drvInst.pwfltr = NULL;
419 }
420 was->drvInst.dwCallback = dwCallback;
421 was->drvInst.dwInstance = dwInstance;
422 was->drvInst.fdwOpen = fdwOpen;
423 was->drvInst.fdwDriver = 0L;
424 was->drvInst.dwDriver = 0L;
425 was->drvInst.has = (HACMSTREAM)was;
426
427 if (had) {
428 if (!(wad = MSACM_GetDriver(had))) {
429 ret = MMSYSERR_INVALPARAM;
430 goto errCleanUp;
431 }
432
433 was->obj.pACMDriverID = wad->obj.pACMDriverID;
434 was->pDrv = wad;
435 was->hAcmDriver = 0; /* not to close it in acmStreamClose */
436
437 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
438 if (ret != MMSYSERR_NOERROR)
439 goto errCleanUp;
440 } else {
441 PWINE_ACMDRIVERID wadi;
442 /* short drv_tag; -- not used */
443 ret = ACMERR_NOTPOSSIBLE;
444 /* if(pwfxSrc->wFormatTag==1)//compression
445 drv_tag=pwfxDst->wFormatTag;
446 else
447 if(pwfxDst->wFormatTag==1)//decompression
448 drv_tag=pwfxSrc->wFormatTag;
449 else
450 goto errCleanUp;
451
452 ret=acmDriverOpen2(drv_tag);
453 if (ret == MMSYSERR_NOERROR) {
454 if ((wad = MSACM_GetDriver(had)) != 0) {
455 was->obj.pACMDriverID = wad->obj.pACMDriverID;
456 was->pDrv = wad;
457 was->hAcmDriver = had;
458
459 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
460 if (ret == MMSYSERR_NOERROR) {
461 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
462 acmDriverClose(had, 0L);
463 }
464 break;
465 }
466 }
467 acmDriverClose(had, 0L);*/
468 //if(MSACM_pFirstACMDriverID==NULL)
469 // MSACM_RegisterAllDrivers();
470
471 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID)
472 {
473 /* Check Format */
474 if ((int)wadi->wFormatTag != (int)pwfxSrc->wFormatTag) continue;
475
476 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
477 if (ret == MMSYSERR_NOERROR) {
478 if ((wad = MSACM_GetDriver(had)) != 0) {
479 was->obj.pACMDriverID = wad->obj.pACMDriverID;
480 was->pDrv = wad;
481 was->hAcmDriver = had;
482
483 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
484 //lhacm - crash printf("RETOPEN %d\n", ret);
485 //ret = 0;
486 if (ret == MMSYSERR_NOERROR) {
487 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
488 acmDriverClose(had, 0L);
489 }
490 break;
491 }
492 }
493 // no match, close this acm driver and try next one
494 acmDriverClose(had, 0L);
495 }
496 }
497 if (ret != MMSYSERR_NOERROR) {
498 ret = ACMERR_NOTPOSSIBLE;
499 goto errCleanUp;
500 }
501 }
502 ret = MMSYSERR_NOERROR;
503 if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
504 if (phas)
505 *phas = (HACMSTREAM)was;
506 TRACE("=> (%d)\n", ret);
507 CodecAlloc();
508 return ret;
509 }
510 errCleanUp:
511 if (phas)
512 *phas = (HACMSTREAM)0;
513 HeapFree(MSACM_hHeap, 0, was);
514 TRACE("=> (%d)\n", ret);
515 return ret;
516 }
517
518
acmStreamClose(HACMSTREAM has,DWORD fdwClose)519 MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
520 {
521 PWINE_ACMSTREAM was;
522 MMRESULT ret;
523
524 TRACE("(0x%08x, %ld)\n", has, fdwClose);
525
526 if ((was = ACM_GetStream(has)) == NULL) {
527 return MMSYSERR_INVALHANDLE;
528 }
529 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
530 if (ret == MMSYSERR_NOERROR) {
531 if (was->hAcmDriver)
532 acmDriverClose(was->hAcmDriver, 0L);
533 HeapFree(MSACM_hHeap, 0, was);
534 CodecRelease();
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