[pinpoint] clutteR: add a "camera" background type
- From: Damien Lespiau <dlespiau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pinpoint] clutteR: add a "camera" background type
- Date: Sat, 23 Jul 2011 14:59:12 +0000 (UTC)
commit cb1a1594f6853273833c44a5a4dd58869d765329
Author: Damien Lespiau <damien lespiau intel com>
Date: Sat Jul 23 13:11:59 2011 +0100
clutteR: add a "camera" background type
It's awesome, it lets you put pull your webcam into your presentation.
pinpoint.c | 23 +++++++-
pinpoint.h | 9 +++
pp-cairo.c | 3 +
pp-clutter.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++--------
4 files changed, 190 insertions(+), 25 deletions(-)
---
diff --git a/pinpoint.c b/pinpoint.c
index 052a109..4d15d8d 100644
--- a/pinpoint.c
+++ b/pinpoint.c
@@ -74,6 +74,10 @@ static PinPointPoint pin_default_point = {
.transition = NULL,
.command = NULL,
+
+ .camera_framerate = 0, /* auto */
+ .camera_resolution = {0, 0}, /* auto */
+
.data = NULL,
};
@@ -392,6 +396,14 @@ void pp_parse_slides (PinPointRenderer *renderer,
*/
static void
+parse_resolution (PPResolution *r,
+ const gchar *str)
+{
+ if (sscanf (str, "%dx%d", &r->width, &r->height) != 2)
+ r->width = r->height = 0;
+}
+
+static void
parse_setting (PinPointPoint *point,
const char *setting)
{
@@ -405,7 +417,9 @@ parse_setting (PinPointPoint *point,
#define IF_PREFIX(prefix) } else if (g_str_has_prefix (setting, prefix)) {
#define IF_EQUAL(string) } else if (g_str_equal (setting, string)) {
#define STRING g_intern_string (strchr (setting, '=') + 1)
+#define INT atoi (strchr (setting, '=') + 1)
#define FLOAT g_ascii_strtod (strchr (setting, '=') + 1, NULL)
+#define RESOLUTION(r) parse_resolution (&r, strchr (setting, '=') + 1)
#define ENUM(r,t,s) \
do { \
int _i; \
@@ -426,6 +440,8 @@ parse_setting (PinPointPoint *point,
IF_PREFIX("duration=") point->duration = FLOAT;
IF_PREFIX("command=") point->command = STRING;
IF_PREFIX("transition=") point->transition = STRING;
+ IF_PREFIX("camera-framerate=") point->camera_framerate = INT;
+ IF_PREFIX("camera-resolution=") RESOLUTION (point->camera_resolution);
IF_EQUAL("fill") point->bg_scale = PP_BG_FILL;
IF_EQUAL("fit") point->bg_scale = PP_BG_FIT;
IF_EQUAL("stretch") point->bg_scale = PP_BG_STRETCH;
@@ -452,7 +468,9 @@ parse_setting (PinPointPoint *point,
#undef IF_EQUAL
#undef FLOAT
#undef STRING
+#undef INT
#undef ENUM
+#undef RESOLUTION
}
static void
@@ -775,7 +793,10 @@ pp_parse_slides (PinPointRenderer *renderer,
filename[i] = tolower(filename[i]);
i++;
}
- if (str_has_video_suffix (filename))
+
+ if (strcmp (filename, "camera") == 0)
+ point->bg_type = PP_BG_CAMERA;
+ else if (str_has_video_suffix (filename))
point->bg_type = PP_BG_VIDEO;
else if (g_str_has_suffix (filename, ".svg"))
point->bg_type = PP_BG_SVG;
diff --git a/pinpoint.h b/pinpoint.h
index 3508e95..2e7ecae 100644
--- a/pinpoint.h
+++ b/pinpoint.h
@@ -47,6 +47,7 @@ typedef enum
PP_BG_COLOR,
PP_BG_IMAGE,
PP_BG_VIDEO,
+ PP_BG_CAMERA,
PP_BG_SVG
} PPBackgroundType;
@@ -58,6 +59,11 @@ typedef enum
PP_BG_STRETCH
} PPBackgroundScale;
+typedef struct
+{
+ gint width, height;
+} PPResolution;
+
#define PINPOINT_RENDERER(renderer) ((PinPointRenderer *) renderer)
struct _PinPointRenderer
@@ -103,6 +109,9 @@ struct _PinPointPoint
const char *command;
+ gint camera_framerate;
+ PPResolution camera_resolution;
+
void *data; /* the renderer can attach data here */
};
diff --git a/pp-cairo.c b/pp-cairo.c
index 167a9f7..de58e48 100644
--- a/pp-cairo.c
+++ b/pp-cairo.c
@@ -426,6 +426,9 @@ _cairo_render_background (CairoRenderer *renderer,
}
#endif
break;
+ case PP_BG_CAMERA:
+ /* silently ignore camera backgrounds */
+ break;
default:
g_assert_not_reached();
}
diff --git a/pp-clutter.c b/pp-clutter.c
index fa21d63..a7126bf 100644
--- a/pp-clutter.c
+++ b/pp-clutter.c
@@ -156,6 +156,10 @@ typedef struct
ClutterActor *midground;
ClutterActor *foreground;
ClutterActor *shading;
+
+#ifdef USE_CLUTTER_GST
+ GstElement *pipeline; /* used for the custom camera pipeline */
+#endif
} ClutterPointData;
#define CLUTTER_RENDERER(renderer) ((ClutterRenderer *) renderer)
@@ -175,9 +179,39 @@ static void file_changed (GFileMonitor *monitor,
static void stage_resized (ClutterActor *actor,
GParamSpec *pspec,
ClutterRenderer *renderer);
-static gboolean key_pressed (ClutterActor *actor,
- ClutterEvent *event,
- ClutterRenderer *renderer);
+static gboolean key_pressed (ClutterActor *actor,
+ ClutterEvent *event,
+ ClutterRenderer *renderer);
+
+static void
+pp_clutter_render_adjust_background (ClutterRenderer *renderer,
+ PinPointPoint *point)
+{
+ float bg_x, bg_y, bg_width, bg_height, bg_scale_x, bg_scale_y;
+ ClutterPointData *data = point->data;
+
+ if (!data)
+ return;
+
+ if (CLUTTER_IS_RECTANGLE (data->background))
+ {
+ clutter_actor_get_size (renderer->stage, &bg_width, &bg_height);
+ clutter_actor_set_size (data->background, bg_width, bg_height);
+ }
+ else
+ {
+ clutter_actor_get_size (data->background, &bg_width, &bg_height);
+ }
+
+ pp_get_background_position_scale (point,
+ clutter_actor_get_width (renderer->stage),
+ clutter_actor_get_height (renderer->stage),
+ bg_width, bg_height,
+ &bg_x, &bg_y, &bg_scale_x, &bg_scale_y);
+
+ clutter_actor_set_scale (data->background, bg_scale_x, bg_scale_y);
+ clutter_actor_set_position (data->background, bg_x, bg_y);
+}
#ifdef HAVE_CLUTTER_X11
static void pp_set_fullscreen (ClutterStage *stage,
@@ -870,6 +904,111 @@ _clutter_get_texture (ClutterRenderer *renderer,
return clutter_clone_new (source);
}
+#if USE_CLUTTER_GST
+static void
+on_size_changed (ClutterActor *texture,
+ gint width,
+ gint height,
+ gpointer user_data)
+{
+ PinPointRenderer *pp_renderer = user_data;
+ ClutterRenderer *renderer = CLUTTER_RENDERER (pp_renderer);
+ PinPointPoint *point;
+ ClutterPointData *data;
+
+ point = pp_slidep->data;
+ if (!point)
+ return;
+
+ data = point->data;
+
+ if (data->background != texture)
+ {
+ g_warning ("size changed but not current background ?!");
+ return;
+ }
+
+ clutter_actor_set_size (texture, width, height);
+ pp_clutter_render_adjust_background (renderer, point);
+}
+
+static gboolean
+setup_camera (PinPointRenderer *renderer,
+ PinPointPoint *point)
+{
+ /* These are static to be able to share the texture and the pipeline between
+ * all the slides using the camera */
+ static ClutterActor *texture = NULL;
+ static GstElement *pipeline = NULL;
+
+ ClutterPointData *data = point->data;
+ GstElement *src;
+ GstElement *capsfilter;
+ GstElement *sink;
+ GstCaps *caps;
+ gboolean result;
+
+ if (texture)
+ {
+ data->background = clutter_clone_new (texture);
+ data->pipeline = pipeline;
+
+ return TRUE;
+ }
+
+ texture = g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL);
+
+ g_signal_connect (CLUTTER_TEXTURE (texture),
+ "size-change",
+ G_CALLBACK (on_size_changed), renderer);
+
+ /* Set up pipeline */
+ pipeline = gst_pipeline_new (NULL);
+
+ src = gst_element_factory_make ("v4l2src", NULL);
+ capsfilter = gst_element_factory_make ("capsfilter", NULL);
+ sink = clutter_gst_video_sink_new (CLUTTER_TEXTURE (texture));
+
+ /* make videotestsrc spit the format we want */
+ caps = gst_caps_new_simple ("video/x-raw-yuv", NULL);
+
+ if (point->camera_framerate)
+ {
+ gst_caps_set_simple (caps,
+ "framerate", GST_TYPE_FRACTION,
+ point->camera_framerate, 1,
+ NULL);
+ }
+
+#define W (point->camera_resolution.width)
+#define H (point->camera_resolution.height)
+ if (W != 0 && H != 0)
+ {
+ gst_caps_set_simple (caps,
+ "width", G_TYPE_INT, W,
+ "height", G_TYPE_INT, H,
+ NULL);
+ }
+#undef W
+#undef H
+
+ g_object_set (capsfilter, "caps", caps, NULL);
+
+ gst_bin_add_many (GST_BIN (pipeline), src, capsfilter, sink, NULL);
+ result = gst_element_link_many (src, capsfilter, sink, NULL);
+ if (result == FALSE)
+ {
+ g_critical("Could not link elements");
+ gst_object_unref (pipeline);
+ return FALSE;
+ }
+
+ data->background = texture;
+ data->pipeline = pipeline;
+
+ return TRUE;
+}
+#endif
static gboolean
clutter_renderer_make_point (PinPointRenderer *pp_renderer,
@@ -917,6 +1056,11 @@ clutter_renderer_make_point (PinPointRenderer *pp_renderer,
ret = TRUE;
#endif
break;
+ case PP_BG_CAMERA:
+#ifdef USE_CLUTTER_GST
+ ret = setup_camera (pp_renderer, point);
+#endif
+ break;
case PP_BG_SVG:
#ifdef USE_DAX
{
@@ -1127,6 +1271,10 @@ static void leave_slide (ClutterRenderer *renderer,
"opacity", 0x0,
NULL);
#ifdef USE_CLUTTER_GST
+ if (point->bg_type == PP_BG_CAMERA)
+ {
+ gst_element_set_state (data->pipeline, GST_STATE_PAUSED);
+ }
if (CLUTTER_GST_IS_VIDEO_TEXTURE (data->background))
{
clutter_media_set_playing (CLUTTER_MEDIA (data->background),
@@ -1610,30 +1758,14 @@ show_slide (ClutterRenderer *renderer, gboolean backwards)
if (data->background)
{
- float bg_x, bg_y, bg_width, bg_height, bg_scale_x, bg_scale_y;
+ pp_clutter_render_adjust_background (renderer, point);
- if (CLUTTER_IS_RECTANGLE (data->background))
- {
- clutter_actor_get_size (renderer->stage, &bg_width, &bg_height);
- clutter_actor_set_size (data->background, bg_width, bg_height);
- }
- else
+#ifdef USE_CLUTTER_GST
+ if (point->bg_type == PP_BG_CAMERA)
{
- clutter_actor_get_size (data->background, &bg_width, &bg_height);
+ gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
}
-
- pp_get_background_position_scale (
- point,
- clutter_actor_get_width (renderer->stage),
- clutter_actor_get_height (renderer->stage),
- bg_width, bg_height,
- &bg_x, &bg_y, &bg_scale_x, &bg_scale_y);
-
- clutter_actor_set_scale (data->background, bg_scale_x, bg_scale_y);
- clutter_actor_set_position (data->background, bg_x, bg_y);
-
-#ifdef USE_CLUTTER_GST
- if (CLUTTER_GST_IS_VIDEO_TEXTURE (data->background))
+ else if (CLUTTER_GST_IS_VIDEO_TEXTURE (data->background))
{
clutter_media_set_progress (CLUTTER_MEDIA (data->background), 0.0);
clutter_media_set_playing (CLUTTER_MEDIA (data->background), TRUE);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]