sinek/src gtkxine_x11.c,NONE,1.1

[email protected] Mon, 17 Feb 2003 00:45:14 -0800
Newsgroups gmane.comp.video.sinek.cvs
Message-ID <[email protected]>
Update of /cvsroot/sinek/sinek/src
In directory sc8-pr-cvs1:/tmp/cvs-serv31002/src

Added Files:
	gtkxine_x11.c 
Log Message:
x11-specific stuff for gtkxine, broken out into its own file


--- NEW FILE: gtkxine_x11.c ---
/*
**  Sinek (Media Player)
**  Copyright (c) 2002  Andres Salomon <[email protected]>
**
**  This code is free software; you can redistribute it and/or
**  modify it under the terms of the GNU General Public License.
**
**  $Id: gtkxine_x11.c,v 1.1 2003/02/17 08:45:12 dilinger Exp $
*/

#include "gtkxine.h"
#include "gtkxine_x11.h"

#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
#include <X11/extensions/XShm.h>
#include <X11/keysym.h>
#include <gdk/gdkx.h>
#include <pthread.h>
                                                                                
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "i18n.h"

struct gtk_xine_x11_visual_t
{
	x11_visual_t vis;
	pthread_t event_thread;
	int complete;
	
	/* screensaver stuff */
	int keycode;
	int have_xtest, disabled, timeout, interval;
	int prefer_blanking, allow_exposures;
};

static void frame_output_cb (void *user_data, int vid_w, int vid_h, double vidp_aspect, int *dest_x, int *dest_y, int *dest_w, int *dest_h, double *dest_vidp_aspect, int *win_x, int *win_y)
{
	GtkWidget *widget = (GtkWidget *) user_data;

	*win_x = widget->allocation.x;
	*win_y = widget->allocation.y;
	*dest_x = 0;
	*dest_y = 0;
	*dest_w = widget->allocation.width;
	*dest_h = widget->allocation.height;
	*dest_vidp_aspect = vidp_aspect;
}

static void dest_size_cb (void *user_data, int vid_w, int vid_h, double vidp_aspect, int *dest_w, int *dest_h, double *dest_vidp_aspect)
{
	GtkWidget *widget = (GtkWidget *) user_data;

	*dest_w = widget->allocation.width;
	*dest_h = widget->allocation.height;
	*dest_vidp_aspect = vidp_aspect;
}

static int translate_point (GtkXine *xine, int x, int y, int *vid_x, int *vid_y)
{
	x11_rectangle_t rect;
	rect.x = x;
	rect.y = y;
	rect.w = 0;
	rect.h = 0;

	if (xine_gui_send_vo_data (xine->stream, XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void *) &rect) != -1)
	{
		*vid_x = rect.x;
		*vid_y = rect.y;
		return 1;
	}

	return 0;
}

static int send_input_event (GtkXine *xine, XEvent *ev)
{
	xine_event_t xine_event;
	xine_input_data_t xine_data;
	int x, y, ret = 0;

	switch (ev->type) {
		case MotionNotify:
			if (translate_point (xine, ((XMotionEvent *) ev)->x, ((XMotionEvent *) ev)->y, &x, &y)) {
				xine_event.type = XINE_EVENT_INPUT_MOUSE_MOVE;
				xine_data.button = 0;
				ret = 1;
			}
			break;
		case ButtonPress:
			if (((XButtonEvent *) ev)->button == 1 && translate_point (xine, ((XButtonEvent *) ev)->x, ((XButtonEvent *) ev)->y, &x, &y)) {
				xine_event.type = XINE_EVENT_INPUT_MOUSE_BUTTON;
				xine_data.button = 1;
				ret = 1;
			}
			break;
	}
	if (ret) {
		xine_event.stream = xine->stream;
		xine_event.data = (void *) &xine_data;
		xine_data.event = xine_event;
		xine_data.x = x;
		xine_data.y = y;
		xine_event_send (xine->stream, &xine_event);
	}

	return ret;
}

static void gtk_xine_event_handler (GtkXine *xine, XEvent *ev)
{
	if (ev->type == ((struct gtk_xine_x11_visual_t *) xine->video_driver_data)->complete) {
		xine_gui_send_vo_data (xine->stream, XINE_GUI_SEND_COMPLETION_EVENT, ev);
		return;
	}

	switch (ev->type) {
		case MotionNotify:
		case ButtonPress:
		case KeyPress:
			send_input_event (xine, ev);
			break;

		case Expose:
			xine_gui_send_vo_data (xine->stream, XINE_GUI_SEND_EXPOSE_EVENT, (void *) ev);
			break;
	}
}

