/*
 * static char *rcsid_sound_c =
 *   "$Id: sounds.c,v 1.13 1998/02/08 03:15:24 master Exp $";
 */

/* Send bug reports to Raphael Quinet (quinet@montefiore.ulg.ac.be) */

#include <global.h>
#include <sproto.h>
#include <sounds.h>

int volume_table[NROF_SOUNDS];

/* This is only used for new client/server sound.  If the sound source
 * on the map is farther away than this, we don't sent it to the client.
 */
#define MAX_SOUND_DISTANCE 10

/* Initializes the sound information.  Setup is only currently needed for
 * rplay stuff - new client server sound stuff doesn't care about this.
 */
void setup_sounds()
{
#ifdef RPLAY_SOUND
  char  buf[MAX_BUF], name_buf[MAX_BUF];
  FILE *fp;
  int	num_sounds = 0, volume;

  sprintf(name_buf, "%s/%s", settings.libdir, SOUNDS_LIST);
  LOG(llevDebug, "Reading sounds from %s...",name_buf);
  fp = fopen(name_buf, "r");
  if (fp == NULL)
    {
      LOG(llevError, "Could not open file '%s'.\n", name_buf);
      return;
    }
 
  while(fgets(buf, sizeof(buf), fp) != NULL)
    {
      switch(buf[0])
	{
	case '#':
	case '\n':
	case '\0':
	case ' ':
	case '\t':
	  continue;
	}
      if (sscanf(buf, "%s %d", name_buf, &volume) < 2)
	volume = -1;
      if (num_sounds >= NROF_SOUNDS)
	{
	  LOG(llevError, "Too many sounds in file (max = %d).\n", NROF_SOUNDS);
	  break;
	}
#if 0
      LOG(llevDebug, "  Loading sound %d = '%s', volume = %d.\n", num_sounds,
	  name_buf, volume);
#endif
      if (volume > 255)
	{
	  LOG(llevError, "Invalid sound volume : %d (max = 255).\n",
	      volume);
	  volume = 255;
	}
      else
	if (volume > 0)
	  volume += 27;
      sound_table[num_sounds] = rplay_create(RPLAY_PLAY);
      if (sound_table[num_sounds] == NULL)
	{
	  LOG(llevError, "Error in rplay_create.  Out of memory ?\n");
	  return;
	}
      volume_table[num_sounds] = volume;
      if (rplay_set(sound_table[num_sounds], RPLAY_APPEND,
		    RPLAY_SOUND, name_buf,
		    RPLAY_VOLUME, volume,
		    NULL) < 0)
	{
	  LOG(llevError, "Error in rplay_set for sound '%s'.\n", name_buf);
	  return;
	}
      num_sounds++;
    }
  LOG(llevDebug, "done.\n");
  fclose(fp);
#endif
}


/* Initializes the sound stuff for a particular player.  Once again, only
 * needed for rplay stuff - newcs stuff doesn't need this.
 */
int init_disp_sound(char *player_disp)
{
#ifdef RPLAY_SOUND
  char *p;
  int   rplay_fd;
  char  hostname[MAX_BUF];

  LOG(llevDebug, "Init display (%s) with sounds...", player_disp);
  strcpy(hostname, player_disp);
  if ((p = strrchr(hostname, ':')) != NULL)
    *p = '\0';
  if (*hostname == '\0')
    {
      gethostname(hostname, sizeof(hostname));
      LOG(llevDebug, " (hostname = %s) ", hostname);
    }

  rplay_fd = rplay_open(hostname);

  if (rplay_fd < 0)
    {
      LOG(llevError, "Could not open socket for sounds on '%s'.\n", hostname);
      return 0;
    }

  LOG(llevDebug, "done.\n");
  return rplay_fd;
#else
  return 0;
#endif
}


/* Plays a particular sound via rplay.  Once again, only needed for
 * rplay people - newcs uses something different.
 */

void play_sound(player *pl, int sound_num, int volume)
{
#ifdef RPLAY_SOUND
  if (volume > pl->play_count * 8)
    pl->play_count = volume / 8 + 2;
  else
    {
#if 0
      LOG(llevDebug, "Sound %d not played (%d <= %d).\n", sound_num, volume, pl->play_count * 8);
#endif
      return;
    }
#if 0
      LOG(llevDebug, "Playing sound %d (%d > %d).\n", sound_num, volume, pl->play_count * 8);
#endif
  rplay_set(sound_table[sound_num],
	    RPLAY_CHANGE, 0, RPLAY_VOLUME, volume,
	    NULL);
  rplay(pl->rplay_fd, sound_table[sound_num]);
#endif
}


void play_sound_player_only(player *pl, int sound_num)
{
    if (pl->eric_server) {
	esrv_play_sound(pl->ob, sound_num, 0, 0);
	return;
    }
#ifdef RPLAY_SOUND
  if ((sound_num >= NROF_SOUNDS) || (sound_table[sound_num] == NULL))
    {
      LOG(llevDebug, "Sound %d not available.\n", sound_num);
      return;
    }
  if ((pl->rplay_fd > 0) && (volume_table[sound_num] > 0))
    play_sound(pl, sound_num, volume_table[sound_num]);
#endif
}


#define POW2(x) ((x) * (x))

/* Plays some sound on map at x,y.  */
void play_sound_map(mapstruct *map, int x, int y, int sound_num)
{
    player *pl;
#ifdef RPLAY_SOUND
    int volume;
#endif

    if (sound_num >= NROF_SOUNDS) {
	LOG(llevError,"Tried to play an invalid sound num: %d\n", sound_num);
	return;
    }
#ifdef RPLAY_SOUND
    if (sound_table[sound_num] == NULL)
    {
	LOG(llevDebug, "Sound %d not available.\n", sound_num);
	return;
    }
#endif

    for (pl = first_player; pl; pl = pl->next) {
	if (pl->ob->map == map) {
	    int distance=isqrt(POW2(pl->ob->x - x) + POW2(pl->ob->y - y));

	    if (pl->eric_server && distance<=MAX_SOUND_DISTANCE) {
		esrv_play_sound(pl->ob, sound_num, x-pl->ob->x, y-pl->ob->y);
	    }
#ifdef RPLAY_SOUND
	    if ((pl->rplay_fd > 0) &&
		((volume = volume_table[sound_num] -  8 * isqrt(distance)) > 0))
		    play_sound(pl, sound_num, volume);
#endif
	}
    }
}
