source: trunk/src/msacm32/stream.c@ 22010

Last change on this file since 22010 was 6712, checked in by sandervl, 24 years ago

restored old version

File size: 12.5 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 <string.h>
18#include "winbase.h"
19#include "winerror.h"
20#include "windef.h"
21#include "debugtools.h"
22#include "mmsystem.h"
23#include "msacm.h"
24#include "msacmdrv.h"
25#include "wineacm.h"
26
27DEFAULT_DEBUG_CHANNEL(msacm);
28
29static PWINE_ACMSTREAM ACM_GetStream(HACMSTREAM has)
30{
31 return (PWINE_ACMSTREAM)has;
32}
33
34/***********************************************************************
35 * acmStreamClose (MSACM32.37)
36 */
37MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
38{
39 PWINE_ACMSTREAM was;
40 MMRESULT ret;
41
42 TRACE("(0x%08x, %ld)\n", has, fdwClose);
43
44 if ((was = ACM_GetStream(has)) == NULL) {
45 return MMSYSERR_INVALHANDLE;
46 }
47 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_CLOSE, (DWORD)&was->drvInst, 0);
48 if (ret == MMSYSERR_NOERROR) {
49 if (was->hAcmDriver)
50 acmDriverClose(was->hAcmDriver, 0L);
51 HeapFree(MSACM_hHeap, 0, was);
52 }
53 TRACE("=> (%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 TRACE("(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 TRACE("=> (%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 FIXME("(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 TRACE("(%p, 0x%08x, %p, %p, %p, %ld, %ld, %ld)\n",
126 phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
127
128 TRACE("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 TRACE("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 if ((fdwOpen & ACM_STREAMOPENF_QUERY) && phas) return MMSYSERR_INVALPARAM;
137 if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) return MMSYSERR_INVALPARAM;
138
139 wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX);
140 if (pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) wfxSrcSize += pwfxSrc->cbSize;
141 if (pwfxDst->wFormatTag != WAVE_FORMAT_PCM) wfxDstSize += pwfxDst->cbSize;
142
143 was = HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0));
144 if (was == NULL)
145 return MMSYSERR_NOMEM;
146
147 was->drvInst.cbStruct = sizeof(was->drvInst);
148 was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
149 memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
150 was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
151 memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
152 if (pwfltr) {
153 was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
154 memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
155 } else {
156 was->drvInst.pwfltr = NULL;
157 }
158 was->drvInst.dwCallback = dwCallback;
159 was->drvInst.dwInstance = dwInstance;
160 was->drvInst.fdwOpen = fdwOpen;
161 was->drvInst.fdwDriver = 0L;
162 was->drvInst.dwDriver = 0L;
163 was->drvInst.has = (HACMSTREAM)was;
164
165 if (had) {
166 if (!(wad = MSACM_GetDriver(had))) {
167 ret = MMSYSERR_INVALPARAM;
168 goto errCleanUp;
169 }
170
171 was->obj.dwType = WINE_ACMOBJ_STREAM;
172 was->obj.pACMDriverID = wad->obj.pACMDriverID;
173 was->pDrv = wad;
174 was->hAcmDriver = 0; /* not to close it in acmStreamClose */
175
176 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
177 if (ret != MMSYSERR_NOERROR)
178 goto errCleanUp;
179 } else {
180 PWINE_ACMDRIVERID wadi;
181
182 ret = ACMERR_NOTPOSSIBLE;
183 for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) {
184 ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
185 if (ret == MMSYSERR_NOERROR) {
186 if ((wad = MSACM_GetDriver(had)) != 0) {
187 was->obj.dwType = WINE_ACMOBJ_STREAM;
188 was->obj.pACMDriverID = wad->obj.pACMDriverID;
189 was->pDrv = wad;
190 was->hAcmDriver = had;
191
192 ret = SendDriverMessage(wad->hDrvr, ACMDM_STREAM_OPEN, (DWORD)&was->drvInst, 0L);
193 if (ret == MMSYSERR_NOERROR) {
194 if (fdwOpen & ACM_STREAMOPENF_QUERY) {
195 acmDriverClose(had, 0L);
196 }
197 break;
198 }
199 }
200 /* no match, close this acm driver and try next one */
201 acmDriverClose(had, 0L);
202 }
203 }
204 if (ret != MMSYSERR_NOERROR) {
205 ret = ACMERR_NOTPOSSIBLE;
206 goto errCleanUp;
207 }
208 }
209 ret = MMSYSERR_NOERROR;
210 if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
211 if (phas)
212 *phas = (HACMSTREAM)was;
213 TRACE("=> (%d)\n", ret);
214 return ret;
215 }
216errCleanUp:
217 if (phas)
218 *phas = (HACMSTREAM)0;
219 HeapFree(MSACM_hHeap, 0, was);
220 TRACE("=> (%d)\n", ret);
221 return ret;
222}
223
224
225/***********************************************************************
226 * acmStreamPrepareHeader (MSACM32.41)
227 */
228MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
229 DWORD fdwPrepare)
230{
231 PWINE_ACMSTREAM was;
232 MMRESULT ret = MMSYSERR_NOERROR;
233 PACMDRVSTREAMHEADER padsh;
234
235 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwPrepare);
236
237 if ((was = ACM_GetStream(has)) == NULL)
238 return MMSYSERR_INVALHANDLE;
239 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
240 return MMSYSERR_INVALPARAM;
241 if (fdwPrepare)
242 ret = MMSYSERR_INVALFLAG;
243
244 if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
245 return MMSYSERR_NOERROR;
246
247 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
248 * size. some fields are private to msacm internals, and are exposed
249 * in ACMSTREAMHEADER in the dwReservedDriver array
250 */
251 padsh = (PACMDRVSTREAMHEADER)pash;
252
253 padsh->fdwConvert = fdwPrepare;
254 padsh->padshNext = NULL;
255 padsh->fdwDriver = padsh->dwDriver = 0L;
256
257 padsh->fdwPrepared = 0;
258 padsh->dwPrepared = 0;
259 padsh->pbPreparedSrc = 0;
260 padsh->cbPreparedSrcLength = 0;
261 padsh->pbPreparedDst = 0;
262 padsh->cbPreparedDstLength = 0;
263
264 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_PREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
265 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
266 ret = MMSYSERR_NOERROR;
267 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
268 padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
269 padsh->fdwPrepared = padsh->fdwStatus;
270 padsh->dwPrepared = 0;
271 padsh->pbPreparedSrc = padsh->pbSrc;
272 padsh->cbPreparedSrcLength = padsh->cbSrcLength;
273 padsh->pbPreparedDst = padsh->pbDst;
274 padsh->cbPreparedDstLength = padsh->cbDstLength;
275 } else {
276 padsh->fdwPrepared = 0;
277 padsh->dwPrepared = 0;
278 padsh->pbPreparedSrc = 0;
279 padsh->cbPreparedSrcLength = 0;
280 padsh->pbPreparedDst = 0;
281 padsh->cbPreparedDstLength = 0;
282 }
283 TRACE("=> (%d)\n", ret);
284 return ret;
285}
286
287/***********************************************************************
288 * acmStreamReset (MSACM32.42)
289 */
290MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
291{
292 PWINE_ACMSTREAM was;
293 MMRESULT ret = MMSYSERR_NOERROR;
294
295 TRACE("(0x%08x, %ld)\n", has, fdwReset);
296
297 if (fdwReset) {
298 ret = MMSYSERR_INVALFLAG;
299 } else if ((was = ACM_GetStream(has)) == NULL) {
300 return MMSYSERR_INVALHANDLE;
301 } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
302 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_RESET, (DWORD)&was->drvInst, 0);
303 }
304 TRACE("=> (%d)\n", ret);
305 return ret;
306}
307
308/***********************************************************************
309 * acmStreamSize (MSACM32.43)
310 */
311MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
312 LPDWORD pdwOutputBytes, DWORD fdwSize)
313{
314 PWINE_ACMSTREAM was;
315 ACMDRVSTREAMSIZE adss;
316 MMRESULT ret;
317
318 TRACE("(0x%08x, %ld, %p, %ld)\n", has, cbInput, pdwOutputBytes, fdwSize);
319
320 if ((was = ACM_GetStream(has)) == NULL) {
321 return MMSYSERR_INVALHANDLE;
322 }
323 if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
324 return MMSYSERR_INVALFLAG;
325 }
326
327 *pdwOutputBytes = 0L;
328
329 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
330 case ACM_STREAMSIZEF_DESTINATION:
331 adss.cbDstLength = cbInput;
332 adss.cbSrcLength = 0;
333 break;
334 case ACM_STREAMSIZEF_SOURCE:
335 adss.cbSrcLength = cbInput;
336 adss.cbDstLength = 0;
337 break;
338 default:
339 return MMSYSERR_INVALFLAG;
340 }
341
342 adss.cbStruct = sizeof(adss);
343 adss.fdwSize = fdwSize;
344 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_SIZE,
345 (DWORD)&was->drvInst, (DWORD)&adss);
346 if (ret == MMSYSERR_NOERROR) {
347 switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
348 case ACM_STREAMSIZEF_DESTINATION:
349 *pdwOutputBytes = adss.cbSrcLength;
350 break;
351 case ACM_STREAMSIZEF_SOURCE:
352 *pdwOutputBytes = adss.cbDstLength;
353 break;
354 }
355 }
356 TRACE("=> (%d) [%lu]\n", ret, *pdwOutputBytes);
357 return ret;
358}
359
360/***********************************************************************
361 * acmStreamUnprepareHeader (MSACM32.44)
362 */
363MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
364 DWORD fdwUnprepare)
365{
366 PWINE_ACMSTREAM was;
367 MMRESULT ret = MMSYSERR_NOERROR;
368 PACMDRVSTREAMHEADER padsh;
369
370 TRACE("(0x%08x, %p, %ld)\n", has, pash, fdwUnprepare);
371
372 if ((was = ACM_GetStream(has)) == NULL)
373 return MMSYSERR_INVALHANDLE;
374 if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER))
375 return MMSYSERR_INVALPARAM;
376
377 if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED))
378 return ACMERR_UNPREPARED;
379
380 /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
381 * size. some fields are private to msacm internals, and are exposed
382 * in ACMSTREAMHEADER in the dwReservedDriver array
383 */
384 padsh = (PACMDRVSTREAMHEADER)pash;
385
386 /* check that pointers have not been modified */
387 if (padsh->pbPreparedSrc != padsh->pbSrc ||
388 padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
389 padsh->pbPreparedDst != padsh->pbDst ||
390 padsh->cbPreparedDstLength < padsh->cbDstLength) {
391 return MMSYSERR_INVALPARAM;
392 }
393
394 padsh->fdwConvert = fdwUnprepare;
395
396 ret = SendDriverMessage(was->pDrv->hDrvr, ACMDM_STREAM_UNPREPARE, (DWORD)&was->drvInst, (DWORD)padsh);
397 if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
398 ret = MMSYSERR_NOERROR;
399 padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
400 }
401 TRACE("=> (%d)\n", ret);
402 return ret;
403}
Note: See TracBrowser for help on using the repository browser.