home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 February / PCO_0299.ISO / filesbbs / linux / mikmod-3.000 / mikmod-3 / mikmod-3.1.2 / drivers / drv_dart.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-07  |  6.8 KB  |  250 lines

  1. /*    MikMod sound library
  2.     (c) 1998 Miodrag Vallat and others - see file AUTHORS for complete list
  3.  
  4.     This library is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU Library General Public License as
  6.     published by the Free Software Foundation; either version 2 of
  7.     the License, or (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Library General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Library General Public
  15.     License along with this library; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19. /*==============================================================================
  20.  
  21.   $Id: drv_dart.c,v 1.11 1998/12/07 06:01:39 miod Exp $
  22.  
  23.   Mikmod driver for output on OS/2 MMPM/2 using direct audio (DART)
  24.  
  25. ==============================================================================*/
  26.  
  27. #ifdef HAVE_CONFIG_H
  28. #include "config.h"
  29. #endif
  30.  
  31. #define INCL_DOS
  32. #include <os2.h>
  33. #include <mcios2.h>
  34. #include <meerror.h>
  35. #include <os2medef.h>
  36.  
  37. #include <stdlib.h>
  38. #include <string.h>
  39.  
  40. #include <mikmod_internals.h>
  41.  
  42. /* No need to be a power of two, but must be at least 4 */
  43. #define BUFFERCOUNT 4
  44.  
  45. static    MCI_MIX_BUFFER MixBuffers[BUFFERCOUNT];
  46. static    MCI_MIXSETUP_PARMS MixSetupParms;
  47. static    MCI_BUFFER_PARMS BufferParms;
  48. static    MCI_GENERIC_PARMS GenericParms;
  49. static    ULONG DeviceID=0,BufferSize;
  50. static    int ready,lastbuffer;
  51.  
  52. /* Buffer update thread (created and called by DART) */
  53. static LONG APIENTRY OS2_Dart_UpdateBuffers(ULONG ulStatus,PMCI_MIX_BUFFER pBuffer,ULONG ulFlags)
  54. {
  55.     /* if we have finished a buffer, we're ready to play a new one */
  56.     if((ulFlags==MIX_WRITE_COMPLETE)||
  57.        ((ulFlags==(MIX_WRITE_COMPLETE|MIX_STREAM_ERROR))&&(ulStatus==ERROR_DEVICE_UNDERRUN)))
  58.         if(ready<BUFFERCOUNT) ready++;
  59.     return TRUE;
  60. }
  61.  
  62. static BOOL OS2_Dart_IsPresent(void)
  63. {
  64.     MCI_AMP_OPEN_PARMS AmpOpenParms;
  65.  
  66.     memset(&AmpOpenParms,0,sizeof(MCI_AMP_OPEN_PARMS));
  67.     AmpOpenParms.usDeviceID=0;
  68.     AmpOpenParms.pszDeviceType=(PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
  69.  
  70.     if(mciSendCommand(0,MCI_OPEN,
  71.                       MCI_WAIT|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID,
  72.                       (PVOID)&AmpOpenParms,0)!=MCIERR_SUCCESS)
  73.         return 0;
  74.  
  75.     mciSendCommand(AmpOpenParms.usDeviceID,MCI_CLOSE,MCI_WAIT,
  76.                    (PVOID)&GenericParms,0);
  77.     return 1;
  78. }
  79.  
  80. static BOOL OS2_Dart_Init(void)
  81. {
  82.     MCI_AMP_OPEN_PARMS AmpOpenParms;
  83.  
  84.     MixBuffers[0].pBuffer=NULL; /* marker */
  85.     memset(&GenericParms,0,sizeof(MCI_GENERIC_PARMS));
  86.  
  87.     /* open AMP device */
  88.     memset(&AmpOpenParms,0,sizeof(MCI_AMP_OPEN_PARMS));
  89.     AmpOpenParms.usDeviceID=0;
  90.     AmpOpenParms.pszDeviceType=(PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
  91.  
  92.     if(mciSendCommand(0,MCI_OPEN,
  93.                       MCI_WAIT|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID,
  94.                       (PVOID)&AmpOpenParms,0)!=MCIERR_SUCCESS) {
  95.         _mm_errno=MMERR_OPENING_AUDIO;
  96.         return 1;
  97.     }
  98.  
  99.     DeviceID=AmpOpenParms.usDeviceID;
  100.  
  101.     /* setup playback parameters */
  102.     memset(&MixSetupParms,0,sizeof(MCI_MIXSETUP_PARMS));
  103.     MixSetupParms.ulBitsPerSample=(md_mode&DMODE_16BITS)?16:8;
  104.     MixSetupParms.ulFormatTag=MCI_WAVE_FORMAT_PCM;
  105.     MixSetupParms.ulSamplesPerSec=md_mixfreq;
  106.     MixSetupParms.ulChannels=(md_mode&DMODE_STEREO)?2:1;
  107.     MixSetupParms.ulFormatMode=MCI_PLAY;
  108.     MixSetupParms.ulDeviceType=MCI_DEVTYPE_WAVEFORM_AUDIO;
  109.     MixSetupParms.pmixEvent=OS2_Dart_UpdateBuffers;
  110.  
  111.     if(mciSendCommand(DeviceID,MCI_MIXSETUP,
  112.                       MCI_WAIT|MCI_MIXSETUP_INIT,
  113.                       (PVOID)&MixSetupParms,0)!=MCIERR_SUCCESS) {
  114.         mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
  115.         _mm_errno=MMERR_OS2_MIXSETUP;
  116.         return 1;
  117.     }
  118.         
  119.     /* take in account the DART suggested buffer size for the fragment size
  120.        computation... */
  121.     BufferSize=MixSetupParms.ulBufferSize;
  122.  
  123.     BufferParms.ulNumBuffers=BUFFERCOUNT;
  124.     BufferParms.ulBufferSize=BufferSize;
  125.     BufferParms.pBufList=MixBuffers;
  126.  
  127.     if(mciSendCommand(DeviceID,MCI_BUFFER,
  128.                       MCI_WAIT|MCI_ALLOCATE_MEMORY,
  129.                       (PVOID)&BufferParms,0)!=MCIERR_SUCCESS) {
  130.         mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
  131.         _mm_errno=MMERR_OUT_OF_MEMORY;
  132.         return 1;
  133.     }
  134.  
  135.     if(VC_Init()) {
  136.         mciSendCommand(DeviceID,MCI_BUFFER,MCI_WAIT|MCI_DEALLOCATE_MEMORY,&BufferParms,0);
  137.         mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
  138.         return 1;
  139.     }
  140.  
  141.     return 0;
  142. }
  143.  
  144. static void OS2_Dart_Exit(void)
  145. {
  146.     VC_Exit();
  147.     if (MixBuffers[0].pBuffer) {
  148.         mciSendCommand(DeviceID,MCI_BUFFER,MCI_WAIT|MCI_DEALLOCATE_MEMORY,&BufferParms,0);
  149.         MixBuffers[0].pBuffer=NULL;
  150.     }
  151.     if (DeviceID) {
  152.         mciSendCommand(DeviceID,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
  153.         DeviceID=0;
  154.     }
  155. }
  156.  
  157. static BOOL OS2_Dart_PlayStart(void)
  158. {
  159.     int i;
  160.  
  161.     VC_PlayStart();
  162.  
  163.     /* silence buffers */
  164.     for(i=0;i<BUFFERCOUNT;i++) {
  165.         VC_SilenceBytes(MixBuffers[i].pBuffer,BufferSize);
  166.         MixBuffers[i].ulBufferLength=BufferSize;
  167.     }
  168.  
  169.     /* wake DART up - it needs at least 2 buffers to do so since the audio
  170.        stream is left open */
  171.     ready=0;lastbuffer=2;
  172.     MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,MixBuffers,2);
  173.  
  174.     return 0;
  175. }
  176.  
  177. static void OS2_Dart_Update(void)
  178. {
  179.     /* it's certainly not the best way to keep ownership of the Amp device,
  180.        but at least it works - it's even a bit aggressive... */
  181.     mciSendCommand(DeviceID,MCI_ACQUIREDEVICE,MCI_ACQUIRE_QUEUE,
  182.                    (PVOID)&GenericParms,0);
  183.  
  184.     /* play a sound buffer if ready to play */
  185.     while(ready) {
  186.         lastbuffer=(lastbuffer+1)%BUFFERCOUNT;
  187.         MixBuffers[lastbuffer].ulBufferLength=
  188.           VC_WriteBytes(MixBuffers[lastbuffer].pBuffer,BufferSize);
  189.         MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,
  190.                                 &(MixBuffers[lastbuffer]),1);
  191.         ready--;
  192.     }
  193. }
  194.  
  195. static void OS2_Dart_PlayStop(void)
  196. {
  197.     int i;
  198.  
  199.     /* play the last BUFFERCOUNT buffers */
  200.     for(i=0;i<BUFFERCOUNT;i++) {
  201.         while(!ready) DosSleep(1); /* force a yield */
  202.         OS2_Dart_Update();
  203.     }
  204.  
  205.     /* send a silence buffer tagged as finishing the playback */
  206.     while(!ready) DosSleep(1);
  207.     VC_SilenceBytes(MixBuffers[0].pBuffer,BufferSize);
  208.     MixBuffers[0].ulBufferLength=BufferSize;
  209.     MixBuffers[0].ulFlags=MIX_BUFFER_EOS;
  210.     MixSetupParms.pmixWrite(MixSetupParms.ulMixHandle,&(MixBuffers[0]),1);
  211.     while(ready<2) DosSleep(1);
  212.  
  213.     VC_PlayStop();
  214. }
  215.  
  216. static BOOL OS2_Dart_Reset(void)
  217. {
  218.     OS2_Dart_Exit();
  219.     return OS2_Dart_Init();
  220. }
  221.  
  222. MDRIVER drv_dart=
  223. {
  224.     NULL,
  225.     "Direct audio (DART)",
  226.     "OS/2 DART driver v1.0",
  227.     0,
  228.     255,
  229.     OS2_Dart_IsPresent,
  230.     VC_SampleLoad,
  231.     VC_SampleUnload,
  232.     VC_SampleSpace,
  233.     VC_SampleLength,
  234.     OS2_Dart_Init,
  235.     OS2_Dart_Exit,
  236.     OS2_Dart_Reset,
  237.     VC_SetNumVoices,
  238.     OS2_Dart_PlayStart,
  239.     OS2_Dart_PlayStop,
  240.     OS2_Dart_Update,
  241.     VC_VoiceSetVolume,
  242.     VC_VoiceSetFrequency,
  243.     VC_VoiceSetPanning,
  244.     VC_VoicePlay,
  245.     VC_VoiceStop,
  246.     VC_VoiceStopped,
  247.     VC_VoiceGetPosition,
  248.     VC_VoiceRealVolume,
  249. };
  250.