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

Last change on this file since 3785 was 2103, checked in by sandervl, 26 years ago

JW's update (wine 991212)

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