~ubuntu-branches/ubuntu/jaunty/gimp/jaunty-security

« back to all changes in this revision

Viewing changes to modules/controller_dx_dinput.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-05-02 16:33:03 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070502163303-bvzhjzbpw8qglc4y
Tags: 2.3.16-1ubuntu1
* Resynchronized with Debian, remaining Ubuntu changes:
  - debian/rules: i18n magic.
* debian/control.in:
  - Maintainer: Ubuntu Core Developers <ubuntu-devel@lists.ubuntu.com>
* debian/patches/02_help-message.patch,
  debian/patches/03_gimp.desktop.in.in.patch,
  debian/patches/10_dont_show_wizard.patch: updated.
* debian/patches/04_composite-signedness.patch,
  debian/patches/05_add-letter-spacing.patch: dropped, used upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GIMP - The GNU Image Manipulation Program
 
2
 * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis
 
3
 *
 
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>
 
8
 *
 
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.
 
13
 *
 
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.
 
18
 *
 
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.
 
22
 */
 
23
 
 
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.
 
29
 */
 
30
 
 
31
#include "config.h"
 
32
 
 
33
#include <errno.h>
 
34
#include <string.h>
 
35
#include <math.h>
 
36
 
 
37
#define _WIN32_WINNT 0x0501 
 
38
#include <windows.h>
 
39
#define DIRECTINPUT_VERSION 0x0800
 
40
#include <dinput.h>
 
41
 
 
42
#include <gtk/gtk.h>
 
43
 
 
44
#include "libgimpconfig/gimpconfig.h"
 
45
#include "libgimpmodule/gimpmodule.h"
 
46
#include "libgimpwidgets/gimpwidgets.h"
 
47
 
 
48
#define GIMP_ENABLE_CONTROLLER_UNDER_CONSTRUCTION
 
49
#include "libgimpwidgets/gimpcontroller.h"
 
50
 
 
51
#include "gimpinputdevicestore.h"
 
52
 
 
53
#include "libgimp/libgimp-intl.h"
 
54
 
 
55
enum
 
56
{
 
57
  PROP_0,
 
58
  PROP_DEVICE,
 
59
  PROP_DEVICE_STORE
 
60
};
 
61
 
 
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 */
 
66
 
 
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))
 
72
 
 
73
typedef struct _DXDInputSource          DXDInputSource;
 
74
typedef struct _ControllerDXDInput      ControllerDXDInput;
 
75
typedef struct _ControllerDXDInputClass ControllerDXDInputClass;
 
76
 
 
77
struct _DXDInputSource
 
78
{
 
79
  GSource             source;
 
80
  ControllerDXDInput *controller;
 
81
};
 
82
  
 
83
struct _ControllerDXDInput
 
84
{
 
85
  GimpController        parent_instance;
 
86
 
 
87
  GimpInputDeviceStore *store;
 
88
 
 
89
  LPDIRECTINPUTDEVICE8W didevice8;
 
90
 
 
91
  HANDLE                event;
 
92
 
 
93
  GPollFD              *pollfd;
 
94
 
 
95
  gint                  num_buttons;
 
96
  gint                  num_button_events;
 
97
 
 
98
  gint                  num_axes;
 
99
  gint                  num_axis_events;
 
100
 
 
101
  gint                  num_sliders;
 
102
  gint                  num_slider_events;
 
103
 
 
104
  gint                  num_povs;
 
105
  gint                  num_pov_events;
 
106
  
 
107
  gint                  num_events;
 
108
  gchar               **event_names;
 
109
  gchar               **event_blurbs;
 
110
 
 
111
  DIDATAFORMAT         *format;
 
112
 
 
113
  guchar               *prevdata;
 
114
 
 
115
  gchar                *guid;
 
116
  GSource              *source;
 
117
 
 
118
  /* Variables used by enumeration callbacks only*/
 
119
  gint                  bei, bi, aei, ai, sei, si, pei, pi;
 
120
};
 
121
 
 
122
struct _ControllerDXDInputClass
 
123
{
 
124
  GimpControllerClass  parent_class;
 
125
};
 
126
 
 
127
 
 
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,
 
134
                                      guint           property_id,
 
135
                                      const GValue   *value,
 
136
                                      GParamSpec     *pspec);
 
137
static void   dx_dinput_get_property (GObject        *object,
 
138
                                      guint           property_id,
 
139
                                      GValue         *value,
 
140
                                      GParamSpec     *pspec);
 
141
 
 
142
static gint          dx_dinput_get_n_events     (GimpController *controller);
 
143
static const gchar * dx_dinput_get_event_name   (GimpController *controller,
 
144
                                                 gint            event_id);
 
