Implement ResetDC and PHYSICALOFFSET[X|Y] devcaps.
[wine] / dlls / msacm / msg711 / msg711.c
1 /*
2  * msg711.drv - G711 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(msg711);
38
39
40 /***********************************************************************/
41
42 enum CodecType
43 {
44         CodecType_Invalid,
45         CodecType_EncMuLaw,
46         CodecType_EncALaw,
47         CodecType_DecMuLaw,
48         CodecType_DecALaw,
49 };
50
51 typedef struct CodecImpl
52 {
53         int     dummy;
54 } CodecImpl;
55
56 /***********************************************************************/
57
58 static const WORD dec_mulaw[256] =
59 {
60         0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84,
61         0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
62         0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84,
63         0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
64         0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804,
65         0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
66         0xF0C4, 0xF144, 0xF1C4, 0xF244, 0xF2C4, 0xF344, 0xF3C4, 0xF444,
67         0xF4C4, 0xF544, 0xF5C4, 0xF644, 0xF6C4, 0xF744, 0xF7C4, 0xF844,
68         0xF8A4, 0xF8E4, 0xF924, 0xF964, 0xF9A4, 0xF9E4, 0xFA24, 0xFA64,
69         0xFAA4, 0xFAE4, 0xFB24, 0xFB64, 0xFBA4, 0xFBE4, 0xFC24, 0xFC64,
70         0xFC94, 0xFCB4, 0xFCD4, 0xFCF4, 0xFD14, 0xFD34, 0xFD54, 0xFD74,
71         0xFD94, 0xFDB4, 0xFDD4, 0xFDF4, 0xFE14, 0xFE34, 0xFE54, 0xFE74,
72         0xFE8C, 0xFE9C, 0xFEAC, 0xFEBC, 0xFECC, 0xFEDC, 0xFEEC, 0xFEFC,
73         0xFF0C, 0xFF1C, 0xFF2C, 0xFF3C, 0xFF4C, 0xFF5C, 0xFF6C, 0xFF7C,
74         0xFF88, 0xFF90, 0xFF98, 0xFFA0, 0xFFA8, 0xFFB0, 0xFFB8, 0xFFC0,
75         0xFFC8, 0xFFD0, 0xFFD8, 0xFFE0, 0xFFE8, 0xFFF0, 0xFFF8, 0x0000,
76         0x7D7C, 0x797C, 0x757C, 0x717C, 0x6D7C, 0x697C, 0x657C, 0x617C,
77         0x5D7C, 0x597C, 0x557C, 0x517C, 0x4D7C, 0x497C, 0x457C, 0x417C,
78         0x3E7C, 0x3C7C, 0x3A7C, 0x387C, 0x367C, 0x347C, 0x327C, 0x307C,
79         0x2E7C, 0x2C7C, 0x2A7C, 0x287C, 0x267C, 0x247C, 0x227C, 0x207C,
80         0x1EFC, 0x1DFC, 0x1CFC, 0x1BFC, 0x1AFC, 0x19FC, 0x18FC, 0x17FC,
81         0x16FC, 0x15FC, 0x14FC, 0x13FC, 0x12FC, 0x11FC, 0x10FC, 0x0FFC,
82         0x0F3C, 0x0EBC, 0x0E3C, 0x0DBC, 0x0D3C, 0x0CBC, 0x0C3C, 0x0BBC,
83         0x0B3C, 0x0ABC, 0x0A3C, 0x09BC, 0x093C, 0x08BC, 0x083C, 0x07BC,
84         0x075C, 0x071C, 0x06DC, 0x069C, 0x065C, 0x061C, 0x05DC, 0x059C,
85         0x055C, 0x051C, 0x04DC, 0x049C, 0x045C, 0x041C, 0x03DC, 0x039C,
86         0x036C, 0x034C, 0x032C, 0x030C, 0x02EC, 0x02CC, 0x02AC, 0x028C,
87         0x026C, 0x024C, 0x022C, 0x020C, 0x01EC, 0x01CC, 0x01AC, 0x018C,
88         0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
89         0x00F4, 0x00E4, 0x00D4, 0x00C4, 0x00B4, 0x00A4, 0x0094, 0x0084,
90         0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
91         0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
92 };
93
94 static const WORD dec_alaw[256] =
95 {
96         0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80,
97         0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
98         0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0,
99         0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
100         0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600,
101         0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
102         0xD500, 0xD700, 0xD100, 0xD300, 0xDD00, 0xDF00, 0xD900, 0xDB00,
103         0xC500, 0xC700, 0xC100, 0xC300, 0xCD00, 0xCF00, 0xC900, 0xCB00,
104         0xFEA8, 0xFEB8, 0xFE88, 0xFE98, 0xFEE8, 0xFEF8, 0xFEC8, 0xFED8,
105         0xFE28, 0xFE38, 0xFE08, 0xFE18, 0xFE68, 0xFE78, 0xFE48, 0xFE58,
106         0xFFA8, 0xFFB8, 0xFF88, 0xFF98, 0xFFE8, 0xFFF8, 0xFFC8, 0xFFD8,
107         0xFF28, 0xFF38, 0xFF08, 0xFF18, 0xFF68, 0xFF78, 0xFF48, 0xFF58,
108         0xFAA0, 0xFAE0, 0xFA20, 0xFA60, 0xFBA0, 0xFBE0, 0xFB20, 0xFB60,
109         0xF8A0, 0xF8E0, 0xF820, 0xF860, 0xF9A0, 0xF9E0, 0xF920, 0xF960,
110         0xFD50, 0xFD70, 0xFD10, 0xFD30, 0xFDD0, 0xFDF0, 0xFD90, 0xFDB0,
111         0xFC50, 0xFC70, 0xFC10, 0xFC30, 0xFCD0, 0xFCF0, 0xFC90, 0xFCB0,
112         0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
113         0x1D80, 0x1C80, 0x1F80, 0x1E80, 0x1980, 0x1880, 0x1B80, 0x1A80,
114         0x0AC0, 0x0A40, 0x0BC0, 0x0B40, 0x08C0, 0x0840, 0x09C0, 0x0940,
115         0x0EC0, 0x0E40, 0x0FC0, 0x0F40, 0x0CC0, 0x0C40, 0x0DC0, 0x0D40,
116         0x5600, 0x5200, 0x5E00, 0x5A00, 0x4600, 0x4200, 0x4E00, 0x4A00,
117         0x7600, 0x7200, 0x7E00, 0x7A00, 0x6600, 0x6200, 0x6E00, 0x6A00,
118         0x2B00, 0x2900, 0x2F00, 0x2D00, 0x2300, 0x2100, 0x2700, 0x2500,
119         0x3B00, 0x3900, 0x3F00, 0x3D00, 0x3300, 0x3100, 0x3700, 0x3500,
120         0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
121         0x01D8, 0x01C8, 0x01F8, 0x01E8, 0x0198, 0x0188, 0x01B8, 0x01A8,
122         0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
123         0x00D8, 0x00C8, 0x00F8, 0x00E8, 0x0098, 0x0088, 0x00B8, 0x00A8,
124         0x0560, 0x0520, 0x05E0, 0x05A0, 0x0460, 0x0420, 0x04E0, 0x04A0,
125         0x0760, 0x0720, 0x07E0, 0x07A0, 0x0660, 0x0620, 0x06E0, 0x06A0,
126         0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250,
127         0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350,
128 };
129
130 static LONG MSG711_Decode( const WORD* pdec, BYTE* pbDst, DWORD cbDstLength, DWORD* pcbDstLengthUsed, BYTE* pbSrc, DWORD cbSrcLength, DWORD* pcbSrcLengthUsed )
131 {
132         DWORD   cSample;
133         WORD    w;
134
135         cSample = cbSrcLength;
136         if ( cSample > (cbDstLength>>1) )
137                 cSample = (cbDstLength>>1);
138
139         *pcbSrcLengthUsed = cSample;
140         *pcbDstLengthUsed = cSample << 1;
141
142         while ( cSample-- > 0 )
143         {
144                 w = pdec[*pbSrc++];
145                 *pbDst++ = LOBYTE(w);
146                 *pbDst++ = HIBYTE(w);
147         }
148
149         return MMSYSERR_NOERROR;
150 }
151
152
153 /***********************************************************************/
154
155 static LONG Codec_DrvQueryConfigure( CodecImpl* This )
156 {
157         return MMSYSERR_NOTSUPPORTED;
158 }
159
160 static LONG Codec_DrvConfigure( CodecImpl* This, HWND hwnd, DRVCONFIGINFO* pinfo )
161 {
162         return MMSYSERR_NOTSUPPORTED;
163 }
164
165 static LONG Codec_DriverDetails( ACMDRIVERDETAILSW* pDrvDetails )
166 {
167         if ( pDrvDetails->cbStruct < sizeof(ACMDRIVERDETAILSW) )
168                 return MMSYSERR_INVALPARAM;
169
170         ZeroMemory( pDrvDetails, sizeof(ACMDRIVERDETAILSW) );
171         pDrvDetails->cbStruct = sizeof(ACMDRIVERDETAILSW);
172
173         pDrvDetails->fccType = ACMDRIVERDETAILS_FCCTYPE_AUDIOCODEC;
174         pDrvDetails->fccComp = ACMDRIVERDETAILS_FCCCOMP_UNDEFINED;
175         pDrvDetails->wMid = 0xff;       /* FIXME? */
176         pDrvDetails->wPid = 0x00;       /* FIXME? */
177         pDrvDetails->vdwACM = 0x01000000;       /* FIXME? */
178         pDrvDetails->vdwDriver = 0x01000000;    /* FIXME? */
179         pDrvDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
180         pDrvDetails->cFormatTags = 3;
181         pDrvDetails->cFilterTags = 0;
182         pDrvDetails->hicon = (HICON)NULL;
183         MultiByteToWideChar( CP_ACP, 0, "WineG711", -1,
184                 pDrvDetails->szShortName,
185                 sizeof(pDrvDetails->szShortName)/sizeof(WCHAR) );
186         MultiByteToWideChar( CP_ACP, 0, "Wine G711 codec", -1,
187                 pDrvDetails->szLongName,
188                 sizeof(pDrvDetails->szLongName)/sizeof(WCHAR) );
189     MultiByteToWideChar( CP_ACP, 0, "Brought to you by the Wine team...", -1,
190                 pDrvDetails->szCopyright,
191                 sizeof(pDrvDetails->szCopyright)/sizeof(WCHAR) );
192         MultiByteToWideChar( CP_ACP, 0, "Refer to LICENSE file", -1,
193                 pDrvDetails->szLicensing,
194                 sizeof(pDrvDetails->szLicensing)/sizeof(WCHAR) );
195         pDrvDetails->szFeatures[0] = 0;
196
197         return MMSYSERR_NOERROR;
198 }
199
200 static LONG Codec_QueryAbout( void )
201 {
202         return MMSYSERR_NOTSUPPORTED;
203 }
204
205 static LONG Codec_About( HWND hwnd )
206 {
207         return MMSYSERR_NOTSUPPORTED;
208 }
209
210 /***********************************************************************/
211
212 static LONG Codec_FormatTagDetails( CodecImpl* This, ACMFORMATTAGDETAILSW* pFmtTagDetails, DWORD dwFlags )
213 {
214         FIXME( "enumerate tags\n" );
215
216         switch ( dwFlags )
217         {
218         case ACM_FORMATTAGDETAILSF_INDEX:
219                 switch ( pFmtTagDetails->dwFormatTagIndex )
220                 {
221                 case 0:
222                         pFmtTagDetails->dwFormatTag = 7;        /* Mu-Law */
223                         break;
224                 case 1:
225                         pFmtTagDetails->dwFormatTag = 6;        /* A-Law */
226                         break;
227                 case 2:
228                         pFmtTagDetails->dwFormatTag = 1;        /* PCM */
229                         break;
230                 default:
231                         return ACMERR_NOTPOSSIBLE;
232                 }
233                 break;
234         case ACM_FORMATTAGDETAILSF_FORMATTAG:
235                 switch ( pFmtTagDetails->dwFormatTag )
236                 {
237                 case 7: /* Mu-Law */
238                         pFmtTagDetails->dwFormatTagIndex = 0;
239                         break;
240                 case 6: /* A-Law */
241                         pFmtTagDetails->dwFormatTagIndex = 1;
242                         break;
243                 case 1: /* PCM */
244                         pFmtTagDetails->dwFormatTagIndex = 2;
245                         break;
246                 default:
247                         return ACMERR_NOTPOSSIBLE;
248                 }
249                 break;
250         case ACM_FORMATTAGDETAILSF_LARGESTSIZE:
251                 if ( pFmtTagDetails->dwFormatTag != 0 &&
252                          pFmtTagDetails->dwFormatTag != 1 &&
253                          pFmtTagDetails->dwFormatTag != 6 &&
254                          pFmtTagDetails->dwFormatTag != 7 )
255                         return ACMERR_NOTPOSSIBLE;
256                 pFmtTagDetails->dwFormatTagIndex = 0;
257                 break;
258         default:
259                 return MMSYSERR_NOTSUPPORTED;
260         }
261
262         pFmtTagDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
263         pFmtTagDetails->cbFormatSize = sizeof(WAVEFORMATEX);
264         pFmtTagDetails->cStandardFormats = 3;   /* FIXME */
265         pFmtTagDetails->szFormatTag[0] = 0;     /* FIXME */
266
267         return MMSYSERR_NOERROR;
268 }
269
270 static LONG Codec_FormatDetails( CodecImpl* This, ACMFORMATDETAILSW* pFmtDetails, DWORD dwFlags )
271 {
272         FIXME( "enumerate standard formats\n" );
273
274         if ( pFmtDetails->cbStruct < sizeof(ACMFORMATDETAILSW) )
275                 return MMSYSERR_INVALPARAM;
276         pFmtDetails->cbStruct = sizeof(ACMFORMATDETAILSW);
277
278         switch ( dwFlags )
279         {
280         case ACM_FORMATDETAILSF_INDEX:
281                 switch ( pFmtDetails->dwFormatIndex )
282                 {
283                 case 0:
284                         pFmtDetails->dwFormatTag = 7;   /* Mu-Law */
285                         break;
286                 case 1:
287                         pFmtDetails->dwFormatTag = 6;   /* A-Law */
288                         break;
289                 case 2:
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 7: /* Mu-Law */
300                         pFmtDetails->dwFormatIndex = 0;
301                         break;
302                 case 6: /* A-Law */
303                         pFmtDetails->dwFormatIndex = 1;
304                         break;
305                 case 1: /* PCM */
306                         pFmtDetails->dwFormatIndex = 2;
307                         break;
308                 default:
309                         return ACMERR_NOTPOSSIBLE;
310                 }
311                 break;
312         default:
313                 return MMSYSERR_NOTSUPPORTED;
314         }
315
316         pFmtDetails->fdwSupport = ACMDRIVERDETAILS_SUPPORTF_CODEC;
317         pFmtDetails->pwfx->wFormatTag = pFmtDetails->dwFormatTag;
318         pFmtDetails->pwfx->nChannels = 1;
319         pFmtDetails->pwfx->nSamplesPerSec = 8000;
320         pFmtDetails->pwfx->wBitsPerSample = 8;
321         if ( pFmtDetails->dwFormatTag == 1 )
322         {
323                 pFmtDetails->cbwfx = sizeof(PCMWAVEFORMAT);
324         }
325         else
326         {
327                 pFmtDetails->pwfx->cbSize = 0;
328                 pFmtDetails->cbwfx = sizeof(WAVEFORMATEX);
329         }
330         pFmtDetails->szFormat[0] = 0;   /* FIXME */
331
332     return MMSYSERR_NOERROR;
333 }
334
335
336 static LONG Codec_FormatSuggest( CodecImpl* This, ACMDRVFORMATSUGGEST* pFmtSuggest )
337 {
338         DWORD   fdwSuggest;
339
340         FIXME( "get suggested format\n" );
341
342         if ( pFmtSuggest->cbStruct != sizeof(ACMDRVFORMATSUGGEST) )
343                 return MMSYSERR_INVALPARAM;
344
345         if ( pFmtSuggest->cbwfxSrc < sizeof(PCMWAVEFORMAT) ||
346                  pFmtSuggest->cbwfxDst < sizeof(PCMWAVEFORMAT) )
347                 return MMSYSERR_INVALPARAM;
348
349         fdwSuggest = pFmtSuggest->fdwSuggest;
350
351         if ( fdwSuggest & ACM_FORMATSUGGESTF_NCHANNELS )
352         {
353                 if ( pFmtSuggest->pwfxSrc->nChannels != pFmtSuggest->pwfxDst->nChannels )
354                         return ACMERR_NOTPOSSIBLE;
355                 fdwSuggest &= ~ACM_FORMATSUGGESTF_NCHANNELS;
356         }
357
358         if ( fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC )
359         {
360                 if ( pFmtSuggest->pwfxSrc->nSamplesPerSec != pFmtSuggest->pwfxDst->nSamplesPerSec )
361                         return ACMERR_NOTPOSSIBLE;
362                 fdwSuggest &= ~ACM_FORMATSUGGESTF_NSAMPLESPERSEC;
363         }
364
365         if ( pFmtSuggest->pwfxSrc->wFormatTag == 1 )
366         {
367                 /* Compressor */
368                 if ( pFmtSuggest->cbwfxDst < sizeof(WAVEFORMATEX) )
369                         return MMSYSERR_INVALPARAM;
370                 if ( pFmtSuggest->pwfxSrc->wBitsPerSample != 16 )
371                         return ACMERR_NOTPOSSIBLE;
372
373                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG )
374                 {
375                         if ( pFmtSuggest->pwfxDst->wFormatTag != 6 &&
376                                  pFmtSuggest->pwfxDst->wFormatTag != 7 )
377                                 return ACMERR_NOTPOSSIBLE;
378                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
379                 }
380
381                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE )
382                 {
383                         if ( pFmtSuggest->pwfxDst->wBitsPerSample != 8 )
384                                 return ACMERR_NOTPOSSIBLE;
385                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
386                 }
387
388                 if ( fdwSuggest != 0 )
389                         return MMSYSERR_INVALFLAG;
390
391                 if ( !(fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG) )
392                         pFmtSuggest->pwfxDst->wFormatTag = 7;
393                 pFmtSuggest->pwfxDst->nChannels = pFmtSuggest->pwfxSrc->nChannels;
394                 pFmtSuggest->pwfxDst->nSamplesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec;
395                 pFmtSuggest->pwfxDst->nAvgBytesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec * pFmtSuggest->pwfxSrc->nChannels;
396                 pFmtSuggest->pwfxDst->nBlockAlign = pFmtSuggest->pwfxSrc->nChannels;
397                 pFmtSuggest->pwfxDst->wBitsPerSample = 8;
398                 pFmtSuggest->pwfxDst->cbSize = 0;
399
400                 FIXME( "no compressor" );
401                 return ACMERR_NOTPOSSIBLE;
402         }
403         else
404         {
405                 /* Decompressor */
406                 if ( pFmtSuggest->cbwfxSrc < sizeof(WAVEFORMATEX) )
407                         return MMSYSERR_INVALPARAM;
408                 if ( pFmtSuggest->pwfxSrc->wFormatTag != 6 &&
409                          pFmtSuggest->pwfxSrc->wFormatTag != 7 )
410                         return ACMERR_NOTPOSSIBLE;
411                 if ( pFmtSuggest->pwfxSrc->wBitsPerSample != 8 )
412                         return ACMERR_NOTPOSSIBLE;
413
414                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG )
415                 {
416                         if ( pFmtSuggest->pwfxDst->wFormatTag != 1 )
417                                 return ACMERR_NOTPOSSIBLE;
418                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
419                 }
420
421                 if ( fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE )
422                 {
423                         if ( pFmtSuggest->pwfxDst->wBitsPerSample != 16 )
424                                 return ACMERR_NOTPOSSIBLE;
425                         fdwSuggest &= ~ACM_FORMATSUGGESTF_WFORMATTAG;
426                 }
427
428                 if ( fdwSuggest != 0 )
429                         return MMSYSERR_INVALFLAG;
430
431                 pFmtSuggest->pwfxDst->wFormatTag = 1;
432                 pFmtSuggest->pwfxDst->nChannels = pFmtSuggest->pwfxSrc->nChannels;
433                 pFmtSuggest->pwfxDst->nSamplesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec;
434                 pFmtSuggest->pwfxDst->nAvgBytesPerSec = pFmtSuggest->pwfxSrc->nSamplesPerSec * pFmtSuggest->pwfxSrc->nChannels * 2;
435                 pFmtSuggest->pwfxDst->nBlockAlign = pFmtSuggest->pwfxSrc->nChannels * 2;
436                 pFmtSuggest->pwfxDst->wBitsPerSample = 16;
437         }
438
439         return MMSYSERR_NOERROR;
440 }
441
442 static LONG Codec_FilterTagDetails( CodecImpl* This, ACMFILTERTAGDETAILSW* pFilterTagDetails, DWORD dwFlags )
443 {
444         /* This is a codec driver. */
445         return MMSYSERR_NOTSUPPORTED;
446 }
447
448 static LONG Codec_FilterDetails( CodecImpl* This, ACMFILTERDETAILSW* pFilterDetails, DWORD dwFlags )
449 {
450         /* This is a codec driver. */
451         return MMSYSERR_NOTSUPPORTED;
452 }
453
454 static LONG Codec_StreamOpen( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst )
455 {
456         enum CodecType  codectype = CodecType_Invalid;
457
458         if ( pStreamInst->cbStruct != sizeof(ACMDRVSTREAMINSTANCE) )
459         {
460                 TRACE("invalid size of struct\n");
461                 return MMSYSERR_INVALPARAM;
462         }
463
464         if ( pStreamInst->fdwOpen & (~(ACM_STREAMOPENF_ASYNC|ACM_STREAMOPENF_NONREALTIME|ACM_STREAMOPENF_QUERY|CALLBACK_EVENT|CALLBACK_FUNCTION|CALLBACK_WINDOW)) )
465         {
466                 TRACE("unknown flags\n");
467                 return MMSYSERR_INVALFLAG;
468         }
469
470         /* No support for async operations. */
471         if ( pStreamInst->fdwOpen & ACM_STREAMOPENF_ASYNC )
472                 return MMSYSERR_INVALFLAG;
473
474         /* This is a codec driver. */
475         if ( pStreamInst->pwfxSrc->nChannels != pStreamInst->pwfxDst->nChannels || pStreamInst->pwfxSrc->nSamplesPerSec != pStreamInst->pwfxDst->nSamplesPerSec )
476                 return ACMERR_NOTPOSSIBLE;
477         if ( pStreamInst->pwfltr != NULL )
478                 return ACMERR_NOTPOSSIBLE;
479
480         if ( pStreamInst->pwfxSrc->wFormatTag == 1 )
481         {
482                 if ( pStreamInst->pwfxSrc->wBitsPerSample != 16 )
483                         return ACMERR_NOTPOSSIBLE;
484                 if ( pStreamInst->pwfxDst->wBitsPerSample != 8 )
485                         return ACMERR_NOTPOSSIBLE;
486
487                 /* Queried as a compressor */
488                 FIXME( "Compressor is not implemented now\n" );
489                 return ACMERR_NOTPOSSIBLE;
490         }
491         else
492         if ( pStreamInst->pwfxDst->wFormatTag == 1 )
493         {
494                 if ( pStreamInst->pwfxDst->wBitsPerSample != 16 )
495                         return ACMERR_NOTPOSSIBLE;
496                 if ( pStreamInst->pwfxSrc->wBitsPerSample != 8 )
497                         return ACMERR_NOTPOSSIBLE;
498
499                 switch ( pStreamInst->pwfxSrc->wFormatTag )
500                 {
501                 case 6: /* A-Law */
502                         TRACE( "A-Law deompressor\n" );
503                         codectype = CodecType_DecALaw;
504                         break;
505                 case 7: /* Mu-Law */
506                         TRACE( "Mu-Law deompressor\n" );
507                         codectype = CodecType_DecMuLaw;
508                         break;
509                 default:
510                         return ACMERR_NOTPOSSIBLE;
511                 }
512         }
513         else
514         {
515                 return ACMERR_NOTPOSSIBLE;
516         }
517
518         if ( pStreamInst->fdwOpen & ACM_STREAMOPENF_QUERY )
519                 return MMSYSERR_NOERROR;
520
521         pStreamInst->dwDriver = (DWORD)codectype;
522
523         return MMSYSERR_NOERROR;
524 }
525
526 static LONG Codec_StreamClose( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst )
527 {
528         return MMSYSERR_NOERROR;
529 }
530
531 static LONG Codec_StreamSize( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMSIZE* pStreamSize )
532 {
533         enum CodecType  codectype;
534         LONG    res;
535
536         if ( pStreamSize->cbStruct != sizeof(ACMDRVSTREAMSIZE) )
537                 return MMSYSERR_INVALPARAM;
538
539         codectype = (enum CodecType)pStreamInst->dwDriver;
540
541         res = MMSYSERR_NOERROR;
542         switch ( codectype )
543         {
544         case CodecType_EncMuLaw:
545         case CodecType_EncALaw:
546                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_SOURCE )
547                         pStreamSize->cbDstLength = pStreamSize->cbSrcLength >> 1;
548                 else
549                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_DESTINATION )
550                         pStreamSize->cbSrcLength = pStreamSize->cbDstLength << 1;
551                 else
552                         res = MMSYSERR_INVALFLAG;
553                 break;
554         case CodecType_DecMuLaw:
555         case CodecType_DecALaw:
556                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_SOURCE )
557                         pStreamSize->cbDstLength = pStreamSize->cbSrcLength << 1;
558                 else
559                 if ( pStreamSize->fdwSize == ACM_STREAMSIZEF_DESTINATION )
560                         pStreamSize->cbSrcLength = pStreamSize->cbDstLength >> 1;
561                 else
562                         res = MMSYSERR_INVALFLAG;
563                 break;
564         default:
565                 ERR( "CodecType_Invalid\n" );
566                 res = MMSYSERR_NOTSUPPORTED;
567                 break;
568         }
569
570         return res;
571 }
572
573 static LONG Codec_StreamConvert( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
574 {
575         enum CodecType  codectype;
576         LONG    res;
577
578         codectype = (enum CodecType)pStreamInst->dwDriver;
579
580         res = MMSYSERR_NOTSUPPORTED;
581         switch ( codectype )
582         {
583         case CodecType_EncMuLaw:
584                 FIXME( "CodecType_EncMuLaw\n" );
585                 break;
586         case CodecType_EncALaw:
587                 FIXME( "CodecType_EncALaw\n" );
588                 break;
589         case CodecType_DecMuLaw:
590                 TRACE( "CodecType_DecMuLaw\n" );
591                 res = MSG711_Decode( dec_mulaw, pStreamHdr->pbDst, pStreamHdr->cbDstLength, &pStreamHdr->cbDstLengthUsed, pStreamHdr->pbSrc, pStreamHdr->cbSrcLength, &pStreamHdr->cbSrcLengthUsed );
592                 break;
593         case CodecType_DecALaw:
594                 TRACE( "CodecType_DecALaw\n" );
595                 res = MSG711_Decode( dec_alaw, pStreamHdr->pbDst, pStreamHdr->cbDstLength, &pStreamHdr->cbDstLengthUsed, pStreamHdr->pbSrc, pStreamHdr->cbSrcLength, &pStreamHdr->cbSrcLengthUsed );
596                 break;
597         default:
598                 ERR( "CodecType_Invalid\n" );
599                 break;
600         }
601
602         return res;
603 }
604
605 static LONG Codec_StreamReset( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, DWORD dwFlags )
606 {
607         return MMSYSERR_NOTSUPPORTED;
608 }
609
610 static LONG Codec_StreamPrepare( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
611 {
612         return MMSYSERR_NOTSUPPORTED;
613 }
614
615 static LONG Codec_StreamUnprepare( CodecImpl* This, ACMDRVSTREAMINSTANCE* pStreamInst, ACMDRVSTREAMHEADER* pStreamHdr )
616 {
617         return MMSYSERR_NOTSUPPORTED;
618 }
619
620
621
622 /***********************************************************************/
623
624 static CodecImpl* Codec_AllocDriver( void )
625 {
626         CodecImpl*      This;
627
628         This = HeapAlloc( GetProcessHeap(), 0, sizeof(CodecImpl) );
629         if ( This == NULL )
630                 return NULL;
631         ZeroMemory( This, sizeof(CodecImpl) );
632
633         /* initialize members. */
634
635         return This;
636 }
637
638 static void Codec_Close( CodecImpl* This )
639 {
640
641         HeapFree( GetProcessHeap(), 0, This );
642 }
643
644
645
646 /***********************************************************************/
647
648 LONG WINAPI MSG711_DriverProc(
649         DWORD dwDriverId, HDRVR hdrvr, UINT msg, LONG lParam1, LONG lParam2 )
650 {
651         TRACE( "DriverProc(%08lx,%08x,%08x,%08lx,%08lx)\n",
652                          dwDriverId, hdrvr, msg, lParam1, lParam2 );
653
654         switch ( msg )
655         {
656         case DRV_LOAD:
657                 TRACE("DRV_LOAD\n");
658                 return TRUE;
659         case DRV_FREE:
660                 TRACE("DRV_FREE\n");
661                 return TRUE;
662         case DRV_OPEN:
663                 TRACE("DRV_OPEN\n");
664                 return (LONG)Codec_AllocDriver();
665         case DRV_CLOSE:
666                 TRACE("DRV_CLOSE\n");
667                 Codec_Close( (CodecImpl*)dwDriverId );
668                 return TRUE;
669         case DRV_ENABLE:
670                 TRACE("DRV_ENABLE\n");
671                 return TRUE;
672         case DRV_DISABLE:
673                 TRACE("DRV_DISABLE\n");
674                 return TRUE;
675         case DRV_QUERYCONFIGURE:
676                 TRACE("DRV_QUERYCONFIGURE\n");
677                 return Codec_DrvQueryConfigure( (CodecImpl*)dwDriverId );
678         case DRV_CONFIGURE:
679                 TRACE("DRV_CONFIGURE\n");
680                 return Codec_DrvConfigure( (CodecImpl*)dwDriverId,
681                                         (HWND)lParam1, (DRVCONFIGINFO*)lParam2 );
682         case DRV_INSTALL:
683                 TRACE("DRV_INSTALL\n");
684                 return DRVCNF_OK;
685         case DRV_REMOVE:
686                 TRACE("DRV_REMOVE\n");
687                 return 0;
688         case DRV_POWER:
689                 TRACE("DRV_POWER\n");
690                 return TRUE;
691
692         case ACMDM_DRIVER_NOTIFY:
693                 return MMSYSERR_NOERROR;
694         case ACMDM_DRIVER_DETAILS:
695                 return Codec_DriverDetails((ACMDRIVERDETAILSW*)lParam1);
696         case ACMDM_DRIVER_ABOUT:
697                 TRACE("ACMDM_DRIVER_ABOUT\n");
698                 return (lParam1 == -1) ? Codec_QueryAbout() : Codec_About( (HWND)lParam1 );
699
700         case ACMDM_HARDWARE_WAVE_CAPS_INPUT:
701                 return MMSYSERR_NOTSUPPORTED;
702         case ACMDM_HARDWARE_WAVE_CAPS_OUTPUT:
703                 return MMSYSERR_NOTSUPPORTED;
704
705         case ACMDM_FORMATTAG_DETAILS:
706                 return Codec_FormatTagDetails( (CodecImpl*)dwDriverId, (ACMFORMATTAGDETAILSW*)lParam1, (DWORD)lParam2 );
707         case ACMDM_FORMAT_DETAILS:
708                 return Codec_FormatDetails( (CodecImpl*)dwDriverId, (ACMFORMATDETAILSW*)lParam1, (DWORD)lParam2 );
709         case ACMDM_FORMAT_SUGGEST:
710                 return Codec_FormatSuggest( (CodecImpl*)dwDriverId, (ACMDRVFORMATSUGGEST*)lParam1 );
711
712         case ACMDM_FILTERTAG_DETAILS:
713                 return Codec_FilterTagDetails( (CodecImpl*)dwDriverId, (ACMFILTERTAGDETAILSW*)lParam1, (DWORD)lParam2 );
714         case ACMDM_FILTER_DETAILS:
715                 return Codec_FilterDetails( (CodecImpl*)dwDriverId, (ACMFILTERDETAILSW*)lParam1, (DWORD)lParam2 );
716
717         case ACMDM_STREAM_OPEN:
718                 return Codec_StreamOpen( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1 );
719         case ACMDM_STREAM_CLOSE:
720                 return Codec_StreamClose( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1 );
721         case ACMDM_STREAM_SIZE:
722                 return Codec_StreamSize( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMSIZE*)lParam2 );
723         case ACMDM_STREAM_CONVERT:
724                 return Codec_StreamConvert( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
725         case ACMDM_STREAM_RESET:
726                 return Codec_StreamReset( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (DWORD)lParam2 );
727         case ACMDM_STREAM_PREPARE:
728                 return Codec_StreamPrepare( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
729         case ACMDM_STREAM_UNPREPARE:
730                 return Codec_StreamUnprepare( (CodecImpl*)dwDriverId, (ACMDRVSTREAMINSTANCE*)lParam1, (ACMDRVSTREAMHEADER*)lParam2 );
731
732         }
733
734         return DefDriverProc( dwDriverId, hdrvr, msg, lParam1, lParam2 );
735 }
736
737 /***********************************************************************/
738
739 BOOL WINAPI MSG711_DllMain( HINSTANCE hInst, DWORD dwReason, LPVOID lpvReserved )
740 {
741         TRACE( "(%08x,%08lx,%p)\n",hInst,dwReason,lpvReserved );
742
743         return TRUE;
744 }