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

📄 mcimidi.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- tab-width: 8; c-basic-offset: 4 -*- *//* * Sample MIDI Wine Driver for Linux * * Copyright 	1994 Martin Ayotte *		1999 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/7 changes for making this MIDI driver work on OSS * 	current support is limited to MIDI ports of OSS systems * 98/9	rewriting MCI code for MIDI * 98/11 splitted in midi.c and mcimidi.c */#include <stdlib.h>#include <stdarg.h>#include <stdio.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "wownt32.h"#include "mmddk.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(mcimidi);#define MIDI_NOTEOFF             0x80#define MIDI_NOTEON              0x90typedef struct {    DWORD		dwFirst;		/* offset in file of track */    DWORD		dwLast;			/* number of bytes in file of track */    DWORD		dwIndex;		/* current index in file (dwFirst <= dwIndex < dwLast) */    DWORD		dwLength;		/* number of pulses in this track */    DWORD		dwEventPulse;		/* current pulse # (event) pointed by dwIndex */    DWORD		dwEventData;		/* current data    (event) pointed by dwIndex */    WORD		wEventLength;		/* current length  (event) pointed by dwIndex */    WORD		wStatus : 1,		/* 1 : playing, 0 : done */	                wTrackNr : 7,	                wLastCommand : 8;	/* last MIDI command on track */} MCI_MIDITRACK;typedef struct tagWINE_MCIMIDI {    UINT		wDevID;			/* the MCI one */    HMIDI		hMidi;    int			nUseCount;          	/* Incremented for each shared open          */    WORD		wNotifyDeviceID;    	/* MCI device ID with a pending notification */    HANDLE 		hCallback;         	/* Callback handle for pending notification  */    HMMIO		hFile;	            	/* mmio file handle open as Element          */    LPSTR		lpstrElementName;	/* Name of file */    LPSTR		lpstrCopyright;    LPSTR		lpstrName;    WORD		dwStatus;		/* one from MCI_MODE_xxxx */    DWORD		dwMciTimeFormat;	/* One of the supported MCI_FORMAT_xxxx */    WORD		wFormat;		/* Format of MIDI hFile (0, 1 or 2) */    WORD		nTracks;		/* Number of tracks in hFile */    WORD		nDivision;		/* Number of division in hFile PPQN or SMPTE */    WORD		wStartedPlaying;    DWORD		dwTempo;		/* Tempo (# of 1/4 note per second */    MCI_MIDITRACK*     	tracks;			/* Content of each track */    DWORD		dwPulse;    DWORD		dwPositionMS;    DWORD		dwStartTicks;} WINE_MCIMIDI;/* =================================================================== * =================================================================== * FIXME: should be using the new mmThreadXXXX functions from WINMM * instead of those * it would require to add a wine internal flag to mmThreadCreate * in order to pass a 32 bit function instead of a 16 bit * =================================================================== * =================================================================== */struct SCA {    UINT 	wDevID;    UINT 	wMsg;    DWORD 	dwParam1;    DWORD 	dwParam2;};/* EPP DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2); *//************************************************************************** * 				MCI_SCAStarter			[internal] */static DWORD CALLBACK	MCI_SCAStarter(LPVOID arg){    struct SCA*	sca = (struct SCA*)arg;    DWORD		ret;    TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",	  sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);    ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);    TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",	  sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);    HeapFree(GetProcessHeap(), 0, sca);    ExitThread(ret);    WARN("Should not happen ? what's wrong \n");    /* should not go after this point */    return ret;}/************************************************************************** * 				MCI_SendCommandAsync		[internal] */static	DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,				   DWORD dwParam2, UINT size){    struct SCA*	sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);    if (sca == 0)	return MCIERR_OUT_OF_MEMORY;    sca->wDevID   = wDevID;    sca->wMsg     = wMsg;    sca->dwParam1 = dwParam1;    if (size && dwParam2) {	sca->dwParam2 = (DWORD)sca + sizeof(struct SCA);	/* copy structure passed by program in dwParam2 to be sure	 * we can still use it whatever the program does	 */	memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);    } else {	sca->dwParam2 = dwParam2;    }    if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {	WARN("Couldn't allocate thread for async command handling, sending synchonously\n");	return MCI_SCAStarter(&sca);    }    return 0;}/*======================================================================* *                  	    MCI MIDI implemantation			* *======================================================================*/static DWORD MIDI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);/************************************************************************** * 				MIDI_drvOpen			[internal] */static	DWORD	MIDI_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp){    WINE_MCIMIDI*	wmm;    if (!modp) return 0xFFFFFFFF;    wmm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIMIDI));    if (!wmm)	return 0;    wmm->wDevID = modp->wDeviceID;    mciSetDriverData(wmm->wDevID, (DWORD)wmm);    modp->wCustomCommandTable = MCI_NO_COMMAND_TABLE;    modp->wType = MCI_DEVTYPE_SEQUENCER;    return modp->wDeviceID;}/************************************************************************** * 				MCIMIDI_drvClose		[internal] */static	DWORD	MIDI_drvClose(DWORD dwDevID){    WINE_MCIMIDI*  wmm = (WINE_MCIMIDI*)mciGetDriverData(dwDevID);    if (wmm) {	HeapFree(GetProcessHeap(), 0, wmm);	mciSetDriverData(dwDevID, 0);	return 1;    }    return (dwDevID == 0xFFFFFFFF) ? 1 : 0;}/************************************************************************** * 				MIDI_mciGetOpenDev		[internal] */static WINE_MCIMIDI*  MIDI_mciGetOpenDev(UINT wDevID){    WINE_MCIMIDI*	wmm = (WINE_MCIMIDI*)mciGetDriverData(wDevID);    if (wmm == NULL || wmm->nUseCount == 0) {	WARN("Invalid wDevID=%u\n", wDevID);	return 0;    }    return wmm;}/************************************************************************** * 				MIDI_mciReadByte		[internal] */static DWORD MIDI_mciReadByte(WINE_MCIMIDI* wmm, BYTE *lpbyt){    DWORD	ret = 0;    if (lpbyt == NULL ||	mmioRead(wmm->hFile, (HPSTR)lpbyt, sizeof(BYTE)) != (long)sizeof(BYTE)) {	WARN("Error reading wmm=%p\n", wmm);	ret = MCIERR_INVALID_FILE;    }    return ret;}/************************************************************************** * 				MIDI_mciReadWord		[internal] */static DWORD MIDI_mciReadWord(WINE_MCIMIDI* wmm, LPWORD lpw){    BYTE	hibyte, lobyte;    DWORD	ret = MCIERR_INVALID_FILE;    if (lpw != NULL &&	MIDI_mciReadByte(wmm, &hibyte) == 0 &&	MIDI_mciReadByte(wmm, &lobyte) == 0) {	*lpw = ((WORD)hibyte << 8) + lobyte;	ret = 0;    }    return ret;}/************************************************************************** * 				MIDI_mciReadLong		[internal] */static DWORD MIDI_mciReadLong(WINE_MCIMIDI* wmm, LPDWORD lpdw){    WORD	hiword, loword;    DWORD	ret = MCIERR_INVALID_FILE;    if (lpdw != NULL &&	MIDI_mciReadWord(wmm, &hiword) == 0 &&	MIDI_mciReadWord(wmm, &loword) == 0) {	*lpdw = MAKELONG(loword, hiword);	ret = 0;    }    return ret;}/************************************************************************** *  				MIDI_mciReadVaryLen		[internal] */static WORD MIDI_mciReadVaryLen(WINE_MCIMIDI* wmm, LPDWORD lpdw){    BYTE	byte;    DWORD	value = 0;    WORD	ret = 0;    if (lpdw == NULL) {	ret = MCIERR_INVALID_FILE;    } else {	do {	    if (MIDI_mciReadByte(wmm, &byte) != 0) {		return 0;	    }	    value = (value << 7) + (byte & 0x7F);	    ret++;	} while (byte & 0x80);	*lpdw = value;	/*	  TRACE("val=%08lX \n", value);	*/    }    return ret;}/************************************************************************** * 				MIDI_mciReadNextEvent		[internal] */static DWORD	MIDI_mciReadNextEvent(WINE_MCIMIDI* wmm, MCI_MIDITRACK* mmt){    BYTE	b1, b2 = 0, b3;    WORD	hw = 0;    DWORD	evtPulse;    DWORD	evtLength;    DWORD	tmp;    if (mmioSeek(wmm->hFile, mmt->dwIndex, SEEK_SET) != mmt->dwIndex) {	WARN("Can't seek at %08lX \n", mmt->dwIndex);	return MCIERR_INVALID_FILE;    }    evtLength = MIDI_mciReadVaryLen(wmm, &evtPulse) + 1;	/* > 0 */    MIDI_mciReadByte(wmm, &b1);    switch (b1) {    case 0xF0:    case 0xF7:	evtLength += MIDI_mciReadVaryLen(wmm, &tmp);	evtLength += tmp;	break;    case 0xFF:	MIDI_mciReadByte(wmm, &b2);	evtLength++;	evtLength += MIDI_mciReadVaryLen(wmm, &tmp);	if (evtLength >= 0x10000u) {	    /* this limitation shouldn't be a problem */	    WARN("Ouch !! Implementation limitation to 64k bytes for a MIDI event is overflowed\n");	    hw = 0xFFFF;	} else {	    hw = LOWORD(evtLength);	}	evtLength += tmp;	break;    default:	if (b1 & 0x80) { /* use running status ? */	    mmt->wLastCommand = b1;	    MIDI_mciReadByte(wmm, &b2);	evtLength++;	} else {	    b2 = b1;	    b1 = mmt->wLastCommand;	}	switch ((b1 >> 4) & 0x07) {	case 0:	case 1:	case 2: case 3: case 6:	    MIDI_mciReadByte(wmm, &b3);	evtLength++;	    hw = b3;	    break;	case 4:	case 5:	    break;	case 7:	    WARN("Strange indeed b1=0x%02x\n", b1);	}	break;    }    if (mmt->dwIndex + evtLength > mmt->dwLast)	return MCIERR_INTERNAL;    mmt->dwEventPulse += evtPulse;    mmt->dwEventData   = (hw << 16) + (b2 << 8) + b1;    mmt->wEventLength  = evtLength;    /*      TRACE("[%u] => pulse=%08lx(%08lx), data=%08lx, length=%u\n",      mmt->wTrackNr, mmt->dwEventPulse, evtPulse,      mmt->dwEventData, mmt->wEventLength);    */    return 0;}/************************************************************************** * 				MIDI_mciReadMTrk		[internal]

⌨️ 快捷键说明

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