Re: [AD] Problems with gamepad on MacOS X and general thoughts

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


Drat! Yes, I had other changes (SDL-style GUIDs for joysticks) and I forgot about them. Here's another version of patch, this is created from a fresh copy of repository. I'm sorry, I'm just not used to contributing to others' projects, and not very proficient with Git either, which leads to some confusion (always worked with SVN).

24.03.2015 23:37, Trent Gamblin пишет:
The patch doesn't apply cleanly. The part about "Fill in
ALLEGRO_JOYSTICK..." where you removed a dozen or so lines fails. Your
patched original looks different than what I have in Allegro git. Did you
apply over some existing changes?

-----Original Message-----
From: Max Savenkov [mailto:max.savenkov@xxxxxxxxxx]
Sent: March 24, 2015 1:51 PM
To: alleg-developers@xxxxxxxxxx
Subject: Re: [AD] Problems with gamepad on MacOS X and general thoughts

OK, here's the patch for hidjoy.m. I only patched the 10.5+ version.

It fixes my problem where there were more Z-axes than X-axes, and the number
of sticks was wrong, and also adds support for "Hatswitch", which represents
D-pad on my gamepad. I could find no documentation on the way Hatswitch
reports values, but from looking at other peoples' code, I decided to just
hard-code 8 directions (Apple documentation for working with HID devices is
lacking a lot of details).


------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the
conversation now. http://goparallel.sourceforge.net/

 src/macosx/hidjoy.m | 215 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 133 insertions(+), 82 deletions(-)

