/*
	GIER w32 sound interface

	(C) Copyright 2001 by Mogens Kjaer


   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include "GIER.h"
#include "common.h"
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>

extern int sound_update_interval;
extern int debug;
static HWAVEOUT hwo;
/* don't make the buffer too large, else the sound would be behind */
#define BUFFERSIZE 2048
#define NBUFFERS 3
extern int interface_check_interval;
static int buffersize=0, nbuffers=0;
static char **sbuffers;
static WAVEHDR *whdr;
static int ibuffer,ipnt;
void w32_sound_close();

#ifdef PANIC1
static void sound_debug(char *txt,int value)
{
  FILE *fh;
  return;
  fh = fopen("sound.debug", "a");
  fprintf(fh, "%s %d\n", txt, value);
  fclose(fh);
}
#endif

int w32_sound_init()
{
  int ndev;
  int i;
  MMRESULT status;
  WAVEFORMATEX wfx;
  FILE *fh;

  /* sound_debug("init",1); */
  w32_sound_close();
  /* sound_debug("init",2); */

  /* Try to read setup file: */

  nbuffers = NBUFFERS;
  buffersize = BUFFERSIZE;

  ndev=waveOutGetNumDevs();
  if(debug&DEBUGsound) fprintf(debug_fh, "No. of devices: %d\n", ndev);
  if(ndev==0) return 0;

  wfx.wFormatTag = WAVE_FORMAT_PCM;
  wfx.nChannels = 1;
  wfx.nSamplesPerSec = 44100;
  wfx.nAvgBytesPerSec = 44100;
  wfx.wBitsPerSample = 8;
  wfx.nBlockAlign = (wfx.wBitsPerSample*wfx.nChannels)/8;
  wfx.cbSize = 0;

  /* sound_debug("init",3); */
  status=waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL|WAVE_ALLOWSYNC);
  if(debug&DEBUGsound) fprintf(debug_fh, "waveOutOpen result: %d\n", status);
  if(status != MMSYSERR_NOERROR) return 0;
  sound_update_interval = gier_clock/wfx.nSamplesPerSec;

  /*
  	Allocate buffers
  */
  sbuffers = (char **) malloc(sizeof(*sbuffers)*nbuffers);
  whdr = (WAVEHDR *) malloc(sizeof(*whdr)*nbuffers);
  /* sound_debug("init",4); */
  for(i=0; i<nbuffers; i++)
  {
    sbuffers[i] = (char *) malloc(buffersize);
    whdr[i].lpData = sbuffers[i];
    whdr[i].dwBufferLength = buffersize;
    whdr[i].dwFlags = WHDR_DONE;
    whdr[i].dwLoops = 0;
    waveOutPrepareHeader(hwo, &whdr[i], sizeof(whdr[i]));
    if(debug&DEBUGsound) fprintf(debug_fh, "WHDR_DONE[%d]: %s\n", i,whdr[i].dwFlags&WHDR_DONE?"true":"false");
    whdr[i].dwFlags |= WHDR_DONE;
  }
  ibuffer = 0;
  ipnt = 0;
  /* sound_debug("init",5); */
  return 1;
}

static void w32_sound_flush()
{
  int iwait;
  if(ipnt>0)
  {
    whdr[ibuffer].dwBufferLength = ipnt;
    waveOutWrite(hwo, &whdr[ibuffer], sizeof(whdr[ibuffer]));
    ibuffer++;
    if(ibuffer>=nbuffers) ibuffer=0;
    iwait=0;
    for(iwait=0; !(whdr[ibuffer].dwFlags&WHDR_DONE); iwait++) Sleep(0);
    ipnt=0;
  }
}

void w32_sound_close()
{
  int i,iwait;
  w32_sound_flush();
  if(nbuffers>0)
  {
    for(i=0; i<nbuffers; i++)
    {
      /* sound_debug("close",2); */
      for(iwait=0; !(whdr[i].dwFlags&WHDR_DONE); iwait++) Sleep(0);
      waveOutUnprepareHeader(hwo, &whdr[i], sizeof(whdr[i]));
      free((char *) sbuffers[i]);
    }
    waveOutReset(hwo);
    waveOutClose(hwo);
    nbuffers=0;
  }
  /* sound_debug("close",3); */
}

void sound_update(int value)
{
  /* sound_debug("update",1); */
  sbuffers[ibuffer][ipnt++] = value?0:127;
  if(ipnt >= buffersize)
  {
    w32_sound_flush();
  }
}

void sound_sync()
{
  w32_sound_flush();
  waveOutReset(hwo);
}