145
static const gchar * dx_dinput_get_event_blurb  (GimpController *controller,
 
146
                                                 gint            event_id);
 
147
 
 
148
static void          dx_dinput_device_changed   (ControllerDXDInput *controller,
 
149
                                                 const gchar        *guid);
 
150
static gboolean      dx_dinput_set_device       (ControllerDXDInput *controller,
 
151
                                                 const gchar        *guid);
 
152
 
 
153
 
 
154
static const GimpModuleInfo dx_dinput_info =
 
155
{
 
156
  GIMP_MODULE_ABI_VERSION,
 
157
  N_("DirectX DirectInput event controller"),
 
158
  "Tor Lillqvist <tml@iki.fi>",
 
159
  "v0.1",
 
160
  "(c) 2004-2007, released under the GPL",
 
161
  "2004-2007"
 
162
};
 
163
 
 
164
 
 
165
static GType                controller_type = 0;
 
166
static GimpControllerClass *parent_class    = NULL;
 
167
 
 
168
 
 
169
G_MODULE_EXPORT const GimpModuleInfo *
 
170
gimp_module_query (GTypeModule *module)
 
171
{
 
172
  return &dx_dinput_info;
 
173
}
 
174
 
 
175
G_MODULE_EXPORT gboolean
 
176
gimp_module_register (GTypeModule *module)
 
177
{
 
178
  gimp_input_device_store_get_type (module);
 
179
  dx_dinput_get_type (module);
 
180
 
 
181
  return TRUE;
 
182
}
 
183
 
 
184
 
 
185
GType
 
186
dx_dinput_get_type (GTypeModule *module)
 
187
{
 
188
  if (! controller_type)
 
189
    {
 
190
      const GTypeInfo controller_info =
 
191
      {
 
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),
 
199
        0,              /* n_preallocs    */
 
200
        (GInstanceInitFunc) dx_dinput_init
 
201
      };
 
202
 
 
203
      controller_type = g_type_module_register_type (module,
 
204
                                                     GIMP_TYPE_CONTROLLER,
 
205
                                                     "ControllerDXDInput",
 
206
                                                     &controller_info, 0);
 
207
    }
 
208
 
 
209
  return controller_type;
 
210
}
 
211
 
 
212
static void
 
213
dx_dinput_class_init (ControllerDXDInputClass *klass)
 
214
{
 
215
  GimpControllerClass *controller_class = GIMP_CONTROLLER_CLASS (klass);
 
216
  GObjectClass        *object_class     = G_OBJECT_CLASS (klass);
 
217
 
 
218
  parent_class = g_type_class_peek_parent (klass);
 
219
 
 
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;
 
224
 
 
225
  g_object_class_install_property (object_class, PROP_DEVICE,
 
226
                                   g_param_spec_string ("device",
 
227
                                                        _("Device:"),
 
228
                                                        _("The device to read DirectInput events from."),
 
229
                                                        NULL,
 
230
                                                        GIMP_CONFIG_PARAM_FLAGS));
 
231
  g_object_class_install_property (object_class, PROP_DEVICE_STORE,
 
232
                                   g_param_spec_object ("device-values",
 
233
                                                        NULL, NULL,
 
234
                                                        GIMP_TYPE_INPUT_DEVICE_STORE,
 
235
                                                        G_PARAM_READABLE));
 
236
 
 
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;
 
240
 
 
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;
 
244
}
 
245
 
 
246
static void
 
247
dx_dinput_init (ControllerDXDInput *controller)
 
248
{
 
249
  controller->store = gimp_input_device_store_new ();
 
250
 
 
251
  if (controller->store)
 
252
    {
 
253
      g_signal_connect_swapped (controller->store, "device-added",
 
254
                                G_CALLBACK (dx_dinput_device_changed),
 
255
                                controller);
 
256
      g_signal_connect_swapped (controller->store, "device-removed",
 
257
                                G_CALLBACK (dx_dinput_device_changed),
 
258
                                controller);
 
259
    }
 
260
}
 
261
 
 
262
static void
 
263
dx_dinput_dispose (GObject *object)
 
264
{
 
265
  ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
 
266
 
 
267
  dx_dinput_set_device (controller, NULL);
 
268
 
 
269
  G_OBJECT_CLASS (parent_class)->dispose (object);
 
270
}
 
271
 
 
272
static void
 
273
dx_dinput_finalize (GObject *object)
 
274
{
 
275
  ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
 
276
 
 
277
  if (controller->source != NULL)
 
278
    {
 
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);
 
282
    }
 
283
 
 
284
  if (controller->didevice8)
 
285
    IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL);
 
286
 
 
287
  if (controller->format != NULL)
 
288
    {
 
289
      g_free (controller->format->rgodf);
 
290
      g_free (controller->format);
 
291
      controller->format = NULL;
 
292
    }
 
