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