gps/GPSResources/tcpmpVerOld/mikmod/libmikmod/drivers/drv_win.c

211 lines
4.8 KiB
C
Executable File

/* MikMod sound library
(c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
complete list.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of
the License, or (at your option) any later version.
This program 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 Library General Public License for more details.
You should have received a copy of the GNU Library 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.
*/
/*==============================================================================
$Id: drv_win.c,v 1.2 2004/01/31 22:39:40 raph Exp $
Driver for output on win32 platforms using the multimedia API
==============================================================================*/
/*
Written by Bjornar Henden <bhenden@online.no>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "mikmod_internals.h"
#ifdef DRV_WIN
#include <windows.h>
#pragma comment(lib,"winmm.lib")
#define NUMBUFFERS 6 /* number of buffers */
#define BUFFERSIZE 120 /* buffer size in milliseconds */
HWAVEOUT hwaveout;
WAVEHDR header[NUMBUFFERS];
LPSTR buffer[NUMBUFFERS]; /* pointers to buffers */
WORD buffersout; /* number of buffers playing/about to be played */
WORD nextbuffer; /* next buffer to be mixed */
ULONG buffersize; /* buffer size in bytes */
/* converts Windows error to libmikmod error */
static int WIN_GetError(MMRESULT mmr)
{
switch (mmr) {
case MMSYSERR_INVALHANDLE:
return MMERR_WINMM_HANDLE;
case MMSYSERR_NODRIVER:
return MMERR_OPENING_AUDIO;
case MMSYSERR_NOMEM:
return MMERR_OUT_OF_MEMORY;
case MMSYSERR_ALLOCATED:
return MMERR_WINMM_ALLOCATED;
case MMSYSERR_BADDEVICEID:
return MMERR_WINMM_DEVICEID;
case WAVERR_BADFORMAT:
return MMERR_WINMM_FORMAT;
default:
return MMERR_WINMM_UNKNOWN; /* should hopefully not happen */
}
}
static BOOL WIN_IsThere(void)
{
return waveOutGetNumDevs()>0?1:0;
}
static void CALLBACK WIN_CallBack(HWAVEOUT hwo,UINT uMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2)
{
if (uMsg==WOM_DONE) --buffersout;
}
static BOOL WIN_Init(void)
{
WAVEFORMATEX wfe;
WORD samplesize;
MMRESULT mmr;
int n;
samplesize=1;
if (md_mode&DMODE_STEREO) samplesize<<=1;
if (md_mode&DMODE_16BITS) samplesize<<=1;
wfe.wFormatTag=WAVE_FORMAT_PCM;
wfe.nChannels=md_mode&DMODE_STEREO?2:1;
wfe.nSamplesPerSec=md_mixfreq;
wfe.nAvgBytesPerSec=md_mixfreq*samplesize;
wfe.nBlockAlign=samplesize;
wfe.wBitsPerSample=md_mode&DMODE_16BITS?16:8;
wfe.cbSize=sizeof(wfe);
mmr=waveOutOpen(&hwaveout,WAVE_MAPPER,&wfe,(DWORD)WIN_CallBack,0,CALLBACK_FUNCTION);
if (mmr!=MMSYSERR_NOERROR) {
_mm_errno=WIN_GetError(mmr);
return 1;
}
buffersize=md_mixfreq*samplesize*BUFFERSIZE/1000;
for (n=0;n<NUMBUFFERS;n++) {
buffer[n]=_mm_malloc(buffersize);
header[n].lpData=buffer[n];
header[n].dwBufferLength=buffersize;
mmr=waveOutPrepareHeader(hwaveout,&header[n],sizeof(WAVEHDR));
if (!buffer[n]||mmr!=MMSYSERR_NOERROR) {
if (!buffer[n])
_mm_errno=MMERR_OUT_OF_MEMORY;
else
_mm_errno=WIN_GetError(mmr);
return 1;
}
}
md_mode|=DMODE_SOFT_MUSIC|DMODE_SOFT_SNDFX;
buffersout=nextbuffer=0;
return VC_Init();
}
static void WIN_Exit(void)
{
int n;
VC_Exit();
if (hwaveout) {
for (n=0;n<NUMBUFFERS;n++) {
if (header[n].dwFlags&WHDR_PREPARED)
waveOutUnprepareHeader(hwaveout,&header[n],sizeof(WAVEHDR));
_mm_free(buffer[n]);
}
while (waveOutClose(hwaveout)==WAVERR_STILLPLAYING) Sleep(10);
hwaveout=NULL;
}
}
static void WIN_Update(void)
{
ULONG done;
while (buffersout<NUMBUFFERS) {
done=VC_WriteBytes(buffer[nextbuffer],buffersize);
if (!done) break;
header[nextbuffer].dwBufferLength=done;
waveOutWrite(hwaveout,&header[nextbuffer],sizeof(WAVEHDR));
if (++nextbuffer>=NUMBUFFERS) nextbuffer%=NUMBUFFERS;
++buffersout;
}
}
static void WIN_PlayStop(void)
{
if (hwaveout) waveOutReset(hwaveout);
VC_PlayStop();
}
MIKMODAPI MDRIVER drv_win={
NULL,
"Windows waveform-audio",
"Windows waveform-audio driver v0.1",
0,255,
"winmm",
NULL,
NULL,
WIN_IsThere,
VC_SampleLoad,
VC_SampleUnload,
VC_SampleSpace,
VC_SampleLength,
WIN_Init,
WIN_Exit,
NULL,
VC_SetNumVoices,
VC_PlayStart,
WIN_PlayStop,
WIN_Update,
NULL,
VC_VoiceSetVolume,
VC_VoiceGetVolume,
VC_VoiceSetFrequency,
VC_VoiceGetFrequency,
VC_VoiceSetPanning,
VC_VoiceGetPanning,
VC_VoicePlay,
VC_VoiceStop,
VC_VoiceStopped,
VC_VoiceGetPosition,
VC_VoiceRealVolume
};
#else
MISSING(drv_win);
#endif
/* ex:set ts=4: */