/*********************************************************************** * acmFormatTagDetailsW (MSACM32.@) */ MMRESULT WINAPI acmFormatTagDetailsW(HACMDRIVER had, PACMFORMATTAGDETAILSW paftd, DWORD fdwDetails) { PWINE_ACMDRIVERID padid; MMRESULT mmr = ACMERR_NOTPOSSIBLE; TRACE("(%p, %p, %d)\n", had, paftd, fdwDetails); if (fdwDetails & ~(ACM_FORMATTAGDETAILSF_FORMATTAG|ACM_FORMATTAGDETAILSF_INDEX| ACM_FORMATTAGDETAILSF_LARGESTSIZE)) return MMSYSERR_INVALFLAG; switch (fdwDetails) { case ACM_FORMATTAGDETAILSF_FORMATTAG: if (had == NULL) { for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { /* should check for codec only */ if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && MSACM_FindFormatTagInCache(padid, paftd->dwFormatTag, NULL) && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); acmDriverClose(had, 0); if (mmr == MMSYSERR_NOERROR) break; } } } else { PWINE_ACMDRIVER pad = MSACM_GetDriver(had); if (pad && MSACM_FindFormatTagInCache(pad->obj.pACMDriverID, paftd->dwFormatTag, NULL)) mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); } break; case ACM_FORMATTAGDETAILSF_INDEX: if (had != NULL) { PWINE_ACMDRIVER pad = MSACM_GetDriver(had); if (pad && paftd->dwFormatTagIndex < pad->obj.pACMDriverID->cFormatTags) mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); } break; case ACM_FORMATTAGDETAILSF_LARGESTSIZE: if (had == NULL) { ACMFORMATTAGDETAILSW tmp; DWORD ft = paftd->dwFormatTag; for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) { /* should check for codec only */ if (!(padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) && acmDriverOpen(&had, (HACMDRIVERID)padid, 0) == 0) { memset(&tmp, 0, sizeof(tmp)); tmp.cbStruct = sizeof(tmp); tmp.dwFormatTag = ft; if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&tmp, fdwDetails) == MMSYSERR_NOERROR) { if (mmr == ACMERR_NOTPOSSIBLE || paftd->cbFormatSize < tmp.cbFormatSize) { *paftd = tmp; mmr = MMSYSERR_NOERROR; } } acmDriverClose(had, 0); } } } else { mmr = MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)paftd, fdwDetails); } break; default: WARN("Unsupported fdwDetails=%08x\n", fdwDetails); mmr = MMSYSERR_ERROR; } if (mmr == MMSYSERR_NOERROR && paftd->dwFormatTag == WAVE_FORMAT_PCM && paftd->szFormatTag[0] == 0) MultiByteToWideChar( CP_ACP, 0, "PCM", -1, paftd->szFormatTag, sizeof(paftd->szFormatTag)/sizeof(WCHAR) ); return mmr; }
/*********************************************************************** * acmStreamOpen (MSACM32.@) */ MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had, PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst, PWAVEFILTER pwfltr, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) { PWINE_ACMSTREAM was; PWINE_ACMDRIVER wad; MMRESULT ret; int wfxSrcSize; int wfxDstSize; WAVEFORMATEX wfxSrc, wfxDst; TRACE("(%p, %p, %p, %p, %p, %ld, %ld, %d)\n", phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen); /* NOTE: pwfxSrc and/or pwfxDst can point to a structure smaller than * WAVEFORMATEX so don't use them directly when not sure */ if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) { memcpy(&wfxSrc, pwfxSrc, sizeof(PCMWAVEFORMAT)); wfxSrc.wBitsPerSample = pwfxSrc->wBitsPerSample; wfxSrc.cbSize = 0; pwfxSrc = &wfxSrc; } if (pwfxDst->wFormatTag == WAVE_FORMAT_PCM) { memcpy(&wfxDst, pwfxDst, sizeof(PCMWAVEFORMAT)); wfxDst.wBitsPerSample = pwfxDst->wBitsPerSample; wfxDst.cbSize = 0; pwfxDst = &wfxDst; } TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec, pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize); TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n", pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec, pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize); /* (WS) In query mode, phas should be NULL. If it is not, then instead * of returning an error we are making sure it is NULL, preventing some * applications that pass garbage for phas from crashing. */ if (fdwOpen & ACM_STREAMOPENF_QUERY) phas = NULL; if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) { WARN("invalid parameter\n"); return MMSYSERR_INVALPARAM; } wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX); if (pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) wfxSrcSize += pwfxSrc->cbSize; if (pwfxDst->wFormatTag != WAVE_FORMAT_PCM) wfxDstSize += pwfxDst->cbSize; was = HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize + ((pwfltr) ? sizeof(WAVEFILTER) : 0)); if (was == NULL) { WARN("no memory\n"); return MMSYSERR_NOMEM; } was->drvInst.cbStruct = sizeof(was->drvInst); was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was)); memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize); was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize); memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize); if (pwfltr) { was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize); memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER)); } else { was->drvInst.pwfltr = NULL; } was->drvInst.dwCallback = dwCallback; was->drvInst.dwInstance = dwInstance; was->drvInst.fdwOpen = fdwOpen; was->drvInst.fdwDriver = 0L; was->drvInst.dwDriver = 0L; /* real value will be stored once ACMDM_STREAM_OPEN succeeds */ was->drvInst.has = 0L; if (had) { if (!(wad = MSACM_GetDriver(had))) { ret = MMSYSERR_INVALPARAM; goto errCleanUp; } was->obj.dwType = WINE_ACMOBJ_STREAM; was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = 0; /* not to close it in acmStreamClose */ ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L); if (ret != MMSYSERR_NOERROR) goto errCleanUp; } else { PWINE_ACMDRIVERID wadi; ret = ACMERR_NOTPOSSIBLE; for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) { if ((wadi->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) || !MSACM_FindFormatTagInCache(wadi, pwfxSrc->wFormatTag, NULL) || !MSACM_FindFormatTagInCache(wadi, pwfxDst->wFormatTag, NULL)) continue; ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L); if (ret != MMSYSERR_NOERROR) continue; if ((wad = MSACM_GetDriver(had)) != 0) { was->obj.dwType = WINE_ACMOBJ_STREAM; was->obj.pACMDriverID = wad->obj.pACMDriverID; was->pDrv = wad; was->hAcmDriver = had; ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L); TRACE("%s => %08x\n", debugstr_w(wadi->pszDriverAlias), ret); if (ret == MMSYSERR_NOERROR) { if (fdwOpen & ACM_STREAMOPENF_QUERY) { MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_CLOSE, (LPARAM)&was->drvInst, 0); acmDriverClose(had, 0L); } break; } } /* no match, close this acm driver and try next one */ acmDriverClose(had, 0L); } if (ret != MMSYSERR_NOERROR) { ret = ACMERR_NOTPOSSIBLE; goto errCleanUp; } } ret = MMSYSERR_NOERROR; was->drvInst.has = (HACMSTREAM)was; if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) { if (phas) *phas = (HACMSTREAM)was; TRACE("=> (%d)\n", ret); return ret; } errCleanUp: if (phas) *phas = NULL; HeapFree(MSACM_hHeap, 0, was); TRACE("=> (%d)\n", ret); return ret; }