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