Вот небольшой файлик. Может наведет на путь истинный. Весь архив прикрепить не позволили. Если что пиши, вышлю мылом.
/* XVGTK Xv widget for Gtk applications
* Copyright (C) 2001 - Ronald Bultje
* Copyright (C) 2004 - Vadim Sinolits, NIIRCOM
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define HAVE_SYS_SHM_H
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdarg.h>
#include <string.h>
#ifdef HAVE_SYS_SHM_H
#include <sys/shm.h>
#endif
#include <X11/Xlib.h>
#include <X11/Xmd.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#ifdef HAVE_SYS_SHM_H
#include <X11/extensions/XShm.h>
#endif
//#ifdef DPMSINFO_IN_DPMS_H
//#include <X11/extensions/dpms.h>
//#endif
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
// local includes
#include "../include/gtktvplug.h"
#include "../include/safe_alloc.h"
//#define MY_DEBUG_EVENTS
//#define MY_DEBUG_PRINTS
// main functions
static void gtk_tvplug_class_init (GtkTvPlugClass *klass);
static void gtk_tvplug_init (GtkTvPlug *tvplug);
static void gtk_tvplug_init_image (GtkTvPlug *tvplug);
static void gtk_tvplug_destroy (GtkObject *object);
static void gtk_tvplug_realize (GtkWidget *widget);
static void gtk_tvplug_size_request (GtkWidget *widget, GtkRequisition *requisition);
static void gtk_tvplug_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
static gint gtk_tvplug_expose (GtkWidget *widget, GdkEventExpose *event);
// use this to detect events
#ifdef MY_DEBUG_EVENTS
static gint gtk_tvplug_events (GtkWidget *widget, GdkEvent *event);
static void gtk_tvplug_event_after (GtkWidget *widget, GdkEvent *event, void *data);
#endif
static void gtk_tvplug_set_properties (GtkTvPlug *tvplug, GtkTvPlugPort *port, int width, int height, int type);
GtkTvPlugPort *gtk_tvplug_get_ports(int *ret);
void gtk_tvplug_query_attributes(GtkWidget *widget);
void show_info(void);
// Common functions
void gtk_tvplug_destroy_image (GtkWidget *tvplug, gpointer data);
static void SelectVideoNotify_xv(GtkWidget *widget, void *plugg);
static void SelectPortNotify_xv(GtkWidget *widget, void *plugg);
// output functions
// XV image
static void gtk_tvplug_create_image_xv(void *plugg);
static void gtk_tvplug_put_image_xv(GtkWidget *widget, void *plugg);
static void gtk_tvplug_destroy_image_xv(GtkWidget *w,void *tvplug);
// XVSHM image
static void gtk_tvplug_create_image_xvsh(void *plugg);
static void gtk_tvplug_put_image_xvsh(GtkWidget *widget, void *plugg);
static void gtk_tvplug_destroy_image_xvsh(GtkWidget *w,void *tvplug);
// XVideo overlay
static void gtk_tvplug_create_image_xvvo(void *plugg);
static void gtk_tvplug_put_image_xvvo(GtkWidget *widget, void *plugg);
static void gtk_tvplug_destroy_image_xvvo(GtkWidget *w,void *tvplug);
static GtkWidgetClass *parent_class = NULL;
// stupid, maybe...
static int log_printf (const char *format, ...) {
int ret=0;
#ifdef MY_DEBUG_PRINTS
va_list arg;
char str[1024];
va_start (arg, format);
vsnprintf(str, 1024, format, arg);
ret=printf("%s",str);
va_end (arg);
#endif
return ret;
}
// new object functions
guint gtk_tvplug_get_type ()
{
static GType tvplug_type = 0;
if (!tvplug_type)
{
static const GTypeInfo tvplug_info =
{
sizeof (GtkTvPlugClass),
NULL,
NULL,
(GClassInitFunc) gtk_tvplug_class_init,
NULL,
NULL,
sizeof(GtkTvPlug),
0,
(GInstanceInitFunc)gtk_tvplug_init,
};
tvplug_type=g_type_register_static (GTK_TYPE_WIDGET, "GtkTvPlug", &tvplug_info, 0);
}
return tvplug_type;
}
// object class init
static void gtk_tvplug_class_init (GtkTvPlugClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
parent_class = gtk_type_class (gtk_widget_get_type ());
object_class->destroy = gtk_tvplug_destroy;
widget_class->realize = gtk_tvplug_realize;
widget_class->expose_event = gtk_tvplug_expose;
#ifdef MY_DEBUG_EVENTS
// for detecting of ALL Gtk events
widget_class->event = gtk_tvplug_events;
#endif
widget_class->size_request = gtk_tvplug_size_request;
widget_class->size_allocate = gtk_tvplug_size_allocate;
}
static void gtk_tvplug_init (GtkTvPlug *tvplug)
{
tvplug->port = NULL;
tvplug->hue_adj = NULL;
tvplug->brightness_adj = NULL;
tvplug->saturation_adj = NULL;
tvplug->contrast_adj = NULL;
tvplug->frequency_adj = NULL;
tvplug->encoding_list = NULL;
pthread_mutex_init (&tvplug->mutex, NULL);
}
// XV image -----------------------------------------------------------
static void gtk_tvplug_create_image_xv(void *plugg) {
GtkTvPlug *tvplug=(GtkTvPlug *)plugg;
tvplug->image=XvCreateImage(GDK_DISPLAY(), tvplug->port->base_id,
tvplug->format, tvplug->image_data,
tvplug->img_width, tvplug->img_height);
}
static void gtk_tvplug_put_image_xv(GtkWidget *widget, void *plugg){
GtkTvPlug *tvplug=(GtkTvPlug *)plugg;
int locker=0;
locker=pthread_mutex_trylock (&tvplug->mutex);
if(locker != EBUSY && locker != EINVAL) {
gdk_threads_enter();
XvPutImage(GDK_DISPLAY(),tvplug->port->base_id,GDK_WINDOW_XWINDOW(widget->window),
GDK_GC_XGC(tvplug->gc),tvplug->image,tvplug->x,tvplug->y,
tvplug->img_width,tvplug->img_height,
tvplug->x,tvplug->y,tvplug->w,tvplug->h);
XSync(GDK_DISPLAY(),False);
gdk_threads_leave();
pthread_mutex_unlock(&tvplug->mutex);
}
}
static void gtk_tvplug_destroy_image_xv (GtkWidget *w,void *plug) {
GtkTvPlug *tvplug=(GtkTvPlug*)plug;
XFree(tvplug->image);
if(tvplug->image_data != NULL)
my_safe_free(tvplug->image_data);
}
// XV overlay -----------------------------------------------------------
// OOPS NOT TESTED
static void gtk_tvplug_create_image_xvvo(void *plugg) {
// NOTHING TO DO HERE
}
static void gtk_tvplug_put_image_xvvo(GtkWidget *widget, void *plugg){
GtkTvPlug *tvplug=(GtkTvPlug *)plugg;
int locker=0;
locker=pthread_mutex_trylock (&tvplug->mutex);
if(locker != EBUSY && locker != EINVAL) {
gdk_threads_enter();
XvPutVideo(GDK_DISPLAY(),tvplug->port->base_id,GDK_WINDOW_XWINDOW(widget->window),
GDK_GC_XGC(tvplug->gc),tvplug->x,tvplug->y,
tvplug->img_width,tvplug->img_height,
tvplug->x,tvplug->y,tvplug->w,tvplug->h);
XSync(GDK_DISPLAY(),False);
gdk_threads_leave();
pthread_mutex_unlock(&tvplug->mutex);
}
}
static void gtk_tvplug_destroy_image_xvvo (GtkWidget *w,void *plug) {
GtkTvPlug *tvplug=(GtkTvPlug*)plug;
XvStopVideo(GDK_DISPLAY(), tvplug->port->base_id, GDK_WINDOW_XWINDOW(w->window));
}
// XVSHM image -----------------------------------------------------------
static void gtk_tvplug_create_image_xvsh(void *plugg) {
GtkTvPlug *tvplug=(GtkTvPlug *)plugg;
tvplug->image=XvShmCreateImage(GDK_DISPLAY(), tvplug->port->base_id,
tvplug->format, 0,
tvplug->img_width, tvplug->img_height,
(XShmSegmentInfo *) &tvplug->shminfo);
tvplug->shminfo.shmid = shmget (IPC_PRIVATE, tvplug->image->data_size, IPC_CREAT | 0776);
if(tvplug->shminfo.shmid < 0 )
{
log_printf("Cannot allocate shm image data (%s)",strerror(errno));
return;
}
tvplug->shminfo.shmaddr = (char*)shmat (tvplug->shminfo.shmid, 0, 0);
tvplug->shminfo.readOnly = False;
if(!XShmAttach (GDK_DISPLAY(), &tvplug->shminfo)) {
log_printf("XShmAttach failed!\n");
return;
}
// make it available for data exchange
tvplug->image->data=tvplug->shminfo.shmaddr;
tvplug->image_data=tvplug->shminfo.shmaddr;
}
static void gtk_tvplug_put_image_xvsh(GtkWidget *widget, void *plugg){
GtkTvPlug *tvplug=(GtkTvPlug *)plugg;
int locker=0;
locker=pthread_mutex_trylock (&tvplug->mutex);
if(locker != EBUSY && locker != EINVAL) {
gdk_threads_enter();
XvShmPutImage(GDK_DISPLAY(),tvplug->port->base_id,GDK_WINDOW_XWINDOW(widget->window),
GDK_GC_XGC(tvplug->gc),tvplug->image,tvplug->x,tvplug->y,
tvplug->img_width,tvplug->img_height,
tvplug->x,tvplug->y,tvplug->w,tvplug->h,False);
XSync(GDK_DISPLAY(),False);
gdk_threads_leave();
pthread_mutex_unlock(&tvplug->mutex);
}
}
static void gtk_tvplug_destroy_image_xvsh (GtkWidget *w,void *plug) {
GtkTvPlug *tvplug=(GtkTvPlug*)plug;
XShmDetach(GDK_DISPLAY(), &tvplug->shminfo);
shmdt(tvplug->shminfo.shmaddr);
shmctl (tvplug->shminfo.shmid, IPC_RMID, 0);
XFree(tvplug->image);
}
// shadow callbacks
static void gtk_tvplug_init_image (GtkTvPlug *tvplug)
{
tvplug->init_image(tvplug);
}
void gtk_tvplug_put_image(GtkWidget *widget) {
GtkTvPlug *tvplug;
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_WIDGET_REALIZED(widget));
g_return_if_fail(GTK_IS_TVPLUG (widget));
tvplug = GTK_TVPLUG(widget);
if(tvplug->started) tvplug->put_image(widget,tvplug);
}
void gtk_tvplug_destroy_image (GtkWidget *widget, gpointer data) {
GtkTvPlug *tvplug=(GtkTvPlug*)data;
tvplug->destroy_image(widget, tvplug);
}
// return of the function need to be free'ed with free (not g_free)
// with internal structure variables 'formats' and 'name' for each port
GtkTvPlugPort *gtk_tvplug_get_ports(int *nports) {
GtkTvPlugPort *ports=NULL;
XvAdaptorInfo *ai;
XvImageFormatValues *formats;
int ver, rel, req, ev, err;
int adaptors=0;
int i, j, num;
char xv_name[5];
*nports=adaptors;
switch(XvQueryExtension(GDK_DISPLAY(),&ver,&rel,&req,&ev,&err))
{
case Success:
log_printf("XV: Ver: %d Rel: %d Req: %d Ev: %d Err: %d\n",
ver, rel, req, ev, err); break;
case XvBadExtension:
log_printf("Server doesn't support Xvideo"); return NULL;
case XvBadAlloc:
log_printf("Server makes XvBadAlloc\n"); return NULL;
default:
log_printf("XvQueryExtension failed\n"); return NULL;
}
switch(XvQueryAdaptors(GDK_DISPLAY(),DefaultRootWindow(GDK_DISPLAY()),&adaptors,&ai))
{
case Success: break;
case XvBadExtension: log_printf("Server doesn't support Xvideo");
return NULL;
case XvBadAlloc: log_printf("Server makes XvBadAlloc for XvQueryAdaptors\n");
return NULL;
default: log_printf("XvQueryAdaptors failed\n");
return NULL;
}
g_print("Guessing ports.....\n");
if(adaptors > 0)
ports=(GtkTvPlugPort*)my_safe_alloc(adaptors*sizeof(GtkTvPlugPort));
xv_name[4]=0x0; // EOL
for(i = 0; i < adaptors; i++) {
num = 0;
ports[i].name=strdup(ai[i].name);
ports[i].base_id=ai[i].base_id;
log_printf("PORT NAME: %s (ID: %ld)\n",ai[i].name,ai[i].base_id);
log_printf("Type: ");
switch(ai[i].type & (XvInputMask | XvOutputMask)) {
case XvInputMask:
if(ai[i].type & XvVideoMask) {
ports[i].type=TvPlugPutVideo;
log_printf("PutVideo ");
}
if(ai[i].type & XvStillMask) {
ports[i].type=TvPlugPutStill;
log_printf("PutStill ");
}
if(ai[i].type & XvImageMask) {
ports[i].type=TvPlugPutImage;
log_printf("PutImage ");
}
break;
case XvOutputMask:
if(ai[i].type & XvVideoMask) {
ports[i].type=TvPlugGetVideo;
log_printf("GetVideo ");
}
if(ai[i].type & XvStillMask) {
ports[i].type=TvPlugGetStill;
log_printf("GetStill ");
}
break;
default: log_printf("none ");
ports[i].type=TvPlugNon;
break;
}
log_printf("\n");
formats = XvListImageFormats(GDK_DISPLAY(), ai[i].base_id, &num);
ports[i].formats=(GtkTvPlugPortFormat*)my_safe_alloc(num*sizeof(GtkTvPlugPortFormat));
ports[i].num_formats=num;
for(j = 0; j < num; j++) {
ports[i].formats[j].id=formats[j].id;
ports[i].formats[j].type=(formats[j].type == XvRGB) ?
TvPlugRGB : TvPlugYUV;
ports[i].formats[j].format=(formats[j].format == XvPacked) ?
TvPlugPacked : TvPlugPlanar;
log_printf(" 0x%x \n", formats[j].id);
memcpy(xv_name, &formats[j].id, 4);
log_printf("(%s) %s\n", xv_name,
(formats[j].format == XvPacked) ?
"packed" : "planar");
} //j
}
XvFreeAdaptorInfo(ai);
*nports=adaptors;
return ports;
}
void gtk_tvplug_query_attributes(GtkWidget *widget)
{
GtkTvPlug *tvplug;
Atom attr;
XvAttribute *at;
XvEncodingInfo *ei;
int j, attributes, encodings, min, max, cur;
GtkAdjustment *adj;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_TVPLUG (widget));
tvplug = GTK_TVPLUG (widget);
if (Success != XvQueryEncodings(GDK_DISPLAY(), tvplug->port->base_id, &encodings, &ei))
log_printf("Oops: XvQueryEncodings failed");
else
for(j=0; j < encodings; j++) {
tvplug->encoding_list = g_list_append(tvplug->encoding_list, g_strdup(ei[j].name));
log_printf("Encoding %s HW: %ld x %ld\n",ei[j].name,ei[j].height,ei[j].width);
if(j == 0){
tvplug->height_min = tvplug->height_max = ei[j].height;
tvplug->width_min = tvplug->width_max = ei[j].width;
} else {
if ((int)ei[j].height < tvplug->height_min)
tvplug->height_min = ei[j].height;
if ((int)ei[j].height > tvplug->height_max)
tvplug->height_max = ei[j].height;
if ((int)ei[j].width < tvplug->width_min)
tvplug->width_min = ei[j].width;
if ((int)ei[j].width > tvplug->width_max)
tvplug->width_max = ei[j].width;
}
}
XvFreeEncodingInfo(ei);
// do not know, what to do with these....
// if ( Success != XvQueryBestSize(GDK_DISPLAY(), tvplug->port->base_id, 1,
// tvplug->width_max*2, tvplug->height_max*2, tvplug->width_max*2, tvplug->height_max*2,
// &(tvplug->width_best), &(tvplug->height_best)) )
// log_printf("XvQueryBestSize() failed\n");
at = XvQueryPortAttributes(GDK_DISPLAY(),tvplug->port->base_id,&attributes);
for (j = 0; j < attributes; j++)
{
log_printf("Attributes: %s\n",at[j].name);
if(strcmp(at[j].name, "XV_BRIGHTNESS") &&
strcmp(at[j].name, "XV_CONTRAST") &&
strcmp(at[j].name, "XV_SATURATION") &&
strcmp(at[j].name, "XV_HUE") &&
strcmp(at[j].name, "XV_FREQ"))
continue;
attr = XInternAtom(GDK_DISPLAY(), at[j].name, False);
XvGetPortAttribute(GDK_DISPLAY(), tvplug->port->base_id, attr, &cur);
min = at[j].min_value;
max = at[j].max_value;
adj = GTK_ADJUSTMENT(gtk_adjustment_new(cur, min, max,
1, (max-min)/10, 0));
if(strcmp(at[j].name, "XV_BRIGHTNESS") == 0) {
tvplug->brightness_adj = adj;
g_object_ref(tvplug->brightness_adj);
}
else if(strcmp(at[j].name, "XV_CONTRAST") == 0) {
tvplug->contrast_adj = adj;
g_object_ref(tvplug->contrast_adj);
}
else if(strcmp(at[j].name, "XV_SATURATION") == 0) {
tvplug->saturation_adj = adj;
g_object_ref(tvplug->saturation_adj);
}
else if(strcmp(at[j].name, "XV_HUE") == 0) {
tvplug->hue_adj = adj;
g_object_ref(tvplug->hue_adj);
}
else if(strcmp(at[j].name, "XV_FREQ") == 0) {
tvplug->frequency_adj = adj;
g_object_ref(tvplug->frequency_adj);
}
}
if(at) XFree(at);
}
void gtk_tvplug_set(GtkWidget *widget, int what, int value)
{
GtkTvPlug *tvplug;
Atom atom=0;
int set=FALSE;
XvEncodingInfo *ei;
gint encodings;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_TVPLUG (widget));
tvplug = GTK_TVPLUG (widget);
switch(what){
case TVPLUG_ADJ_HUE:
atom = XInternAtom(GDK_DISPLAY(), "XV_HUE", False);
gtk_adjustment_set_value(tvplug->hue_adj, value);
set=TRUE;
break;
case TVPLUG_ADJ_CONTRAST:
atom = XInternAtom(GDK_DISPLAY(), "XV_CONTRAST", False);
gtk_adjustment_set_value(tvplug->contrast_adj, value);
set=TRUE;
break;
case TVPLUG_ADJ_BRIGHTNESS:
atom = XInternAtom(GDK_DISPLAY(), "XV_BRIGHTNESS", False);
gtk_adjustment_set_value(tvplug->brightness_adj, value);
set=TRUE;
break;
case TVPLUG_ADJ_SATURATION:
atom = XInternAtom(GDK_DISPLAY(), "XV_SATURATION", False);
gtk_adjustment_set_value(tvplug->saturation_adj, value);
set=TRUE;
break;
case TVPLUG_ADJ_FREQUENCY:
atom = XInternAtom(GDK_DISPLAY(), "XV_FREQ", False);
gtk_adjustment_set_value(tvplug->frequency_adj, value);
set=TRUE;
break;
case TVPLUG_ADJ_MUTE:
atom = XInternAtom(GDK_DISPLAY(), "XV_MUTE", False);
set=TRUE;
break;
case TVPLUG_ADJ_ENCODING:
atom = XInternAtom(GDK_DISPLAY(), "XV_ENCODING", False);
if (Success != XvQueryEncodings(GDK_DISPLAY(), tvplug->port->base_id, &encodings, &ei))
log_printf("XvQueryEncodings failed");
else
{
set=TRUE;
// Do not know, for what this can be used?...
// tvplug->width_best = ei[value].width;
// tvplug->height_best = ei[value].height;
}
break;
case TVPLUG_ADJ_PORT:
tvplug->port->base_id = value;
gtk_tvplug_redraw(widget);
break;
default:
log_printf("Value \"%s\" unknown!\n", what);
break;
}
if(set) XvSetPortAttribute(GDK_DISPLAY(), tvplug->port->base_id,atom,value);
}
// main widget function
GtkWidget* gtk_tvplug_new (GtkTvPlugPort *port, GtkTvPlugIni *data)
{
GtkTvPlug *tvplug;
tvplug = gtk_type_new (gtk_tvplug_get_type ());
tvplug->gc=NULL;
gtk_tvplug_set_properties(tvplug, port, data->width, data->height, data->format);
gtk_tvplug_query_attributes(GTK_WIDGET(tvplug));
tvplug->mode=data->mode;
// install callbacks and data here
switch(data->mode) {
case GTK_TVPLUG_OUT_XVIM: tvplug->put_image=gtk_tvplug_put_image_xv;
tvplug->init_image=gtk_tvplug_create_image_xv;
tvplug->SelectVideoNotify=SelectVideoNotify_xv;
tvplug->SelectPortNotify=SelectPortNotify_xv;
tvplug->destroy_image=gtk_tvplug_destroy_image_xv;
tvplug->image_data=data->data;
break;
case GTK_TVPLUG_OUT_XVIMSH: tvplug->put_image=gtk_tvplug_put_image_xvsh;
tvplug->init_image=gtk_tvplug_create_image_xvsh;
tvplug->SelectVideoNotify=SelectVideoNotify_xv;
tvplug->SelectPortNotify=SelectPortNotify_xv;
tvplug->destroy_image=gtk_tvplug_destroy_image_xvsh;
break;
case GTK_TVPLUG_OUT_XVVO: tvplug->put_image=gtk_tvplug_put_image_xvvo;
tvplug->init_image=gtk_tvplug_create_image_xvvo;
tvplug->SelectVideoNotify=SelectVideoNotify_xv;
tvplug->SelectPortNotify=SelectPortNotify_xv;
tvplug->destroy_image=gtk_tvplug_destroy_image_xvvo;
break;
}
gtk_tvplug_init_image(tvplug);
return GTK_WIDGET (tvplug);
}
static void gtk_tvplug_destroy (GtkObject *object)
{
GtkTvPlug *tvplug;
g_return_if_fail (object != NULL);
g_return_if_fail (GTK_IS_TVPLUG (object));
tvplug = GTK_TVPLUG (object);
if(tvplug->hue_adj) {
g_object_unref(GTK_OBJECT(tvplug->hue_adj));
tvplug->hue_adj=NULL;
}
if(tvplug->brightness_adj) {
g_object_unref(GTK_OBJECT(tvplug->brightness_adj));
tvplug->brightness_adj=NULL;
}
if(tvplug->contrast_adj) {
g_object_unref(GTK_OBJECT(tvplug->contrast_adj));
tvplug->contrast_adj=NULL;
}
if(tvplug->saturation_adj) {
g_object_unref(GTK_OBJECT(tvplug->saturation_adj));
tvplug->saturation_adj=NULL;
}
if(tvplug->frequency_adj) {
g_object_unref(GTK_OBJECT(tvplug->frequency_adj));
tvplug->frequency_adj=NULL;
}
if(tvplug->gc != NULL) {
//??? gdk_gc_destroy(tvplug->gc);
g_object_unref(tvplug->gc);
tvplug->gc=NULL;
}
if(GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}
static void gtk_tvplug_set_properties (GtkTvPlug *tvplug, GtkTvPlugPort *port, int width, int height, int type)
{
g_return_if_fail(tvplug != NULL);
g_return_if_fail(GTK_IS_TVPLUG (tvplug));
tvplug->port = port;
tvplug->img_width = width;
tvplug->img_height = height;
tvplug->format = type;
}
static void gtk_tvplug_realize (GtkWidget *widget)
{
GtkTvPlug *tvplug;
GdkWindowAttr attributes;
gint attributes_mask;
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_IS_TVPLUG (widget));
GTK_WIDGET_SET_FLAGS(widget, GTK_REALIZED);
tvplug = GTK_TVPLUG(widget);
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
attributes.height = widget->allocation.height;
attributes.wclass = GDK_INPUT_OUTPUT;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.event_mask = gtk_widget_get_events (widget) |
GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
GDK_VISIBILITY_NOTIFY_MASK |
GDK_POINTER_MOTION_HINT_MASK;
attributes.visual = gtk_widget_get_visual (widget);
attributes.colormap = gtk_widget_get_colormap (widget);
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
widget->window = gdk_window_new (widget->parent->window, &attributes,
attributes_mask);
widget->style = gtk_style_attach (widget->style, widget->window);
gdk_window_set_user_data (widget->window, widget);
gtk_style_set_background (widget->style, widget->window,
GTK_STATE_ACTIVE);
gtk_widget_set_app_paintable(widget,TRUE);
#ifdef MY_DEBUG_EVENTS
// for local mutex unlock, when parsing all events (debug)
g_signal_connect (G_OBJECT (widget), "event-after",
G_CALLBACK (gtk_tvplug_event_after), NULL);
#endif //MY_DEBUG_EVENTS
g_signal_connect_after (G_OBJECT (widget), "delete_event",
G_CALLBACK (gtk_tvplug_destroy_image), tvplug);
g_signal_connect_after (G_OBJECT (widget), "destroy",
G_CALLBACK (gtk_tvplug_destroy_image), tvplug);
tvplug->gc = gdk_gc_new(widget->window);
gdk_gc_set_exposures(tvplug->gc,TRUE);
gtk_widget_set_double_buffered(widget,FALSE);
tvplug->started=FALSE;
}
static void gtk_tvplug_size_request (GtkWidget *widget, GtkRequisition *requisition)
{
GtkTvPlug *tvplug;
tvplug = GTK_TVPLUG(widget);
requisition->width = tvplug->img_width;
requisition->height = tvplug->img_height;
}
static void gtk_tvplug_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
GtkTvPlug *tvplug;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_TVPLUG (widget));
g_return_if_fail (allocation != NULL);
widget->allocation = *allocation;
tvplug = GTK_TVPLUG(widget);
if(GTK_WIDGET_REALIZED (widget))
{
gdk_window_move_resize (widget->window,
allocation->x, allocation->y,
allocation->width, allocation->height);
gtk_tvplug_redraw(widget);
}
}
static void SelectVideoNotify_xv(GtkWidget *widget, void *plugg){
XvSelectVideoNotify(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(widget->window),1);
}
static void SelectPortNotify_xv(GtkWidget *widget, void *plugg){
GtkTvPlug *tvplug=(GtkTvPlug*)plugg;
XvSelectPortNotify(GDK_DISPLAY(), tvplug->port->base_id, 1);
}
void gtk_tvplug_redraw(GtkWidget *widget)
{
GtkTvPlug *tvplug;
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_IS_TVPLUG (widget));
tvplug = GTK_TVPLUG(widget);
if(tvplug->mode == GTK_TVPLUG_OUT_XVVO)
XvStopVideo(GDK_DISPLAY(), tvplug->port->base_id,
GDK_WINDOW_XWINDOW(widget->window));
tvplug->SelectPortNotify(widget,tvplug);
// the commented code below behaves in a bad manner when the window is shaded by
// another one; do not uncomment it
/* gdk_window_clear_area (widget->window,
0, 0,
widget->allocation.width,
widget->allocation.height);
gdk_draw_rectangle(widget->window,
widget->style->white_gc,
1, 0, 0,
widget->allocation.width,
widget->allocation.height);
*/
tvplug->w = widget->allocation.width;
tvplug->h = widget->allocation.height;
tvplug->x = 0;
tvplug->y = 0;
tvplug->SelectVideoNotify(widget,tvplug);
// reallocate GC for different reasons
if(tvplug->gc != NULL) gdk_gc_destroy(tvplug->gc);
tvplug->gc = gdk_gc_new(GTK_WIDGET(tvplug)->window);
gdk_gc_set_exposures(tvplug->gc,TRUE);
if(tvplug->started) gtk_tvplug_put_image(widget);
else tvplug->started=TRUE; // wait for the next time call
}
static gint gtk_tvplug_expose (GtkWidget *widget, GdkEventExpose *event)
{
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TVPLUG (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if(event->count > 0) // stable 0 all times
return FALSE;
gtk_tvplug_redraw(widget);
return FALSE;
}
#ifdef MY_DEBUG_EVENTS
// callback for catching all events
static gint gtk_tvplug_events (GtkWidget *widget, GdkEvent *event)
{
GtkTvPlug *tvplug;
g_return_val_if_fail (event != NULL, FALSE);
g_return_val_if_fail(widget != NULL, FALSE);
g_return_val_if_fail(GTK_IS_TVPLUG (widget),FALSE);
tvplug = GTK_TVPLUG(widget);
pthread_mutex_lock (&tvplug->mutex);
log_printf("EVENT: %d ",event->type);
switch(event->type) {
case GDK_NOTHING : log_printf("GDK_NOTHING\n"); break;
case GDK_DELETE : log_printf("GDK_DELETE\n"); break;
case GDK_DESTROY : log_printf("GDK_DESTROY \n"); break;
case GDK_EXPOSE : log_printf("GDK_EXPOSE \n"); break;
case GDK_MOTION_NOTIFY : log_printf("GDK_MOTION_NOTIFY \n"); break;
case GDK_BUTTON_PRESS : log_printf("GDK_BUTTON_PRESS \n"); break;
case GDK_2BUTTON_PRESS : log_printf("GDK_2BUTTON_PRESS \n"); break;
case GDK_3BUTTON_PRESS : log_printf("GDK_3BUTTON_PRESS \n"); break;
case GDK_BUTTON_RELEASE : log_printf("GDK_BUTTON_RELEASE \n"); break;
case GDK_KEY_PRESS : log_printf("GDK_KEY_PRESS \n"); break;
case GDK_KEY_RELEASE : log_printf("GDK_KEY_RELEASE \n"); break;
case GDK_ENTER_NOTIFY : log_printf("GDK_ENTER_NOTIFY \n"); break;
case GDK_LEAVE_NOTIFY : log_printf("GDK_LEAVE_NOTIFY \n"); break;
case GDK_FOCUS_CHANGE : log_printf("GDK_FOCUS_CHANGE \n"); break;
case GDK_CONFIGURE : log_printf("GDK_CONFIGURE \n"); break;
case GDK_MAP : log_printf("GDK_MAP \n"); break;
case GDK_UNMAP : log_printf("GDK_UNMAP \n"); break;
case GDK_PROPERTY_NOTIFY: log_printf("GDK_PROPERTY_NOTIFY\n"); break;
case GDK_SELECTION_CLEAR: log_printf("GDK_SELECTION_CLEAR\n"); break;
case GDK_SELECTION_REQUEST: log_printf("GDK_SELECTION_REQUEST\n"); break;
case GDK_SELECTION_NOTIFY: log_printf("GDK_SELECTION_NOTIFY\n"); break;
case GDK_PROXIMITY_IN : log_printf("GDK_PROXIMITY_IN \n"); break;
case GDK_PROXIMITY_OUT : log_printf("GDK_PROXIMITY_OUT \n"); break;
case GDK_DRAG_ENTER : log_printf("GDK_DRAG_ENTER \n"); break;
case GDK_DRAG_LEAVE : log_printf("GDK_DRAG_LEAVE \n"); break;
case GDK_DRAG_MOTION : log_printf("GDK_DRAG_MOTION \n"); break;
case GDK_DRAG_STATUS : log_printf("GDK_DRAG_STATUS \n"); break;
case GDK_DROP_START : log_printf("GDK_DROP_START \n"); break;
case GDK_DROP_FINISHED : log_printf("GDK_DROP_FINISHED \n"); break;
case GDK_CLIENT_EVENT : log_printf("GDK_CLIENT_EVENT \n"); break;
case GDK_VISIBILITY_NOTIFY: log_printf("GDK_VISIBILITY_NOTIFY\n"); break;
case GDK_NO_EXPOSE : log_printf("GDK_NO_EXPOSE\n"); break;
case GDK_SCROLL : log_printf("GDK_SCROLL\n"); break;
case GDK_WINDOW_STATE : log_printf("GDK_WINDOW_STATE\n"); break;
case GDK_SETTING : log_printf("GDK_SETTING\n"); break;
default: log_printf("GDK UNKNOWN EVENT\n"); break;
}
return FALSE;
}
// the function below is called after the event
static void gtk_tvplug_event_after (GtkWidget *widget, GdkEvent *event, void *data)
{
GtkTvPlug *tvplug;
g_return_if_fail (event != NULL);
g_return_if_fail(widget != NULL);
g_return_if_fail(GTK_IS_TVPLUG (widget));
tvplug = GTK_TVPLUG(widget);
// unlock local mutex after successfull redraw
pthread_mutex_unlock (&tvplug->mutex);
}
#endif // MY_DEBUG_EVENTS
Админы, хватит насиловать людей! Уже сделайте нормальное прикрепление файлов! Пол часа парился, воткнул так.