1
/* GIMP - The GNU Image Manipulation Program
2
* Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
4
* controller_dx_dinput.c
5
* Copyright (C) 2004-2007 Sven Neumann <sven@gimp.org>
6
* Michael Natterer <mitch@gimp.org>
7
* Tor Lillqvist <tml@iki.fi>
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
/* When using gcc with the February 2007 version of the DirectX SDK,
25
* at least, you need to fix a couple of duplicate typedefs in the
26
* DirectX <dinput.h>. Unfortunately I can't include the diff here,
27
* both for copyright reasons, and because that would confuse the C
28
* lexer even if inside #if 0.
37
#define _WIN32_WINNT 0x0501
39
#define DIRECTINPUT_VERSION 0x0800
44
#include "libgimpconfig/gimpconfig.h"
45
#include "libgimpmodule/gimpmodule.h"
46
#include "libgimpwidgets/gimpwidgets.h"
48
#define GIMP_ENABLE_CONTROLLER_UNDER_CONSTRUCTION
49
#include "libgimpwidgets/gimpcontroller.h"
51
#include "gimpinputdevicestore.h"
53
#include "libgimp/libgimp-intl.h"
62
#define NUM_EVENTS_PER_BUTTON 3 /* Button click, press and release */
63
#define NUM_EVENTS_PER_AXIS 2 /* Axis decrease and increase */
64
#define NUM_EVENTS_PER_SLIDER 2 /* Slider decrease and increase */
65
#define NUM_EVENTS_PER_POV 3 /* POV view vector X and Y view and return */
67
#define CONTROLLER_TYPE_DX_DINPUT (controller_type)
68
#define CONTROLLER_DX_DINPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CONTROLLER_TYPE_DX_DINPUT, ControllerDXDInput))
69
#define CONTROLLER_DX_DINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CONTROLLER_TYPE_DX_DINPUT, ControllerDXDInputClass))
70
#define CONTROLLER_IS_DX_DINPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CONTROLLER_TYPE_DX_DINPUT))
71
#define CONTROLLER_IS_DX_DINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CONTROLLER_TYPE_DX_DINPUT))
73
typedef struct _DXDInputSource DXDInputSource;
74
typedef struct _ControllerDXDInput ControllerDXDInput;
75
typedef struct _ControllerDXDInputClass ControllerDXDInputClass;
77
struct _DXDInputSource
80
ControllerDXDInput *controller;
83
struct _ControllerDXDInput
85
GimpController parent_instance;
87
GimpInputDeviceStore *store;
89
LPDIRECTINPUTDEVICE8W didevice8;
96
gint num_button_events;
102
gint num_slider_events;
109
gchar **event_blurbs;
111
DIDATAFORMAT *format;
118
/* Variables used by enumeration callbacks only*/
119
gint bei, bi, aei, ai, sei, si, pei, pi;
122
struct _ControllerDXDInputClass
124
GimpControllerClass parent_class;
128
GType dx_dinput_get_type (GTypeModule *module);
129
static void dx_dinput_class_init (ControllerDXDInputClass *klass);
130
static void dx_dinput_init (ControllerDXDInput *controller);
131
static void dx_dinput_dispose (GObject *object);
132
static void dx_dinput_finalize (GObject *object);
133
static void dx_dinput_set_property (GObject *object,
137
static void dx_dinput_get_property (GObject *object,
142
static gint dx_dinput_get_n_events (GimpController *controller);
143
static const gchar * dx_dinput_get_event_name (GimpController *controller,
145
static const gchar * dx_dinput_get_event_blurb (GimpController *controller,
148
static void dx_dinput_device_changed (ControllerDXDInput *controller,
150
static gboolean dx_dinput_set_device (ControllerDXDInput *controller,
154
static const GimpModuleInfo dx_dinput_info =
156
GIMP_MODULE_ABI_VERSION,
157
N_("DirectX DirectInput event controller"),
158
"Tor Lillqvist <tml@iki.fi>",
160
"(c) 2004-2007, released under the GPL",
165
static GType controller_type = 0;
166
static GimpControllerClass *parent_class = NULL;
169
G_MODULE_EXPORT const GimpModuleInfo *
170
gimp_module_query (GTypeModule *module)
172
return &dx_dinput_info;
175
G_MODULE_EXPORT gboolean
176
gimp_module_register (GTypeModule *module)
178
gimp_input_device_store_get_type (module);
179
dx_dinput_get_type (module);
186
dx_dinput_get_type (GTypeModule *module)
188
if (! controller_type)
190
const GTypeInfo controller_info =
192
sizeof (ControllerDXDInputClass),
193
(GBaseInitFunc) NULL,
194
(GBaseFinalizeFunc) NULL,
195
(GClassInitFunc) dx_dinput_class_init,
196
NULL, /* class_finalize */
197
NULL, /* class_data */
198
sizeof (ControllerDXDInput),
200
(GInstanceInitFunc) dx_dinput_init
203
controller_type = g_type_module_register_type (module,
204
GIMP_TYPE_CONTROLLER,
205
"ControllerDXDInput",
206
&controller_info, 0);
209
return controller_type;
213
dx_dinput_class_init (ControllerDXDInputClass *klass)
215
GimpControllerClass *controller_class = GIMP_CONTROLLER_CLASS (klass);
216
GObjectClass *object_class = G_OBJECT_CLASS (klass);
218
parent_class = g_type_class_peek_parent (klass);
220
object_class->dispose = dx_dinput_dispose;
221
object_class->finalize = dx_dinput_finalize;
222
object_class->get_property = dx_dinput_get_property;
223
object_class->set_property = dx_dinput_set_property;
225
g_object_class_install_property (object_class, PROP_DEVICE,
226
g_param_spec_string ("device",
228
_("The device to read DirectInput events from."),
230
GIMP_CONFIG_PARAM_FLAGS));
231
g_object_class_install_property (object_class, PROP_DEVICE_STORE,
232
g_param_spec_object ("device-values",
234
GIMP_TYPE_INPUT_DEVICE_STORE,
237
controller_class->name = _("DirectX DirectInput");
238
controller_class->help_id = "gimp-controller-directx-directinput";
239
controller_class->stock_id = GIMP_STOCK_CONTROLLER_LINUX_INPUT;
241
controller_class->get_n_events = dx_dinput_get_n_events;
242
controller_class->get_event_name = dx_dinput_get_event_name;
243
controller_class->get_event_blurb = dx_dinput_get_event_blurb;
247
dx_dinput_init (ControllerDXDInput *controller)
249
controller->store = gimp_input_device_store_new ();
251
if (controller->store)
253
g_signal_connect_swapped (controller->store, "device-added",
254
G_CALLBACK (dx_dinput_device_changed),
256
g_signal_connect_swapped (controller->store, "device-removed",
257
G_CALLBACK (dx_dinput_device_changed),
263
dx_dinput_dispose (GObject *object)
265
ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
267
dx_dinput_set_device (controller, NULL);
269
G_OBJECT_CLASS (parent_class)->dispose (object);
273
dx_dinput_finalize (GObject *object)
275
ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
277
if (controller->source != NULL)
279
g_source_remove_poll (controller->source, controller->pollfd);
280
g_source_remove (g_source_get_id (controller->source));
281
g_source_unref (controller->source);
284
if (controller->didevice8)
285
IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL);
287
if (controller->format != NULL)
289
g_free (controller->format->rgodf);
290
g_free (controller->format);
291
controller->format = NULL;
294
g_free (controller->prevdata);
295
controller->prevdata = NULL;
297
if (controller->event != NULL)
299
CloseHandle (controller->event);
300
controller->event = 0;
303
if (controller->store)
305
g_object_unref (controller->store);
306
controller->store = NULL;
309
G_OBJECT_CLASS (parent_class)->finalize (object);
313
dx_dinput_set_property (GObject *object,
318
ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
323
dx_dinput_set_device (controller, g_value_get_string (value));
326
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
332
dx_dinput_get_property (GObject *object,
337
ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
342
g_value_set_string (value, controller->guid);
344
case PROP_DEVICE_STORE:
345
g_value_set_object (value, controller->store);
348
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
354
dx_dinput_get_n_events (GimpController *controller)
356
ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller;
358
return cdxdi->num_events;
362
dx_dinput_get_event_name
363
(GimpController *controller,
366
ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller;
368
if (event_id < 0 || event_id >= cdxdi->num_events)
371
return cdxdi->event_names[event_id];
375
dx_dinput_get_event_blurb (GimpController *controller,
378
ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller;
380
if (event_id < 0 || event_id >= cdxdi->num_events)
383
return cdxdi->event_blurbs[event_id];
387
count_objects (const DIDEVICEOBJECTINSTANCEW *doi,
390
ControllerDXDInput *controller = (ControllerDXDInput *) user_data;
394
if (doi->dwType & DIDFT_AXIS)
396
/* Set reported range to physical range, not to give upper
397
* level software any false impression of higher accuracy.
400
range.diph.dwSize = sizeof (DIPROPRANGE);
401
range.diph.dwHeaderSize = sizeof (DIPROPHEADER);
402
range.diph.dwObj = doi->dwType;
403
range.diph.dwHow = DIPH_BYID;
405
if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8,
406
DIPROP_PHYSICALRANGE,
408
g_warning ("IDirectInputDevice8::GetProperty failed: %s",
409
g_win32_error_message (hresult));
412
if (FAILED ((hresult = IDirectInputDevice8_SetProperty (controller->didevice8,
415
g_warning ("IDirectInputDevice8::SetProperty failed: %s",
416
g_win32_error_message (hresult));
420
if (IsEqualGUID (&doi->guidType, &GUID_Button))
421
controller->num_buttons++;
422
else if (IsEqualGUID (&doi->guidType, &GUID_XAxis) ||
423
IsEqualGUID (&doi->guidType, &GUID_YAxis) ||
424
IsEqualGUID (&doi->guidType, &GUID_ZAxis) ||
425
IsEqualGUID (&doi->guidType, &GUID_RxAxis) ||
426
IsEqualGUID (&doi->guidType, &GUID_RyAxis) ||
427
IsEqualGUID (&doi->guidType, &GUID_RzAxis))
428
controller->num_axes++;
429
else if (IsEqualGUID (&doi->guidType, &GUID_Slider))
430
controller->num_sliders++;
431
else if (IsEqualGUID (&doi->guidType, &GUID_POV))
432
controller->num_povs++;
434
return DIENUM_CONTINUE;
438
name_objects (const DIDEVICEOBJECTINSTANCEW *doi,
441
ControllerDXDInput *controller = (ControllerDXDInput *) user_data;
443
if (IsEqualGUID (&doi->guidType, &GUID_Button))
445
controller->event_names[controller->bei] = g_strdup_printf ("button-%d", controller->bi);
446
controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d"), controller->bi);
448
controller->event_names[controller->bei] = g_strdup_printf ("button-%d-press", controller->bi);
449
controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d Press"), controller->bi);
451
controller->event_names[controller->bei] = g_strdup_printf ("button-%d-release", controller->bi);
452
controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d Release"), controller->bi);
455
g_assert (controller->bi < controller->num_buttons);
459
else if (IsEqualGUID (&doi->guidType, &GUID_XAxis) ||
460
IsEqualGUID (&doi->guidType, &GUID_YAxis) ||
461
IsEqualGUID (&doi->guidType, &GUID_ZAxis) ||
462
IsEqualGUID (&doi->guidType, &GUID_RxAxis) ||
463
IsEqualGUID (&doi->guidType, &GUID_RyAxis) ||
464
IsEqualGUID (&doi->guidType, &GUID_RzAxis))
466
if (IsEqualGUID (&doi->guidType, &GUID_XAxis))
468
controller->event_names[controller->aei] = g_strdup ("x-move-left");
469
controller->event_blurbs[controller->aei] = g_strdup (_("X Move Left"));
471
controller->event_names[controller->aei] = g_strdup ("x-move-right");
472
controller->event_blurbs[controller->aei] = g_strdup (_("X Move Right"));
475
else if (IsEqualGUID (&doi->guidType, &GUID_YAxis))
477
controller->event_names[controller->aei] = g_strdup ("y-move-away");
478
controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Away"));
480
controller->event_names[controller->aei] = g_strdup ("y-move-near");
481
controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Near"));
484
else if (IsEqualGUID (&doi->guidType, &GUID_ZAxis))
486
controller->event_names[controller->aei] = g_strdup ("z-move-up");
487
controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Up"));
489
controller->event_names[controller->aei] = g_strdup ("z-move-down");
490
controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Down"));
493
else if (IsEqualGUID (&doi->guidType, &GUID_RxAxis))
495
controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-away");
496
controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Away"));
498
controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-near");
499
controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Near"));
502
else if (IsEqualGUID (&doi->guidType, &GUID_RyAxis))
504
controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-right");
505
controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Right"));
507
controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-left");
508
controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Left"));
511
else if (IsEqualGUID (&doi->guidType, &GUID_RzAxis))
513
controller->event_names[controller->aei] = g_strdup ("z-axis-turn-left");
514
controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Left"));
516
controller->event_names[controller->aei] = g_strdup ("z-axis-turn-right");
517
controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Right"));
521
g_assert (controller->ai < controller->num_axes);
525
else if (IsEqualGUID (&doi->guidType, &GUID_Slider))
527
controller->event_names[controller->sei] = g_strdup_printf ("slider-%d-increase", controller->si);
528
controller->event_blurbs[controller->sei] = g_strdup_printf (_("Slider %d Increase"), controller->si);
530
controller->event_names[controller->sei] = g_strdup_printf ("slider-%d-decrease", controller->si);
531
controller->event_blurbs[controller->sei] = g_strdup_printf (_("Slider %d Decrease"), controller->si);
534
g_assert (controller->si < controller->num_sliders);
538
else if (IsEqualGUID (&doi->guidType, &GUID_POV))
540
controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-x-view", controller->pi);
541
controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d X View"), controller->pi);
543
controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-y-view", controller->pi);
544
controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d Y View"), controller->pi);
546
controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-x-return", controller->pi);
547
controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d Return"), controller->pi);
550
g_assert (controller->pi < controller->num_povs);
555
return DIENUM_CONTINUE;
559
dx_dinput_get_device_info (ControllerDXDInput *controller,
564
controller->num_buttons =
565
controller->num_axes =
566
controller->num_sliders =
567
controller->num_povs = 0;
569
if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8,
579
g_set_error (error, 0, 0,
580
"IDirectInputDevice8::EnumObjects failed: %s",
581
g_win32_error_message (hresult));
585
controller->num_button_events = controller->num_buttons*NUM_EVENTS_PER_BUTTON;
586
controller->num_axis_events = controller->num_axes*NUM_EVENTS_PER_AXIS;
587
controller->num_slider_events = controller->num_sliders*NUM_EVENTS_PER_SLIDER;
588
controller->num_pov_events = controller->num_povs*NUM_EVENTS_PER_POV;
590
controller->num_events =
591
controller->num_button_events +
592
controller->num_axis_events +
593
controller->num_slider_events +
594
controller->num_pov_events;
596
controller->event_names = g_new (gchar *, controller->num_events);
597
controller->event_blurbs = g_new (gchar *, controller->num_events);
599
controller->bi = controller->ai = controller->si = controller->pi = 0;
602
controller->aei = controller->bei + controller->num_button_events;
603
controller->sei = controller->aei + controller->num_axis_events;
604
controller->pei = controller->sei + controller->num_slider_events;
606
if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8,
616
g_free (controller->event_names);
617
g_free (controller->event_blurbs);
619
g_set_error (error, 0, 0,
620
"IDirectInputDevice8::EnumObjects failed: %s",
621
g_win32_error_message (hresult));
626
g_assert (controller->bei == controller->num_button_events);
627
g_assert (controller->aei == controller->bei + controller->num_axis_events);
628
g_assert (controller->sei == controller->aei + controller->num_slider_events);
629
g_assert (controller->pei == controller->sei + controller->num_pov_events);
636
dx_dinput_device_changed (ControllerDXDInput *controller,
639
if (controller->guid && strcmp (guid, controller->guid) == 0)
641
dx_dinput_set_device (controller, guid);
642
g_object_notify (G_OBJECT (controller), "device");
647
dx_dinput_event_prepare (GSource *source,
656
dx_dinput_event_check (GSource *source)
658
DXDInputSource *input = (DXDInputSource *) source;
660
if (WaitForSingleObject (input->controller->event, 0) == WAIT_OBJECT_0)
662
ResetEvent (input->controller->event);
670
dx_dinput_event_dispatch (GSource *source,
671
GSourceFunc callback,
674
ControllerDXDInput * const input = ((DXDInputSource *) source)->controller;
675
GimpController *controller = &input->parent_instance;
676
const DIDATAFORMAT * const format = input->format;
677
const DIOBJECTDATAFORMAT *rgodf = format->rgodf;
681
GimpControllerEvent cevent = { 0, };
683
data = g_malloc (format->dwDataSize);
685
if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (input->didevice8,
693
g_object_ref (controller);
695
for (i = 0; i < input->num_buttons; i++)
697
if (input->prevdata[rgodf->dwOfs] != data[rgodf->dwOfs])
699
if (data[rgodf->dwOfs] & 0x80)
701
/* Click event, compatibility with Linux Input */
702
cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
703
cevent.any.source = controller;
704
cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON;
705
gimp_controller_event (controller, &cevent);
708
cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 1;
709
gimp_controller_event (controller, &cevent);
714
cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
715
cevent.any.source = controller;
716
cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 2;
717
gimp_controller_event (controller, &cevent);
723
for (i = 0; i < input->num_axes; i++)
725
LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs);
726
LONG *curr = (LONG *)(data+rgodf->dwOfs);
728
if (ABS (*prev - *curr) > 1)
730
cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE;
731
cevent.any.source = controller;
732
cevent.any.event_id =
733
input->num_button_events +
734
i*NUM_EVENTS_PER_AXIS;
735
g_value_init (&cevent.value.value, G_TYPE_DOUBLE);
736
if (*curr - *prev < 0)
738
g_value_set_double (&cevent.value.value, *prev - *curr);
742
cevent.any.event_id++;
743
g_value_set_double (&cevent.value.value, *curr - *prev);
745
gimp_controller_event (controller, &cevent);
746
g_value_unset (&cevent.value.value);
753
for (i = 0; i < input->num_sliders; i++)
755
LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs);
756
LONG *curr = (LONG *)(data+rgodf->dwOfs);
758
if (ABS (*prev - *curr) > 1)
760
cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE;
761
cevent.any.source = controller;
762
cevent.any.event_id =
763
input->num_button_events +
764
input->num_axis_events +
765
i*NUM_EVENTS_PER_SLIDER;
766
g_value_init (&cevent.value.value, G_TYPE_DOUBLE);
767
if (*curr - *prev < 0)
769
g_value_set_double (&cevent.value.value, *prev - *curr);
773
cevent.any.event_id++;
774
g_value_set_double (&cevent.value.value, *curr - *prev);
776
gimp_controller_event (controller, &cevent);
777
g_value_unset (&cevent.value.value);
784
for (i = 0; i < input->num_povs; i++)
786
LONG prev = *((LONG *)(input->prevdata+rgodf->dwOfs));
787
LONG curr = *((LONG *)(data+rgodf->dwOfs));
800
prevx = sin (prev/36000.*2.*G_PI);
801
prevy = cos (prev/36000.*2.*G_PI);
810
currx = sin (curr/36000.*2.*G_PI);
811
curry = cos (curr/36000.*2.*G_PI);
814
cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE;
815
cevent.any.source = controller;
816
cevent.any.event_id =
817
input->num_button_events +
818
input->num_axis_events +
819
input->num_slider_events +
820
i*NUM_EVENTS_PER_POV;
821
g_value_init (&cevent.value.value, G_TYPE_DOUBLE);
822
g_value_set_double (&cevent.value.value, currx - prevx);
823
gimp_controller_event (controller, &cevent);
824
cevent.any.event_id++;
825
g_value_set_double (&cevent.value.value, curry - prevy);
826
gimp_controller_event (controller, &cevent);
827
g_value_unset (&cevent.value.value);
830
cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
831
cevent.any.event_id++;
832
gimp_controller_event (controller, &cevent);
838
g_assert (rgodf == format->rgodf + format->dwNumObjs);
840
memmove (input->prevdata, data, format->dwDataSize);
842
g_object_unref (controller);
847
static GSourceFuncs dx_dinput_event_funcs = {
848
dx_dinput_event_prepare,
849
dx_dinput_event_check,
850
dx_dinput_event_dispatch,
856
dump_data_format (const DIDATAFORMAT *format)
861
g_print ("dwSize: %ld\n", format->dwSize);
862
g_print ("dwObjSize: %ld\n", format->dwObjSize);
863
g_print ("dwFlags: ");
864
if (format->dwFlags == DIDF_ABSAXIS)
865
g_print ("DIDF_ABSAXIS");
866
else if (format->dwFlags == DIDF_RELAXIS)
867
g_print ("DIDF_RELAXIS");
869
g_print ("%#lx", format->dwFlags);
871
g_print ("dwDataSize: %ld\n", format->dwDataSize);
872
g_print ("dwNumObjs: %ld\n", format->dwNumObjs);
874
for (i = 0; i < format->dwNumObjs; i++)
876
const DIOBJECTDATAFORMAT *oformat = (DIOBJECTDATAFORMAT *) (((char *) format->rgodf) + i*format->dwObjSize);
879
g_print ("Object %d:\n", i);
880
if (oformat->pguid == NULL)
881
g_print (" pguid: NULL\n");
884
UuidToString (oformat->pguid, &guid);
885
g_print (" pguid: %s\n", guid);
886
RpcStringFree (&guid);
889
g_print (" dwOfs: %ld\n", oformat->dwOfs);
890
g_print (" dwType: ");
891
switch (DIDFT_GETTYPE (oformat->dwType))
893
#define CASE(x) case DIDFT_##x: g_print ("DIDFT_"#x); break
904
default: g_print ("%#x", DIDFT_GETTYPE (oformat->dwType));
907
if (DIDFT_GETINSTANCE (oformat->dwType) == DIDFT_GETINSTANCE (DIDFT_ANYINSTANCE))
908
g_print ("ANYINSTANCE");
910
g_print ("#%d", DIDFT_GETINSTANCE (oformat->dwType));
911
#define BIT(x) if (oformat->dwType & DIDFT_##x) g_print (" "#x)
913
BIT (FFEFFECTTRIGGER);
920
g_print (" dwFlags:");
921
#define BIT(x) if (oformat->dwFlags & DIDOI_ASPECT##x) g_print (" DIDOI_ASPECT"#x)
922
switch (oformat->dwFlags & DIDOI_ASPECTACCEL)
924
case DIDOI_ASPECTPOSITION: g_print (" DIDOI_ASPECTPOSITION"); break;
925
case DIDOI_ASPECTVELOCITY: g_print (" DIDOI_ASPECTVELOCITY"); break;
926
case DIDOI_ASPECTACCEL: g_print (" DIDOI_ASPECTACCEL"); break;
928
if (oformat->dwFlags & DIDOI_ASPECTFORCE)
929
g_print (" DIDOI_ASPECTFORCE");
936
dx_dinput_setup_events (ControllerDXDInput *controller,
942
DXDInputSource *source;
944
if ((controller->event = CreateEvent (NULL, TRUE, FALSE, NULL)) == NULL)
946
g_set_error (error, 0, 0,
947
"CreateEvent failed: %s",
948
g_win32_error_message (GetLastError ()));
952
controller->format = g_new (DIDATAFORMAT, 1);
953
controller->format->dwSize = sizeof (DIDATAFORMAT);
954
controller->format->dwObjSize = sizeof (DIOBJECTDATAFORMAT);
956
dword.diph.dwSize = sizeof (DIPROPDWORD);
957
dword.diph.dwHeaderSize = sizeof (DIPROPHEADER);
958
dword.diph.dwObj = 0;
959
dword.diph.dwHow = DIPH_DEVICE;
961
/* Get the axis mode so we can use the same in the format */
962
if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8,
966
g_set_error (error, 0, 0,
967
"IDirectInputDevice8::GetParameters failed: %s",
968
g_win32_error_message (hresult));
972
controller->format->dwFlags = dword.dwData + 1;
974
controller->format->dwNumObjs =
975
controller->num_buttons +
976
controller->num_axes +
977
controller->num_sliders +
978
controller->num_povs;
980
controller->format->rgodf = g_new (DIOBJECTDATAFORMAT, controller->format->dwNumObjs);
983
controller->format->dwDataSize = 0;
985
for (i = 0; i < controller->num_buttons; i++)
987
controller->format->rgodf[k].pguid = NULL;
988
controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
989
controller->format->rgodf[k].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE (i);
990
controller->format->rgodf[k].dwFlags = 0;
991
controller->format->dwDataSize += 1;
995
controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4);
997
for (i = 0; i < controller->num_axes; i++)
999
controller->format->rgodf[k].pguid = NULL;
1000
controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
1001
controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i);
1002
controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION;
1003
controller->format->dwDataSize += 4;
1007
for (i = 0; i < controller->num_sliders; i++)
1009
controller->format->rgodf[k].pguid = NULL;
1010
controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
1011
controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i);
1012
controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION;
1013
controller->format->dwDataSize += 4;
1017
for (i = 0; i < controller->num_povs; i++)
1019
controller->format->rgodf[k].pguid = NULL;
1020
controller->format->rgodf[k].dwOfs = controller->format->dwDataSize;
1021
controller->format->rgodf[k].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE (i);
1022
controller->format->rgodf[k].dwFlags = 0;
1023
controller->format->dwDataSize += 4;
1027
g_assert (k == controller->format->dwNumObjs);
1029
controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4);
1030
controller->prevdata = g_malloc (controller->format->dwDataSize);
1032
dump_data_format (controller->format);
1034
if (FAILED ((hresult = IDirectInputDevice8_SetDataFormat (controller->didevice8,
1035
controller->format))))
1037
g_set_error (error, 0, 0,
1038
"IDirectInputDevice8::SetDataFormat failed: %s",
1039
g_win32_error_message (hresult));
1043
if (FAILED ((hresult = IDirectInputDevice8_SetEventNotification (controller->didevice8,
1044
controller->event))))
1046
g_set_error (error, 0, 0,
1047
"IDirectInputDevice8::SetEventNotification failed: %s",
1048
g_win32_error_message (hresult));
1052
if (FAILED ((hresult = IDirectInputDevice8_Acquire (controller->didevice8))))
1054
g_set_error (error, 0, 0,
1055
"IDirectInputDevice8::Acquire failed: %s",
1056
g_win32_error_message (hresult));
1060
if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (controller->didevice8,
1061
controller->format->dwDataSize,
1062
controller->prevdata))))
1064
g_set_error (error, 0, 0,
1065
"IDirectInputDevice8::GetDeviceState failed: %s",
1066
g_win32_error_message (hresult));
1070
source = (DXDInputSource *) g_source_new (&dx_dinput_event_funcs,
1071
sizeof (DXDInputSource));
1072
source->controller = controller;
1073
controller->source = (GSource *) source;
1075
controller->pollfd = g_new (GPollFD, 1);
1077
controller->pollfd->fd = (int) controller->event;
1078
controller->pollfd->events = G_IO_IN;
1080
g_source_add_poll (&source->source, controller->pollfd);
1081
g_source_attach (&source->source, NULL);
1086
IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL);
1088
g_free (controller->format->rgodf);
1089
g_free (controller->format);
1090
controller->format = NULL;
1091
g_free (controller->prevdata);
1092
controller->prevdata = NULL;
1094
CloseHandle (controller->event);
1095
controller->event = 0;
1101
dx_dinput_set_device (ControllerDXDInput *controller,
1104
GError *error = NULL;
1106
if (controller->guid)
1107
g_free (controller->guid);
1109
controller->guid = g_strdup (guid);
1111
g_object_set (controller, "name", _("DirectInput Events"), NULL);
1113
if (controller->guid && strlen (controller->guid))
1115
if (controller->store)
1116
controller->didevice8 =
1117
(LPDIRECTINPUTDEVICE8W) gimp_input_device_store_get_device_file (controller->store,
1122
g_object_set (controller, "state", _("No device configured"), NULL);
1127
if (controller->didevice8)
1129
if (!dx_dinput_get_device_info (controller, &error) ||
1130
!dx_dinput_setup_events (controller, &error))
1132
g_object_set (controller, "state", error->message, NULL);
1133
g_error_free (error);
1136
else if (controller->store)
1138
error = gimp_input_device_store_get_error (controller->store);
1142
g_object_set (controller, "state", error->message, NULL);
1143
g_error_free (error);
1147
g_object_set (controller, "state", _("Device not available"), NULL);