Fix a crash when launching Unix executables.
[wine/multimedia.git] / dlls / msacm / filter.c
blob3bce5c23d3cefb9c1dbc156bdf49e7bece523294
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MSACM32 library
6 * Copyright 1998 Patrik Stridvall
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.
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.
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
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"
36 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
38 /***********************************************************************
39 * acmFilterChooseA (MSACM32.@)
41 MMRESULT WINAPI acmFilterChooseA(PACMFILTERCHOOSEA pafltrc)
43 FIXME("(%p): stub\n", pafltrc);
44 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
45 return MMSYSERR_ERROR;
48 /***********************************************************************
49 * acmFilterChooseW (MSACM32.@)
51 MMRESULT WINAPI acmFilterChooseW(PACMFILTERCHOOSEW pafltrc)
53 FIXME("(%p): stub\n", pafltrc);
54 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
55 return MMSYSERR_ERROR;
58 /***********************************************************************
59 * acmFilterDetailsA (MSACM32.@)
61 MMRESULT WINAPI acmFilterDetailsA(HACMDRIVER had, PACMFILTERDETAILSA pafd,
62 DWORD fdwDetails)
64 ACMFILTERDETAILSW afdw;
65 MMRESULT mmr;
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;
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 );
81 return mmr;
84 /***********************************************************************
85 * acmFilterDetailsW (MSACM32.@)
87 MMRESULT WINAPI acmFilterDetailsW(HACMDRIVER had, PACMFILTERDETAILSW pafd,
88 DWORD fdwDetails)
90 MMRESULT mmr;
91 ACMFILTERTAGDETAILSA aftd;
93 TRACE("(%p, %p, %ld)\n", had, pafd, fdwDetails);
95 memset(&aftd, 0, sizeof(aftd));
96 aftd.cbStruct = sizeof(aftd);
98 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
100 switch (fdwDetails) {
101 case ACM_FILTERDETAILSF_FILTER:
102 if (pafd->dwFilterTag != pafd->pwfltr->dwFilterTag) {
103 mmr = MMSYSERR_INVALPARAM;
104 break;
106 if (had == NULL) {
107 PWINE_ACMDRIVERID padid;
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;
120 } else {
121 mmr = MSACM_Message(had, ACMDM_FILTER_DETAILS, (LPARAM)pafd, fdwDetails);
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;
134 TRACE("=> %d\n", mmr);
135 return mmr;
138 struct MSACM_FilterEnumWtoA_Instance {
139 PACMFILTERDETAILSA pafda;
140 DWORD dwInstance;
141 ACMFILTERENUMCBA fnCallback;
144 static BOOL CALLBACK MSACM_FilterEnumCallbackWtoA(HACMDRIVERID hadid,
145 PACMFILTERDETAILSW pafdw,
146 DWORD dwInstance,
147 DWORD fdwSupport)
149 struct MSACM_FilterEnumWtoA_Instance* pafei;
151 pafei = (struct MSACM_FilterEnumWtoA_Instance*)dwInstance;
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 );
159 return (pafei->fnCallback)(hadid, pafei->pafda,
160 pafei->dwInstance, fdwSupport);
163 /***********************************************************************
164 * acmFilterEnumA (MSACM32.@)
166 MMRESULT WINAPI acmFilterEnumA(HACMDRIVER had, PACMFILTERDETAILSA pafda,
167 ACMFILTERENUMCBA fnCallback, DWORD dwInstance,
168 DWORD fdwEnum)
170 ACMFILTERDETAILSW afdw;
171 struct MSACM_FilterEnumWtoA_Instance afei;
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;
180 afei.pafda = pafda;
181 afei.dwInstance = dwInstance;
182 afei.fnCallback = fnCallback;
184 return acmFilterEnumW(had, &afdw, MSACM_FilterEnumCallbackWtoA,
185 (DWORD)&afei, fdwEnum);
188 static BOOL MSACM_FilterEnumHelper(PWINE_ACMDRIVERID padid, HACMDRIVER had,
189 PACMFILTERDETAILSW pafd,
190 ACMFILTERENUMCBW fnCallback, DWORD dwInstance,
191 DWORD fdwEnum)
193 ACMFILTERTAGDETAILSW aftd;
194 int i, j;
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;
203 if ((fdwEnum & ACM_FILTERENUMF_DWFILTERTAG) &&
204 aftd.dwFilterTag != pafd->pwfltr->dwFilterTag)
205 continue;
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;
213 if (!(fnCallback)((HACMDRIVERID)padid, pafd, dwInstance, padid->fdwSupport))
214 return FALSE;
217 return TRUE;
220 /***********************************************************************
221 * acmFilterEnumW (MSACM32.@)
223 MMRESULT WINAPI acmFilterEnumW(HACMDRIVER had, PACMFILTERDETAILSW pafd,
224 ACMFILTERENUMCBW fnCallback, DWORD dwInstance,
225 DWORD fdwEnum)
227 PWINE_ACMDRIVERID padid;
228 BOOL ret;
230 TRACE("(%p, %p, %p, %ld, %ld)\n",
231 had, pafd, fnCallback, dwInstance, fdwEnum);
233 if (pafd->cbStruct < sizeof(*pafd)) return MMSYSERR_INVALPARAM;
235 if (fdwEnum & ~(ACM_FILTERENUMF_DWFILTERTAG))
236 FIXME("Unsupported fdwEnum values\n");
238 if (had) {
239 HACMDRIVERID hadid;
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;
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;
257 return MMSYSERR_NOERROR;
260 /***********************************************************************
261 * acmFilterTagDetailsA (MSACM32.@)
263 MMRESULT WINAPI acmFilterTagDetailsA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda,
264 DWORD fdwDetails)
266 ACMFILTERTAGDETAILSW aftdw;
267 MMRESULT mmr;
269 memset(&aftdw, 0, sizeof(aftdw));
270 aftdw.cbStruct = sizeof(aftdw);
271 aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
272 aftdw.dwFilterTag = paftda->dwFilterTag;
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 );
284 return mmr;
287 /***********************************************************************
288 * acmFilterTagDetailsW (MSACM32.@)
290 MMRESULT WINAPI acmFilterTagDetailsW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
291 DWORD fdwDetails)
293 PWINE_ACMDRIVERID padid;
294 MMRESULT mmr;
296 TRACE("(%p, %p, %ld)\n", had, paftd, fdwDetails);
298 if (fdwDetails & ~(ACM_FILTERTAGDETAILSF_FILTERTAG|ACM_FILTERTAGDETAILSF_INDEX|
299 ACM_FILTERTAGDETAILSF_LARGESTSIZE))
300 return MMSYSERR_INVALFLAG;
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;
315 } else {
316 mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
318 break;
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;
325 case ACM_FILTERTAGDETAILSF_LARGESTSIZE:
326 if (had == NULL) {
327 ACMFILTERTAGDETAILSW tmp;
328 DWORD ft = paftd->dwFilterTag;
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) {
336 memset(&tmp, 0, sizeof(tmp));
337 tmp.cbStruct = sizeof(tmp);
338 tmp.dwFilterTag = ft;
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;
348 acmDriverClose(had, 0);
351 } else {
352 mmr = MSACM_Message(had, ACMDM_FILTERTAG_DETAILS, (LPARAM)paftd, fdwDetails);
354 break;
356 default:
357 WARN("Unsupported fdwDetails=%08lx\n", fdwDetails);
358 mmr = MMSYSERR_ERROR;
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) );
366 return mmr;
369 struct MSACM_FilterTagEnumWtoA_Instance {
370 PACMFILTERTAGDETAILSA paftda;
371 DWORD dwInstance;
372 ACMFILTERTAGENUMCBA fnCallback;
375 static BOOL CALLBACK MSACM_FilterTagEnumCallbackWtoA(HACMDRIVERID hadid,
376 PACMFILTERTAGDETAILSW paftdw,
377 DWORD dwInstance,
378 DWORD fdwSupport)
380 struct MSACM_FilterTagEnumWtoA_Instance* paftei;
382 paftei = (struct MSACM_FilterTagEnumWtoA_Instance*)dwInstance;
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 );
392 return (paftei->fnCallback)(hadid, paftei->paftda,
393 paftei->dwInstance, fdwSupport);
396 /***********************************************************************
397 * acmFilterTagEnumA (MSACM32.@)
399 MMRESULT WINAPI acmFilterTagEnumA(HACMDRIVER had, PACMFILTERTAGDETAILSA paftda,
400 ACMFILTERTAGENUMCBA fnCallback, DWORD dwInstance,
401 DWORD fdwEnum)
403 ACMFILTERTAGDETAILSW aftdw;
404 struct MSACM_FilterTagEnumWtoA_Instance aftei;
406 memset(&aftdw, 0, sizeof(aftdw));
407 aftdw.cbStruct = sizeof(aftdw);
408 aftdw.dwFilterTagIndex = paftda->dwFilterTagIndex;
409 aftdw.dwFilterTag = paftda->dwFilterTag;
411 aftei.paftda = paftda;
412 aftei.dwInstance = dwInstance;
413 aftei.fnCallback = fnCallback;
415 return acmFilterTagEnumW(had, &aftdw, MSACM_FilterTagEnumCallbackWtoA,
416 (DWORD)&aftei, fdwEnum);
419 /***********************************************************************
420 * acmFilterTagEnumW (MSACM32.@)
422 MMRESULT WINAPI acmFilterTagEnumW(HACMDRIVER had, PACMFILTERTAGDETAILSW paftd,
423 ACMFILTERTAGENUMCBW fnCallback, DWORD dwInstance,
424 DWORD fdwEnum)
426 PWINE_ACMDRIVERID padid;
427 int i;
429 TRACE("(%p, %p, %p, %ld, %ld)\n",
430 had, paftd, fnCallback, dwInstance, fdwEnum);
432 if (paftd->cbStruct < sizeof(*paftd)) return MMSYSERR_INVALPARAM;
434 if (had) FIXME("had != NULL, not supported\n");
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) {
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;
451 acmDriverClose(had, 0);
453 return MMSYSERR_NOERROR;