293
 
 
294
  g_free (controller->prevdata);
 
295
  controller->prevdata = NULL;
 
296
 
 
297
  if (controller->event != NULL)
 
298
    {
 
299
      CloseHandle (controller->event);
 
300
      controller->event = 0;
 
301
    }
 
302
 
 
303
  if (controller->store)
 
304
    {
 
305
      g_object_unref (controller->store);
 
306
      controller->store = NULL;
 
307
    }
 
308
 
 
309
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
310
}
 
311
 
 
312
static void
 
313
dx_dinput_set_property (GObject      *object,
 
314
                        guint         property_id,
 
315
                        const GValue *value,
 
316
                        GParamSpec   *pspec)
 
317
{
 
318
  ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
 
319
 
 
320
  switch (property_id)
 
321
    {
 
322
    case PROP_DEVICE:
 
323
      dx_dinput_set_device (controller, g_value_get_string (value));
 
324
      break;
 
325
    default:
 
326
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
327
      break;
 
328
    }
 
329
}
 
330
 
 
331
static void
 
332
dx_dinput_get_property (GObject    *object,
 
333
                        guint       property_id,
 
334
                        GValue     *value,
 
335
                        GParamSpec *pspec)
 
336
{
 
337
  ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object);
 
338
 
 
339
  switch (property_id)
 
340
    {
 
341
    case PROP_DEVICE:
 
342
      g_value_set_string (value, controller->guid);
 
343
      break;
 
344
    case PROP_DEVICE_STORE:
 
345
      g_value_set_object (value, controller->store);
 
346
      break;
 
347
    default:
 
348
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
349
      break;
 
350
    }
 
351
}
 
352
 
 
353
static gint
 
354
dx_dinput_get_n_events (GimpController *controller)
 
355
{
 
356
  ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller;
 
357
  
 
358
  return cdxdi->num_events;
 
359
}
 
360
 
 
361
static const gchar *
 
362
dx_dinput_get_event_name
 
363
 (GimpController *controller,
 
364
                          gint            event_id)
 
365
{
 
366
  ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller;
 
367
 
 
368
  if (event_id < 0 || event_id >= cdxdi->num_events)
 
369
    return NULL;
 
370
  
 
371
  return cdxdi->event_names[event_id];
 
372
}
 
373
 
 
374
static const gchar *
 
375
dx_dinput_get_event_blurb (GimpController *controller,
 
376
                           gint            event_id)
 
377
{
 
378
  ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller;
 
379
 
 
380
  if (event_id < 0 || event_id >= cdxdi->num_events)
 
381
    return NULL;
 
382
  
 
383
  return cdxdi->event_blurbs[event_id];
 
384
}
 
385
 
 
386
static BOOL CALLBACK
 
387
count_objects (const DIDEVICEOBJECTINSTANCEW *doi,
 
388
               void                          *user_data)
 
389
{
 
390
  ControllerDXDInput *controller = (ControllerDXDInput *) user_data;
 
391
  HRESULT             hresult;
 
392
  DIPROPRANGE         range;
 
393
 
 
394
  if (doi->dwType & DIDFT_AXIS)
 
395
    {
 
396
      /* Set reported range to  physical range, not to give upper
 
397
       * level software any false impression of higher accuracy.
 
398
       */
 
399
 
 
400
      range.diph.dwSize = sizeof (DIPROPRANGE);
 
401
      range.diph.dwHeaderSize = sizeof (DIPROPHEADER);
 
402
      range.diph.dwObj = doi->dwType;
 
403
      range.diph.dwHow = DIPH_BYID;
 
404
 
 
405
      if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8,
 
406
                                                              DIPROP_PHYSICALRANGE,
 
407
                                                              &range.diph))))
 
408
        g_warning ("IDirectInputDevice8::GetProperty failed: %s",
 
409
                   g_win32_error_message (hresult));
 
410
      else
 
411
        {
 
412
          if (FAILED ((hresult = IDirectInputDevice8_SetProperty (controller->didevice8,
 
413
                                                                  DIPROP_RANGE,
 
414
                                                                  &range.diph))))
 
415
            g_warning ("IDirectInputDevice8::SetProperty failed: %s",
 
416
                       g_win32_error_message (hresult));
 
417
        }
 
418
    }
 
419
 
 
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++;
 
433
 
 
434
  return DIENUM_CONTINUE;
 
435
}
 
436
 
 
437
static BOOL CALLBACK
 
438
name_objects (const DIDEVICEOBJECTINSTANCEW *doi,
 
439
              void                          *user_data)
 
440
{
 
441
  ControllerDXDInput *controller = (ControllerDXDInput *) user_data;
 
442
 
 
443
  if (IsEqualGUID (&doi->guidType, &GUID_Button))
 
444
    {
 
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);
 
447
      controller->bei++;
 
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);
 
