/* input-device-manager.c generated by valac 0.36.1.17-97a62, the Vala compiler
 * generated from input-device-manager.vala, do not modify */

/* This file is part of retro-gtk. License: GPL-3.0+.*/

#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>


#define RETRO_TYPE_INPUT (retro_input_get_type ())
#define RETRO_INPUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RETRO_TYPE_INPUT, RetroInput))
#define RETRO_IS_INPUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RETRO_TYPE_INPUT))
#define RETRO_INPUT_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), RETRO_TYPE_INPUT, RetroInputIface))

typedef struct _RetroInput RetroInput;
typedef struct _RetroInputIface RetroInputIface;

#define RETRO_TYPE_DEVICE_TYPE (retro_device_type_get_type ())

#define RETRO_TYPE_INPUT_DESCRIPTOR (retro_input_descriptor_get_type ())
typedef struct _RetroInputDescriptor RetroInputDescriptor;

#define RETRO_TYPE_INPUT_DEVICE (retro_input_device_get_type ())
#define RETRO_INPUT_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RETRO_TYPE_INPUT_DEVICE, RetroInputDevice))
#define RETRO_IS_INPUT_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RETRO_TYPE_INPUT_DEVICE))
#define RETRO_INPUT_DEVICE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), RETRO_TYPE_INPUT_DEVICE, RetroInputDeviceIface))

typedef struct _RetroInputDevice RetroInputDevice;
typedef struct _RetroInputDeviceIface RetroInputDeviceIface;

#define RETRO_TYPE_INPUT_DEVICE_MANAGER (retro_input_device_manager_get_type ())
#define RETRO_INPUT_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RETRO_TYPE_INPUT_DEVICE_MANAGER, RetroInputDeviceManager))
#define RETRO_INPUT_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RETRO_TYPE_INPUT_DEVICE_MANAGER, RetroInputDeviceManagerClass))
#define RETRO_IS_INPUT_DEVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RETRO_TYPE_INPUT_DEVICE_MANAGER))
#define RETRO_IS_INPUT_DEVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RETRO_TYPE_INPUT_DEVICE_MANAGER))
#define RETRO_INPUT_DEVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RETRO_TYPE_INPUT_DEVICE_MANAGER, RetroInputDeviceManagerClass))

typedef struct _RetroInputDeviceManager RetroInputDeviceManager;
typedef struct _RetroInputDeviceManagerClass RetroInputDeviceManagerClass;
typedef struct _RetroInputDeviceManagerPrivate RetroInputDeviceManagerPrivate;
enum  {
	RETRO_INPUT_DEVICE_MANAGER_DUMMY_PROPERTY,
	RETRO_INPUT_DEVICE_MANAGER_LAST_PROPERTY
};
static GParamSpec* retro_input_device_manager_properties[RETRO_INPUT_DEVICE_MANAGER_LAST_PROPERTY];
#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
#define _g_list_free0(var) ((var == NULL) ? NULL : (var = (g_list_free (var), NULL)))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))

typedef enum  {
	RETRO_DEVICE_TYPE_TYPE_MASK = 0xff,
	RETRO_DEVICE_TYPE_NONE = 0,
	RETRO_DEVICE_TYPE_JOYPAD = 1,
	RETRO_DEVICE_TYPE_MOUSE = 2,
	RETRO_DEVICE_TYPE_KEYBOARD = 3,
	RETRO_DEVICE_TYPE_LIGHTGUN = 4,
	RETRO_DEVICE_TYPE_ANALOG = 5,
	RETRO_DEVICE_TYPE_POINTER = 6
} RetroDeviceType;

struct _RetroInputDescriptor {
	guint port;
	RetroDeviceType device;
	guint index;
	guint id;
	gchar* description;
};

struct _RetroInputDeviceIface {
	GTypeInterface parent_iface;
	void (*poll) (RetroInputDevice* self);
	gint16 (*get_input_state) (RetroInputDevice* self, RetroDeviceType device, guint index, guint id);
	RetroDeviceType (*get_device_type) (RetroInputDevice* self);
	guint64 (*get_device_capabilities) (RetroInputDevice* self);
};

typedef void (*RetroInputControllerCallback) (guint port, RetroInputDevice* device, void* user_data);
struct _RetroInputIface {
	GTypeInterface parent_iface;
	void (*poll) (RetroInput* self);
	gint16 (*get_state) (RetroInput* self, guint port, RetroDeviceType device, guint index, guint id);
	void (*set_descriptors) (RetroInput* self, RetroInputDescriptor* input_descriptors, int input_descriptors_length1);
	guint64 (*get_device_capabilities) (RetroInput* self);
	void (*foreach_controller) (RetroInput* self, RetroInputControllerCallback callback, void* callback_target);
};

