[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