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