Implement ResetDC and PHYSICALOFFSET[X|Y] devcaps.
[wine] / dlls / msacm / imaadp32 / imaadp32.c
1 /*
2  * imaadp32.drv - IMA4 codec driver
3  *
4  * Copyright 2001 Hidenori Takeshima
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *
21  * FIXME - no encoding.
22  */
23
24 #include "config.h"
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winnls.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
32 #include "msacm.h"
33 #include "../msacmdrv.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(imaadp32);
38
39 /***********************************************************************/
40
41 enum CodecType
42 {
43         CodecType_Invalid,
44         CodecType_EncIMAADPCM,
45         CodecType_DecIMAADPCM,
46 };
47
48 typedef struct CodecImpl
49 {
50         int     dummy;
51 } CodecImpl;
52
53 /***********************************************************************/
54
55
56 static const int ima_step[88+1] =
57 {
58         /* from Y.Ajima's WAVFMT.TXT */
59             7,     8,     9,    10,    11,    12,    13,    14,
60            16,    17,    19,    21,    23,    25,    28,    31,
61            34,    37,    41,    45,    50,    55,    60,    66,
62            73,    80,    88,    97,   107,   118,   130,   143,
63           157,   173,   190,   209,   230,   253,   279,   307,
64           337,   371,   408,   449,   494,   544,   598,   658,
65           724,   796,   876,   963,  1060,  1166,  1282,  1411,
66          1552,  1707,  1878,  2066,  2272,  2499,  2749,  3024,
67          3327,  3660,  4026,  4428,  4871,  5358,  5894,  6484,
68          7132,  7845,  8630,  9493, 10442, 11487, 12635, 13899,
69         15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
70 };
71
72 static const int ima_indexupdate[8*2] =
73 {
74         /* from Y.Ajima's WAVFMT.TXT */
75         -1,-1,-1,-1, 2, 4, 6, 8,
76         -1,-1,-1,-1, 2, 4, 6, 8,
77 };
78
79 static int stepindex_to_diff( int stepindex, int input )
80 {
81         /* from Y.Ajima's WAVFMT.TXT */
82         int absdiff;
83
84         absdiff = (ima_step[stepindex]*((input&0x7)*2+1)) >> 3;
85         return (input&0x8) ? (-absdiff) : absdiff;
86 }
87
88 static int update_stepindex( int oldindex, int input )
89 {
90         int     index;
91
92         index = oldindex + ima_indexupdate[input];
93         return (index < 0) ? 0 : (index > 88) ? 88 : index;
94 }
95
96 static void decode_ima_block( int channels, int samplesperblock, SHORT* pDst, BYTE* pSrc )
97 {
98         int     samp[2];
99         int     stepindex[2];
100         int     inputs[8];
101         int     n,k,diff;
102
103         for ( n = 0; n < channels; n++ )
104         {
105                 samp[n] = *(SHORT*)pSrc; pSrc += sizeof(SHORT);
106                 stepindex[n] = *pSrc; pSrc += sizeof(SHORT);
107                 *pDst++ = samp[n];
108         }
109         samplesperblock --;
110
111         while ( samplesperblock >= 8 )
112         {
113                 for ( n = 0; n < channels; n++ )
114                 {
115                         for ( k = 0; k < 4; k++ )
116                         {
117                                 inputs[k*2+0] = (*pSrc) & 0xf;
118                                 inputs[k*2+1] = (*pSrc) >> 4;
119                                 pSrc ++;
120                         }
121                         for ( k = 0; k < 8; k++ )
122                         {
123                                 diff = stepindex_to_diff( stepindex[n], inputs[k] );
124                                 stepindex[n] = update_stepindex( stepindex[n], inputs[k] );
125                                 diff += samp[n];
126                                 if ( diff < -32768 ) diff = -32768;
127                                 if ( diff >  32767 ) diff =  32767;
128                                 samp[n] = diff;
129                                 pDst[k*channels+n] = samp[n];
130                         }
131                 }
132
133                 pDst += channels*8;
134                 samplesperblock -= 8;
135         }
136 }
137
138 static LONG IMAADPCM32_Decode( int channels, int blockalign, int samplesperblock, BYTE* pbDst, DWORD cbDstLength, DWORD* pcbDstLengthUsed, BYTE* pbSrc, DWORD cbSrcLength, DWORD* pcbSrcLengthUsed )
139 {
140         DWORD   cbDstLengthUsed = 0;
141         DWORD   cbSrcLengthUsed = 0;
142         int     dstblocksize;
143
144         dstblocksize = samplesperblock*channels*sizeof(SHORT);
145         while ( cbDstLength >= dstblocksize && cbSrcLength >= blockalign )
146         {
147                 decode_ima_block( channels, samplesperblock, (SHORT*)pbDst, pbSrc );
148                 pbDst += dstblocksize;
149                 cbDstLength -= dstblocksize;
150                 cbDstLengthUsed += dstblocksize;
151                 pbSrc += blockalign;
152                 cbSrcLength -= blockalign;
153                 cbSrcLengthUsed += blockalign;
154         }
155
156         *pcbSrcLengthUsed = cbSrcLengthUsed;
157         *pcbDstLengthUsed = cbDstLengthUsed;
158
159         return MMSYSERR_NOERROR;
160 }
161
162
163 /***********************************************************************/
164
165 static LONG Codec_DrvQueryConfigure( CodecImpl* This )
166 {
167         return MMSYSERR_NOTSUPPORTED;
168 }
169
170 static LONG Codec_DrvConfigure( CodecImpl* This, HWND hwnd, DRVCONFIGINFO* pinfo )
171 {
172         return MMSYSERR_NOTSUPPORTED;
173 }
174
175 static LONG Codec_DriverDetails( ACMDRIVERDETAILSW* pDrvDetails )
176 {
177         if ( pDrvDetails->cbStruct < sizeof(ACMDRIVERDETAILSW) )
178                 return MMSYSERR_INVALPARAM;
179
180         ZeroMemory( pDrvDetails, sizeof(ACMDRIVERDETAILSW) );
181         pDrvDetails->cbStruct = sizeof(ACMDRIVERDETAILSW);
182
183         pDrvDetails->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
184         pDrvDetails->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
185         pDrvDetails->wMid = 0xff;       /* FIXME? */
186         pDrvDetails->wPid = 0x00;       /* FIXME? */
187         pDrvDetails->vdwACM = 0x01000000;       /* FIXME? */
188         pDrvDetails->vdwDriver = 0x01000000;    /* FIXME? */
189         pDrvDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
190         pDrvDetails->cFormatTags = 2;
191         pDrvDetails->cFilterTags = 0;
192         pDrvDetails->hicon = (HICON)NULL;
193         MultiByteToWideChar( CP_ACP, 0, "WineIMA", -1,
194                 pDrvDetails->szShortName,
195                 sizeof(pDrvDetails->szShortName)/sizeof(WCHAR) );
196         MultiByteToWideChar( CP_ACP, 0, "Wine IMA codec", -1,
197                 pDrvDetails->szLongName,
198                 sizeof(pDrvDetails->szLongName)/sizeof(WCHAR) );
199     MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
200                 pDrvDetails->szCopyright,
201                 sizeof(pDrvDetails->szCopyright)/sizeof(WCHAR) );
202         MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
203                 pDrvDetails->szLicensing,
204                 sizeof(pDrvDetails->szLicensing)/sizeof(WCHAR) );
205         pDrvDetails->szFeatures[0] = 0;
206
207         return MMSYSERR_NOERROR;
208 }
209
210 static LONG Codec_QueryAbout( void )
211 {
212         return MMSYSERR_NOTSUPPORTED;
213 }
214
215 static LONG Codec_About( HWND hwnd )
216 {
217         return MMSYSERR_NOTSUPPORTED;
218 }
219
220 /***********************************************************************/
221
222 static LONG Codec_FormatTagDetails( CodecImpl* This, ACMFORMATTAGDETAILSW* pFmtTagDetails, DWORD dwFlags )
223 {
224         FIXME( "enumerate tags\n" );
225
226         switch ( dwFlags )
227         {
228         case ACM_FORMATTAGDETAILSF_INDEX:
229                 switch ( pFmtTagDetails->dwFormatTagIndex )
230                 {
231                 case 0:
232                         pFmtTagDetails->dwFormatTag = 0x11;     /* IMA ADPCM */
233                         break;
234                 case 1:
235                         pFmtTagDetails->dwFormatTag = 1;        /* PCM */
236                         break;
237                 default:
238                         return ACMERR_NOTPOSSIBLE;
239                 }
240                 break;
241         case ACM_FORMATTAGDETAILSF_FORMATTAG:
242                 switch ( pFmtTagDetails->dwFormatTag )
243                 {
244                 case 0x11:      /* IMA ADPCM */
245                         pFmtTagDetails->dwFormatTagIndex = 0;
246                         break;
247                 case 1: /* PCM */
248                         pFmtTagDetails->dwFormatTagIndex = 1;
249                         break;
250                 default:
251                         return ACMERR_NOTPOSSIBLE;
252                 }
253                 break;
254         case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
255                 if ( pFmtTagDetails->dwFormatTag != 0 &&
256                          pFmtTagDetails->dwFormatTag != 1 &&
257                          pFmtTagDetails->dwFormatTag != 0x11 )
258                         return ACMERR_NOTPOSSIBLE;
259                 pFmtTagDetails->dwFormatTagIndex = 0;
260                 break;
261         default:
262                 return MMSYSERR_NOTSUPPORTED;
263         }
264
265         pFmtTagDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
266         pFmtTagDetails->cbFormatSize = sizeof(WAVEFORMATEX);
267         pFmtTagDetails->cStandardFormats = 2;   /* FIXME */
268         pFmtTagDetails->szFormatTag[0] = 0;     /* FIXME */
269
270         return MMSYSERR_NOERROR;
271 }
272
273 static LONG Codec_FormatDetails( CodecImpl* This, ACMFORMATDETAILSW* pFmtDetails, DWORD dwFlags )
274 {
275         FIXME( "enumerate standard formats\n" );
276
277         if ( pFmtDetails->cbStruct < sizeof(ACMFORMATDETAILSW) )
278                 return MMSYSERR_INVALPARAM;
279         pFmtDetails->cbStruct = sizeof(ACMFORMATDETAILSW);
280
281         switch ( dwFlags )
282         {
283         case ACM_FORMATDETAILSF_INDEX:
284                 switch ( pFmtDetails->dwFormatIndex )
285                 {
286                 case 0:
287                         pFmtDetails->dwFormatTag = 0x11;        /* IMA ADPCM */
288                         break;
289                 case 1:
290                         pFmtDetails->dwFormatTag = 1;   /* PCM */
291                         break;
292                 default:
293                         return MMSYSERR_INVALPARAM;
294                 }
295                 break;
296         case ACM_FORMATDETAILSF_FORMAT:
297                 switch ( pFmtDetails->dwFormatTag )
298                 {
299                 case 0x11:      /* IMA ADPCM */
300                         pFmtDetails->dwFormatIndex = 0;
301                         break;
302                 case 1: /* PCM */
303                         pFmtDetails->dwFormatIndex = 1;
304                         break;
305                 default:
306                         return ACMERR_NOTPOSSIBLE;
307                 }
308                 break;
309         default:
310                 return MMSYSERR_NOTSUPPORTED;
311         }
312
313         pFmtDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
314         pFmtDetails->pwfx->wFormatTag = pFmtDetails->dwFormatTag;
315         pFmtDetails->pwfx->nChannels = 1;
316         pFmtDetails->pwfx->nSamplesPerSec = 11025;
317         pFmtDetails->pwfx->wBitsPerSample = 4;
318         if ( pFmtDetails->dwFormatTag == 1 )
319         {
320                 pFmtDetails->cbwfx = sizeof(PCMWAVEFORMAT);
321         }
322         else
323         {
324                 pFmtDetails->pwfx->cbSize = sizeof(WORD);
325                 pFmtDetails->cbwfx = sizeof(WAVEFORMATEX) + sizeof(WORD);
326         }
327         pFmtDetails->szFormat[0] = 0;   /* FIXME */
328
329     return MMSYSERR_NOERROR;
330 }
331
332
333 static LONG Codec_FormatSuggest( CodecImpl* This, ACMDRVFORMATSUGGEST* pFmtSuggest )
334 {
335         DWORD   fdwSuggest;
336
337         FIXME( "get suggested format\n" );
338
339         if ( pFmtSuggest->cbStruct != sizeof(ACMDRVFORMATSUGGEST) )
340                 return MMSYSERR_INVALPARAM;
341
342         if ( pFmtSuggest->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
343                  pFmtSuggest->cbwfxDst < sizeof(PCMWAVEFORMAT) )
344                 return MMSYSERR_INVALPARAM;
345
346         fdwSuggest = pFmtSuggest->fdwSuggest;
347
348         if ( fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS )
349         {
350                 if ( pFmtSuggest->pwfxSrc->nChannels != pFmtSuggest->pwfxDst->nChannels )
351                         return ACMERR_NOTPOSSIBLE;
352                 fdwSuggest &= ~ACM_FORMATSUGGESTF_NCHANNELS;
353         }
354
355         if ( fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC )
356         {
357                 if ( pFmtSuggest->pwfxSrc->nSamplesPerSec != pFmtSuggest->pwfxDst->nSamplesPerSec )
358                         return ACMERR_NOTPOSSIBLE;
359                 fdwSuggest &= ~ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
360         }
361
362         if ( pFmtSuggest->pwfxSrc->wFormatTag == 1 )
363         {
364                 /* Compressor */
365                 if ( pFmtSuggest->cbwfxDst < (sizeof(WAVEFORMATEX)+sizeof(WORD)) )
366                         return MMSYSERR_INVALPARAM;
367                 if ( pFmtSuggest->pwfxSrc->wBitsPerSample != 16 )
368                         return ACMERR_NOTPOSSIBLE;
369
370                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG )
371                 {
372                         if ( pFmtSuggest->pwfxDst->wFormatTag != 0x11 )
373                                 return ACMERR_NOTPOSSIBLE;
374                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
375                 }
376
377                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE )
378                 {
379                         if ( pFmtSuggest->pwfxDst->wBitsPerSample != 4 )
380                                 return ACMERR_NOTPOSSIBLE;
381                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
382                 }
383
384                 if ( fdwSuggest != 0 )
385                         return MMSYSERR_INVALFLAG;
386
387                 if ( !(fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) )
388                         pFmtSuggest->pwfxDst->wFormatTag = 0x11;
389                 pFmtSuggest->pwfxDst->nChannels = pFmtSuggest->pwfxSrc->nChannels;
390                 pFmtSuggest->pwfxDst->nSamplesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec;
391                 pFmtSuggest->pwfxDst->nAvgBytesPerSec = 0; /* FIXME */
392                 pFmtSuggest->pwfxDst->nBlockAlign = 0; /* FIXME */
393                 pFmtSuggest->pwfxDst->wBitsPerSample = 4;
394                 pFmtSuggest->pwfxDst->cbSize = 2;
395
396                 FIXME( "no compressor" );
397                 return ACMERR_NOTPOSSIBLE;
398         }
399         else
400         {
401                 /* Decompressor */
402                 if ( pFmtSuggest->cbwfxSrc < (sizeof(WAVEFORMATEX)+sizeof(WORD)) )
403                         return MMSYSERR_INVALPARAM;
404                 if ( pFmtSuggest->pwfxSrc->wFormatTag != 0x11 )
405                         return ACMERR_NOTPOSSIBLE;
406                 if ( pFmtSuggest->pwfxSrc->wBitsPerSample != 4 )
407                         return ACMERR_NOTPOSSIBLE;
408
409                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG )
410                 {
411                         if ( pFmtSuggest->pwfxDst->wFormatTag != 1 )
412                                 return ACMERR_NOTPOSSIBLE;
413                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
414                 }
415
416                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE )
417                 {
418                         if ( pFmtSuggest->pwfxDst->wBitsPerSample != 16 )
419                                 return ACMERR_NOTPOSSIBLE;
420                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
421                 }
422
423                 if ( fdwSuggest != 0 )
424                         return MMSYSERR_INVALFLAG;
425
426                 pFmtSuggest->pwfxDst->wFormatTag = 1;
427                 pFmtSuggest->pwfxDst->nChannels = pFmtSuggest->pwfxSrc->nChannels;
428                 pFmtSuggest->pwfxDst->nSamplesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec;
429                 pFmtSuggest->pwfxDst->nAvgBytesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec * pFmtSuggest->pwfxSrc->nChannels * 2;
430                 pFmtSuggest->pwfxDst->nBlockAlign = pFmtSuggest->pwfxSrc->nChannels * 2;
431                 pFmtSuggest->pwfxDst->wBitsPerSample = 16;
432         }
433
434         return MMSYSERR_NOERROR;
435 }
436
437 static LONG Codec_FilterTagDetails( CodecImpl* This, ACMFILTERTAGDETAILSW* pFilterTagDetails, DWORD dwFlags )
438 {
439         /* This is a codec driver. */
440         return MMSYSERR_NOTSUPPORTED;
441 }
442
443 static LONG Codec_FilterDetails( CodecImpl* This, ACMFILTERDETAILSW* pFilterDetails, DWORD dwFlags )
444 {
445         /* This is a codec driver. */
446         return MMSYSERR_NOTSUPPORTED;
447 }
448
449 static LONG Codec_StreamOpen( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst )
450 {
451         enum CodecType  codectype = CodecType_Invalid;
452
453         if ( pStreamInst->cbStruct != sizeof(ACMDRVSTREAMINSTANCE) )
454         {
455                 TRACE("invalid size of struct\n");
456                 return MMSYSERR_INVALPARAM;
457         }
458
459         if ( pStreamInst->fdwOpen & (~(ACM_STREAMOPENF_ASYNC|ACM_STREAMOPENF_NONREALTIME|ACM_STREAMOPENF_QUERY|CALLBACK_EVENT|CALLBACK_FUNCTION|CALLBACK_WINDOW)) )
460         {
461                 TRACE("unknown flags\n");
462                 return MMSYSERR_INVALFLAG;
463         }
464
465         /* No support for async operations. */
466         if ( pStreamInst->fdwOpen & ACM_STREAMOPENF_ASYNC )
467                 return MMSYSERR_INVALFLAG;
468
469         /* This is a codec driver. */
470         if ( pStreamInst->pwfxSrc->nChannels != pStreamInst->pwfxDst->nChannels || pStreamInst->pwfxSrc->nSamplesPerSec != pStreamInst->pwfxDst->nSamplesPerSec )
471                 return ACMERR_NOTPOSSIBLE;
472         if ( pStreamInst->pwfltr != NULL )
473                 return ACMERR_NOTPOSSIBLE;
474
475         if ( pStreamInst->pwfxSrc->wFormatTag == 1 )
476         {
477                 if ( pStreamInst->pwfxSrc->wBitsPerSample != 16 )
478                         return ACMERR_NOTPOSSIBLE;
479                 if ( pStreamInst->pwfxDst->wBitsPerSample != 4 )
480                         return ACMERR_NOTPOSSIBLE;
481
482                 /* Queried as a compressor */
483                 FIXME( "Compressor is not implemented now\n" );
484                 return ACMERR_NOTPOSSIBLE;
485         }
486         else
487         if ( pStreamInst->pwfxDst->wFormatTag == 1 )
488         {
489                 if ( pStreamInst->pwfxDst->wBitsPerSample != 16 )
490                         return ACMERR_NOTPOSSIBLE;
491                 if ( pStreamInst->pwfxSrc->wBitsPerSample != 4 )
492                         return ACMERR_NOTPOSSIBLE;
493
494                 switch ( pStreamInst->pwfxSrc->wFormatTag )
495                 {
496                 case 0x11: /* IMA ADPCM */
497                         TRACE( "IMG ADPCM deompressor\n" );
498                         codectype = CodecType_DecIMAADPCM;
499                         break;
500                 default:
501                         return ACMERR_NOTPOSSIBLE;
502                 }
503         }
504         else
505         {
506                 return ACMERR_NOTPOSSIBLE;
507         }
508
509         if ( pStreamInst->fdwOpen & ACM_STREAMOPENF_QUERY )
510                 return MMSYSERR_NOERROR;
511
512         pStreamInst->dwDriver = (DWORD)codectype;
513
514         return MMSYSERR_NOERROR;
515 }
516
517 static LONG Codec_StreamClose( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst )
518 {
519         return MMSYSERR_NOERROR;
520 }
521
522 static LONG Codec_StreamSize( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMSIZE* pStreamSize )
523 {
524         enum CodecType  codectype;
525         LONG    res;
526
527         if ( pStreamSize->cbStruct != sizeof(ACMDRVSTREAMSIZE) )
528                 return MMSYSERR_INVALPARAM;
529
530         codectype = (enum CodecType)pStreamInst->dwDriver;
531
532         res = MMSYSERR_NOERROR;
533         FIXME("()\n");
534         switch ( codectype )
535         {
536         case CodecType_EncIMAADPCM:
537                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_SOURCE )
538                         pStreamSize->cbDstLength = 64 + (pStreamSize->cbSrcLength >> 2);
539                 else
540                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_DESTINATION )
541                         pStreamSize->cbSrcLength = pStreamSize->cbDstLength << 2;
542                 else
543                         res = MMSYSERR_INVALFLAG;
544                 break;
545         case CodecType_DecIMAADPCM:
546                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_SOURCE )
547                         pStreamSize->cbDstLength = pStreamSize->cbSrcLength << 2;
548                 else
549                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_DESTINATION )
550                         pStreamSize->cbSrcLength = 64 + (pStreamSize->cbDstLength >> 2);
551                 else
552                         res = MMSYSERR_INVALFLAG;
553                 break;
554         default:
555                 ERR( "CodecType_Invalid\n" );
556                 res = MMSYSERR_NOTSUPPORTED;
557                 break;
558         }
559
560         return res;
561 }
562
563 static LONG Codec_StreamConvert( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
564 {
565         enum CodecType  codectype;
566         LONG    res;
567
568         codectype = (enum CodecType)pStreamInst->dwDriver;
569
570         res = MMSYSERR_NOTSUPPORTED;
571         switch ( codectype )
572         {
573         case CodecType_EncIMAADPCM:
574                 FIXME( "CodecType_EncIMAADPCM\n" );
575                 break;
576         case CodecType_DecIMAADPCM:
577                 TRACE( "CodecType_DecIMAADPCM\n" );
578                 res = IMAADPCM32_Decode( pStreamInst->pwfxSrc->nChannels, pStreamInst->pwfxSrc->nBlockAlign, *(WORD*)(((BYTE*)pStreamInst->pwfxSrc) + sizeof(WAVEFORMATEX)), pStreamHdr->pbDst, pStreamHdr->cbDstLength, &pStreamHdr->cbDstLengthUsed, pStreamHdr->pbSrc, pStreamHdr->cbSrcLength, &pStreamHdr->cbSrcLengthUsed );
579                 break;
580         default:
581                 ERR( "CodecType_Invalid\n" );
582                 break;
583         }
584
585         return res;
586 }
587
588 static LONG Codec_StreamReset( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, DWORD dwFlags )
589 {
590         return MMSYSERR_NOTSUPPORTED;
591 }
592
593 static LONG Codec_StreamPrepare( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
594 {
595         return MMSYSERR_NOTSUPPORTED;
596 }
597
598 static LONG Codec_StreamUnprepare( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
599 {
600         return MMSYSERR_NOTSUPPORTED;
601 }
602
603
604
605 /***********************************************************************/
606
607 static CodecImpl* Codec_AllocDriver( void )
608 {
609         CodecImpl*      This;
610
611         This = HeapAlloc( GetProcessHeap(), 0, sizeof(CodecImpl) );
612         if ( This == NULL )
613                 return NULL;
614         ZeroMemory( This, sizeof(CodecImpl) );
615
616         /* initialize members. */
617
618         return This;
619 }
620
621 static void Codec_Close( CodecImpl* This )
622 {
623
624         HeapFree( GetProcessHeap(), 0, This );
625 }
626
627
628
629 /***********************************************************************/
630
631 LONG WINAPI IMAADP32_DriverProc(
632         DWORD dwDriverId, HDRVR hdrvr, UINT msg, LONG lParam1, LONG lParam2 )
633 {
634         TRACE( "DriverProc(%08lx,%08x,%08x,%08lx,%08lx)\n",
635                          dwDriverId, hdrvr, msg, lParam1, lParam2 );
636
637         switch ( msg )
638         {
639         case DRV_LOAD:
640                 TRACE("DRV_LOAD\n");
641                 return TRUE;
642         case DRV_FREE:
643                 TRACE("DRV_FREE\n");
644                 return TRUE;
645         case DRV_OPEN:
646                 TRACE("DRV_OPEN\n");
647                 return (LONG)Codec_AllocDriver();
648         case DRV_CLOSE:
649                 TRACE("DRV_CLOSE\n");
650                 Codec_Close( (CodecImpl*)dwDriverId );
651                 return TRUE;
652         case DRV_ENABLE:
653                 TRACE("DRV_ENABLE\n");
654                 return TRUE;
655         case DRV_DISABLE:
656                 TRACE("DRV_DISABLE\n");
657                 return TRUE;
658         case DRV_QUERYCONFIGURE:
659                 TRACE("DRV_QUERYCONFIGURE\n");
660                 return Codec_DrvQueryConfigure( (CodecImpl*)dwDriverId );
661         case DRV_CONFIGURE:
662                 TRACE("DRV_CONFIGURE\n");
663                 return Codec_DrvConfigure( (CodecImpl*)dwDriverId,
664                                         (HWND)lParam1, (DRVCONFIGINFO*)lParam2 );
665         case DRV_INSTALL:
666                 TRACE("DRV_INSTALL\n");
667                 return DRVCNF_OK;
668         case DRV_REMOVE:
669                 TRACE("DRV_REMOVE\n");
670                 return 0;
671         case DRV_POWER:
672                 TRACE("DRV_POWER\n");
673                 return TRUE;
674
675         case ACMDM_DRIVER_NOTIFY:
676                 return MMSYSERR_NOERROR;
677         case ACMDM_DRIVER_DETAILS:
678                 return Codec_DriverDetails((ACMDRIVERDETAILSW*)lParam1);
679         case ACMDM_DRIVER_ABOUT:
680                 TRACE("ACMDM_DRIVER_ABOUT\n");
681                 return (lParam1 == -1) ? Codec_QueryAbout() : Codec_About( (HWND)lParam1 );
682
683         case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
684                 return MMSYSERR_NOTSUPPORTED;
685         case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
686                 return MMSYSERR_NOTSUPPORTED;
687
688         case ACMDM_FORMATTAG_DETAILS:
689                 return Codec_FormatTagDetails( (CodecImpl*)dwDriverId, (ACMFORMATTAGDETAILSW*)lParam1, (DWORD)lParam2 );
690         case ACMDM_FORMAT_DETAILS:
691                 return Codec_FormatDetails( (CodecImpl*)dwDriverId, (ACMFORMATDETAILSW*)lParam1, (DWORD)lParam2 );
692         case ACMDM_FORMAT_SUGGEST:
693                 return Codec_FormatSuggest( (CodecImpl*)dwDriverId, (ACMDRVFORMATSUGGEST*)lParam1 );
694
695         case ACMDM_FILTERTAG_DETAILS:
696                 return Codec_FilterTagDetails( (CodecImpl*)dwDriverId, (ACMFILTERTAGDETAILSW*)lParam1, (DWORD)lParam2 );
697         case ACMDM_FILTER_DETAILS:
698                 return Codec_FilterDetails( (CodecImpl*)dwDriverId, (ACMFILTERDETAILSW*)lParam1, (DWORD)lParam2 );
699
700         case ACMDM_STREAM_OPEN:
701                 return Codec_StreamOpen( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1 );
702         case ACMDM_STREAM_CLOSE:
703                 return Codec_StreamClose( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1 );
704         case ACMDM_STREAM_SIZE:
705                 return Codec_StreamSize( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMSIZE*)lParam2 );
706         case ACMDM_STREAM_CONVERT:
707                 return Codec_StreamConvert( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
708         case ACMDM_STREAM_RESET:
709                 return Codec_StreamReset( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (DWORD)lParam2 );
710         case ACMDM_STREAM_PREPARE:
711                 return Codec_StreamPrepare( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
712         case ACMDM_STREAM_UNPREPARE:
713                 return Codec_StreamUnprepare( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
714
715         }
716
717         return DefDriverProc( dwDriverId, hdrvr, msg, lParam1, lParam2 );
718 }
719
720 /***********************************************************************/
721
722 BOOL WINAPI IMAADP32_DllMain( HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved )
723 {
724         TRACE( "(%08x,%08lx,%p)\n",hInst,dwReason,lpvReserved );
725
726         return TRUE;
727 }