/* sdljoystick.c: routines for dealing with the SDL joystick
   Copyright (c) 2003-2004 Darren Salt, Fredrick Meunier, Philip Kendall

   $Id: sdljoystick.c,v 1.7 2004/06/18 21:53:22 pak21 Exp $

   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., 49 Temple Place, Suite 330, Boston, MA 02111-1307 USA

   Author contact information:

   E-mail: pak21-fuse@srcf.ucam.org
   Postal address: 15 Crescent Road, Wokingham, Berks, RG40 2DB, England

   Fred: fredm@spamcop.net
*/

#include <config.h>

#ifdef UI_SDL			/* Use this iff we're using SDL */

#if !defined USE_JOYSTICK || defined HAVE_JSW_H
/* Fake joystick, or override UI-specific handling */
#include "../uijoystick.c"

#else			/* #if !defined USE_JOYSTICK || defined HAVE_JSW_H */

#include <SDL.h>

#include "compat.h"
#include "input.h"
#include "sdljoystick.h"
#include "settings.h"
#include "ui/ui.h"
#include "ui/uijoystick.h"

static SDL_Joystick *joystick1 = NULL;
static SDL_Joystick *joystick2 = NULL;

static void do_axis( int which, Sint16 value, input_joystick_button negative,
		     input_joystick_button positive );

int
ui_joystick_init( void )
{
  int retval = SDL_NumJoysticks();

  SDL_InitSubSystem( SDL_INIT_JOYSTICK );

  if( retval >= 2 ) {

    retval = 2;

    if( ( joystick2 = SDL_JoystickOpen( 1 ) ) == NULL ) {
      ui_error( UI_ERROR_ERROR, "failed to initialise joystick 2" );
      return 0;
    }

    if( SDL_JoystickNumAxes( joystick2 ) < 2    ||
        SDL_JoystickNumButtons( joystick2 ) < 1    ) {
      ui_error( UI_ERROR_ERROR, "sorry, joystick 2 is inadequate!" );
      return 0;
    }

  }

  if( retval > 0 ) {

    if( ( joystick1 = SDL_JoystickOpen( 0 ) ) == NULL ) {
      ui_error( UI_ERROR_ERROR, "failed to initialise joystick 1" );
      return 0;
    }
 
    if( SDL_JoystickNumAxes( joystick1 ) < 2    ||
        SDL_JoystickNumButtons( joystick1 ) < 1    ) {
      ui_error( UI_ERROR_ERROR, "sorry, joystick 1 is inadequate!" );
      return 0;
    }
  }

  SDL_JoystickEventState( SDL_ENABLE );

  return retval;
}

void
ui_joystick_poll( void )
{
  /* No action needed; joysticks already handled by the SDL events
     system */
}

static void
button_action( SDL_JoyButtonEvent *buttonevent, input_event_type type )
{
  int button;
  input_event_t event;
  
  button = buttonevent->button;
  if( button > 10 ) return;	/* We support 'only' 10 fire buttons */

  event.type = type;
  event.types.joystick.which = buttonevent->which;
  event.types.joystick.button = INPUT_JOYSTICK_FIRE_1 + button;

  input_event( &event );
}

void
sdljoystick_buttonpress( SDL_JoyButtonEvent *buttonevent )
{
  button_action( buttonevent, INPUT_EVENT_JOYSTICK_PRESS );
}

void
sdljoystick_buttonrelease( SDL_JoyButtonEvent *buttonevent )
{
  button_action( buttonevent, INPUT_EVENT_JOYSTICK_RELEASE );
}

void
sdljoystick_axismove( SDL_JoyAxisEvent *axisevent )
{
  if( axisevent->axis == 0 ) {
    do_axis( axisevent->which, axisevent->value,
	     INPUT_JOYSTICK_LEFT, INPUT_JOYSTICK_RIGHT );
  } else if( axisevent->axis == 1 ) {
    do_axis( axisevent->which, axisevent->value,
	     INPUT_JOYSTICK_UP,   INPUT_JOYSTICK_DOWN  );
  }
}

static void
do_axis( int which, Sint16 value,
	 input_joystick_button negative, input_joystick_button positive )
{
  input_event_t event1, event2;

  event1.types.joystick.which = event2.types.joystick.which = which;

  event1.types.joystick.button = negative;
  event2.types.joystick.button = positive;

  if( value > 16384 ) {
    event1.type = INPUT_EVENT_JOYSTICK_RELEASE;
    event2.type = INPUT_EVENT_JOYSTICK_PRESS;
  } else if( value < -16384 ) {
    event1.type = INPUT_EVENT_JOYSTICK_PRESS;
    event2.type = INPUT_EVENT_JOYSTICK_RELEASE;
  } else {
    event1.type = INPUT_EVENT_JOYSTICK_RELEASE;
    event2.type = INPUT_EVENT_JOYSTICK_RELEASE;
  }

  input_event( &event1 );
  input_event( &event2 );
}

void
ui_joystick_end( void )
{
  if( joystick1 != NULL || joystick2 != NULL ) {

    SDL_JoystickEventState( SDL_IGNORE );
    if( joystick1 != NULL ) SDL_JoystickClose( joystick1 );
    if( joystick2 != NULL ) SDL_JoystickClose( joystick2 );
    joystick1 = NULL;
    joystick2 = NULL;

  }

  SDL_QuitSubSystem( SDL_INIT_JOYSTICK );
}

#endif			/* #if !defined USE_JOYSTICK || defined HAVE_JSW_H */

#endif			/* #ifdef UI_SDL */