struct _RetroInputDeviceManager {
	GObject parent_instance;
	RetroInputDeviceManagerPrivate * priv;
};

struct _RetroInputDeviceManagerClass {
	GObjectClass parent_class;
};

struct _RetroInputDeviceManagerPrivate {
	GHashTable* controller_devices;
};


static gpointer retro_input_device_manager_parent_class = NULL;
static RetroInputIface * retro_input_device_manager_retro_input_parent_iface = NULL;

GType retro_device_type_get_type (void) G_GNUC_CONST;
GType retro_input_descriptor_get_type (void) G_GNUC_CONST;
RetroInputDescriptor* retro_input_descriptor_dup (const RetroInputDescriptor* self);
void retro_input_descriptor_free (RetroInputDescriptor* self);
void retro_input_descriptor_copy (const RetroInputDescriptor* self, RetroInputDescriptor* dest);
void retro_input_descriptor_destroy (RetroInputDescriptor* self);
GType retro_input_device_get_type (void) G_GNUC_CONST;
GType retro_input_get_type (void) G_GNUC_CONST;
GType retro_input_device_manager_get_type (void) G_GNUC_CONST;
#define RETRO_INPUT_DEVICE_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RETRO_TYPE_INPUT_DEVICE_MANAGER, RetroInputDeviceManagerPrivate))
static void retro_input_device_manager_real_poll (RetroInput* base);
void retro_input_device_poll (RetroInputDevice* self);
static gint16 retro_input_device_manager_real_get_state (RetroInput* base, guint port, RetroDeviceType device, guint index, guint id);
guint64 retro_input_device_get_device_capabilities (RetroInputDevice* self);
gint16 retro_input_device_get_input_state (RetroInputDevice* self, RetroDeviceType device, guint index, guint id);
static void retro_input_device_manager_real_set_descriptors (RetroInput* base, RetroInputDescriptor* input_descriptors, int input_descriptors_length1);
static guint64 retro_input_device_manager_real_get_device_capabilities (RetroInput* base);
void retro_input_device_manager_set_controller_device (RetroInputDeviceManager* self, guint port, RetroInputDevice* device);
static guint* _uint_dup (guint* self);
void retro_input_device_manager_set_keyboard (RetroInputDeviceManager* self, GtkWidget* widget);
static gboolean __lambda4_ (RetroInputDeviceManager* self, GtkWidget* w, GdkEventKey* e);
static gboolean ___lambda4__gtk_widget_key_press_event (GtkWidget* _sender, GdkEventKey* event, gpointer self);
static gboolean __lambda5_ (RetroInputDeviceManager* self, GtkWidget* w, GdkEventKey* e);
static gboolean ___lambda5__gtk_widget_key_release_event (GtkWidget* _sender, GdkEventKey* event, gpointer self);
void retro_input_device_manager_remove_controller_device (RetroInputDeviceManager* self, guint port);
static void retro_input_device_manager_real_foreach_controller (RetroInput* base, RetroInputControllerCallback callback, void* callback_target);
RetroInputDeviceManager* retro_input_device_manager_new (void);
RetroInputDeviceManager* retro_input_device_manager_construct (GType object_type);
static GObject * retro_input_device_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties);
static void _g_free0_ (gpointer var);
static void _g_object_unref0_ (gpointer var);
static void retro_input_device_manager_finalize (GObject * obj);


static void retro_input_device_manager_real_poll (RetroInput* base) {
	RetroInputDeviceManager * self;
	GHashTable* _tmp0_;
	GList* _tmp1_;
	self = (RetroInputDeviceManager*) base;
	_tmp0_ = self->priv->controller_devices;
	_tmp1_ = g_hash_table_get_values (_tmp0_);
	{
		GList* device_collection = NULL;
		GList* device_it = NULL;
		device_collection = _tmp1_;
		for (device_it = device_collection; device_it != NULL; device_it = device_it->next) {
			RetroInputDevice* device = NULL;
			device = (RetroInputDevice*) device_it->data;
			{
				RetroInputDevice* _tmp2_;
				_tmp2_ = device;
				if (_tmp2_ != NULL) {
					RetroInputDevice* _tmp3_;
					_tmp3_ = device;
					retro_input_device_poll (_tmp3_);
				}
			}
		}
		_g_list_free0 (device_collection);
	}
}


static gpointer _g_object_ref0 (gpointer self) {
	return self ? g_object_ref (self) : NULL;
}


