text: /*
    pygame - Python Game Library
    Copyright (C) 2000-2001  Pete Shinners
  
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.
  
    This library 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
    Library General Public License for more details.
  
    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
    Pete Shinners
    pete@shinners.org
  */
  
  #define PYGAMEAPI_JOYSTICK_INTERNAL
  #include "pygame.h"
  
  #include "pgcompat.h"
  
  #include "doc/joystick_doc.h"
  
  #define JOYSTICK_MAXSTICKS 32
  static SDL_Joystick *joystick_stickdata[JOYSTICK_MAXSTICKS] = {NULL};
  static PyTypeObject pgJoystick_Type;
  static PyObject *
  pgJoystick_New(int);
  #define pgJoystick_Check(x) ((x)->ob_type == &pgJoystick_Type)
  
  static void
  joy_autoquit(void)
  {
      int loop;
      for (loop = 0; loop < JOYSTICK_MAXSTICKS; ++loop) {
          if (joystick_stickdata[loop]) {
              SDL_JoystickClose(joystick_stickdata[loop]);
              joystick_stickdata[loop] = NULL;
          }
      }
  
      if (SDL_WasInit(SDL_INIT_JOYSTICK)) {
          SDL_JoystickEventState(SDL_ENABLE);
          SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
      }
  }
  
  static PyObject *
  joy_autoinit(PyObject *self)
  {
      if (!SDL_WasInit(SDL_INIT_JOYSTICK)) {
          if (SDL_InitSubSystem(SDL_INIT_JOYSTICK)) {
              return PyInt_FromLong(0);
          }
          SDL_JoystickEventState(SDL_ENABLE);
          pg_RegisterQuit(joy_autoquit);
      }
      return PyInt_FromLong(1);
  }
  
  static PyObject *
  quit(PyObject *self)
  {
      joy_autoquit();
      Py_RETURN_NONE;
  }
  
  static PyObject *
  init(PyObject *self)
  {
      PyObject *result;
      int istrue;
  
      result = joy_autoinit(self);
      istrue = PyObject_IsTrue(result);
      Py_DECREF(result);
      if (!istrue) {
          return RAISE(pgExc_SDLError, SDL_GetError());
      }
      Py_RETURN_NONE;
  }
  
  static PyObject *
  get_init(PyObject *self)
  {
      return PyBool_FromLong(SDL_WasInit(SDL_INIT_JOYSTICK) != 0);
  }
  
  /*joystick object funcs*/
  static void
  joy_dealloc(PyObject *self)
  {
      PyObject_DEL(self);
  }
  
  static PyObject *
  Joystick(PyObject *self, PyObject *args)
  {
      int id;
      if (!PyArg_ParseTuple(args, "i", &id)) {
          return NULL;
      }
  
      JOYSTICK_INIT_CHECK();
  
      return pgJoystick_New(id);
  }
  
  static PyObject *
  get_count(PyObject *self, PyObject *args)
  {
      JOYSTICK_INIT_CHECK();
      return PyInt_FromLong(SDL_NumJoysticks());
  }
  
  static PyObject *
  joy_init(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
  
      JOYSTICK_INIT_CHECK();
      if (!joystick_stickdata[joy_id]) {
          joystick_stickdata[joy_id] = SDL_JoystickOpen(joy_id);
          if (!joystick_stickdata[joy_id]) {
              return RAISE(pgExc_SDLError, SDL_GetError());
          }
      }
      Py_RETURN_NONE;
  }
  
  static PyObject *
  joy_quit(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
  
      JOYSTICK_INIT_CHECK();
  
      if (joystick_stickdata[joy_id]) {
          SDL_JoystickClose(joystick_stickdata[joy_id]);
          joystick_stickdata[joy_id] = NULL;
      }
      Py_RETURN_NONE;
  }
  
  static PyObject *
  joy_get_init(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      return PyBool_FromLong(joystick_stickdata[joy_id] != NULL);
  }
  
  static PyObject *
  joy_get_id(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      return PyInt_FromLong(joy_id);
  }
  
  static PyObject *
  joy_get_name(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      JOYSTICK_INIT_CHECK();
  #if IS_SDLv1
      return Text_FromLocale(SDL_JoystickName(joy_id));
  #else  /* IS_SDLv2 */
      return Text_FromUTF8(SDL_JoystickNameForIndex(joy_id));
  #endif /* IS_SDLv2 */
  }
  
  static PyObject *
  joy_get_numaxes(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
  
      return PyInt_FromLong(SDL_JoystickNumAxes(joy));
  }
  
  static PyObject *
  joy_get_axis(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
      int axis, value;
  
      if (!PyArg_ParseTuple(args, "i", &axis)) {
          return NULL;
      }
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
      if (axis < 0 || axis >= SDL_JoystickNumAxes(joy)) {
          return RAISE(pgExc_SDLError, "Invalid joystick axis");
      }
  
      value = SDL_JoystickGetAxis(joy, axis);
  #ifdef DEBUG
      /*printf("SDL_JoystickGetAxis value:%d:\n", value);*/
  #endif
  
      return PyFloat_FromDouble(value / 32768.0);
  }
  
  static PyObject *
  joy_get_numbuttons(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
  
      return PyInt_FromLong(SDL_JoystickNumButtons(joy));
  }
  
  static PyObject *
  joy_get_button(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
      int _index, value;
  
      if (!PyArg_ParseTuple(args, "i", &_index)) {
          return NULL;
      }
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
      if (_index < 0 || _index >= SDL_JoystickNumButtons(joy)) {
          return RAISE(pgExc_SDLError, "Invalid joystick button");
      }
  
      value = SDL_JoystickGetButton(joy, _index);
  #ifdef DEBUG
      /*printf("SDL_JoystickGetButton value:%d:\n", value);*/
  #endif
      return PyInt_FromLong(value);
  }
  
  static PyObject *
  joy_get_numballs(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
  
      return PyInt_FromLong(SDL_JoystickNumBalls(joy));
  }
  
  static PyObject *
  joy_get_ball(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
      int _index, dx, dy;
      int value;
  
      if (!PyArg_ParseTuple(args, "i", &_index)) {
          return NULL;
      }
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
      value = SDL_JoystickNumBalls(joy);
  #ifdef DEBUG
      /*printf("SDL_JoystickNumBalls value:%d:\n", value);*/
  #endif
      if (_index < 0 || _index >= value) {
          return RAISE(pgExc_SDLError, "Invalid joystick trackball");
      }
  
      SDL_JoystickGetBall(joy, _index, &dx, &dy);
      return Py_BuildValue("(ii)", dx, dy);
  }
  
  static PyObject *
  joy_get_numhats(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      Uint32 value;
      SDL_Joystick *joy = joystick_stickdata[joy_id];
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
  
      value = SDL_JoystickNumHats(joy);
  #ifdef DEBUG
      /*printf("SDL_JoystickNumHats value:%d:\n", value);*/
  #endif
      return PyInt_FromLong(value);
  }
  
  static PyObject *
  joy_get_hat(PyObject *self, PyObject *args)
  {
      int joy_id = pgJoystick_AsID(self);
      SDL_Joystick *joy = joystick_stickdata[joy_id];
      int _index, px, py;
      Uint32 value;
  
      if (!PyArg_ParseTuple(args, "i", &_index)) {
          return NULL;
      }
  
      JOYSTICK_INIT_CHECK();
      if (!joy) {
          return RAISE(pgExc_SDLError, "Joystick not initialized");
      }
      if (_index < 0 || _index >= SDL_JoystickNumHats(joy)) {
          return RAISE(pgExc_SDLError, "Invalid joystick hat");
      }
  
      px = py = 0;
      value = SDL_JoystickGetHat(joy, _index);
  #ifdef DEBUG
      /*printf("SDL_JoystickGetHat value:%d:\n", value);*/
  #endif
      if (value & SDL_HAT_UP) {
          py = 1;
      }
      else if (value & SDL_HAT_DOWN) {
          py = -1;
      }
      if (value & SDL_HAT_RIGHT) {
          px = 1;
      }
      else if (value & SDL_HAT_LEFT) {
          px = -1;
      }
  
      return Py_BuildValue("(ii)", px, py);
  }
  
  static PyMethodDef joy_methods[] = {
      {"init", joy_init, METH_NOARGS, DOC_JOYSTICKINIT},
      {"quit", joy_quit, METH_NOARGS, DOC_JOYSTICKQUIT},
      {"get_init", joy_get_init, METH_NOARGS, DOC_JOYSTICKGETINIT},
  
      {"get_id", joy_get_id, METH_NOARGS, DOC_JOYSTICKGETID},
      {"get_name", joy_get_name, METH_NOARGS, DOC_JOYSTICKGETNAME},
  
      {"get_numaxes", joy_get_numaxes, METH_NOARGS,
       DOC_JOYSTICKGETNUMAXES},
      {"get_axis", joy_get_axis, METH_VARARGS, DOC_JOYSTICKGETAXIS},
      {"get_numbuttons", joy_get_numbuttons, METH_NOARGS,
       DOC_JOYSTICKGETNUMBUTTONS},
      {"get_button", joy_get_button, METH_VARARGS, DOC_JOYSTICKGETBUTTON},
      {"get_numballs", joy_get_numballs, METH_NOARGS,
       DOC_JOYSTICKGETNUMBALLS},
      {"get_ball", joy_get_ball, METH_VARARGS, DOC_JOYSTICKGETBALL},
      {"get_numhats", joy_get_numhats, METH_NOARGS,
       DOC_JOYSTICKGETNUMHATS},
      {"get_hat", joy_get_hat, METH_VARARGS, DOC_JOYSTICKGETHAT},
  
      {NULL, NULL, 0, NULL}};
  
  static PyTypeObject pgJoystick_Type = {
      TYPE_HEAD(NULL, 0) "Joystick", /* name */
      sizeof(pgJoystickObject),      /* basic size */
      0,                             /* itemsize */
      joy_dealloc,                   /* dealloc */
      0,                             /* print */
      0,                             /* getattr */
      0,                             /* setattr */
      0,                             /* compare */
      0,                             /* repr */
      0,                             /* as_number */
      0,                             /* as_sequence */
      0,                             /* as_mapping */
      0,                             /* hash */
      0,                             /* call */
      0,                             /* str */
      0,                             /* tp_getattro */
      0,                             /* tp_setattro */
      0,                             /* tp_as_buffer */
      0,                             /* flags */
      DOC_PYGAMEJOYSTICKJOYSTICK,    /* Documentation string */
      0,                             /* tp_traverse */
      0,                             /* tp_clear */
      0,                             /* tp_richcompare */
      0,                             /* tp_weaklistoffset */
      0,                             /* tp_iter */
      0,                             /* tp_iternext */
      joy_methods,                   /* tp_methods */
      0,                             /* tp_members */
      0,                             /* tp_getset */
      0,                             /* tp_base */
      0,                             /* tp_dict */
      0,                             /* tp_descr_get */
      0,                             /* tp_descr_set */
      0,                             /* tp_dictoffset */
      0,                             /* tp_init */
      0,                             /* tp_alloc */
      0,                             /* tp_new */
  };
  
  static PyObject *
  pgJoystick_New(int id)
  {
      pgJoystickObject *joy;
  
      if (id < 0 || id >= JOYSTICK_MAXSTICKS || id >= SDL_NumJoysticks()) {
          return RAISE(pgExc_SDLError, "Invalid joystick device number");
      }
  
      joy = PyObject_NEW(pgJoystickObject, &pgJoystick_Type);
      if (!joy) {
          return NULL;
      }
  
      joy->id = id;
  
      return (PyObject *)joy;
  }
  
  static PyMethodDef _joystick_methods[] = {
      {"__PYGAMEinit__", (PyCFunction)joy_autoinit, METH_NOARGS,
       "auto initialize function for joystick"},
      {"init", (PyCFunction)init, METH_NOARGS, DOC_PYGAMEJOYSTICKINIT},
      {"quit", (PyCFunction)quit, METH_NOARGS, DOC_PYGAMEJOYSTICKQUIT},
      {"get_init", (PyCFunction)get_init, METH_NOARGS,
       DOC_PYGAMEJOYSTICKGETINIT},
      {"get_count", (PyCFunction)get_count, METH_NOARGS,
       DOC_PYGAMEJOYSTICKGETCOUNT},
      {"Joystick", Joystick, METH_VARARGS, DOC_PYGAMEJOYSTICKJOYSTICK},
      {NULL, NULL, 0, NULL}};
  
  MODINIT_DEFINE(joystick)
  {
      PyObject *module, *dict, *apiobj;
      int ecode;
      static void *c_api[PYGAMEAPI_JOYSTICK_NUMSLOTS];
  
  #if PY3
      static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
                                           "joystick",
                                           DOC_PYGAMEJOYSTICK,
                                           -1,
                                           _joystick_methods,
                                           NULL,
                                           NULL,
                                           NULL,
                                           NULL};
  #endif
  
      /* imported needed apis; Do this first so if there is an error
         the module is not loaded.
      */
      import_pygame_base();
      if (PyErr_Occurred()) {
          MODINIT_ERROR;
      }
  
      /* type preparation */
      if (PyType_Ready(&pgJoystick_Type) == -1) {
          MODINIT_ERROR;
      }
  
      /* create the module */
  #if PY3
      module = PyModule_Create(&_module);
  #else
      module = Py_InitModule3("joystick", _joystick_methods, DOC_PYGAMEJOYSTICK);
  #endif
      if (module == NULL) {
          MODINIT_ERROR;
      }
      dict = PyModule_GetDict(module);
  
      if (PyDict_SetItemString(dict, "JoystickType",
                               (PyObject *)&pgJoystick_Type) == -1) {
          DECREF_MOD(module);
          MODINIT_ERROR;
      }
  
      /* export the c api */
      c_api[0] = &pgJoystick_Type;
      c_api[1] = pgJoystick_New;
      apiobj = encapsulate_api(c_api, "joystick");
      if (apiobj == NULL) {
          DECREF_MOD(module);
          MODINIT_ERROR;
      }
      ecode = PyDict_SetItemString(dict, PYGAMEAPI_LOCAL_ENTRY, apiobj);
      Py_DECREF(apiobj);
      if (ecode == -1) {
          DECREF_MOD(module);
          MODINIT_ERROR;
      }
      MODINIT_RETURN(module);
  }
  