450
      controller->bei++;
 
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);
 
453
      controller->bei++;
 
454
 
 
455
      g_assert (controller->bi < controller->num_buttons);
 
456
 
 
457
      controller->bi++;
 
458
    }
 
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))
 
465
    {
 
466
      if (IsEqualGUID (&doi->guidType, &GUID_XAxis))
 
467
        {
 
468
          controller->event_names[controller->aei] = g_strdup ("x-move-left");
 
469
          controller->event_blurbs[controller->aei] = g_strdup (_("X Move Left"));
 
470
          controller->aei++;
 
471
          controller->event_names[controller->aei] = g_strdup ("x-move-right");
 
472
          controller->event_blurbs[controller->aei] = g_strdup (_("X Move Right"));
 
473
          controller->aei++;
 
474
        }
 
475
      else if (IsEqualGUID (&doi->guidType, &GUID_YAxis))
 
476
        {
 
477
          controller->event_names[controller->aei] = g_strdup ("y-move-away");
 
478
          controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Away"));
 
479
          controller->aei++;
 
480
          controller->event_names[controller->aei] = g_strdup ("y-move-near");
 
481
          controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Near"));
 
482
          controller->aei++;
 
483
        }
 
484
      else if (IsEqualGUID (&doi->guidType, &GUID_ZAxis))
 
485
        {
 
486
          controller->event_names[controller->aei] = g_strdup ("z-move-up");
 
487
          controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Up"));
 
488
          controller->aei++;
 
489
          controller->event_names[controller->aei] = g_strdup ("z-move-down");
 
490
          controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Down"));
 
491
          controller->aei++;
 
492
        }
 
493
      else if (IsEqualGUID (&doi->guidType, &GUID_RxAxis))
 
494
        {
 
495
          controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-away");
 
496
          controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Away"));
 
497
          controller->aei++;
 
498
          controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-near");
 
499
          controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Near"));
 
500
          controller->aei++;
 
501
        }
 
502
      else if (IsEqualGUID (&doi->guidType, &GUID_RyAxis))
 
503
        {
 
504
          controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-right");
 
505
          controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Right"));
 
506
          controller->aei++;
 
507
          controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-left");
 
508
          controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Left"));
 
509
          controller->aei++;
 
510
        }
 
511
      else if (IsEqualGUID (&doi->guidType, &GUID_RzAxis))
 
512
        {
 
513
          controller->event_names[controller->aei] = g_strdup ("z-axis-turn-left");
 
514
          controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Left"));
 
515
          controller->aei++;
 
516
          controller->event_names[controller->aei] = g_strdup ("z-axis-turn-right");
 
517
          controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Right"));
 
518
          controller->aei++;
 
519
        }
 
520
 
 
521
      g_assert (controller->ai < controller->num_axes);
 
522
 
 
523
      controller->ai++;
 
524
    }
 
525
  else if (IsEqualGUID (&doi->guidType, &GUID_Slider))
 
526
    {
 
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);
 
529
      controller->sei++;
 
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);
 
532
      controller->sei++;
 
533
 
 
534
      g_assert (controller->si < controller->num_sliders);
 
535
 
 
536
      controller->si++;
 
537
    }
 
538
  else if (IsEqualGUID (&doi->guidType, &GUID_POV))
 
539
    {
 
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);
 
542
      controller->pei++;
 
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);
 
545
      controller->pei++;
 
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);
 
548
      controller->pei++;
 
549
 
 
550
      g_assert (controller->pi < controller->num_povs);
 
551
 
 
552
      controller->pi++;
 
553
    }
 
554
 
 
555
  return DIENUM_CONTINUE;
 
556
}
 
557
 
 
558
static gboolean
 
559
dx_dinput_get_device_info (ControllerDXDInput *controller,
 
560
                           GError            **error)
 
561
{
 
562
  HRESULT hresult;
 
563
 
 
564
  controller->num_buttons =
 
565
    controller->num_axes =
 
566
    controller->num_sliders =
 
567
    controller->num_povs = 0;
 
568
  
 
569
  if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8,
 
570
                                                          count_objects,
 
571
                                                          controller,
 
572
                                                          DIDFT_AXIS|
 
573
                                                          DIDFT_BUTTON|
 
574
                                                          DIDFT_POV|
 
575
                                                          DIDFT_PSHBUTTON|
 
576
                                                          DIDFT_RELAXIS|
 
577
                                                          DIDFT_TGLBUTTON))))
 
578
    {
 
579
      g_set_error (error, 0, 0,
 
580
                   "IDirectInputDevice8::EnumObjects failed: %s",
 
581
                   g_win32_error_message (hresult));
 
582
      return FALSE;
 
583
    }
 
