/*
 *  Copyright (c) by Jaroslav Kysela (Perex soft)
 */

#include <signal.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <ncurses.h>
#include "pmod.h"

static void signalHandler( int sgnl )
{
  int key = EOF;
  int tick;

#ifdef 0
  dprintf( "\nsignal (%i) !!!!\n", sgnl );
#endif
  signal( sgnl, signalHandler );
  switch ( sgnl ) {
    case SIGINT:
    case SIGTERM: key = 'q'; break;
    case SIGUSR1: key = 'p'; break;
    case SIGUSR2: key = 'n'; break;
  }
  if ( !background && seqfd >= 0 && timeSynchroFirst )
    {
      struct sTimeSynchro *ts;
    
      if ( ( tick = ioctl( seqfd, GUS_IOCTL_GET_TICK ) ) < 0 )
        fatal( "signal: GUS_IOCTL_GET_TICK failed" );
#ifdef 0
      dprintf( "\n> %i <\n", tick );
#endif
      if ( ( ts = timeSynchroGet( tick ) ) != NULL )
        playShowPosition( ts -> order, ts -> row );
    }
  if ( key == EOF && !background ) key = getch();
  while ( key != EOF )
    {
#ifdef 0
      dprintf( "key = %i\n", key );
#endif
      switch ( key ) {
        case 'f':
        case KEY_RIGHT:
          orderDelta++;
          break;
        case 'b':
        case KEY_LEFT:
          orderDelta--;
          break;
        case 'q':
        case KEY_END:
        case 27:
          quit = 1;
          break;
        case 'p':
        case KEY_PPAGE:
          prev = 1;
          break;
        case ' ':
        case 'n':
        case KEY_NPAGE:
          next = 1;
          break;
        case 'l':
          loop ^= 1;
          break;
        case KEY_UP:
        case '+':
          if ( mainVolume < 0 || mainVolume >= 100 ) break;	/* already maximum */
          mainVolume++;
          gusSetupVolume();
          break;
        case KEY_DOWN:
        case '-':
          if ( mainVolume <= 0 ) break;		/* already minimum */
          if ( mainVolume < 0 )
            mainVolume = 100;
           else
            mainVolume--;
          gusSetupVolume();
          break;
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9': disableChannels ^= 1 << ( key - '1' ); break;
        case '0': disableChannels ^= 1 <<  9; break;
        case '!': disableChannels ^= 1 << 10; break;
        case '@': disableChannels ^= 1 << 11; break;
        case '#': disableChannels ^= 1 << 12; break;
        case '$': disableChannels ^= 1 << 13; break;
        case '%': disableChannels ^= 1 << 14; break;
        case '^': disableChannels ^= 1 << 15; break;
        case '&': disableChannels ^= 1 << 16; break;
        case '*': disableChannels ^= 1 << 17; break;
        case '(': disableChannels ^= 1 << 18; break;
        case ')': disableChannels ^= 1 << 19; break;
        case 'e': disableChannels = 0; break;
        case 'd': disableChannels = 0xffffffff; break;
        case 'x': disableChannels ^= 0xffffffff; break;
      } 
      if ( !background ) key = getch(); else key = EOF;
    }
}

void initSignalHandlers()
{
  struct itimerval tvalue;

  signal( SIGINT, signalHandler );
  signal( SIGTERM, signalHandler );
  signal( SIGUSR1, signalHandler );
  signal( SIGUSR2, signalHandler );
  if ( !background ) 
    {
      signal( SIGALRM, signalHandler );
      tvalue.it_interval.tv_sec = 1;
      tvalue.it_value.tv_sec = 1;
      tvalue.it_interval.tv_usec = 0;
      tvalue.it_value.tv_usec = 0;
      setitimer( ITIMER_REAL, &tvalue, NULL );
    }
}

void doneSignalHandlers()
{
  struct itimerval tvalue;

  signal( SIGINT, SIG_DFL );
  signal( SIGTERM, SIG_DFL );
  signal( SIGUSR1, SIG_DFL );
  signal( SIGUSR2, SIG_DFL );
  if ( !background )
    {
      signal( SIGALRM, SIG_IGN );
      tvalue.it_interval.tv_sec = 0;
      tvalue.it_value.tv_sec = 0;
      tvalue.it_interval.tv_usec = 0;
      tvalue.it_value.tv_usec = 0;
      setitimer( ITIMER_REAL, &tvalue, NULL );
    }
}
