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