source: trunk/src/msacm32/stream.cpp@ 1687

Last change on this file since 1687 was 1607, checked in by sandervl, 26 years ago

Jens Weissner's update

File size: 12.2 KB
Line 
1/* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3/*
4 * MSACM32 library
5 *
6 * Copyright 1998 Patrik Stridvall
7 * 1999 Eric Pouech
8 */
9
10/* TODO
11 * + asynchronous conversion is not implemented
12 * + callback/notification
13 * * acmStreamMessage
14 * + properly close ACM streams
15 */
16
17#include <os2win.h>
18#include <string.h>
19#include "winbase.h"
20#include "winerror.h"
21#include "windef.h"
22#include "debugtools.h"
23#include "mmsystem.h"
24#include "msacm.h"
25#include "msacmdrv.h"
26#include "wineacm.h"
27
28DEFAULT_DEBUG_CHANNEL(msacm)
29
30static PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
31{
32 return (PWINE_ACMSTREAM)has;
33}
34
35/***********************************************************************
36 * acmStreamClose (MSACM32.37)
37 */
38MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
39{
40 PWINE_ACMSTREAM was;
41 MMRESULT ret;
42
43 dprintf(("(0x%08x, %ld)\n", has, fdwClose));
44
45 if ((was = ACM_GetStream(has)) == NULL) {
46 return MMSYSERR_INVALHANDLE;
47 }
48 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
49 if (ret == MMSYSERR_NOERROR) {
50 /* FIXME: shall the was->pDrv->hDrvr be also closed ? */
51 HeapFree(MSACM_hHeap, 0, was);
52 }
53 dprintf(("=> (%d)\n", ret));
54 return ret;
55}
56
57/***********************************************************************
58 * acmStreamConvert (MSACM32.38)
59 */
60MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash,
61 DWORD fdwConvert)
62{
63 PWINE_ACMSTREAM was;
64 MMRESULT ret = MMSYSERR_NOERROR;
65 PACMDRVSTREAMHEADER padsh;
66
67 dprintf(("(0x%08x, %p, %ld)\n", has, pash, fdwConvert));
68
69 if ((was = ACM_GetStream(has)) == NULL)
70 return MMSYSERR_INVALHANDLE;
71 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
72 return MMSYSERR_INVALPARAM;
73
74 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
75 return ACMERR_UNPREPARED;
76
77 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
78 * size. some fields are private to msacm internals, and are exposed
79 * in ACMSTREAMHEADER in the dwReservedDriver array
80 */
81 padsh = (PACMDRVSTREAMHEADER)pash;
82
83 /* check that pointers have not been modified */
84 if (padsh->pbPreparedSrc != padsh->pbSrc ||
85 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
86 padsh->pbPreparedDst != padsh->pbDst ||
87 padsh->cbPreparedDstLength < padsh->cbDstLength) {
88 return MMSYSERR_INVALPARAM;
89 }
90
91 padsh->fdwConvert = fdwConvert;
92
93 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CONVERT, (DWORD)&was->drvInst, (DWORD)padsh);
94 if (ret == MMSYSERR_NOERROR) {
95 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE;
96 }
97 dprintf(("=> (%d)\n", ret));
98 return ret;
99}
100
101/***********************************************************************
102 * acmStreamMessage (MSACM32.39)
103 */
104MMRESULT WINAPI acmStreamMessage(HACMSTREAM has, UINT uMsg, LPARAM lParam1,
105 LPARAM lParam2)
106{
107 dprintf(("(0x%08x, %u, %ld, %ld): stub\n", has, uMsg, lParam1, lParam2));
108 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
109 return MMSYSERR_ERROR;
110}
111
112/***********************************************************************
113 * acmStreamOpen (MSACM32.40)
114 */
115MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc,
116 PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD dwCallback,
117 DWORD dwInstance, DWORD fdwOpen)
118{
119 PWINE_ACMSTREAM was;
120 PWINE_ACMDRIVER wad;
121 MMRESULT ret;
122 int wfxSrcSize;
123 int wfxDstSize;
124
125 dprintf(("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
126 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen));
127
128 dprintf(("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
129 pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
130 pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize));
131
132 dprintf(("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%lu, nAvgBytesPerSec=%lu, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
133 pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
134 pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize));
135
136#define SIZEOF_WFX(wfx) (sizeof(WAVEFORMATEX) + ((wfx->wFormatTag == WAVE_FORMAT_PCM) ? 0 : wfx->cbSize))
137 wfxSrcSize = SIZEOF_WFX(pwfxSrc);
138 wfxDstSize = SIZEOF_WFX(pwfxDst);
139#undef SIZEOF_WFX
140
141 was = PWINE_ACMSTREAM(HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0)));
142 if (was == NULL)
143 return MMSYSERR_NOMEM;
144
145 was->drvInst.cbStruct = sizeof(was->drvInst);
146 was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
147 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
148 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
149 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
150 if (pwfltr) {
151 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
152 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
153 } else {
154 was->drvInst.pwfltr = NULL;
155 }
156 was->drvInst.dwCallback = dwCallback;
157 was->drvInst.dwInstance = dwInstance;
158 was->drvInst.fdwOpen = fdwOpen;
159 was->drvInst.fdwDriver = 0L;
160 was->drvInst.dwDriver = 0L;
161 was->drvInst.has = (HACMSTREAM)was;
162
163 if (had) {
164 if (!(wad = MSACM_GetDriver(had))) {
165 ret = MMSYSERR_INVALPARAM;
166 goto errCleanUp;
167 }
168
169 was->obj.pACMDriverID = wad->obj.pACMDriverID;
170 was->pDrv = wad;
171
172 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
173 if (ret != MMSYSERR_NOERROR)
174 goto errCleanUp;
175 } else {
176 PWINE_ACMDRIVERID wadi;
177
178 ret = ACMERR_NOTPOSSIBLE;
179 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) {
180 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
181 if (ret == MMSYSERR_NOERROR) {
182 if ((wad = MSACM_GetDriver(had)) != 0) {
183 was->obj.pACMDriverID = wad->obj.pACMDriverID;
184 was->pDrv = wad;
185
186 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
187 /* FIXME: when shall the acmDriver be Close():d ? */
188 if (ret == MMSYSERR_NOERROR)
189 break;
190 }
191 /* no match, close this acm driver and try next one */
192 acmDriverClose(had, 0L);
193 }
194 }
195 if (ret != MMSYSERR_NOERROR) {
196 ret = ACMERR_NOTPOSSIBLE;
197 goto errCleanUp;
198 }
199 }
200 if (phas)
201 *phas = (HACMSTREAM)was;
202 dprintf(("=> (%d)\n", ret));
203 ret = MMSYSERR_NOERROR;
204 if (!(fdwOpen & ACM_STREAMOPENF_QUERY))
205 return ret;
206errCleanUp:
207 HeapFree(MSACM_hHeap, 0, was);
208 dprintf(("=> (%d)\n", ret));
209 return ret;
210}
211
212
213/***********************************************************************
214 * acmStreamPrepareHeader (MSACM32.41)
215 */
216MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
217 DWORD fdwPrepare)
218{
219 PWINE_ACMSTREAM was;
220 MMRESULT ret = MMSYSERR_NOERROR;
221 PACMDRVSTREAMHEADER padsh;
222
223 dprintf(("(0x%08x, %p, %ld)\n", has, pash, fdwPrepare));
224
225 if ((was = ACM_GetStream(has)) == NULL)
226 return MMSYSERR_INVALHANDLE;
227 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
228 return MMSYSERR_INVALPARAM;
229 if (fdwPrepare)
230 ret = MMSYSERR_INVALFLAG;
231
232 if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
233 return MMSYSERR_NOERROR;
234
235 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
236 * size. some fields are private to msacm internals, and are exposed
237 * in ACMSTREAMHEADER in the dwReservedDriver array
238 */
239 padsh = (PACMDRVSTREAMHEADER)pash;
240
241 padsh->fdwConvert = fdwPrepare;
242 padsh->padshNext = NULL;
243 padsh->fdwDriver = padsh->dwDriver = 0L;
244
245 padsh->fdwPrepared = 0;
246 padsh->dwPrepared = 0;
247 padsh->pbPreparedSrc = 0;
248 padsh->cbPreparedSrcLength = 0;
249 padsh->pbPreparedDst = 0;
250 padsh->cbPreparedDstLength = 0;
251
252 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_PREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
253 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
254 ret = MMSYSERR_NOERROR;
255 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
256 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
257 padsh->fdwPrepared = padsh->fdwStatus;
258 padsh->dwPrepared = 0;
259 padsh->pbPreparedSrc = padsh->pbSrc;
260 padsh->cbPreparedSrcLength = padsh->cbSrcLength;
261 padsh->pbPreparedDst = padsh->pbDst;
262 padsh->cbPreparedDstLength = padsh->cbDstLength;
263 } else {
264 padsh->fdwPrepared = 0;
265 padsh->dwPrepared = 0;
266 padsh->pbPreparedSrc = 0;
267 padsh->cbPreparedSrcLength = 0;
268 padsh->pbPreparedDst = 0;
269 padsh->cbPreparedDstLength = 0;
270 }
271 dprintf(("=> (%d)\n", ret));
272 return ret;
273}
274
275/***********************************************************************
276 * acmStreamReset (MSACM32.42)
277 */
278MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
279{
280 PWINE_ACMSTREAM was;
281 MMRESULT ret = MMSYSERR_NOERROR;
282
283 dprintf(("(0x%08x, %ld)\n", has, fdwReset));
284
285 if (fdwReset) {
286 ret = MMSYSERR_INVALFLAG;
287 } else if ((was = ACM_GetStream(has)) == NULL) {
288 return MMSYSERR_INVALHANDLE;
289 } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
290 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_RESET, (DWORD)&was->drvInst, 0);
291 }
292 dprintf(("=> (%d)\n", ret));
293 return ret;
294}
295
296/***********************************************************************
297 * acmStreamSize (MSACM32.43)
298 */
299MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
300 LPDWORD pdwOutputBytes, DWORD fdwSize)
301{
302 PWINE_ACMSTREAM was;
303 ACMDRVSTREAMSIZE adss;
304 MMRESULT ret;
305
306 dprintf(("(0x%08x, %ld, %p, %ld)\n", has, cbInput, pdwOutputBytes, fdwSize));
307
308 if ((was = ACM_GetStream(has)) == NULL) {
309 return MMSYSERR_INVALHANDLE;
310 }
311 if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
312 return MMSYSERR_INVALFLAG;
313 }
314
315 *pdwOutputBytes = 0L;
316
317 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
318 case ACM_STREAMSIZEF_DESTINATION:
319 adss.cbDstLength = cbInput;
320 adss.cbSrcLength = 0;
321 break;
322 case ACM_STREAMSIZEF_SOURCE:
323 adss.cbSrcLength = cbInput;
324 adss.cbDstLength = 0;
325 break;
326 default:
327 return MMSYSERR_INVALFLAG;
328 }
329
330 adss.cbStruct = sizeof(adss);
331 adss.fdwSize = fdwSize;
332 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_SIZE,
333 (DWORD)&was->drvInst, (DWORD)&adss);
334 if (ret == MMSYSERR_NOERROR) {
335 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
336 case ACM_STREAMSIZEF_DESTINATION:
337 *pdwOutputBytes = adss.cbSrcLength;
338 break;
339 case ACM_STREAMSIZEF_SOURCE:
340 *pdwOutputBytes = adss.cbDstLength;
341 break;
342 }
343 }
344 dprintf(("=> (%d) [%lu]\n", ret, *pdwOutputBytes));
345 return ret;
346}
347
348/***********************************************************************
349 * acmStreamUnprepareHeader (MSACM32.44)
350 */
351MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
352 DWORD fdwUnprepare)
353{
354 PWINE_ACMSTREAM was;
355 MMRESULT ret = MMSYSERR_NOERROR;
356 PACMDRVSTREAMHEADER padsh;
357
358 dprintf(("(0x%08x, %p, %ld)\n", has, pash, fdwUnprepare));
359
360 if ((was = ACM_GetStream(has)) == NULL)
361 return MMSYSERR_INVALHANDLE;
362 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
363 return MMSYSERR_INVALPARAM;
364
365 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
366 return ACMERR_UNPREPARED;
367
368 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
369 * size. some fields are private to msacm internals, and are exposed
370 * in ACMSTREAMHEADER in the dwReservedDriver array
371 */
372 padsh = (PACMDRVSTREAMHEADER)pash;
373
374 /* check that pointers have not been modified */
375 if (padsh->pbPreparedSrc != padsh->pbSrc ||
376 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
377 padsh->pbPreparedDst != padsh->pbDst ||
378 padsh->cbPreparedDstLength < padsh->cbDstLength) {
379 return MMSYSERR_INVALPARAM;
380 }
381
382 padsh->fdwConvert = fdwUnprepare;
383
384 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_UNPREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
385 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
386 ret = MMSYSERR_NOERROR;
387 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
388 }
389 dprintf(("=> (%d)\n", ret));
390 return ret;
391}
Note: See TracBrowser for help on using the repository browser.