⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmm.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- tab-width: 8; c-basic-offset: 4 -*- */

/*
 * WINMM functions
 *
 * Copyright 1993      Martin Ayotte
 *           1998-2002 Eric Pouech
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*
 * Eric POUECH :
 * 	98/9	added Win32 MCI support
 *  	99/4	added midiStream support
 *      99/9	added support for loadable low level drivers
 */

/* TODO
 *      + it seems that some programs check what's installed in
 *        registry against the value returned by drivers. Wine is
 *        currently broken regarding this point.
 *      + check thread-safeness for MMSYSTEM and WINMM entry points
 *      + unicode entry points are badly supported (would require
 *        moving 32 bit drivers as Unicode as they are supposed to be)
 *      + allow joystick and timer external calls as we do for wave,
 *        midi, mixer and aux
 */

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "mmsystem.h"
#include "winuser.h"
#include "winnls.h"
#include "winreg.h"
#include "winternl.h"
#include "winemm.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(winmm);

void    (WINAPI *pFnReleaseThunkLock)(DWORD*);
void    (WINAPI *pFnRestoreThunkLock)(DWORD);

/* ========================================================================
 *                   G L O B A L   S E T T I N G S
 * ========================================================================*/

WINE_MM_IDATA WINMM_IData;

/**************************************************************************
 * 			WINMM_CreateIData			[internal]
 */
static	BOOL	WINMM_CreateIData(HINSTANCE hInstDLL)
{
    memset( &WINMM_IData, 0, sizeof WINMM_IData );

    WINMM_IData.hWinMM32Instance = hInstDLL;
    InitializeCriticalSection(&WINMM_IData.cs);
/* FIXME crashes in ReactOS
    WINMM_IData.cs.DebugInfo->Spare[1] = (DWORD)"WINMM_IData";
*/
    WINMM_IData.psStopEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
    WINMM_IData.psLastEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
    TRACE("Initialized IData (%p)\n", &WINMM_IData);
    return TRUE;
}

/**************************************************************************
 * 			WINMM_DeleteIData			[internal]
 */
static	void WINMM_DeleteIData(void)
{
    TIME_MMTimeStop();

    /* FIXME: should also free content and resources allocated
     * inside WINMM_IData */
    CloseHandle(WINMM_IData.psStopEvent);
    CloseHandle(WINMM_IData.psLastEvent);
    DeleteCriticalSection(&WINMM_IData.cs);
}

/******************************************************************
 *             WINMM_LoadMMSystem
 *
 */
#ifndef __REACTOS__
static HANDLE (WINAPI *pGetModuleHandle16)(LPCSTR);
static DWORD (WINAPI *pLoadLibrary16)(LPCSTR);
#endif

BOOL WINMM_CheckForMMSystem(void)
{
    /* 0 is not checked yet, -1 is not present, 1 is present */
    static      int    loaded /* = 0 */;

    if (loaded == 0)
    {
        HANDLE      h = GetModuleHandleA("kernel32");
        loaded = -1;
        if (h)
        {
#ifndef __REACTOS__
            pGetModuleHandle16 = (void*)GetProcAddress(h, "GetModuleHandle16");
            pLoadLibrary16 = (void*)GetProcAddress(h, "LoadLibrary16");
            if (pGetModuleHandle16 && pLoadLibrary16 &&
                (pGetModuleHandle16("MMSYSTEM.DLL") || pLoadLibrary16("MMSYSTEM.DLL")))
#endif /* __REACTOS__ */
                loaded = 1;
        }
    }
    return loaded > 0;
}

/******************************************************************
 *             WINMM_ErrorToString
 */
