direct-input/test/raw.cpp

Go to the documentation of this file.
00001 /*
00002  * raw.cpp
00003  *
00004  * Copyright (C) 2010  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  * Performs raw lookups and reads of DirectInput devices.
00008  */
00009 
00010 // includes --------------------------------------------------------------------
00011 #include <iostream>
00012 #include <time.h>
00013 
00014 #include "common/common.h"
00015 #include "direct-input/di-diagnostics.h"
00016 #include "perf/perf.h"
00017 #include "util/file.h"
00018 #include "wave-windows/wave-windows.h"
00019 
00020 
00021 ////////////////////////////////////////////////////////////////////////////////
00022 //
00023 //      static helper methods
00024 //
00025 ////////////////////////////////////////////////////////////////////////////////
00026 
00027 static BOOL
00028 deviceCallback
00029 (
00030 LPCDIDEVICEINSTANCEA lpddi,
00031 void * context
00032 )
00033 {
00034         ASSERT(lpddi, "null device instance?");
00035         // ASSERT(context) -- we don't care
00036 
00037         std::cerr << "Device found:\n";
00038         std::cerr << *lpddi;
00039 
00040         if (context) {
00041                 GUID * pg = (GUID *) context;
00042                 *pg = lpddi->guidInstance;
00043                 return FALSE;
00044         }
00045         return TRUE;
00046 }
00047 
00048 
00049 
00050 #define DUMP_FORMAT( token )                                            \
00051         {                                                               \
00052                 DPRINTF("Dumping %s...", #token);                       \
00053                 std::cerr << ( token );                                 \
00054         }
00055 
00056 
00057 static void
00058 doTest
00059 (
00060 void
00061 )
00062 {
00063         // create DirectInput object
00064         HINSTANCE hinst = GetModuleHandle(NULL);
00065         ASSERT_THROW(hinst, "failed to acquire win32 instance handle");
00066         DWORD dwVersion = DIRECTINPUT_VERSION;
00067         REFIID riid = IID_IDirectInput8;
00068         LPUNKNOWN punkOuter = NULL;
00069         COM_ptr<IDirectInput8> pdi;
00070         ASSERT(!pdi, "should be null");
00071 
00072         HRESULT hr = DirectInput8Create(hinst, dwVersion, riid,
00073             pdi, punkOuter);
00074         DI_VERIFY(DI_OK == hr && pdi, hr,
00075             "Failed to create DirectInput object");
00076 
00077         // enumerate all devices
00078         DWORD dwDevType = DI8DEVCLASS_ALL;
00079         void * context = NULL;
00080         DWORD dwFlags = DIEDFL_ALLDEVICES;
00081         LPDIENUMDEVICESCALLBACKA callback =
00082             (LPDIENUMDEVICESCALLBACKA) deviceCallback;
00083 
00084         DPRINTF("ALL DEVICES =============");
00085         hr = pdi->EnumDevices(dwDevType, callback, context, dwFlags);
00086         DI_VERIFY(DI_OK == hr, hr,
00087             "Failed to enumerate direct input devices");
00088 
00089         // enumerate only gamepads
00090         DPRINTF("GAMEPADS =============");
00091         dwDevType = DI8DEVCLASS_GAMECTRL;
00092         hr = pdi->EnumDevices(dwDevType, callback, context, dwFlags);
00093         DI_VERIFY(DI_OK == hr, hr,
00094             "Failed to enumerate direct input gamepad devices");
00095 
00096         // final pass: pick first one
00097         DPRINTF("PICKING FIRST GAMEPAD ============");
00098         GUID guidGamepad;
00099         context = (void *) &guidGamepad;
00100         hr = pdi->EnumDevices(dwDevType, callback, context, dwFlags);
00101         DI_VERIFY(DI_OK == hr, hr,
00102             "Failed to enumerate gamepad devices");
00103         std::cerr << "Picked gamepad: " << guidGamepad << "\n";
00104 
00105         // now create a device for this gamepad
00106         IDirectInputDevice8 * pdiDevice = NULL;
00107         hr = pdi->CreateDevice(guidGamepad, &pdiDevice, punkOuter);
00108         DI_VERIFY(DI_OK == hr && pdiDevice, hr,
00109             "Failed to create device for first gamepad");
00110 
00111         // dump the various DirectInput data formats
00112 //      DUMP_FORMAT(c_dfDIMouse)
00113 //      DUMP_FORMAT(c_dfDIMouse2)
00114 //      DUMP_FORMAT(c_dfDIKeyboard)
00115 //      DUMP_FORMAT(c_dfDIJoystick)
00116 //      DUMP_FORMAT(c_dfDIJoystick2)
00117 
00118 /*
00119         // based on inspection, Joystick2 seems to be the most advanced
00120         // (we need lots of inputs to handle gamepads)
00121         hr = pdiDevice->SetDataFormat(&c_dfDIJoystick2);
00122         DI_VERIFY(DI_OK == hr, hr,
00123             "Failed to set data format");
00124 
00125         // acquire
00126         hr = pdiDevice->Acquire();
00127         DI_VERIFY(DI_OK == hr || S_FALSE == hr, hr,
00128             "Failed to acquire gamepad");
00129 */
00130         // interrogate the gamepad
00131 //      DIDEVCAPS devcaps;
00132 //      devcaps.dwSize = sizeof(DIDEVCAPS);     // have to set this one field
00133 //      hr = pdiDevice->GetCapabilities(&devcaps);
00134 //      DI_VERIFY(DI_OK == hr, hr,
00135 //          "Failed to get device capabilities");
00136 //      std::cerr << devcaps;
00137 //      ASSERT(false, "halt");
00138 
00139         // now we'll grab current data using Joystick2 format
00140 //      DIJOYSTATE2 joy2;
00141 //      dword_t dwSize = sizeof(DIJOYSTATE2);
00142 //      hr = pdiDevice->GetDeviceState(dwSize, &joy2);
00143 //      DI_VERIFY(DI_OK == hr, hr,
00144 //          "Failed to get device state");
00145 
00146         // given the data format and data, dump the results
00147 //      DPRINTF("About to dump raw data from device...");
00148 //      gamepad::writeStateDebug(std::cerr, c_dfDIJoystick2, (byte_t *) &joy2);
00149 //      gamepad::writeState(std::cerr, c_dfDIJoystick2, (byte_t *) &joy2);
00150 
00151         // now build our own custom data format from the device capabilities
00152         gamepad::device_caps_t dc;
00153         byte_t * pDataFormat = gamepad::getDataFormatForDevice(pdiDevice, dc);
00154         ASSERT_THROW(pDataFormat, "Failed to construct data format");
00155         DIDATAFORMAT * pdf = (DIDATAFORMAT *) pDataFormat;
00156         DUMP_FORMAT(*pdf);
00157         dc.dump("Detected capabilities for first gamepad");
00158 
00159         // now set our custom data format
00160         hr = pdiDevice->SetDataFormat(pdf);
00161         DI_VERIFY(DI_OK == hr, hr,
00162             "Failed to set custom data format");
00163 
00164         // acquire
00165         hr = pdiDevice->Acquire();
00166         DI_VERIFY(DI_OK == hr || S_FALSE == hr, hr,
00167             "Failed to acquire gamepad");
00168 
00169         // get buffer to hold state
00170         ASSERT_THROW(dc.dataBytes > 0, "Bad data bytes: " << dc.dataBytes);
00171         byte_t * state = new byte_t[dc.dataBytes];
00172         ASSERT(state, "out of memory");
00173 
00174         // now loop
00175         const int desiredHz = 33;       // run loop at this many cycles/second
00176         const int msSleep = 1000 / desiredHz;
00177         const int nObjs = 10;   // show this many objects
00178         while (true) {
00179                 Sleep(msSleep);
00180                 hr = pdiDevice->Poll();
00181                 DI_VERIFY(DI_OK == hr || DI_NOEFFECT == hr, hr,
00182                     "Failed to poll device");
00183                 hr = pdiDevice->GetDeviceState(dc.dataBytes, state);
00184                 DI_VERIFY(DI_OK == hr, hr,
00185                     "Failed to get device state");
00186 
00187                 long * pl = (long *) state;
00188                 for (int i = 0; i < nObjs; ++i, ++pl) {
00189                         fprintf(stderr, " %6d", *pl);
00190                 }
00191                 fprintf(stderr, "\n");
00192         }
00193 }
00194 
00195 
00196 
00197 ////////////////////////////////////////////////////////////////////////////////
00198 //
00199 //      entry point
00200 //
00201 ////////////////////////////////////////////////////////////////////////////////
00202 
00203 int
00204 main
00205 (
00206 IN int argc,
00207 IN const char * argv[]
00208 )
00209 {
00210 
00211         int retval = 0;
00212         try {
00213                 perf::Timer timer("overall timer");
00214 
00215                 doTest();
00216 
00217         } catch (std::exception& e) {
00218                 DPRINTF("EXCEPTION: %s", e.what());
00219                 retval = 1;
00220         }
00221 
00222         perf::dumpTimingSummary(std::cerr);
00223 
00224         return retval;
00225 }
00226