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