const char* WINMM_ErrorToString(MMRESULT error)
{
#define ERR_TO_STR(dev) case dev: return #dev
    static char unknown[32];
    switch (error) {
    ERR_TO_STR(MMSYSERR_NOERROR);
    ERR_TO_STR(MMSYSERR_ERROR);
    ERR_TO_STR(MMSYSERR_BADDEVICEID);
    ERR_TO_STR(MMSYSERR_NOTENABLED);
    ERR_TO_STR(MMSYSERR_ALLOCATED);
    ERR_TO_STR(MMSYSERR_INVALHANDLE);
    ERR_TO_STR(MMSYSERR_NODRIVER);
    ERR_TO_STR(MMSYSERR_NOMEM);
    ERR_TO_STR(MMSYSERR_NOTSUPPORTED);
    ERR_TO_STR(MMSYSERR_BADERRNUM);
    ERR_TO_STR(MMSYSERR_INVALFLAG);
    ERR_TO_STR(MMSYSERR_INVALPARAM);
    ERR_TO_STR(MMSYSERR_HANDLEBUSY);
    ERR_TO_STR(MMSYSERR_INVALIDALIAS);
    ERR_TO_STR(MMSYSERR_BADDB);
    ERR_TO_STR(MMSYSERR_KEYNOTFOUND);
    ERR_TO_STR(MMSYSERR_READERROR);
    ERR_TO_STR(MMSYSERR_WRITEERROR);
    ERR_TO_STR(MMSYSERR_DELETEERROR);
    ERR_TO_STR(MMSYSERR_VALNOTFOUND);
    ERR_TO_STR(MMSYSERR_NODRIVERCB);
    ERR_TO_STR(WAVERR_BADFORMAT);
    ERR_TO_STR(WAVERR_STILLPLAYING);
    ERR_TO_STR(WAVERR_UNPREPARED);
    ERR_TO_STR(WAVERR_SYNC);
    }
    sprintf(unknown, "Unknown(0x%08x)", error);
    return unknown;
#undef ERR_TO_STR
}

/**************************************************************************
 *		DllMain (WINMM.init)
 *
 * WINMM DLL entry point
 *
 */
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
{
    TRACE("%p 0x%lx %p\n", hInstDLL, fdwReason, fImpLoad);

    switch (fdwReason) {
    case DLL_PROCESS_ATTACH:
        DisableThreadLibraryCalls(hInstDLL);

	if (!WINMM_CreateIData(hInstDLL))
	    return FALSE;
        if (!MMDRV_Init()) {
            WINMM_DeleteIData();
            return FALSE;
	}
	break;
    case DLL_PROCESS_DETACH:
        /* close all opened MCI drivers */
        MCI_SendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, 0L, TRUE);
        MMDRV_Exit();
        /* now unload all remaining drivers... */
        DRIVER_UnloadAll();

	WINMM_DeleteIData();
	break;
    }
    return TRUE;
}

/**************************************************************************
 * 	Mixer devices. New to Win95
 */

/**************************************************************************
 * find out the real mixer ID depending on hmix (depends on dwFlags)
 */
static UINT MIXER_GetDev(HMIXEROBJ hmix, DWORD dwFlags, LPWINE_MIXER * lplpwm)
{
    LPWINE_MIXER	lpwm = NULL;
    UINT		uRet = MMSYSERR_NOERROR;

    switch (dwFlags & 0xF0000000ul) {
    case MIXER_OBJECTF_MIXER:
	lpwm = (LPWINE_MIXER)MMDRV_Get(hmix, MMDRV_MIXER, TRUE);
	break;
    case MIXER_OBJECTF_HMIXER:
	lpwm = (LPWINE_MIXER)MMDRV_Get(hmix, MMDRV_MIXER, FALSE);
	break;
    case MIXER_OBJECTF_WAVEOUT:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEOUT, TRUE,  MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_HWAVEOUT:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEOUT, FALSE, MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_WAVEIN:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEIN,  TRUE,  MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_HWAVEIN:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_WAVEIN,  FALSE, MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_MIDIOUT:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIOUT, TRUE,  MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_HMIDIOUT:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIOUT, FALSE, MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_MIDIIN:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIIN,  TRUE,  MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_HMIDIIN:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_MIDIIN,  FALSE, MMDRV_MIXER);
	break;
    case MIXER_OBJECTF_AUX:
	lpwm = (LPWINE_MIXER)MMDRV_GetRelated(hmix, MMDRV_AUX,     TRUE,  MMDRV_MIXER);
	break;
    default:
	WARN("Unsupported flag (%08lx)\n", dwFlags & 0xF0000000ul);
        lpwm = 0;
        uRet = MMSYSERR_INVALFLAG;
	break;
    }
    *lplpwm = lpwm;
    if (lpwm == 0 && uRet == MMSYSERR_NOERROR)
        uRet = MMSYSERR_INVALPARAM;
    return uRet;
}

/**************************************************************************
 * 				mixerGetNumDevs			[WINMM.@]
 */
UINT WINAPI mixerGetNumDevs(void)
{
    return MMDRV_GetNum(MMDRV_MIXER);
}

/**************************************************************************
 * 				mixerGetDevCapsA		[WINMM.@]
 */
