ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

stream.c
Go to the documentation of this file.
00001 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
00002 
00003 /*
00004  *      MSACM32 library
00005  *
00006  *      Copyright 1998  Patrik Stridvall
00007  *        1999  Eric Pouech
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 /* TODO
00025  *  + asynchronous conversion is not implemented
00026  *  + callback/notification
00027  *  * acmStreamMessage
00028  *  + properly close ACM streams
00029  */
00030 
00031 #include <stdarg.h>
00032 #include <string.h>
00033 #include "windef.h"
00034 #include "winbase.h"
00035 #include "winerror.h"
00036 #include "wine/debug.h"
00037 #include "mmsystem.h"
00038 #define NOBITMAP
00039 #include "mmreg.h"
00040 #include "msacm.h"
00041 #include "msacmdrv.h"
00042 #include "wineacm.h"
00043 
00044 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
00045 
00046 static PWINE_ACMSTREAM  ACM_GetStream(HACMSTREAM has)
00047 {
00048     TRACE("(%p)\n", has);
00049 
00050     return (PWINE_ACMSTREAM)has;
00051 }
00052 
00053 /***********************************************************************
00054  *           acmStreamClose (MSACM32.@)
00055  */
00056 MMRESULT WINAPI acmStreamClose(HACMSTREAM has, DWORD fdwClose)
00057 {
00058     PWINE_ACMSTREAM was;
00059     MMRESULT        ret;
00060 
00061     TRACE("(%p, %d)\n", has, fdwClose);
00062 
00063     if ((was = ACM_GetStream(has)) == NULL) {
00064         WARN("invalid handle\n");
00065     return MMSYSERR_INVALHANDLE;
00066     }
00067     ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_CLOSE, (LPARAM)&was->drvInst, 0);
00068     if (ret == MMSYSERR_NOERROR) {
00069     if (was->hAcmDriver)
00070         acmDriverClose(was->hAcmDriver, 0L);
00071     HeapFree(MSACM_hHeap, 0, was);
00072     }
00073     TRACE("=> (%d)\n", ret);
00074     return ret;
00075 }
00076 
00077 /***********************************************************************
00078  *           acmStreamConvert (MSACM32.@)
00079  */
00080 MMRESULT WINAPI acmStreamConvert(HACMSTREAM has, PACMSTREAMHEADER pash,
00081                  DWORD fdwConvert)
00082 {
00083     PWINE_ACMSTREAM was;
00084     MMRESULT        ret = MMSYSERR_NOERROR;
00085     PACMDRVSTREAMHEADER padsh;
00086 
00087     TRACE("(%p, %p, %d)\n", has, pash, fdwConvert);
00088 
00089     if ((was = ACM_GetStream(has)) == NULL) {
00090         WARN("invalid handle\n");
00091     return MMSYSERR_INVALHANDLE;
00092     }
00093     if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER)) {
00094         WARN("invalid parameter\n");
00095     return MMSYSERR_INVALPARAM;
00096     }
00097     if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)) {
00098         WARN("unprepared header\n");
00099     return ACMERR_UNPREPARED;
00100     }
00101 
00102     pash->cbSrcLengthUsed = 0;
00103     pash->cbDstLengthUsed = 0;
00104 
00105     /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
00106      * size. some fields are private to msacm internals, and are exposed
00107      * in ACMSTREAMHEADER in the dwReservedDriver array
00108      */
00109     padsh = (PACMDRVSTREAMHEADER)pash;
00110 
00111     /* check that pointers have not been modified */
00112     if (padsh->pbPreparedSrc != padsh->pbSrc ||
00113     padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
00114     padsh->pbPreparedDst != padsh->pbDst ||
00115     padsh->cbPreparedDstLength < padsh->cbDstLength) {
00116         WARN("invalid parameter\n");
00117     return MMSYSERR_INVALPARAM;
00118     }
00119 
00120     padsh->fdwConvert = fdwConvert;
00121 
00122     ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_CONVERT, (LPARAM)&was->drvInst, (LPARAM)padsh);
00123     if (ret == MMSYSERR_NOERROR) {
00124     padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_DONE;
00125     }
00126     TRACE("=> (%d)\n", ret);
00127     return ret;
00128 }
00129 
00130 /***********************************************************************
00131  *           acmStreamMessage (MSACM32.@)
00132  */
00133 MMRESULT WINAPI acmStreamMessage(HACMSTREAM has, UINT uMsg, LPARAM lParam1,
00134                  LPARAM lParam2)
00135 {
00136     FIXME("(%p, %u, %ld, %ld): stub\n", has, uMsg, lParam1, lParam2);
00137     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
00138     return MMSYSERR_ERROR;
00139 }
00140 
00141 /***********************************************************************
00142  *           acmStreamOpen (MSACM32.@)
00143  */
00144 MMRESULT WINAPI acmStreamOpen(PHACMSTREAM phas, HACMDRIVER had,
00145                               PWAVEFORMATEX pwfxSrc, PWAVEFORMATEX pwfxDst,
00146                               PWAVEFILTER pwfltr, DWORD_PTR dwCallback,
00147                               DWORD_PTR dwInstance, DWORD fdwOpen)
00148 {
00149     PWINE_ACMSTREAM was;
00150     PWINE_ACMDRIVER wad;
00151     MMRESULT        ret;
00152     int         wfxSrcSize;
00153     int         wfxDstSize;
00154     WAVEFORMATEX    wfxSrc, wfxDst;
00155 
00156     TRACE("(%p, %p, %p, %p, %p, %ld, %ld, %d)\n",
00157       phas, had, pwfxSrc, pwfxDst, pwfltr, dwCallback, dwInstance, fdwOpen);
00158 
00159     /* NOTE: pwfxSrc and/or pwfxDst can point to a structure smaller than
00160      * WAVEFORMATEX so don't use them directly when not sure */
00161     if (pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) {
00162         memcpy(&wfxSrc, pwfxSrc, sizeof(PCMWAVEFORMAT));
00163         wfxSrc.wBitsPerSample = pwfxSrc->wBitsPerSample;
00164         wfxSrc.cbSize = 0;
00165         pwfxSrc = &wfxSrc;
00166     }
00167 
00168     if (pwfxDst->wFormatTag == WAVE_FORMAT_PCM) {
00169         memcpy(&wfxDst, pwfxDst, sizeof(PCMWAVEFORMAT));
00170         wfxDst.wBitsPerSample = pwfxDst->wBitsPerSample;
00171         wfxDst.cbSize = 0;
00172         pwfxDst = &wfxDst;
00173     }
00174 
00175     TRACE("src [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
00176       pwfxSrc->wFormatTag, pwfxSrc->nChannels, pwfxSrc->nSamplesPerSec, pwfxSrc->nAvgBytesPerSec,
00177       pwfxSrc->nBlockAlign, pwfxSrc->wBitsPerSample, pwfxSrc->cbSize);
00178 
00179     TRACE("dst [wFormatTag=%u, nChannels=%u, nSamplesPerSec=%u, nAvgBytesPerSec=%u, nBlockAlign=%u, wBitsPerSample=%u, cbSize=%u]\n",
00180       pwfxDst->wFormatTag, pwfxDst->nChannels, pwfxDst->nSamplesPerSec, pwfxDst->nAvgBytesPerSec,
00181       pwfxDst->nBlockAlign, pwfxDst->wBitsPerSample, pwfxDst->cbSize);
00182 
00183     /* (WS) In query mode, phas should be NULL. If it is not, then instead
00184      * of returning an error we are making sure it is NULL, preventing some
00185      * applications that pass garbage for phas from crashing.
00186      */
00187     if (fdwOpen & ACM_STREAMOPENF_QUERY) phas = NULL;
00188 
00189     if (pwfltr && (pwfxSrc->wFormatTag != pwfxDst->wFormatTag)) {
00190         WARN("invalid parameter\n");
00191         return MMSYSERR_INVALPARAM;
00192     }
00193 
00194     wfxSrcSize = wfxDstSize = sizeof(WAVEFORMATEX);
00195     if (pwfxSrc->wFormatTag != WAVE_FORMAT_PCM) wfxSrcSize += pwfxSrc->cbSize;
00196     if (pwfxDst->wFormatTag != WAVE_FORMAT_PCM) wfxDstSize += pwfxDst->cbSize;
00197 
00198     was = HeapAlloc(MSACM_hHeap, 0, sizeof(*was) + wfxSrcSize + wfxDstSize +
00199             ((pwfltr) ? sizeof(WAVEFILTER) : 0));
00200     if (was == NULL) {
00201         WARN("no memory\n");
00202     return MMSYSERR_NOMEM;
00203     }
00204 
00205     was->drvInst.cbStruct = sizeof(was->drvInst);
00206     was->drvInst.pwfxSrc = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was));
00207     memcpy(was->drvInst.pwfxSrc, pwfxSrc, wfxSrcSize);
00208     was->drvInst.pwfxDst = (PWAVEFORMATEX)((LPSTR)was + sizeof(*was) + wfxSrcSize);
00209     memcpy(was->drvInst.pwfxDst, pwfxDst, wfxDstSize);
00210     if (pwfltr) {
00211     was->drvInst.pwfltr = (PWAVEFILTER)((LPSTR)was + sizeof(*was) + wfxSrcSize + wfxDstSize);
00212     memcpy(was->drvInst.pwfltr, pwfltr, sizeof(WAVEFILTER));
00213     } else {
00214     was->drvInst.pwfltr = NULL;
00215     }
00216     was->drvInst.dwCallback = dwCallback;
00217     was->drvInst.dwInstance = dwInstance;
00218     was->drvInst.fdwOpen = fdwOpen;
00219     was->drvInst.fdwDriver = 0L;
00220     was->drvInst.dwDriver = 0L;
00221     /* real value will be stored once ACMDM_STREAM_OPEN succeeds */
00222     was->drvInst.has = 0L;
00223 
00224     if (had) {
00225     if (!(wad = MSACM_GetDriver(had))) {
00226         ret = MMSYSERR_INVALPARAM;
00227         goto errCleanUp;
00228     }
00229 
00230     was->obj.dwType = WINE_ACMOBJ_STREAM;
00231     was->obj.pACMDriverID = wad->obj.pACMDriverID;
00232     was->pDrv = wad;
00233     was->hAcmDriver = 0; /* not to close it in acmStreamClose */
00234 
00235     ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L);
00236     if (ret != MMSYSERR_NOERROR)
00237         goto errCleanUp;
00238     } else {
00239     PWINE_ACMDRIVERID wadi;
00240 
00241     ret = ACMERR_NOTPOSSIBLE;
00242     for (wadi = MSACM_pFirstACMDriverID; wadi; wadi = wadi->pNextACMDriverID) {
00243         if ((wadi->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ||
00244         !MSACM_FindFormatTagInCache(wadi, pwfxSrc->wFormatTag, NULL) ||
00245         !MSACM_FindFormatTagInCache(wadi, pwfxDst->wFormatTag, NULL))
00246         continue;
00247         ret = acmDriverOpen(&had, (HACMDRIVERID)wadi, 0L);
00248         if (ret != MMSYSERR_NOERROR)
00249         continue;
00250         if ((wad = MSACM_GetDriver(had)) != 0) {
00251         was->obj.dwType = WINE_ACMOBJ_STREAM;
00252         was->obj.pACMDriverID = wad->obj.pACMDriverID;
00253         was->pDrv = wad;
00254         was->hAcmDriver = had;
00255 
00256         ret = MSACM_Message((HACMDRIVER)wad, ACMDM_STREAM_OPEN, (LPARAM)&was->drvInst, 0L);
00257         TRACE("%s => %08x\n", debugstr_w(wadi->pszDriverAlias), ret);
00258         if (ret == MMSYSERR_NOERROR) {
00259             if (fdwOpen & ACM_STREAMOPENF_QUERY) {
00260             acmDriverClose(had, 0L);
00261             }
00262             break;
00263         }
00264         }
00265         /* no match, close this acm driver and try next one */
00266         acmDriverClose(had, 0L);
00267     }
00268     if (ret != MMSYSERR_NOERROR) {
00269         ret = ACMERR_NOTPOSSIBLE;
00270         goto errCleanUp;
00271     }
00272     }
00273     ret = MMSYSERR_NOERROR;
00274     was->drvInst.has = (HACMSTREAM)was;
00275     if (!(fdwOpen & ACM_STREAMOPENF_QUERY)) {
00276     if (phas)
00277         *phas = (HACMSTREAM)was;
00278     TRACE("=> (%d)\n", ret);
00279     return ret;
00280     }
00281 errCleanUp:
00282     if (phas)
00283     *phas = NULL;
00284     HeapFree(MSACM_hHeap, 0, was);
00285     TRACE("=> (%d)\n", ret);
00286     return ret;
00287 }
00288 
00289 
00290 /***********************************************************************
00291  *           acmStreamPrepareHeader (MSACM32.@)
00292  */
00293 MMRESULT WINAPI acmStreamPrepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
00294                        DWORD fdwPrepare)
00295 {
00296     PWINE_ACMSTREAM was;
00297     MMRESULT        ret = MMSYSERR_NOERROR;
00298     PACMDRVSTREAMHEADER padsh;
00299 
00300     TRACE("(%p, %p, %d)\n", has, pash, fdwPrepare);
00301 
00302     if ((was = ACM_GetStream(has)) == NULL) {
00303         WARN("invalid handle\n");
00304     return MMSYSERR_INVALHANDLE;
00305     }
00306     if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER)) {
00307         WARN("invalid parameter\n");
00308     return MMSYSERR_INVALPARAM;
00309     }
00310     if (fdwPrepare)
00311     ret = MMSYSERR_INVALFLAG;
00312 
00313     if (pash->fdwStatus & ACMSTREAMHEADER_STATUSF_DONE)
00314     return MMSYSERR_NOERROR;
00315 
00316     /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
00317      * size. some fields are private to msacm internals, and are exposed
00318      * in ACMSTREAMHEADER in the dwReservedDriver array
00319      */
00320     padsh = (PACMDRVSTREAMHEADER)pash;
00321 
00322     padsh->fdwConvert = fdwPrepare;
00323     padsh->padshNext = NULL;
00324     padsh->fdwDriver = padsh->dwDriver = 0L;
00325 
00326     padsh->fdwPrepared = 0;
00327     padsh->dwPrepared = 0;
00328     padsh->pbPreparedSrc = 0;
00329     padsh->cbPreparedSrcLength = 0;
00330     padsh->pbPreparedDst = 0;
00331     padsh->cbPreparedDstLength = 0;
00332 
00333     ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_PREPARE, (LPARAM)&was->drvInst, (LPARAM)padsh);
00334     if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
00335     ret = MMSYSERR_NOERROR;
00336     padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE);
00337     padsh->fdwStatus |= ACMSTREAMHEADER_STATUSF_PREPARED;
00338     padsh->fdwPrepared = padsh->fdwStatus;
00339     padsh->dwPrepared = 0;
00340     padsh->pbPreparedSrc = padsh->pbSrc;
00341     padsh->cbPreparedSrcLength = padsh->cbSrcLength;
00342     padsh->pbPreparedDst = padsh->pbDst;
00343     padsh->cbPreparedDstLength = padsh->cbDstLength;
00344     } else {
00345     padsh->fdwPrepared = 0;
00346     padsh->dwPrepared = 0;
00347     padsh->pbPreparedSrc = 0;
00348     padsh->cbPreparedSrcLength = 0;
00349     padsh->pbPreparedDst = 0;
00350     padsh->cbPreparedDstLength = 0;
00351     }
00352     TRACE("=> (%d)\n", ret);
00353     return ret;
00354 }
00355 
00356 /***********************************************************************
00357  *           acmStreamReset (MSACM32.@)
00358  */
00359 MMRESULT WINAPI acmStreamReset(HACMSTREAM has, DWORD fdwReset)
00360 {
00361     PWINE_ACMSTREAM was;
00362     MMRESULT        ret = MMSYSERR_NOERROR;
00363 
00364     TRACE("(%p, %d)\n", has, fdwReset);
00365 
00366     if (fdwReset) {
00367         WARN("invalid flag\n");
00368     ret = MMSYSERR_INVALFLAG;
00369     } else if ((was = ACM_GetStream(has)) == NULL) {
00370         WARN("invalid handle\n");
00371     return MMSYSERR_INVALHANDLE;
00372     } else if (was->drvInst.fdwOpen & ACM_STREAMOPENF_ASYNC) {
00373     ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_RESET, (LPARAM)&was->drvInst, 0);
00374     }
00375     TRACE("=> (%d)\n", ret);
00376     return ret;
00377 }
00378 
00379 /***********************************************************************
00380  *           acmStreamSize (MSACM32.@)
00381  */
00382 MMRESULT WINAPI acmStreamSize(HACMSTREAM has, DWORD cbInput,
00383                   LPDWORD pdwOutputBytes, DWORD fdwSize)
00384 {
00385     PWINE_ACMSTREAM was;
00386     ACMDRVSTREAMSIZE    adss;
00387     MMRESULT        ret;
00388 
00389     TRACE("(%p, %d, %p, %d)\n", has, cbInput, pdwOutputBytes, fdwSize);
00390 
00391     if ((was = ACM_GetStream(has)) == NULL) {
00392         WARN("invalid handle\n");
00393     return MMSYSERR_INVALHANDLE;
00394     }
00395     if ((fdwSize & ~ACM_STREAMSIZEF_QUERYMASK) != 0) {
00396         WARN("invalid flag\n");
00397     return MMSYSERR_INVALFLAG;
00398     }
00399 
00400     *pdwOutputBytes = 0L;
00401 
00402     switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
00403     case ACM_STREAMSIZEF_DESTINATION:
00404     adss.cbDstLength = cbInput;
00405     adss.cbSrcLength = 0;
00406     break;
00407     case ACM_STREAMSIZEF_SOURCE:
00408     adss.cbSrcLength = cbInput;
00409     adss.cbDstLength = 0;
00410     break;
00411     default:
00412         WARN("invalid flag\n");
00413     return MMSYSERR_INVALFLAG;
00414     }
00415 
00416     adss.cbStruct = sizeof(adss);
00417     adss.fdwSize = fdwSize;
00418     ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_SIZE,
00419                             (LPARAM)&was->drvInst, (LPARAM)&adss);
00420     if (ret == MMSYSERR_NOERROR) {
00421     switch (fdwSize & ACM_STREAMSIZEF_QUERYMASK) {
00422     case ACM_STREAMSIZEF_DESTINATION:
00423         *pdwOutputBytes = adss.cbSrcLength;
00424         break;
00425     case ACM_STREAMSIZEF_SOURCE:
00426         *pdwOutputBytes = adss.cbDstLength;
00427         break;
00428     }
00429     }
00430     TRACE("=> (%d) [%u]\n", ret, *pdwOutputBytes);
00431     return ret;
00432 }
00433 
00434 /***********************************************************************
00435  *           acmStreamUnprepareHeader (MSACM32.@)
00436  */
00437 MMRESULT WINAPI acmStreamUnprepareHeader(HACMSTREAM has, PACMSTREAMHEADER pash,
00438                      DWORD fdwUnprepare)
00439 {
00440     PWINE_ACMSTREAM was;
00441     MMRESULT        ret = MMSYSERR_NOERROR;
00442     PACMDRVSTREAMHEADER padsh;
00443 
00444     TRACE("(%p, %p, %d)\n", has, pash, fdwUnprepare);
00445 
00446     if ((was = ACM_GetStream(has)) == NULL) {
00447         WARN("invalid handle\n");
00448     return MMSYSERR_INVALHANDLE;
00449     }
00450     if (!pash || pash->cbStruct < sizeof(ACMSTREAMHEADER)) {
00451         WARN("invalid parameter\n");
00452     return MMSYSERR_INVALPARAM;
00453     }
00454     if (!(pash->fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)) {
00455         WARN("unprepared header\n");
00456     return ACMERR_UNPREPARED;
00457     }
00458 
00459     /* Note: the ACMSTREAMHEADER and ACMDRVSTREAMHEADER structs are of same
00460      * size. some fields are private to msacm internals, and are exposed
00461      * in ACMSTREAMHEADER in the dwReservedDriver array
00462      */
00463     padsh = (PACMDRVSTREAMHEADER)pash;
00464 
00465     /* check that pointers have not been modified */
00466     if (padsh->pbPreparedSrc != padsh->pbSrc ||
00467     padsh->cbPreparedSrcLength < padsh->cbSrcLength ||
00468     padsh->pbPreparedDst != padsh->pbDst ||
00469     padsh->cbPreparedDstLength < padsh->cbDstLength) {
00470         WARN("invalid parameter\n");
00471     return MMSYSERR_INVALPARAM;
00472     }
00473 
00474     padsh->fdwConvert = fdwUnprepare;
00475 
00476     ret = MSACM_Message((HACMDRIVER)was->pDrv, ACMDM_STREAM_UNPREPARE, (LPARAM)&was->drvInst, (LPARAM)padsh);
00477     if (ret == MMSYSERR_NOERROR || ret == MMSYSERR_NOTSUPPORTED) {
00478     ret = MMSYSERR_NOERROR;
00479     padsh->fdwStatus &= ~(ACMSTREAMHEADER_STATUSF_DONE|ACMSTREAMHEADER_STATUSF_INQUEUE|ACMSTREAMHEADER_STATUSF_PREPARED);
00480     }
00481     TRACE("=> (%d)\n", ret);
00482     return ret;
00483 }

Generated on Fri May 25 2012 04:21:59 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.