diff --git a/src/macosx/hidjoy.m b/src/macosx/hidjoy.m
index c329447..69cb721 100644
--- a/src/macosx/hidjoy.m
+++ b/src/macosx/hidjoy.m
@@ -52,12 +52,12 @@ typedef enum {
 
 typedef struct {
    ALLEGRO_JOYSTICK parent;
-   int num_buttons;
-   int num_x_axes;
-   int num_y_axes;
-   int num_z_axes;
    IOHIDElementRef buttons[_AL_MAX_JOYSTICK_BUTTONS];
    IOHIDElementRef axes[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
+   IOHIDElementRef dpad;
+   int dpad_stick;
+   int dpad_axis_vert;
+   int dpad_axis_horiz;
    long min[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
    long max[_AL_MAX_JOYSTICK_STICKS][_AL_MAX_JOYSTICK_AXES];
    CONFIG_STATE cfg_state;
@@ -169,10 +169,27 @@ static void joy_null(ALLEGRO_JOYSTICK_OSX *joy)
    }
 }
 
+static void add_axis(ALLEGRO_JOYSTICK_OSX *joy, int stick_index, int axis_index, int min, int max, char *name, IOHIDElementRef elem)
+{
+   if ( axis_index >= _AL_MAX_JOYSTICK_AXES )
+      return;
+   
+   joy->min[stick_index][axis_index] = min;
+   joy->max[stick_index][axis_index] = max;
+   
+   joy->parent.info.stick[stick_index].axis[axis_index].name = name;
+   joy->parent.info.stick[stick_index].num_axes++;
+   joy->axes[stick_index][axis_index] = elem;
+}
+
 static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
 {
+
+    
    int i;
    char default_name[100];
+   int stick_class = -1;
+   int axis_index = 0;
            
    joy_null(joy);
 
@@ -181,58 +198,95 @@ static void add_elements(CFArrayRef elements, ALLEGRO_JOYSTICK_OSX *joy)
          elements,
          i
       );
+       
       int usage = IOHIDElementGetUsage(elem);
       if (IOHIDElementGetType(elem) == kIOHIDElementTypeInput_Button) {
          if (usage >= 0 && usage < _AL_MAX_JOYSTICK_BUTTONS &&
             !joy->buttons[usage-1]) {
             joy->buttons[usage-1] = elem;
             sprintf(default_name, "Button %d", usage-1);
-	    const char *name = get_element_name(elem, default_name);
-	    char *str = al_malloc(strlen(name)+1);
-	    strcpy(str, name);
+            const char *name = get_element_name(elem, default_name);
+            char *str = al_malloc(strlen(name)+1);
+            strcpy(str, name);
             joy->parent.info.button[usage-1].name = str;
-            joy->num_buttons++;
+            joy->parent.info.num_buttons++;
          }
       }
       else if (
          IOHIDElementGetType(elem) == kIOHIDElementTypeInput_Misc) {
          long min = IOHIDElementGetLogicalMin(elem);
          long max = IOHIDElementGetLogicalMax(elem);
-         if ((usage == kHIDUsage_GD_X ||
-            usage == kHIDUsage_GD_Rx) &&
-            joy->num_x_axes < _AL_MAX_JOYSTICK_STICKS) {
-            joy->min[joy->num_x_axes][0] = min;
-            joy->max[joy->num_x_axes][0] = max;
-            sprintf(default_name, "Axis 0");
-	    const char *name = get_element_name(elem, default_name);
-	    char *str = al_malloc(strlen(name)+1);
-	    strcpy(str, name);
-            joy->parent.info.stick[joy->num_x_axes].axis[0].name = str;
-            joy->axes[joy->num_x_axes++][0] = elem;
+         int new_stick_class = -1;
+         int stick_index = joy->parent.info.num_sticks - 1;
+         
+         switch( usage )
+         {
+            case kHIDUsage_GD_X:
+            case kHIDUsage_GD_Y:
+            case kHIDUsage_GD_Z:
+               new_stick_class = 1;
+               break;
+               
+            case kHIDUsage_GD_Rx:
+            case kHIDUsage_GD_Ry:
+            case kHIDUsage_GD_Rz:
+               new_stick_class = 2;
+               break;
+               
+            case kHIDUsage_GD_Hatswitch:
+               new_stick_class = 3;
+               break;
+         }
+         
+         if ( new_stick_class < 0 )
+            continue;
+         
+         if ( stick_class != new_stick_class ) {
+            if ( joy->parent.info.num_sticks >= _AL_MAX_JOYSTICK_STICKS-1 )
+               break;
+            
+            joy->parent.info.num_sticks++;
+            
+            stick_index++;
+            axis_index = 0;
+            
+            stick_class = new_stick_class;
+            
+            char *buf = al_malloc(20);
+            sprintf(buf, "Stick %d", stick_index);
+            joy->parent.info.stick[stick_index].name = buf;
          }
-         else if ((usage == kHIDUsage_GD_Y ||
-            usage == kHIDUsage_GD_Ry) &&
-            joy->num_x_axes < _AL_MAX_JOYSTICK_STICKS) {
-            joy->min[joy->num_y_axes][1] = min;
-            joy->max[joy->num_y_axes][1] = max;
-            sprintf(default_name, "Axis 1");
-	    const char *name = get_element_name(elem, default_name);
-	    char *str = al_malloc(strlen(name)+1);
-	    strcpy(str, name);
-            joy->parent.info.stick[joy->num_y_axes].axis[1].name = str;
-            joy->axes[joy->num_y_axes++][1] = elem;
+         else
+            axis_index++;
+         
+         if (stick_class == 3)
+         {
+            joy->dpad_stick = stick_index;
+            joy->dpad = elem;
+            
+            joy->dpad_axis_horiz = axis_index;
+            sprintf(default_name, "Axis %i", axis_index);
+            char *str = al_malloc(strlen(default_name)+1);
+            strcpy(str, default_name);
+            joy->parent.info.stick[stick_index].axis[axis_index].name = str;
+            
+            ++axis_index;
+            joy->dpad_axis_vert = axis_index;
+            sprintf(default_name, "Axis %i", axis_index);
+            str = al_malloc(strlen(default_name)+1);
+            strcpy(str, default_name);
+            add_axis(joy, stick_index, axis_index, min, max, str, elem );
+            joy->parent.info.stick[stick_index].axis[axis_index].name = str;
+
+            joy->parent.info.stick[stick_index].num_axes = 2;
          }
-         else if ((usage == kHIDUsage_GD_Z ||
-            usage == kHIDUsage_GD_Rz) &&
-            joy->num_z_axes < _AL_MAX_JOYSTICK_STICKS) {
-            joy->min[joy->num_z_axes][2] = min;
-            joy->max[joy->num_z_axes][2] = max;
-            sprintf(default_name, "Axis 2");
-	    const char *name = get_element_name(elem, default_name);
-	    char *str = al_malloc(strlen(name)+1);
-	    strcpy(str, name);
-            joy->parent.info.stick[joy->num_z_axes].axis[2].name = str;
-            joy->axes[joy->num_z_axes++][2] = elem;
+         else
+         {
+            sprintf(default_name, "Axis %i", axis_index);
+            const char *name = get_element_name(elem, default_name);
+            char *str = al_malloc(strlen(name)+1);
+            strcpy(str, name);
+            add_axis(joy, stick_index, axis_index, min, max, str, elem );
          }
       }
    }
@@ -282,27 +336,13 @@ static void device_add_callback(
 
    CFRelease(elements);
 
-   // Fill in ALLEGRO_JOYSTICK properties
-   joy->parent.info.num_sticks = joy->num_x_axes;
-   joy->parent.info.num_buttons = joy->num_buttons;
-   for (i = 0; i < joy->num_x_axes; i++) {
-      int axes = 1;
-      if (joy->num_y_axes >= i)
-         axes++;
-      if (joy->num_z_axes >= i)
-         axes++;
-      joy->parent.info.stick[i].num_axes = axes;
-      char *buf = al_malloc(20);
-      sprintf(buf, "Stick %d", i);
-      joy->parent.info.stick[i].name = buf;
-   }
 
    al_unlock_mutex(add_mutex);
 
    osx_joy_generate_configure_event();
 
-   ALLEGRO_INFO("Found joystick (%d buttons, %d %d %d axes)\n",
-      joy->num_buttons, joy->num_x_axes, joy->num_y_axes, joy->num_z_axes);
+   ALLEGRO_INFO("Found joystick (%d buttons, %d sticks)\n",
+      joy->parent.info.num_buttons, joy->parent.info.num_sticks);
 }
 
 static void device_remove_callback(
@@ -369,6 +409,24 @@ static void osx_joy_generate_button_event(ALLEGRO_JOYSTICK_OSX *joy, int button,
    _al_event_source_emit_event(es, &event);
 }
 
+static const int MAX_HAT_DIRECTIONS = 9;
+struct HAT_MAPPING
+{
+   int axisV;
+   int axisH;
+} hat_mapping[MAX_HAT_DIRECTIONS]=
+{
+   { -1,  0 }, // 0
+   { -1,  1 }, // 1
+   {  0,  1 }, // 2
+   {  1,  1 }, // 3
+   {  1,  0 }, // 4
+   {  1, -1 }, // 5
+   {  0, -1 }, // 6
+   { -1, -1 }, // 7
+   {  0,  0 }, // 8
+};
+
 static void value_callback(
    void *context,
    IOReturn result,
@@ -391,7 +449,7 @@ static void value_callback(
    _al_event_source_lock(es);
 
    int i;
-   for (i = 0; i < joy->num_buttons; i++) {
+   for (i = 0; i < joy->parent.info.num_buttons; i++) {
       if (joy->buttons[i] == elem) {
          ALLEGRO_EVENT_TYPE type;
          if (IOHIDValueGetIntegerValue(value) == 0)
@@ -402,28 +460,24 @@ static void value_callback(
          goto done;
       }
    }
+
    int int_value = IOHIDValueGetIntegerValue(value);
-   int stick = -1;
-   int axis = -1;
-   for (i = 0; i < joy->num_x_axes; i++) {
-      if (joy->axes[i][0] == elem) {
-         stick = i;
-         axis = 0;
-         goto gen_axis_event;
-      }
-   }
-   for (i = 0; i < joy->num_y_axes; i++) {
-      if (joy->axes[i][1] == elem) {
-         stick = i;
-         axis = 1;
-         goto gen_axis_event;
+
+   if (joy->dpad == elem){
+      if (int_value>=0 && int_value<MAX_HAT_DIRECTIONS) {
+         osx_joy_generate_axis_event(joy, joy->dpad_stick, joy->dpad_axis_vert,  (float)hat_mapping[int_value].axisV );
+         osx_joy_generate_axis_event(joy, joy->dpad_stick, joy->dpad_axis_horiz, (float)hat_mapping[int_value].axisH );
       }
+      goto done;
    }
-   for (i = 0; i < joy->num_z_axes; i++) {
-      if (joy->axes[i][2] == elem) {
-         stick = i;
-         axis = 2;
-         goto gen_axis_event;
+   
+   int stick = -1;
+   int axis = -1;
+   for (stick = 0; stick < joy->parent.info.num_sticks; stick++) {
+      for(axis = 0; axis < joy->parent.info.stick[stick].num_axes; ++axis){
+         if (joy->axes[stick][axis] == elem) {
+            goto gen_axis_event;
+         }
       }
    }
 
@@ -670,13 +724,10 @@ static bool reconfigure_joysticks(void)
                al_free(joy->parent.info.stick[i].axis[j].name);
             }
          }
-	 joy_null(joy);
-         joy->num_buttons =
-         joy->num_x_axes =
-         joy->num_y_axes =
-         joy->num_z_axes = 0;
+	      joy_null(joy);
          memset(joy->buttons, 0, _AL_MAX_JOYSTICK_BUTTONS*sizeof(IOHIDElementRef));
          memset(&joy->state, 0, sizeof(ALLEGRO_JOYSTICK_STATE));
+         joy->dpad=0;
       }
       else if (joy->cfg_state == JOY_STATE_BORN)
          joy->cfg_state = JOY_STATE_ALIVE;


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/