[gnome-desktop] gnome-bg: split slide show stuff off into separate api
- From: Ray Strode <halfline src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-desktop] gnome-bg: split slide show stuff off into separate api
- Date: Mon, 18 Feb 2013 23:24:52 +0000 (UTC)
commit 33d793c5e3996046f165499f941b5256d8a51850
Author: Ray Strode <rstrode redhat com>
Date: Mon Feb 18 14:36:27 2013 -0500
gnome-bg: split slide show stuff off into separate api
We need to be able to parse slide shows directly from within gnome-shell.
https://bugzilla.gnome.org/show_bug.cgi?id=694121
libgnome-desktop/Makefile.am | 2 +
libgnome-desktop/gnome-bg-slide-show.c | 766 ++++++++++++++++++++++++++++++++
libgnome-desktop/gnome-bg-slide-show.h | 89 ++++
libgnome-desktop/gnome-bg.c | 662 +++++-----------------------
4 files changed, 959 insertions(+), 560 deletions(-)
---
diff --git a/libgnome-desktop/Makefile.am b/libgnome-desktop/Makefile.am
index 3f04191..00ba47b 100644
--- a/libgnome-desktop/Makefile.am
+++ b/libgnome-desktop/Makefile.am
@@ -27,6 +27,7 @@ introspection_sources = \
gnome-desktop-thumbnail.c \
gnome-thumbnail-pixbuf-utils.c \
gnome-bg.c \
+ gnome-bg-slide-show.c \
gnome-bg-crossfade.c \
display-name.c \
gnome-rr.c \
@@ -66,6 +67,7 @@ libgnome_desktopdir = $(includedir)/gnome-desktop-3.0/libgnome-desktop
libgnome_desktop_HEADERS = \
gnome-bg.h \
gnome-bg-crossfade.h \
+ gnome-bg-slide-show.h \
gnome-desktop-thumbnail.h \
gnome-rr.h \
gnome-rr-config.h \
diff --git a/libgnome-desktop/gnome-bg-slide-show.c b/libgnome-desktop/gnome-bg-slide-show.c
new file mode 100644
index 0000000..cbdbf7b
--- /dev/null
+++ b/libgnome-desktop/gnome-bg-slide-show.c
@@ -0,0 +1,766 @@
+/* gnome-bg-slide-show.h
+ *
+ * Copyright (C) 2008, 2013 Red Hat, Inc.
+ *
+ * This program 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 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <string.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#include <gio/gio.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include "gnome-bg-slide-show.h"
+
+struct _GnomeBGSlideShowPrivate
+{
+ char *filename;
+
+ double start_time;
+ double total_duration;
+
+ GQueue *slides;
+
+ gboolean has_multiple_sizes;
+
+ /* used during parsing */
+ struct tm start_tm;
+ GQueue *stack;
+};
+
+typedef struct _Slide Slide;
+
+struct _Slide
+{
+ double duration; /* in seconds */
+ gboolean fixed;
+
+ GSList *file1;
+ GSList *file2; /* NULL if fixed is TRUE */
+};
+
+typedef struct _FileSize FileSize;
+struct _FileSize
+{
+ gint width;
+ gint height;
+
+ char *file;
+};
+
+enum {
+ PROP_0,
+ PROP_FILENAME,
+ PROP_START_TIME,
+ PROP_TOTAL_DURATION,
+ PROP_HAS_MULTIPLE_SIZES,
+};
+
+G_DEFINE_TYPE (GnomeBGSlideShow, gnome_bg_slide_show, G_TYPE_OBJECT)
+#define GNOME_BG_SLIDE_SHOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),\
+ GNOME_BG_TYPE_SLIDE_SHOW,\
+ GnomeBGSlideShowPrivate))
+
+static void
+gnome_bg_slide_show_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GnomeBGSlideShow *self;
+
+ g_assert (GNOME_BG_IS_SLIDE_SHOW (object));
+
+ self = GNOME_BG_SLIDE_SHOW (object);
+
+ switch (property_id)
+ {
+ case PROP_FILENAME:
+ self->priv->filename = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gnome_bg_slide_show_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GnomeBGSlideShow *self;
+
+ g_assert (GNOME_BG_IS_SLIDE_SHOW (object));
+
+ self = GNOME_BG_SLIDE_SHOW (object);
+
+ switch (property_id)
+ {
+ case PROP_START_TIME:
+ g_value_set_int (value, self->priv->start_time);
+ break;
+ case PROP_TOTAL_DURATION:
+ g_value_set_int (value, self->priv->total_duration);
+ break;
+ case PROP_HAS_MULTIPLE_SIZES:
+ g_value_set_boolean (value, self->priv->has_multiple_sizes);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gnome_bg_slide_show_finalize (GObject *object)
+{
+ GnomeBGSlideShow *self;
+
+ GList *list;
+ GSList *slist;
+ FileSize *size;
+
+ self = GNOME_BG_SLIDE_SHOW (object);
+
+ for (list = self->priv->slides->head; list != NULL; list = list->next) {
+ Slide *slide = list->data;
+
+ for (slist = slide->file1; slist != NULL; slist = slist->next) {
+ size = slist->data;
+ g_free (size->file);
+ g_free (size);
+ }
+ g_slist_free (slide->file1);
+
+ for (slist = slide->file2; slist != NULL; slist = slist->next) {
+ size = slist->data;
+ g_free (size->file);
+ g_free (size);
+ }
+ g_slist_free (slide->file2);
+
+ g_free (slide);
+ }
+
+ g_queue_free (self->priv->slides);
+
+ g_list_foreach (self->priv->stack->head, (GFunc) g_free, NULL);
+ g_queue_free (self->priv->stack);
+}
+
+static void
+gnome_bg_slide_show_class_init (GnomeBGSlideShowClass *self_class)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (self_class);
+
+ gobject_class->get_property = gnome_bg_slide_show_get_property;
+ gobject_class->set_property = gnome_bg_slide_show_set_property;
+ gobject_class->finalize = gnome_bg_slide_show_finalize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_FILENAME,
+ g_param_spec_string ("filename",
+ "Filename",
+ "Filename",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class,
+ PROP_START_TIME,
+ g_param_spec_double ("start-time",
+ "Start time",
+ "start time",
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_TOTAL_DURATION,
+ g_param_spec_double ("total-duration",
+ "Start duration",
+ "total duration",
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_HAS_MULTIPLE_SIZES,
+ g_param_spec_boolean ("has-multiple-sizes",
+ "Has multiple sizes",
+ "Has multiple sizes",
+ FALSE,
+ G_PARAM_READABLE));
+
+ g_type_class_add_private (gobject_class, sizeof (GnomeBGSlideShowPrivate));
+}
+
+static void
+gnome_bg_slide_show_init (GnomeBGSlideShow *self)
+{
+ self->priv = GNOME_BG_SLIDE_SHOW_GET_PRIVATE (self);
+
+ self->priv->stack = g_queue_new ();
+ self->priv->slides = g_queue_new ();
+}
+
+/**
+ * gnome_bg_slide_show_new:
+ * @filename: The name of the slide show file
+ *
+ * Creates a new object to manage a slide show.
+ * window background between two #cairo_surface_ts.
+ *
+ * Return value: the new #GnomeBGSlideShow
+ **/
+GnomeBGSlideShow *
+gnome_bg_slide_show_new (const char *filename)
+{
+ return GNOME_BG_SLIDE_SHOW (g_object_new (GNOME_BG_TYPE_SLIDE_SHOW,
+ "filename", filename,
+ NULL));
+}
+
+static void
+threadsafe_localtime (time_t time, struct tm *tm)
+{
+ struct tm *res;
+
+ G_LOCK_DEFINE_STATIC (localtime_mutex);
+
+ G_LOCK (localtime_mutex);
+
+ res = localtime (&time);
+ if (tm) {
+ *tm = *res;
+ }
+
+ G_UNLOCK (localtime_mutex);
+}
+static gboolean stack_is (GnomeBGSlideShow *self, const char *s1, ...);
+
+/* Parser for fading background */
+static void
+handle_start_element (GMarkupParseContext *context,
+ const gchar *name,
+ const gchar **attr_names,
+ const gchar **attr_values,
+ gpointer user_data,
+ GError **err)
+{
+ GnomeBGSlideShow *self = user_data;
+ gint i;
+
+ if (strcmp (name, "static") == 0 || strcmp (name, "transition") == 0) {
+ Slide *slide = g_new0 (Slide, 1);
+
+ if (strcmp (name, "static") == 0)
+ slide->fixed = TRUE;
+
+ g_queue_push_tail (self->priv->slides, slide);
+ }
+ else if (strcmp (name, "size") == 0) {
+ Slide *slide = self->priv->slides->tail->data;
+ FileSize *size = g_new0 (FileSize, 1);
+ for (i = 0; attr_names[i]; i++) {
+ if (strcmp (attr_names[i], "width") == 0)
+ size->width = atoi (attr_values[i]);
+ else if (strcmp (attr_names[i], "height") == 0)
+ size->height = atoi (attr_values[i]);
+ }
+ if (self->priv->stack->tail &&
+ (strcmp (self->priv->stack->tail->data, "file") == 0 ||
+ strcmp (self->priv->stack->tail->data, "from") == 0)) {
+ slide->file1 = g_slist_prepend (slide->file1, size);
+ }
+ else if (self->priv->stack->tail &&
+ strcmp (self->priv->stack->tail->data, "to") == 0) {
+ slide->file2 = g_slist_prepend (slide->file2, size);
+ }
+ }
+ g_queue_push_tail (self->priv->stack, g_strdup (name));
+}
+
+static void
+handle_end_element (GMarkupParseContext *context,
+ const gchar *name,
+ gpointer user_data,
+ GError **err)
+{
+ GnomeBGSlideShow *self = user_data;
+
+ g_free (g_queue_pop_tail (self->priv->stack));
+}
+
+static gboolean
+stack_is (GnomeBGSlideShow *self,
+ const char *s1,
+ ...)
+{
+ GList *stack = NULL;
+ const char *s;
+ GList *l1, *l2;
+ va_list args;
+
+ stack = g_list_prepend (stack, (gpointer)s1);
+
+ va_start (args, s1);
+
+ s = va_arg (args, const char *);
+ while (s) {
+ stack = g_list_prepend (stack, (gpointer)s);
+ s = va_arg (args, const char *);
+ }
+
+ l1 = stack;
+ l2 = self->priv->stack->head;
+
+ while (l1 && l2) {
+ if (strcmp (l1->data, l2->data) != 0) {
+ g_list_free (stack);
+ return FALSE;
+ }
+
+ l1 = l1->next;
+ l2 = l2->next;
+ }
+
+ g_list_free (stack);
+
+ return (!l1 && !l2);
+}
+
+static int
+parse_int (const char *text)
+{
+ return strtol (text, NULL, 0);
+}
+
+static void
+handle_text (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **err)
+{
+ GnomeBGSlideShow *self = user_data;
+ Slide *slide = self->priv->slides->tail? self->priv->slides->tail->data : NULL;
+ FileSize *fs;
+ gint i;
+
+ if (stack_is (self, "year", "starttime", "background", NULL)) {
+ self->priv->start_tm.tm_year = parse_int (text) - 1900;
+ }
+ else if (stack_is (self, "month", "starttime", "background", NULL)) {
+ self->priv->start_tm.tm_mon = parse_int (text) - 1;
+ }
+ else if (stack_is (self, "day", "starttime", "background", NULL)) {
+ self->priv->start_tm.tm_mday = parse_int (text);
+ }
+ else if (stack_is (self, "hour", "starttime", "background", NULL)) {
+ self->priv->start_tm.tm_hour = parse_int (text) - 1;
+ }
+ else if (stack_is (self, "minute", "starttime", "background", NULL)) {
+ self->priv->start_tm.tm_min = parse_int (text);
+ }
+ else if (stack_is (self, "second", "starttime", "background", NULL)) {
+ self->priv->start_tm.tm_sec = parse_int (text);
+ }
+ else if (stack_is (self, "duration", "static", "background", NULL) ||
+ stack_is (self, "duration", "transition", "background", NULL)) {
+ slide->duration = g_strtod (text, NULL);
+ self->priv->total_duration += slide->duration;
+ }
+ else if (stack_is (self, "file", "static", "background", NULL) ||
+ stack_is (self, "from", "transition", "background", NULL)) {
+ for (i = 0; text[i]; i++) {
+ if (!g_ascii_isspace (text[i]))
+ break;
+ }
+ if (text[i] == 0)
+ return;
+ fs = g_new (FileSize, 1);
+ fs->width = -1;
+ fs->height = -1;
+ fs->file = g_strdup (text);
+ slide->file1 = g_slist_prepend (slide->file1, fs);
+ if (slide->file1->next != NULL)
+ self->priv->has_multiple_sizes = TRUE;
+ }
+ else if (stack_is (self, "size", "file", "static", "background", NULL) ||
+ stack_is (self, "size", "from", "transition", "background", NULL)) {
+ fs = slide->file1->data;
+ fs->file = g_strdup (text);
+ if (slide->file1->next != NULL)
+ self->priv->has_multiple_sizes = TRUE;
+ }
+ else if (stack_is (self, "to", "transition", "background", NULL)) {
+ for (i = 0; text[i]; i++) {
+ if (!g_ascii_isspace (text[i]))
+ break;
+ }
+ if (text[i] == 0)
+ return;
+ fs = g_new (FileSize, 1);
+ fs->width = -1;
+ fs->height = -1;
+ fs->file = g_strdup (text);
+ slide->file2 = g_slist_prepend (slide->file2, fs);
+ if (slide->file2->next != NULL)
+ self->priv->has_multiple_sizes = TRUE;
+ }
+ else if (stack_is (self, "size", "to", "transition", "background", NULL)) {
+ fs = slide->file2->data;
+ fs->file = g_strdup (text);
+ if (slide->file2->next != NULL)
+ self->priv->has_multiple_sizes = TRUE;
+ }
+}
+
+/*
+ * Find the FileSize that best matches the given size.
+ * Do two passes; the first pass only considers FileSizes
+ * that are larger than the given size.
+ * We are looking for the image that best matches the aspect ratio.
+ * When two images have the same aspect ratio, prefer the one whose
+ * width is closer to the given width.
+ */
+static const char *
+find_best_size (GSList *sizes, gint width, gint height)
+{
+ GSList *s;
+ gdouble a, d, distance;
+ FileSize *best = NULL;
+ gint pass;
+
+ a = width/(gdouble)height;
+ distance = 10000.0;
+
+ for (pass = 0; pass < 2; pass++) {
+ for (s = sizes; s; s = s->next) {
+ FileSize *size = s->data;
+
+ if (pass == 0 && (size->width < width || size->height < height))
+ continue;
+
+ d = fabs (a - size->width/(gdouble)size->height);
+ if (d < distance) {
+ distance = d;
+ best = size;
+ }
+ else if (d == distance) {
+ if (abs (size->width - width) < abs (best->width - width)) {
+ best = size;
+ }
+ }
+ }
+
+ if (best)
+ break;
+ }
+
+ return best->file;
+}
+
+static double
+now (void)
+{
+ GTimeVal tv;
+
+ g_get_current_time (&tv);
+
+ return (double)tv.tv_sec + (tv.tv_usec / 1000000.0);
+}
+
+/**
+ * gnome_bg_slide_show_get_current_slide:
+ * @self: a #GnomeBGSlideShow
+ * @width: monitor width
+ * @height: monitor height
+ * @progress: slide progress
+ * @duration: slide duration
+ * @is_fixed: if slide is fixed
+ * @file1: (transfer none): first file in slide
+ * @file2: (transfer none): second file in slide
+ *
+ * Returns the current slides progress
+ *
+ * Return value: %TRUE if successful
+ **/
+void
+gnome_bg_slide_show_get_current_slide (GnomeBGSlideShow *self,
+ int width,
+ int height,
+ gdouble *progress,
+ double *duration,
+ gboolean *is_fixed,
+ const char **file1,
+ const char **file2)
+{
+ double delta = fmod (now() - self->priv->start_time, self->priv->total_duration);
+ GList *list;
+ double elapsed;
+ int i;
+
+ if (delta < 0)
+ delta += self->priv->total_duration;
+
+ elapsed = 0;
+ i = 0;
+ for (list = self->priv->slides->head; list != NULL; list = list->next) {
+ Slide *slide = list->data;
+
+ if (elapsed + slide->duration > delta) {
+ if (progress)
+ *progress = (delta - elapsed) / (double)slide->duration;
+ if (duration)
+ *duration = slide->duration;
+
+ if (is_fixed)
+ *is_fixed = slide->fixed;
+
+ if (file1)
+ *file1 = find_best_size (slide->file1, width, height);
+
+ if (file2 && slide->file2)
+ *file2 = find_best_size (slide->file2, width, height);
+
+ return;
+ }
+
+ i++;
+ elapsed += slide->duration;
+ }
+
+ /* this should never happen since we have slides and we should always
+ * find a current slide for the elapsed time since beginning -- we're
+ * looping with fmod() */
+ g_assert_not_reached ();
+}
+
+/**
+ * gnome_bg_slide_show_get_slide:
+ * @self: a #GnomeBGSlideShow
+ * @frame_number: frame number
+ * @width: monitor width
+ * @height: monitor height
+ * @duration: slide duration
+ * @is_fixed: if slide is fixed
+ * @file1: (transfer none): first file in slide
+ * @file2: (transfer none): second file in slide
+ *
+ * Retrieves slide by frame number
+ *
+ * Return value: %TRUE if successful
+ **/
+gboolean
+gnome_bg_slide_show_get_slide (GnomeBGSlideShow *self,
+ int frame_number,
+ int width,
+ int height,
+ double *progress,
+ double *duration,
+ gboolean *is_fixed,
+ const char **file1,
+ const char **file2)
+{
+ double delta = fmod (now() - self->priv->start_time, self->priv->total_duration);
+ GList *l;
+ int i, skipped;
+ gboolean found;
+ double elapsed;
+ Slide *slide;
+
+ if (delta < 0)
+ delta += self->priv->total_duration;
+
+ elapsed = 0;
+ i = 0;
+ skipped = 0;
+ found = FALSE;
+ for (l = self->priv->slides->head; l; l = l->next) {
+ slide = l->data;
+
+ if (!slide->fixed) {
+ elapsed += slide->duration;
+
+ skipped++;
+ continue;
+ }
+ if (i == frame_number) {
+ found = TRUE;
+ break;
+ }
+ i++;
+ elapsed += slide->duration;
+ }
+ if (!found)
+ return FALSE;
+
+ if (progress) {
+ if (elapsed + slide->duration > delta) {
+ *progress = (delta - elapsed) / (double)slide->duration;
+ } else {
+ *progress = 0.0;
+ }
+ }
+
+ if (duration)
+ *duration = slide->duration;
+
+ if (is_fixed)
+ *is_fixed = slide->fixed;
+
+ if (file1)
+ *file1 = find_best_size (slide->file1, width, height);
+
+ if (file2 && slide->file2)
+ *file2 = find_best_size (slide->file2, width, height);
+
+ return TRUE;
+}
+
+/**
+ * gnome_bg_slide_show_load:
+ * @self: a #GnomeBGSlideShow
+ * @error: a #GError
+ *
+ * Tries to load the slide show.
+ *
+ * Return value: %TRUE if successful
+ **/
+gboolean
+gnome_bg_slide_show_load (GnomeBGSlideShow *self,
+ GError **error)
+{
+ GMarkupParser parser = {
+ handle_start_element,
+ handle_end_element,
+ handle_text,
+ NULL, /* passthrough */
+ NULL, /* error */
+ };
+
+ GFile *file;
+ char *contents = NULL;
+ gsize len;
+ GMarkupParseContext *context = NULL;
+ time_t t;
+ gboolean failed = FALSE;
+
+ file = g_file_new_for_path (self->priv->filename);
+ if (!g_file_load_contents (file, NULL, &contents, &len, NULL, NULL)) {
+ return FALSE;
+ }
+ g_object_unref (file);
+
+ threadsafe_localtime ((time_t)0, &self->priv->start_tm);
+
+ context = g_markup_parse_context_new (&parser, 0, self, NULL);
+
+ if (!g_markup_parse_context_parse (context, contents, len, error)) {
+ failed = TRUE;
+ }
+
+ if (!failed && !g_markup_parse_context_end_parse (context, error)) {
+ failed = TRUE;
+ }
+
+ g_markup_parse_context_free (context);
+
+ if (!failed) {
+ int len;
+
+ t = mktime (&self->priv->start_tm);
+
+ self->priv->start_time = (double)t;
+
+ len = g_queue_get_length (self->priv->slides);
+
+ /* no slides, that's not a slideshow */
+ if (len == 0) {
+ failed = TRUE;
+ /* one slide, there's no transition */
+ } else if (len == 1) {
+ Slide *slide = self->priv->slides->head->data;
+ slide->duration = self->priv->total_duration = G_MAXUINT;
+ }
+ }
+
+ g_free (contents);
+
+ return !failed;
+}
+
+/**
+ * gnome_bg_slide_show_get_start_time:
+ * @self: a #GnomeBGSlideShow
+ *
+ * gets the start time of the slide show
+ *
+ * Return value: a timestamp
+ **/
+double
+gnome_bg_slide_show_get_start_time (GnomeBGSlideShow *self)
+{
+ return self->priv->start_time;
+}
+
+/**
+ * gnome_bg_slide_show_get_total_duration:
+ * @self: a #GnomeBGSlideShow
+ *
+ * gets the total duration of the slide show
+ *
+ * Return value: a timestamp
+ **/
+double
+gnome_bg_slide_show_get_total_duration (GnomeBGSlideShow *self)
+{
+ return self->priv->total_duration;
+}
+
+/**
+ * gnome_bg_slide_show_get_has_multiple_sizes:
+ * @self: a #GnomeBGSlideShow
+ *
+ * gets whether or not the slide show has multiple sizes for different monitors
+ *
+ * Return value: %TRUE if multiple sizes
+ **/
+gboolean
+gnome_bg_slide_show_get_has_multiple_sizes (GnomeBGSlideShow *self)
+{
+ return self->priv->has_multiple_sizes;
+}
+
+/**
+ * gnome_bg_slide_show_get_num_slides:
+ * @self: a #GnomeBGSlideShow
+ *
+ * Returns number of slides in slide show
+ **/
+int
+gnome_bg_slide_show_get_num_slides (GnomeBGSlideShow *self)
+{
+ return g_queue_get_length (self->priv->slides);
+}
diff --git a/libgnome-desktop/gnome-bg-slide-show.h b/libgnome-desktop/gnome-bg-slide-show.h
new file mode 100644
index 0000000..5776f7c
--- /dev/null
+++ b/libgnome-desktop/gnome-bg-slide-show.h
@@ -0,0 +1,89 @@
+/* gnome-bg-slide_show.h - fade window background between two surfaces
+
+ Copyright 2008, Red Hat, Inc.
+
+ This file is part of the Gnome Library.
+
+ The Gnome 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.
+
+ The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+ Author: Ray Strode <rstrode redhat com>
+*/
+
+#ifndef __GNOME_BG_SLIDE_SHOW_H__
+#define __GNOME_BG_SLIDE_SHOW_H__
+
+#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
+#error GnomeBGSlideShow is unstable API. You must define GNOME_DESKTOP_USE_UNSTABLE_API before including
gnome-bg-slide_show.h
+#endif
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+#define GNOME_BG_TYPE_SLIDE_SHOW (gnome_bg_slide_show_get_type ())
+#define GNOME_BG_SLIDE_SHOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_BG_TYPE_SLIDE_SHOW,
GnomeBGSlideShow))
+#define GNOME_BG_SLIDE_SHOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_BG_TYPE_SLIDE_SHOW,
GnomeBGSlideShowClass))
+#define GNOME_BG_IS_SLIDE_SHOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_BG_TYPE_SLIDE_SHOW))
+#define GNOME_BG_IS_SLIDE_SHOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_BG_TYPE_SLIDE_SHOW))
+#define GNOME_BG_SLIDE_SHOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_BG_TYPE_SLIDE_SHOW,
GnomeBGSlideShowClass))
+
+typedef struct _GnomeBGSlideShowPrivate GnomeBGSlideShowPrivate;
+typedef struct _GnomeBGSlideShow GnomeBGSlideShow;
+typedef struct _GnomeBGSlideShowClass GnomeBGSlideShowClass;
+
+struct _GnomeBGSlideShow
+{
+ GObject parent_object;
+
+ GnomeBGSlideShowPrivate *priv;
+};
+
+struct _GnomeBGSlideShowClass
+{
+ GObjectClass parent_class;
+};
+
+GType gnome_bg_slide_show_get_type (void);
+GnomeBGSlideShow *gnome_bg_slide_show_new (const char *filename);
+gboolean gnome_bg_slide_show_load (GnomeBGSlideShow *self,
+ GError **error);
+gboolean gnome_bg_slide_show_get_slide (GnomeBGSlideShow *self,
+ int frame_number,
+ int width,
+ int height,
+ gdouble *progress,
+ double *duration,
+ gboolean *is_fixed,
+ const char **file1,
+ const char **file2);
+
+void gnome_bg_slide_show_get_current_slide (GnomeBGSlideShow *self,
+ int width,
+ int height,
+ gdouble *progress,
+ double *duration,
+ gboolean *is_fixed,
+ const char **file1,
+ const char **file2);
+
+
+double gnome_bg_slide_show_get_start_time (GnomeBGSlideShow *self);
+double gnome_bg_slide_show_get_total_duration (GnomeBGSlideShow *self);
+gboolean gnome_bg_slide_show_get_has_multiple_sizes (GnomeBGSlideShow *self);
+int gnome_bg_slide_show_get_num_slides (GnomeBGSlideShow *self);
+G_END_DECLS
+
+#endif
diff --git a/libgnome-desktop/gnome-bg.c b/libgnome-desktop/gnome-bg.c
index 0073d68..36e4a5f 100644
--- a/libgnome-desktop/gnome-bg.c
+++ b/libgnome-desktop/gnome-bg.c
@@ -44,6 +44,7 @@ Author: Soren Sandmann <sandmann redhat com>
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include "gnome-bg.h"
+#include "gnome-bg-slide-show.h"
#include "gnome-bg-crossfade.h"
#define BG_KEY_DRAW_BACKGROUND "draw-background"
@@ -58,27 +59,6 @@ Author: Soren Sandmann <sandmann redhat com>
in the slideshow is less than 60 seconds away */
#define KEEP_EXPENSIVE_CACHE_SECS 60
-typedef struct _SlideShow SlideShow;
-typedef struct _Slide Slide;
-
-struct _Slide
-{
- double duration; /* in seconds */
- gboolean fixed;
-
- GSList *file1;
- GSList *file2; /* NULL if fixed is TRUE */
-};
-
-typedef struct _FileSize FileSize;
-struct _FileSize
-{
- gint width;
- gint height;
-
- char *file;
-};
-
/* This is the size of the GdkRGB dither matrix, in order to avoid
* bad dithering when tiling the gradient
*/
@@ -108,7 +88,7 @@ struct _GnomeBG
guint blow_caches_id;
/* Cached information, only access through cache accessor functions */
- SlideShow * slideshow;
+ GnomeBGSlideShow * slideshow;
time_t file_mtime;
GdkPixbuf * pixbuf_cache;
int timeout_id;
@@ -185,20 +165,10 @@ static GdkPixbuf *create_img_thumbnail (GnomeBG *bg,
int dest_width,
int dest_height,
int frame_num);
-static SlideShow * get_as_slideshow (GnomeBG *bg,
- const char *filename);
-static Slide * get_current_slide (SlideShow *show,
- double *alpha);
-static gboolean slideshow_has_multiple_sizes (SlideShow *show);
-
-static SlideShow *read_slideshow_file (const char *filename,
+static GnomeBGSlideShow * get_as_slideshow (GnomeBG *bg,
+ const char *filename);
+static GnomeBGSlideShow *read_slideshow_file (const char *filename,
GError **err);
-static SlideShow *slideshow_ref (SlideShow *show);
-static void slideshow_unref (SlideShow *show);
-
-static FileSize *find_best_size (GSList *sizes,
- gint width,
- gint height);
static void
color_from_string (const char *string,
@@ -1025,7 +995,7 @@ gnome_bg_draw (GnomeBG *bg,
gboolean
gnome_bg_has_multiple_sizes (GnomeBG *bg)
{
- SlideShow *show;
+ GnomeBGSlideShow *show;
gboolean ret;
g_return_val_if_fail (bg != NULL, FALSE);
@@ -1034,8 +1004,8 @@ gnome_bg_has_multiple_sizes (GnomeBG *bg)
show = get_as_slideshow (bg, bg->filename);
if (show) {
- ret = slideshow_has_multiple_sizes (show);
- slideshow_unref (show);
+ ret = gnome_bg_slide_show_get_has_multiple_sizes (show);
+ g_object_unref (show);
}
return ret;
@@ -1272,9 +1242,8 @@ get_original_size (const char *filename,
static const char *
get_filename_for_size (GnomeBG *bg, gint best_width, gint best_height)
{
- SlideShow *show;
- Slide *slide;
- FileSize *size;
+ GnomeBGSlideShow *show;
+ const char *file = NULL;
if (!bg->filename)
return NULL;
@@ -1284,10 +1253,8 @@ get_filename_for_size (GnomeBG *bg, gint best_width, gint best_height)
return bg->filename;
}
- slide = get_current_slide (show, NULL);
- slideshow_unref (show);
- size = find_best_size (slide->file1, best_width, best_height);
- return size->file;
+ gnome_bg_slide_show_get_current_slide (show, best_width, best_height, NULL, NULL, NULL, &file, NULL);
+ return file;
}
gboolean
@@ -1647,51 +1614,6 @@ struct _SlideShow
};
-static double
-now (void)
-{
- GTimeVal tv;
-
- g_get_current_time (&tv);
-
- return (double)tv.tv_sec + (tv.tv_usec / 1000000.0);
-}
-
-static Slide *
-get_current_slide (SlideShow *show,
- double *alpha)
-{
- double delta = fmod (now() - show->start_time, show->total_duration);
- GList *list;
- double elapsed;
- int i;
-
- if (delta < 0)
- delta += show->total_duration;
-
- elapsed = 0;
- i = 0;
- for (list = show->slides->head; list != NULL; list = list->next) {
- Slide *slide = list->data;
-
- if (elapsed + slide->duration > delta) {
- if (alpha)
- *alpha = (delta - elapsed) / (double)slide->duration;
- return slide;
- }
-
- i++;
- elapsed += slide->duration;
- }
-
- /* this should never happen since we have slides and we should always
- * find a current slide for the elapsed time since beginning -- we're
- * looping with fmod() */
- g_assert_not_reached ();
-
- return NULL;
-}
-
static GdkPixbuf *
blend (GdkPixbuf *p1,
GdkPixbuf *p2,
@@ -1730,7 +1652,7 @@ struct FileCacheEntry
char *filename;
union {
GdkPixbuf *pixbuf;
- SlideShow *slideshow;
+ GnomeBGSlideShow *slideshow;
GdkPixbuf *thumbnail;
} u;
};
@@ -1745,7 +1667,7 @@ file_cache_entry_delete (FileCacheEntry *ent)
g_object_unref (ent->u.pixbuf);
break;
case SLIDESHOW:
- slideshow_unref (ent->u.slideshow);
+ g_object_unref (ent->u.slideshow);
break;
case THUMBNAIL:
g_object_unref (ent->u.thumbnail);
@@ -1825,10 +1747,10 @@ file_cache_add_thumbnail (GnomeBG *bg,
static void
file_cache_add_slide_show (GnomeBG *bg,
const char *filename,
- SlideShow *show)
+ GnomeBGSlideShow *show)
{
FileCacheEntry *ent = file_cache_entry_new (bg, SLIDESHOW, filename);
- ent->u.slideshow = slideshow_ref (show);
+ ent->u.slideshow = g_object_ref (show);
}
static GdkPixbuf *
@@ -1899,15 +1821,15 @@ get_as_pixbuf_for_size (GnomeBG *bg,
}
}
-static SlideShow *
+static GnomeBGSlideShow *
get_as_slideshow (GnomeBG *bg, const char *filename)
{
const FileCacheEntry *ent;
if ((ent = file_cache_lookup (bg, SLIDESHOW, filename))) {
- return slideshow_ref (ent->u.slideshow);
+ return g_object_ref (ent->u.slideshow);
}
else {
- SlideShow *show = read_slideshow_file (filename, NULL);
+ GnomeBGSlideShow *show = read_slideshow_file (filename, NULL);
if (show)
file_cache_add_slide_show (bg, filename, show);
@@ -1984,11 +1906,12 @@ on_timeout (gpointer data)
}
static double
-get_slide_timeout (Slide *slide)
+get_slide_timeout (gboolean is_fixed,
+ gdouble duration)
{
double timeout;
- if (slide->fixed) {
- timeout = slide->duration;
+ if (is_fixed) {
+ timeout = duration;
} else {
/* Maybe the number of steps should be configurable? */
@@ -2002,18 +1925,16 @@ get_slide_timeout (Slide *slide)
* color mode in the worst case, so we'll use this as an approximation
* of whats detectable.
*/
- timeout = slide->duration / 64.0;
+ timeout = duration / 64.0;
}
return timeout;
}
static void
ensure_timeout (GnomeBG *bg,
- Slide *slide)
+ gdouble timeout)
{
if (!bg->timeout_id) {
- double timeout = get_slide_timeout (slide);
-
/* G_MAXUINT means "only one slide" */
if (timeout < G_MAXUINT) {
bg->timeout_id = g_timeout_add_full (
@@ -2137,25 +2058,41 @@ create_img_thumbnail (GnomeBG *bg,
return result;
}
else {
- SlideShow *show = get_as_slideshow (bg, bg->filename);
+ GnomeBGSlideShow *show = get_as_slideshow (bg, bg->filename);
if (show) {
double alpha;
- Slide *slide;
+ double duration;
+ gboolean is_fixed;
+ const char *file1;
+ const char *file2;
+ GdkPixbuf *tmp;
if (frame_num == -1)
- slide = get_current_slide (show, &alpha);
+ gnome_bg_slide_show_get_current_slide (show,
+ dest_width,
+ dest_height,
+ &alpha,
+ &duration,
+ &is_fixed,
+ &file1,
+ &file2);
else
- slide = g_queue_peek_nth (show->slides, frame_num);
-
- if (slide->fixed) {
- GdkPixbuf *tmp;
- FileSize *fs;
- fs = find_best_size (slide->file1, dest_width, dest_height);
- tmp = get_as_thumbnail (bg, factory, fs->file);
+ gnome_bg_slide_show_get_slide (show,
+ frame_num,
+ dest_width,
+ dest_height,
+ &alpha,
+ &duration,
+ &is_fixed,
+ &file1,
+ &file2);
+
+ if (is_fixed) {
+ tmp = get_as_thumbnail (bg, factory, file1);
if (tmp) {
thumb = scale_thumbnail (bg->placement,
- fs->file,
+ file1,
tmp,
screen,
dest_width,
@@ -2164,26 +2101,22 @@ create_img_thumbnail (GnomeBG *bg,
}
}
else {
- FileSize *fs1, *fs2;
GdkPixbuf *p1, *p2;
- fs1 = find_best_size (slide->file1, dest_width, dest_height);
- p1 = get_as_thumbnail (bg, factory, fs1->file);
-
- fs2 = find_best_size (slide->file2, dest_width, dest_height);
- p2 = get_as_thumbnail (bg, factory, fs2->file);
+ p1 = get_as_thumbnail (bg, factory, file1);
+ p2 = get_as_thumbnail (bg, factory, file2);
if (p1 && p2) {
GdkPixbuf *thumb1, *thumb2;
thumb1 = scale_thumbnail (bg->placement,
- fs1->file,
+ file1,
p1,
screen,
dest_width,
dest_height);
thumb2 = scale_thumbnail (bg->placement,
- fs2->file,
+ file2,
p2,
screen,
dest_width,
@@ -2200,9 +2133,9 @@ create_img_thumbnail (GnomeBG *bg,
g_object_unref (p2);
}
- ensure_timeout (bg, slide);
+ ensure_timeout (bg, (guint)get_slide_timeout (is_fixed, duration));
- slideshow_unref (show);
+ g_object_unref (show);
}
}
@@ -2212,51 +2145,6 @@ create_img_thumbnail (GnomeBG *bg,
return NULL;
}
-/*
- * Find the FileSize that best matches the given size.
- * Do two passes; the first pass only considers FileSizes
- * that are larger than the given size.
- * We are looking for the image that best matches the aspect ratio.
- * When two images have the same aspect ratio, prefer the one whose
- * width is closer to the given width.
- */
-static FileSize *
-find_best_size (GSList *sizes, gint width, gint height)
-{
- GSList *s;
- gdouble a, d, distance;
- FileSize *best = NULL;
- gint pass;
-
- a = width/(gdouble)height;
- distance = 10000.0;
-
- for (pass = 0; pass < 2; pass++) {
- for (s = sizes; s; s = s->next) {
- FileSize *size = s->data;
-
- if (pass == 0 && (size->width < width || size->height < height))
- continue;
-
- d = fabs (a - size->width/(gdouble)size->height);
- if (d < distance) {
- distance = d;
- best = size;
- }
- else if (d == distance) {
- if (abs (size->width - width) < abs (best->width - width)) {
- best = size;
- }
- }
- }
-
- if (best)
- break;
- }
-
- return best;
-}
-
static GdkPixbuf *
get_pixbuf_for_size (GnomeBG *bg,
gint num_monitor,
@@ -2284,28 +2172,33 @@ get_pixbuf_for_size (GnomeBG *bg,
bg->pixbuf_cache = get_as_pixbuf_for_size (bg, bg->filename, num_monitor, best_width,
best_height);
time_until_next_change = G_MAXUINT;
if (!bg->pixbuf_cache) {
- SlideShow *show = get_as_slideshow (bg, bg->filename);
+ GnomeBGSlideShow *show = get_as_slideshow (bg, bg->filename);
if (show) {
double alpha;
- Slide *slide;
-
- slideshow_ref (show);
-
- slide = get_current_slide (show, &alpha);
- time_until_next_change = (guint)get_slide_timeout (slide);
- if (slide->fixed) {
- FileSize *size;
- size = find_best_size (slide->file1, best_width, best_height);
- bg->pixbuf_cache = get_as_pixbuf_for_size (bg, size->file,
num_monitor, best_width, best_height);
+ double duration;
+ gboolean is_fixed;
+ const char *file1;
+ const char *file2;
+
+ g_object_ref (show);
+
+ gnome_bg_slide_show_get_current_slide (show,
+ best_width,
+ best_height,
+ &alpha,
+ &duration,
+ &is_fixed,
+ &file1,
+ &file2);
+ time_until_next_change = (guint)get_slide_timeout (is_fixed, duration);
+ if (is_fixed) {
+ bg->pixbuf_cache = get_as_pixbuf_for_size (bg, file1, num_monitor,
best_width, best_height);
}
else {
- FileSize *size;
GdkPixbuf *p1, *p2;
- size = find_best_size (slide->file1, best_width, best_height);
- p1 = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width,
best_height);
- size = find_best_size (slide->file2, best_width, best_height);
- p2 = get_as_pixbuf_for_size (bg, size->file, num_monitor, best_width,
best_height);
+ p1 = get_as_pixbuf_for_size (bg, file1, num_monitor, best_width,
best_height);
+ p2 = get_as_pixbuf_for_size (bg, file2, num_monitor, best_width,
best_height);
if (p1 && p2) {
bg->pixbuf_cache = blend (p1, p2, alpha);
@@ -2316,9 +2209,9 @@ get_pixbuf_for_size (GnomeBG *bg,
g_object_unref (p2);
}
- ensure_timeout (bg, slide);
+ ensure_timeout (bg, time_until_next_change);
- slideshow_unref (show);
+ g_object_unref (show);
}
}
@@ -2641,355 +2534,20 @@ pixbuf_tile (GdkPixbuf *src, GdkPixbuf *dest)
}
}
-static gboolean stack_is (SlideShow *parser, const char *s1, ...);
-
-/* Parser for fading background */
-static void
-handle_start_element (GMarkupParseContext *context,
- const gchar *name,
- const gchar **attr_names,
- const gchar **attr_values,
- gpointer user_data,
- GError **err)
-{
- SlideShow *parser = user_data;
- gint i;
-
- if (strcmp (name, "static") == 0 || strcmp (name, "transition") == 0) {
- Slide *slide = g_new0 (Slide, 1);
-
- if (strcmp (name, "static") == 0)
- slide->fixed = TRUE;
-
- g_queue_push_tail (parser->slides, slide);
- }
- else if (strcmp (name, "size") == 0) {
- Slide *slide = parser->slides->tail->data;
- FileSize *size = g_new0 (FileSize, 1);
- for (i = 0; attr_names[i]; i++) {
- if (strcmp (attr_names[i], "width") == 0)
- size->width = atoi (attr_values[i]);
- else if (strcmp (attr_names[i], "height") == 0)
- size->height = atoi (attr_values[i]);
- }
- if (parser->stack->tail &&
- (strcmp (parser->stack->tail->data, "file") == 0 ||
- strcmp (parser->stack->tail->data, "from") == 0)) {
- slide->file1 = g_slist_prepend (slide->file1, size);
- }
- else if (parser->stack->tail &&
- strcmp (parser->stack->tail->data, "to") == 0) {
- slide->file2 = g_slist_prepend (slide->file2, size);
- }
- }
- g_queue_push_tail (parser->stack, g_strdup (name));
-}
-
-static void
-handle_end_element (GMarkupParseContext *context,
- const gchar *name,
- gpointer user_data,
- GError **err)
-{
- SlideShow *parser = user_data;
-
- g_free (g_queue_pop_tail (parser->stack));
-}
-
-static gboolean
-stack_is (SlideShow *parser,
- const char *s1,
- ...)
-{
- GList *stack = NULL;
- const char *s;
- GList *l1, *l2;
- va_list args;
-
- stack = g_list_prepend (stack, (gpointer)s1);
-
- va_start (args, s1);
-
- s = va_arg (args, const char *);
- while (s) {
- stack = g_list_prepend (stack, (gpointer)s);
- s = va_arg (args, const char *);
- }
-
- l1 = stack;
- l2 = parser->stack->head;
-
- while (l1 && l2) {
- if (strcmp (l1->data, l2->data) != 0) {
- g_list_free (stack);
- return FALSE;
- }
-
- l1 = l1->next;
- l2 = l2->next;
- }
-
- g_list_free (stack);
-
- return (!l1 && !l2);
-}
-
-static int
-parse_int (const char *text)
-{
- return strtol (text, NULL, 0);
-}
-
-static void
-handle_text (GMarkupParseContext *context,
- const gchar *text,
- gsize text_len,
- gpointer user_data,
- GError **err)
-{
- SlideShow *parser = user_data;
- Slide *slide = parser->slides->tail? parser->slides->tail->data : NULL;
- FileSize *fs;
- gint i;
-
- if (stack_is (parser, "year", "starttime", "background", NULL)) {
- parser->start_tm.tm_year = parse_int (text) - 1900;
- }
- else if (stack_is (parser, "month", "starttime", "background", NULL)) {
- parser->start_tm.tm_mon = parse_int (text) - 1;
- }
- else if (stack_is (parser, "day", "starttime", "background", NULL)) {
- parser->start_tm.tm_mday = parse_int (text);
- }
- else if (stack_is (parser, "hour", "starttime", "background", NULL)) {
- parser->start_tm.tm_hour = parse_int (text) - 1;
- }
- else if (stack_is (parser, "minute", "starttime", "background", NULL)) {
- parser->start_tm.tm_min = parse_int (text);
- }
- else if (stack_is (parser, "second", "starttime", "background", NULL)) {
- parser->start_tm.tm_sec = parse_int (text);
- }
- else if (stack_is (parser, "duration", "static", "background", NULL) ||
- stack_is (parser, "duration", "transition", "background", NULL)) {
- slide->duration = g_strtod (text, NULL);
- parser->total_duration += slide->duration;
- }
- else if (stack_is (parser, "file", "static", "background", NULL) ||
- stack_is (parser, "from", "transition", "background", NULL)) {
- for (i = 0; text[i]; i++) {
- if (!g_ascii_isspace (text[i]))
- break;
- }
- if (text[i] == 0)
- return;
- fs = g_new (FileSize, 1);
- fs->width = -1;
- fs->height = -1;
- fs->file = g_strdup (text);
- slide->file1 = g_slist_prepend (slide->file1, fs);
- if (slide->file1->next != NULL)
- parser->has_multiple_sizes = TRUE;
- }
- else if (stack_is (parser, "size", "file", "static", "background", NULL) ||
- stack_is (parser, "size", "from", "transition", "background", NULL)) {
- fs = slide->file1->data;
- fs->file = g_strdup (text);
- if (slide->file1->next != NULL)
- parser->has_multiple_sizes = TRUE;
- }
- else if (stack_is (parser, "to", "transition", "background", NULL)) {
- for (i = 0; text[i]; i++) {
- if (!g_ascii_isspace (text[i]))
- break;
- }
- if (text[i] == 0)
- return;
- fs = g_new (FileSize, 1);
- fs->width = -1;
- fs->height = -1;
- fs->file = g_strdup (text);
- slide->file2 = g_slist_prepend (slide->file2, fs);
- if (slide->file2->next != NULL)
- parser->has_multiple_sizes = TRUE;
- }
- else if (stack_is (parser, "size", "to", "transition", "background", NULL)) {
- fs = slide->file2->data;
- fs->file = g_strdup (text);
- if (slide->file2->next != NULL)
- parser->has_multiple_sizes = TRUE;
- }
-}
-
-static SlideShow *
-slideshow_ref (SlideShow *show)
-{
- show->ref_count++;
- return show;
-}
-
-static void
-slideshow_unref (SlideShow *show)
-{
- GList *list;
- GSList *slist;
- FileSize *size;
-
- show->ref_count--;
- if (show->ref_count > 0)
- return;
-
- for (list = show->slides->head; list != NULL; list = list->next) {
- Slide *slide = list->data;
-
- for (slist = slide->file1; slist != NULL; slist = slist->next) {
- size = slist->data;
- g_free (size->file);
- g_free (size);
- }
- g_slist_free (slide->file1);
-
- for (slist = slide->file2; slist != NULL; slist = slist->next) {
- size = slist->data;
- g_free (size->file);
- g_free (size);
- }
- g_slist_free (slide->file2);
-
- g_free (slide);
- }
-
- g_queue_free (show->slides);
-
- g_list_foreach (show->stack->head, (GFunc) g_free, NULL);
- g_queue_free (show->stack);
-
- g_free (show);
-}
-
-static void
-dump_bg (SlideShow *show)
-{
-#if 0
- GList *list;
- GSList *slist;
-
- for (list = show->slides->head; list != NULL; list = list->next)
- {
- Slide *slide = list->data;
-
- g_print ("\nSlide: %s\n", slide->fixed? "fixed" : "transition");
- g_print ("duration: %f\n", slide->duration);
- g_print ("File1:\n");
- for (slist = slide->file1; slist != NULL; slist = slist->next) {
- FileSize *size = slist->data;
- g_print ("\t%s (%dx%d)\n",
- size->file, size->width, size->height);
- }
- g_print ("File2:\n");
- for (slist = slide->file2; slist != NULL; slist = slist->next) {
- FileSize *size = slist->data;
- g_print ("\t%s (%dx%d)\n",
- size->file, size->width, size->height);
- }
- }
-#endif
-}
-
-static void
-threadsafe_localtime (time_t time, struct tm *tm)
-{
- struct tm *res;
-
- G_LOCK_DEFINE_STATIC (localtime_mutex);
-
- G_LOCK (localtime_mutex);
-
- res = localtime (&time);
- if (tm) {
- *tm = *res;
- }
-
- G_UNLOCK (localtime_mutex);
-}
-
-static SlideShow *
+static GnomeBGSlideShow *
read_slideshow_file (const char *filename,
GError **err)
{
- GMarkupParser parser = {
- handle_start_element,
- handle_end_element,
- handle_text,
- NULL, /* passthrough */
- NULL, /* error */
- };
-
- GFile *file;
- char *contents = NULL;
- gsize len;
- SlideShow *show = NULL;
- GMarkupParseContext *context = NULL;
- time_t t;
-
- if (!filename)
- return NULL;
-
- file = g_file_new_for_path (filename);
- if (!g_file_load_contents (file, NULL, &contents, &len, NULL, NULL)) {
- g_object_unref (file);
- return NULL;
- }
- g_object_unref (file);
-
- show = g_new0 (SlideShow, 1);
- show->ref_count = 1;
- threadsafe_localtime ((time_t)0, &show->start_tm);
- show->stack = g_queue_new ();
- show->slides = g_queue_new ();
-
- context = g_markup_parse_context_new (&parser, 0, show, NULL);
-
- if (!g_markup_parse_context_parse (context, contents, len, err)) {
- slideshow_unref (show);
- show = NULL;
- }
-
+ GnomeBGSlideShow *show;
- if (show) {
- if (!g_markup_parse_context_end_parse (context, err)) {
- slideshow_unref (show);
- show = NULL;
- }
- }
-
- g_markup_parse_context_free (context);
+ show = gnome_bg_slide_show_new (filename);
- if (show) {
- int len;
-
- t = mktime (&show->start_tm);
-
- show->start_time = (double)t;
-
- dump_bg (show);
-
- len = g_queue_get_length (show->slides);
-
- /* no slides, that's not a slideshow */
- if (len == 0) {
- slideshow_unref (show);
- show = NULL;
- /* one slide, there's no transition */
- } else if (len == 1) {
- Slide *slide = show->slides->head->data;
- slide->duration = show->total_duration = G_MAXUINT;
- }
- }
+ if (!gnome_bg_slide_show_load (show, err)) {
+ g_object_unref (show);
+ return NULL;
+ }
- g_free (contents);
-
- return show;
+ return show;
}
/* Thumbnail utilities */
@@ -3071,25 +2629,19 @@ get_thumb_annotations (GdkPixbuf *thumb,
return FALSE;
}
-static gboolean
-slideshow_has_multiple_sizes (SlideShow *show)
-{
- return show->has_multiple_sizes;
-}
-
/*
* Returns whether the background is a slideshow.
*/
gboolean
gnome_bg_changes_with_time (GnomeBG *bg)
{
- SlideShow *show;
+ GnomeBGSlideShow *show;
g_return_val_if_fail (bg != NULL, FALSE);
show = get_as_slideshow (bg, bg->filename);
if (show)
- return g_queue_get_length (show->slides) > 1;
+ return gnome_bg_slide_show_get_num_slides (show) > 1;
return FALSE;
}
@@ -3112,12 +2664,12 @@ gnome_bg_create_frame_thumbnail (GnomeBG *bg,
int dest_height,
int frame_num)
{
- SlideShow *show;
+ GnomeBGSlideShow *show;
GdkPixbuf *result;
GdkPixbuf *thumb;
GList *l;
- int i, skipped;
- gboolean found;
+ int skipped;
+ gboolean is_fixed;
g_return_val_if_fail (bg != NULL, FALSE);
@@ -3127,27 +2679,17 @@ gnome_bg_create_frame_thumbnail (GnomeBG *bg,
return NULL;
- if (frame_num < 0 || frame_num >= g_queue_get_length (show->slides))
+ if (frame_num < 0 || frame_num >= gnome_bg_slide_show_get_num_slides (show))
return NULL;
- i = 0;
- skipped = 0;
- found = FALSE;
- for (l = show->slides->head; l; l = l->next) {
- Slide *slide = l->data;
- if (!slide->fixed) {
- skipped++;
- continue;
- }
- if (i == frame_num) {
- found = TRUE;
- break;
- }
- i++;
- }
- if (!found)
- return NULL;
+ gnome_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, NULL, NULL, &is_fixed,
NULL, NULL);
+
+ skipped = 0;
+ while (!is_fixed) {
+ skipped++;
+ gnome_bg_slide_show_get_slide (show, frame_num, dest_width, dest_height, NULL, NULL, &is_fixed,
NULL, NULL);
+ }
result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, dest_width, dest_height);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]