diff options
author | Filippo Argiolas <filippo.argiolas@gmail.com> | 2009-04-04 11:05:44 +0200 |
---|---|---|
committer | Filippo Argiolas <filippo.argiolas@gmail.com> | 2009-04-04 11:05:44 +0200 |
commit | 106b6400907a6f48bfae35030e888eabff22e399 (patch) | |
tree | 82f6bc046bf021d41b4c115603dcfe312def7cae | |
parent | ee6adea4bf28545b6dd49607aec2da7974944c03 (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.am | 2 | ||||
-rw-r--r-- | src/cheese-stage.c | 283 | ||||
-rw-r--r-- | src/cheese-texture.c | 265 | ||||
-rw-r--r-- | src/cheese-texture.h | 61 |
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__ */ |