home *** CD-ROM | disk | FTP | other *** search
- /* MikMod sound library
- (c) 1998 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /*==============================================================================
-
- $Id: drv_os2s.c,v 1.10 1998/12/07 06:01:44 miod Exp $
-
- Mikmod driver for output on OS/2 using MMPM/2 MCI interface
-
- ==============================================================================*/
-
- /*
-
- Written by Stefan Tibus <Stefan.Tibus@ThePentagon.com>
-
- */
-
- #define INCL_DOS
- #define INCL_32
- #include <os2.h>
- #include <mcios2.h>
- #include <stdlib.h>
-
- #include <mikmod_internals.h>
-
- /* global variables */
- static MCI_OPEN_PARMS mciOpenParms;
- static MCI_GENERIC_PARMS mciGenericParms;
- static MCI_PLAY_PARMS mciPlayParms;
- static MCI_WAVE_SET_PARMS mciWaveSetParms;
- static ULONG ulrc;
- static PVOID pBuffer=NULL;
- static TID tidUpdateBuffer=0;
- static INT iNext;
- static HEV hevPlay=0, hevUpdateBuffer=0; /* semaphore handles */
- static HTIMER htimerUpdateBuffer=0;
-
- /* playlist-structure */
- typedef struct {
- ULONG ulCommand;
- ULONG ulOperand1;
- ULONG ulOperand2;
- ULONG ulOperand3;
- } PLAYLISTSTRUCTURE;
-
- static PLAYLISTSTRUCTURE playList[3];
-
- /* size of each buffer */
- #define FRAGSIZE 32768
- /* buffer count */
- #define UPDATES 2
- /* total buffer size */
- #define BUFFERSIZE (FRAGSIZE*UPDATES)
-
- /* thread handling buffer-updates */
- static VOID APIENTRY OS2_Small_UpdateBufferThread(ULONG ul)
- {
- ULONG ulPostCt; /* times a semaphor has been posted */
-
- while(1) {
- /* wait for play */
- DosWaitEventSem(hevPlay, SEM_INDEFINITE_WAIT);
- /* wait for update */
- DosWaitEventSem(hevUpdateBuffer, SEM_INDEFINITE_WAIT);
- /* reset semaphore */
- DosResetEventSem(hevUpdateBuffer, &ulPostCt);
-
- /* look which buffer to update */
- if (playList[0].ulOperand3>0) {
- /* first buffer is playing, update the second */
- if (iNext==1) {
- if (!Player_Paused())
- playList[1].ulOperand2=VC_WriteBytes((SBYTE*)playList[1].ulOperand1,playList[1].ulOperand2);
- else
- VC_SilenceBytes((SBYTE*)playList[1].ulOperand1,playList[1].ulOperand2);
- playList[1].ulOperand3=0;
- iNext=0;
- }
- }
- if (playList[1].ulOperand3>0) {
- /* second buffer is playing, update the first */
- if (iNext==0) {
- if (!Player_Paused())
- playList[0].ulOperand2=VC_WriteBytes((SBYTE*)playList[0].ulOperand1,playList[0].ulOperand2);
- else
- VC_SilenceBytes((SBYTE*)playList[0].ulOperand1,playList[0].ulOperand2);
- playList[0].ulOperand3=0;
- iNext=1;
- }
- }
- }
- }
-
- /* checks for availability of an OS/2 MCI-WAVEAUDIO-device */
- static BOOL OS2_Small_IsPresent(void)
- {
- mciOpenParms.hwndCallback=(HWND) NULL;
- mciOpenParms.usDeviceID=(USHORT) NULL;
- mciOpenParms.pszDeviceType=(PSZ) MCI_DEVTYPE_WAVEFORM_AUDIO;
- mciOpenParms.pszElementName=(PSZ) NULL;
-
- /* try to open WAVEAUDIO-device */
- ulrc=mciSendCommand(0,MCI_OPEN,MCI_WAIT|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID,
- (PVOID)&mciOpenParms,0);
-
- if (ulrc)
- return 0;
- else {
- mciGenericParms.hwndCallback=(HWND) NULL;
- mciSendCommand(mciOpenParms.usDeviceID,MCI_CLOSE,MCI_WAIT,
- (PVOID)&mciGenericParms, 0);
- return 1;
- }
- }
-
- BOOL OS2_Small_Init(VOID)
- {
- ULONG ulInterval;
- ULONG ulPostCt; /* times a semaphor has been posted */
-
- mciOpenParms.usDeviceID=0;
-
- /* allocate (commited) memory */
- pBuffer=NULL;
- DosAllocMem(&pBuffer,BUFFERSIZE,PAG_READ|PAG_WRITE|PAG_COMMIT);
- if (!pBuffer) {
- _mm_errno=MMERR_OUT_OF_MEMORY;
- return 1;
- }
-
- /* create playlist */
- playList[0].ulCommand=DATA_OPERATION; /* play data */
- playList[0].ulOperand1=(ULONG)pBuffer; /* buffer */
- playList[0].ulOperand2=(ULONG)FRAGSIZE; /* size */
- playList[0].ulOperand3=0; /* offset */
-
- playList[1].ulCommand=DATA_OPERATION;
- playList[1].ulOperand1=(ULONG)pBuffer+(ULONG)FRAGSIZE;
- playList[1].ulOperand2=(ULONG)FRAGSIZE;
- playList[1].ulOperand3=0;
-
- playList[2].ulCommand=BRANCH_OPERATION; /* jump */
- playList[2].ulOperand1=0;
- playList[2].ulOperand2=0; /* destination */
- playList[2].ulOperand3=0;
-
- mciOpenParms.hwndCallback=(HWND) NULL;
- mciOpenParms.pszDeviceType=(PSZ) MCI_DEVTYPE_WAVEFORM_AUDIO;
- mciOpenParms.pszElementName=(PSZ) &playList;
-
- /* open WAVEAUDIO-device */
- ulrc=mciSendCommand(0,MCI_OPEN,MCI_WAIT|MCI_OPEN_TYPE_ID|MCI_OPEN_PLAYLIST,
- (PVOID)&mciOpenParms,0);
- if (ulrc) {
- _mm_errno=MMERR_OPENING_AUDIO;
- return 1;
- }
-
- mciWaveSetParms.hwndCallback=(HWND) NULL;
- mciWaveSetParms.ulSamplesPerSec=md_mixfreq;
- mciWaveSetParms.usBitsPerSample=(md_mode&DMODE_16BITS)?16:8;
- mciWaveSetParms.usChannels=(md_mode&DMODE_STEREO)?2:1;
- mciWaveSetParms.ulAudio=MCI_SET_AUDIO_ALL;
-
- /* set play-parameters */
- ulrc=mciSendCommand(mciOpenParms.usDeviceID,MCI_SET,
- MCI_WAIT|MCI_WAVE_SET_SAMPLESPERSEC|
- MCI_WAVE_SET_BITSPERSAMPLE|MCI_WAVE_SET_CHANNELS,
- (PVOID)&mciWaveSetParms,0);
- if (ulrc) {
- _mm_errno=MMERR_OS2_MIXSETUP;
- return 1;
- }
-
- if (VC_Init()) return 1;
-
- /* setup semaphore for playing */
- ulrc=DosCreateEventSem("\\SEM32\\libMikMod\\Play",&hevPlay,DC_SEM_SHARED,
- FALSE);
- if (ulrc) {
- _mm_errno=MMERR_OS2_SEMAPHORE;
- return 1;
- }
- /* reset semaphore */
- DosResetEventSem(hevPlay, &ulPostCt);
-
- /* setup semaphore for buffer-updates */
- ulrc=DosCreateEventSem("\\SEM32\\libMikMod\\UpdateBuffer",&hevUpdateBuffer,
- DC_SEM_SHARED, FALSE);
- if (ulrc) {
- _mm_errno=MMERR_OS2_SEMAPHORE;
- return 1;
- }
- /* reset semaphore */
- DosResetEventSem(hevUpdateBuffer, &ulPostCt);
-
- /* setup timer for buffer-updates */
- /* calculate interval in ms (2 possible updates while playing 1 block) */
- ulInterval=1000L*FRAGSIZE/mciWaveSetParms.usChannels/
- (mciWaveSetParms.usBitsPerSample/8)/
- mciWaveSetParms.ulSamplesPerSec/UPDATES;
- ulrc=DosStartTimer(ulInterval,(HSEM)hevUpdateBuffer,&htimerUpdateBuffer);
- if (ulrc) {
- _mm_errno=MMERR_OS2_TIMER;
- return 1;
- }
-
- // create thread for buffer-updates
- ulrc=DosCreateThread(&tidUpdateBuffer,&OS2_Small_UpdateBufferThread,0,
- CREATE_READY|STACK_SPARSE,4096);
- if (ulrc) {
- _mm_errno=MMERR_OS2_THREAD;
- return 1;
- }
-
- return 0;
- }
-
- static VOID OS2_Small_Exit(VOID)
- {
- if(tidUpdateBuffer) {
- DosKillThread(tidUpdateBuffer);
- tidUpdateBuffer=0;
- }
- if(htimerUpdateBuffer) {
- DosStopTimer(htimerUpdateBuffer);
- htimerUpdateBuffer=0;
- }
- if(hevUpdateBuffer) {
- DosCloseEventSem(hevUpdateBuffer);
- hevUpdateBuffer=0;
- }
- if(hevPlay) {
- DosCloseEventSem(hevPlay);
- hevPlay=0;
- }
- VC_Exit();
- if(mciOpenParms.usDeviceID) {
- mciGenericParms.hwndCallback=(HWND) NULL;
- mciSendCommand(mciOpenParms.usDeviceID,MCI_CLOSE,MCI_WAIT,
- (PVOID)&mciGenericParms,0);
- mciOpenParms.usDeviceID=0;
- }
- if(pBuffer) {
- DosFreeMem(pBuffer);
- pBuffer=NULL;
- }
- }
-
- static BOOL OS2_Small_PlayStart(VOID)
- {
- VC_SilenceBytes((SBYTE*)pBuffer,BUFFERSIZE);
- VC_PlayStart();
-
- /* signal update of 1st. block (as soon as 2nd. plays) */
- iNext=0;
- playList[1].ulOperand3=0;
- playList[0].ulOperand3=0;
-
- /* signal play */
- DosPostEventSem(hevPlay);
-
- mciPlayParms.hwndCallback=(HWND) NULL;
- mciPlayParms.ulFrom=0;
- mciPlayParms.ulTo=0;
-
- /* no MCI_WAIT here, because we have to continue in our program */
- ulrc=mciSendCommand(mciOpenParms.usDeviceID,MCI_PLAY,MCI_FROM,
- &mciPlayParms,0);
- if (ulrc) {
- _mm_errno=MMERR_OS2_MIXSETUP;
- return 1;
- }
- return 0;
- }
-
- static VOID OS2_Small_PlayStop(VOID)
- {
- ULONG ulPostCt; /* times a semaphore has been posted */
-
- mciGenericParms.hwndCallback=(HWND) NULL;
- ulrc=mciSendCommand(mciOpenParms.usDeviceID,MCI_STOP,MCI_WAIT,
- &mciGenericParms,0);
- DosResetEventSem(hevPlay, &ulPostCt);
-
- VC_PlayStop();
- }
-
- static VOID OS2_Small_Update(VOID)
- {
- /* does nothing since buffer is updated in the background */
- return;
- }
-
- static BOOL OS2_Small_Reset(VOID)
- {
- OS2_Small_Exit();
- return OS2_Small_Init();
- }
-
- MDRIVER drv_os2s=
- {
- NULL,
- "OS/2 small buffer",
- "OS/2 MMPM/2 MCI driver (64kB buffer) v1.0",
- 0,
- 255,
- OS2_Small_IsPresent,
- VC_SampleLoad,
- VC_SampleUnload,
- VC_SampleSpace,
- VC_SampleLength,
- OS2_Small_Init,
- OS2_Small_Exit,
- OS2_Small_Reset,
- VC_SetNumVoices,
- OS2_Small_PlayStart,
- OS2_Small_PlayStop,
- OS2_Small_Update,
- VC_VoiceSetVolume,
- VC_VoiceSetFrequency,
- VC_VoiceSetPanning,
- VC_VoicePlay,
- VC_VoiceStop,
- VC_VoiceStopped,
- VC_VoiceGetPosition,
- VC_VoiceRealVolume,
- };
-