static void *gtk_xine_input_thread (void *data)
{
	GtkXine *xine = GTK_XINE (data);
	x11_visual_t *vis = (x11_visual_t *) xine->video_driver_data;
	XEvent xev;

	pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
	while (xine->video_driver_data) {
		XNextEvent (vis->display, &xev);
		gtk_xine_event_handler ((GtkXine *) data, &xev);
	}

	return NULL;
}

#if HAVE_XTEST
static gboolean fake_event (gpointer data)
{
	struct gtk_xine_x11_visual_t *vis = (struct gtk_xine_x11_visual_t *) ((GtkXine *) data)->video_driver_data;

	if (vis->disabled) {
		XTestFakeKeyEvent (vis->vis.display, vis->keycode, True, CurrentTime);
		XTestFakeKeyEvent (vis->vis.display, vis->keycode, False, CurrentTime);
	}
	return TRUE;
}
#endif

static void gtk_xine_x11_scrsaver_init (GtkXine *xine)
{
	struct gtk_xine_x11_visual_t *vis = (struct gtk_xine_x11_visual_t *) xine->video_driver_data;
	
#if HAVE_XTEST
	int a, b, c, d;
	
	vis->have_xtest = XTestQueryExtension (vis->vis.display, &a, &b, &c, &d);
	if (vis->have_xtest) {
		vis->keycode = XKeysymToKeycode (vis->vis.display, XK_Shift_L);
		g_timeout_add (15000, (GSourceFunc) fake_event, xine);
	}
#else
	vis->have_xtest = 0;
#endif
}

void gtk_xine_x11_video_init (GtkXine *xine)
{
	struct gtk_xine_x11_visual_t *gvis;
	x11_visual_t *vis;

	g_return_if_fail (xine != NULL);
	if (!XInitThreads ())
		g_error (_("XInitThreads() failed, your X library is not thread-safe!"));
	if (!g_thread_supported ())
		g_thread_init (NULL);

	gvis = g_malloc (sizeof (*gvis));
	xine->video_driver_data = (void *) gvis;
	vis = (x11_visual_t *) gvis;

	vis->display = XOpenDisplay (NULL);
	XLockDisplay (vis->display);
	vis->screen = DefaultScreen (vis->display);
	vis->d = GDK_WINDOW_XID (GTK_WIDGET (xine)->window);
	vis->user_data = (void *) xine;
	vis->dest_size_cb = dest_size_cb;
	vis->frame_output_cb = frame_output_cb;

	gvis->complete = 0;
	if (XShmQueryExtension (vis->display))
		gvis->complete = XShmGetEventBase (vis->display) + ShmCompletion;
	XSelectInput (vis->display, vis->d,
			StructureNotifyMask | ExposureMask
			| ButtonPressMask | PointerMotionMask | KeyPressMask);
	gtk_xine_x11_scrsaver_init (xine);
	XUnlockDisplay (vis->display);

	pthread_create (&gvis->event_thread, NULL, gtk_xine_input_thread, (void *) xine);
}

void gtk_xine_x11_video_finalize (GtkXine *xine)
{
	pthread_t thr;

	g_return_if_fail (xine != NULL);
	thr = ((struct gtk_xine_x11_visual_t *) xine->video_driver_data)->event_thread;
	g_free (xine->video_driver_data);
	xine->video_driver_data = NULL;
	pthread_cancel (thr);
	pthread_join (thr, NULL);
}

int gtk_xine_x11_video_scrsaver_set (GtkXine *xine, gboolean enable)
{
	struct gtk_xine_x11_visual_t *vis = (struct gtk_xine_x11_visual_t *) xine->video_driver_data;

	if (enable && vis->disabled) {
		if (!vis->have_xtest)
			XSetScreenSaver (vis->vis.display, vis->timeout, vis->interval, vis->prefer_blanking, vis->allow_exposures);
		vis->disabled = 0;
	}
	else if (!enable && !vis->disabled) {
		if (!vis->have_xtest) {
			XGetScreenSaver (vis->vis.display, &vis->timeout, &vis->interval, &vis->prefer_blanking, &vis->allow_exposures);
			XSetScreenSaver (vis->vis.display, 0, 0, DontPreferBlanking, DontAllowExposures);
		}
		vis->disabled = 1;
	}

	return enable;
}

int gtk_xine_x11_video_visual_type (GtkXine *xine)
{
	return XINE_VISUAL_TYPE_X11;
}




-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf