[PATCH 2/5] programs/joystick: Command line options and possibility to test buttons and axes

Lucas Fialho Zawacki lfzawacki at gmail.com
Fri May 18 08:50:47 CDT 2012


From: Lucas Fialho Zawacki <lfzawacki at gmail.com>

---
 programs/joystick/main.c |  188 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 183 insertions(+), 5 deletions(-)

diff --git a/programs/joystick/main.c b/programs/joystick/main.c
index 108d7f0..357388d 100644
--- a/programs/joystick/main.c
+++ b/programs/joystick/main.c
@@ -28,6 +28,8 @@
 #include <stdio.h>
 #include <dinput.h>
 
+#define NUMELEMS(array) (sizeof(array)/sizeof(array[0]))
+
 struct Joystick {
     IDirectInputDevice8A *device;
     DIDEVICEINSTANCEA instance;
@@ -40,8 +42,49 @@ struct JoystickData {
     struct Joystick *joysticks;
     int num_joysticks;
     int cur_joystick;
+    int poll_time;
 };
 
+/*  Printing Functions */
+/*
+    DumpState
+    Dumps the current joystick state. Pressed buttons and axis information.
+*/
+static void DumpState(DIJOYSTATE* st, int num_buttons)
+{
+    int i;
+    printf("----------------------------------\n");
+    printf("Ax: (% 5d,% 5d,% 5d)\tRAx: (% 5d,% 5d,% 5d)\nSlider: (% 5d,% 5d)\tPov: (% 5d,% 5d,% 5d,% 5d)\n\n",
+                st->lX,st->lY,st->lZ,st->lRx,st->lRy,st->lRz,
+                st->rglSlider[0],st->rglSlider[1],
+                st->rgdwPOV[0],st->rgdwPOV[1],st->rgdwPOV[2],st->rgdwPOV[3]
+           );
+
+    for(i=0; i < num_buttons; i++) {
+        printf("% 3d", i);
+    }
+    printf("\n");
+    for(i=0; i < num_buttons; i++) {
+        printf("  %c",st->rgbButtons[i] ? 'x' : 'o');
+    }
+    printf("\n");
+}
+
+/*
+    EnumObjectsCallback
+    Counts buttons and axes and sets some object properties.
+*/
+static BOOL CALLBACK EnumObjectsCallback(const DIDEVICEOBJECTINSTANCEA *instance, void *context)
+{
+    struct JoystickData *data = context;
+    struct Joystick *joystick = &data->joysticks[data->cur_joystick];
+
+    if (instance->dwType & DIDFT_BUTTON) joystick->num_buttons += 1;
+    if (instance->dwType & DIDFT_AXIS) joystick->num_axes += 1;
+
+    return DIENUM_CONTINUE;
+}
+
 /*
     EnumCallback
     Enumerates, creates and sets the common data format for all the joystick devices.
@@ -70,14 +113,130 @@ static BOOL CALLBACK EnumCallback(const DIDEVICEINSTANCEA *instance, void *conte
     return DIENUM_CONTINUE;
 }
 
+static HRESULT Poll(IDirectInputDevice8A *joystick, DIJOYSTATE *state)
+{
+    HRESULT  hr;
+
+    hr = IDirectInputDevice8_Poll(joystick);
+
+    /* Try to acquire the joystick */
+    if (FAILED(hr)) {
+
+        hr = IDirectInputDevice8_Acquire(joystick);
+
+        while (hr == DIERR_INPUTLOST)
+            hr = IDirectInputDevice8_Acquire(joystick);
+
+        if (hr == DIERR_INVALIDPARAM || hr == DIERR_NOTINITIALIZED) return E_FAIL;
+
+        if (hr == DIERR_OTHERAPPHASPRIO) return S_OK;
+    }
+
+    hr = IDirectInputDevice8_GetDeviceState(joystick, sizeof(DIJOYSTATE), state);
+
+    /* Should not fail, the device has just been acquired */
+    if (FAILED(hr)) return hr;
+
+    return S_OK;
+}
+
+static void WaitForInput(const struct JoystickData* data, int chosen)
+{
+    int i = 0;
+    int num_buttons = data->joysticks[chosen].num_buttons;
+
+    struct Joystick *joystick = &data->joysticks[chosen];
+    DIJOYSTATE state;
+    BOOL pressed = FALSE;
+
+    ZeroMemory(&state, sizeof(state));
+
+    printf("Polling input from '%s'\n", joystick->instance.tszInstanceName);
+    printf("Joystick has %d buttons and %d axes\n", joystick->num_buttons, joystick->num_axes);
+    printf("Press any joystick button ...\n");
+
+    while (!Poll(joystick->device, &state) && !pressed)
+        for (i=0; i < num_buttons && !pressed; i++)
+            pressed = pressed || state.rgbButtons[i];
+
+    /* Wait for input and dump */
+    while (!Poll(joystick->device, &state)) {
+        DumpState(&state, num_buttons);
+        Sleep(data->poll_time);
+    }
+}
+
+/*
+    ProcessCmdLine
+    Receives the command line input.
+*/
+static void ProcessCmdLine(struct JoystickData *params, LPSTR lpCmdLine)
+{
+    int i, j, buffer_index;
+    /* Options are { 'poll' } */
+    char options[] = { 'p' };
+    char buffer[32];
+    char command;
+
+    for (i=0; lpCmdLine[i] != '\0'; i++) {
+        if (lpCmdLine[i] == '/' || lpCmdLine[i] == '-') {
+            /* Find valid command */
+            BOOL valid = FALSE;
+            command = lpCmdLine[++i];
+            for (j=0; j < NUMELEMS(options) && !valid; j++)
+                if (options[j] == command)
+                    valid = TRUE;
+
+            if (!valid) goto invalid;
+
+            /* Skip extra spaces */
+            while (lpCmdLine[++i] == ' ');
+
+            /* If the next word is a parameter, copy it.
+               Parameters dont start with - or /, that's for commands.
+               The isdigit call is to test for negative numbers (-1 for example)
+               and to not confuse them with commands */
+            buffer_index = 0;
+            if ((lpCmdLine[i] != '-' || isdigit(lpCmdLine[i+1])) && lpCmdLine[i] != '/') {
+                /* Copy the word and don't let it overflow */
+                while (lpCmdLine[i] != ' ' && lpCmdLine[i] != '\0' && buffer_index < sizeof(buffer)) {
+                    buffer[buffer_index] = lpCmdLine[i];
+                    buffer_index++;
+                    i++;
+                }
+            }
+            buffer[buffer_index] = '\0';
+
+            /* Process command and extract parameter */
+            switch (command)
+            {
+                case 'p':
+                    if (strlen(buffer) == 0) goto invalid;
+                    params->poll_time = atoi(buffer);
+                break;
+            }
+        }
+    }
+
+    return;
+
+    invalid:
+        printf("Invalid parameters or command line option '%c'\n", command);
+        exit(1);
+}
+
+
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR szCmdLine, int nShow)
 {
     /* Structure with the data and settings for the application */
-    /* data is: lpdi, joy[], num_joy, cur_joy */
-    struct JoystickData data = { NULL, NULL, 0, 0 };
+    /* data is: lpdi, joy[], num_joy, cur_joy, poll_time */
+    struct JoystickData data = { NULL, NULL, 0, 0, 0 };
     HRESULT hr;
-    int i;
 
+    /* Get settings from the command line */
+    ProcessCmdLine(&data, szCmdLine);
+
+    /* Then initialize dinput */
     hr = DirectInput8Create(GetModuleHandleA(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void**) &data.di, NULL);
 
     if (FAILED(hr)) {
@@ -92,11 +251,30 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR szCmdLine, int nS
     /* Get all the joysticks */
     hr = IDirectInput8_EnumDevices(data.di, DI8DEVCLASS_GAMECTRL, EnumCallback, &data, DIEDFL_ATTACHEDONLY);
 
+    /* Count joysticks buttons, axes and apply settings */
+    for (data.cur_joystick = 0; data.cur_joystick < data.num_joysticks; data.cur_joystick++) {
+        IDirectInputDevice8_EnumObjects(
+            data.joysticks[data.cur_joystick].device, EnumObjectsCallback, &data, DIDFT_AXIS | DIDFT_BUTTON);
+    }
+
     printf("Found %d joysticks.\n", data.num_joysticks);
 
     /* Default case just lists the joysticks */
-    for (i=0; i < data.num_joysticks; i++)
-        printf("%d: %s\n", i, data.joysticks[i].instance.tszInstanceName);
+    if (data.poll_time == 0) {
+
+        int i = 0;
+        for (i=0; i < data.num_joysticks; i++)
+            printf("%d: %s\n", i, data.joysticks[i].instance.tszInstanceName);
+    }
+    else {
+
+        /* If we'll poll the joystick for input */
+        if (data.num_joysticks > 0) {
+
+            /* Use the first joystick */
+            WaitForInput(&data, 0);
+        }
+    }
 
     return 0;
 }
-- 
1.7.9.5




More information about the wine-patches mailing list