static gint16 retro_input_device_manager_real_get_state (RetroInput* base, guint port, RetroDeviceType device, guint index, guint id) {
	RetroInputDeviceManager * self;
	gint16 result = 0;
	GHashTable* _tmp0_;
	guint _tmp1_;
	gboolean _tmp2_;
	self = (RetroInputDeviceManager*) base;
	_tmp0_ = self->priv->controller_devices;
	_tmp1_ = port;
	_tmp2_ = g_hash_table_contains (_tmp0_, &_tmp1_);
	if (_tmp2_) {
		RetroInputDevice* controller_device;
		GHashTable* _tmp3_;
		guint _tmp4_;
		gconstpointer _tmp5_;
		RetroInputDevice* _tmp6_;
		RetroInputDevice* _tmp7_;
		_tmp3_ = self->priv->controller_devices;
		_tmp4_ = port;
		_tmp5_ = g_hash_table_lookup (_tmp3_, &_tmp4_);
		_tmp6_ = _g_object_ref0 ((RetroInputDevice*) _tmp5_);
		controller_device = _tmp6_;
		_tmp7_ = controller_device;
		if (_tmp7_ != NULL) {
			guint64 capabilities;
			RetroInputDevice* _tmp8_;
			guint64 _tmp9_;
			gboolean is_capable;
			guint64 _tmp10_;
			RetroDeviceType _tmp11_;
			gboolean _tmp12_;
			_tmp8_ = controller_device;
			_tmp9_ = retro_input_device_get_device_capabilities (_tmp8_);
			capabilities = _tmp9_;
			_tmp10_ = capabilities;
			_tmp11_ = device;
			is_capable = (_tmp10_ & (1 << _tmp11_)) != ((guint64) 0);
			_tmp12_ = is_capable;
			if (_tmp12_) {
				RetroInputDevice* _tmp13_;
				RetroDeviceType _tmp14_;
				guint _tmp15_;
				guint _tmp16_;
				gint16 _tmp17_;
				_tmp13_ = controller_device;
				_tmp14_ = device;
				_tmp15_ = index;
				_tmp16_ = id;
				_tmp17_ = retro_input_device_get_input_state (_tmp13_, _tmp14_, _tmp15_, _tmp16_);
				result = _tmp17_;
				_g_object_unref0 (controller_device);
				return result;
			}
		}
		_g_object_unref0 (controller_device);
	}
	result = (gint16) 0;
	return result;
}


static void retro_input_device_manager_real_set_descriptors (RetroInput* base, RetroInputDescriptor* input_descriptors, int input_descriptors_length1) {
	RetroInputDeviceManager * self;
	self = (RetroInputDeviceManager*) base;
}


static guint64 retro_input_device_manager_real_get_device_capabilities (RetroInput* base) {
	RetroInputDeviceManager * self;
	guint64 result = 0ULL;
	self = (RetroInputDeviceManager*) base;
	result = (guint64) 0;
	return result;
}


static guint* _uint_dup (guint* self) {
	guint* dup;
	dup = g_new0 (guint, 1);
	memcpy (dup, self, sizeof (guint));
	return dup;
}


static gpointer __uint_dup0 (gpointer self) {
	return self ? _uint_dup (self) : NULL;
}


void retro_input_device_manager_set_controller_device (RetroInputDeviceManager* self, guint port, RetroInputDevice* device) {
	GHashTable* _tmp0_;
	guint _tmp1_;
	gboolean _tmp2_;
	guint _tmp13_;
	RetroInputDevice* _tmp14_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (device != NULL);
	_tmp0_ = self->priv->controller_devices;
	_tmp1_ = port;
	_tmp2_ = g_hash_table_contains (_tmp0_, &_tmp1_);
	if (_tmp2_) {
		GHashTable* _tmp3_;
		guint _tmp4_;
		guint* _tmp5_;
		RetroInputDevice* _tmp6_;
		RetroInputDevice* _tmp7_;
		_tmp3_ = self->priv->controller_devices;
		_tmp4_ = port;
		_tmp5_ = __uint_dup0 (&_tmp4_);
		_tmp6_ = device;
		_tmp7_ = _g_object_ref0 (_tmp6_);
		g_hash_table_replace (_tmp3_, _tmp5_, _tmp7_);
	} else {
		GHashTable* _tmp8_;
		guint _tmp9_;
		guint* _tmp10_;
		RetroInputDevice* _tmp11_;
		RetroInputDevice* _tmp12_;
		_tmp8_ = self->priv->controller_devices;
		_tmp9_ = port;
		_tmp10_ = __uint_dup0 (&_tmp9_);
		_tmp11_ = device;
		_tmp12_ = _g_object_ref0 (_tmp11_);
		g_hash_table_insert (_tmp8_, _tmp10_, _tmp12_);
	}
	_tmp13_ = port;
	_tmp14_ = device;
	g_signal_emit_by_name ((RetroInput*) self, "controller-connected", _tmp13_, _tmp14_);
}


static gboolean __lambda4_ (RetroInputDeviceManager* self, GtkWidget* w, GdkEventKey* e) {
	gboolean result = FALSE;
	GdkEventKey* _tmp0_;
	gboolean _tmp1_ = FALSE;
	g_return_val_if_fail (w != NULL, FALSE);
	g_return_val_if_fail (e != NULL, FALSE);
	_tmp0_ = e;
	g_signal_emit_by_name ((RetroInput*) self, "key-event", _tmp0_, &_tmp1_);
	result = _tmp1_;
	return result;
}


static gboolean ___lambda4__gtk_widget_key_press_event (GtkWidget* _sender, GdkEventKey* event, gpointer self) {
	gboolean result;
	result = __lambda4_ ((RetroInputDeviceManager*) self, _sender, event);
	return result;
}


static gboolean __lambda5_ (RetroInputDeviceManager* self, GtkWidget* w, GdkEventKey* e) {
	gboolean result = FALSE;
	GdkEventKey* _tmp0_;
	gboolean _tmp1_ = FALSE;
	g_return_val_if_fail (w != NULL, FALSE);
	g_return_val_if_fail (e != NULL, FALSE);
	_tmp0_ = e;
	g_signal_emit_by_name ((RetroInput*) self, "key-event", _tmp0_, &_tmp1_);
	result = _tmp1_;
	return result;
}


static gboolean ___lambda5__gtk_widget_key_release_event (GtkWidget* _sender, GdkEventKey* event, gpointer self) {
	gboolean result;
	result = __lambda5_ ((RetroInputDeviceManager*) self, _sender, event);
	return result;
}


void retro_input_device_manager_set_keyboard (RetroInputDeviceManager* self, GtkWidget* widget) {
	GtkWidget* _tmp0_;
	GtkWidget* _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (widget != NULL);
	_tmp0_ = widget;
	g_signal_connect_object (_tmp0_, "key-press-event", (GCallback) ___lambda4__gtk_widget_key_press_event, self, 0);
	_tmp1_ = widget;
	g_signal_connect_object (_tmp1_, "key-release-event", (GCallback) ___lambda5__gtk_widget_key_release_event, self, 0);
}


void retro_input_device_manager_remove_controller_device (RetroInputDeviceManager* self, guint port) {
	GHashTable* _tmp0_;
	guint _tmp1_;
	gboolean _tmp2_;
	GHashTable* _tmp3_;
	guint _tmp4_;
	guint _tmp5_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->controller_devices;
	_tmp1_ = port;
	_tmp2_ = g_hash_table_contains (_tmp0_, &_tmp1_);
	if (!_tmp2_) {
		return;
	}
	_tmp3_ = self->priv->controller_devices;
	_tmp4_ = port;
	g_hash_table_remove (_tmp3_, &_tmp4_);
	_tmp5_ = port;
	g_signal_emit_by_name ((RetroInput*) self, "controller-disconnected", _tmp5_);
}


static void retro_input_device_manager_real_foreach_controller (RetroInput* base, RetroInputControllerCallback callback, void* callback_target) {
	RetroInputDeviceManager * self;
	GHashTable* _tmp0_;
	GList* _tmp1_;
	self = (RetroInputDeviceManager*) base;
	_tmp0_ = self->priv->controller_devices;
	_tmp1_ = g_hash_table_get_keys (_tmp0_);
	{
		GList* port_collection = NULL;
		GList* port_it = NULL;
		port_collection = _tmp1_;
		for (port_it = port_collection; port_it != NULL; port_it = port_it->next) {
			guint* port = NULL;
			port = (guint*) port_it->data;
			{
				RetroInputControllerCallback _tmp2_;
				void* _tmp2__target;
				guint* _tmp3_;
				GHashTable* _tmp4_;
				guint* _tmp5_;
				gconstpointer _tmp6_;
				_tmp2_ = callback;
				_tmp2__target = callback_target;
				_tmp3_ = port;
				_tmp4_ = self->priv->controller_devices;
				_tmp5_ = port;
				_tmp6_ = g_hash_table_lookup (_tmp4_, _tmp5_);
				_tmp2_ (*_tmp3_, (RetroInputDevice*) _tmp6_, _tmp2__target);
			}
		}
		_g_list_free0 (port_collection);
	}
}


RetroInputDeviceManager* retro_input_device_manager_construct (GType object_type) {
	RetroInputDeviceManager * self = NULL;
	self = (RetroInputDeviceManager*) g_object_new (object_type, NULL);
	return self;
}


RetroInputDeviceManager* retro_input_device_manager_new (void) {
	return retro_input_device_manager_construct (RETRO_TYPE_INPUT_DEVICE_MANAGER);
}


static void _g_free0_ (gpointer var) {
	(var == NULL) ? NULL : (var = (g_free (var), NULL));
}


static void _g_object_unref0_ (gpointer var) {
	(var == NULL) ? NULL : (var = (g_object_unref (var), NULL));
}


static GObject * retro_input_device_manager_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties) {
	GObject * obj;
	GObjectClass * parent_class;
	RetroInputDeviceManager * self;
	GHashFunc _tmp0_;
	GEqualFunc _tmp1_;
	GHashTable* _tmp2_;
	parent_class = G_OBJECT_CLASS (retro_input_device_manager_parent_class);
	obj = parent_class->constructor (type, n_construct_properties, construct_properties);
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, RETRO_TYPE_INPUT_DEVICE_MANAGER, RetroInputDeviceManager);
	_tmp0_ = g_int_hash;
	_tmp1_ = g_int_equal;
	_tmp2_ = g_hash_table_new_full (_tmp0_, _tmp1_, _g_free0_, _g_object_unref0_);
	_g_hash_table_unref0 (self->priv->controller_devices);
	self->priv->controller_devices = _tmp2_;
	return obj;
}


static void retro_input_device_manager_class_init (RetroInputDeviceManagerClass * klass) {
	retro_input_device_manager_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (RetroInputDeviceManagerPrivate));
	G_OBJECT_CLASS (klass)->constructor = retro_input_device_manager_constructor;
	G_OBJECT_CLASS (klass)->finalize = retro_input_device_manager_finalize;
}


static void retro_input_device_manager_retro_input_interface_init (RetroInputIface * iface) {
	retro_input_device_manager_retro_input_parent_iface = g_type_interface_peek_parent (iface);
	iface->poll = (void (*) (RetroInput *)) retro_input_device_manager_real_poll;
	iface->get_state = (gint16 (*) (RetroInput *, guint, RetroDeviceType, guint, guint)) retro_input_device_manager_real_get_state;
	iface->set_descriptors = (void (*) (RetroInput *, RetroInputDescriptor*, int)) retro_input_device_manager_real_set_descriptors;
	iface->get_device_capabilities = (guint64 (*) (RetroInput *)) retro_input_device_manager_real_get_device_capabilities;
	iface->foreach_controller = (void (*) (RetroInput *, RetroInputControllerCallback, void*)) retro_input_device_manager_real_foreach_controller;
}


static void retro_input_device_manager_instance_init (RetroInputDeviceManager * self) {
	self->priv = RETRO_INPUT_DEVICE_MANAGER_GET_PRIVATE (self);
}


static void retro_input_device_manager_finalize (GObject * obj) {
	RetroInputDeviceManager * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, RETRO_TYPE_INPUT_DEVICE_MANAGER, RetroInputDeviceManager);
	_g_hash_table_unref0 (self->priv->controller_devices);
	G_OBJECT_CLASS (retro_input_device_manager_parent_class)->finalize (obj);
}


GType retro_input_device_manager_get_type (void) {
	static volatile gsize retro_input_device_manager_type_id__volatile = 0;
	if (g_once_init_enter (&retro_input_device_manager_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (RetroInputDeviceManagerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) retro_input_device_manager_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RetroInputDeviceManager), 0, (GInstanceInitFunc) retro_input_device_manager_instance_init, NULL };
		static const GInterfaceInfo retro_input_info = { (GInterfaceInitFunc) retro_input_device_manager_retro_input_interface_init, (GInterfaceFinalizeFunc) NULL, NULL};
		GType retro_input_device_manager_type_id;
		retro_input_device_manager_type_id = g_type_register_static (G_TYPE_OBJECT, "RetroInputDeviceManager", &g_define_type_info, 0);
		g_type_add_interface_static (retro_input_device_manager_type_id, RETRO_TYPE_INPUT, &retro_input_info);
		g_once_init_leave (&retro_input_device_manager_type_id__volatile, retro_input_device_manager_type_id);
	}
	return retro_input_device_manager_type_id__volatile;
}



