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

Last change on this file since 5120 was 3925, checked in by bird, 25 years ago

Added the CVS keyword Id.

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