584
 
 
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;
 
589
 
 
590
  controller->num_events =
 
591
    controller->num_button_events +
 
592
    controller->num_axis_events +
 
593
    controller->num_slider_events +
 
594
    controller->num_pov_events;
 
595
 
 
596
  controller->event_names = g_new (gchar *, controller->num_events);
 
597
  controller->event_blurbs = g_new (gchar *, controller->num_events);
 
598
 
 
599
  controller->bi = controller->ai = controller->si = controller->pi = 0;
 
600
 
 
601
  controller->bei = 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;
 
605
 
 
606
  if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8,
 
607
                                                          name_objects,
 
608
                                                          controller,
 
609
                                                          DIDFT_AXIS|
 
610
                                                          DIDFT_BUTTON|
 
611
                                                          DIDFT_POV|
 
612
                                                          DIDFT_PSHBUTTON|
 
613
                                                          DIDFT_RELAXIS|
 
614
                                                          DIDFT_TGLBUTTON))))
 
615
    {
 
616
      g_free (controller->event_names);
 
617
      g_free (controller->event_blurbs);
 
618
 
 
619
      g_set_error (error, 0, 0,
 
620
                   "IDirectInputDevice8::EnumObjects failed: %s",
 
621
                   g_win32_error_message (hresult));
 
622
      return FALSE;
 
623
    }
 
624
 
 
625
 
 
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);
 
630
 
 
631
  return TRUE;
 
632
}
 
633
 
 
634
 
 
635
static void
 
636
dx_dinput_device_changed (ControllerDXDInput *controller,
 
637
                          const gchar        *guid)
 
638
{
 
639
  if (controller->guid && strcmp (guid, controller->guid) == 0)
 
640
    {
 
641
      dx_dinput_set_device (controller, guid);
 
642
      g_object_notify (G_OBJECT (controller), "device");
 
643
    }
 
644
}
 
645
 
 
646
static gboolean
 
647
dx_dinput_event_prepare (GSource *source,
 
648
                         gint    *timeout)
 
649
{
 
650
  *timeout = -1;
 
651
 
 
652
  return FALSE;
 
653
}
 
654
 
 
655
static gboolean
 
656
dx_dinput_event_check (GSource *source)
 
657
{
 
658
  DXDInputSource *input = (DXDInputSource *) source;
 
659
 
 
660
  if (WaitForSingleObject (input->controller->event, 0) == WAIT_OBJECT_0)
 
661
    {
 
662
      ResetEvent (input->controller->event);
 
663
      return TRUE;
 
664
    }
 
665
 
 
666
  return FALSE;
 
667
}
 
668
 
 
669
static gboolean
 
670
dx_dinput_event_dispatch (GSource     *source,
 
671
                          GSourceFunc  callback,
 
672
                          gpointer     user_data)
 
673
{
 
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;
 
678
  HRESULT                          hresult;
 
679
  guchar                          *data;
 
680
  gint                             i;
 
681
  GimpControllerEvent              cevent = { 0, };
 
682
  
 
683
  data = g_malloc (format->dwDataSize);
 
684
 
 
685
  if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (input->didevice8,
 
686
                                                             format->dwDataSize,
 
687
                                                             data))))
 
688
    {
 
689
      g_free (data);
 
690
      return TRUE;
 
691
    }
 
692
 
 
693
  g_object_ref (controller);
 
694
 
 
695
  for (i = 0; i < input->num_buttons; i++)
 
696
    {
 
697
      if (input->prevdata[rgodf->dwOfs] != data[rgodf->dwOfs])
 
698
        {
 
699
          if (data[rgodf->dwOfs] & 0x80)
 
700
            {
 
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);
 
706
 
 
707
              /* Press event */
 
708
              cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 1;
 
709
              gimp_controller_event (controller, &cevent);
 
710
            }
 
711
          else
 
712
            {
 
713
              /* Release event */
 
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);
 
718
            }
 
719
        }
 
720
      rgodf++;
 
721
    }
 
722
 
 
723
  for (i = 0; i < input->num_axes; i++)
 
724
    {
 
725
      LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs);
 
726
      LONG *curr = (LONG *)(data+rgodf->dwOfs);
 
727
 
 
728
      if (ABS (*prev - *curr) > 1)
 
729
        {
 
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)
 
737
            {
 
738
              g_value_set_double (&cevent.value.value, *prev - *curr);
 
739
            }
 
740
          else
 
741
            {
 
742
              cevent.any.event_id++;
 
743
              g_value_set_double (&cevent.value.value, *curr - *prev);
 
744
            }
 
745
          gimp_controller_event (controller, &cevent);
 
