
/* This file is part of the GMOD package */

#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/soundcard.h>

#include <sys/types.h>
#include <unistd.h>

#include "defines.h"
#include "structs.h"
#include "globals.h"

void get_message (char *, unsigned long);

static unsigned long current_time;
static unsigned long real_time;

unsigned long
get_real_time ()
{
  struct timeval tv;
  struct timezone tz =
  {0, DST_NONE};

  gettimeofday (&tv, &tz);
  return (tv.tv_sec);
}

void
timer_handler (int sig)
{
  int keypress = EOF;
  unsigned char volume;
  static int sync_ticks = 0;
  char message[80];

  signal (sig, timer_handler);

  switch (sig)
    {
    case SIGALRM:
      if (!background)
	keypress = getchar ();
      current_time++;
      break;
    case SIGTERM:
      keypress = 'q';
      break;
    case SIGUSR1:
      keypress = 'p';
      break;
    case SIGUSR2:
      keypress = 'n';
      break;
    }

  if (sync_ticks++ >= 60)
    {
      sync_ticks = 0;
      current_time = get_real_time () - real_time;
    }

  do
    {
      get_message (message, current_time);
      if ((message[0] != '\0') && (background == 0))
	printf ("%s", message);
    }
  while (message[0] != '\0');

  while (keypress != EOF)
    {
      switch (keypress)
	{
	case 'n':
	  stop_flag = STOP_NEXT;
	  dump_enabled = 0;
	  break;
	case 'p':
	  stop_flag = STOP_PREV;
	  dump_enabled = 0;
	  break;
	case 'q':
	  stop_flag = STOP_EXIT;
	  dump_enabled = 0;
	  break;
	case '+':
	  if (mixerfd != -1)
	    {
	      ioctl (mixerfd, MIXER_READ (SOUND_MIXER_SYNTH), &volume);
	      if (volume < MIXER_MAX_VOL)
		volume += 1;
	      ioctl (mixerfd, MIXER_WRITE (SOUND_MIXER_SYNTH), &volume);
	    }
	  break;
	case '-':
	  if (mixerfd != -1)
	    {
	      ioctl (mixerfd, MIXER_READ (SOUND_MIXER_SYNTH), &volume);
	      if (volume > MIXER_MIN_VOL)
		volume -= 1;
	      ioctl (mixerfd, MIXER_WRITE (SOUND_MIXER_SYNTH), &volume);
	    }
	  break;
	case '0':
	  keypress = '9' + 1;
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	case '9':
	  volume = (keypress - '0') * 10;
	  if (mixerfd != -1)
	    ioctl (mixerfd, MIXER_WRITE (SOUND_MIXER_SYNTH), &volume);
	  break;
	}

      if (!background)
	keypress = getchar ();
      else
	keypress = EOF;
    }
}

void
timer_set (int mode)
{
  struct itimerval tvalue;
  char message[80];

  if (mode == TIMER_ON)
    {
      tvalue.it_interval.tv_sec = 1;
      tvalue.it_value.tv_sec = 1;
      signal (SIGALRM, timer_handler);
      signal (SIGTERM, timer_handler);
      signal (SIGUSR1, timer_handler);
      signal (SIGUSR2, timer_handler);

      current_time = 0;
      real_time = get_real_time ();
    }
  else
    {
      tvalue.it_interval.tv_sec = 0;
      tvalue.it_value.tv_sec = 0;
      signal (SIGALRM, SIG_IGN);
      signal (SIGTERM, SIG_DFL);
      signal (SIGUSR1, SIG_DFL);
      signal (SIGUSR2, SIG_DFL);

      do
	{
	  get_message (message, 0xffffffff);
	}
      while (message[0] != '\0');
    }

  tvalue.it_interval.tv_usec = 0;
  tvalue.it_value.tv_usec = 0;

  setitimer (ITIMER_REAL, &tvalue, NULL);
}
