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