[pinpoint/wip/speaker-view] run with previous timings for presentation progress
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pinpoint/wip/speaker-view] run with previous timings for presentation progress
- Date: Wed, 1 Jun 2011 11:23:43 +0000 (UTC)
commit a92bb03d6d18ce0c59b1f443d8e359ac72755503
Author: �yvind Kolås <pippin gimp org>
Date: Tue May 31 15:19:47 2011 +0100
run with previous timings for presentation progress
introduction.pin | 64 +++---
pinpoint.c | 27 ++-
pinpoint.h | 5 +-
pp-cairo.c | 80 ++++++--
pp-clutter.c | 608 +++++++++++++++++++++++++++++++++++++++---------------
5 files changed, 569 insertions(+), 215 deletions(-)
---
diff --git a/introduction.pin b/introduction.pin
index 6939da5..fd558ab 100644
--- a/introduction.pin
+++ b/introduction.pin
@@ -3,17 +3,17 @@
[bg.jpg]
[font=Sans 50px]
[duration=3.000000]
--- [duration=1.224066]
+-- [duration=4.448699]
Welcome to pinpoint
--- [duration=2.811049]
+-- [duration=3.393199]
A tool for making excellent presentations
--- [bowls.jpg] [duration=2.396589]
+-- [bowls.jpg] [duration=4.322308]
It has a simple text source
# The source can include witty comment lines
--- [font=monospace 18px] [shading-opacity=1.000000] [duration=2.173404]
+-- [font=monospace 18px] [shading-opacity=1.000000] [duration=23.560078]
The current presentation thus far:
#!/usr/bin/env pinpoint
[font=Sans 50px]
@@ -32,7 +32,7 @@ The current presentation thus far:
- [font=monospace 18px] [shading-opacity=1.0]
The current presentation thus far:
--- [text-align=center] [duration=1.792367]
+-- [text-align=center] [duration=12.553503]
You start by writing down the core concepts that you will be talking about. Then sort and format
them as a pinpoint presentation in a text editor of your choice.
@@ -43,97 +43,97 @@ Pinpoint reloads the presentation when it changes on disk, very useful when you'
so keep both pinpoint and your text editor open. And remember, the less text you have, the happier
your audience will be ;-)
--- [duration=1.663685]
+-- [duration=3.136431]
Let's use some of the more
esoteric features of pinpoint
--- [bowls.jpg] [text-align=center] [duration=1.430618]
+-- [bowls.jpg] [text-align=center] [duration=5.757168]
- [filename.jpg]
set a custom background for an individual slide
--- [bunny.ogv] [fill] [duration=1.465077]
+-- [bunny.ogv] [fill] [duration=24.458597]
You can put <b>anything</b> in the background
--- [linus.jpg] [fill] [bottom-left] [duration=1.324098]
+-- [linus.jpg] [fill] [bottom-left] [duration=3.724967]
But, slides with cat pictures are best
--- [text-align=right] [top-right] [duration=1.396734]
+-- [text-align=right] [top-right] [duration=1.879800]
position text in the
[top-right]
--- [right] [duration=1.222382]
+-- [right] [duration=1.031598]
[right]
--- [bottom-right] [duration=1.264147]
+-- [bottom-right] [duration=1.064696]
[bottom-right]
--- [bottom] [duration=1.264479]
+-- [bottom] [duration=1.047646]
[bottom]
--- [bottom-left] [duration=1.164848]
+-- [bottom-left] [duration=1.132064]
[bottom-left]
--- [left] [duration=1.364550]
+-- [left] [duration=1.014935]
[left]
--- [top-left] [duration=1.240191]
+-- [top-left] [duration=1.214729]
[top-left]
--- [top] [duration=1.297619]
+-- [top] [duration=1.747087]
[top]
--- [text-align=center] [duration=1.005195]
+-- [text-align=center] [duration=4.109942]
and even in the
[center]
(which is the default)
--- [white] [bottom] [font=Monospace 100px] [text-color=black] [shading-opacity=0.000000] [duration=0.266029]
+-- [white] [bottom] [font=Monospace 100px] [text-color=black] [shading-opacity=0.000000] [duration=7.491852]
Make text big!
[font=Monospace 100px]
[white][text-color=black]
[shading-opacity=0.0][bottom]
--- [duration=0.266103]
+-- [duration=2.912952]
<s>use</s> <b>pango</b> <i
><span foreground='red'>m<u
>ar</u>k<sup>up</sup></span></i> for style
--- [duration=0.232756]
+-- [duration=4.263503]
[no-markup]
<s>don't use</s> <b>pango</b> <i
><span foreground='red'>m<u
>ar</u>k<sup>up</sup></span></i>
--- [bowls.jpg] [transition=page-curl-both] [duration=0.249426]
+-- [bowls.jpg] [transition=page-curl-both] [duration=4.935558]
need bullets?
â?¥ use the power of unicode
â?¢ â?½ â?© â?? â?? â?¦
--- [transition=text-slide-up] [duration=0.282905]
+-- [transition=text-slide-up] [duration=6.881204]
$ pinpoint presentation.txt -o output.pdf
Export to PDF. Handy.
--- [fill] [duration=0.271180]
+-- [fill] [duration=3.903439]
[fill]
Fill the slide with your background
(the default is [fit])
--- [transition=swing] [duration=0.278247]
+-- [transition=swing] [duration=2.679214]
Keybindings:
--- [transition=sheet] [duration=0.448654]
+-- [transition=sheet] [duration=2.913154]
right, down or space - next slide
--- [transition=slide-left] [duration=0.299550]
+-- [transition=slide-left] [duration=4.702688]
left or up - previous slide
--- [transition=slide-up] [duration=0.299543]
-F11 - toggle fullscreen
+-- [transition=slide-up] [duration=3.435221]
+F11 - toggle fullscreen!
--- [transition=text-slide-down] [duration=0.382787]
+-- [transition=text-slide-down] [duration=2.167284]
Escape - quit pinpoint
--- [fill] [transition=slide-in-left] [command=killall xeyes ; xeyes] [duration=0.715592]
+-- [fill] [transition=slide-in-left] [command=killall xeyes ; xeyes] [duration=16.965691]
Enter - Run command
Tab - Edit command
[command=killall xeyes ; xeyes]
@@ -142,7 +142,7 @@ N.B. run pinpoint with the -m option
and hidden or auto-hiding panels, to
allow window management in fullscreen.
--- [linus.jpg] [fill] [bottom-right] [duration=0.499109]
+-- [linus.jpg] [fill] [bottom-right] [duration=7.079270]
That's pretty much everything.
Told you it was simple.
diff --git a/pinpoint.c b/pinpoint.c
index a238759..f64e702 100644
--- a/pinpoint.c
+++ b/pinpoint.c
@@ -118,13 +118,14 @@ void pp_rehearse_init (void)
for (iter = pp_slides; iter; iter=iter->next)
{
PinPointPoint *point = iter->data;
- point->duration = 0.0;
+ point->new_duration = 0.0;
}
}
+
static char *pinfile = NULL;
-void pp_rehearse_save (void)
+static void pp_rehearse_save (void)
{
GError *error = NULL;
char *content = pp_serialize ();
@@ -134,11 +135,23 @@ void pp_rehearse_save (void)
}
else
{
- printf ("saved\n");
+ printf ("saved to %s\n", pinfile);
}
g_free (content);
}
+
+void pp_rehearse_done (void)
+{
+ GList *iter;
+ for (iter = pp_slides; iter; iter=iter->next)
+ {
+ PinPointPoint *point = iter->data;
+ point->duration = point->new_duration;
+ }
+ pp_rehearse_save ();
+}
+
int
main (int argc,
char **argv)
@@ -218,8 +231,10 @@ main (int argc,
renderer->finalize (renderer);
if (renderer->source)
g_free (renderer->source);
+#if 0
if (pp_rehearse)
pp_rehearse_save ();
+#endif
g_list_free (pp_slides);
@@ -510,7 +525,9 @@ str_has_video_suffix (const char *string)
for (ext = video_extensions; *ext; ext ++)
if (g_str_has_suffix (string, *ext))
- return TRUE;
+ {
+ return TRUE;
+ }
return FALSE;
}
@@ -690,7 +707,7 @@ pp_parse_slides (PinPointRenderer *renderer,
start_of_line = FALSE;
}
}
- slideno--;
+ slideno-=2;
g_free (renderer->source);
}
renderer->source = g_strdup (slide_src);
diff --git a/pinpoint.h b/pinpoint.h
index 1b7fc2f..3508e95 100644
--- a/pinpoint.h
+++ b/pinpoint.h
@@ -28,6 +28,7 @@
#include "config.h"
#endif
+
#include <clutter/clutter.h>
typedef struct _PinPointPoint PinPointPoint;
@@ -92,6 +93,8 @@ struct _PinPointPoint
presentation, other slides have a representation
of their portion of the presentation */
+ gfloat new_duration; /* new duration,. used during reharsal */
+
char *speaker_notes; /* speaker comments for the slide */
const char *shading_color;
@@ -122,7 +125,7 @@ pp_get_padding (float stage_width,
float *padding);
void pp_rehearse_init (void);
-void pp_rehearse_save (void);
+void pp_rehearse_done (void);
void
pp_get_background_position_scale (PinPointPoint *point,
diff --git a/pp-cairo.c b/pp-cairo.c
index 2d1b044..167a9f7 100644
--- a/pp-cairo.c
+++ b/pp-cairo.c
@@ -52,6 +52,8 @@ typedef struct _CairoRenderer
when using it in several slides */
cairo_surface_t *surface;
cairo_t *ctx;
+ double width;
+ double height;
} CairoRenderer;
typedef struct
@@ -76,8 +78,10 @@ cairo_renderer_init (PinPointRenderer *pp_renderer,
CairoRenderer *renderer = CAIRO_RENDERER (pp_renderer);
/* A4, landscape */
+ renderer->width = A4_LS_WIDTH;
+ renderer->height = A4_LS_HEIGHT;
renderer->surface = cairo_pdf_surface_create (pp_output_filename,
- A4_LS_WIDTH, A4_LS_HEIGHT);
+ renderer->width, renderer->height);
renderer->path = g_strdup (pinpoint_file);
renderer->ctx = cairo_create (renderer->surface);
@@ -88,6 +92,11 @@ cairo_renderer_init (PinPointRenderer *pp_renderer,
g_object_unref);
}
+static void
+cairo_renderer_cr_render(void *pp_renderer,
+ cairo_t *cr);
+
+
/* This function is adapted from Gtk's gdk_cairo_set_source_pixbuf() you can
* find in gdk/gdkcairo.c.
* Copyright (C) Red Had, Inc.
@@ -282,7 +291,16 @@ _cairo_render_background (CairoRenderer *renderer,
PinPointPoint *point)
{
char *full_path = NULL;
- const char *file = point->bg;
+ const char *file;
+
+ if (point == NULL)
+ {
+ cairo_set_source_rgb (renderer->ctx, 0,0,0);
+ cairo_paint (renderer->ctx);
+ return;
+ }
+
+ file = point->bg;
if (point->bg_type != PP_BG_COLOR && renderer->path && file)
{
@@ -335,7 +353,7 @@ _cairo_render_background (CairoRenderer *renderer,
bg_height = cairo_image_surface_get_height (surface);
pp_get_background_position_scale (point,
- A4_LS_WIDTH, A4_LS_HEIGHT,
+ renderer->width, renderer->height,
bg_width, bg_height,
&bg_x, &bg_y,
&bg_scale_x, &bg_scale_y);
@@ -367,7 +385,7 @@ _cairo_render_background (CairoRenderer *renderer,
bg_height = cairo_image_surface_get_height (surface);
pp_get_background_position_scale (point,
- A4_LS_WIDTH, A4_LS_HEIGHT,
+ renderer->width, A4_LS_HEIGHT,
bg_width, bg_height,
&bg_x, &bg_y,
&bg_scale_x, &bg_scale_y);
@@ -394,7 +412,7 @@ _cairo_render_background (CairoRenderer *renderer,
rsvg_handle_get_dimensions (svg, &dim);
pp_get_background_position_scale (point,
- A4_LS_WIDTH, A4_LS_HEIGHT,
+ renderer->width, renderer->height,
dim.width, dim.height,
&bg_x, &bg_y,
&bg_scale_x, &bg_scale_y);
@@ -427,6 +445,8 @@ _cairo_render_text (CairoRenderer *renderer,
float text_x, text_y, text_width, text_height, text_scale;
float shading_x, shading_y, shading_width, shading_height;
+ if (point == NULL)
+ return;
layout = pango_cairo_create_layout (renderer->ctx);
desc = pango_font_description_from_string (point->font);
@@ -444,12 +464,12 @@ _cairo_render_text (CairoRenderer *renderer,
goto out;
pp_get_text_position_scale (point,
- A4_LS_WIDTH, A4_LS_HEIGHT,
+ renderer->width, renderer->height,
text_width, text_height,
&text_x, &text_y,
&text_scale);
- pp_get_shading_position_size (A4_LS_HEIGHT, A4_LS_WIDTH,
+ pp_get_shading_position_size (renderer->height, renderer->width, /* XXX: is this right order?? */
text_x, text_y,
text_width, text_height,
text_scale,
@@ -484,9 +504,9 @@ out:
g_object_unref (layout);
}
-static void
-_cairo_render_page (CairoRenderer *renderer,
- PinPointPoint *point)
+void
+cairo_renderer_render_page (CairoRenderer *renderer,
+ PinPointPoint *point)
{
_cairo_render_background (renderer, point);
_cairo_render_text (renderer, point);
@@ -500,7 +520,7 @@ cairo_renderer_run (PinPointRenderer *pp_renderer)
GList *cur;
for (cur = pp_slides; cur; cur = g_list_next (cur))
- _cairo_render_page (renderer, cur->data);
+ cairo_renderer_render_page (renderer, cur->data);
}
static void
@@ -509,12 +529,15 @@ cairo_renderer_finalize (PinPointRenderer *pp_renderer)
CairoRenderer *renderer = CAIRO_RENDERER (pp_renderer);
g_free (renderer->path);
- cairo_surface_destroy (renderer->surface);
+ if (renderer->surface)
+ cairo_surface_destroy (renderer->surface);
g_hash_table_unref (renderer->surfaces);
g_hash_table_unref (renderer->svgs);
- cairo_destroy (renderer->ctx);
+ if (renderer->ctx)
+ cairo_destroy (renderer->ctx);
}
+
static gboolean
cairo_renderer_make_point (PinPointRenderer *pp_renderer,
PinPointPoint *point)
@@ -525,12 +548,41 @@ cairo_renderer_make_point (PinPointRenderer *pp_renderer,
{
ClutterColor color;
- ret = clutter_color_from_string (&color, point->bg);
+ ret = clutter_color_from_string (&color, point->bg); /* this roughly checks that the color is valid? */
}
return ret;
}
+void
+cairo_renderer_unset_cr (PinPointRenderer *pp_renderer)
+{
+ CairoRenderer *renderer = CAIRO_RENDERER (pp_renderer);
+ renderer->ctx = NULL;
+}
+
+void
+cairo_renderer_set_cr (PinPointRenderer *pp_renderer,
+ cairo_t *ctx,
+ float width,
+ float height)
+{
+ CairoRenderer *renderer = CAIRO_RENDERER (pp_renderer);
+ if (renderer->ctx)
+ {
+ if (renderer->surface)
+ {
+ cairo_surface_destroy (renderer->surface);
+ renderer->surface = NULL;
+ }
+ cairo_destroy (renderer->ctx);
+ renderer->ctx = NULL;
+ }
+ renderer->ctx = ctx;
+ renderer->width = width;
+ renderer->height = height;
+}
+
static void *
cairo_renderer_allocate_data (PinPointRenderer *renderer)
{
diff --git a/pp-clutter.c b/pp-clutter.c
index 5645619..85c8c5e 100644
--- a/pp-clutter.c
+++ b/pp-clutter.c
@@ -40,6 +40,17 @@
#endif
#include <stdlib.h>
+
+void cairo_renderer_unset_cr (PinPointRenderer *pp_renderer);
+
+void cairo_renderer_set_cr (PinPointRenderer *pp_renderer,
+ cairo_t *ctx,
+ float width,
+ float height);
+
+void cairo_renderer_render_page (void *renderer,
+ PinPointPoint *point);
+
/* #define QUICK_ACCESS_LEFT - uncomment to move speed access from top to left,
* useful on meego netbook
*/
@@ -57,6 +68,10 @@ static ClutterColor gray = {0x77,0x77,0x77,0xff};
static ClutterColor white = {0xff,0xff,0xff,0xff};
static ClutterColor red = {0xff,0x00,0x00,0xff};
+#ifdef HAVE_PDF
+PinPointRenderer *pp_cairo_renderer (void);
+#endif
+
typedef struct _ClutterRenderer
{
PinPointRenderer renderer;
@@ -77,7 +92,7 @@ typedef struct _ClutterRenderer
GTimer *timer;
gboolean timer_paused;
int total_seconds;
- gboolean autoplay;
+ gboolean autoadvance;
gboolean speaker_mode;
ClutterActor *speaker_screen;
@@ -85,13 +100,17 @@ typedef struct _ClutterRenderer
gdouble slide_start_time;
ClutterActor *speaker_buttons_group;
+ ClutterActor *speaker_speakerscreen;
ClutterActor *speaker_rehearse;
- ClutterActor *speaker_autoplay;
- ClutterActor *speaker_reset_time;
- ClutterActor *speaker_pause_time;
+ ClutterActor *speaker_autoadvance;
+ ClutterActor *speaker_start;
+ ClutterActor *speaker_pause;
+ ClutterActor *speaker_fullscreen;
ClutterActor *speaker_notes;
- ClutterActor *speaker_clone;
+ ClutterActor *speaker_prev;
+ ClutterActor *speaker_current;
+ ClutterActor *speaker_next;
ClutterActor *speaker_slide_prog_warning;
ClutterActor *speaker_prog_warning;
@@ -99,7 +118,8 @@ typedef struct _ClutterRenderer
ClutterActor *speaker_prog_bg;
ClutterActor *speaker_prog_slide;
ClutterActor *speaker_prog_time;
- ClutterActor *speaker_time_remaining;/* < should be just minutes */
+ ClutterActor *speaker_slide_time_remaining;
+ ClutterActor *speaker_time_remaining;
ClutterActor *speaker_slide_prog_bg;
ClutterActor *speaker_slide_prog_time;
@@ -107,6 +127,12 @@ typedef struct _ClutterRenderer
char *path; /* path of the file of the GFileMonitor callback */
float rest_y; /* where the text can rest */
+
+ gboolean reset; /* tells the speaker screen update function to
+ reset all state
+ */
+
+ PinPointRenderer *cairo_renderer;
} ClutterRenderer;
typedef struct
@@ -384,11 +410,12 @@ opacity_hover_leave (ClutterActor *actor,
return FALSE;
}
-#define opacity_hover(o) \
- clutter_actor_set_opacity (o, NORMAL_OPACITY);\
- g_signal_connect (o, "enter-event", \
+#define opacity_hover(o) \
+ clutter_actor_set_opacity (o, NORMAL_OPACITY); \
+ clutter_actor_set_reactive (o, TRUE); \
+ g_signal_connect (o, "enter-event", \
G_CALLBACK (opacity_hover_enter), NULL); \
- g_signal_connect (o, "leave-event", \
+ g_signal_connect (o, "leave-event", \
G_CALLBACK (opacity_hover_leave), NULL); \
static gboolean
@@ -401,66 +428,114 @@ play_pause (ClutterActor *actor,
{
g_timer_continue (renderer->timer);
renderer->timer_paused = FALSE;
- clutter_text_set_text (CLUTTER_TEXT (actor), "pause");
+ clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_pause), "pause");
}
else
{
g_timer_stop (renderer->timer);
renderer->timer_paused = TRUE;
- clutter_text_set_text (CLUTTER_TEXT (actor), "play");
+ clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_pause), "go");
}
return TRUE;
}
-
static gboolean
-reset_time (ClutterActor *actor,
- ClutterEvent *event,
- gpointer data)
+toggle_autoadvance (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer data)
{
ClutterRenderer *renderer = CLUTTER_RENDERER (data);
- g_timer_stop (renderer->timer);
- g_timer_start (renderer->timer);
-
- if (renderer->timer_paused)
- g_timer_stop (renderer->timer);
+ if (renderer->autoadvance)
+ {
+ renderer->autoadvance = FALSE;
+ clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_autoadvance), "enable autoadvance");
+ }
+ else
+ {
+ renderer->autoadvance = TRUE;
+ clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_autoadvance), "disable autoadvance");
+ }
return TRUE;
}
+static void end_of_presentation (ClutterRenderer *renderer);
+
+static void
+next_slide (ClutterRenderer *renderer)
+{
+ if (pp_slidep && pp_slidep->next)
+ {
+ leave_slide (renderer, FALSE);
+ pp_slidep = pp_slidep->next;
+ show_slide (renderer, FALSE);
+ }
+ else
+ {
+ end_of_presentation (renderer);
+ }
+}
+
+static void
+prev_slide (ClutterRenderer *renderer)
+{
+ if (pp_slidep && pp_slidep->prev)
+ {
+ leave_slide (renderer, TRUE);
+ pp_slidep = pp_slidep->prev;
+ show_slide (renderer, TRUE);
+ }
+}
static gboolean
-toggle_autoplay (ClutterActor *actor,
- ClutterEvent *event,
- gpointer data)
+go_prev (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer data)
{
ClutterRenderer *renderer = CLUTTER_RENDERER (data);
- if (renderer->autoplay)
- renderer->autoplay = FALSE;
- else
- renderer->autoplay = TRUE;
+ prev_slide (renderer);
return TRUE;
}
-
static gboolean
-start_rehearse (ClutterActor *actor,
- ClutterEvent *event,
- gpointer data)
+go_next (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer data)
{
ClutterRenderer *renderer = CLUTTER_RENDERER (data);
- g_warning ("%s NYI\n", __FUNCTION__);
+ next_slide (renderer);
+ return TRUE;
+}
+static gboolean
+start (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer data)
+{
+ ClutterRenderer *renderer = CLUTTER_RENDERER (data);
g_timer_stop (renderer->timer);
g_timer_start (renderer->timer);
renderer->timer_paused = FALSE;
leave_slide (renderer, TRUE);
pp_slidep = pp_slides;
+ play_pause (NULL, NULL, data);
+ play_pause (NULL, NULL, data);
+ if (pp_rehearse)
+ {
+ pp_rehearse = FALSE;
+ }
show_slide (renderer, TRUE);
+ renderer->reset = TRUE;
+ return TRUE;
+}
+
+static gboolean
+start_rehearse (ClutterActor *actor,
+ ClutterEvent *event,
+ gpointer data)
+{
+ start (actor, event, data);
pp_rehearse = TRUE;
pp_rehearse_init ();
-
- /* end of presentation */
-
}
@@ -478,78 +553,122 @@ clutter_renderer_init_speaker_screen (ClutterRenderer *renderer)
"color", &white,
NULL);
- renderer->speaker_time_remaining = g_object_new (CLUTTER_TYPE_TEXT,
+ renderer->speaker_slide_time_remaining = g_object_new (CLUTTER_TYPE_TEXT,
"x", 300.0,
"y", 0.0,
"opacity", NORMAL_OPACITY,
"font-name", "Sans 28px",
- "text", "-3",
- "reactive", TRUE,
+ "text", "-",
"color", &white,
NULL);
+ renderer->speaker_time_remaining = g_object_new (CLUTTER_TYPE_TEXT,
+ "x", 300.0,
+ "y", 0.0,
+ "opacity", NORMAL_OPACITY,
+ "font-name", "Sans 28px",
+ "text", "-",
+ "color", &white,
+ NULL);
renderer->speaker_buttons_group = clutter_group_new ();
+
+#define BUTTON_FONT "Sans 20px"
+
+ renderer->speaker_speakerscreen = g_object_new (CLUTTER_TYPE_TEXT,
+ "x", 0.0,
+ "y", 0.0,
+ "opacity", NORMAL_OPACITY,
+ "font-name", BUTTON_FONT,
+ "text", "speaker",
+ "reactive", TRUE,
+ "color", &white,
+ NULL);
+
renderer->speaker_rehearse = g_object_new (CLUTTER_TYPE_TEXT,
"x", 0.0,
"y", 0.0,
"opacity", NORMAL_OPACITY,
- "font-name", "Sans 28px",
+ "font-name", BUTTON_FONT,
"text", "rehearse",
"reactive", TRUE,
"color", &white,
NULL);
- renderer->speaker_autoplay = g_object_new (CLUTTER_TYPE_TEXT,
- "x", 140.0,
+ renderer->speaker_autoadvance = g_object_new (CLUTTER_TYPE_TEXT,
"y", 0.0,
"opacity", NORMAL_OPACITY,
- "font-name", "Sans 28px",
- "text", "autoplay",
+ "font-name", BUTTON_FONT,
+ "text", "enable autoadvance",
"reactive", TRUE,
"color", &white,
NULL);
- renderer->speaker_reset_time = g_object_new (CLUTTER_TYPE_TEXT,
- "x", 280.0,
+ renderer->speaker_start = g_object_new (CLUTTER_TYPE_TEXT,
"y", 0.0,
"opacity", NORMAL_OPACITY,
- "font-name", "Sans 28px",
- "text", "restart",
+ "font-name", BUTTON_FONT,
+ "text", "(re)start",
"reactive", TRUE,
"color", &white,
NULL);
- renderer->speaker_pause_time = g_object_new (CLUTTER_TYPE_TEXT,
- "x", 440.0,
+ renderer->speaker_pause = g_object_new (CLUTTER_TYPE_TEXT,
"y", 0.0,
"opacity", NORMAL_OPACITY,
- "font-name", "Sans 28px",
- "text", "pause",
+ "font-name", BUTTON_FONT,
+ "text", "",
"reactive", TRUE,
"color", &white,
NULL);
+ renderer->speaker_fullscreen = g_object_new (CLUTTER_TYPE_TEXT,
+ "x", 0.0,
+ "y", 0.0,
+ "opacity", NORMAL_OPACITY,
+ "font-name", BUTTON_FONT,
+ "text", "fullscreen",
+ "reactive", TRUE,
+ "color", &white,
+ NULL);
+
+ opacity_hover(renderer->speaker_speakerscreen);
opacity_hover(renderer->speaker_rehearse);
g_signal_connect (renderer->speaker_rehearse, "button-press-event",
G_CALLBACK (start_rehearse), renderer);
- opacity_hover(renderer->speaker_autoplay);
+ opacity_hover(renderer->speaker_autoadvance);
- g_signal_connect (renderer->speaker_autoplay, "button-press-event",
- G_CALLBACK (toggle_autoplay), renderer);
+ g_signal_connect (renderer->speaker_autoadvance, "button-press-event",
+ G_CALLBACK (toggle_autoadvance), renderer);
- opacity_hover(renderer->speaker_reset_time);
+ opacity_hover(renderer->speaker_start);
- g_signal_connect (renderer->speaker_reset_time, "button-press-event",
- G_CALLBACK (reset_time), renderer);
+ g_signal_connect (renderer->speaker_start, "button-press-event",
+ G_CALLBACK (start), renderer);
- opacity_hover(renderer->speaker_pause_time);
+ opacity_hover(renderer->speaker_pause);
- g_signal_connect (renderer->speaker_pause_time, "button-press-event",
+ g_signal_connect (renderer->speaker_pause, "button-press-event",
G_CALLBACK (play_pause), renderer);
+ opacity_hover(renderer->speaker_fullscreen);
- renderer->timer_paused = FALSE;
+ clutter_container_add (CLUTTER_CONTAINER (renderer->speaker_buttons_group),
+ renderer->speaker_speakerscreen,
+ renderer->speaker_start,
+ renderer->speaker_pause,
+ renderer->speaker_autoadvance,
+ renderer->speaker_rehearse,
+ renderer->speaker_fullscreen,
+ NULL);
+
+ g_signal_connect (renderer->speaker_screen, "key-press-event",
+ G_CALLBACK (key_pressed), renderer);
+
+
+
+ renderer->timer_paused = TRUE;
renderer->timer = g_timer_new ();
+ g_timer_stop (renderer->timer);
renderer->speaker_slide_prog_bg = clutter_rectangle_new_with_color (&c_prog_bg);
@@ -581,27 +700,35 @@ clutter_renderer_init_speaker_screen (ClutterRenderer *renderer)
renderer->speaker_buttons_group,
+ renderer->speaker_slide_time_remaining,
renderer->speaker_time_remaining,
- renderer->speaker_clone,
+ renderer->speaker_prev,
+ renderer->speaker_next,
+ renderer->speaker_current,
NULL);
- clutter_container_add (CLUTTER_CONTAINER (renderer->speaker_buttons_group),
- renderer->speaker_rehearse,
- renderer->speaker_autoplay,
- renderer->speaker_reset_time,
- renderer->speaker_pause_time,
- NULL);
clutter_actor_set_opacity (renderer->speaker_slide_prog_warning, 0);
clutter_actor_set_opacity (renderer->speaker_prog_warning, 0);
- /* offscreen creation for actor on different stage not supported */
- //renderer->speaker_clone = clutter_texture_new_from_actor (renderer->root);
- renderer->speaker_clone = clutter_clone_new (renderer->root);
+ renderer->speaker_prev = clutter_cairo_texture_new (320, 240);
+ renderer->speaker_current = clutter_cairo_texture_new (320, 240);
+ renderer->speaker_next = clutter_cairo_texture_new (320, 240);
+
+ opacity_hover(renderer->speaker_prev);
+ opacity_hover(renderer->speaker_next);
+
+ g_signal_connect (renderer->speaker_prev, "button-press-event",
+ G_CALLBACK (go_prev), renderer);
+ g_signal_connect (renderer->speaker_next, "button-press-event",
+ G_CALLBACK (go_next), renderer);
+
clutter_container_add (CLUTTER_CONTAINER (renderer->speaker_screen),
- renderer->speaker_clone,
+ renderer->speaker_prev,
+ renderer->speaker_current,
+ renderer->speaker_next,
NULL);
}
@@ -663,6 +790,8 @@ clutter_renderer_init (PinPointRenderer *pp_renderer,
{
g_signal_connect (renderer->speaker_screen, "notify::width",
G_CALLBACK (stage_resized), renderer);
+ g_signal_connect (renderer->speaker_screen, "notify::height",
+ G_CALLBACK (stage_resized), renderer);
}
g_signal_connect (stage, "notify::height",
@@ -692,6 +821,9 @@ clutter_renderer_init (PinPointRenderer *pp_renderer,
renderer->bg_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, _destroy_surface);
+
+ renderer->cairo_renderer = pp_cairo_renderer ();
+ renderer->cairo_renderer->init (renderer->cairo_renderer, "");
}
static gboolean update_speaker_screen (ClutterRenderer *renderer);
@@ -894,39 +1026,15 @@ static void end_of_presentation (ClutterRenderer *renderer)
{
if (pp_rehearse)
{
- pp_rehearse_save ();
+ pp_rehearse_done ();
}
pp_rehearse = FALSE;
-}
-
-static void
-next_slide (ClutterRenderer *renderer)
-{
- if (pp_slidep && pp_slidep->next)
- {
- leave_slide (renderer, FALSE);
- pp_slidep = pp_slidep->next;
- show_slide (renderer, FALSE);
- }
- else
- {
- end_of_presentation (renderer);
- }
+ if (renderer->autoadvance)
+ toggle_autoadvance (NULL, NULL, renderer);
}
static void
-prev_slide (ClutterRenderer *renderer)
-{
- if (pp_slidep && pp_slidep->prev)
- {
- leave_slide (renderer, TRUE);
- pp_slidep = pp_slidep->prev;
- show_slide (renderer, TRUE);
- }
-}
-
-static void
toggle_speaker_screen (ClutterRenderer *renderer)
{
if (!renderer->speaker_screen)
@@ -966,12 +1074,27 @@ key_pressed (ClutterActor *actor,
case CLUTTER_Escape:
clutter_main_quit ();
break;
- case CLUTTER_F11:
- pp_set_fullscreen (CLUTTER_STAGE (renderer->stage),
- !pp_get_fullscreen (CLUTTER_STAGE (renderer->stage)));
+ case CLUTTER_F1:
+ {
+ gboolean was_fullscreen = pp_get_fullscreen (CLUTTER_STAGE (renderer->stage));
+ toggle_speaker_screen (renderer);
+ if (renderer->speaker_mode && renderer->speaker_screen)
+ pp_set_fullscreen (CLUTTER_STAGE (renderer->speaker_screen), was_fullscreen);
+ }
+ break;
+ case CLUTTER_F2:
+ if (renderer->autoadvance)
+ renderer->autoadvance = FALSE;
+ else
+ renderer->autoadvance = TRUE;
break;
- case CLUTTER_F12:
- toggle_speaker_screen (renderer);
+ case CLUTTER_F11:
+ {
+ gboolean was_fullscreen = pp_get_fullscreen (CLUTTER_STAGE (renderer->stage));
+ pp_set_fullscreen (CLUTTER_STAGE (renderer->stage), !was_fullscreen);
+ if (renderer->speaker_mode && renderer->speaker_screen)
+ pp_set_fullscreen (CLUTTER_STAGE (renderer->speaker_screen), !was_fullscreen);
+ }
break;
case CLUTTER_Return:
action_slide (renderer);
@@ -979,12 +1102,6 @@ key_pressed (ClutterActor *actor,
case CLUTTER_Tab:
activate_commandline (renderer);
break;
- case CLUTTER_a:
- if (renderer->autoplay)
- renderer->autoplay = FALSE;
- else
- renderer->autoplay = TRUE;
- break;
}
return TRUE;
}
@@ -996,8 +1113,8 @@ static void leave_slide (ClutterRenderer *renderer,
ClutterPointData *data = point->data;
if (pp_rehearse)
- point->duration += g_timer_elapsed (renderer->timer, NULL) -
- renderer->slide_start_time;
+ point->new_duration += g_timer_elapsed (renderer->timer, NULL) -
+ renderer->slide_start_time;
if (!point->transition)
{
@@ -1155,7 +1272,27 @@ static void update_commandline_shading (ClutterRenderer *renderer)
NULL);
}
-static gfloat total_time (GList *start)
+static gfloat point_time (ClutterRenderer *renderer,
+ PinPointPoint *point)
+{
+ float time = point->duration != 0.0 ? point->duration : 2.0;
+#if 0
+ if (pp_rehearse && pp_slidep && pp_slidep->data == point)
+ {
+ if (point->new_duration + g_timer_elapsed (renderer->timer, NULL) - renderer->slide_start_time >
+ point->duration)
+ {
+ time = point->new_duration;
+ time += g_timer_elapsed (renderer->timer, NULL) -
+ renderer->slide_start_time;
+ }
+ }
+#endif
+ return time;
+}
+
+static gfloat total_time (ClutterRenderer *renderer,
+ GList *start)
{
GList *iter;
gfloat total = 0;
@@ -1163,25 +1300,53 @@ static gfloat total_time (GList *start)
start = pp_slides;
for (iter = start; iter; iter = iter->next)
{
- PinPointPoint *point = iter->data;
- total +=
- point->duration != 0.0 ? point->duration : 2.0;
+ total += point_time (renderer, iter->data);
}
return total;
}
+static gfloat slide_rel_duration (ClutterRenderer *renderer,
+ GList *slide)
+{
+ return point_time (renderer, slide->data) / total_time (renderer, pp_slides);
+}
+
+static gfloat slide_rel_start (ClutterRenderer *renderer,
+ GList *slide)
+{
+ GList *iter;
+ float time = 0;
+
+ for (iter = slide ->prev; iter; iter = iter->prev)
+ {
+ time += point_time (renderer, iter->data);
+ }
+
+ time = time / total_time (renderer, pp_slides);
+ return time;
+}
+
static gfloat slide_time (ClutterRenderer *renderer,
GList *slide)
{
- PinPointPoint *point = slide->data;
- float time = (point->duration != 0.0 ? point->duration : 2.0) /
- total_time (slide);
+ float time = point_time (renderer, slide->data) /
+ total_time (renderer, slide);
float remaining_time = renderer->total_seconds -
g_timer_elapsed (renderer->timer, NULL);
time *= remaining_time;
return time;
}
+/* The maximum of these is used, either 80% of the slide time
+ or 20seconds left of the slide
+ */
+#define SLIDE_WARN_THRESHOLD 0.5 /* 0.8 ? */
+#define SLIDE_WARN_TIME 10.0
+#define OPACITY_OK 0
+#define OPACITY_PAST_THRESHOLD 64
+#define OPACITY_FEW_LEFT 128
+#define OPACITY_OVER_TIME 200
+
static gboolean update_speaker_screen (ClutterRenderer *renderer)
{
PinPointPoint *point;
@@ -1191,10 +1356,19 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
static float current_slide_time = 0.0;
static float current_slide_duration = 0.0;
static GList *current_slide = NULL;
+ float nh, nw;
+ if (renderer->reset)
{
- static float current_slide_prev = 0.0;
- float diff = g_timer_elapsed (renderer->timer, NULL) - current_slide_prev;
+ current_slide = NULL;
+ current_slide_duration = 0.0;
+ current_slide_time = 0.0;
+ renderer->reset = FALSE;
+ }
+
+ {
+ static float current_slide_prev_time = 0.0;
+ float diff = g_timer_elapsed (renderer->timer, NULL) - current_slide_prev_time;
if (current_slide != pp_slidep)
{
@@ -1206,30 +1380,47 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
current_slide_time += diff;
if (current_slide_time >= current_slide_duration)
{
- if (renderer->autoplay)
+ if (renderer->autoadvance)
{
current_slide_time = 0;
next_slide (renderer);
}
- else
- {
- if (renderer->speaker_slide_prog_warning)
- clutter_actor_animate (renderer->speaker_slide_prog_warning,
- CLUTTER_LINEAR, 500,
- "opacity", 128,
- NULL);
- }
+
+
+ if (renderer->speaker_slide_prog_warning)
+ clutter_actor_animate (renderer->speaker_slide_prog_warning,
+ CLUTTER_LINEAR, 500,
+ "opacity", OPACITY_OVER_TIME,
+ NULL);
+ }
+
+
+ else if ((current_slide_duration - current_slide_time < SLIDE_WARN_TIME))
+ {
+ if (renderer->speaker_slide_prog_warning)
+ clutter_actor_animate (renderer->speaker_slide_prog_warning,
+ CLUTTER_LINEAR, 2000,
+ "opacity", OPACITY_FEW_LEFT,
+ NULL);
+ }
+ else if ((current_slide_time >= current_slide_duration * SLIDE_WARN_THRESHOLD))
+ {
+ if (renderer->speaker_slide_prog_warning)
+ clutter_actor_animate (renderer->speaker_slide_prog_warning,
+ CLUTTER_LINEAR, 2000,
+ "opacity", OPACITY_PAST_THRESHOLD,
+ NULL);
}
else
{
if (renderer->speaker_slide_prog_warning)
clutter_actor_animate (renderer->speaker_slide_prog_warning,
CLUTTER_LINEAR, 50,
- "opacity", 0,
+ "opacity", OPACITY_OK,
NULL);
}
- current_slide_prev = g_timer_elapsed (renderer->timer, NULL);
+ current_slide_prev_time = g_timer_elapsed (renderer->timer, NULL);
}
if (!renderer->speaker_mode)
@@ -1241,6 +1432,9 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
else
clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_notes), "");
+ nw = clutter_actor_get_width (renderer->speaker_screen) + 1;
+ nh = clutter_actor_get_height (renderer->speaker_screen);
+
{ /* should draw rectangles representing progress instead... */
GString *str = g_string_new ("");
int i;
@@ -1252,20 +1446,27 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
n_slides = g_list_length (pp_slides);
-
-
{
- int time = renderer->total_seconds -
+ int time;
+ gboolean over_time = FALSE;
+ time = renderer->total_seconds -
g_timer_elapsed (renderer->timer, NULL) + 0.5;
+ if (time < 0)
+ over_time = TRUE;
if (time <= -60)
g_string_printf (str, "%imin", time/60);
- else if (time <= 60)
+ else if (time <= 10)
g_string_printf (str, "%is", time);
+ else if (time <= 60)
+ {
+ time = ((time + 4)/ 5) * 5;
+ g_string_printf (str, "%is", time);
+ }
else
g_string_printf (str, "%i%smin", time / 60, (time % 60 > 30) ? "½":"");
- clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_time_remaining),
- str->str);
+ clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_time_remaining),
+ str->str);
if (renderer->speaker_prog_warning)
{
@@ -1280,16 +1481,44 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
"opacity", 0,
NULL);
}
- }
- g_string_assign (str, "");
+
+ time = current_slide_duration - current_slide_time;
+
+ if (over_time)
+ g_string_printf (str, "");
+ else if (time <= -60)
+ g_string_printf (str, "%imin", time/60);
+ else if (time <= 10)
+ g_string_printf (str, "%is", time);
+ else if (time <= 60)
+ {
+ time = ((time + 4)/ 5) * 5;
+ g_string_printf (str, "%is", time);
+ }
+ else
+ g_string_printf (str, "%i%smin", time / 60, (time % 60 > 30) ? "½":"");
+
+ clutter_text_set_text (CLUTTER_TEXT (renderer->speaker_slide_time_remaining),
+ str->str);
+ }
g_string_free (str, TRUE);
}
{
- float height = 40;
- float nh = clutter_actor_get_height (renderer->speaker_screen);
- float nw = clutter_actor_get_width (renderer->speaker_screen) + 1;
+#define append_rtl(a,b) \
+ clutter_actor_set_x (b, clutter_actor_get_x (a) + clutter_actor_get_width (a) + 10)
+
+ /* should be replace with constraints */
+ append_rtl (renderer->speaker_speakerscreen, renderer->speaker_start);
+ append_rtl (renderer->speaker_start, renderer->speaker_pause);
+ append_rtl (renderer->speaker_pause, renderer->speaker_autoadvance);
+ append_rtl (renderer->speaker_autoadvance, renderer->speaker_rehearse);
+ append_rtl (renderer->speaker_rehearse, renderer->speaker_fullscreen);
+ }
+
+ {
+ float height = 32;
float y = clutter_actor_get_height (renderer->speaker_screen) - height;
float elapsed_part = g_timer_elapsed (renderer->timer, NULL) / renderer->total_seconds;
@@ -1321,10 +1550,15 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
clutter_actor_set_position (renderer->speaker_time_remaining,
nw - clutter_actor_get_width (renderer->speaker_time_remaining),
nh - clutter_actor_get_height (renderer->speaker_time_remaining));
+ clutter_actor_set_position (renderer->speaker_slide_time_remaining,
+ nw - clutter_actor_get_width (renderer->speaker_slide_time_remaining),
+ nh - clutter_actor_get_height (renderer->speaker_slide_time_remaining) - height);
- clutter_actor_set_x (renderer->speaker_prog_slide, nw * (1.0 * (slide_no-1) / n_slides));
- clutter_actor_set_width (renderer->speaker_prog_slide, nw / n_slides);
+ clutter_actor_set_width (renderer->speaker_prog_slide,
+ nw * slide_rel_duration (renderer, pp_slidep));
+ clutter_actor_set_x (renderer->speaker_prog_slide,
+ nw * slide_rel_start (renderer, pp_slidep));
clutter_actor_set_x (renderer->speaker_prog_time, nw * elapsed_part);
@@ -1338,19 +1572,72 @@ static gboolean update_speaker_screen (ClutterRenderer *renderer)
}
-
{
float scale;
- scale = clutter_actor_get_width (renderer->speaker_screen) / clutter_actor_get_width (renderer->stage) * 0.4;
- clutter_actor_set_scale (renderer->speaker_clone, scale, scale);
+ scale = nw / clutter_actor_get_width (renderer->speaker_next) * 0.4;
+ clutter_actor_set_scale (renderer->speaker_prev, scale * 0.75, scale * 0.75);
+ clutter_actor_set_scale (renderer->speaker_current, scale, scale);
+ clutter_actor_set_scale (renderer->speaker_next, scale * 0.75, scale * 0.75);
+ }
+
+ {
+ static GList *current_slide = NULL;
+ float nh, nw;
+ if (current_slide != pp_slidep)
+ {
+ cairo_t *cr;
+
+ /*************/
+ cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (renderer->speaker_prev));
+ cairo_renderer_set_cr (renderer->cairo_renderer,
+ cr, clutter_actor_get_width (renderer->speaker_prev),
+ clutter_actor_get_height (renderer->speaker_prev));
+ if (pp_slidep->prev)
+ cairo_renderer_render_page (renderer->cairo_renderer,
+ pp_slidep->prev->data);
+ else
+ cairo_renderer_render_page (renderer->cairo_renderer,
+ NULL);
+ cairo_renderer_unset_cr (renderer->cairo_renderer);
+ cairo_destroy (cr);
+
+ /*************/
+ cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (renderer->speaker_current));
+ cairo_renderer_set_cr (renderer->cairo_renderer,
+ cr, clutter_actor_get_width (renderer->speaker_current),
+ clutter_actor_get_height (renderer->speaker_current));
+ cairo_renderer_render_page (renderer->cairo_renderer,
+ pp_slidep->data);
+ cairo_renderer_unset_cr (renderer->cairo_renderer);
+ cairo_destroy (cr);
+
+ /*************/
+ cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (renderer->speaker_next));
+ cairo_renderer_set_cr (renderer->cairo_renderer,
+ cr, clutter_actor_get_width (renderer->speaker_next),
+ clutter_actor_get_height (renderer->speaker_next));
+ if (pp_slidep->next)
+ cairo_renderer_render_page (renderer->cairo_renderer,
+ pp_slidep->next->data);
+ else
+ cairo_renderer_render_page (renderer->cairo_renderer,
+ NULL);
+ cairo_renderer_unset_cr (renderer->cairo_renderer);
+ cairo_destroy (cr);
+ /*************/
+ current_slide = pp_slidep;
+ }
}
- clutter_actor_set_position (renderer->speaker_clone,
- clutter_actor_get_width (renderer->speaker_screen) * 0.05,
- clutter_actor_get_height (renderer->speaker_screen) * 0.3);
- clutter_actor_set_clip (renderer->speaker_clone,
- 0,0,
- clutter_actor_get_width (renderer->stage),
- clutter_actor_get_height (renderer->stage));
+
+ clutter_actor_set_position (renderer->speaker_prev,
+ nw * 0.0,
+ nh * 0.4);
+ clutter_actor_set_position (renderer->speaker_current,
+ nw * 0.3,
+ nh * 0.3);
+ clutter_actor_set_position (renderer->speaker_next,
+ nw * 0.7,
+ nh * 0.4);
return TRUE;
}
@@ -1364,8 +1651,7 @@ show_slide (ClutterRenderer *renderer, gboolean backwards)
if (!pp_slidep)
return;
- if (pp_rehearse)
- renderer->slide_start_time = g_timer_elapsed (renderer->timer, NULL);
+ renderer->slide_start_time = g_timer_elapsed (renderer->timer, NULL);
point = pp_slidep->data;
data = point->data;
@@ -1644,7 +1930,6 @@ show_slide (ClutterRenderer *renderer, gboolean backwards)
clutter_state_set_state (data->state, "show");
}
-
/* render potentially executed commands */
{
float text_x, text_y, text_width, text_height;
@@ -1749,9 +2034,6 @@ PinPointRenderer *pp_clutter_renderer (void)
}
/*
- - only make the time run after having gone to slide #2 ? .. uncertain
- - have the user start the timer by doing an ignored "next slide"
- - scale the slide shown in time progress based on slide "size" in duration?..
- ... doing so would make the position in progress more closely resemble
- wall clock time for presentation.
+ make moving the mouse to some location (as well as tapping in it) cause the
+ previews to re-arrange themselves in a grid.
*/
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]