211 lines
4.8 KiB
C
Executable File
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: */
|