UINT WINAPI mixerGetDevCapsA(UINT_PTR uDeviceID, LPMIXERCAPSA lpCaps, UINT uSize)
{
    MIXERCAPSW micW;
    UINT       ret;

    if (lpCaps == NULL) return MMSYSERR_INVALPARAM;

    ret = mixerGetDevCapsW(uDeviceID, &micW, sizeof(micW));

    if (ret == MMSYSERR_NOERROR) {
        MIXERCAPSA micA;
        micA.wMid           = micW.wMid;
        micA.wPid           = micW.wPid;
        micA.vDriverVersion = micW.vDriverVersion;
        WideCharToMultiByte( CP_ACP, 0, micW.szPname, -1, micA.szPname,
                             sizeof(micA.szPname), NULL, NULL );
        micA.fdwSupport     = micW.fdwSupport;
        micA.cDestinations  = micW.cDestinations;
        memcpy(lpCaps, &micA, min(uSize, sizeof(micA)));
    }
    return ret;
}

/**************************************************************************
 * 				mixerGetDevCapsW		[WINMM.@]
 */
UINT WINAPI mixerGetDevCapsW(UINT_PTR uDeviceID, LPMIXERCAPSW lpCaps, UINT uSize)
{
    LPWINE_MLD wmld;

    if (lpCaps == NULL)        return MMSYSERR_INVALPARAM;

    if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIXER, TRUE)) == NULL)
        return MMSYSERR_BADDEVICEID;

    return MMDRV_Message(wmld, MXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize, TRUE);
}

UINT  MIXER_Open(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback,
                 DWORD_PTR dwInstance, DWORD fdwOpen, BOOL bFrom32)
{
    HANDLE		hMix;
    LPWINE_MLD		wmld;
    DWORD		dwRet = 0;
    MIXEROPENDESC	mod;

    TRACE("(%p, %d, %08lx, %08lx, %08lx)\n",
	  lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen);

    wmld = MMDRV_Alloc(sizeof(WINE_MIXER), MMDRV_MIXER, &hMix, &fdwOpen,
		       &dwCallback, &dwInstance, bFrom32);

    wmld->uDeviceID = uDeviceID;
    mod.hmx = (HMIXEROBJ)hMix;
    mod.dwCallback = dwCallback;
    mod.dwInstance = dwInstance;

    dwRet = MMDRV_Open(wmld, MXDM_OPEN, (DWORD)&mod, fdwOpen);

    if (dwRet != MMSYSERR_NOERROR) {
	MMDRV_Free(hMix, wmld);
	hMix = 0;
    }
    if (lphMix) *lphMix = hMix;
    TRACE("=> %ld hMixer=%p\n", dwRet, hMix);

    return dwRet;
}

/**************************************************************************
 * 				mixerOpen			[WINMM.@]
 */
UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback,
                     DWORD_PTR dwInstance, DWORD fdwOpen)
{
    return MIXER_Open(lphMix, uDeviceID, dwCallback, dwInstance, fdwOpen, TRUE);
}

/**************************************************************************
 * 				mixerClose			[WINMM.@]
 */
UINT WINAPI mixerClose(HMIXER hMix)
{
    LPWINE_MLD		wmld;
    DWORD		dwRet;

    TRACE("(%p)\n", hMix);

    if ((wmld = MMDRV_Get(hMix, MMDRV_MIXER, FALSE)) == NULL) return MMSYSERR_INVALHANDLE;

    dwRet = MMDRV_Close(wmld, MXDM_CLOSE);
    MMDRV_Free(hMix, wmld);

    return dwRet;
}

/**************************************************************************
 * 				mixerGetID			[WINMM.@]
 */
UINT WINAPI mixerGetID(HMIXEROBJ hmix, LPUINT lpid, DWORD fdwID)
{
    LPWINE_MIXER	lpwm;
    UINT		uRet = MMSYSERR_NOERROR;

    TRACE("(%p %p %08lx)\n", hmix, lpid, fdwID);

    if ((uRet = MIXER_GetDev(hmix, fdwID, &lpwm)) != MMSYSERR_NOERROR)
	return uRet;

    if (lpid)
      *lpid = lpwm->mld.uDeviceID;

    return uRet;
}

/**************************************************************************
 * 				mixerGetControlDetailsW		[WINMM.@]
 */
UINT WINAPI mixerGetControlDetailsW(HMIXEROBJ hmix, LPMIXERCONTROLDETAILS lpmcdW,
				    DWORD fdwDetails)
{
    LPWINE_MIXER	lpwm;
    UINT		uRet = MMSYSERR_NOERROR;

    TRACE("(%p, %p, %08lx)\n", hmix, lpmcdW, fdwDetails);

    if ((uRet = MIXER_GetDev(hmix, fdwDetails, &lpwm)) != MMSYSERR_NOERROR)
	return uRet;

    if (lpmcdW == NULL || lpmcdW->cbStruct != sizeof(*lpmcdW))
	return MMSYSERR_INVALPARAM;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -