libpurple/eventloop.c

Thu, 15 Jun 2017 11:35:00 -0500

author
Mike Ruprecht <cmaiku@gmail.com>
date
Thu, 15 Jun 2017 11:35:00 -0500
changeset 38418
9d86663a7437
parent 38417
0b114022d5f9
child 38419
4c934cacb332
permissions
-rw-r--r--

eventloop: Replace eventloop input functions with Pidgin versions

Now that libpurple uses Gio, configuring the event loop to use
something other than the GLib event loop causes things to break.
This is because Gio adds sources to the GLib event loop in a way
which can't practically be overridden.

Fortunately, other event loops can still be used by driving the
GLib event loop manually. See the GLib Main Event Loop docs for
information on doing this.

This patch replaces purple_input_add() and purple_input_remove()
with what has been used in Pidgin. This should be a suitable,
generic, GLib solution until the rest of the codebase can be
ported off of these functions.

/* purple
 *
 * Purple is the legal property of its developers, whose names are too numerous
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 * source distribution.
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 */
#include "internal.h"
#include "eventloop.h"

#define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)

static PurpleEventLoopUiOps *eventloop_ui_ops = NULL;

typedef struct _PurpleIOClosure {
	PurpleInputFunction function;
	guint result;
	gpointer data;
} PurpleIOClosure;

guint
purple_timeout_add(guint interval, GSourceFunc function, gpointer data)
{
	return g_timeout_add(interval, function, data);
}

guint
purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data)
{
	return g_timeout_add_seconds(interval, function, data);
}

gboolean
purple_timeout_remove(guint tag)
{
	return g_source_remove(tag);
}

static gboolean
purple_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
{
	PurpleIOClosure *closure = data;
	PurpleInputCondition purple_cond = 0;

	if (condition & PURPLE_GLIB_READ_COND)
		purple_cond |= PURPLE_INPUT_READ;
	if (condition & PURPLE_GLIB_WRITE_COND)
		purple_cond |= PURPLE_INPUT_WRITE;

#ifdef _WIN32
	if(!purple_cond) {
		return TRUE;
	}
#endif /* _WIN32 */

	closure->function(closure->data, g_io_channel_unix_get_fd(source),
			  purple_cond);

	return TRUE;
}

guint
purple_input_add(int source, PurpleInputCondition condition, PurpleInputFunction func, gpointer user_data)
{
	PurpleIOClosure *closure = g_new0(PurpleIOClosure, 1);
	GIOChannel *channel;
	GIOCondition cond = 0;

	closure->function = func;
	closure->data = user_data;

	if (condition & PURPLE_INPUT_READ)
		cond |= PURPLE_GLIB_READ_COND;
	if (condition & PURPLE_INPUT_WRITE)
		cond |= PURPLE_GLIB_WRITE_COND;

#ifdef _WIN32
	channel = g_io_channel_win32_new_socket(source);
#else
	channel = g_io_channel_unix_new(source);
#endif

	closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT,
			cond, purple_io_invoke, closure, g_free);

	g_io_channel_unref(channel);
	return closure->result;
}

gboolean
purple_input_remove(guint tag)
{
	return g_source_remove(tag);
}

int
purple_input_get_error(int fd, int *error)
{
	PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops();

	if (ops->input_get_error)
	{
		int ret = ops->input_get_error(fd, error);
		errno = *error;
		return ret;
	}
	else
	{
		socklen_t len;
		len = sizeof(*error);

		return getsockopt(fd, SOL_SOCKET, SO_ERROR, error, &len);
	}
}

int
purple_input_pipe(int pipefd[2])
{
#ifdef _WIN32
	return wpurple_input_pipe(pipefd);
#else
	return pipe(pipefd);
#endif
}

void
purple_eventloop_set_ui_ops(PurpleEventLoopUiOps *ops)
{
	eventloop_ui_ops = ops;
}

PurpleEventLoopUiOps *
purple_eventloop_get_ui_ops(void)
{
	g_return_val_if_fail(eventloop_ui_ops != NULL, NULL);

	return eventloop_ui_ops;
}

/**************************************************************************
 * GBoxed code
 **************************************************************************/
static PurpleEventLoopUiOps *
purple_eventloop_ui_ops_copy(PurpleEventLoopUiOps *ops)
{
	PurpleEventLoopUiOps *ops_new;

	g_return_val_if_fail(ops != NULL, NULL);

	ops_new = g_new(PurpleEventLoopUiOps, 1);
	*ops_new = *ops;

	return ops_new;
}

GType
purple_eventloop_ui_ops_get_type(void)
{
	static GType type = 0;

	if (type == 0) {
		type = g_boxed_type_register_static("PurpleEventLoopUiOps",
				(GBoxedCopyFunc)purple_eventloop_ui_ops_copy,
				(GBoxedFreeFunc)g_free);
	}

	return type;
}

mercurial