746
          g_value_unset (&cevent.value.value);
 
747
        }
 
748
      else
 
749
        *curr = *prev;
 
750
      rgodf++;
 
751
    }
 
752
  
 
753
  for (i = 0; i < input->num_sliders; i++)
 
754
    {
 
755
      LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs);
 
756
      LONG *curr = (LONG *)(data+rgodf->dwOfs);
 
757
 
 
758
      if (ABS (*prev - *curr) > 1)
 
759
        {
 
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)
 
768
            {
 
769
              g_value_set_double (&cevent.value.value, *prev - *curr);
 
770
            }
 
771
          else
 
772
            {
 
773
              cevent.any.event_id++;
 
774
              g_value_set_double (&cevent.value.value, *curr - *prev);
 
775
            }
 
776
          gimp_controller_event (controller, &cevent);
 
777
          g_value_unset (&cevent.value.value);
 
778
        }
 
779
      else
 
780
        *curr = *prev;
 
781
      rgodf++;
 
782
    }
 
783
  
 
784
  for (i = 0; i < input->num_povs; i++)
 
785
    {
 
786
      LONG prev = *((LONG *)(input->prevdata+rgodf->dwOfs));
 
787
      LONG curr = *((LONG *)(data+rgodf->dwOfs));
 
788
      double prevx, prevy;
 
789
      double currx, curry;
 
790
 
 
791
      if (prev != curr)
 
792
        {
 
793
          if (prev == -1)
 
794
            {
 
795
              prevx = 0.;
 
796
              prevy = 0.;
 
797
            }
 
798
          else
 
799
            {
 
800
              prevx = sin (prev/36000.*2.*G_PI);
 
801
              prevy = cos (prev/36000.*2.*G_PI);
 
802
            }
 
803
          if (curr == -1)
 
804
            {
 
805
              currx = 0.;
 
806
              curry = 0.;
 
807
            }
 
808
          else
 
809
            {
 
810
              currx = sin (curr/36000.*2.*G_PI);
 
811
              curry = cos (curr/36000.*2.*G_PI);
 
812
            }
 
813
 
 
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);
 
828
          if (curr == -1)
 
829
            {
 
830
              cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER;
 
831
              cevent.any.event_id++;
 
832
              gimp_controller_event (controller, &cevent);
 
833
            }
 
834
        }
 
835
      rgodf++;
 
836
    }
 
837
  
 
838
  g_assert (rgodf == format->rgodf + format->dwNumObjs);
 
839
 
 
840
  memmove (input->prevdata, data, format->dwDataSize);
 
841
 
 
842
  g_object_unref (controller);
 
843
 
 
844
  return TRUE;
 
845
}
 
846
 
 
847
static GSourceFuncs dx_dinput_event_funcs = {
 
848
  dx_dinput_event_prepare,
 
849
  dx_dinput_event_check,
 
850
  dx_dinput_event_dispatch,
 
851
  NULL
 
852
};
 
853
 
 
854
 
 
855
static void
 
856
dump_data_format (const DIDATAFORMAT *format)
 
857
{
 
858
#ifdef GIMP_UNSTABLE
 
859
  gint i;
 
860
 
 
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");
 
868
  else
 
869
    g_print ("%#lx", format->dwFlags);
 
870
  g_print ("\n");
 
871
  g_print ("dwDataSize: %ld\n", format->dwDataSize);
 
872
  g_print ("dwNumObjs: %ld\n", format->dwNumObjs);
 
873
 
 
874
  for (i = 0; i < format->dwNumObjs; i++)
 
875
    {
 
876
      const DIOBJECTDATAFORMAT *oformat = (DIOBJECTDATAFORMAT *) (((char *) format->rgodf) + i*format->dwObjSize);
 
877
      unsigned char *guid;
 
878
      
 
879
      g_print ("Object %d:\n", i);
 
880
      if (oformat->pguid == NULL)
 
881
        g_print ("  pguid: NULL\n");
 
882
      else
 
883
        {
 
884
          UuidToString (oformat->pguid, &guid);
 
885
          g_print ("  pguid: %s\n", guid);
 
886
          RpcStringFree (&guid);
 
887
        }
 
888
 
 
889
      g_print ("  dwOfs: %ld\n", oformat->dwOfs);
 
890
      g_print ("  dwType: ");
 
891
      switch (DIDFT_GETTYPE (oformat->dwType))
 
892
        {
 
893
#define CASE(x) case DIDFT_##x: g_print ("DIDFT_"#x); break
 
894
        CASE (RELAXIS);
 
895
        CASE (ABSAXIS);
 
896
        CASE (AXIS);
 
897
        CASE (PSHBUTTON);
 
898
        CASE (TGLBUTTON);
 
899
        CASE (BUTTON);
 
900
        CASE (POV);
 
901
        CASE (COLLECTION);
 
902
        CASE (NODATA);
 
903
#undef CASE
 
904
        default: g_print ("%#x", DIDFT_GETTYPE (oformat->dwType));
 
905
        }
 
906
      g_print (" ");
 
907
      if (DIDFT_GETINSTANCE (oformat->dwType) == DIDFT_GETINSTANCE (DIDFT_ANYINSTANCE))
 
908
        g_print ("ANYINSTANCE");
 
909
      else
 
910
        g_print ("#%d", DIDFT_GETINSTANCE (oformat->dwType));
 
911
#define BIT(x) if (oformat->dwType & DIDFT_##x) g_print (" "#x)
 
912
      BIT (FFACTUATOR);
 
913
      BIT (FFEFFECTTRIGGER);
 
914
      BIT (OUTPUT);
 
915
      BIT (VENDORDEFINED);
 
916
      BIT (ALIAS);
 
917
      BIT (OPTIONAL);
 
918
#undef BIT
 
919
      g_print ("\n");
 
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)
 
923
        {
 
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;
 
927
        }
 
928
      if (oformat->dwFlags & DIDOI_ASPECTFORCE)
 
929
        g_print (" DIDOI_ASPECTFORCE");
 
930
      g_print ("\n");
 
931
    }
 
