Moving the Windows-specific includes into the Windows-specific header file
[freeglut] / src / mswin / freeglut_joystick_mswin.c
index 2aad217..50dbf1e 100644 (file)
 \r
 \r
 #if !defined(_WIN32_WCE)\r
+#    include <windows.h>\r
+#    include <mmsystem.h>\r
+#    include <regstr.h>\r
+\r
+\r
+\r
+\r
+void fgPlatformJoystickRawRead( SFG_Joystick* joy, int* buttons, float* axes )\r
+{\r
+    MMRESULT status;\r
+\r
+    status = joyGetPosEx( joy->pJoystick.js_id, &joy->pJoystick.js );\r
+\r
+    if ( status != JOYERR_NOERROR )\r
+    {\r
+        joy->error = GL_TRUE;\r
+        return;\r
+    }\r
+\r
+    if ( buttons )\r
+        *buttons = joy->pJoystick.js.dwButtons;\r
+\r
+    if ( axes )\r
+    {\r
+        /*\r
+         * WARNING - Fall through case clauses!!\r
+         */\r
+        switch ( joy->num_axes )\r
+        {\r
+        case 8:\r
+            /* Generate two POV axes from the POV hat angle.\r
+             * Low 16 bits of js.dwPOV gives heading (clockwise from ahead) in\r
+             *   hundredths of a degree, or 0xFFFF when idle.\r
+             */\r
+            if ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) == 0xFFFF )\r
+            {\r
+              axes [ 6 ] = 0.0;\r
+              axes [ 7 ] = 0.0;\r
+            }\r
+            else\r
+            {\r
+              /* This is the contentious bit: how to convert angle to X/Y.\r
+               *    wk: I know of no define for PI that we could use here:\r
+               *    SG_PI would pull in sg, M_PI is undefined for MSVC\r
+               * But the accuracy of the value of PI is very unimportant at\r
+               * this point.\r
+               */\r
+              float s = (float) sin ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) );\r
+              float c = (float) cos ( ( joy->pJoystick.js.dwPOV & 0xFFFF ) * ( 0.01 * 3.1415926535f / 180.0f ) );\r
+\r
+              /* Convert to coordinates on a square so that North-East\r
+               * is (1,1) not (.7,.7), etc.\r
+               * s and c cannot both be zero so we won't divide by zero.\r
+               */\r
+              if ( fabs ( s ) < fabs ( c ) )\r
+              {\r
+                axes [ 6 ] = ( c < 0.0 ) ? -s/c  : s/c ;\r
+                axes [ 7 ] = ( c < 0.0 ) ? -1.0f : 1.0f;\r
+              }\r
+              else\r
+              {\r
+                axes [ 6 ] = ( s < 0.0 ) ? -1.0f : 1.0f;\r
+                axes [ 7 ] = ( s < 0.0 ) ? -c/s  : c/s ;\r
+              }\r
+            }\r
+\r
+        case 6: axes[5] = (float) joy->pJoystick.js.dwVpos;\r
+        case 5: axes[4] = (float) joy->pJoystick.js.dwUpos;\r
+        case 4: axes[3] = (float) joy->pJoystick.js.dwRpos;\r
+        case 3: axes[2] = (float) joy->pJoystick.js.dwZpos;\r
+        case 2: axes[1] = (float) joy->pJoystick.js.dwYpos;\r
+        case 1: axes[0] = (float) joy->pJoystick.js.dwXpos;\r
+        }\r
+    }\r
+}\r
+\r
+\r
+\r
+/* Inspired by\r
+   http://msdn.microsoft.com/archive/en-us/dnargame/html/msdn_sidewind3d.asp\r
+ */\r
+#  if FREEGLUT_LIB_PRAGMAS\r
+#      pragma comment (lib, "advapi32.lib")\r
+#  endif\r
+\r
+static int fghJoystickGetOEMProductName ( SFG_Joystick* joy, char *buf, int buf_sz )\r
+{\r
+    char buffer [ 256 ];\r
+\r
+    char OEMKey [ 256 ];\r
+\r
+    HKEY  hKey;\r
+    DWORD dwcb;\r
+    LONG  lr;\r
+\r
+    if ( joy->error )\r
+        return 0;\r
+\r
+    /* Open .. MediaResources\CurrentJoystickSettings */\r
+    _snprintf ( buffer, sizeof(buffer), "%s\\%s\\%s",\r
+                REGSTR_PATH_JOYCONFIG, joy->pJoystick.jsCaps.szRegKey,\r
+                REGSTR_KEY_JOYCURR );\r
+\r
+    lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey);\r
+\r
+    if ( lr != ERROR_SUCCESS ) return 0;\r
+\r
+    /* Get OEM Key name */\r
+    dwcb = sizeof(OEMKey);\r
+\r
+    /* JOYSTICKID1-16 is zero-based; registry entries for VJOYD are 1-based. */\r
+    _snprintf ( buffer, sizeof(buffer), "Joystick%d%s", joy->pJoystick.js_id + 1, REGSTR_VAL_JOYOEMNAME );\r
+\r
+    lr = RegQueryValueEx ( hKey, buffer, 0, 0, (LPBYTE) OEMKey, &dwcb);\r
+    RegCloseKey ( hKey );\r
+\r
+    if ( lr != ERROR_SUCCESS ) return 0;\r
+\r
+    /* Open OEM Key from ...MediaProperties */\r
+    _snprintf ( buffer, sizeof(buffer), "%s\\%s", REGSTR_PATH_JOYOEM, OEMKey );\r
+\r
+    lr = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, buffer, 0, KEY_QUERY_VALUE, &hKey );\r
+\r
+    if ( lr != ERROR_SUCCESS ) return 0;\r
+\r
+    /* Get OEM Name */\r
+    dwcb = buf_sz;\r
+\r
+    lr = RegQueryValueEx ( hKey, REGSTR_VAL_JOYOEMNAME, 0, 0, (LPBYTE) buf,\r
+                             &dwcb );\r
+    RegCloseKey ( hKey );\r
+\r
+    if ( lr != ERROR_SUCCESS ) return 0;\r
+\r
+    return 1;\r
+}\r
+\r
+\r
+void fgPlatformJoystickOpen( SFG_Joystick* joy )\r
+{\r
+       int i = 0;\r
+\r
+    joy->pJoystick.js.dwFlags = JOY_RETURNALL;\r
+    joy->pJoystick.js.dwSize  = sizeof( joy->pJoystick.js );\r
+\r
+    memset( &joy->pJoystick.jsCaps, 0, sizeof( joy->pJoystick.jsCaps ) );\r
+\r
+    joy->error =\r
+        ( joyGetDevCaps( joy->pJoystick.js_id, &joy->pJoystick.jsCaps, sizeof( joy->pJoystick.jsCaps ) ) !=\r
+          JOYERR_NOERROR );\r
+\r
+    if( joy->pJoystick.jsCaps.wNumAxes == 0 )\r
+    {\r
+        joy->num_axes = 0;\r
+        joy->error = GL_TRUE;\r
+    }\r
+    else\r
+    {\r
+        /* Device name from jsCaps is often "Microsoft PC-joystick driver",\r
+         * at least for USB.  Try to get the real name from the registry.\r
+         */\r
+        if ( ! fghJoystickGetOEMProductName( joy, joy->name,\r
+                                             sizeof( joy->name ) ) )\r
+        {\r
+            fgWarning( "JS: Failed to read joystick name from registry" );\r
+            strncpy( joy->name, joy->pJoystick.jsCaps.szPname, sizeof( joy->name ) );\r
+        }\r
+\r
+        /* Windows joystick drivers may provide any combination of\r
+         * X,Y,Z,R,U,V,POV - not necessarily the first n of these.\r
+         */\r
+        if( joy->pJoystick.jsCaps.wCaps & JOYCAPS_HASPOV )\r
+        {\r
+            joy->num_axes = _JS_MAX_AXES;\r
+            joy->min[ 7 ] = -1.0; joy->max[ 7 ] = 1.0;  /* POV Y */\r
+            joy->min[ 6 ] = -1.0; joy->max[ 6 ] = 1.0;  /* POV X */\r
+        }\r
+        else\r
+            joy->num_axes = 6;\r
+\r
+        joy->min[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmin;\r
+        joy->max[ 5 ] = ( float )joy->pJoystick.jsCaps.wVmax;\r
+        joy->min[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmin;\r
+        joy->max[ 4 ] = ( float )joy->pJoystick.jsCaps.wUmax;\r
+        joy->min[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmin;\r
+        joy->max[ 3 ] = ( float )joy->pJoystick.jsCaps.wRmax;\r
+        joy->min[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmin;\r
+        joy->max[ 2 ] = ( float )joy->pJoystick.jsCaps.wZmax;\r
+        joy->min[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmin;\r
+        joy->max[ 1 ] = ( float )joy->pJoystick.jsCaps.wYmax;\r
+        joy->min[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmin;\r
+        joy->max[ 0 ] = ( float )joy->pJoystick.jsCaps.wXmax;\r
+    }\r
+\r
+    /* Guess all the rest judging on the axes extremals */\r
+    for( i = 0; i < joy->num_axes; i++ )\r
+    {\r
+        joy->center   [ i ] = ( joy->max[ i ] + joy->min[ i ] ) * 0.5f;\r
+        joy->dead_band[ i ] = 0.0f;\r
+        joy->saturate [ i ] = 1.0f;\r
+    }\r
+}\r
+\r
+\r
+\r
+void fgPlatformJoystickInit( SFG_Joystick *fgJoystick[], int ident )\r
+{\r
+    switch( ident )\r
+    {\r
+    case 0:\r
+        fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID1;\r
+        fgJoystick[ ident ]->error = GL_FALSE;\r
+        break;\r
+    case 1:\r
+        fgJoystick[ ident ]->pJoystick.js_id = JOYSTICKID2;\r
+        fgJoystick[ ident ]->error = GL_FALSE;\r
+        break;\r
+    default:\r
+        fgJoystick[ ident ]->num_axes = 0;\r
+        fgJoystick[ ident ]->error = GL_TRUE;\r
+        return;\r
+    }\r
+}\r
+\r
+\r
+\r
 void fgPlatformJoystickClose ( int ident )\r
 {\r
     /* Do nothing special */\r