From 7b320c7bf66156b6fc1c8b556a42fdaf14a187db Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Sun, 21 Nov 2010 16:09:09 +0100 Subject: [PATCH] Get rid of DOS line endings --- app/base/base-utils.c | 280 ++-- app/base/base-utils.h | 56 +- build/.gitignore | 2 +- build/Makefile.am | 2 +- build/windows/gimprc.rule | 20 +- modules/controller-dx-dinput.c | 2246 ++++++++++++++++---------------- 6 files changed, 1303 insertions(+), 1303 deletions(-) diff --git a/app/base/base-utils.c b/app/base/base-utils.c index f323bb50ca..757f58d63f 100644 --- a/app/base/base-utils.c +++ b/app/base/base-utils.c @@ -1,140 +1,140 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif - -#include - -#ifdef G_OS_WIN32 -#define _WIN32_WINNT 0x0500 -#include -#include -#endif - -#ifdef G_OS_UNIX -/* For get_backtrace() */ -#include -#include -#include -#endif - -#include "base-utils.h" - - -#define NUM_PROCESSORS_DEFAULT 1 -#define MAX_FUNC 100 - - -/* public functions */ - -gint -get_pid (void) -{ - return (gint) getpid (); -} - -gint -get_number_of_processors (void) -{ - gint retval = NUM_PROCESSORS_DEFAULT; - -#ifdef G_OS_UNIX -#if defined(HAVE_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) - retval = sysconf (_SC_NPROCESSORS_ONLN); -#endif -#endif -#ifdef G_OS_WIN32 - SYSTEM_INFO system_info; - - GetSystemInfo (&system_info); - - retval = system_info.dwNumberOfProcessors; -#endif - - return retval; -} - -guint64 -get_physical_memory_size (void) -{ -#ifdef G_OS_UNIX -#if defined(HAVE_UNISTD_H) && defined(_SC_PHYS_PAGES) && defined (_SC_PAGE_SIZE) - return (guint64) sysconf (_SC_PHYS_PAGES) * sysconf (_SC_PAGE_SIZE); -#endif -#endif - -#ifdef G_OS_WIN32 -# if defined(_MSC_VER) && (_MSC_VER <= 1200) - MEMORYSTATUS memory_status; - memory_status.dwLength = sizeof (memory_status); - - GlobalMemoryStatus (&memory_status); - return memory_status.dwTotalPhys; -# else - /* requires w2k and newer SDK than provided with msvc6 */ - MEMORYSTATUSEX memory_status; - - memory_status.dwLength = sizeof (memory_status); - - if (GlobalMemoryStatusEx (&memory_status)) - return memory_status.ullTotalPhys; -# endif -#endif - - return 0; -} - -/** - * get_backtrace: - * - * Returns: The current stack trace. Free with g_free(). Mainly meant - * for debugging, for example storing the allocation stack traces for - * objects to hunt down leaks. - **/ -char * -get_backtrace (void) -{ -#ifdef G_OS_UNIX - void *functions[MAX_FUNC]; - char **function_names; - int n_functions; - int i; - GString *result; - - /* Get symbols */ - n_functions = backtrace (functions, MAX_FUNC); - function_names = backtrace_symbols (functions, n_functions); - - /* Construct stack trace */ - result = g_string_new (""); - for (i = 0; i < n_functions; i++) - g_string_append_printf (result, "%s\n", function_names[i]); - - /* We must not free the function names themselves, we only need to - * free the array that points to them - */ - free (function_names); - - return g_string_free (result, FALSE/*free_segment*/); -#else - return g_strdup ("backtrace() only available with GNU libc\n"); -#endif -} +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "config.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +#ifdef G_OS_WIN32 +#define _WIN32_WINNT 0x0500 +#include +#include +#endif + +#ifdef G_OS_UNIX +/* For get_backtrace() */ +#include +#include +#include +#endif + +#include "base-utils.h" + + +#define NUM_PROCESSORS_DEFAULT 1 +#define MAX_FUNC 100 + + +/* public functions */ + +gint +get_pid (void) +{ + return (gint) getpid (); +} + +gint +get_number_of_processors (void) +{ + gint retval = NUM_PROCESSORS_DEFAULT; + +#ifdef G_OS_UNIX +#if defined(HAVE_UNISTD_H) && defined(_SC_NPROCESSORS_ONLN) + retval = sysconf (_SC_NPROCESSORS_ONLN); +#endif +#endif +#ifdef G_OS_WIN32 + SYSTEM_INFO system_info; + + GetSystemInfo (&system_info); + + retval = system_info.dwNumberOfProcessors; +#endif + + return retval; +} + +guint64 +get_physical_memory_size (void) +{ +#ifdef G_OS_UNIX +#if defined(HAVE_UNISTD_H) && defined(_SC_PHYS_PAGES) && defined (_SC_PAGE_SIZE) + return (guint64) sysconf (_SC_PHYS_PAGES) * sysconf (_SC_PAGE_SIZE); +#endif +#endif + +#ifdef G_OS_WIN32 +# if defined(_MSC_VER) && (_MSC_VER <= 1200) + MEMORYSTATUS memory_status; + memory_status.dwLength = sizeof (memory_status); + + GlobalMemoryStatus (&memory_status); + return memory_status.dwTotalPhys; +# else + /* requires w2k and newer SDK than provided with msvc6 */ + MEMORYSTATUSEX memory_status; + + memory_status.dwLength = sizeof (memory_status); + + if (GlobalMemoryStatusEx (&memory_status)) + return memory_status.ullTotalPhys; +# endif +#endif + + return 0; +} + +/** + * get_backtrace: + * + * Returns: The current stack trace. Free with g_free(). Mainly meant + * for debugging, for example storing the allocation stack traces for + * objects to hunt down leaks. + **/ +char * +get_backtrace (void) +{ +#ifdef G_OS_UNIX + void *functions[MAX_FUNC]; + char **function_names; + int n_functions; + int i; + GString *result; + + /* Get symbols */ + n_functions = backtrace (functions, MAX_FUNC); + function_names = backtrace_symbols (functions, n_functions); + + /* Construct stack trace */ + result = g_string_new (""); + for (i = 0; i < n_functions; i++) + g_string_append_printf (result, "%s\n", function_names[i]); + + /* We must not free the function names themselves, we only need to + * free the array that points to them + */ + free (function_names); + + return g_string_free (result, FALSE/*free_segment*/); +#else + return g_strdup ("backtrace() only available with GNU libc\n"); +#endif +} diff --git a/app/base/base-utils.h b/app/base/base-utils.h index 7888904ca2..4f5bbf3e3d 100644 --- a/app/base/base-utils.h +++ b/app/base/base-utils.h @@ -1,28 +1,28 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995 Spencer Kimball and Peter Mattis - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __BASE_H__ -#define __BASE_H__ - - -gint get_pid (void); -gint get_number_of_processors (void); -guint64 get_physical_memory_size (void); -char * get_backtrace (void); - - -#endif /* __BASE_H__ */ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __BASE_H__ +#define __BASE_H__ + + +gint get_pid (void); +gint get_number_of_processors (void); +guint64 get_physical_memory_size (void); +char * get_backtrace (void); + + +#endif /* __BASE_H__ */ diff --git a/build/.gitignore b/build/.gitignore index 725942114c..05db30c0d3 100644 --- a/build/.gitignore +++ b/build/.gitignore @@ -1,2 +1,2 @@ -/Makefile +/Makefile /Makefile.in \ No newline at end of file diff --git a/build/Makefile.am b/build/Makefile.am index 097833ffa1..30b2e5fbb0 100644 --- a/build/Makefile.am +++ b/build/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS = \ +SUBDIRS = \ windows \ No newline at end of file diff --git a/build/windows/gimprc.rule b/build/windows/gimprc.rule index 363cc65ba0..b6b81f5783 100644 --- a/build/windows/gimprc.rule +++ b/build/windows/gimprc.rule @@ -1,10 +1,10 @@ -# Version resources for Microsoft Windows - -SUFFIXES = .rc .rc.o - -.rc.rc.o: $(top_srcdir)/build/windows/gimp.rc - $(WINDRES) --define ORIGINALFILENAME_STR="$*$(EXEEXT)" \ - --define INTERNALNAME_STR="$*" \ - --define TOP_SRCDIR="$(top_srcdir)" \ - -I$(top_srcdir)/app \ - $< $@ +# Version resources for Microsoft Windows + +SUFFIXES = .rc .rc.o + +.rc.rc.o: $(top_srcdir)/build/windows/gimp.rc + $(WINDRES) --define ORIGINALFILENAME_STR="$*$(EXEEXT)" \ + --define INTERNALNAME_STR="$*" \ + --define TOP_SRCDIR="$(top_srcdir)" \ + -I$(top_srcdir)/app \ + $< $@ diff --git a/modules/controller-dx-dinput.c b/modules/controller-dx-dinput.c index 9e40d11821..f00d2fb84a 100644 --- a/modules/controller-dx-dinput.c +++ b/modules/controller-dx-dinput.c @@ -1,1123 +1,1123 @@ -/* GIMP - The GNU Image Manipulation Program - * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis - * - * controller_dx_dinput.c - * Copyright (C) 2004-2007 Sven Neumann - * Michael Natterer - * Tor Lillqvist - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* When using gcc with the February 2007 version of the DirectX SDK, - * at least, you need to fix a couple of duplicate typedefs in the - * DirectX . Unfortunately I can't include the diff here, - * both for copyright reasons, and because that would confuse the C - * lexer even if inside #if 0. - */ - -#include "config.h" - -#include -#include -#include - -#define _WIN32_WINNT 0x0501 -#include -#define DIRECTINPUT_VERSION 0x0800 -#include - -#include - -#include "libgimpconfig/gimpconfig.h" -#include "libgimpmodule/gimpmodule.h" -#include "libgimpwidgets/gimpwidgets.h" - -#define GIMP_ENABLE_CONTROLLER_UNDER_CONSTRUCTION -#include "libgimpwidgets/gimpcontroller.h" - -#include "gimpinputdevicestore.h" - -#include "libgimp/libgimp-intl.h" - -enum -{ - PROP_0, - PROP_DEVICE, - PROP_DEVICE_STORE -}; - -#define NUM_EVENTS_PER_BUTTON 3 /* Button click, press and release */ -#define NUM_EVENTS_PER_AXIS 2 /* Axis decrease and increase */ -#define NUM_EVENTS_PER_SLIDER 2 /* Slider decrease and increase */ -#define NUM_EVENTS_PER_POV 3 /* POV view vector X and Y view and return */ - -#define CONTROLLER_TYPE_DX_DINPUT (controller_dx_dinput_get_type ()) -#define CONTROLLER_DX_DINPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CONTROLLER_TYPE_DX_DINPUT, ControllerDXDInput)) -#define CONTROLLER_DX_DINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CONTROLLER_TYPE_DX_DINPUT, ControllerDXDInputClass)) -#define CONTROLLER_IS_DX_DINPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CONTROLLER_TYPE_DX_DINPUT)) -#define CONTROLLER_IS_DX_DINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CONTROLLER_TYPE_DX_DINPUT)) - -typedef struct _DXDInputSource DXDInputSource; -typedef struct _ControllerDXDInput ControllerDXDInput; -typedef struct _ControllerDXDInputClass ControllerDXDInputClass; - -struct _DXDInputSource -{ - GSource source; - ControllerDXDInput *controller; -}; - -struct _ControllerDXDInput -{ - GimpController parent_instance; - - GimpInputDeviceStore *store; - - LPDIRECTINPUTDEVICE8W didevice8; - - HANDLE event; - - GPollFD *pollfd; - - gint num_buttons; - gint num_button_events; - - gint num_axes; - gint num_axis_events; - - gint num_sliders; - gint num_slider_events; - - gint num_povs; - gint num_pov_events; - - gint num_events; - gchar **event_names; - gchar **event_blurbs; - - DIDATAFORMAT *format; - - guchar *prevdata; - - gchar *guid; - GSource *source; - - /* Variables used by enumeration callbacks only*/ - gint bei, bi, aei, ai, sei, si, pei, pi; -}; - -struct _ControllerDXDInputClass -{ - GimpControllerClass parent_class; -}; - - -GType controller_dx_dinput_get_type (void); - -static void dx_dinput_dispose (GObject *object); -static void dx_dinput_finalize (GObject *object); -static void dx_dinput_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void dx_dinput_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); - -static gint dx_dinput_get_n_events (GimpController *controller); -static const gchar * dx_dinput_get_event_name (GimpController *controller, - gint event_id); -static const gchar * dx_dinput_get_event_blurb (GimpController *controller, - gint event_id); - -static void dx_dinput_device_changed (ControllerDXDInput *controller, - const gchar *guid); -static gboolean dx_dinput_set_device (ControllerDXDInput *controller, - const gchar *guid); - - -static const GimpModuleInfo dx_dinput_info = -{ - GIMP_MODULE_ABI_VERSION, - N_("DirectX DirectInput event controller"), - "Tor Lillqvist ", - "v0.1", - "(c) 2004-2007, released under the GPL", - "2004-2007" -}; - - -G_DEFINE_DYNAMIC_TYPE (ControllerDXDInput, controller_dx_dinput, - GIMP_TYPE_CONTROLLER) - - -G_MODULE_EXPORT const GimpModuleInfo * -gimp_module_query (GTypeModule *module) -{ - return &dx_dinput_info; -} - -G_MODULE_EXPORT gboolean -gimp_module_register (GTypeModule *module) -{ - gimp_input_device_store_register_types (module); - controller_dx_dinput_register_type (module); - - return TRUE; -} - -static void -controller_dx_dinput_class_init (ControllerDXDInputClass *klass) -{ - GimpControllerClass *controller_class = GIMP_CONTROLLER_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = dx_dinput_dispose; - object_class->finalize = dx_dinput_finalize; - object_class->get_property = dx_dinput_get_property; - object_class->set_property = dx_dinput_set_property; - - g_object_class_install_property (object_class, PROP_DEVICE, - g_param_spec_string ("device", - _("Device:"), - _("The device to read DirectInput events from."), - NULL, - GIMP_CONFIG_PARAM_FLAGS)); - g_object_class_install_property (object_class, PROP_DEVICE_STORE, - g_param_spec_object ("device-values", - NULL, NULL, - GIMP_TYPE_INPUT_DEVICE_STORE, - G_PARAM_READABLE)); - - controller_class->name = _("DirectX DirectInput"); - controller_class->help_id = "gimp-controller-directx-directinput"; - controller_class->stock_id = GIMP_STOCK_CONTROLLER_LINUX_INPUT; - - controller_class->get_n_events = dx_dinput_get_n_events; - controller_class->get_event_name = dx_dinput_get_event_name; - controller_class->get_event_blurb = dx_dinput_get_event_blurb; -} - -static void -controller_dx_dinput_class_finalize (ControllerDXDInputClass *klass) -{ -} - -static void -controller_dx_dinput_init (ControllerDXDInput *controller) -{ - controller->store = gimp_input_device_store_new (); - - if (controller->store) - { - g_signal_connect_swapped (controller->store, "device-added", - G_CALLBACK (dx_dinput_device_changed), - controller); - g_signal_connect_swapped (controller->store, "device-removed", - G_CALLBACK (dx_dinput_device_changed), - controller); - } -} - -static void -dx_dinput_dispose (GObject *object) -{ - ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); - - dx_dinput_set_device (controller, NULL); - - G_OBJECT_CLASS (controller_dx_dinput_parent_class)->dispose (object); -} - -static void -dx_dinput_finalize (GObject *object) -{ - ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); - - if (controller->source != NULL) - { - g_source_remove_poll (controller->source, controller->pollfd); - g_source_remove (g_source_get_id (controller->source)); - g_source_unref (controller->source); - } - - if (controller->didevice8) - IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL); - - if (controller->format != NULL) - { - g_free (controller->format->rgodf); - g_free (controller->format); - controller->format = NULL; - } - - g_free (controller->prevdata); - controller->prevdata = NULL; - - if (controller->event != NULL) - { - CloseHandle (controller->event); - controller->event = 0; - } - - if (controller->store) - { - g_object_unref (controller->store); - controller->store = NULL; - } - - G_OBJECT_CLASS (controller_dx_dinput_parent_class)->finalize (object); -} - -static void -dx_dinput_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); - - switch (property_id) - { - case PROP_DEVICE: - dx_dinput_set_device (controller, g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -dx_dinput_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); - - switch (property_id) - { - case PROP_DEVICE: - g_value_set_string (value, controller->guid); - break; - case PROP_DEVICE_STORE: - g_value_set_object (value, controller->store); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static gint -dx_dinput_get_n_events (GimpController *controller) -{ - ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller; - - return cdxdi->num_events; -} - -static const gchar * -dx_dinput_get_event_name - (GimpController *controller, - gint event_id) -{ - ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller; - - if (event_id < 0 || event_id >= cdxdi->num_events) - return NULL; - - return cdxdi->event_names[event_id]; -} - -static const gchar * -dx_dinput_get_event_blurb (GimpController *controller, - gint event_id) -{ - ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller; - - if (event_id < 0 || event_id >= cdxdi->num_events) - return NULL; - - return cdxdi->event_blurbs[event_id]; -} - -static BOOL CALLBACK -count_objects (const DIDEVICEOBJECTINSTANCEW *doi, - void *user_data) -{ - ControllerDXDInput *controller = (ControllerDXDInput *) user_data; - HRESULT hresult; - DIPROPRANGE range; - - if (doi->dwType & DIDFT_AXIS) - { - /* Set reported range to physical range, not to give upper - * level software any false impression of higher accuracy. - */ - - range.diph.dwSize = sizeof (DIPROPRANGE); - range.diph.dwHeaderSize = sizeof (DIPROPHEADER); - range.diph.dwObj = doi->dwType; - range.diph.dwHow = DIPH_BYID; - - if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8, - DIPROP_PHYSICALRANGE, - &range.diph)))) - g_warning ("IDirectInputDevice8::GetProperty failed: %s", - g_win32_error_message (hresult)); - else - { - if (FAILED ((hresult = IDirectInputDevice8_SetProperty (controller->didevice8, - DIPROP_RANGE, - &range.diph)))) - g_warning ("IDirectInputDevice8::SetProperty failed: %s", - g_win32_error_message (hresult)); - } - } - - if (IsEqualGUID (&doi->guidType, &GUID_Button)) - controller->num_buttons++; - else if (IsEqualGUID (&doi->guidType, &GUID_XAxis) || - IsEqualGUID (&doi->guidType, &GUID_YAxis) || - IsEqualGUID (&doi->guidType, &GUID_ZAxis) || - IsEqualGUID (&doi->guidType, &GUID_RxAxis) || - IsEqualGUID (&doi->guidType, &GUID_RyAxis) || - IsEqualGUID (&doi->guidType, &GUID_RzAxis)) - controller->num_axes++; - else if (IsEqualGUID (&doi->guidType, &GUID_Slider)) - controller->num_sliders++; - else if (IsEqualGUID (&doi->guidType, &GUID_POV)) - controller->num_povs++; - - return DIENUM_CONTINUE; -} - -static BOOL CALLBACK -name_objects (const DIDEVICEOBJECTINSTANCEW *doi, - void *user_data) -{ - ControllerDXDInput *controller = (ControllerDXDInput *) user_data; - - if (IsEqualGUID (&doi->guidType, &GUID_Button)) - { - controller->event_names[controller->bei] = g_strdup_printf ("button-%d", controller->bi); - controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d"), controller->bi); - controller->bei++; - controller->event_names[controller->bei] = g_strdup_printf ("button-%d-press", controller->bi); - controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d Press"), controller->bi); - controller->bei++; - controller->event_names[controller->bei] = g_strdup_printf ("button-%d-release", controller->bi); - controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d Release"), controller->bi); - controller->bei++; - - g_assert (controller->bi < controller->num_buttons); - - controller->bi++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_XAxis) || - IsEqualGUID (&doi->guidType, &GUID_YAxis) || - IsEqualGUID (&doi->guidType, &GUID_ZAxis) || - IsEqualGUID (&doi->guidType, &GUID_RxAxis) || - IsEqualGUID (&doi->guidType, &GUID_RyAxis) || - IsEqualGUID (&doi->guidType, &GUID_RzAxis)) - { - if (IsEqualGUID (&doi->guidType, &GUID_XAxis)) - { - controller->event_names[controller->aei] = g_strdup ("x-move-left"); - controller->event_blurbs[controller->aei] = g_strdup (_("X Move Left")); - controller->aei++; - controller->event_names[controller->aei] = g_strdup ("x-move-right"); - controller->event_blurbs[controller->aei] = g_strdup (_("X Move Right")); - controller->aei++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_YAxis)) - { - controller->event_names[controller->aei] = g_strdup ("y-move-away"); - controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Away")); - controller->aei++; - controller->event_names[controller->aei] = g_strdup ("y-move-near"); - controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Near")); - controller->aei++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_ZAxis)) - { - controller->event_names[controller->aei] = g_strdup ("z-move-up"); - controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Up")); - controller->aei++; - controller->event_names[controller->aei] = g_strdup ("z-move-down"); - controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Down")); - controller->aei++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_RxAxis)) - { - controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-away"); - controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Away")); - controller->aei++; - controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-near"); - controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Near")); - controller->aei++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_RyAxis)) - { - controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-right"); - controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Right")); - controller->aei++; - controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-left"); - controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Left")); - controller->aei++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_RzAxis)) - { - controller->event_names[controller->aei] = g_strdup ("z-axis-turn-left"); - controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Left")); - controller->aei++; - controller->event_names[controller->aei] = g_strdup ("z-axis-turn-right"); - controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Right")); - controller->aei++; - } - - g_assert (controller->ai < controller->num_axes); - - controller->ai++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_Slider)) - { - controller->event_names[controller->sei] = g_strdup_printf ("slider-%d-increase", controller->si); - controller->event_blurbs[controller->sei] = g_strdup_printf (_("Slider %d Increase"), controller->si); - controller->sei++; - controller->event_names[controller->sei] = g_strdup_printf ("slider-%d-decrease", controller->si); - controller->event_blurbs[controller->sei] = g_strdup_printf (_("Slider %d Decrease"), controller->si); - controller->sei++; - - g_assert (controller->si < controller->num_sliders); - - controller->si++; - } - else if (IsEqualGUID (&doi->guidType, &GUID_POV)) - { - controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-x-view", controller->pi); - controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d X View"), controller->pi); - controller->pei++; - controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-y-view", controller->pi); - controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d Y View"), controller->pi); - controller->pei++; - controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-x-return", controller->pi); - controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d Return"), controller->pi); - controller->pei++; - - g_assert (controller->pi < controller->num_povs); - - controller->pi++; - } - - return DIENUM_CONTINUE; -} - -static gboolean -dx_dinput_get_device_info (ControllerDXDInput *controller, - GError **error) -{ - HRESULT hresult; - - controller->num_buttons = - controller->num_axes = - controller->num_sliders = - controller->num_povs = 0; - - if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8, - count_objects, - controller, - DIDFT_AXIS| - DIDFT_BUTTON| - DIDFT_POV| - DIDFT_PSHBUTTON| - DIDFT_RELAXIS| - DIDFT_TGLBUTTON)))) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::EnumObjects failed: %s", - g_win32_error_message (hresult)); - return FALSE; - } - - controller->num_button_events = controller->num_buttons*NUM_EVENTS_PER_BUTTON; - controller->num_axis_events = controller->num_axes*NUM_EVENTS_PER_AXIS; - controller->num_slider_events = controller->num_sliders*NUM_EVENTS_PER_SLIDER; - controller->num_pov_events = controller->num_povs*NUM_EVENTS_PER_POV; - - controller->num_events = - controller->num_button_events + - controller->num_axis_events + - controller->num_slider_events + - controller->num_pov_events; - - controller->event_names = g_new (gchar *, controller->num_events); - controller->event_blurbs = g_new (gchar *, controller->num_events); - - controller->bi = controller->ai = controller->si = controller->pi = 0; - - controller->bei = 0; - controller->aei = controller->bei + controller->num_button_events; - controller->sei = controller->aei + controller->num_axis_events; - controller->pei = controller->sei + controller->num_slider_events; - - if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8, - name_objects, - controller, - DIDFT_AXIS| - DIDFT_BUTTON| - DIDFT_POV| - DIDFT_PSHBUTTON| - DIDFT_RELAXIS| - DIDFT_TGLBUTTON)))) - { - g_free (controller->event_names); - g_free (controller->event_blurbs); - - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::EnumObjects failed: %s", - g_win32_error_message (hresult)); - return FALSE; - } - - - g_assert (controller->bei == controller->num_button_events); - g_assert (controller->aei == controller->bei + controller->num_axis_events); - g_assert (controller->sei == controller->aei + controller->num_slider_events); - g_assert (controller->pei == controller->sei + controller->num_pov_events); - - return TRUE; -} - - -static void -dx_dinput_device_changed (ControllerDXDInput *controller, - const gchar *guid) -{ - if (controller->guid && strcmp (guid, controller->guid) == 0) - { - dx_dinput_set_device (controller, guid); - g_object_notify (G_OBJECT (controller), "device"); - } -} - -static gboolean -dx_dinput_event_prepare (GSource *source, - gint *timeout) -{ - *timeout = -1; - - return FALSE; -} - -static gboolean -dx_dinput_event_check (GSource *source) -{ - DXDInputSource *input = (DXDInputSource *) source; - - if (WaitForSingleObject (input->controller->event, 0) == WAIT_OBJECT_0) - { - ResetEvent (input->controller->event); - return TRUE; - } - - return FALSE; -} - -static gboolean -dx_dinput_event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - ControllerDXDInput * const input = ((DXDInputSource *) source)->controller; - GimpController *controller = &input->parent_instance; - const DIDATAFORMAT * const format = input->format; - const DIOBJECTDATAFORMAT *rgodf = format->rgodf; - HRESULT hresult; - guchar *data; - gint i; - GimpControllerEvent cevent = { 0, }; - - data = g_alloca (format->dwDataSize); - - if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (input->didevice8, - format->dwDataSize, - data)))) - { - return TRUE; - } - - g_object_ref (controller); - - for (i = 0; i < input->num_buttons; i++) - { - if (input->prevdata[rgodf->dwOfs] != data[rgodf->dwOfs]) - { - if (data[rgodf->dwOfs] & 0x80) - { - /* Click event, compatibility with Linux Input */ - cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER; - cevent.any.source = controller; - cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON; - gimp_controller_event (controller, &cevent); - - /* Press event */ - cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 1; - gimp_controller_event (controller, &cevent); - } - else - { - /* Release event */ - cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER; - cevent.any.source = controller; - cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 2; - gimp_controller_event (controller, &cevent); - } - } - rgodf++; - } - - for (i = 0; i < input->num_axes; i++) - { - LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs); - LONG *curr = (LONG *)(data+rgodf->dwOfs); - - if (ABS (*prev - *curr) > 1) - { - cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE; - cevent.any.source = controller; - cevent.any.event_id = - input->num_button_events + - i*NUM_EVENTS_PER_AXIS; - g_value_init (&cevent.value.value, G_TYPE_DOUBLE); - if (*curr - *prev < 0) - { - g_value_set_double (&cevent.value.value, *prev - *curr); - } - else - { - cevent.any.event_id++; - g_value_set_double (&cevent.value.value, *curr - *prev); - } - gimp_controller_event (controller, &cevent); - g_value_unset (&cevent.value.value); - } - else - *curr = *prev; - rgodf++; - } - - for (i = 0; i < input->num_sliders; i++) - { - LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs); - LONG *curr = (LONG *)(data+rgodf->dwOfs); - - if (ABS (*prev - *curr) > 1) - { - cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE; - cevent.any.source = controller; - cevent.any.event_id = - input->num_button_events + - input->num_axis_events + - i*NUM_EVENTS_PER_SLIDER; - g_value_init (&cevent.value.value, G_TYPE_DOUBLE); - if (*curr - *prev < 0) - { - g_value_set_double (&cevent.value.value, *prev - *curr); - } - else - { - cevent.any.event_id++; - g_value_set_double (&cevent.value.value, *curr - *prev); - } - gimp_controller_event (controller, &cevent); - g_value_unset (&cevent.value.value); - } - else - *curr = *prev; - rgodf++; - } - - for (i = 0; i < input->num_povs; i++) - { - LONG prev = *((LONG *)(input->prevdata+rgodf->dwOfs)); - LONG curr = *((LONG *)(data+rgodf->dwOfs)); - double prevx, prevy; - double currx, curry; - - if (prev != curr) - { - if (prev == -1) - { - prevx = 0.; - prevy = 0.; - } - else - { - prevx = sin (prev/36000.*2.*G_PI); - prevy = cos (prev/36000.*2.*G_PI); - } - if (curr == -1) - { - currx = 0.; - curry = 0.; - } - else - { - currx = sin (curr/36000.*2.*G_PI); - curry = cos (curr/36000.*2.*G_PI); - } - - cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE; - cevent.any.source = controller; - cevent.any.event_id = - input->num_button_events + - input->num_axis_events + - input->num_slider_events + - i*NUM_EVENTS_PER_POV; - g_value_init (&cevent.value.value, G_TYPE_DOUBLE); - g_value_set_double (&cevent.value.value, currx - prevx); - gimp_controller_event (controller, &cevent); - cevent.any.event_id++; - g_value_set_double (&cevent.value.value, curry - prevy); - gimp_controller_event (controller, &cevent); - g_value_unset (&cevent.value.value); - if (curr == -1) - { - cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER; - cevent.any.event_id++; - gimp_controller_event (controller, &cevent); - } - } - rgodf++; - } - - g_assert (rgodf == format->rgodf + format->dwNumObjs); - - memmove (input->prevdata, data, format->dwDataSize); - - g_object_unref (controller); - - return TRUE; -} - -static GSourceFuncs dx_dinput_event_funcs = { - dx_dinput_event_prepare, - dx_dinput_event_check, - dx_dinput_event_dispatch, - NULL -}; - - -static void -dump_data_format (const DIDATAFORMAT *format) -{ -#ifdef GIMP_UNSTABLE - gint i; - - g_print ("dwSize: %ld\n", format->dwSize); - g_print ("dwObjSize: %ld\n", format->dwObjSize); - g_print ("dwFlags: "); - if (format->dwFlags == DIDF_ABSAXIS) - g_print ("DIDF_ABSAXIS"); - else if (format->dwFlags == DIDF_RELAXIS) - g_print ("DIDF_RELAXIS"); - else - g_print ("%#lx", format->dwFlags); - g_print ("\n"); - g_print ("dwDataSize: %ld\n", format->dwDataSize); - g_print ("dwNumObjs: %ld\n", format->dwNumObjs); - - for (i = 0; i < format->dwNumObjs; i++) - { - const DIOBJECTDATAFORMAT *oformat = (DIOBJECTDATAFORMAT *) (((char *) format->rgodf) + i*format->dwObjSize); - unsigned char *guid; - - g_print ("Object %d:\n", i); - if (oformat->pguid == NULL) - g_print (" pguid: NULL\n"); - else - { - UuidToString (oformat->pguid, &guid); - g_print (" pguid: %s\n", guid); - RpcStringFree (&guid); - } - - g_print (" dwOfs: %ld\n", oformat->dwOfs); - g_print (" dwType: "); - switch (DIDFT_GETTYPE (oformat->dwType)) - { -#define CASE(x) case DIDFT_##x: g_print ("DIDFT_"#x); break - CASE (RELAXIS); - CASE (ABSAXIS); - CASE (AXIS); - CASE (PSHBUTTON); - CASE (TGLBUTTON); - CASE (BUTTON); - CASE (POV); - CASE (COLLECTION); - CASE (NODATA); -#undef CASE - default: g_print ("%#x", DIDFT_GETTYPE (oformat->dwType)); - } - g_print (" "); - if (DIDFT_GETINSTANCE (oformat->dwType) == DIDFT_GETINSTANCE (DIDFT_ANYINSTANCE)) - g_print ("ANYINSTANCE"); - else - g_print ("#%d", DIDFT_GETINSTANCE (oformat->dwType)); -#define BIT(x) if (oformat->dwType & DIDFT_##x) g_print (" "#x) - BIT (FFACTUATOR); - BIT (FFEFFECTTRIGGER); - BIT (OUTPUT); - BIT (VENDORDEFINED); - BIT (ALIAS); - BIT (OPTIONAL); -#undef BIT - g_print ("\n"); - g_print (" dwFlags:"); - switch (oformat->dwFlags & DIDOI_ASPECTACCEL) - { - case DIDOI_ASPECTPOSITION: g_print (" DIDOI_ASPECTPOSITION"); break; - case DIDOI_ASPECTVELOCITY: g_print (" DIDOI_ASPECTVELOCITY"); break; - case DIDOI_ASPECTACCEL: g_print (" DIDOI_ASPECTACCEL"); break; - } - if (oformat->dwFlags & DIDOI_ASPECTFORCE) - g_print (" DIDOI_ASPECTFORCE"); - g_print ("\n"); - } -#endif -} - -static gboolean -dx_dinput_setup_events (ControllerDXDInput *controller, - GError **error) -{ - HRESULT hresult; - DIPROPDWORD dword; - gint i, k; - DXDInputSource *source; - - if ((controller->event = CreateEvent (NULL, TRUE, FALSE, NULL)) == NULL) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "CreateEvent failed: %s", - g_win32_error_message (GetLastError ())); - return FALSE; - } - - controller->format = g_new (DIDATAFORMAT, 1); - controller->format->dwSize = sizeof (DIDATAFORMAT); - controller->format->dwObjSize = sizeof (DIOBJECTDATAFORMAT); - - dword.diph.dwSize = sizeof (DIPROPDWORD); - dword.diph.dwHeaderSize = sizeof (DIPROPHEADER); - dword.diph.dwObj = 0; - dword.diph.dwHow = DIPH_DEVICE; - - /* Get the axis mode so we can use the same in the format */ - if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8, - DIPROP_AXISMODE, - &dword.diph)))) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::GetParameters failed: %s", - g_win32_error_message (hresult)); - goto fail0; - } - - controller->format->dwFlags = dword.dwData + 1; - - controller->format->dwNumObjs = - controller->num_buttons + - controller->num_axes + - controller->num_sliders + - controller->num_povs; - - controller->format->rgodf = g_new (DIOBJECTDATAFORMAT, controller->format->dwNumObjs); - - k = 0; - controller->format->dwDataSize = 0; - - for (i = 0; i < controller->num_buttons; i++) - { - controller->format->rgodf[k].pguid = NULL; - controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; - controller->format->rgodf[k].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE (i); - controller->format->rgodf[k].dwFlags = 0; - controller->format->dwDataSize += 1; - k++; - } - - controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4); - - for (i = 0; i < controller->num_axes; i++) - { - controller->format->rgodf[k].pguid = NULL; - controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; - controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i); - controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION; - controller->format->dwDataSize += 4; - k++; - } - - for (i = 0; i < controller->num_sliders; i++) - { - controller->format->rgodf[k].pguid = NULL; - controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; - controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i); - controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION; - controller->format->dwDataSize += 4; - k++; - } - - for (i = 0; i < controller->num_povs; i++) - { - controller->format->rgodf[k].pguid = NULL; - controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; - controller->format->rgodf[k].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE (i); - controller->format->rgodf[k].dwFlags = 0; - controller->format->dwDataSize += 4; - k++; - } - - g_assert (k == controller->format->dwNumObjs); - - controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4); - controller->prevdata = g_malloc (controller->format->dwDataSize); - - dump_data_format (controller->format); - - if (FAILED ((hresult = IDirectInputDevice8_SetDataFormat (controller->didevice8, - controller->format)))) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::SetDataFormat failed: %s", - g_win32_error_message (hresult)); - goto fail1; - } - - if (FAILED ((hresult = IDirectInputDevice8_SetEventNotification (controller->didevice8, - controller->event)))) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::SetEventNotification failed: %s", - g_win32_error_message (hresult)); - goto fail2; - } - - if (FAILED ((hresult = IDirectInputDevice8_Acquire (controller->didevice8)))) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::Acquire failed: %s", - g_win32_error_message (hresult)); - goto fail2; - } - - if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (controller->didevice8, - controller->format->dwDataSize, - controller->prevdata)))) - { - g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, - "IDirectInputDevice8::GetDeviceState failed: %s", - g_win32_error_message (hresult)); - goto fail2; - } - - source = (DXDInputSource *) g_source_new (&dx_dinput_event_funcs, - sizeof (DXDInputSource)); - source->controller = controller; - controller->source = (GSource *) source; - - controller->pollfd = g_new (GPollFD, 1); - - controller->pollfd->fd = (int) controller->event; - controller->pollfd->events = G_IO_IN; - - g_source_add_poll (&source->source, controller->pollfd); - g_source_attach (&source->source, NULL); - - return TRUE; - - fail2: - IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL); - fail1: - g_free (controller->format->rgodf); - g_free (controller->format); - controller->format = NULL; - g_free (controller->prevdata); - controller->prevdata = NULL; - fail0: - CloseHandle (controller->event); - controller->event = 0; - - return FALSE; -} - -static gboolean -dx_dinput_set_device (ControllerDXDInput *controller, - const gchar *guid) -{ - GError *error = NULL; - - if (controller->guid) - g_free (controller->guid); - - controller->guid = g_strdup (guid); - - g_object_set (controller, "name", _("DirectInput Events"), NULL); - - if (controller->guid && strlen (controller->guid)) - { - if (controller->store) - controller->didevice8 = - (LPDIRECTINPUTDEVICE8W) gimp_input_device_store_get_device_file (controller->store, - controller->guid); - } - else - { - g_object_set (controller, "state", _("No device configured"), NULL); - - return FALSE; - } - - if (controller->didevice8) - { - if (!dx_dinput_get_device_info (controller, &error) || - !dx_dinput_setup_events (controller, &error)) - { - g_object_set (controller, "state", error->message, NULL); - g_error_free (error); - } - } - else if (controller->store) - { - error = gimp_input_device_store_get_error (controller->store); - - if (error) - { - g_object_set (controller, "state", error->message, NULL); - g_error_free (error); - } - else - { - g_object_set (controller, "state", _("Device not available"), NULL); - } - } - - return FALSE; -} +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995-1997 Spencer Kimball and Peter Mattis + * + * controller_dx_dinput.c + * Copyright (C) 2004-2007 Sven Neumann + * Michael Natterer + * Tor Lillqvist + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* When using gcc with the February 2007 version of the DirectX SDK, + * at least, you need to fix a couple of duplicate typedefs in the + * DirectX . Unfortunately I can't include the diff here, + * both for copyright reasons, and because that would confuse the C + * lexer even if inside #if 0. + */ + +#include "config.h" + +#include +#include +#include + +#define _WIN32_WINNT 0x0501 +#include +#define DIRECTINPUT_VERSION 0x0800 +#include + +#include + +#include "libgimpconfig/gimpconfig.h" +#include "libgimpmodule/gimpmodule.h" +#include "libgimpwidgets/gimpwidgets.h" + +#define GIMP_ENABLE_CONTROLLER_UNDER_CONSTRUCTION +#include "libgimpwidgets/gimpcontroller.h" + +#include "gimpinputdevicestore.h" + +#include "libgimp/libgimp-intl.h" + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_DEVICE_STORE +}; + +#define NUM_EVENTS_PER_BUTTON 3 /* Button click, press and release */ +#define NUM_EVENTS_PER_AXIS 2 /* Axis decrease and increase */ +#define NUM_EVENTS_PER_SLIDER 2 /* Slider decrease and increase */ +#define NUM_EVENTS_PER_POV 3 /* POV view vector X and Y view and return */ + +#define CONTROLLER_TYPE_DX_DINPUT (controller_dx_dinput_get_type ()) +#define CONTROLLER_DX_DINPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CONTROLLER_TYPE_DX_DINPUT, ControllerDXDInput)) +#define CONTROLLER_DX_DINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CONTROLLER_TYPE_DX_DINPUT, ControllerDXDInputClass)) +#define CONTROLLER_IS_DX_DINPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CONTROLLER_TYPE_DX_DINPUT)) +#define CONTROLLER_IS_DX_DINPUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CONTROLLER_TYPE_DX_DINPUT)) + +typedef struct _DXDInputSource DXDInputSource; +typedef struct _ControllerDXDInput ControllerDXDInput; +typedef struct _ControllerDXDInputClass ControllerDXDInputClass; + +struct _DXDInputSource +{ + GSource source; + ControllerDXDInput *controller; +}; + +struct _ControllerDXDInput +{ + GimpController parent_instance; + + GimpInputDeviceStore *store; + + LPDIRECTINPUTDEVICE8W didevice8; + + HANDLE event; + + GPollFD *pollfd; + + gint num_buttons; + gint num_button_events; + + gint num_axes; + gint num_axis_events; + + gint num_sliders; + gint num_slider_events; + + gint num_povs; + gint num_pov_events; + + gint num_events; + gchar **event_names; + gchar **event_blurbs; + + DIDATAFORMAT *format; + + guchar *prevdata; + + gchar *guid; + GSource *source; + + /* Variables used by enumeration callbacks only*/ + gint bei, bi, aei, ai, sei, si, pei, pi; +}; + +struct _ControllerDXDInputClass +{ + GimpControllerClass parent_class; +}; + + +GType controller_dx_dinput_get_type (void); + +static void dx_dinput_dispose (GObject *object); +static void dx_dinput_finalize (GObject *object); +static void dx_dinput_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void dx_dinput_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gint dx_dinput_get_n_events (GimpController *controller); +static const gchar * dx_dinput_get_event_name (GimpController *controller, + gint event_id); +static const gchar * dx_dinput_get_event_blurb (GimpController *controller, + gint event_id); + +static void dx_dinput_device_changed (ControllerDXDInput *controller, + const gchar *guid); +static gboolean dx_dinput_set_device (ControllerDXDInput *controller, + const gchar *guid); + + +static const GimpModuleInfo dx_dinput_info = +{ + GIMP_MODULE_ABI_VERSION, + N_("DirectX DirectInput event controller"), + "Tor Lillqvist ", + "v0.1", + "(c) 2004-2007, released under the GPL", + "2004-2007" +}; + + +G_DEFINE_DYNAMIC_TYPE (ControllerDXDInput, controller_dx_dinput, + GIMP_TYPE_CONTROLLER) + + +G_MODULE_EXPORT const GimpModuleInfo * +gimp_module_query (GTypeModule *module) +{ + return &dx_dinput_info; +} + +G_MODULE_EXPORT gboolean +gimp_module_register (GTypeModule *module) +{ + gimp_input_device_store_register_types (module); + controller_dx_dinput_register_type (module); + + return TRUE; +} + +static void +controller_dx_dinput_class_init (ControllerDXDInputClass *klass) +{ + GimpControllerClass *controller_class = GIMP_CONTROLLER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = dx_dinput_dispose; + object_class->finalize = dx_dinput_finalize; + object_class->get_property = dx_dinput_get_property; + object_class->set_property = dx_dinput_set_property; + + g_object_class_install_property (object_class, PROP_DEVICE, + g_param_spec_string ("device", + _("Device:"), + _("The device to read DirectInput events from."), + NULL, + GIMP_CONFIG_PARAM_FLAGS)); + g_object_class_install_property (object_class, PROP_DEVICE_STORE, + g_param_spec_object ("device-values", + NULL, NULL, + GIMP_TYPE_INPUT_DEVICE_STORE, + G_PARAM_READABLE)); + + controller_class->name = _("DirectX DirectInput"); + controller_class->help_id = "gimp-controller-directx-directinput"; + controller_class->stock_id = GIMP_STOCK_CONTROLLER_LINUX_INPUT; + + controller_class->get_n_events = dx_dinput_get_n_events; + controller_class->get_event_name = dx_dinput_get_event_name; + controller_class->get_event_blurb = dx_dinput_get_event_blurb; +} + +static void +controller_dx_dinput_class_finalize (ControllerDXDInputClass *klass) +{ +} + +static void +controller_dx_dinput_init (ControllerDXDInput *controller) +{ + controller->store = gimp_input_device_store_new (); + + if (controller->store) + { + g_signal_connect_swapped (controller->store, "device-added", + G_CALLBACK (dx_dinput_device_changed), + controller); + g_signal_connect_swapped (controller->store, "device-removed", + G_CALLBACK (dx_dinput_device_changed), + controller); + } +} + +static void +dx_dinput_dispose (GObject *object) +{ + ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); + + dx_dinput_set_device (controller, NULL); + + G_OBJECT_CLASS (controller_dx_dinput_parent_class)->dispose (object); +} + +static void +dx_dinput_finalize (GObject *object) +{ + ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); + + if (controller->source != NULL) + { + g_source_remove_poll (controller->source, controller->pollfd); + g_source_remove (g_source_get_id (controller->source)); + g_source_unref (controller->source); + } + + if (controller->didevice8) + IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL); + + if (controller->format != NULL) + { + g_free (controller->format->rgodf); + g_free (controller->format); + controller->format = NULL; + } + + g_free (controller->prevdata); + controller->prevdata = NULL; + + if (controller->event != NULL) + { + CloseHandle (controller->event); + controller->event = 0; + } + + if (controller->store) + { + g_object_unref (controller->store); + controller->store = NULL; + } + + G_OBJECT_CLASS (controller_dx_dinput_parent_class)->finalize (object); +} + +static void +dx_dinput_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); + + switch (property_id) + { + case PROP_DEVICE: + dx_dinput_set_device (controller, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +dx_dinput_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); + + switch (property_id) + { + case PROP_DEVICE: + g_value_set_string (value, controller->guid); + break; + case PROP_DEVICE_STORE: + g_value_set_object (value, controller->store); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gint +dx_dinput_get_n_events (GimpController *controller) +{ + ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller; + + return cdxdi->num_events; +} + +static const gchar * +dx_dinput_get_event_name + (GimpController *controller, + gint event_id) +{ + ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller; + + if (event_id < 0 || event_id >= cdxdi->num_events) + return NULL; + + return cdxdi->event_names[event_id]; +} + +static const gchar * +dx_dinput_get_event_blurb (GimpController *controller, + gint event_id) +{ + ControllerDXDInput *cdxdi = (ControllerDXDInput *) controller; + + if (event_id < 0 || event_id >= cdxdi->num_events) + return NULL; + + return cdxdi->event_blurbs[event_id]; +} + +static BOOL CALLBACK +count_objects (const DIDEVICEOBJECTINSTANCEW *doi, + void *user_data) +{ + ControllerDXDInput *controller = (ControllerDXDInput *) user_data; + HRESULT hresult; + DIPROPRANGE range; + + if (doi->dwType & DIDFT_AXIS) + { + /* Set reported range to physical range, not to give upper + * level software any false impression of higher accuracy. + */ + + range.diph.dwSize = sizeof (DIPROPRANGE); + range.diph.dwHeaderSize = sizeof (DIPROPHEADER); + range.diph.dwObj = doi->dwType; + range.diph.dwHow = DIPH_BYID; + + if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8, + DIPROP_PHYSICALRANGE, + &range.diph)))) + g_warning ("IDirectInputDevice8::GetProperty failed: %s", + g_win32_error_message (hresult)); + else + { + if (FAILED ((hresult = IDirectInputDevice8_SetProperty (controller->didevice8, + DIPROP_RANGE, + &range.diph)))) + g_warning ("IDirectInputDevice8::SetProperty failed: %s", + g_win32_error_message (hresult)); + } + } + + if (IsEqualGUID (&doi->guidType, &GUID_Button)) + controller->num_buttons++; + else if (IsEqualGUID (&doi->guidType, &GUID_XAxis) || + IsEqualGUID (&doi->guidType, &GUID_YAxis) || + IsEqualGUID (&doi->guidType, &GUID_ZAxis) || + IsEqualGUID (&doi->guidType, &GUID_RxAxis) || + IsEqualGUID (&doi->guidType, &GUID_RyAxis) || + IsEqualGUID (&doi->guidType, &GUID_RzAxis)) + controller->num_axes++; + else if (IsEqualGUID (&doi->guidType, &GUID_Slider)) + controller->num_sliders++; + else if (IsEqualGUID (&doi->guidType, &GUID_POV)) + controller->num_povs++; + + return DIENUM_CONTINUE; +} + +static BOOL CALLBACK +name_objects (const DIDEVICEOBJECTINSTANCEW *doi, + void *user_data) +{ + ControllerDXDInput *controller = (ControllerDXDInput *) user_data; + + if (IsEqualGUID (&doi->guidType, &GUID_Button)) + { + controller->event_names[controller->bei] = g_strdup_printf ("button-%d", controller->bi); + controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d"), controller->bi); + controller->bei++; + controller->event_names[controller->bei] = g_strdup_printf ("button-%d-press", controller->bi); + controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d Press"), controller->bi); + controller->bei++; + controller->event_names[controller->bei] = g_strdup_printf ("button-%d-release", controller->bi); + controller->event_blurbs[controller->bei] = g_strdup_printf (_("Button %d Release"), controller->bi); + controller->bei++; + + g_assert (controller->bi < controller->num_buttons); + + controller->bi++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_XAxis) || + IsEqualGUID (&doi->guidType, &GUID_YAxis) || + IsEqualGUID (&doi->guidType, &GUID_ZAxis) || + IsEqualGUID (&doi->guidType, &GUID_RxAxis) || + IsEqualGUID (&doi->guidType, &GUID_RyAxis) || + IsEqualGUID (&doi->guidType, &GUID_RzAxis)) + { + if (IsEqualGUID (&doi->guidType, &GUID_XAxis)) + { + controller->event_names[controller->aei] = g_strdup ("x-move-left"); + controller->event_blurbs[controller->aei] = g_strdup (_("X Move Left")); + controller->aei++; + controller->event_names[controller->aei] = g_strdup ("x-move-right"); + controller->event_blurbs[controller->aei] = g_strdup (_("X Move Right")); + controller->aei++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_YAxis)) + { + controller->event_names[controller->aei] = g_strdup ("y-move-away"); + controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Away")); + controller->aei++; + controller->event_names[controller->aei] = g_strdup ("y-move-near"); + controller->event_blurbs[controller->aei] = g_strdup (_("Y Move Near")); + controller->aei++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_ZAxis)) + { + controller->event_names[controller->aei] = g_strdup ("z-move-up"); + controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Up")); + controller->aei++; + controller->event_names[controller->aei] = g_strdup ("z-move-down"); + controller->event_blurbs[controller->aei] = g_strdup (_("Z Move Down")); + controller->aei++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_RxAxis)) + { + controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-away"); + controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Away")); + controller->aei++; + controller->event_names[controller->aei] = g_strdup ("x-axis-tilt-near"); + controller->event_blurbs[controller->aei] = g_strdup (_("X Axis Tilt Near")); + controller->aei++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_RyAxis)) + { + controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-right"); + controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Right")); + controller->aei++; + controller->event_names[controller->aei] = g_strdup ("y-axis-tilt-left"); + controller->event_blurbs[controller->aei] = g_strdup (_("Y Axis Tilt Left")); + controller->aei++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_RzAxis)) + { + controller->event_names[controller->aei] = g_strdup ("z-axis-turn-left"); + controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Left")); + controller->aei++; + controller->event_names[controller->aei] = g_strdup ("z-axis-turn-right"); + controller->event_blurbs[controller->aei] = g_strdup (_("Z Axis Turn Right")); + controller->aei++; + } + + g_assert (controller->ai < controller->num_axes); + + controller->ai++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_Slider)) + { + controller->event_names[controller->sei] = g_strdup_printf ("slider-%d-increase", controller->si); + controller->event_blurbs[controller->sei] = g_strdup_printf (_("Slider %d Increase"), controller->si); + controller->sei++; + controller->event_names[controller->sei] = g_strdup_printf ("slider-%d-decrease", controller->si); + controller->event_blurbs[controller->sei] = g_strdup_printf (_("Slider %d Decrease"), controller->si); + controller->sei++; + + g_assert (controller->si < controller->num_sliders); + + controller->si++; + } + else if (IsEqualGUID (&doi->guidType, &GUID_POV)) + { + controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-x-view", controller->pi); + controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d X View"), controller->pi); + controller->pei++; + controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-y-view", controller->pi); + controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d Y View"), controller->pi); + controller->pei++; + controller->event_names[controller->pei] = g_strdup_printf ("pov-%d-x-return", controller->pi); + controller->event_blurbs[controller->pei] = g_strdup_printf (_("POV %d Return"), controller->pi); + controller->pei++; + + g_assert (controller->pi < controller->num_povs); + + controller->pi++; + } + + return DIENUM_CONTINUE; +} + +static gboolean +dx_dinput_get_device_info (ControllerDXDInput *controller, + GError **error) +{ + HRESULT hresult; + + controller->num_buttons = + controller->num_axes = + controller->num_sliders = + controller->num_povs = 0; + + if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8, + count_objects, + controller, + DIDFT_AXIS| + DIDFT_BUTTON| + DIDFT_POV| + DIDFT_PSHBUTTON| + DIDFT_RELAXIS| + DIDFT_TGLBUTTON)))) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::EnumObjects failed: %s", + g_win32_error_message (hresult)); + return FALSE; + } + + controller->num_button_events = controller->num_buttons*NUM_EVENTS_PER_BUTTON; + controller->num_axis_events = controller->num_axes*NUM_EVENTS_PER_AXIS; + controller->num_slider_events = controller->num_sliders*NUM_EVENTS_PER_SLIDER; + controller->num_pov_events = controller->num_povs*NUM_EVENTS_PER_POV; + + controller->num_events = + controller->num_button_events + + controller->num_axis_events + + controller->num_slider_events + + controller->num_pov_events; + + controller->event_names = g_new (gchar *, controller->num_events); + controller->event_blurbs = g_new (gchar *, controller->num_events); + + controller->bi = controller->ai = controller->si = controller->pi = 0; + + controller->bei = 0; + controller->aei = controller->bei + controller->num_button_events; + controller->sei = controller->aei + controller->num_axis_events; + controller->pei = controller->sei + controller->num_slider_events; + + if (FAILED ((hresult = IDirectInputDevice8_EnumObjects (controller->didevice8, + name_objects, + controller, + DIDFT_AXIS| + DIDFT_BUTTON| + DIDFT_POV| + DIDFT_PSHBUTTON| + DIDFT_RELAXIS| + DIDFT_TGLBUTTON)))) + { + g_free (controller->event_names); + g_free (controller->event_blurbs); + + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::EnumObjects failed: %s", + g_win32_error_message (hresult)); + return FALSE; + } + + + g_assert (controller->bei == controller->num_button_events); + g_assert (controller->aei == controller->bei + controller->num_axis_events); + g_assert (controller->sei == controller->aei + controller->num_slider_events); + g_assert (controller->pei == controller->sei + controller->num_pov_events); + + return TRUE; +} + + +static void +dx_dinput_device_changed (ControllerDXDInput *controller, + const gchar *guid) +{ + if (controller->guid && strcmp (guid, controller->guid) == 0) + { + dx_dinput_set_device (controller, guid); + g_object_notify (G_OBJECT (controller), "device"); + } +} + +static gboolean +dx_dinput_event_prepare (GSource *source, + gint *timeout) +{ + *timeout = -1; + + return FALSE; +} + +static gboolean +dx_dinput_event_check (GSource *source) +{ + DXDInputSource *input = (DXDInputSource *) source; + + if (WaitForSingleObject (input->controller->event, 0) == WAIT_OBJECT_0) + { + ResetEvent (input->controller->event); + return TRUE; + } + + return FALSE; +} + +static gboolean +dx_dinput_event_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ControllerDXDInput * const input = ((DXDInputSource *) source)->controller; + GimpController *controller = &input->parent_instance; + const DIDATAFORMAT * const format = input->format; + const DIOBJECTDATAFORMAT *rgodf = format->rgodf; + HRESULT hresult; + guchar *data; + gint i; + GimpControllerEvent cevent = { 0, }; + + data = g_alloca (format->dwDataSize); + + if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (input->didevice8, + format->dwDataSize, + data)))) + { + return TRUE; + } + + g_object_ref (controller); + + for (i = 0; i < input->num_buttons; i++) + { + if (input->prevdata[rgodf->dwOfs] != data[rgodf->dwOfs]) + { + if (data[rgodf->dwOfs] & 0x80) + { + /* Click event, compatibility with Linux Input */ + cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER; + cevent.any.source = controller; + cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON; + gimp_controller_event (controller, &cevent); + + /* Press event */ + cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 1; + gimp_controller_event (controller, &cevent); + } + else + { + /* Release event */ + cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER; + cevent.any.source = controller; + cevent.any.event_id = i*NUM_EVENTS_PER_BUTTON + 2; + gimp_controller_event (controller, &cevent); + } + } + rgodf++; + } + + for (i = 0; i < input->num_axes; i++) + { + LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs); + LONG *curr = (LONG *)(data+rgodf->dwOfs); + + if (ABS (*prev - *curr) > 1) + { + cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE; + cevent.any.source = controller; + cevent.any.event_id = + input->num_button_events + + i*NUM_EVENTS_PER_AXIS; + g_value_init (&cevent.value.value, G_TYPE_DOUBLE); + if (*curr - *prev < 0) + { + g_value_set_double (&cevent.value.value, *prev - *curr); + } + else + { + cevent.any.event_id++; + g_value_set_double (&cevent.value.value, *curr - *prev); + } + gimp_controller_event (controller, &cevent); + g_value_unset (&cevent.value.value); + } + else + *curr = *prev; + rgodf++; + } + + for (i = 0; i < input->num_sliders; i++) + { + LONG *prev = (LONG *)(input->prevdata+rgodf->dwOfs); + LONG *curr = (LONG *)(data+rgodf->dwOfs); + + if (ABS (*prev - *curr) > 1) + { + cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE; + cevent.any.source = controller; + cevent.any.event_id = + input->num_button_events + + input->num_axis_events + + i*NUM_EVENTS_PER_SLIDER; + g_value_init (&cevent.value.value, G_TYPE_DOUBLE); + if (*curr - *prev < 0) + { + g_value_set_double (&cevent.value.value, *prev - *curr); + } + else + { + cevent.any.event_id++; + g_value_set_double (&cevent.value.value, *curr - *prev); + } + gimp_controller_event (controller, &cevent); + g_value_unset (&cevent.value.value); + } + else + *curr = *prev; + rgodf++; + } + + for (i = 0; i < input->num_povs; i++) + { + LONG prev = *((LONG *)(input->prevdata+rgodf->dwOfs)); + LONG curr = *((LONG *)(data+rgodf->dwOfs)); + double prevx, prevy; + double currx, curry; + + if (prev != curr) + { + if (prev == -1) + { + prevx = 0.; + prevy = 0.; + } + else + { + prevx = sin (prev/36000.*2.*G_PI); + prevy = cos (prev/36000.*2.*G_PI); + } + if (curr == -1) + { + currx = 0.; + curry = 0.; + } + else + { + currx = sin (curr/36000.*2.*G_PI); + curry = cos (curr/36000.*2.*G_PI); + } + + cevent.any.type = GIMP_CONTROLLER_EVENT_VALUE; + cevent.any.source = controller; + cevent.any.event_id = + input->num_button_events + + input->num_axis_events + + input->num_slider_events + + i*NUM_EVENTS_PER_POV; + g_value_init (&cevent.value.value, G_TYPE_DOUBLE); + g_value_set_double (&cevent.value.value, currx - prevx); + gimp_controller_event (controller, &cevent); + cevent.any.event_id++; + g_value_set_double (&cevent.value.value, curry - prevy); + gimp_controller_event (controller, &cevent); + g_value_unset (&cevent.value.value); + if (curr == -1) + { + cevent.any.type = GIMP_CONTROLLER_EVENT_TRIGGER; + cevent.any.event_id++; + gimp_controller_event (controller, &cevent); + } + } + rgodf++; + } + + g_assert (rgodf == format->rgodf + format->dwNumObjs); + + memmove (input->prevdata, data, format->dwDataSize); + + g_object_unref (controller); + + return TRUE; +} + +static GSourceFuncs dx_dinput_event_funcs = { + dx_dinput_event_prepare, + dx_dinput_event_check, + dx_dinput_event_dispatch, + NULL +}; + + +static void +dump_data_format (const DIDATAFORMAT *format) +{ +#ifdef GIMP_UNSTABLE + gint i; + + g_print ("dwSize: %ld\n", format->dwSize); + g_print ("dwObjSize: %ld\n", format->dwObjSize); + g_print ("dwFlags: "); + if (format->dwFlags == DIDF_ABSAXIS) + g_print ("DIDF_ABSAXIS"); + else if (format->dwFlags == DIDF_RELAXIS) + g_print ("DIDF_RELAXIS"); + else + g_print ("%#lx", format->dwFlags); + g_print ("\n"); + g_print ("dwDataSize: %ld\n", format->dwDataSize); + g_print ("dwNumObjs: %ld\n", format->dwNumObjs); + + for (i = 0; i < format->dwNumObjs; i++) + { + const DIOBJECTDATAFORMAT *oformat = (DIOBJECTDATAFORMAT *) (((char *) format->rgodf) + i*format->dwObjSize); + unsigned char *guid; + + g_print ("Object %d:\n", i); + if (oformat->pguid == NULL) + g_print (" pguid: NULL\n"); + else + { + UuidToString (oformat->pguid, &guid); + g_print (" pguid: %s\n", guid); + RpcStringFree (&guid); + } + + g_print (" dwOfs: %ld\n", oformat->dwOfs); + g_print (" dwType: "); + switch (DIDFT_GETTYPE (oformat->dwType)) + { +#define CASE(x) case DIDFT_##x: g_print ("DIDFT_"#x); break + CASE (RELAXIS); + CASE (ABSAXIS); + CASE (AXIS); + CASE (PSHBUTTON); + CASE (TGLBUTTON); + CASE (BUTTON); + CASE (POV); + CASE (COLLECTION); + CASE (NODATA); +#undef CASE + default: g_print ("%#x", DIDFT_GETTYPE (oformat->dwType)); + } + g_print (" "); + if (DIDFT_GETINSTANCE (oformat->dwType) == DIDFT_GETINSTANCE (DIDFT_ANYINSTANCE)) + g_print ("ANYINSTANCE"); + else + g_print ("#%d", DIDFT_GETINSTANCE (oformat->dwType)); +#define BIT(x) if (oformat->dwType & DIDFT_##x) g_print (" "#x) + BIT (FFACTUATOR); + BIT (FFEFFECTTRIGGER); + BIT (OUTPUT); + BIT (VENDORDEFINED); + BIT (ALIAS); + BIT (OPTIONAL); +#undef BIT + g_print ("\n"); + g_print (" dwFlags:"); + switch (oformat->dwFlags & DIDOI_ASPECTACCEL) + { + case DIDOI_ASPECTPOSITION: g_print (" DIDOI_ASPECTPOSITION"); break; + case DIDOI_ASPECTVELOCITY: g_print (" DIDOI_ASPECTVELOCITY"); break; + case DIDOI_ASPECTACCEL: g_print (" DIDOI_ASPECTACCEL"); break; + } + if (oformat->dwFlags & DIDOI_ASPECTFORCE) + g_print (" DIDOI_ASPECTFORCE"); + g_print ("\n"); + } +#endif +} + +static gboolean +dx_dinput_setup_events (ControllerDXDInput *controller, + GError **error) +{ + HRESULT hresult; + DIPROPDWORD dword; + gint i, k; + DXDInputSource *source; + + if ((controller->event = CreateEvent (NULL, TRUE, FALSE, NULL)) == NULL) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "CreateEvent failed: %s", + g_win32_error_message (GetLastError ())); + return FALSE; + } + + controller->format = g_new (DIDATAFORMAT, 1); + controller->format->dwSize = sizeof (DIDATAFORMAT); + controller->format->dwObjSize = sizeof (DIOBJECTDATAFORMAT); + + dword.diph.dwSize = sizeof (DIPROPDWORD); + dword.diph.dwHeaderSize = sizeof (DIPROPHEADER); + dword.diph.dwObj = 0; + dword.diph.dwHow = DIPH_DEVICE; + + /* Get the axis mode so we can use the same in the format */ + if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8, + DIPROP_AXISMODE, + &dword.diph)))) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::GetParameters failed: %s", + g_win32_error_message (hresult)); + goto fail0; + } + + controller->format->dwFlags = dword.dwData + 1; + + controller->format->dwNumObjs = + controller->num_buttons + + controller->num_axes + + controller->num_sliders + + controller->num_povs; + + controller->format->rgodf = g_new (DIOBJECTDATAFORMAT, controller->format->dwNumObjs); + + k = 0; + controller->format->dwDataSize = 0; + + for (i = 0; i < controller->num_buttons; i++) + { + controller->format->rgodf[k].pguid = NULL; + controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; + controller->format->rgodf[k].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE (i); + controller->format->rgodf[k].dwFlags = 0; + controller->format->dwDataSize += 1; + k++; + } + + controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4); + + for (i = 0; i < controller->num_axes; i++) + { + controller->format->rgodf[k].pguid = NULL; + controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; + controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i); + controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION; + controller->format->dwDataSize += 4; + k++; + } + + for (i = 0; i < controller->num_sliders; i++) + { + controller->format->rgodf[k].pguid = NULL; + controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; + controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i); + controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION; + controller->format->dwDataSize += 4; + k++; + } + + for (i = 0; i < controller->num_povs; i++) + { + controller->format->rgodf[k].pguid = NULL; + controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; + controller->format->rgodf[k].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE (i); + controller->format->rgodf[k].dwFlags = 0; + controller->format->dwDataSize += 4; + k++; + } + + g_assert (k == controller->format->dwNumObjs); + + controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4); + controller->prevdata = g_malloc (controller->format->dwDataSize); + + dump_data_format (controller->format); + + if (FAILED ((hresult = IDirectInputDevice8_SetDataFormat (controller->didevice8, + controller->format)))) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::SetDataFormat failed: %s", + g_win32_error_message (hresult)); + goto fail1; + } + + if (FAILED ((hresult = IDirectInputDevice8_SetEventNotification (controller->didevice8, + controller->event)))) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::SetEventNotification failed: %s", + g_win32_error_message (hresult)); + goto fail2; + } + + if (FAILED ((hresult = IDirectInputDevice8_Acquire (controller->didevice8)))) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::Acquire failed: %s", + g_win32_error_message (hresult)); + goto fail2; + } + + if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (controller->didevice8, + controller->format->dwDataSize, + controller->prevdata)))) + { + g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, + "IDirectInputDevice8::GetDeviceState failed: %s", + g_win32_error_message (hresult)); + goto fail2; + } + + source = (DXDInputSource *) g_source_new (&dx_dinput_event_funcs, + sizeof (DXDInputSource)); + source->controller = controller; + controller->source = (GSource *) source; + + controller->pollfd = g_new (GPollFD, 1); + + controller->pollfd->fd = (int) controller->event; + controller->pollfd->events = G_IO_IN; + + g_source_add_poll (&source->source, controller->pollfd); + g_source_attach (&source->source, NULL); + + return TRUE; + + fail2: + IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL); + fail1: + g_free (controller->format->rgodf); + g_free (controller->format); + controller->format = NULL; + g_free (controller->prevdata); + controller->prevdata = NULL; + fail0: + CloseHandle (controller->event); + controller->event = 0; + + return FALSE; +} + +static gboolean +dx_dinput_set_device (ControllerDXDInput *controller, + const gchar *guid) +{ + GError *error = NULL; + + if (controller->guid) + g_free (controller->guid); + + controller->guid = g_strdup (guid); + + g_object_set (controller, "name", _("DirectInput Events"), NULL); + + if (controller->guid && strlen (controller->guid)) + { + if (controller->store) + controller->didevice8 = + (LPDIRECTINPUTDEVICE8W) gimp_input_device_store_get_device_file (controller->store, + controller->guid); + } + else + { + g_object_set (controller, "state", _("No device configured"), NULL); + + return FALSE; + } + + if (controller->didevice8) + { + if (!dx_dinput_get_device_info (controller, &error) || + !dx_dinput_setup_events (controller, &error)) + { + g_object_set (controller, "state", error->message, NULL); + g_error_free (error); + } + } + else if (controller->store) + { + error = gimp_input_device_store_get_error (controller->store); + + if (error) + { + g_object_set (controller, "state", error->message, NULL); + g_error_free (error); + } + else + { + g_object_set (controller, "state", _("Device not available"), NULL); + } + } + + return FALSE; +}