932
#endif
 
933
}
 
934
 
 
935
static gboolean
 
936
dx_dinput_setup_events (ControllerDXDInput *controller,
 
937
                        GError            **error)
 
938
{
 
939
  HRESULT         hresult;
 
940
  DIPROPDWORD     dword;
 
941
  gint            i, k;
 
942
  DXDInputSource *source;
 
943
 
 
944
  if ((controller->event = CreateEvent (NULL, TRUE, FALSE, NULL)) == NULL)
 
945
    {
 
946
      g_set_error (error, 0, 0,
 
947
                   "CreateEvent failed: %s",
 
948
                   g_win32_error_message (GetLastError ()));
 
949
      return FALSE;
 
950
    }
 
951
 
 
952
  controller->format = g_new (DIDATAFORMAT, 1);
 
953
  controller->format->dwSize = sizeof (DIDATAFORMAT);
 
954
  controller->format->dwObjSize = sizeof (DIOBJECTDATAFORMAT);
 
955
 
 
956
  dword.diph.dwSize = sizeof (DIPROPDWORD);
 
957
  dword.diph.dwHeaderSize = sizeof (DIPROPHEADER);
 
958
  dword.diph.dwObj = 0;
 
959
  dword.diph.dwHow = DIPH_DEVICE;
 
960
 
 
961
  /* Get the axis mode so we can use the same in the format */
 
962
  if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8,
 
963
                                                          DIPROP_AXISMODE,
 
964
                                                          &dword.diph))))
 
965
    {
 
966
      g_set_error (error, 0, 0,
 
967
                   "IDirectInputDevice8::GetParameters failed: %s",
 
968
                   g_win32_error_message (hresult));
 
969
      goto fail0;
 
970
    }
 
971
                                                          
 
972
  controller->format->dwFlags = dword.dwData + 1;
 
973
 
 
974
  controller->format->dwNumObjs =
 
975
    controller->num_buttons +
 
976
    controller->num_axes +
 
977
    controller->num_sliders +
 
978
    controller->num_povs;
 
979
 
 
980
  controller->format->rgodf = g_new (DIOBJECTDATAFORMAT, controller->format->dwNumObjs);
 
981
 
 
982
  k = 0;
 
983
  controller->format->dwDataSize = 0;
 
984
 
 
985
  for (i = 0; i < controller->num_buttons; i++)
 
986
    {
 
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;
 
992
      k++;
 
993
    }
 
994
 
 
995
  controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4);
 
996
  
 
997
  for (i = 0; i < controller->num_axes; i++)
 
998
    {
 
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;
 
1004
      k++;
 
1005
    }
 
1006
  
 
1007
  for (i = 0; i < controller->num_sliders; i++)
 
1008
    {
 
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;
 
1014
      k++;
 
1015
    }
 
1016
 
 
1017
  for (i = 0; i < controller->num_povs; i++)
 
1018
    {
 
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;
 
1024
      k++;
 
1025
    }
 
1026
 
 
1027
  g_assert (k == controller->format->dwNumObjs);
 
1028
 
 
1029
  controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4);
 
1030
  controller->prevdata = g_malloc (controller->format->dwDataSize);
 
1031
 
 
1032
  dump_data_format (controller->format);
 
1033
 
 
1034
  if (FAILED ((hresult = IDirectInputDevice8_SetDataFormat (controller->didevice8,
 
1035
                                                            controller->format))))
 
