summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippo Argiolas <filippo.argiolas@gmail.com>2009-04-04 11:05:44 +0200
committerFilippo Argiolas <filippo.argiolas@gmail.com>2009-04-04 11:05:44 +0200
commit106b6400907a6f48bfae35030e888eabff22e399 (patch)
tree82f6bc046bf021d41b4c115603dcfe312def7cae
parentee6adea4bf28545b6dd49607aec2da7974944c03 (diff)
First skeleton of ClutterGLXTexturePixmap subclass
Subclass ClutterGLXTexturePixmap. At the moment it does nothing more than the parent class, well I'm no even sure I need a subclass.. we'll see.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/cheese-stage.c283
-rw-r--r--src/cheese-texture.c265
-rw-r--r--src/cheese-texture.h61
4 files changed, 371 insertions, 240 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index b57c100..50cb73b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,8 @@
bin_PROGRAMS = cheese-stage
cheese_stage_SOURCES = \
+ cheese-stage.c \
+ cheese-texture.h \
cheese-texture.c
cheese_stage_LDADD = \
diff --git a/src/cheese-stage.c b/src/cheese-stage.c
new file mode 100644
index 0000000..cf2a5d2
--- /dev/null
+++ b/src/cheese-stage.c
@@ -0,0 +1,283 @@
+/*
+ * GStreamer
+ * Copyright (C) 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+#include <X11/Xlib.h>
+
+#include "cheese-texture.h"
+
+#include <X11/extensions/Xcomposite.h>
+#include <clutter/clutter.h>
+#include <clutter/x11/clutter-x11.h>
+#include <clutter/glx/clutter-glx.h>
+#include <gst/gst.h>
+#include <gst/interfaces/xoverlay.h>
+
+#define ROWS 3
+#define COLS 3
+#define N_ACTORS ROWS*COLS
+#define W 160
+#define H 120
+
+struct GstGLClutterActor_
+{
+ Window win;
+ Window root;
+ ClutterActor *texture;
+ ClutterActor *stage;
+};
+
+typedef struct GstGLClutterActor_ GstGLClutterActor;
+
+static ClutterX11FilterReturn event_filter (XEvent * ev, ClutterEvent * cev,
+ gpointer unused);
+
+static ClutterX11FilterReturn
+event_filter (XEvent * ev, ClutterEvent * cev, gpointer data)
+{
+ Window *windows = (Window *) data;
+ gint i;
+ switch (ev->type) {
+ case MapRequest:
+ g_message ("map request");
+ return CLUTTER_X11_FILTER_CONTINUE;
+ case MapNotify:
+ if (ev->xmap.window == windows[N_ACTORS]) {
+ g_message ("stage map");
+// XMapSubwindows (ev->xmap.display, ev->xmap.window);
+ for (i = 0; i < N_ACTORS; i++) {
+ XMapWindow (ev->xmap.display, windows[i]);
+ }
+ XSync (ev->xmap.display, FALSE);
+ } else
+ g_message ("map");
+ XMapSubwindows (ev->xmap.display, ev->xmap.window);
+ return CLUTTER_X11_FILTER_CONTINUE;
+ case UnmapNotify:
+ if (ev->xmap.window == windows[N_ACTORS]) {
+ g_message ("stage unmap");
+// XUnmapSubwindows (ev->xmap.display, ev->xmap.window);
+ for (i = 0; i < N_ACTORS; i++) {
+ XUnmapWindow (ev->xmap.display, windows[i]);
+ }
+ XSync (ev->xmap.display, FALSE);
+ } else
+ g_message ("unmap");
+ return CLUTTER_X11_FILTER_CONTINUE;
+ default:
+ return CLUTTER_X11_FILTER_CONTINUE;
+ }
+}
+
+static gboolean
+create_actor (GstGLClutterActor * actor)
+{
+ static gint xpos = 0;
+ static gint ypos = 0;
+ Display *disp;
+ actor->texture = g_object_new (CHEESE_TYPE_TEXTURE,
+ "window", actor->win, "automatic-updates", TRUE, NULL);
+ clutter_container_add_actor (CLUTTER_CONTAINER (actor->stage),
+ actor->texture);
+ clutter_actor_set_position (actor->texture, xpos, ypos);
+
+ disp = clutter_x11_get_default_display ();
+
+ if (xpos > (COLS - 1) * W) {
+ xpos = 0;
+ ypos += H + 1;
+ } else
+ xpos += W + 1;
+ clutter_actor_show (actor->texture);
+
+ return FALSE;
+}
+
+static GstBusSyncReply
+create_window (GstBus * bus, GstMessage * message, gpointer data)
+{
+ GstGLClutterActor **actor = (GstGLClutterActor **) data;
+ static gint count = 0;
+ static GMutex *mutex = NULL;
+ // ignore anything but 'prepare-xwindow-id' element messages
+ if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
+ return GST_BUS_PASS;
+
+ if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
+ return GST_BUS_PASS;
+
+ if (!mutex)
+ mutex = g_mutex_new ();
+
+ g_mutex_lock (mutex);
+
+ if (count < N_ACTORS) {
+ g_message ("adding actor %d", count);
+ gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
+ actor[count]->win);
+ clutter_threads_add_idle ((GSourceFunc) create_actor, actor[count]);
+ count++;
+ }
+
+ g_mutex_unlock (mutex);
+
+ gst_message_unref (message);
+ return GST_BUS_DROP;
+}
+
+#if 0
+void
+apply_fx (GstElement * element, const gchar * fx)
+{
+ GEnumClass *p_class;
+
+ /* from fxtest ;) */
+ /* heeeellppppp!! */
+ p_class =
+ G_PARAM_SPEC_ENUM (g_object_class_find_property (G_OBJECT_GET_CLASS
+ (G_OBJECT (data)), "effect")
+ )->enum_class;
+
+ g_print ("setting: %s - %s\n", fx, g_enum_get_value_by_nick (p_class,
+ fx)->value_name);
+ g_object_set (G_OBJECT (element), "effect", g_enum_get_value_by_nick (p_class,
+ fx)->value, NULL);
+}
+#endif
+
+int
+main (int argc, char *argv[])
+{
+ GstPipeline *pipeline;
+ GstBus *bus;
+
+ GstElement *srcbin;
+ GstElement *tee;
+ GstElement *queue[N_ACTORS], *sink[N_ACTORS];
+/*
+ GstElement *upload[N_ACTORS];
+ GstElement *effect[N_ACTORS];
+*/
+ ClutterActor *stage;
+ GstGLClutterActor *actor[N_ACTORS];
+ Window windows[N_ACTORS + 1];
+ Display *disp;
+ Window stage_win;
+ const gchar *desc;
+ gint i;
+ gint ok = FALSE;
+
+ XSetWindowAttributes attributes;
+ unsigned long mask;
+
+ clutter_init (&argc, &argv);
+ gst_init (&argc, &argv);
+
+ disp = clutter_x11_get_default_display ();
+ if (!clutter_x11_has_composite_extension ()) {
+ g_error ("XComposite extension missing");
+ }
+
+ stage = clutter_stage_get_default ();
+ clutter_actor_set_size (CLUTTER_ACTOR (stage),
+ W * COLS + (COLS - 1), H * ROWS + (ROWS - 1));
+
+ stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
+
+ attributes.background_pixel = BlackPixel (disp, DefaultScreen (disp));
+ attributes.event_mask = StructureNotifyMask | VisibilityChangeMask;
+ mask = CWBackPixel | CWEventMask;
+
+ for (i = 0; i < N_ACTORS; i++) {
+ actor[i] = g_new0 (GstGLClutterActor, 1);
+ actor[i]->stage = stage;
+ actor[i]->win = XCreateWindow (disp, stage_win,
+ 0, 0, W, H, 0, CopyFromParent, InputOutput, CopyFromParent,
+ mask, &attributes);
+ windows[i] = actor[i]->win;
+ XCompositeRedirectWindow (disp, actor[i]->win, CompositeRedirectManual);
+ XMapRaised (disp, actor[i]->win);
+ XSync (disp, FALSE);
+ }
+ windows[N_ACTORS] = stage_win;
+ clutter_x11_add_filter (event_filter, windows);
+
+/*
+ desc = g_strdup_printf ("v4l2src ! "
+ "video/x-raw-yuv, width=640, height=480, framerate=30/1 ! "
+ "videoscale !"
+ "video/x-raw-yuv, width=%d, height=%d ! "
+ "identity", W, H);
+*/
+ desc = g_strdup_printf ("videotestsrc ! "
+ "video/x-raw-rgb, width=%d, height=%d !" "identity", W, H);
+ pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
+
+ srcbin = gst_parse_bin_from_description (desc, TRUE, NULL);
+ if (!srcbin)
+ g_error ("Source bin creation failed");
+
+ tee = gst_element_factory_make ("tee", NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), srcbin, tee, NULL);
+
+ for (i = 0; i < N_ACTORS; i++) {
+ queue[i] = gst_element_factory_make ("queue", NULL);
+/* upload[i] = gst_element_factory_make ("glupload", NULL);
+ effect[i] = gst_element_factory_make ("gleffects", NULL); */
+ sink[i] = gst_element_factory_make ("glimagesink", NULL);
+/* gst_bin_add_many (GST_BIN (pipeline),
+ queue[i], upload[i], effect[i], sink[i], NULL); */
+ gst_bin_add_many (GST_BIN (pipeline), queue[i], sink[i], NULL);
+ }
+
+ gst_element_link_many (srcbin, tee, NULL);
+
+ for (i = 0; i < N_ACTORS; i++) {
+ ok |=
+// gst_element_link_many (tee, queue[i], upload[i], effect[i], sink[i],
+ gst_element_link_many (tee, queue[i], sink[i], NULL);
+ }
+
+ if (!ok)
+ g_error ("Failed to link one or more elements");
+
+/*
+ for (i = 0; i < N_ACTORS; i++) {
+ g_message ("setting effect %d on %s", i + 1,
+ gst_element_get_name (effect[i]));
+ g_object_set (G_OBJECT (effect[i]), "effect", i + 1, NULL);
+ }
+*/
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
+
+ gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, actor);
+
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
+
+ clutter_actor_show_all (stage);
+
+ clutter_main ();
+
+ gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
+ g_object_unref (pipeline);
+
+ return 0;
+}
diff --git a/src/cheese-texture.c b/src/cheese-texture.c
index 5447379..9b1dc31 100644
--- a/src/cheese-texture.c
+++ b/src/cheese-texture.c
@@ -1,6 +1,6 @@
/*
* GStreamer
- * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
+ * Copyright (C) 2009 Filippo Argiolas <filippo.argiolas@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,264 +18,49 @@
* Boston, MA 02111-1307, USA.
*/
-#include <X11/Xlib.h>
+#include "cheese-texture.h"
+#include <X11/Xlib.h>
#include <X11/extensions/Xcomposite.h>
+
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#include <clutter/glx/clutter-glx.h>
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
-#define ROWS 3
-#define COLS 3
-#define N_ACTORS ROWS*COLS
-#define W 160
-#define H 120
-
-struct GstGLClutterActor_
-{
- Window win;
- Window root;
- ClutterActor *texture;
- ClutterActor *stage;
-};
-
-typedef struct GstGLClutterActor_ GstGLClutterActor;
-
-static ClutterX11FilterReturn event_filter (XEvent * ev, ClutterEvent * cev,
- gpointer unused);
+G_DEFINE_TYPE (CheeseTexture, cheese_texture, CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
-static ClutterX11FilterReturn
-event_filter (XEvent * ev, ClutterEvent * cev, gpointer data)
-{
- Window *windows = (Window *) data;
- gint i;
- switch (ev->type) {
- case MapRequest:
- g_message ("map request");
- return CLUTTER_X11_FILTER_CONTINUE;
- case MapNotify:
- if (ev->xmap.window == windows[N_ACTORS]) {
- g_message ("stage map");
-// XMapSubwindows (ev->xmap.display, ev->xmap.window);
- for (i = 0; i < N_ACTORS; i++) {
- XMapWindow (ev->xmap.display, windows[i]);
- }
- XSync (ev->xmap.display, FALSE);
- } else
- g_message ("map");
- XMapSubwindows (ev->xmap.display, ev->xmap.window);
- return CLUTTER_X11_FILTER_CONTINUE;
- case UnmapNotify:
- if (ev->xmap.window == windows[N_ACTORS]) {
- g_message ("stage unmap");
-// XUnmapSubwindows (ev->xmap.display, ev->xmap.window);
- for (i = 0; i < N_ACTORS; i++) {
- XUnmapWindow (ev->xmap.display, windows[i]);
- }
- XSync (ev->xmap.display, FALSE);
- } else
- g_message ("unmap");
- return CLUTTER_X11_FILTER_CONTINUE;
- default:
- return CLUTTER_X11_FILTER_CONTINUE;
- }
-}
+#define CHEESE_TEXTURE_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), CHEESE_TYPE_TEXTURE, CheeseTexturePrivate))
-static gboolean
-create_actor (GstGLClutterActor * actor)
+struct _CheeseTexturePrivate
{
- static gint xpos = 0;
- static gint ypos = 0;
- Display *disp;
- actor->texture = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
- "window", actor->win, "automatic-updates", TRUE, NULL);
- clutter_container_add_actor (CLUTTER_CONTAINER (actor->stage),
- actor->texture);
- clutter_actor_set_position (actor->texture, xpos, ypos);
-
- disp = clutter_x11_get_default_display ();
-
- if (xpos > (COLS - 1) * W) {
- xpos = 0;
- ypos += H + 1;
- } else
- xpos += W + 1;
- clutter_actor_show (actor->texture);
-
- return FALSE;
-}
+ /* stuff */
+ gpointer stuff;
+};
-static GstBusSyncReply
-create_window (GstBus * bus, GstMessage * message, gpointer data)
+static void
+cheese_texture_class_init (CheeseTextureClass *klass)
{
- GstGLClutterActor **actor = (GstGLClutterActor **) data;
- static gint count = 0;
- static GMutex *mutex = NULL;
- // ignore anything but 'prepare-xwindow-id' element messages
- if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
- return GST_BUS_PASS;
-
- if (!gst_structure_has_name (message->structure, "prepare-xwindow-id"))
- return GST_BUS_PASS;
-
- if (!mutex)
- mutex = g_mutex_new ();
-
- g_mutex_lock (mutex);
+/* GObjectClass *gobject_class = (GObjectClass *) klass; */
+/* ClutterActorClass *actor_class = (ClutterActorClass *) klass; */
- if (count < N_ACTORS) {
- g_message ("adding actor %d", count);
- gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (message)),
- actor[count]->win);
- clutter_threads_add_idle ((GSourceFunc) create_actor, actor[count]);
- count++;
- }
-
- g_mutex_unlock (mutex);
-
- gst_message_unref (message);
- return GST_BUS_DROP;
+ g_type_class_add_private (klass, sizeof (CheeseTexturePrivate));
}
-#if 0
-void
-apply_fx (GstElement * element, const gchar * fx)
+static void
+cheese_texture_init (CheeseTexture *self)
{
- GEnumClass *p_class;
-
- /* from fxtest ;) */
- /* heeeellppppp!! */
- p_class =
- G_PARAM_SPEC_ENUM (g_object_class_find_property (G_OBJECT_GET_CLASS
- (G_OBJECT (data)), "effect")
- )->enum_class;
+ CheeseTexturePrivate *priv;
- g_print ("setting: %s - %s\n", fx, g_enum_get_value_by_nick (p_class,
- fx)->value_name);
- g_object_set (G_OBJECT (element), "effect", g_enum_get_value_by_nick (p_class,
- fx)->value, NULL);
+ priv = self->priv = CHEESE_TEXTURE_GET_PRIVATE (self);
}
-#endif
-int
-main (int argc, char *argv[])
+ClutterActor *
+cheese_texture_new (void)
{
- GstPipeline *pipeline;
- GstBus *bus;
-
- GstElement *srcbin;
- GstElement *tee;
- GstElement *queue[N_ACTORS], *sink[N_ACTORS];
-/*
- GstElement *upload[N_ACTORS];
- GstElement *effect[N_ACTORS];
-*/
- ClutterActor *stage;
- GstGLClutterActor *actor[N_ACTORS];
- Window windows[N_ACTORS + 1];
- Display *disp;
- Window stage_win;
- const gchar *desc;
- gint i;
- gint ok = FALSE;
-
- XSetWindowAttributes attributes;
- unsigned long mask;
-
- clutter_init (&argc, &argv);
- gst_init (&argc, &argv);
-
- disp = clutter_x11_get_default_display ();
- if (!clutter_x11_has_composite_extension ()) {
- g_error ("XComposite extension missing");
- }
-
- stage = clutter_stage_get_default ();
- clutter_actor_set_size (CLUTTER_ACTOR (stage),
- W * COLS + (COLS - 1), H * ROWS + (ROWS - 1));
-
- stage_win = clutter_x11_get_stage_window (CLUTTER_STAGE (stage));
-
- attributes.background_pixel = BlackPixel (disp, DefaultScreen (disp));
- attributes.event_mask = StructureNotifyMask | VisibilityChangeMask;
- mask = CWBackPixel | CWEventMask;
-
- for (i = 0; i < N_ACTORS; i++) {
- actor[i] = g_new0 (GstGLClutterActor, 1);
- actor[i]->stage = stage;
- actor[i]->win = XCreateWindow (disp, stage_win,
- 0, 0, W, H, 0, CopyFromParent, InputOutput, CopyFromParent,
- mask, &attributes);
- windows[i] = actor[i]->win;
- XCompositeRedirectWindow (disp, actor[i]->win, CompositeRedirectManual);
- XMapRaised (disp, actor[i]->win);
- XSync (disp, FALSE);
- }
- windows[N_ACTORS] = stage_win;
- clutter_x11_add_filter (event_filter, windows);
-
-/*
- desc = g_strdup_printf ("v4l2src ! "
- "video/x-raw-yuv, width=640, height=480, framerate=30/1 ! "
- "videoscale !"
- "video/x-raw-yuv, width=%d, height=%d ! "
- "identity", W, H);
-*/
- desc = g_strdup_printf ("videotestsrc ! "
- "video/x-raw-rgb, width=%d, height=%d !" "identity", W, H);
- pipeline = GST_PIPELINE (gst_pipeline_new (NULL));
-
- srcbin = gst_parse_bin_from_description (desc, TRUE, NULL);
- if (!srcbin)
- g_error ("Source bin creation failed");
-
- tee = gst_element_factory_make ("tee", NULL);
-
- gst_bin_add_many (GST_BIN (pipeline), srcbin, tee, NULL);
-
- for (i = 0; i < N_ACTORS; i++) {
- queue[i] = gst_element_factory_make ("queue", NULL);
-/* upload[i] = gst_element_factory_make ("glupload", NULL);
- effect[i] = gst_element_factory_make ("gleffects", NULL); */
- sink[i] = gst_element_factory_make ("glimagesink", NULL);
-/* gst_bin_add_many (GST_BIN (pipeline),
- queue[i], upload[i], effect[i], sink[i], NULL); */
- gst_bin_add_many (GST_BIN (pipeline), queue[i], sink[i], NULL);
- }
-
- gst_element_link_many (srcbin, tee, NULL);
-
- for (i = 0; i < N_ACTORS; i++) {
- ok |=
-// gst_element_link_many (tee, queue[i], upload[i], effect[i], sink[i],
- gst_element_link_many (tee, queue[i], sink[i], NULL);
- }
-
- if (!ok)
- g_error ("Failed to link one or more elements");
-
-/*
- for (i = 0; i < N_ACTORS; i++) {
- g_message ("setting effect %d on %s", i + 1,
- gst_element_get_name (effect[i]));
- g_object_set (G_OBJECT (effect[i]), "effect", i + 1, NULL);
- }
-*/
-
- bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
-
- gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, actor);
-
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-
- clutter_actor_show_all (stage);
-
- clutter_main ();
-
- gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
- g_object_unref (pipeline);
-
- return 0;
+ ClutterActor *self = g_object_new (CHEESE_TYPE_TEXTURE, NULL);
+
+ return self;
}
diff --git a/src/cheese-texture.h b/src/cheese-texture.h
new file mode 100644
index 0000000..44f1db9
--- /dev/null
+++ b/src/cheese-texture.h
@@ -0,0 +1,61 @@
+/*
+ * Cheese Texture
+ *
+ * An actor to import textures from gstreamer video sinks using TFP
+ *
+ * Copyright (C) 2009 Filippo Argiolas
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef __CHEESE_TEXTURE_H__
+#define __CHEESE_TEXTURE_H__
+
+#include <clutter/clutter.h>
+/* TODO: fallback to X11 TFP if GLX is not supported */
+#include <clutter/glx/clutter-glx.h>
+
+G_BEGIN_DECLS
+
+#define CHEESE_TYPE_TEXTURE (cheese_texture_get_type())
+#define CHEESE_TEXTURE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CHEESE_TYPE_TEXTURE, CheeseTexture))
+#define CHEESE_TEXTURE_CLASS(k) (G_TYPE_CHECK_CLASS((k), CHEESE_TYPE_TEXTURE, CheeseTextureClass))
+#define CHEESE_IS_TEXTURE(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), CHEESE_TYPE_TEXTURE))
+#define CHEESE_IS_TEXTURE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), CHEESE_TYPE_TEXTURE))
+#define CHEESE_TEXTURE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), CHEESE_TYPE_TEXTURE, CheeseTextureClass))
+
+typedef struct _CheeseTexture CheeseTexture;
+typedef struct _CheeseTextureClass CheeseTextureClass;
+typedef struct _CheeseTexturePrivate CheeseTexturePrivate;
+
+struct _CheeseTexture {
+ /*< private >*/
+ ClutterGLXTexturePixmap parent;
+ CheeseTexturePrivate *priv;
+};
+
+struct _CheeseTextureClass {
+ /*< private >*/
+ ClutterGLXTexturePixmapClass parent_class;
+};
+
+GType cheese_texture_get_type (void);
+
+ClutterActor *cheese_texture_new (void);
+
+G_END_DECLS
+
+#endif /* __CHEESE_TEXTURE_H__ */