Updated.
[wine] / dlls / msacm / filter.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  *      MSACM32 library
5  *
6  *      Copyright 1998  Patrik Stridvall
7  */
8
9 #include <string.h>
10 #include "winbase.h"
11 #include "winnls.h"
12 #include "winerror.h"
13 #include "mmsystem.h"
14 #include "msacm.h"
15 #include "msacmdrv.h"
16 #include "wineacm.h"
17 #include "debugtools.h"
18
19 DEFAULT_DEBUG_CHANNEL(msacm);
20
21 /***********************************************************************
22  *           acmFilterChooseA (MSACM32.13)
23  */
24 MMRESULT WINAPI acmFilterChooseA(PACMFILTERCHOOSEA pafltrc)
25 {
26     FIXME("(%p): stub\n", pafltrc);
27     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
28     return MMSYSERR_ERROR;
29 }
30
31 /***********************************************************************
32  *           acmFilterChooseW (MSACM32.14)
33  */
34 MMRESULT WINAPI acmFilterChooseW(PACMFILTERCHOOSEW pafltrc)
35 {
36     FIXME("(%p): stub\n", pafltrc);
37     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
38     return MMSYSERR_ERROR;
39 }
40
41 /***********************************************************************
42  *           acmFilterDetailsA (MSACM32.15)
43  */
44 MMRESULT WINAPI acmFilterDetailsA(HACMDRIVER had, PACMFILTERDETAILSA pafd, 
45                                   DWORD fdwDetails)
46 {
47     ACMFILTERDETAILSW   afdw;
48     MMRESULT            mmr;
49
50     memset(&afdw, 0, sizeof(afdw));
51     afdw.cbStruct = sizeof(afdw);
52     afdw.dwFilterIndex = pafd->dwFilterIndex;
53     afdw.dwFilterTag = pafd->dwFilterTag; 
54     afdw.pwfltr = pafd->pwfltr;
55     afdw.cbwfltr = pafd->cbwfltr;
56
57     mmr = acmFilterDetailsW(had, &afdw, fdwDetails);
58     if (mmr == MMSYSERR_NOERROR) {
59         pafd->dwFilterTag = afdw.dwFilterTag; 
60         pafd->fdwSupport = afdw.fdwSupport; 
61         WideCharToMultiByte( CP_ACP, 0, afdw.szFilter, -1, pafd->szFilter,
62                              sizeof(pafd->szFilter), NULL, NULL );
63     }
64     return mmr;
65 }
66
67 /***********************************************************************
68  *           acmFilterDetailsW (MSACM32.16)
69  */
70 MMRESULT WINAPI acmFilterDetailsW(HACMDRIVER had, PACMFILTERDETAILSW pafd, 
71                                   DWORD fdwDetails)
72 {
73     MMRESULT                    mmr;
74     ACMFILTERTAGDETAILSA        aftd;
75
76     TRACE("(0x%08x, %p, %ld)\n", had, pafd, fdwDetails);
77
78     memset(&aftd, 0, sizeof(aftd));
79     aftd.cbStruct = sizeof(aftd);
80
81     if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
82         
83     switch (fdwDetails) {
84     case ACM_FILTERDETAILSF_FILTER:
85         if (pafd->dwFilterTag != pafd->pwfltr->dwFilterTag) {
86             mmr = MMSYSERR_INVALPARAM;
87             break;
88         }
89         if (had == (HACMDRIVER)NULL) {
90             PWINE_ACMDRIVERID           padid;
91
92             mmr = ACMERR_NOTPOSSIBLE;
93             for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
94                 /* should check for codec only */
95                 if (padid->bEnabled && 
96                     acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
97                     mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
98                                         (LPARAM)pafd, (LPARAM)fdwDetails);
99                     acmDriverClose(had, 0);
100                     if (mmr == MMSYSERR_NOERROR) break;
101                 }
102             }               
103         } else {
104             mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
105                                 (LPARAM)pafd, (LPARAM)fdwDetails);
106         }
107         break;
108     case ACM_FILTERDETAILSF_INDEX:
109         /* should check pafd->dwFilterIndex < aftd->cStandardFilters */
110         mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS,
111                             (LPARAM)pafd, (LPARAM)fdwDetails);
112         break;
113     default:
114         WARN("Unknown fdwDetails %08lx\n", fdwDetails);
115         mmr = MMSYSERR_INVALFLAG;
116         break;
117     }
118
119     TRACE("=> %d\n", mmr);
120     return mmr;
121 }
122
123 struct MSACM_FilterEnumWtoA_Instance {
124     PACMFILTERDETAILSA  pafda;
125     DWORD               dwInstance;
126     ACMFILTERENUMCBA    fnCallback;
127 };
128
129 static BOOL CALLBACK MSACM_FilterEnumCallbackWtoA(HACMDRIVERID hadid,
130                                                   PACMFILTERDETAILSW pafdw,  
131                                                   DWORD dwInstance,             
132                                                   DWORD fdwSupport)
133 {
134     struct MSACM_FilterEnumWtoA_Instance* pafei;
135
136     pafei = (struct MSACM_FilterEnumWtoA_Instance*)dwInstance;
137
138     pafei->pafda->dwFilterIndex = pafdw->dwFilterIndex; 
139     pafei->pafda->dwFilterTag = pafdw->dwFilterTag; 
140     pafei->pafda->fdwSupport = pafdw->fdwSupport; 
141     WideCharToMultiByte( CP_ACP, 0, pafdw->szFilter, -1, pafei->pafda->szFilter,
142                          sizeof(pafei->pafda->szFilter), NULL, NULL );
143
144     return (pafei->fnCallback)(hadid, pafei->pafda, 
145                                pafei->dwInstance, fdwSupport);
146 }
147
148 /***********************************************************************
149  *           acmFilterEnumA (MSACM32.17)
150  */
151 MMRESULT WINAPI acmFilterEnumA(HACMDRIVER had, PACMFILTERDETAILSA pafda, 
152                                ACMFILTERENUMCBA fnCallback, DWORD dwInstance, 
153                                DWORD fdwEnum)
154 {
155     ACMFILTERDETAILSW           afdw;
156     struct MSACM_FilterEnumWtoA_Instance afei;
157
158     memset(&afdw, 0, sizeof(afdw));
159     afdw.cbStruct = sizeof(afdw);
160     afdw.dwFilterIndex = pafda->dwFilterIndex;
161     afdw.dwFilterTag = pafda->dwFilterTag;
162     afdw.pwfltr = pafda->pwfltr;
163     afdw.cbwfltr = pafda->cbwfltr;
164
165     afei.pafda = pafda;
166     afei.dwInstance = dwInstance;
167     afei.fnCallback = fnCallback;
168
169     return acmFilterEnumW(had, &afdw, MSACM_FilterEnumCallbackWtoA, 
170                           (DWORD)&afei, fdwEnum);
171 }
172
173 static BOOL MSACM_FilterEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had, 
174                                    PACMFILTERDETAILSW pafd, 
175                                    ACMFILTERENUMCBW fnCallback, DWORD dwInstance,  
176                                    DWORD fdwEnum)
177 {
178     ACMDRIVERDETAILSW           add;
179     ACMFILTERTAGDETAILSW        aftd;
180     int                         i, j;
181
182     add.cbStruct = sizeof(add);
183     
184     if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) != MMSYSERR_NOERROR) return FALSE;
185
186     for (i = 0; i < add.cFilterTags; i++) {
187         memset(&aftd, 0, sizeof(aftd));
188         aftd.cbStruct = sizeof(aftd);
189         aftd.dwFilterTagIndex = i;
190         if (acmFilterTagDetailsW(had, &aftd, ACM_FILTERTAGDETAILSF_INDEX) != MMSYSERR_NOERROR)
191             continue;
192         
193         if ((fdwEnum & ACM_FILTERENUMF_DWFILTERTAG) && 
194             aftd.dwFilterTag != pafd->pwfltr->dwFilterTag)
195             continue;
196         
197         for (j = 0; j < aftd.cStandardFilters; j++) {
198             pafd->dwFilterIndex = j;
199             pafd->dwFilterTag = aftd.dwFilterTag;
200             if (acmFilterDetailsW(had, pafd, ACM_FILTERDETAILSF_INDEX) != MMSYSERR_NOERROR) 
201                 continue;
202             
203             if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, add.fdwSupport))
204                 return FALSE; 
205         }
206     }
207     return TRUE;
208 }
209
210 /***********************************************************************
211  *           acmFilterEnumW (MSACM32.18)
212  */
213 MMRESULT WINAPI acmFilterEnumW(HACMDRIVER had, PACMFILTERDETAILSW pafd, 
214                                ACMFILTERENUMCBW fnCallback, DWORD dwInstance, 
215                                DWORD fdwEnum)
216 {
217     PWINE_ACMDRIVERID           padid;
218     BOOL                        ret;
219
220     TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
221           had, pafd, fnCallback, dwInstance, fdwEnum);
222
223     if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
224
225     if (fdwEnum & ~(ACM_FILTERENUMF_DWFILTERTAG))
226         FIXME("Unsupported fdwEnum values\n");
227
228     if (had) {
229         HACMDRIVERID    hadid;
230
231         if (acmDriverID(had, &hadid, 0) != MMSYSERR_NOERROR)
232             return MMSYSERR_INVALHANDLE;
233         MSACM_FilterEnumHelper(MSACM_GetDriverID(hadid), had, pafd,
234                                fnCallback, dwInstance, fdwEnum);
235         return MMSYSERR_NOERROR;
236     }
237     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
238             /* should check for codec only */
239             if (!padid->bEnabled || acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != MMSYSERR_NOERROR)
240                 continue;
241             ret = MSACM_FilterEnumHelper(padid, had, pafd, 
242                                          fnCallback, dwInstance, fdwEnum);
243             acmDriverClose(had, 0);
244             if (!ret) break;
245     }
246     return MMSYSERR_NOERROR;
247 }
248
249 /***********************************************************************
250  *           acmFilterTagDetailsA (MSACM32.19)
251  */
252 MMRESULT WINAPI acmFilterTagDetailsA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda, 
253                                      DWORD fdwDetails)
254 {
255     ACMFILTERTAGDETAILSW        aftdw;
256     MMRESULT                    mmr;
257
258     memset(&aftdw, 0, sizeof(aftdw));
259     aftdw.cbStruct = sizeof(aftdw);
260     aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
261     aftdw.dwFilterTag = paftda->dwFilterTag;
262
263     mmr = acmFilterTagDetailsW(had, &aftdw, fdwDetails);
264     if (mmr == MMSYSERR_NOERROR) {
265         paftda->dwFilterTag = aftdw.dwFilterTag; 
266         paftda->dwFilterTagIndex = aftdw.dwFilterTagIndex;
267         paftda->cbFilterSize = aftdw.cbFilterSize; 
268         paftda->fdwSupport = aftdw.fdwSupport; 
269         paftda->cStandardFilters = aftdw.cStandardFilters; 
270         WideCharToMultiByte( CP_ACP, 0, aftdw.szFilterTag, -1, paftda->szFilterTag,
271                              sizeof(paftda->szFilterTag), NULL, NULL );
272     }
273     return mmr;
274 }
275
276 /***********************************************************************
277  *           acmFilterTagDetailsW (MSACM32.20)
278  */
279 MMRESULT WINAPI acmFilterTagDetailsW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd, 
280                                      DWORD fdwDetails)
281 {
282     PWINE_ACMDRIVERID   padid;
283     MMRESULT            mmr;
284
285     TRACE("(0x%08x, %p, %ld)\n", had, paftd, fdwDetails);
286
287     if (fdwDetails & ~(ACM_FILTERTAGDETAILSF_FILTERTAG|ACM_FILTERTAGDETAILSF_INDEX|
288                        ACM_FILTERTAGDETAILSF_LARGESTSIZE))
289         return MMSYSERR_INVALFLAG;
290
291     switch (fdwDetails) {
292     case ACM_FILTERTAGDETAILSF_FILTERTAG:
293         if (had == (HACMDRIVER)NULL) {
294             mmr = ACMERR_NOTPOSSIBLE;
295             for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
296                 /* should check for codec only */
297                 if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
298                     mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
299                                         (LPARAM)paftd, (LPARAM)fdwDetails);
300                     acmDriverClose(had, 0);
301                     if (mmr == MMSYSERR_NOERROR) break;
302                 }
303             }
304         } else {
305             mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
306                                 (LPARAM)paftd, (LPARAM)fdwDetails);
307         }
308         break;
309
310     case ACM_FILTERTAGDETAILSF_INDEX:
311         /* FIXME should check paftd->dwFilterTagIndex < add.cFilterTags */
312         mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
313                             (LPARAM)paftd, (LPARAM)fdwDetails);
314         break;
315
316     case ACM_FILTERTAGDETAILSF_LARGESTSIZE:
317         if (had == (HACMDRIVER)NULL) {
318             ACMFILTERTAGDETAILSW        tmp;
319             DWORD                       ft = paftd->dwFilterTag;
320
321             mmr = ACMERR_NOTPOSSIBLE;
322             for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
323                 /* should check for codec only */
324                 if (padid->bEnabled && 
325                     acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) {
326
327                     memset(&tmp, 0, sizeof(tmp));
328                     tmp.cbStruct = sizeof(tmp);
329                     tmp.dwFilterTag = ft;
330
331                     if (MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
332                                       (LPARAM)&tmp, 
333                                       (LPARAM)fdwDetails) == MMSYSERR_NOERROR) {
334                         if (mmr == ACMERR_NOTPOSSIBLE ||
335                             paftd->cbFilterSize < tmp.cbFilterSize) {
336                             *paftd = tmp;
337                             mmr = MMSYSERR_NOERROR;
338                         } 
339                     }
340                     acmDriverClose(had, 0);
341                 }
342             }
343         } else {
344             mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS,
345                                 (LPARAM)paftd, (LPARAM)fdwDetails);
346         }
347         break;
348
349     default:
350         WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
351         mmr = MMSYSERR_ERROR;
352     }
353
354     if (mmr == MMSYSERR_NOERROR && 
355         paftd->dwFilterTag == WAVE_FORMAT_PCM && paftd->szFilterTag[0] == 0)
356         MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFilterTag,
357                              sizeof(paftd->szFilterTag)/sizeof(WCHAR) );
358
359     return mmr;
360 }
361
362 struct MSACM_FilterTagEnumWtoA_Instance {
363     PACMFILTERTAGDETAILSA       paftda;
364     DWORD                       dwInstance;
365     ACMFILTERTAGENUMCBA         fnCallback;
366 };
367
368 static BOOL CALLBACK MSACM_FilterTagEnumCallbackWtoA(HACMDRIVERID hadid,
369                                                      PACMFILTERTAGDETAILSW paftdw,  
370                                                      DWORD dwInstance,             
371                                                      DWORD fdwSupport)
372 {
373     struct MSACM_FilterTagEnumWtoA_Instance* paftei;
374
375     paftei = (struct MSACM_FilterTagEnumWtoA_Instance*)dwInstance;
376
377     paftei->paftda->dwFilterTagIndex = paftdw->dwFilterTagIndex; 
378     paftei->paftda->dwFilterTag = paftdw->dwFilterTag; 
379     paftei->paftda->cbFilterSize = paftdw->cbFilterSize; 
380     paftei->paftda->fdwSupport = paftdw->fdwSupport; 
381     paftei->paftda->cStandardFilters = paftdw->cStandardFilters; 
382     WideCharToMultiByte( CP_ACP, 0, paftdw->szFilterTag, -1, paftei->paftda->szFilterTag,
383                          sizeof(paftei->paftda->szFilterTag), NULL, NULL );
384
385     return (paftei->fnCallback)(hadid, paftei->paftda, 
386                                 paftei->dwInstance, fdwSupport);
387 }
388
389 /***********************************************************************
390  *           acmFilterTagEnumA (MSACM32.21)
391  */
392 MMRESULT WINAPI acmFilterTagEnumA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda,
393                                   ACMFILTERTAGENUMCBA fnCallback, DWORD dwInstance, 
394                                   DWORD fdwEnum)
395 {
396     ACMFILTERTAGDETAILSW        aftdw;
397     struct MSACM_FilterTagEnumWtoA_Instance aftei;
398
399     memset(&aftdw, 0, sizeof(aftdw));
400     aftdw.cbStruct = sizeof(aftdw);
401     aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
402     aftdw.dwFilterTag = paftda->dwFilterTag;
403
404     aftei.paftda = paftda;
405     aftei.dwInstance = dwInstance;
406     aftei.fnCallback = fnCallback;
407
408     return acmFilterTagEnumW(had, &aftdw, MSACM_FilterTagEnumCallbackWtoA, 
409                              (DWORD)&aftei, fdwEnum);
410 }
411
412 /***********************************************************************
413  *           acmFilterTagEnumW (MSACM32.22)
414  */
415 MMRESULT WINAPI acmFilterTagEnumW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
416                                   ACMFILTERTAGENUMCBW fnCallback, DWORD dwInstance, 
417                                   DWORD fdwEnum)
418 {
419     PWINE_ACMDRIVERID           padid;
420     ACMDRIVERDETAILSW           add;
421     int                         i;
422
423     TRACE("(0x%08x, %p, %p, %ld, %ld)\n",
424           had, paftd, fnCallback, dwInstance, fdwEnum); 
425
426     if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
427
428     if (had) FIXME("had != NULL, not supported\n");
429     
430     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {
431         /* should check for codec only */
432         if (padid->bEnabled && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == MMSYSERR_NOERROR) {
433             add.cbStruct = sizeof(add);
434
435             if (acmDriverDetailsW((HACMDRIVERID)padid, &add, 0) == MMSYSERR_NOERROR) {
436                 for (i = 0; i < add.cFilterTags; i++) {
437                     paftd->dwFilterTagIndex = i;
438                     if (acmFilterTagDetailsW(had, paftd, ACM_FILTERTAGDETAILSF_INDEX) == MMSYSERR_NOERROR) {
439                         if (!(fnCallback)((HACMDRIVERID)padid, paftd, dwInstance, 
440                                           add.fdwSupport)) {
441                             padid = NULL;
442                             break;
443                         }
444                     }
445                 }
446             }
447         }
448         acmDriverClose(had, 0);
449     }
450     return MMSYSERR_NOERROR;
451 }