1036
    {
 
1037
      g_set_error (error, 0, 0,
 
1038
                   "IDirectInputDevice8::SetDataFormat failed: %s",
 
1039
                   g_win32_error_message (hresult));
 
1040
      goto fail1;
 
1041
    }
 
1042
 
 
1043
  if (FAILED ((hresult = IDirectInputDevice8_SetEventNotification (controller->didevice8,
 
1044
                                                                   controller->event))))
 
1045
    {
 
1046
      g_set_error (error, 0, 0,
 
1047
                   "IDirectInputDevice8::SetEventNotification failed: %s",
 
1048
                   g_win32_error_message (hresult));
 
1049
      goto fail2;
 
1050
    }
 
1051
 
 
1052
  if (FAILED ((hresult = IDirectInputDevice8_Acquire (controller->didevice8))))
 
1053
    {
 
1054
      g_set_error (error, 0, 0,
 
1055
                   "IDirectInputDevice8::Acquire failed: %s",
 
1056
                   g_win32_error_message (hresult));
 
1057
      goto fail2;
 
1058
    }
 
1059
    
 
1060
  if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (controller->didevice8,
 
1061
                                                             controller->format->dwDataSize,
 
1062
                                                             controller->prevdata))))
 
1063
    {
 
1064
      g_set_error (error, 0, 0,
 
1065
                   "IDirectInputDevice8::GetDeviceState failed: %s",
 
1066
                   g_win32_error_message (hresult));
 
1067
      goto fail2;
 
1068
    }
 
1069
 
 
1070
  source = (DXDInputSource *) g_source_new (&dx_dinput_event_funcs,
 
1071
                                            sizeof (DXDInputSource));
 
1072
  source->controller = controller;
 
1073
  controller->source = (GSource *) source;
 
1074
 
 
1075
  controller->pollfd = g_new (GPollFD, 1);
 
1076
 
 
1077
  controller->pollfd->fd = (int) controller->event;
 
1078
  controller->pollfd->events = G_IO_IN;
 
1079
 
 
1080
  g_source_add_poll (&source->source, controller->pollfd);
 
1081
  g_source_attach (&source->source, NULL);
 
1082
 
 
1083
  return TRUE;
 
1084
 
 
1085
 fail2:
 
1086
  IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL);
 
1087
 fail1:
 
1088
  g_free (controller->format->rgodf);
 
1089
  g_free (controller->format);
 
1090
  controller->format = NULL;
 
1091
  g_free (controller->prevdata);
 
1092
  controller->prevdata = NULL;
 
1093
 fail0:
 
1094
  CloseHandle (controller->event);
 
1095
  controller->event = 0;
 
1096
 
 
1097
  return FALSE;
 
1098
}
 
1099
 
 
1100
static gboolean
 
1101
dx_dinput_set_device (ControllerDXDInput *controller,
 
1102
                      const gchar        *guid)
 
1103
{
 
1104
  GError *error = NULL;
 
1105
 
 
1106
  if (controller->guid)
 
1107
    g_free (controller->guid);
 
1108
 
 
1109
  controller->guid = g_strdup (guid);
 
1110
 
 
1111
  g_object_set (controller, "name", _("DirectInput Events"), NULL);
 
1112
 
 
1113
  if (controller->guid && strlen (controller->guid))
 
1114
    {
 
1115
      if (controller->store)
 
1116
        controller->didevice8 =
 
1117
          (LPDIRECTINPUTDEVICE8W) gimp_input_device_store_get_device_file (controller->store,
 
1118
                                                                           controller->guid);
 
1119
    }
 
1120
  else
 
1121
    {
 
1122
      g_object_set (controller, "state", _("No device configured"), NULL);
 
1123
 
 
1124
      return FALSE;
 
1125
    }
 
1126
 
 
1127
  if (controller->didevice8)
 
1128
    {
 
1129
      if (!dx_dinput_get_device_info (controller, &error) ||
 
1130
          !dx_dinput_setup_events (controller, &error))
 
1131
        {
 
1132
          g_object_set (controller, "state", error->message, NULL);
 
1133
          g_error_free (error);
 
1134
        }
 
1135
    }
 
1136
  else if (controller->store)
 
1137
    {
 
1138
      error = gimp_input_device_store_get_error (controller->store);
 
1139
 
 
1140
      if (error)
 
1141
        {
 
1142
          g_object_set (controller, "state", error->message, NULL);
 
1143
          g_error_free (error);
 
1144
        }
 
1145
      else
 
1146
        {
 
1147
          g_object_set (controller, "state", _("Device not available"), NULL);
 
1148
        }
 
1149
    }
 
1150
 
 
1151
  return FALSE;
 
1152
}