[Swfdec] 15 commits - configure.ac doc/Makefile.am doc/swfdec-docs.sgml doc/swfdec-sections.txt doc/swfdec.types libswfdec-gtk/.gitignore libswfdec-gtk/Makefile.am libswfdec-gtk/swfdec-gtk.h libswfdec-gtk/swfdec_gtk_player.c libswfdec-gtk/swfdec_gtk_player.h libswfdec-gtk/swfdec_gtk_widget.c libswfdec-gtk/swfdec_gtk_widget.h libswfdec-gtk/swfdec_playback_alsa.c libswfdec-gtk/swfdec_playback.h libswfdec-gtk/swfdec_playback_none.c libswfdec-gtk/swfdec_source.c libswfdec-gtk/swfdec_source.h libswfdec/js libswfdec/Makefile.am Makefile.am player/.gitignore player/Makefile.am player/swfdebug.c player/swfdec_debug_widget.c player/swfdec_debug_widget.h player/swfdec_playback_alsa.c player/swfdec_playback.h player/swfdec_playback_none.c player/swfdec_player_manager.c player/swfdec_source.c player/swfdec_source.h player/swfdec_widget.c player/swfdec_widget.h player/swfplay.c swfdec-gtk.pc.in test/image test/Makefile.am test/sound test/trace test/various

Benjamin Otte company at kemper.freedesktop.org
Mon Mar 26 09:56:06 PDT 2007


 Makefile.am                          |   10 
 configure.ac                         |   51 +-
 doc/Makefile.am                      |   16 
 doc/swfdec-docs.sgml                 |    7 
 doc/swfdec-sections.txt              |   53 ++
 doc/swfdec.types                     |    2 
 libswfdec-gtk/.gitignore             |   14 
 libswfdec-gtk/Makefile.am            |   40 +
 libswfdec-gtk/swfdec-gtk.h           |   17 
 libswfdec-gtk/swfdec_gtk_player.c    |  338 ++++++++++++++++
 libswfdec-gtk/swfdec_gtk_player.h    |   56 ++
 libswfdec-gtk/swfdec_gtk_widget.c    |  717 +++++++++++++++++++++++++++++++++++
 libswfdec-gtk/swfdec_gtk_widget.h    |   73 +++
 libswfdec-gtk/swfdec_playback.h      |    8 
 libswfdec-gtk/swfdec_playback_alsa.c |   25 -
 libswfdec-gtk/swfdec_playback_none.c |    4 
 libswfdec-gtk/swfdec_source.c        |    9 
 libswfdec-gtk/swfdec_source.h        |    2 
 libswfdec/Makefile.am                |    4 
 libswfdec/js/Makefile.am             |    2 
 player/.gitignore                    |    2 
 player/Makefile.am                   |   39 -
 player/swfdebug.c                    |    9 
 player/swfdec_debug_widget.c         |   25 -
 player/swfdec_debug_widget.h         |    8 
 player/swfdec_player_manager.c       |    2 
 player/swfdec_widget.c               |  450 ---------------------
 player/swfdec_widget.h               |   73 ---
 player/swfplay.c                     |   46 --
 swfdec-gtk.pc.in                     |   11 
 test/Makefile.am                     |   24 -
 test/image/Makefile.am               |    4 
 test/sound/Makefile.am               |    4 
 test/trace/Makefile.am               |    4 
 test/various/Makefile.am             |    8 
 35 files changed, 1474 insertions(+), 683 deletions(-)

New commits:
diff-tree 58cd315b3b41e451e7f94b282e8a4fe8e787069e (from 18bb6f82cd25bee7c1786cecc6051bf5c4574e56)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 18:55:39 2007 +0200

    add a default header

diff --git a/libswfdec-gtk/Makefile.am b/libswfdec-gtk/Makefile.am
index b787c6e..93b6897 100644
--- a/libswfdec-gtk/Makefile.am
+++ b/libswfdec-gtk/Makefile.am
@@ -29,6 +29,7 @@ libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_LDF
 	$(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
 libswfdec_ at SWFDEC_MAJORMINOR@includedir = $(includedir)/swfdec- at SWFDEC_MAJORMINOR@/libswfdec
 libswfdec_ at SWFDEC_MAJORMINOR@include_HEADERS = \
+	swfdec-gtk.h \
 	swfdec_gtk_player.h \
 	swfdec_gtk_widget.h
 
diff --git a/libswfdec-gtk/swfdec-gtk.h b/libswfdec-gtk/swfdec-gtk.h
new file mode 100644
index 0000000..c9a0ac8
--- /dev/null
+++ b/libswfdec-gtk/swfdec-gtk.h
@@ -0,0 +1,26 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SWFDEC_GTK_H__
+#define __SWFDEC_GTK_H__
+
+#include <libswfdec-gtk/swfdec_gtk_player.h>
+#include <libswfdec-gtk/swfdec_gtk_widget.h>
+
+#endif
diff-tree 18bb6f82cd25bee7c1786cecc6051bf5c4574e56 (from 56b33194342c5635e12adeb2e02f6badf4ebba30)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 18:55:22 2007 +0200

    enable audio playback by default

diff --git a/libswfdec-gtk/swfdec_gtk_player.c b/libswfdec-gtk/swfdec_gtk_player.c
index 92d8231..475cd3f 100644
--- a/libswfdec-gtk/swfdec_gtk_player.c
+++ b/libswfdec-gtk/swfdec_gtk_player.c
@@ -152,6 +152,7 @@ static void
 swfdec_gtk_player_init (SwfdecGtkPlayer * player)
 {
   player->speed = 1.0;
+  player->audio_enabled = TRUE;
 }
 
 /*** PUBLIC API ***/
diff-tree 56b33194342c5635e12adeb2e02f6badf4ebba30 (from cc49873efa4dec9ef12869809050f102ec9d4998)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 18:52:44 2007 +0200

    update to use SwfdecGtkPlayer

diff --git a/player/swfplay.c b/player/swfplay.c
index 0a3805c..db08066 100644
--- a/player/swfplay.c
+++ b/player/swfplay.c
@@ -24,14 +24,10 @@
 #include <math.h>
 #include <libswfdec/swfdec.h>
 
-#include <libswfdec-gtk/swfdec_playback.h>
-#include <libswfdec-gtk/swfdec_source.h>
-#include <libswfdec-gtk/swfdec_gtk_widget.h>
+#include <libswfdec-gtk/swfdec-gtk.h>
 
 #include "swfdec_slow_loader.h"
 
-static gpointer playback;
-
 static void
 set_title (GtkWindow *window, const char *filename)
 {
@@ -61,20 +57,6 @@ view_swf (SwfdecPlayer *player, double s
 }
 
 static void
-play_swf (SwfdecPlayer *player, double speed)
-{
-  GSource *source;
-
-  source = swfdec_iterate_source_new (player, speed);
-  g_source_attach (source, NULL);
-
-  gtk_main ();
-
-  g_source_destroy (source);
-  g_source_unref (source);
-}
-
-static void
 print_trace (SwfdecPlayer *player, const char *message, gpointer unused)
 {
   g_print ("%s\n", message);
@@ -133,7 +115,7 @@ main (int argc, char *argv[])
     g_error_free (error);
     return 1;
   }
-  player = swfdec_player_new ();
+  player = swfdec_gtk_player_new ();
   if (trace)
     g_signal_connect (player, "trace", G_CALLBACK (print_trace), NULL);
   
@@ -149,18 +131,16 @@ main (int argc, char *argv[])
     return 1;
   }
 
+  if (no_sound)
+    swfdec_gtk_player_set_audio (SWFDEC_GTK_PLAYER (player), FALSE);
+
+  swfdec_gtk_player_set_speed (SWFDEC_GTK_PLAYER (player), speed / 100.);
+  swfdec_gtk_player_set_playing (SWFDEC_GTK_PLAYER (player), TRUE);
+
   window = view_swf (player, scale, use_image);
   set_title (GTK_WINDOW (window), argv[1]);
 
-  if (no_sound || speed != 100) {
-    playback = NULL;
-  } else {
-    playback = swfdec_playback_open (player, g_main_context_default ());
-  }
-  play_swf (player, speed / 100.);
-
-  if (playback)
-    swfdec_playback_close (playback);
+  gtk_main ();
 
   g_object_unref (player);
   player = NULL;
diff-tree cc49873efa4dec9ef12869809050f102ec9d4998 (from f0088c36f8e0f02c6a850e3d7bb53695ba972ab5)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 18:45:09 2007 +0200

    update the docs for SwfdecGtkPlayer

diff --git a/doc/Makefile.am b/doc/Makefile.am
index d9700aa..0b037de 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -109,6 +109,7 @@ IGNORE_HFILES= \
 	swfdec_xml.h
 
 EXTRA_HFILES = \
+	../libswfdec-gtk/swfdec_gtk_player.h \
 	../libswfdec-gtk/swfdec_gtk_widget.h
 
 # Images to copy into HTML directory.
diff --git a/doc/swfdec-docs.sgml b/doc/swfdec-docs.sgml
index 432547b..e5b1d71 100644
--- a/doc/swfdec-docs.sgml
+++ b/doc/swfdec-docs.sgml
@@ -8,6 +8,7 @@
 
   <chapter>
     <title>Swfdec Gtk library</title>
+    <xi:include href="xml/SwfdecGtkPlayer.xml"/>
     <xi:include href="xml/SwfdecGtkWidget.xml"/>
   </chapter>
   <chapter>
diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt
index 942f73c..f33b594 100644
--- a/doc/swfdec-sections.txt
+++ b/doc/swfdec-sections.txt
@@ -108,6 +108,29 @@ swfdec_mouse_cursor_get_type
 
 
 <SECTION>
+<FILE>SwfdecGtkPlayer</FILE>
+<TITLE>SwfdecGtkPlayer</TITLE>
+SwfdecGtkPlayer
+swfdec_gtk_player_new
+swfdec_gtk_player_new_from_file
+swfdec_gtk_player_get_playing
+swfdec_gtk_player_set_playing
+swfdec_gtk_player_get_speed
+swfdec_gtk_player_set_speed
+swfdec_gtk_player_get_audio
+swfdec_gtk_player_set_audio
+<SUBSECTION Standard>
+SwfdecGtkPlayerClass
+swfdec_gtk_player_get_type
+SWFDEC_GTK_PLAYER
+SWFDEC_GTK_PLAYER_CLASS
+SWFDEC_GTK_PLAYER_GET_CLASS
+SWFDEC_IS_GTK_PLAYER
+SWFDEC_IS_GTK_PLAYER_CLASS
+SWFDEC_TYPE_GTK_PLAYER
+</SECTION>
+
+<SECTION>
 <FILE>SwfdecGtkWidget</FILE>
 <TITLE>SwfdecGtkWidget</TITLE>
 SwfdecGtkWidget
diff --git a/doc/swfdec.types b/doc/swfdec.types
index c3030f0..dbd39e4 100644
--- a/doc/swfdec.types
+++ b/doc/swfdec.types
@@ -3,4 +3,6 @@
 swfdec_player_get_type
 swfdec_audio_get_type
 swfdec_loader_get_type
+swfdec_gtk_player_get_type
+swfdec_gtk_widget_get_type
 
diff-tree f0088c36f8e0f02c6a850e3d7bb53695ba972ab5 (from a7771114e2f618c43b3758797e1bcea6c5ce9dc7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 18:44:50 2007 +0200

    Add SwfdecGtkPlayer
    
    It's basically a SwfdecPlayer that integrates into the main loop and does audio playback

diff --git a/libswfdec-gtk/Makefile.am b/libswfdec-gtk/Makefile.am
index 1c35f3e..b787c6e 100644
--- a/libswfdec-gtk/Makefile.am
+++ b/libswfdec-gtk/Makefile.am
@@ -13,6 +13,7 @@ lib_LTLIBRARIES = libswfdec-gtk- at SWFDEC_
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
 	swfdec_playback.c \
 	swfdec_source.c \
+	swfdec_gtk_player.c \
 	swfdec_gtk_widget.c
 
 noinst_HEADERS = \
@@ -21,13 +22,14 @@ noinst_HEADERS = \
 
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
 	$(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) $(AUDIO_CFLAGS) \
-	-DG_LOG_DOMAIN=\"Swfdec-Gtk\"
+	-DG_LOG_DOMAIN=\"Swfdec-Gtk\" -DXP_UNIX
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
 	-version-info $(SWFDEC_LIBVERSION) \
 	-export-symbols-regex '^(swfdec_.*)' \
 	$(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
 libswfdec_ at SWFDEC_MAJORMINOR@includedir = $(includedir)/swfdec- at SWFDEC_MAJORMINOR@/libswfdec
 libswfdec_ at SWFDEC_MAJORMINOR@include_HEADERS = \
+	swfdec_gtk_player.h \
 	swfdec_gtk_widget.h
 
 endif
diff --git a/libswfdec-gtk/swfdec_gtk_player.c b/libswfdec-gtk/swfdec_gtk_player.c
new file mode 100644
index 0000000..92d8231
--- /dev/null
+++ b/libswfdec-gtk/swfdec_gtk_player.c
@@ -0,0 +1,337 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <libswfdec/swfdec_player_internal.h>
+#include "libswfdec-gtk/swfdec_gtk_player.h"
+#include "libswfdec-gtk/swfdec_playback.h"
+#include "libswfdec-gtk/swfdec_source.h"
+
+struct _SwfdecGtkPlayer
+{
+  SwfdecPlayer		player;
+
+  GSource *		source;		/* source if playing, NULL otherwise */
+  SwfdecPlayback *	playback;	/* audio playback object */
+  gboolean		audio_enabled;	/* TRUE if audio should be played */
+  double		speed;		/* desired playback speed */
+};
+
+struct _SwfdecGtkPlayerClass
+{
+  SwfdecPlayerClass   	player_class;
+};
+
+enum {
+  PROP_0,
+  PROP_PLAYING,
+  PROP_AUDIO,
+  PROP_SPEED
+};
+
+/*** gtk-doc ***/
+
+/**
+ * SECTION:SwfdecGtkPlayer
+ * @title: SwfdecGtkPlayer
+ * @short_description: an improved #SwfdecPlayer
+ *
+ * The #SwfdecGtkPlayer adds common functionality to the rather barebones 
+ * #SwfdecPlayer class, such as automatic playback and audio handling. Note 
+ * that by default, the player will be paused, so you need to call 
+ * swfdec_gtk_player_set_playing () on the new player.
+ *
+ * @see_also: SwfdecPlayer
+ */
+
+/**
+ * SwfdecGtkPlayer:
+ *
+ * The structure for the Swfdec Gtk player contains no public fields.
+ */
+
+/*** SWFDEC_GTK_PLAYER ***/
+
+G_DEFINE_TYPE (SwfdecGtkPlayer, swfdec_gtk_player, SWFDEC_TYPE_PLAYER)
+
+static void
+swfdec_gtk_player_get_property (GObject *object, guint param_id, GValue *value, 
+    GParamSpec * pspec)
+{
+  SwfdecGtkPlayer *player = SWFDEC_GTK_PLAYER (object);
+  
+  switch (param_id) {
+    case PROP_PLAYING:
+      g_value_set_boolean (value, player->source != NULL);
+      break;
+    case PROP_AUDIO:
+      g_value_set_boolean (value, player->audio_enabled);
+      break;
+    case PROP_SPEED:
+      g_value_set_double (value, player->speed);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_gtk_player_set_property (GObject *object, guint param_id, const GValue *value,
+    GParamSpec *pspec)
+{
+  SwfdecGtkPlayer *player = SWFDEC_GTK_PLAYER (object);
+  
+  switch (param_id) {
+    case PROP_PLAYING:
+      swfdec_gtk_player_set_playing (player, g_value_get_boolean (value));
+      break;
+    case PROP_AUDIO:
+      swfdec_gtk_player_set_audio (player, g_value_get_boolean (value));
+      break;
+    case PROP_SPEED:
+      swfdec_gtk_player_set_speed (player, g_value_get_double (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_gtk_player_dispose (GObject *object)
+{
+  SwfdecGtkPlayer *player = SWFDEC_GTK_PLAYER (object);
+
+  swfdec_gtk_player_set_playing (player, FALSE);
+  g_assert (player->playback == NULL);
+
+  G_OBJECT_CLASS (swfdec_gtk_player_parent_class)->dispose (object);
+}
+
+static void
+swfdec_gtk_player_class_init (SwfdecGtkPlayerClass * g_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
+
+  object_class->dispose = swfdec_gtk_player_dispose;
+  object_class->get_property = swfdec_gtk_player_get_property;
+  object_class->set_property = swfdec_gtk_player_set_property;
+
+  g_object_class_install_property (object_class, PROP_PLAYING,
+      g_param_spec_boolean ("playing", "playing", "TRUE if the player is playing (d'oh)",
+	  FALSE, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_AUDIO,
+      g_param_spec_boolean ("audio-enabled", "audio enabled", "TRUE if automatic audio handling is enabled",
+	  TRUE, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_SPEED,
+      g_param_spec_double ("speed", "speed", "desired playback speed",
+	  G_MINDOUBLE, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE));
+}
+
+static void
+swfdec_gtk_player_init (SwfdecGtkPlayer * player)
+{
+  player->speed = 1.0;
+}
+
+/*** PUBLIC API ***/
+
+/**
+ * swfdec_gtk_player_new:
+ *
+ * Creates a new Swfdec Gtk player.
+ * This function calls swfdec_init () for you if it wasn't called before.
+ *
+ * Returns: The new player
+ **/
+SwfdecPlayer *
+swfdec_gtk_player_new (void)
+{
+  SwfdecPlayer *player;
+
+  swfdec_init ();
+  player = g_object_new (SWFDEC_TYPE_GTK_PLAYER, NULL);
+
+  return player;
+}
+
+/**
+ * swfdec_gtk_player_new_from_file:
+ * @filename: name of the file to play
+ * @error: return location for error or %NULL
+ *
+ * Tries to create a player to play back the given file. If the file does not
+ * exist or another error occurs, %NULL is returned.
+ * This function calls swfdec_init () for you if it wasn't called before.
+ *
+ * Returns: a new player or %NULL on error.
+ **/
+SwfdecPlayer *
+swfdec_player_new_from_file (const char *filename, GError **error)
+{
+  SwfdecLoader *loader;
+  SwfdecPlayer *player;
+
+  g_return_val_if_fail (filename != NULL, NULL);
+
+  loader = swfdec_loader_new_from_file (filename, error);
+  if (loader == NULL)
+    return NULL;
+  player = swfdec_gtk_player_new ();
+  swfdec_player_set_loader (player, loader);
+
+  return player;
+}
+
+static void
+swfdec_gtk_player_update_audio (SwfdecGtkPlayer *player)
+{
+  gboolean should_play = player->audio_enabled;
+  
+  should_play &= (player->source != NULL);
+  should_play &= (player->speed == 1.0);
+
+  if (should_play && player->playback == NULL) {
+    player->playback = swfdec_playback_open (SWFDEC_PLAYER (player),
+	g_main_context_default ());
+  } else if (!should_play && player->playback != NULL) {
+    swfdec_playback_close (player->playback);
+    player->playback = NULL;
+  }
+}
+
+/**
+ * swfdec_gtk_player_set_playing:
+ * @player: a #SwfdecGtkPlayer
+ * @playing: if the player should play or not
+ *
+ * Sets if @player should be playing or not. If the player is playing, a timer 
+ * will be attached to the default main loop that periodically calls 
+ * swfdec_player_advance().
+ **/
+void
+swfdec_gtk_player_set_playing (SwfdecGtkPlayer *player, gboolean playing)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_PLAYER (player));
+
+  if (playing && player->source == NULL) {
+    player->source = swfdec_iterate_source_new (SWFDEC_PLAYER (player), player->speed);
+    g_source_attach (player->source, NULL);
+  } else if (!playing && player->source != NULL) {
+    g_source_destroy (player->source);
+    g_source_unref (player->source);
+  }
+  swfdec_gtk_player_update_audio (player);
+  g_object_notify (G_OBJECT (player), "playing");
+}
+
+/**
+ * swfdec_gtk_player_get_playing:
+ * @player: a #SwfdecGtkPlayer
+ *
+ * Queries if the player is playing.
+ *
+ * Returns: %TRUE if the player is playing
+ **/
+gboolean
+swfdec_gtk_player_get_playing (SwfdecGtkPlayer *player)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_PLAYER (player), FALSE);
+
+  return player->source != NULL;
+}
+
+/**
+ * swfdec_gtk_player_set_audio:
+ * @player: a #SwfdecGtkPlayer
+ * @enabled: %TRUE to enable audio
+ *
+ * Enables or disables automatic audio playback.
+ **/
+void
+swfdec_gtk_player_set_audio (SwfdecGtkPlayer *player, gboolean enabled)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_PLAYER (player));
+
+  if (player->audio_enabled == enabled)
+    return;
+  player->audio_enabled = enabled;
+  swfdec_gtk_player_update_audio (player);
+  g_object_notify (G_OBJECT (player), "audio-enabled");
+}
+
+/**
+ * swfdec_gtk_player_get_audio:
+ * @player: a #SwfdecGtkPlayer
+ *
+ * Queries if audio playback for @player is enabled or not.
+ *
+ * Returns: %TRUE if audio playback is enabled
+ **/
+gboolean
+swfdec_gtk_player_get_audio (SwfdecGtkPlayer *player)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_PLAYER (player), FALSE);
+
+  return player->audio_enabled;
+}
+
+/**
+ * swfdec_gtk_player_set_speed:
+ * @player: a #SwfdecGtkPlayer
+ * @speed: the new playback speed
+ *
+ * Sets the new playback speed. 1.0 means the default speed, bigger values
+ * make playback happen faster. Audio will only play back if the speed is 
+ * 1.0. Note that if the player is not playing when calling this function,
+ * it will not automatically start.
+ **/
+void
+swfdec_gtk_player_set_speed (SwfdecGtkPlayer *player, double speed)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_PLAYER (player));
+  g_return_if_fail (speed > 0.0);
+
+  player->speed = speed;
+  swfdec_gtk_player_update_audio (player);
+  if (player->source)
+    swfdec_iterate_source_set_speed (player->source, player->speed);
+  g_object_notify (G_OBJECT (player), "speed");
+}
+
+/**
+ * swfdec_gtk_player_get_speed:
+ * @player: a #SwfdecGtkPlayer
+ *
+ * Queries the current playback speed. If the player is currently paused, it
+ * will report the speed that it would use if playing.
+ *
+ * Returns: the current playback speed.
+ **/
+double
+swfdec_gtk_player_get_speed (SwfdecGtkPlayer *player)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_PLAYER (player), FALSE);
+
+  return player->speed;
+}
diff --git a/libswfdec-gtk/swfdec_gtk_player.h b/libswfdec-gtk/swfdec_gtk_player.h
new file mode 100644
index 0000000..c5a9c17
--- /dev/null
+++ b/libswfdec-gtk/swfdec_gtk_player.h
@@ -0,0 +1,56 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_GTK_PLAYER_H_
+#define _SWFDEC_GTK_PLAYER_H_
+
+#include <libswfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecGtkPlayer SwfdecGtkPlayer;
+typedef struct _SwfdecGtkPlayerClass SwfdecGtkPlayerClass;
+
+#define SWFDEC_TYPE_GTK_PLAYER                    (swfdec_gtk_player_get_type())
+#define SWFDEC_IS_GTK_PLAYER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GTK_PLAYER))
+#define SWFDEC_IS_GTK_PLAYER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GTK_PLAYER))
+#define SWFDEC_GTK_PLAYER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GTK_PLAYER, SwfdecGtkPlayer))
+#define SWFDEC_GTK_PLAYER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GTK_PLAYER, SwfdecGtkPlayerClass))
+#define SWFDEC_GTK_PLAYER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_GTK_PLAYER, SwfdecGtkPlayerClass))
+
+GType 		swfdec_gtk_player_get_type    	(void);
+
+SwfdecPlayer *	swfdec_gtk_player_new	      	(void);
+SwfdecPlayer *	swfdec_gtk_player_new_from_file	(const char *		filename,
+			      	      		 GError **		error);
+
+void		swfdec_gtk_player_set_playing 	(SwfdecGtkPlayer *	player,
+						 gboolean		playing);
+gboolean	swfdec_gtk_player_get_playing 	(SwfdecGtkPlayer *	player);
+void		swfdec_gtk_player_set_audio	(SwfdecGtkPlayer *	player,
+						 gboolean		enabled);
+gboolean	swfdec_gtk_player_get_audio 	(SwfdecGtkPlayer *	player);
+void		swfdec_gtk_player_set_speed	(SwfdecGtkPlayer *	player,
+						 double			speed);
+double		swfdec_gtk_player_get_speed 	(SwfdecGtkPlayer *	player);
+
+
+
+G_END_DECLS
+#endif
diff-tree a7771114e2f618c43b3758797e1bcea6c5ce9dc7 (from 9d9cebe02b434c2554fb6953aa47d2a1e8e7e7f7)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 18:42:03 2007 +0200

    add swfdec_iterate_source_set_speed

diff --git a/libswfdec-gtk/swfdec_source.c b/libswfdec-gtk/swfdec_source.c
index 81e383b..f001de3 100644
--- a/libswfdec-gtk/swfdec_source.c
+++ b/libswfdec-gtk/swfdec_source.c
@@ -141,6 +141,15 @@ swfdec_iterate_source_new (SwfdecPlayer 
   return (GSource *) source;
 }
 
+void
+swfdec_iterate_source_set_speed (GSource *source, double speed)
+{
+  /* FIXME: need a return_if_fail if wrong source? */
+  g_return_if_fail (speed > 0.0);
+
+  ((SwfdecIterateSource *) source)->speed = 1.0 / speed;
+}
+
 guint
 swfdec_iterate_add (SwfdecPlayer *player)
 {
diff --git a/libswfdec-gtk/swfdec_source.h b/libswfdec-gtk/swfdec_source.h
index 4321d6d..0c7c383 100644
--- a/libswfdec-gtk/swfdec_source.h
+++ b/libswfdec-gtk/swfdec_source.h
@@ -26,6 +26,8 @@ G_BEGIN_DECLS
 
 GSource *	swfdec_iterate_source_new	(SwfdecPlayer *		player,
 						 double			speed);
+void		swfdec_iterate_source_set_speed (GSource *		source,
+						 double			speed);
 guint		swfdec_iterate_add		(SwfdecPlayer *		player);
 
 G_END_DECLS
diff-tree 9d9cebe02b434c2554fb6953aa47d2a1e8e7e7f7 (from 1eb5785b0e4e1440f9bae4b6e74f761a6672c82a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 17:43:46 2007 +0200

    hack to convince gtk-doc to read two subdirs for docs

diff --git a/doc/Makefile.am b/doc/Makefile.am
index d373503..d9700aa 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -33,7 +33,7 @@ SCAN_OPTIONS=
 
 # Extra options to supply to gtkdoc-mkdb.
 # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
-MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS=--sgml-mode --output-format=xml --source-dir=../libswfdec-gtk
 
 # Extra options to supply to gtkdoc-mktmpl
 # e.g. MKTMPL_OPTIONS=--only-section-tmpl
diff-tree 1eb5785b0e4e1440f9bae4b6e74f761a6672c82a (from c2006dbbccaac8dda324afc39691536a95e7cb47)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 17:43:10 2007 +0200

    Add API docs

diff --git a/libswfdec-gtk/swfdec_gtk_widget.c b/libswfdec-gtk/swfdec_gtk_widget.c
index 84bddf1..dcd39a0 100644
--- a/libswfdec-gtk/swfdec_gtk_widget.c
+++ b/libswfdec-gtk/swfdec_gtk_widget.c
@@ -40,11 +40,36 @@ struct _SwfdecGtkWidgetPrivate
 enum {
   PROP_0,
   PROP_PLAYER,
+  PROP_SCALE,
   PROP_INTERACTIVE,
   PROP_RENDERER_SET,
   PROP_RENDERER
 };
 
+/*** gtk-doc ***/
+
+/**
+ * SECTION:SwfdecGtkWidget
+ * @title: SwfdecGtkWidget
+ * @short_description: a #GtkWidget for embedding SWF files
+ *
+ * This is a widget for playing Flash movies rendered with Swfdec in a Gtk 
+ * application. It supports a lot of advanced features, if you want to use
+ * them. If you don't want to use them and just want to embed a movie in 
+ * your application, swfdec_gtk_widget_new() will probably be the only 
+ * function you need.
+ *
+ * @see_also: SwfdecGtkPlayer
+ */
+
+/**
+ * SwfdecGtkWidget:
+ *
+ * The structure for the Swfdec Gtk widget contains no public fields.
+ */
+
+/*** SWFDEC_GTK_WIDGET ***/
+
 G_DEFINE_TYPE (SwfdecGtkWidget, swfdec_gtk_widget, GTK_TYPE_WIDGET)
 
 static gboolean
@@ -168,6 +193,9 @@ swfdec_gtk_widget_get_property (GObject 
     case PROP_PLAYER:
       g_value_set_object (value, priv->player);
       break;
+    case PROP_SCALE:
+      g_value_set_double (value, priv->set_scale);
+      break;
     case PROP_INTERACTIVE:
       g_value_set_boolean (value, priv->interactive);
       break;
@@ -194,6 +222,9 @@ swfdec_gtk_widget_set_property (GObject 
     case PROP_PLAYER:
       swfdec_gtk_widget_set_player (widget, g_value_get_object (value));
       break;
+    case PROP_SCALE:
+      swfdec_gtk_widget_set_scale (widget, g_value_get_double (value));
+      break;
     case PROP_INTERACTIVE:
       swfdec_gtk_widget_set_interactive (widget, g_value_get_boolean (value));
       break;
@@ -291,7 +322,10 @@ swfdec_gtk_widget_update_cursor (SwfdecG
 
   if (window == NULL)
     return;
-  g_object_get (priv->player, "mouse-cursor", &swfcursor, NULL);
+  if (priv->interactive)
+    swfcursor = SWFDEC_MOUSE_CURSOR_NORMAL;
+  else
+    g_object_get (priv->player, "mouse-cursor", &swfcursor, NULL);
 
   switch (swfcursor) {
     case SWFDEC_MOUSE_CURSOR_NONE:
@@ -379,6 +413,9 @@ swfdec_gtk_widget_class_init (SwfdecGtkW
   g_object_class_install_property (object_class, PROP_PLAYER,
       g_param_spec_object ("player", "player", "player that is displayed",
 	  SWFDEC_TYPE_PLAYER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_SCALE,
+      g_param_spec_double ("scale", "scale", "scale factor to use or 0.0 for automatic",
+	  0.0, G_MAXDOUBLE, 0.0, G_PARAM_READWRITE));
   g_object_class_install_property (object_class, PROP_INTERACTIVE,
       g_param_spec_boolean ("interactive", "interactive", "if mouse events are processed",
 	  TRUE, G_PARAM_READWRITE));
@@ -440,6 +477,15 @@ swfdec_gtk_widget_notify_cb (SwfdecPlaye
   }
 }
 
+/*** PUBLIC API ***/
+
+/**
+ * swfdec_gtk_widget_set_player:
+ * @widget: a #SwfdecGtkWidget
+ * @player: the #SwfdecPlayer to display or %NULL for none
+ *
+ * Sets the new player to display in @widget.
+ **/
 void
 swfdec_gtk_widget_set_player (SwfdecGtkWidget *widget, SwfdecPlayer *player)
 {
@@ -467,6 +513,14 @@ swfdec_gtk_widget_set_player (SwfdecGtkW
   g_object_notify (G_OBJECT (widget), "player");
 }
 
+/**
+ * swfdec_gtk_widget_get_player:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Gets the player that is currently played back in this @widget.
+ *
+ * Returns: the #SwfdecPlayer or %NULL if none
+ **/
 SwfdecPlayer *
 swfdec_gtk_widget_get_player (SwfdecGtkWidget *widget)
 {
@@ -475,6 +529,14 @@ swfdec_gtk_widget_get_player (SwfdecGtkW
   return widget->priv->player;
 }
 
+/**
+ * swfdec_gtk_widget_new:
+ * @player: a #SwfdecPlayer or %NULL
+ *
+ * Creates a new #SwfdecGtkWidget to display @player.
+ *
+ * Returns: the new widget that displays @player
+ **/
 GtkWidget *
 swfdec_gtk_widget_new (SwfdecPlayer *player)
 {
@@ -487,6 +549,14 @@ swfdec_gtk_widget_new (SwfdecPlayer *pla
   return GTK_WIDGET (widget);
 }
 
+/**
+ * swfdec_gtk_widget_set_scale:
+ * @widget: a #SwfdecGtkWidget
+ * @scale: scale factor to use or 0 for automatic
+ *
+ * Sets the scale factor to use. If you set @scale to 0, the movie is displayed
+ * as big as the window is.
+ **/
 void
 swfdec_gtk_widget_set_scale (SwfdecGtkWidget *widget, double scale)
 {
@@ -495,8 +565,18 @@ swfdec_gtk_widget_set_scale (SwfdecGtkWi
 
   widget->priv->set_scale = scale;
   gtk_widget_queue_resize (GTK_WIDGET (widget));
+  g_object_notify (G_OBJECT (widget), "scale");
 }
 
+/**
+ * swfdec_gtk_widget_get_scale:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Gets the user-set scale factor for this @widget. If you want the scale 
+ * factor that is currently in effect, use swfdec_gtk_widget_get_current_scale().
+ *
+ * Returns: The current scale factor or 0.0 if automatic.
+ **/
 double
 swfdec_gtk_widget_get_scale (SwfdecGtkWidget *widget)
 {
@@ -505,6 +585,17 @@ swfdec_gtk_widget_get_scale (SwfdecGtkWi
   return widget->priv->set_scale;
 }
 
+/**
+ * swfdec_gtk_widget_get_current_scale:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Queries the current scale factor in use. The returned value is undefined 
+ * if the widget has not been allocated a size. This value is only different 
+ * from the value returned by swfdec_gtk_widget_get_scale(), if automatic 
+ * scaling is in effect.
+ *
+ * Returns: The current scale factor.
+ **/
 double
 swfdec_gtk_widget_get_current_scale (SwfdecGtkWidget *widget)
 {
@@ -513,14 +604,34 @@ swfdec_gtk_widget_get_current_scale (Swf
   return widget->priv->real_scale;
 }
 
+/**
+ * swfdec_gtk_widget_set_interactive:
+ * @widget: a #SwfdecGtkWidget
+ * @interactive: %TRUE to make the widget interactive
+ *
+ * Sets the widget to be interactive or not. An interactive widget processes 
+ * mouse and keyboard events, while a non-interactive widget does not care about
+ * user input. Widgets are interactive by default.
+ **/
 void
 swfdec_gtk_widget_set_interactive (SwfdecGtkWidget *widget, gboolean interactive)
 {
   g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
 
   widget->priv->interactive = interactive;
+  swfdec_gtk_widget_update_cursor (widget);
+  g_object_notify (G_OBJECT (widget), "interactive");
 }
 
+/**
+ * swfdec_gtk_widget_get_interactive:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Queries if the @widget is currently interactive. See 
+ * swfdec_gtk_widget_set_interactive() for details.
+ *
+ * Returns: %TRUE if the widget is interactive, %FALSE otherwise.
+ **/
 gboolean
 swfdec_gtk_widget_get_interactive (SwfdecGtkWidget *widget)
 {
@@ -529,6 +640,15 @@ swfdec_gtk_widget_get_interactive (Swfde
   return widget->priv->interactive;
 }
 
+/**
+ * swfdec_gtk_widget_set_renderer:
+ * @widget: a #SwfdecGtkWidget
+ * @renderer: a #cairo_surface_type_t for the intermediate renderer
+ *
+ * Tells @widget to use an intermediate surface for rendering. This is
+ * useful for debugging or performance measurements inside swfdec and is 
+ * probably not interesting for anyone else.
+ **/
 void
 swfdec_gtk_widget_set_renderer (SwfdecGtkWidget *widget, cairo_surface_type_t renderer)
 {
@@ -542,6 +662,13 @@ swfdec_gtk_widget_set_renderer (SwfdecGt
   g_object_notify (G_OBJECT (widget), "renderer");
 }
 
+/**
+ * swfdec_gtk_widget_unset_renderer:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Unsets the use of an intermediate rendering surface. See 
+ * swfdec_gtk_widget_set_renderer() for details.
+ **/
 void
 swfdec_gtk_widget_unset_renderer (SwfdecGtkWidget *widget)
 {
@@ -553,6 +680,16 @@ swfdec_gtk_widget_unset_renderer (Swfdec
   g_object_notify (G_OBJECT (widget), "renderer-set");
 }
 
+/**
+ * swfdec_gtk_widget_get_renderer:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Gets the intermediate renderer that is or would be in use by @widget. Use
+ * swfdec_gtk_widget_uses_renderer() to check if an intermediate renderer is in
+ * use. See swfdec_gtk_widget_set_renderer() for details.
+ *
+ * Returns: the type of the intermediate renderer
+ **/
 cairo_surface_type_t
 swfdec_gtk_widget_get_renderer (SwfdecGtkWidget *widget)
 {
@@ -561,6 +698,15 @@ swfdec_gtk_widget_get_renderer (SwfdecGt
   return widget->priv->renderer;
 }
 
+/**
+ * swfdec_gtk_widget_uses_renderer:
+ * @widget: a #SwfdecGtkWidget
+ *
+ * Queries if an intermediate renderer set via swfdec_gtk_widget_set_renderer()
+ * is currently in use.
+ *
+ * Returns: %TRUE if an intermediate renderer is used.
+ **/
 gboolean
 swfdec_gtk_widget_uses_renderer (SwfdecGtkWidget *widget)
 {
diff --git a/libswfdec-gtk/swfdec_gtk_widget.h b/libswfdec-gtk/swfdec_gtk_widget.h
index fa9580e..c7799ed 100644
--- a/libswfdec-gtk/swfdec_gtk_widget.h
+++ b/libswfdec-gtk/swfdec_gtk_widget.h
@@ -39,12 +39,13 @@ struct _SwfdecGtkWidget
 {
   GtkWidget			widget;
 
+  /*< private >*/
   SwfdecGtkWidgetPrivate *	priv;
 };
 
 struct _SwfdecGtkWidgetClass
 {
-  GtkWidgetClass	widget_class;
+  GtkWidgetClass		widget_class;
 };
 
 GType		swfdec_gtk_widget_get_type		(void);
diff-tree c2006dbbccaac8dda324afc39691536a95e7cb47 (from 5c55ebf25f01e1e43276df79e1ca08a5decd2f05)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 17:42:33 2007 +0200

    Use a SwfdecPlayback struct instead of gpointer
    
    makes gcc catch more errors

diff --git a/libswfdec-gtk/swfdec_playback.h b/libswfdec-gtk/swfdec_playback.h
index 8b894cf..8be67dd 100644
--- a/libswfdec-gtk/swfdec_playback.h
+++ b/libswfdec-gtk/swfdec_playback.h
@@ -24,10 +24,12 @@
 
 G_BEGIN_DECLS
 
-gpointer	swfdec_playback_open	(SwfdecPlayer *	player,
-					 GMainContext *	context);
+typedef struct _SwfdecPlayback SwfdecPlayback;
 
-void		swfdec_playback_close	(gpointer	sound);
+SwfdecPlayback *swfdec_playback_open	(SwfdecPlayer *		player,
+					 GMainContext *		context);
+
+void		swfdec_playback_close	(SwfdecPlayback *	sound);
 
 G_END_DECLS
 #endif
diff --git a/libswfdec-gtk/swfdec_playback_alsa.c b/libswfdec-gtk/swfdec_playback_alsa.c
index ea47099..8160f1c 100644
--- a/libswfdec-gtk/swfdec_playback_alsa.c
+++ b/libswfdec-gtk/swfdec_playback_alsa.c
@@ -22,7 +22,7 @@
 #endif
 
 #include <alsa/asoundlib.h>
-#include "swfdec_source.h"
+#include "swfdec_playback.h"
 
 /* Why ALSA sucks for beginners:
  * - snd_pcm_delay is not sample-exact, but period-exact most of the time.
@@ -41,14 +41,14 @@
 
 /*** DEFINITIONS ***/
 
-typedef struct {
+struct _SwfdecPlayback {
   SwfdecPlayer *	player;
   GList *		streams;	/* all Stream objects */
   GMainContext *	context;	/* context we work in */
-} Sound;
+};
 
 typedef struct {
-  Sound *		sound;		/* reference to sound object */
+  SwfdecPlayback *     	sound;		/* reference to sound object */
   SwfdecAudio *		audio;		/* the audio we play back */
   snd_pcm_t *		pcm;		/* the pcm we play back to */
   GSource **		sources;	/* sources for writing data */
@@ -193,7 +193,7 @@ swfdec_stream_start (Stream *stream)
 }
 
 static void
-swfdec_stream_open (Sound *sound, SwfdecAudio *audio)
+swfdec_stream_open (SwfdecPlayback *sound, SwfdecAudio *audio)
 {
   Stream *stream;
   snd_pcm_t *ret;
@@ -274,7 +274,7 @@ swfdec_stream_close (Stream *stream)
 static void
 advance_before (SwfdecPlayer *player, guint msecs, guint audio_samples, gpointer data)
 {
-  Sound *sound = data;
+  SwfdecPlayback *sound = data;
   GList *walk;
 
   for (walk = sound->streams; walk; walk = walk->next) {
@@ -288,13 +288,13 @@ advance_before (SwfdecPlayer *player, gu
 }
 
 static void
-audio_added (SwfdecPlayer *player, SwfdecAudio *audio, Sound *sound)
+audio_added (SwfdecPlayer *player, SwfdecAudio *audio, SwfdecPlayback *sound)
 {
   swfdec_stream_open (sound, audio);
 }
 
 static void
-audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, Sound *sound)
+audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, SwfdecPlayback *sound)
 {
   GList *walk;
 
@@ -308,16 +308,16 @@ audio_removed (SwfdecPlayer *player, Swf
   g_assert_not_reached ();
 }
 
-gpointer
+SwfdecPlayback *
 swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
 {
-  Sound *sound;
+  SwfdecPlayback *sound;
   const GList *walk;
 
   g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
   g_return_val_if_fail (context != NULL, NULL);
 
-  sound = g_new0 (Sound, 1);
+  sound = g_new0 (SwfdecPlayback, 1);
   sound->player = g_object_ref (player);
   g_signal_connect (player, "advance", G_CALLBACK (advance_before), sound);
   g_signal_connect (player, "audio-added", G_CALLBACK (audio_added), sound);
@@ -331,9 +331,8 @@ swfdec_playback_open (SwfdecPlayer *play
 }
 
 void
-swfdec_playback_close (gpointer data)
+swfdec_playback_close (SwfdecPlayback *sound)
 {
-  Sound *sound = data;
 #define REMOVE_HANDLER_FULL(obj,func,data,count) G_STMT_START {\
   if (g_signal_handlers_disconnect_by_func ((obj), \
 	G_CALLBACK (func), (data)) != (count)) { \
diff --git a/libswfdec-gtk/swfdec_playback_none.c b/libswfdec-gtk/swfdec_playback_none.c
index 6464a4a..79651d6 100644
--- a/libswfdec-gtk/swfdec_playback_none.c
+++ b/libswfdec-gtk/swfdec_playback_none.c
@@ -25,14 +25,14 @@
 
 /* STUBS ONLY - audio is disabled */
 
-gpointer
+SwfdecPlayback *
 swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
 {
   return GINT_TO_POINTER (-1);
 }
 
 void
-swfdec_playback_close (gpointer sound)
+swfdec_playback_close (SwfdecPlayback *sound)
 {
   g_assert (sound == GINT_TO_POINTER (-1));
 }
diff-tree 5c55ebf25f01e1e43276df79e1ca08a5decd2f05 (from d88f4665b965a124dad44a70fa1ca859340cd59c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 16:51:19 2007 +0200

    hook up libswfdec-gtk

diff --git a/doc/Makefile.am b/doc/Makefile.am
index fdb3962..d373503 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -25,7 +25,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sg
 DOC_SOURCE_DIR=../libswfdec
 
 # Extra options to pass to gtkdoc-scangobj. Not normally needed.
-SCANGOBJ_OPTIONS=--type-init-func="swfdec_init()" 
+SCANGOBJ_OPTIONS=--type-init-func="swfdec_init(); gtk_init (NULL, NULL);" 
 
 # Extra options to supply to gtkdoc-scan.
 # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" 
@@ -46,8 +46,8 @@ FIXXREF_OPTIONS=
 # Used for dependencies. The docs will be rebuilt if any of these change.
 # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
 # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
-HFILE_GLOB=$(top_srcdir)/libswfdec/*.h
-CFILE_GLOB=$(top_srcdir)/libswfdec/*.c
+HFILE_GLOB=$(top_srcdir)/libswfdec/*.h $(top_srcdir)/libswfdec-gtk/*.h
+CFILE_GLOB=$(top_srcdir)/libswfdec/*.c $(top_srcdir)/libswfdec-gtk/*.c
 
 # Header files to ignore when scanning.
 # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
@@ -108,6 +108,9 @@ IGNORE_HFILES= \
 	swfdec_video_movie.h \
 	swfdec_xml.h
 
+EXTRA_HFILES = \
+	../libswfdec-gtk/swfdec_gtk_widget.h
+
 # Images to copy into HTML directory.
 # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
 HTML_IMAGES=
@@ -126,8 +129,8 @@ expand_content_files=
 # signals and properties.
 # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-INCLUDES=$(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
-GTKDOC_LIBS=$(SWFDEC_LIBS)
+INCLUDES=$(SWFDEC_GTK_CFLAGS) $(CAIRO_CFLAGS)
+GTKDOC_LIBS=$(SWFDEC_GTK_LIBS)
 
 # This includes the standard gtk-doc make rules, copied by gtkdocize.
 include $(top_srcdir)/gtk-doc.make
diff --git a/doc/swfdec-docs.sgml b/doc/swfdec-docs.sgml
index 64e00e5..432547b 100644
--- a/doc/swfdec-docs.sgml
+++ b/doc/swfdec-docs.sgml
@@ -7,7 +7,11 @@
   </bookinfo>
 
   <chapter>
-    <title>Public API</title>
+    <title>Swfdec Gtk library</title>
+    <xi:include href="xml/SwfdecGtkWidget.xml"/>
+  </chapter>
+  <chapter>
+    <title>Swfdec library</title>
     <xi:include href="xml/Enumerations.xml"/>
     <xi:include href="xml/SwfdecPlayer.xml"/>
     <xi:include href="xml/SwfdecAudio.xml"/>
diff --git a/doc/swfdec-sections.txt b/doc/swfdec-sections.txt
index f8a4514..942f73c 100644
--- a/doc/swfdec-sections.txt
+++ b/doc/swfdec-sections.txt
@@ -77,7 +77,7 @@ SwfdecBufferQueue
 swfdec_buffer_new
 swfdec_buffer_new_and_alloc
 swfdec_buffer_new_and_alloc0
-swfdec_buffer_new_with_data
+swfdec_buffer_new_for_data
 swfdec_buffer_new_subbuffer
 swfdec_buffer_new_from_file
 swfdec_buffer_ref
@@ -105,3 +105,31 @@ swfdec_loader_data_type_get_type
 SWFDEC_TYPE_MOUSE_CURSOR
 swfdec_mouse_cursor_get_type
 </SECTION>
+
+
+<SECTION>
+<FILE>SwfdecGtkWidget</FILE>
+<TITLE>SwfdecGtkWidget</TITLE>
+SwfdecGtkWidget
+swfdec_gtk_widget_new
+swfdec_gtk_widget_get_player
+swfdec_gtk_widget_set_player
+swfdec_gtk_widget_get_current_scale
+swfdec_gtk_widget_get_scale
+swfdec_gtk_widget_set_scale
+swfdec_gtk_widget_get_interactive
+swfdec_gtk_widget_set_interactive
+swfdec_gtk_widget_get_renderer
+swfdec_gtk_widget_uses_renderer
+swfdec_gtk_widget_set_renderer
+swfdec_gtk_widget_unset_renderer
+<SUBSECTION Standard>
+swfdec_gtk_widget_get_type
+SwfdecGtkWidgetClass
+SwfdecGtkWidgetPrivate
+SWFDEC_GTK_WIDGET
+SWFDEC_GTK_WIDGET_CLASS
+SWFDEC_IS_GTK_WIDGET
+SWFDEC_IS_GTK_WIDGET_CLASS
+SWFDEC_TYPE_GTK_WIDGET
+</SECTION>
diff-tree d88f4665b965a124dad44a70fa1ca859340cd59c (from ad94392c93f6855d01fff706ba7d4827e01082c8)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 16:50:57 2007 +0200

    apparently I can't name functions correctly

diff --git a/libswfdec-gtk/swfdec_gtk_widget.c b/libswfdec-gtk/swfdec_gtk_widget.c
index 3f393cc..84bddf1 100644
--- a/libswfdec-gtk/swfdec_gtk_widget.c
+++ b/libswfdec-gtk/swfdec_gtk_widget.c
@@ -543,7 +543,7 @@ swfdec_gtk_widget_set_renderer (SwfdecGt
 }
 
 void
-swfdec_gtk_player_unset_renderer (SwfdecGtkWidget *widget)
+swfdec_gtk_widget_unset_renderer (SwfdecGtkWidget *widget)
 {
   g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
 
diff --git a/libswfdec-gtk/swfdec_gtk_widget.h b/libswfdec-gtk/swfdec_gtk_widget.h
index a808da3..fa9580e 100644
--- a/libswfdec-gtk/swfdec_gtk_widget.h
+++ b/libswfdec-gtk/swfdec_gtk_widget.h
@@ -60,7 +60,7 @@ double		swfdec_gtk_widget_get_scale		(Sw
 double		swfdec_gtk_widget_get_current_scale   	(SwfdecGtkWidget *	widget);
 void		swfdec_gtk_widget_set_renderer		(SwfdecGtkWidget *	widget,
 							 cairo_surface_type_t	renderer);
-void		swfdec_gtk_player_unset_renderer	(SwfdecGtkWidget *      widget);
+void		swfdec_gtk_widget_unset_renderer	(SwfdecGtkWidget *      widget);
 cairo_surface_type_t
 		swfdec_gtk_widget_get_renderer		(SwfdecGtkWidget *	widget);
 gboolean	swfdec_gtk_widget_uses_renderer		(SwfdecGtkWidget *	widget);
diff-tree ad94392c93f6855d01fff706ba7d4827e01082c8 (from 5956357f5cba90936a1aa15934957155400d272c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 16:26:46 2007 +0200

    prepare the gtk widget for exporting its API

diff --git a/libswfdec-gtk/Makefile.am b/libswfdec-gtk/Makefile.am
index c9756be..1c35f3e 100644
--- a/libswfdec-gtk/Makefile.am
+++ b/libswfdec-gtk/Makefile.am
@@ -13,12 +13,11 @@ lib_LTLIBRARIES = libswfdec-gtk- at SWFDEC_
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
 	swfdec_playback.c \
 	swfdec_source.c \
-	swfdec_widget.c
+	swfdec_gtk_widget.c
 
 noinst_HEADERS = \
 	swfdec_playback.h \
-	swfdec_source.h \
-	swfdec_widget.h
+	swfdec_source.h
 
 libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
 	$(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) $(AUDIO_CFLAGS) \
@@ -27,6 +26,9 @@ libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_LDF
 	-version-info $(SWFDEC_LIBVERSION) \
 	-export-symbols-regex '^(swfdec_.*)' \
 	$(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
+libswfdec_ at SWFDEC_MAJORMINOR@includedir = $(includedir)/swfdec- at SWFDEC_MAJORMINOR@/libswfdec
+libswfdec_ at SWFDEC_MAJORMINOR@include_HEADERS = \
+	swfdec_gtk_widget.h
 
 endif
 
diff --git a/libswfdec-gtk/swfdec_gtk_widget.c b/libswfdec-gtk/swfdec_gtk_widget.c
new file mode 100644
index 0000000..3f393cc
--- /dev/null
+++ b/libswfdec-gtk/swfdec_gtk_widget.c
@@ -0,0 +1,571 @@
+/* Swfdec
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include <libswfdec-gtk/swfdec_gtk_widget.h>
+
+struct _SwfdecGtkWidgetPrivate
+{
+  SwfdecPlayer *	player;		/* the video we play */
+
+  double		real_scale;	/* the real scale factor used */
+  double		set_scale;    	/* the set scale factor of the video */
+  gboolean		renderer_set;	/* TRUE if a special renderer has been set */
+  cairo_surface_type_t	renderer;	/* the renderer that was set */
+  gboolean		interactive;	/* if this gtk_widget propagates keyboard and mouse events */
+
+  int			button;		/* status of mouse button in displayed movie */
+};
+
+enum {
+  PROP_0,
+  PROP_PLAYER,
+  PROP_INTERACTIVE,
+  PROP_RENDERER_SET,
+  PROP_RENDERER
+};
+
+G_DEFINE_TYPE (SwfdecGtkWidget, swfdec_gtk_widget, GTK_TYPE_WIDGET)
+
+static gboolean
+swfdec_gtk_widget_motion_notify (GtkWidget *gtkwidget, GdkEventMotion *event)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+  int x, y;
+
+  gdk_window_get_pointer (gtkwidget->window, &x, &y, NULL);
+
+  if (priv->interactive)
+    swfdec_player_handle_mouse (priv->player, 
+	x / priv->real_scale, y / priv->real_scale, priv->button);
+  
+  return FALSE;
+}
+
+static gboolean
+swfdec_gtk_widget_leave_notify (GtkWidget *gtkwidget, GdkEventCrossing *event)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+
+  if (priv->interactive) {
+    priv->button = 0;
+    swfdec_player_handle_mouse (priv->player, 
+	event->x / priv->real_scale, event->y / priv->real_scale, 0);
+  }
+  return FALSE;
+}
+
+static gboolean
+swfdec_gtk_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+
+  if (event->button == 1) {
+    priv->button = 1;
+    if (priv->interactive)
+      swfdec_player_handle_mouse (priv->player, 
+	  event->x / priv->real_scale, event->y / priv->real_scale, 1);
+  }
+  return FALSE;
+}
+
+static gboolean
+swfdec_gtk_widget_button_release (GtkWidget *gtkwidget, GdkEventButton *event)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+
+  if (event->button == 1) {
+    priv->button = 0;
+    if (priv->interactive)
+      swfdec_player_handle_mouse (priv->player, 
+	  event->x / priv->real_scale, event->y / priv->real_scale, 0);
+  }
+  return FALSE;
+}
+
+static cairo_surface_t *
+swfdec_gtk_widget_create_renderer (cairo_surface_type_t type, int width, int height)
+{
+  switch (type) {
+    case CAIRO_SURFACE_TYPE_IMAGE:
+      return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+    default:
+      break;
+  }
+
+  return NULL;
+}
+
+static gboolean
+swfdec_gtk_widget_expose (GtkWidget *gtkwidget, GdkEventExpose *event)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+  cairo_t *cr;
+  cairo_surface_t *surface = NULL;
+
+  if (event->window != gtkwidget->window)
+    return FALSE;
+
+  if (!priv->renderer_set ||
+      (surface = swfdec_gtk_widget_create_renderer (priv->renderer, 
+	      event->area.width, event->area.height)) == NULL) {
+    cr = gdk_cairo_create (gtkwidget->window);
+  } else {
+    cr = cairo_create (surface);
+    cairo_translate (cr, -event->area.x, -event->area.y);
+  }
+  cairo_scale (cr, priv->real_scale, priv->real_scale);
+  swfdec_player_render (priv->player, cr,
+      event->area.x / priv->real_scale, event->area.y / priv->real_scale, 
+      event->area.width / priv->real_scale, event->area.height / priv->real_scale);
+  cairo_show_page (cr);
+  cairo_destroy (cr);
+
+  if (surface) {
+    cairo_t *crw = gdk_cairo_create (gtkwidget->window);
+    cairo_set_source_surface (crw, surface, event->area.x, event->area.y);
+    cairo_paint (crw);
+    cairo_destroy (crw);
+    cairo_surface_destroy (surface);
+  }
+
+  return FALSE;
+}
+
+static void
+swfdec_gtk_widget_get_property (GObject *object, guint param_id, GValue *value, 
+    GParamSpec * pspec)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (object);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+  
+  switch (param_id) {
+    case PROP_PLAYER:
+      g_value_set_object (value, priv->player);
+      break;
+    case PROP_INTERACTIVE:
+      g_value_set_boolean (value, priv->interactive);
+      break;
+    case PROP_RENDERER_SET:
+      g_value_set_boolean (value, priv->renderer_set);
+      break;
+    case PROP_RENDERER:
+      g_value_set_uint (value, priv->renderer);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_gtk_widget_set_property (GObject *object, guint param_id, const GValue *value,
+    GParamSpec *pspec)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (object);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+  
+  switch (param_id) {
+    case PROP_PLAYER:
+      swfdec_gtk_widget_set_player (widget, g_value_get_object (value));
+      break;
+    case PROP_INTERACTIVE:
+      swfdec_gtk_widget_set_interactive (widget, g_value_get_boolean (value));
+      break;
+    case PROP_RENDERER_SET:
+      priv->renderer_set = g_value_get_boolean (value);
+      gtk_widget_queue_draw (GTK_WIDGET (widget));
+      break;
+    case PROP_RENDERER:
+      priv->renderer = g_value_get_uint (value);
+      if (priv->renderer_set)
+	gtk_widget_queue_draw (GTK_WIDGET (widget));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_gtk_widget_dispose (GObject *object)
+{
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (object);
+
+  swfdec_gtk_widget_set_player (widget, NULL);
+
+  G_OBJECT_CLASS (swfdec_gtk_widget_parent_class)->dispose (object);
+}
+
+static void
+swfdec_gtk_widget_size_allocate (GtkWidget *gtkwidget, GtkAllocation *allocation)
+{
+  double scale;
+  int w, h;
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+
+  gtkwidget->allocation = *allocation;
+
+  swfdec_player_get_image_size (priv->player, &w, &h);
+  if (priv->set_scale > 0.0) {
+    scale = priv->set_scale;
+  } else if (priv->player == NULL) {
+    scale = 1.0;
+  } else {
+    if (w != 0 && h != 0)
+      scale = MIN ((double) allocation->width / w, (double) allocation->height / h);
+    else
+      scale = 1.0;
+  }
+  w = ceil (w * scale);
+  h = ceil (h * scale);
+  if (w > allocation->width)
+    w = allocation->width;
+  if (h > allocation->height)
+    h = allocation->height;
+
+  if (GTK_WIDGET_REALIZED (gtkwidget)) {
+    gdk_window_move_resize (gtkwidget->window, 
+	allocation->x + (allocation->width - w) / 2,
+	allocation->y + (allocation->height - h) / 2,
+	w, h);
+  }
+  priv->real_scale = scale;
+}
+
+static void
+swfdec_gtk_widget_size_request (GtkWidget *gtkwidget, GtkRequisition *req)
+{
+  double scale;
+  SwfdecGtkWidget * widget = SWFDEC_GTK_WIDGET (gtkwidget);
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+
+  if (priv->player == NULL) {
+    req->width = req->height = 0;
+  } else {
+    swfdec_player_get_image_size (priv->player, 
+	  &req->width, &req->height);
+  } 
+  if (priv->set_scale != 0.0)
+    scale = priv->set_scale;
+  else
+    scale = 1.0;
+  req->width = ceil (req->width * scale);
+  req->height = ceil (req->height * scale);
+}
+
+static void
+swfdec_gtk_widget_update_cursor (SwfdecGtkWidget *widget)
+{
+  GdkWindow *window = GTK_WIDGET (widget)->window;
+  GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (widget));
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+  SwfdecMouseCursor swfcursor;
+  GdkCursor *cursor;
+
+  if (window == NULL)
+    return;
+  g_object_get (priv->player, "mouse-cursor", &swfcursor, NULL);
+
+  switch (swfcursor) {
+    case SWFDEC_MOUSE_CURSOR_NONE:
+      {
+	GdkBitmap *bitmap;
+	GdkColor color = { 0, 0, 0, 0 };
+	char data = 0;
+
+	bitmap = gdk_bitmap_create_from_data (window, &data, 1, 1);
+	if (bitmap == NULL)
+	  return;
+	cursor = gdk_cursor_new_from_pixmap (bitmap, bitmap, &color, &color, 0, 0);
+	gdk_window_set_cursor (window, cursor);
+	gdk_cursor_unref (cursor);
+	g_object_unref (bitmap);
+	break;
+      }
+    case SWFDEC_MOUSE_CURSOR_TEXT:
+      cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+      gdk_window_set_cursor (window, cursor);
+      gdk_cursor_unref (cursor);
+      break;
+    case SWFDEC_MOUSE_CURSOR_CLICK:
+      cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+      gdk_window_set_cursor (window, cursor);
+      gdk_cursor_unref (cursor);
+      break;
+    case SWFDEC_MOUSE_CURSOR_NORMAL:
+      cursor = gdk_cursor_new_for_display (display, GDK_LEFT_PTR);
+      gdk_window_set_cursor (window, cursor);
+      gdk_cursor_unref (cursor);
+      break;
+    default:
+      g_warning ("invalid cursor %d", (int) swfcursor);
+      gdk_window_set_cursor (window, NULL);
+      break;
+  }
+}
+
+static void
+swfdec_gtk_widget_realize (GtkWidget *widget)
+{
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x;
+  attributes.y = widget->allocation.y;
+  attributes.width = widget->allocation.width;
+  attributes.height = widget->allocation.height;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |= GDK_EXPOSURE_MASK | 
+			   GDK_BUTTON_PRESS_MASK |
+			   GDK_BUTTON_RELEASE_MASK |
+			   GDK_LEAVE_NOTIFY_MASK | 
+			   GDK_POINTER_MOTION_MASK | 
+			   GDK_POINTER_MOTION_HINT_MASK;
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+      &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, widget);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
+
+  if (SWFDEC_GTK_WIDGET (widget)->priv->player) {
+    swfdec_gtk_widget_update_cursor (SWFDEC_GTK_WIDGET (widget));
+  }
+}
+
+static void
+swfdec_gtk_widget_class_init (SwfdecGtkWidgetClass * g_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (g_class);
+
+  object_class->dispose = swfdec_gtk_widget_dispose;
+  object_class->get_property = swfdec_gtk_widget_get_property;
+  object_class->set_property = swfdec_gtk_widget_set_property;
+
+  g_object_class_install_property (object_class, PROP_PLAYER,
+      g_param_spec_object ("player", "player", "player that is displayed",
+	  SWFDEC_TYPE_PLAYER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+  g_object_class_install_property (object_class, PROP_INTERACTIVE,
+      g_param_spec_boolean ("interactive", "interactive", "if mouse events are processed",
+	  TRUE, G_PARAM_READWRITE));
+  g_object_class_install_property (object_class, PROP_RENDERER_SET,
+      g_param_spec_boolean ("renderer-set", "renderer set", "if an intermediate renderer should be used",
+	  TRUE, G_PARAM_READWRITE));
+  /* FIXME: get an enum for cairo_surface_type_t */
+  g_object_class_install_property (object_class, PROP_RENDERER,
+      g_param_spec_uint ("renderer", "renderer", "cairo_surface_type_t of intermediate renderer to use",
+	  0, G_MAXUINT, CAIRO_SURFACE_TYPE_IMAGE, G_PARAM_READWRITE));
+
+  widget_class->realize = swfdec_gtk_widget_realize;
+  widget_class->size_request = swfdec_gtk_widget_size_request;
+  widget_class->size_allocate = swfdec_gtk_widget_size_allocate;
+  widget_class->expose_event = swfdec_gtk_widget_expose;
+  widget_class->button_press_event = swfdec_gtk_widget_button_press;
+  widget_class->button_release_event = swfdec_gtk_widget_button_release;
+  widget_class->motion_notify_event = swfdec_gtk_widget_motion_notify;
+  widget_class->leave_notify_event = swfdec_gtk_widget_leave_notify;
+
+  g_type_class_add_private (object_class, sizeof (SwfdecGtkWidgetPrivate));
+}
+
+static void
+swfdec_gtk_widget_init (SwfdecGtkWidget * widget)
+{
+  SwfdecGtkWidgetPrivate *priv;
+  
+  priv = widget->priv = G_TYPE_INSTANCE_GET_PRIVATE (widget, SWFDEC_TYPE_GTK_WIDGET, SwfdecGtkWidgetPrivate);
+
+  priv->real_scale = 1.0;
+  priv->interactive = TRUE;
+  priv->renderer = CAIRO_SURFACE_TYPE_IMAGE;
+}
+
+static void
+swfdec_gtk_widget_invalidate_cb (SwfdecPlayer *player, double x, double y, 
+    double width, double height, SwfdecGtkWidget *widget)
+{
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+  GdkRectangle rect;
+
+  if (!GTK_WIDGET_REALIZED (widget))
+    return;
+  rect.x = floor (x * priv->real_scale);
+  rect.y = floor (y * priv->real_scale);
+  rect.width = ceil ((x + width) * priv->real_scale) - rect.x;
+  rect.height = ceil ((y + height) * priv->real_scale) - rect.y;
+  gdk_window_invalidate_rect (GTK_WIDGET (widget)->window, &rect, FALSE);
+}
+
+static void
+swfdec_gtk_widget_notify_cb (SwfdecPlayer *player, GParamSpec *pspec, SwfdecGtkWidget *widget)
+{
+  if (g_str_equal (pspec->name, "mouse-cursor")) {
+    swfdec_gtk_widget_update_cursor (widget);
+  } else if (g_str_equal (pspec->name, "initialized")) {
+    gtk_widget_queue_resize (GTK_WIDGET (widget));
+  }
+}
+
+void
+swfdec_gtk_widget_set_player (SwfdecGtkWidget *widget, SwfdecPlayer *player)
+{
+  SwfdecGtkWidgetPrivate *priv = widget->priv;
+
+  g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
+  g_return_if_fail (player == NULL || SWFDEC_IS_PLAYER (player));
+  
+  if (priv->player) {
+    g_signal_handlers_disconnect_by_func (priv->player, swfdec_gtk_widget_invalidate_cb, widget);
+    g_signal_handlers_disconnect_by_func (priv->player, swfdec_gtk_widget_notify_cb, widget);
+    g_object_unref (priv->player);
+  }
+  priv->player = player;
+  if (player) {
+    g_signal_connect (player, "invalidate", G_CALLBACK (swfdec_gtk_widget_invalidate_cb), widget);
+    g_signal_connect (player, "notify", G_CALLBACK (swfdec_gtk_widget_notify_cb), widget);
+    g_object_ref (player);
+    swfdec_gtk_widget_update_cursor (widget);
+  } else {
+    if (GTK_WIDGET (widget)->window)
+      gdk_window_set_cursor (GTK_WIDGET (widget)->window, NULL); 
+  }
+  gtk_widget_queue_resize (GTK_WIDGET (widget));
+  g_object_notify (G_OBJECT (widget), "player");
+}
+
+SwfdecPlayer *
+swfdec_gtk_widget_get_player (SwfdecGtkWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_WIDGET (widget), NULL);
+
+  return widget->priv->player;
+}
+
+GtkWidget *
+swfdec_gtk_widget_new (SwfdecPlayer *player)
+{
+  SwfdecGtkWidget *widget;
+  
+  g_return_val_if_fail (player == NULL || SWFDEC_IS_PLAYER (player), NULL);
+
+  widget = g_object_new (SWFDEC_TYPE_GTK_WIDGET, "player", player, NULL);
+
+  return GTK_WIDGET (widget);
+}
+
+void
+swfdec_gtk_widget_set_scale (SwfdecGtkWidget *widget, double scale)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
+  g_return_if_fail (scale >= 0.0);
+
+  widget->priv->set_scale = scale;
+  gtk_widget_queue_resize (GTK_WIDGET (widget));
+}
+
+double
+swfdec_gtk_widget_get_scale (SwfdecGtkWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_WIDGET (widget), 1.0);
+
+  return widget->priv->set_scale;
+}
+
+double
+swfdec_gtk_widget_get_current_scale (SwfdecGtkWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_WIDGET (widget), 1.0);
+
+  return widget->priv->real_scale;
+}
+
+void
+swfdec_gtk_widget_set_interactive (SwfdecGtkWidget *widget, gboolean interactive)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
+
+  widget->priv->interactive = interactive;
+}
+
+gboolean
+swfdec_gtk_widget_get_interactive (SwfdecGtkWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_WIDGET (widget), FALSE);
+
+  return widget->priv->interactive;
+}
+
+void
+swfdec_gtk_widget_set_renderer (SwfdecGtkWidget *widget, cairo_surface_type_t renderer)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
+
+  widget->priv->renderer = renderer;
+  if (widget->priv->renderer_set == FALSE) {
+    widget->priv->renderer_set = TRUE;
+    g_object_notify (G_OBJECT (widget), "renderer-set");
+  }
+  g_object_notify (G_OBJECT (widget), "renderer");
+}
+
+void
+swfdec_gtk_player_unset_renderer (SwfdecGtkWidget *widget)
+{
+  g_return_if_fail (SWFDEC_IS_GTK_WIDGET (widget));
+
+  if (widget->priv->renderer_set == FALSE)
+    return;
+  widget->priv->renderer_set = FALSE;
+  g_object_notify (G_OBJECT (widget), "renderer-set");
+}
+
+cairo_surface_type_t
+swfdec_gtk_widget_get_renderer (SwfdecGtkWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_WIDGET (widget), CAIRO_SURFACE_TYPE_IMAGE);
+
+  return widget->priv->renderer;
+}
+
+gboolean
+swfdec_gtk_widget_uses_renderer (SwfdecGtkWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_GTK_WIDGET (widget), FALSE);
+
+  return widget->priv->renderer_set;
+}
+
diff --git a/libswfdec-gtk/swfdec_gtk_widget.h b/libswfdec-gtk/swfdec_gtk_widget.h
new file mode 100644
index 0000000..a808da3
--- /dev/null
+++ b/libswfdec-gtk/swfdec_gtk_widget.h
@@ -0,0 +1,72 @@
+/* Swfdec
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_GTK_WIDGET_H_
+#define _SWFDEC_GTK_WIDGET_H_
+
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecGtkWidget SwfdecGtkWidget;
+typedef struct _SwfdecGtkWidgetClass SwfdecGtkWidgetClass;
+typedef struct _SwfdecGtkWidgetPrivate SwfdecGtkWidgetPrivate;
+
+#define SWFDEC_TYPE_GTK_WIDGET                    (swfdec_gtk_widget_get_type())
+#define SWFDEC_IS_GTK_WIDGET(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_GTK_WIDGET))
+#define SWFDEC_IS_GTK_WIDGET_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_GTK_WIDGET))
+#define SWFDEC_GTK_WIDGET(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_GTK_WIDGET, SwfdecGtkWidget))
+#define SWFDEC_GTK_WIDGET_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_GTK_WIDGET, SwfdecGtkWidgetClass))
+
+struct _SwfdecGtkWidget
+{
+  GtkWidget			widget;
+
+  SwfdecGtkWidgetPrivate *	priv;
+};
+
+struct _SwfdecGtkWidgetClass
+{
+  GtkWidgetClass	widget_class;
+};
+
+GType		swfdec_gtk_widget_get_type		(void);
+
+GtkWidget *	swfdec_gtk_widget_new			(SwfdecPlayer *		player);
+
+void		swfdec_gtk_widget_set_player		(SwfdecGtkWidget *	widget,
+							 SwfdecPlayer *		player);
+SwfdecPlayer *	swfdec_gtk_widget_get_player		(SwfdecGtkWidget *	widget);
+void		swfdec_gtk_widget_set_scale		(SwfdecGtkWidget *	widget,
+							 double			scale);
+double		swfdec_gtk_widget_get_scale		(SwfdecGtkWidget *	widget);
+double		swfdec_gtk_widget_get_current_scale   	(SwfdecGtkWidget *	widget);
+void		swfdec_gtk_widget_set_renderer		(SwfdecGtkWidget *	widget,
+							 cairo_surface_type_t	renderer);
+void		swfdec_gtk_player_unset_renderer	(SwfdecGtkWidget *      widget);
+cairo_surface_type_t
+		swfdec_gtk_widget_get_renderer		(SwfdecGtkWidget *	widget);
+gboolean	swfdec_gtk_widget_uses_renderer		(SwfdecGtkWidget *	widget);
+void		swfdec_gtk_widget_set_interactive	(SwfdecGtkWidget *	widget,
+							 gboolean		interactive);
+gboolean	swfdec_gtk_widget_get_interactive	(SwfdecGtkWidget *	widget);
+
+G_END_DECLS
+#endif
diff --git a/libswfdec-gtk/swfdec_widget.c b/libswfdec-gtk/swfdec_widget.c
deleted file mode 100644
index 99b414e..0000000
--- a/libswfdec-gtk/swfdec_widget.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <math.h>
-#include "swfdec_widget.h"
-
-enum {
-  PROP_0,
-  PROP_PLAYER
-};
-
-G_DEFINE_TYPE (SwfdecWidget, swfdec_widget, GTK_TYPE_WIDGET)
-
-static gboolean
-swfdec_widget_motion_notify (GtkWidget *gtkwidget, GdkEventMotion *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-  int x, y;
-
-  gdk_window_get_pointer (gtkwidget->window, &x, &y, NULL);
-
-  if (widget->interactive)
-    swfdec_player_handle_mouse (widget->player, 
-	x / widget->real_scale, y / widget->real_scale, widget->button);
-  
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_leave_notify (GtkWidget *gtkwidget, GdkEventCrossing *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (widget->interactive) {
-    widget->button = 0;
-    swfdec_player_handle_mouse (widget->player, 
-	event->x / widget->real_scale, event->y / widget->real_scale, 0);
-  }
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (event->button == 1) {
-    widget->button = 1;
-    if (widget->interactive)
-      swfdec_player_handle_mouse (widget->player, 
-	  event->x / widget->real_scale, event->y / widget->real_scale, 1);
-  }
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_button_release (GtkWidget *gtkwidget, GdkEventButton *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (event->button == 1) {
-    widget->button = 0;
-    if (widget->interactive)
-      swfdec_player_handle_mouse (widget->player, 
-	  event->x / widget->real_scale, event->y / widget->real_scale, 0);
-  }
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_expose (GtkWidget *gtkwidget, GdkEventExpose *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-  cairo_t *cr;
-  cairo_surface_t *surface = NULL;
-
-  if (event->window != gtkwidget->window)
-    return FALSE;
-
-  if (!widget->use_image) {
-    cr = gdk_cairo_create (gtkwidget->window);
-  } else {
-    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 
-      event->area.width, event->area.height);
-    cr = cairo_create (surface);
-    cairo_translate (cr, -event->area.x, -event->area.y);
-    cairo_surface_destroy (surface);
-  }
-  cairo_scale (cr, widget->real_scale, widget->real_scale);
-  swfdec_player_render (widget->player, cr,
-      event->area.x / widget->real_scale, event->area.y / widget->real_scale, 
-      event->area.width / widget->real_scale, event->area.height / widget->real_scale);
-  if (widget->use_image) {
-    cairo_t *crw = gdk_cairo_create (gtkwidget->window);
-    cairo_set_source_surface (crw, surface, event->area.x, event->area.y);
-    cairo_paint (crw);
-    cairo_destroy (crw);
-  }
-
-  cairo_destroy (cr);
-
-  return FALSE;
-}
-
-static void
-swfdec_widget_get_property (GObject *object, guint param_id, GValue *value, 
-    GParamSpec * pspec)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (object);
-  
-  switch (param_id) {
-    case PROP_PLAYER:
-      g_value_set_object (value, widget->player);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-  }
-}
-
-static void
-swfdec_widget_set_property (GObject *object, guint param_id, const GValue *value,
-    GParamSpec *pspec)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (object);
-  
-  switch (param_id) {
-    case PROP_PLAYER:
-      swfdec_widget_set_player (widget, g_value_get_object (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-  }
-}
-
-static void
-swfdec_widget_dispose (GObject *object)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (object);
-
-  swfdec_widget_set_player (widget, NULL);
-
-  G_OBJECT_CLASS (swfdec_widget_parent_class)->dispose (object);
-}
-
-static void
-swfdec_widget_size_allocate (GtkWidget *gtkwidget, GtkAllocation *allocation)
-{
-  double scale;
-  int w, h;
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  gtkwidget->allocation = *allocation;
-
-  swfdec_player_get_image_size (widget->player, &w, &h);
-  if (widget->set_scale > 0.0) {
-    scale = widget->set_scale;
-  } else if (widget->player == NULL) {
-    scale = 1.0;
-  } else {
-    if (w != 0 && h != 0)
-      scale = MIN ((double) allocation->width / w, (double) allocation->height / h);
-    else
-      scale = 1.0;
-  }
-  w = ceil (w * scale);
-  h = ceil (h * scale);
-  if (w > allocation->width)
-    w = allocation->width;
-  if (h > allocation->height)
-    h = allocation->height;
-
-  if (GTK_WIDGET_REALIZED (gtkwidget)) {
-    gdk_window_move_resize (gtkwidget->window, 
-	allocation->x + (allocation->width - w) / 2,
-	allocation->y + (allocation->height - h) / 2,
-	w, h);
-  }
-  widget->real_scale = scale;
-}
-
-static void
-swfdec_widget_size_request (GtkWidget *gtkwidget, GtkRequisition *req)
-{
-  double scale;
-  SwfdecWidget * widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (widget->player == NULL) {
-    req->width = req->height = 0;
-  } else {
-    swfdec_player_get_image_size (widget->player, 
-	  &req->width, &req->height);
-  } 
-  if (widget->set_scale != 0.0)
-    scale = widget->set_scale;
-  else
-    scale = 1.0;
-  req->width = ceil (req->width * scale);
-  req->height = ceil (req->height * scale);
-}
-
-static void
-swfdec_widget_update_cursor (SwfdecWidget *widget)
-{
-  GdkWindow *window = GTK_WIDGET (widget)->window;
-  GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (widget));
-  SwfdecMouseCursor swfcursor;
-  GdkCursor *cursor;
-
-  if (window == NULL)
-    return;
-  g_object_get (widget->player, "mouse-cursor", &swfcursor, NULL);
-
-  switch (swfcursor) {
-    case SWFDEC_MOUSE_CURSOR_NONE:
-      {
-	GdkBitmap *bitmap;
-	GdkColor color = { 0, 0, 0, 0 };
-	char data = 0;
-
-	bitmap = gdk_bitmap_create_from_data (window, &data, 1, 1);
-	if (bitmap == NULL)
-	  return;
-	cursor = gdk_cursor_new_from_pixmap (bitmap, bitmap, &color, &color, 0, 0);
-	gdk_window_set_cursor (window, cursor);
-	gdk_cursor_unref (cursor);
-	g_object_unref (bitmap);
-	break;
-      }
-    case SWFDEC_MOUSE_CURSOR_TEXT:
-      cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
-      gdk_window_set_cursor (window, cursor);
-      gdk_cursor_unref (cursor);
-      break;
-    case SWFDEC_MOUSE_CURSOR_CLICK:
-      cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
-      gdk_window_set_cursor (window, cursor);
-      gdk_cursor_unref (cursor);
-      break;
-    case SWFDEC_MOUSE_CURSOR_NORMAL:
-      cursor = gdk_cursor_new_for_display (display, GDK_LEFT_PTR);
-      gdk_window_set_cursor (window, cursor);
-      gdk_cursor_unref (cursor);
-      break;
-    default:
-      g_warning ("invalid cursor %d", (int) swfcursor);
-      gdk_window_set_cursor (window, NULL);
-      break;
-  }
-}
-
-static void
-swfdec_widget_realize (GtkWidget *widget)
-{
-  GdkWindowAttr attributes;
-  gint attributes_mask;
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
-  attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = widget->allocation.x;
-  attributes.y = widget->allocation.y;
-  attributes.width = widget->allocation.width;
-  attributes.height = widget->allocation.height;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.event_mask = gtk_widget_get_events (widget);
-  attributes.event_mask |= GDK_EXPOSURE_MASK | 
-			   GDK_BUTTON_PRESS_MASK |
-			   GDK_BUTTON_RELEASE_MASK |
-			   GDK_LEAVE_NOTIFY_MASK | 
-			   GDK_POINTER_MOTION_MASK | 
-			   GDK_POINTER_MOTION_HINT_MASK;
-
-  attributes_mask = GDK_WA_X | GDK_WA_Y;
-
-  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
-      &attributes, attributes_mask);
-  gdk_window_set_user_data (widget->window, widget);
-
-  widget->style = gtk_style_attach (widget->style, widget->window);
-
-  if (SWFDEC_WIDGET (widget)->player) {
-    swfdec_widget_update_cursor (SWFDEC_WIDGET (widget));
-  }
-}
-
-static void
-swfdec_widget_class_init (SwfdecWidgetClass * g_class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (g_class);
-
-  object_class->dispose = swfdec_widget_dispose;
-  object_class->get_property = swfdec_widget_get_property;
-  object_class->set_property = swfdec_widget_set_property;
-
-  g_object_class_install_property (object_class, PROP_PLAYER,
-      g_param_spec_object ("player", "player", "player that is displayed",
-	  SWFDEC_TYPE_PLAYER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  widget_class->realize = swfdec_widget_realize;
-  widget_class->size_request = swfdec_widget_size_request;
-  widget_class->size_allocate = swfdec_widget_size_allocate;
-  widget_class->expose_event = swfdec_widget_expose;
-  widget_class->button_press_event = swfdec_widget_button_press;
-  widget_class->button_release_event = swfdec_widget_button_release;
-  widget_class->motion_notify_event = swfdec_widget_motion_notify;
-  widget_class->leave_notify_event = swfdec_widget_leave_notify;
-}
-
-static void
-swfdec_widget_init (SwfdecWidget * widget)
-{
-  widget->real_scale = 1.0;
-  widget->interactive = TRUE;
-}
-
-static void
-swfdec_widget_invalidate_cb (SwfdecPlayer *player, double x, double y, 
-    double width, double height, SwfdecWidget *widget)
-{
-  GdkRectangle rect;
-
-  if (!GTK_WIDGET_REALIZED (widget))
-    return;
-  rect.x = floor (x * widget->real_scale);
-  rect.y = floor (y * widget->real_scale);
-  rect.width = ceil ((x + width) * widget->real_scale) - rect.x;
-  rect.height = ceil ((y + height) * widget->real_scale) - rect.y;
-  gdk_window_invalidate_rect (GTK_WIDGET (widget)->window, &rect, FALSE);
-}
-
-static void
-swfdec_widget_notify_cb (SwfdecPlayer *player, GParamSpec *pspec, SwfdecWidget *widget)
-{
-  if (g_str_equal (pspec->name, "mouse-cursor")) {
-    swfdec_widget_update_cursor (widget);
-  } else if (g_str_equal (pspec->name, "initialized")) {
-    gtk_widget_queue_resize (GTK_WIDGET (widget));
-  }
-}
-
-void
-swfdec_widget_set_player (SwfdecWidget *widget, SwfdecPlayer *player)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-  g_return_if_fail (player == NULL || SWFDEC_IS_PLAYER (player));
-  
-  if (widget->player) {
-    g_signal_handlers_disconnect_by_func (widget->player, swfdec_widget_invalidate_cb, widget);
-    g_signal_handlers_disconnect_by_func (widget->player, swfdec_widget_notify_cb, widget);
-    g_object_unref (widget->player);
-  }
-  widget->player = player;
-  if (player) {
-    g_signal_connect (player, "invalidate", G_CALLBACK (swfdec_widget_invalidate_cb), widget);
-    g_signal_connect (player, "notify", G_CALLBACK (swfdec_widget_notify_cb), widget);
-    g_object_ref (player);
-    swfdec_widget_update_cursor (widget);
-  } else {
-    if (GTK_WIDGET (widget)->window)
-      gdk_window_set_cursor (GTK_WIDGET (widget)->window, NULL); 
-  }
-  gtk_widget_queue_resize (GTK_WIDGET (widget));
-}
-
-GtkWidget *
-swfdec_widget_new (SwfdecPlayer *player)
-{
-  SwfdecWidget *widget;
-  
-  g_return_val_if_fail (player == NULL || SWFDEC_IS_PLAYER (player), NULL);
-
-  widget = g_object_new (SWFDEC_TYPE_WIDGET, "player", player, NULL);
-
-  return GTK_WIDGET (widget);
-}
-
-void
-swfdec_widget_set_scale	(SwfdecWidget *widget, double scale)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-  g_return_if_fail (scale >= 0.0);
-
-  widget->set_scale = scale;
-  gtk_widget_queue_resize (GTK_WIDGET (widget));
-}
-
-double
-swfdec_widget_get_scale (SwfdecWidget *widget)
-{
-  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), 1.0);
-
-  return widget->set_scale;
-}
-
-void
-swfdec_widget_set_use_image (SwfdecWidget *widget, gboolean use_image)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-
-  widget->use_image = use_image;
-  gtk_widget_queue_draw (GTK_WIDGET (widget));
-}
-
-gboolean
-swfdec_widget_get_use_image (SwfdecWidget *widget)
-{
-  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), 1.0);
-
-  return widget->use_image;
-}
-
-void
-swfdec_widget_set_interactive (SwfdecWidget *widget, gboolean interactive)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-
-  widget->interactive = interactive;
-}
-
-gboolean
-swfdec_widget_get_interactive (SwfdecWidget *widget)
-{
-  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), FALSE);
-
-  return widget->interactive;
-}
-
diff --git a/libswfdec-gtk/swfdec_widget.h b/libswfdec-gtk/swfdec_widget.h
deleted file mode 100644
index 1988f20..0000000
--- a/libswfdec-gtk/swfdec_widget.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _SWFDEC_WIDGET_H_
-#define _SWFDEC_WIDGET_H_
-
-#include <gtk/gtk.h>
-#include <libswfdec/swfdec.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SwfdecWidget SwfdecWidget;
-typedef struct _SwfdecWidgetClass SwfdecWidgetClass;
-
-#define SWFDEC_TYPE_WIDGET                    (swfdec_widget_get_type())
-#define SWFDEC_IS_WIDGET(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_WIDGET))
-#define SWFDEC_IS_WIDGET_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_WIDGET))
-#define SWFDEC_WIDGET(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_WIDGET, SwfdecWidget))
-#define SWFDEC_WIDGET_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_WIDGET, SwfdecWidgetClass))
-
-struct _SwfdecWidget
-{
-  GtkWidget		widget;
-
-  SwfdecPlayer *	player;		/* the video we play */
-
-  double		real_scale;	/* the real scale factor used */
-  double		set_scale;    	/* the set scale factor of the video */
-  gboolean		use_image;	/* TRUE to draw to an image first before rendering to Gtk */
-  gboolean		interactive;	/* if this widget propagates keyboard and mouse events */
-
-  int			button;		/* status of mouse button in displayed movie */
-};
-
-struct _SwfdecWidgetClass
-{
-  GtkWidgetClass	widget_class;
-};
-
-GType		swfdec_widget_get_type		(void);
-
-GtkWidget *	swfdec_widget_new		(SwfdecPlayer *	player);
-
-void		swfdec_widget_set_scale		(SwfdecWidget *	widget,
-						 double		scale);
-double		swfdec_widget_get_scale		(SwfdecWidget *	widget);
-void		swfdec_widget_set_use_image	(SwfdecWidget *	widget,
-						 gboolean	use_image);
-gboolean	swfdec_widget_get_use_image	(SwfdecWidget *	widget);
-void		swfdec_widget_set_interactive	(SwfdecWidget * widget,
-						 gboolean	interactive);
-gboolean	swfdec_widget_get_interactive	(SwfdecWidget * widget);
-void		swfdec_widget_set_player	(SwfdecWidget *	widget,
-						 SwfdecPlayer *	player);
-
-G_END_DECLS
-#endif
diff --git a/player/swfdebug.c b/player/swfdebug.c
index c7f74d1..af7f7dc 100644
--- a/player/swfdebug.c
+++ b/player/swfdebug.c
@@ -118,9 +118,9 @@ message_display_cb (SwfdecPlayerManager 
 }
 
 static void
-interrupt_widget_cb (SwfdecPlayerManager *manager, GParamSpec *pspec, SwfdecWidget *widget)
+interrupt_widget_cb (SwfdecPlayerManager *manager, GParamSpec *pspec, SwfdecGtkWidget *widget)
 {
-  swfdec_widget_set_interactive (widget,
+  swfdec_gtk_widget_set_interactive (widget,
       !swfdec_player_manager_get_interrupted (manager));
 }
 
@@ -292,8 +292,9 @@ view_swf (SwfdecPlayer *player, double s
   gtk_paned_add2 (GTK_PANED (hpaned), vbox);
 
   widget = swfdec_debug_widget_new (player);
-  swfdec_widget_set_scale (SWFDEC_WIDGET (widget), scale);
-  swfdec_widget_set_use_image (SWFDEC_WIDGET (widget), use_image);
+  swfdec_gtk_widget_set_scale (SWFDEC_GTK_WIDGET (widget), scale);
+  if (use_image)
+    swfdec_gtk_widget_set_renderer (SWFDEC_GTK_WIDGET (widget), CAIRO_SURFACE_TYPE_IMAGE);
   gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
   signal_auto_connect (manager, "notify::interrupted", G_CALLBACK (interrupt_widget_cb), widget);
 
diff --git a/player/swfdec_debug_widget.c b/player/swfdec_debug_widget.c
index df5a9d5..4c7ebcc 100644
--- a/player/swfdec_debug_widget.c
+++ b/player/swfdec_debug_widget.c
@@ -25,7 +25,7 @@
 #include "swfdec_debug_widget.h"
 
 
-G_DEFINE_TYPE (SwfdecDebugWidget, swfdec_debug_widget, SWFDEC_TYPE_WIDGET)
+G_DEFINE_TYPE (SwfdecDebugWidget, swfdec_debug_widget, SWFDEC_TYPE_GTK_WIDGET)
 
 
 static gboolean
@@ -53,28 +53,30 @@ swfdec_debug_widget_invalidate_click_are
 static gboolean
 swfdec_debug_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
 {
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+  SwfdecGtkWidget *widget = SWFDEC_GTK_WIDGET (gtkwidget);
   SwfdecDebugWidget *debug = SWFDEC_DEBUG_WIDGET (gtkwidget);
 
   if (event->window != gtkwidget->window)
     return FALSE;
 
-  if (event->button == 1 && widget->interactive) {
+  if (event->button == 1 && swfdec_gtk_widget_get_interactive (widget)) {
+    double scale = swfdec_gtk_widget_get_scale (widget);
+    SwfdecPlayer *player = swfdec_gtk_widget_get_player (widget);
     switch (event->type) {
       case GDK_BUTTON_PRESS:
 	swfdec_debug_widget_invalidate_click_area (debug);
 	debug->x = event->x;
 	debug->y = event->y;
-	swfdec_player_handle_mouse (widget->player, 
-	    debug->x / widget->real_scale, debug->y / widget->real_scale, 
-	    widget->button);
+	swfdec_player_handle_mouse (player, 
+	    debug->x / scale, debug->y / scale, 
+	    debug->button);
 	swfdec_debug_widget_invalidate_click_area (debug);
 	break;
       case GDK_2BUTTON_PRESS:
-	widget->button = 1 - widget->button;
-	swfdec_player_handle_mouse (widget->player, 
-	    debug->x / widget->real_scale, debug->y / widget->real_scale, 
-	    widget->button);
+	debug->button = 1 - debug->button;
+	swfdec_player_handle_mouse (player, 
+	    debug->x / scale, debug->y / scale, 
+	    debug->button);
 	swfdec_debug_widget_invalidate_click_area (debug);
 	break;
       default:
@@ -93,7 +95,6 @@ swfdec_debug_widget_button_release (GtkW
 static gboolean
 swfdec_debug_widget_expose (GtkWidget *gtkwidget, GdkEventExpose *event)
 {
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
   SwfdecDebugWidget *debug = SWFDEC_DEBUG_WIDGET (gtkwidget);
   cairo_t *cr;
 
@@ -106,7 +107,7 @@ swfdec_debug_widget_expose (GtkWidget *g
   cr = gdk_cairo_create (gtkwidget->window);
 
   cairo_arc (cr, debug->x, debug->y, RADIUS - 1.5, 0.0, 2 * G_PI);
-  if (widget->button) {
+  if (debug->button) {
     cairo_set_source_rgba (cr, 0.25, 0.25, 0.25, 0.5);
     cairo_fill_preserve (cr);
   }
diff --git a/player/swfdec_debug_widget.h b/player/swfdec_debug_widget.h
index c11c8a4..b00117d 100644
--- a/player/swfdec_debug_widget.h
+++ b/player/swfdec_debug_widget.h
@@ -20,7 +20,7 @@
 #ifndef _SWFDEC_DEBUG_WIDGET_H_
 #define _SWFDEC_DEBUG_WIDGET_H_
 
-#include <libswfdec-gtk/swfdec_widget.h>
+#include <libswfdec-gtk/swfdec_gtk_widget.h>
 
 G_BEGIN_DECLS
 
@@ -35,15 +35,16 @@ typedef struct _SwfdecDebugWidgetClass S
 
 struct _SwfdecDebugWidget
 {
-  SwfdecWidget		widget;
+  SwfdecGtkWidget     	widget;
 
   int			x;
   int			y;
+  int			button;
 };
 
 struct _SwfdecDebugWidgetClass
 {
-  SwfdecWidgetClass	debug_widget_class;
+  SwfdecGtkWidgetClass	debug_widget_class;
 };
 
 GType		swfdec_debug_widget_get_type		(void);
diff --git a/player/swfplay.c b/player/swfplay.c
index e9d62ad..0a3805c 100644
--- a/player/swfplay.c
+++ b/player/swfplay.c
@@ -26,7 +26,7 @@
 
 #include <libswfdec-gtk/swfdec_playback.h>
 #include <libswfdec-gtk/swfdec_source.h>
-#include <libswfdec-gtk/swfdec_widget.h>
+#include <libswfdec-gtk/swfdec_gtk_widget.h>
 
 #include "swfdec_slow_loader.h"
 
@@ -49,9 +49,10 @@ view_swf (SwfdecPlayer *player, double s
   GtkWidget *window, *widget;
 
   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-  widget = swfdec_widget_new (player);
-  swfdec_widget_set_scale (SWFDEC_WIDGET (widget), scale);
-  swfdec_widget_set_use_image (SWFDEC_WIDGET (widget), use_image);
+  widget = swfdec_gtk_widget_new (player);
+  swfdec_gtk_widget_set_scale (SWFDEC_GTK_WIDGET (widget), scale);
+  if (use_image)
+    swfdec_gtk_widget_set_renderer (SWFDEC_GTK_WIDGET (widget), CAIRO_SURFACE_TYPE_IMAGE);
   gtk_container_add (GTK_CONTAINER (window), widget);
   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
   gtk_widget_show_all (window);
diff-tree 5956357f5cba90936a1aa15934957155400d272c (from a6845d55ff3420aa75dd666e70ecf5dfb4fb5dd4)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 12:46:56 2007 +0200

    movie libswfdecui to libswfdec-gtk and make libswfdec-gtk an installed library

diff --git a/configure.ac b/configure.ac
index 5ac3db0..65be1fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -122,7 +122,11 @@ if test "$with_audio" = "auto" -o "$with
   if test "$AUDIO_TYPE" = "alsa"; then
     with_audio=alsa
   else
-    AC_MSG_WARN([no alsa audio support])
+    if test "$with_audio" = "alsa"; then
+      AC_MSG_ERROR([no alsa audio support])
+    else
+      AC_MSG_WARN([no alsa audio support])
+    fi
   fi
   AUDIO_CFLAGS=$ALSA_CFLAGS
   AUDIO_LIBS=$ALSA_LIBS
@@ -207,6 +211,11 @@ SWFDEC_LIBS="\$(top_builddir)/libswfdec/
 AC_SUBST(SWFDEC_LIBS)
 AC_SUBST(SWFDEC_CFLAGS)
 
+SWFDEC_GTK_CFLAGS="$SWFDEC_CFLAGS"
+SWFDEC_GTK_LIBS="\$(top_builddir)/libswfdec-gtk/libswfdec-gtk-$SWFDEC_MAJORMINOR.la $SWFDEC_LIBS"
+AC_SUBST(SWFDEC_GTK_LIBS)
+AC_SUBST(SWFDEC_GTK_CFLAGS)
+
 GTK_DOC_CHECK([1.6])
 
 if test "x${prefix}" = "xNONE"; then
diff --git a/libswfdec-gtk/.gitignore b/libswfdec-gtk/.gitignore
index 87c0f2d..cad6c66 100644
--- a/libswfdec-gtk/.gitignore
+++ b/libswfdec-gtk/.gitignore
@@ -11,3 +11,4 @@ Makefile.in
 *.lo
 *.loT
 
+swfdec_playback.c
diff --git a/libswfdec-gtk/Makefile.am b/libswfdec-gtk/Makefile.am
index e69de29..c9756be 100644
--- a/libswfdec-gtk/Makefile.am
+++ b/libswfdec-gtk/Makefile.am
@@ -0,0 +1,35 @@
+if WITH_GTK
+
+# this workaround is needed or autotools don't generate the .deps/*.Plo files correctly
+swfdec_playback.c: swfdec_playback_$(AUDIO_TYPE).c Makefile
+	cmp -s $(srcdir)/swfdec_playback_$(AUDIO_TYPE).c swfdec_playback.c \
+	|| cp $(srcdir)/swfdec_playback_$(AUDIO_TYPE).c swfdec_playback.c
+
+BUILT_SOURCES = swfdec_playback.c
+CLEANFILES = swfdec_playback.c
+
+lib_LTLIBRARIES = libswfdec-gtk- at SWFDEC_MAJORMINOR@.la
+
+libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
+	swfdec_playback.c \
+	swfdec_source.c \
+	swfdec_widget.c
+
+noinst_HEADERS = \
+	swfdec_playback.h \
+	swfdec_source.h \
+	swfdec_widget.h
+
+libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
+	$(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) $(AUDIO_CFLAGS) \
+	-DG_LOG_DOMAIN=\"Swfdec-Gtk\"
+libswfdec_gtk_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
+	-version-info $(SWFDEC_LIBVERSION) \
+	-export-symbols-regex '^(swfdec_.*)' \
+	$(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
+
+endif
+
+EXTRA_DIST = \
+	swfdec_playback_alsa.c \
+	swfdec_playback_none.c
diff --git a/libswfdec-gtk/swfdec_playback.h b/libswfdec-gtk/swfdec_playback.h
new file mode 100644
index 0000000..8b894cf
--- /dev/null
+++ b/libswfdec-gtk/swfdec_playback.h
@@ -0,0 +1,33 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_PLAYBACK_H_
+#define _SWFDEC_PLAYBACK_H_
+
+#include <libswfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+gpointer	swfdec_playback_open	(SwfdecPlayer *	player,
+					 GMainContext *	context);
+
+void		swfdec_playback_close	(gpointer	sound);
+
+G_END_DECLS
+#endif
diff --git a/libswfdec-gtk/swfdec_playback_alsa.c b/libswfdec-gtk/swfdec_playback_alsa.c
new file mode 100644
index 0000000..ea47099
--- /dev/null
+++ b/libswfdec-gtk/swfdec_playback_alsa.c
@@ -0,0 +1,355 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <alsa/asoundlib.h>
+#include "swfdec_source.h"
+
+/* Why ALSA sucks for beginners:
+ * - snd_pcm_delay is not sample-exact, but period-exact most of the time.
+ *   Yay for getting told the time every 512 samples when a human notices
+ *   a delay of 100 samples (oooops)
+ * - lots of functions are simply not implemented. So the super-smart idea
+ *   of using snd_pcm_rewind to avoid XRUNS and still get low latency has
+ *   some issues when dmix just returns -EIO all of the time. That wouldn't
+ *   be so bad if there was actually a way to query if it's supported.
+ * - But to make up for all this, you have 10 hardware parameters, 10 
+ *   software parameters and 10 configuration parameters. All of this is
+ *   naturally supported on 10 driver APIs depending on kernel. So if your
+ *   sound card seems to do weird stuff, that is not my fault.
+ * Welcome to Linux sound in the 21st century.
+ */
+
+/*** DEFINITIONS ***/
+
+typedef struct {
+  SwfdecPlayer *	player;
+  GList *		streams;	/* all Stream objects */
+  GMainContext *	context;	/* context we work in */
+} Sound;
+
+typedef struct {
+  Sound *		sound;		/* reference to sound object */
+  SwfdecAudio *		audio;		/* the audio we play back */
+  snd_pcm_t *		pcm;		/* the pcm we play back to */
+  GSource **		sources;	/* sources for writing data */
+  guint			n_sources;	/* number of sources */
+  guint			offset;		/* offset into sound */
+} Stream;
+
+#define ALSA_TRY(func,msg) G_STMT_START{ \
+  int err = func; \
+  if (err < 0) \
+    g_printerr (msg ": %s\n", snd_strerror (err)); \
+}G_STMT_END
+
+#define ALSA_ERROR(func,msg,retval) G_STMT_START { \
+  int err = func; \
+  if (err < 0) { \
+    g_printerr (msg ": %s\n", snd_strerror (err)); \
+    return retval; \
+  } \
+}G_STMT_END
+
+/*** STREAMS ***/
+
+static snd_pcm_uframes_t
+write_player (Stream *stream, const snd_pcm_channel_area_t *dst, 
+    snd_pcm_uframes_t offset, snd_pcm_uframes_t avail)
+{
+  /* FIXME: do a long path if this doesn't hold */
+  g_assert (dst[1].first - dst[0].first == 16);
+  g_assert (dst[0].addr == dst[1].addr);
+  g_assert (dst[0].step == dst[1].step);
+  g_assert (dst[0].step == 32);
+
+  memset (dst[0].addr + offset * dst[0].step / 8, 0, avail * 4);
+  swfdec_audio_render (stream->audio, dst[0].addr + offset * dst[0].step / 8, 
+      stream->offset, avail);
+  //g_print ("rendering %u %u\n", stream->offset, (guint) avail);
+  return avail;
+}
+
+static gboolean
+try_write (Stream *stream)
+{
+  snd_pcm_sframes_t avail_result;
+  snd_pcm_uframes_t offset, avail;
+  const snd_pcm_channel_area_t *dst;
+
+  while (TRUE) {
+    avail_result = snd_pcm_avail_update (stream->pcm);
+    ALSA_ERROR (avail_result, "snd_pcm_avail_update failed", FALSE);
+    if (avail_result == 0)
+      return TRUE;
+    avail = avail_result;
+    ALSA_ERROR (snd_pcm_mmap_begin (stream->pcm, &dst, &offset, &avail),
+	"snd_pcm_mmap_begin failed", FALSE);
+    //g_print ("  avail = %u\n", (guint) avail);
+
+    avail = write_player (stream, dst, offset, avail);
+    if (snd_pcm_mmap_commit (stream->pcm, offset, avail) < 0) {
+      g_printerr ("snd_pcm_mmap_commit failed\n");
+      return FALSE;
+    }
+    stream->offset += avail;
+    //g_print ("offset: %u (+%u)\n", stream->offset, (guint) avail);
+  }
+  return TRUE;
+}
+
+static void
+swfdec_stream_remove_handlers (Stream *stream)
+{
+  unsigned int i;
+
+  for (i = 0; i < stream->n_sources; i++) {
+    if (stream->sources[i]) {
+      g_source_destroy (stream->sources[i]);
+      g_source_unref (stream->sources[i]);
+      stream->sources[i] = NULL;
+    }
+  }
+}
+
+static void swfdec_stream_start (Stream *stream);
+static gboolean
+handle_stream (GIOChannel *source, GIOCondition cond, gpointer data)
+{
+  Stream *stream = data;
+  snd_pcm_state_t state;
+
+  state = snd_pcm_state (stream->pcm);
+  if (state != SND_PCM_STATE_RUNNING) {
+    swfdec_stream_start (stream);
+  } else {
+    try_write (stream);
+  }
+  return TRUE;
+}
+
+static void
+swfdec_stream_install_handlers (Stream *stream)
+{
+  if (stream->n_sources > 0) {
+    struct pollfd polls[stream->n_sources];
+    unsigned int i, count;
+    if (stream->n_sources > 1)
+      g_printerr ("attention: more than one fd!\n");
+    count = snd_pcm_poll_descriptors (stream->pcm, polls, stream->n_sources);
+    for (i = 0; i < count; i++) {
+      if (stream->sources[i] != NULL)
+	continue;
+      GIOChannel *channel = g_io_channel_unix_new (polls[i].fd);
+      stream->sources[i] = g_io_create_watch (channel, polls[i].events);
+      g_source_set_priority (stream->sources[i], G_PRIORITY_HIGH);
+      g_source_set_callback (stream->sources[i], (GSourceFunc) handle_stream, stream, NULL);
+      g_io_channel_unref (channel);
+      g_source_attach (stream->sources[i], stream->sound->context);
+    }
+  }
+}
+
+static void
+swfdec_stream_start (Stream *stream)
+{
+  snd_pcm_state_t state = snd_pcm_state (stream->pcm);
+  switch (state) {
+    case SND_PCM_STATE_XRUN:
+      ALSA_ERROR (snd_pcm_prepare (stream->pcm), "no prepare",);
+      //g_print ("XRUN!\n");
+      /* fall through */
+    case SND_PCM_STATE_SUSPENDED:
+    case SND_PCM_STATE_PREPARED:
+      stream->offset = 0;
+      //g_print ("offset: %u (delay: %ld)\n", sound->offset, delay);
+      if (try_write (stream)) {
+	ALSA_ERROR (snd_pcm_start (stream->pcm), "error starting",);
+	swfdec_stream_install_handlers (stream);
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+static void
+swfdec_stream_open (Sound *sound, SwfdecAudio *audio)
+{
+  Stream *stream;
+  snd_pcm_t *ret;
+  snd_pcm_hw_params_t *hw_params;
+  unsigned int rate;
+  snd_pcm_uframes_t uframes;
+
+  /* "default" uses dmix, and dmix ticks way slow, so this thingy here stutters */
+  ALSA_ERROR (snd_pcm_open (&ret, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK),
+      "Failed to open sound device", );
+
+  snd_pcm_hw_params_alloca (&hw_params);
+  if (snd_pcm_hw_params_any (ret, hw_params) < 0) {
+    g_printerr ("No sound format available\n");
+    return;
+  }
+  if (snd_pcm_hw_params_set_access (ret, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
+    g_printerr ("Failed setting access\n");
+    goto fail;
+  }
+  if (snd_pcm_hw_params_set_format (ret, hw_params, SND_PCM_FORMAT_S16) < 0) {
+    g_printerr ("Failed setting format\n");
+    goto fail;
+  }
+  if (snd_pcm_hw_params_set_channels (ret, hw_params, 2) < 0) {
+    g_printerr ("Failed setting channels\n");
+    goto fail;
+  }
+  rate = 44100;
+  if (snd_pcm_hw_params_set_rate_near (ret, hw_params, &rate, 0) < 0) {
+    g_printerr ("Failed setting rate\n");
+    goto fail;
+  }
+  uframes = 16384;
+  if (snd_pcm_hw_params_set_buffer_size_near (ret, hw_params, &uframes) < 0) {
+    g_printerr ("Failed setting buffer size\n");
+    goto fail;
+  }
+  if (snd_pcm_hw_params (ret, hw_params) < 0) {
+    g_printerr ("Could not set hardware parameters\n");
+    goto fail;
+  }
+#if 0
+  {
+    snd_output_t *log;
+    snd_output_stdio_attach (&log, stderr, 0);
+    snd_pcm_hw_params_dump (hw_params, log);
+  }
+#endif
+  stream = g_new0 (Stream, 1);
+  stream->sound = sound;
+  stream->audio = g_object_ref (audio);
+  stream->pcm = ret;
+  stream->n_sources = snd_pcm_poll_descriptors_count (ret);
+  if (stream->n_sources > 0)
+    stream->sources = g_new0 (GSource *, stream->n_sources);
+  sound->streams = g_list_prepend (sound->streams, stream);
+  swfdec_stream_start (stream);
+  return;
+
+fail:
+  snd_pcm_close (ret);
+}
+
+static void
+swfdec_stream_close (Stream *stream)
+{
+  ALSA_TRY (snd_pcm_close (stream->pcm), "failed closing");
+  swfdec_stream_remove_handlers (stream);
+  g_free (stream->sources);
+  stream->sound->streams = g_list_remove (stream->sound->streams, stream);
+  g_object_unref (stream->audio);
+  g_free (stream);
+}
+
+/*** SOUND ***/
+
+static void
+advance_before (SwfdecPlayer *player, guint msecs, guint audio_samples, gpointer data)
+{
+  Sound *sound = data;
+  GList *walk;
+
+  for (walk = sound->streams; walk; walk = walk->next) {
+    Stream *stream = walk->data;
+    if (audio_samples >= stream->offset) {
+      stream->offset = 0;
+    } else {
+      stream->offset -= audio_samples;
+    }
+  }
+}
+
+static void
+audio_added (SwfdecPlayer *player, SwfdecAudio *audio, Sound *sound)
+{
+  swfdec_stream_open (sound, audio);
+}
+
+static void
+audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, Sound *sound)
+{
+  GList *walk;
+
+  for (walk = sound->streams; walk; walk = walk->next) {
+    Stream *stream = walk->data;
+    if (stream->audio == audio) {
+      swfdec_stream_close (stream);
+      return;
+    }
+  }
+  g_assert_not_reached ();
+}
+
+gpointer
+swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
+{
+  Sound *sound;
+  const GList *walk;
+
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  g_return_val_if_fail (context != NULL, NULL);
+
+  sound = g_new0 (Sound, 1);
+  sound->player = g_object_ref (player);
+  g_signal_connect (player, "advance", G_CALLBACK (advance_before), sound);
+  g_signal_connect (player, "audio-added", G_CALLBACK (audio_added), sound);
+  g_signal_connect (player, "audio-removed", G_CALLBACK (audio_removed), sound);
+  for (walk = swfdec_player_get_audio (player); walk; walk = walk->next) {
+    swfdec_stream_open (sound, walk->data);
+  }
+  g_main_context_ref (context);
+  sound->context = context;
+  return sound;
+}
+
+void
+swfdec_playback_close (gpointer data)
+{
+  Sound *sound = data;
+#define REMOVE_HANDLER_FULL(obj,func,data,count) G_STMT_START {\
+  if (g_signal_handlers_disconnect_by_func ((obj), \
+	G_CALLBACK (func), (data)) != (count)) { \
+    g_assert_not_reached (); \
+  } \
+} G_STMT_END
+#define REMOVE_HANDLER(obj,func,data) REMOVE_HANDLER_FULL (obj, func, data, 1)
+
+  while (sound->streams)
+    swfdec_stream_close (sound->streams->data);
+  REMOVE_HANDLER (sound->player, advance_before, sound);
+  REMOVE_HANDLER (sound->player, audio_added, sound);
+  REMOVE_HANDLER (sound->player, audio_removed, sound);
+  g_object_unref (sound->player);
+  g_main_context_unref (sound->context);
+  g_free (sound);
+}
+
+
diff --git a/libswfdec-gtk/swfdec_playback_none.c b/libswfdec-gtk/swfdec_playback_none.c
new file mode 100644
index 0000000..6464a4a
--- /dev/null
+++ b/libswfdec-gtk/swfdec_playback_none.c
@@ -0,0 +1,38 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "swfdec_playback.h"
+
+/* STUBS ONLY - audio is disabled */
+
+gpointer
+swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
+{
+  return GINT_TO_POINTER (-1);
+}
+
+void
+swfdec_playback_close (gpointer sound)
+{
+  g_assert (sound == GINT_TO_POINTER (-1));
+}
diff --git a/libswfdec-gtk/swfdec_source.c b/libswfdec-gtk/swfdec_source.c
new file mode 100644
index 0000000..81e383b
--- /dev/null
+++ b/libswfdec-gtk/swfdec_source.c
@@ -0,0 +1,158 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "swfdec_source.h"
+
+static glong
+my_time_val_difference (const GTimeVal *compare, const GTimeVal *now)
+{
+  return (compare->tv_sec - now->tv_sec) * 1000 + 
+    (compare->tv_usec - now->tv_usec) / 1000;
+}
+
+/*** SwfdecIterateSource ***/
+
+typedef struct _SwfdecIterateSource SwfdecIterateSource;
+struct _SwfdecIterateSource {
+  GSource		source;
+  SwfdecPlayer *	player;
+  double		speed;		/* inverse playback speed (so 0.5 means double speed) */
+  gulong		notify;		/* set for iterate notifications */
+  GTimeVal		last;		/* last time */
+};
+
+static glong
+swfdec_iterate_get_msecs_to_next_event (GSource *source_)
+{
+  SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
+  GTimeVal now;
+  glong diff;
+
+  diff = swfdec_player_get_next_event (source->player);
+  if (diff == 0)
+    return G_MAXLONG;
+  diff *= source->speed;
+  g_source_get_current_time (source_, &now);
+  /* should really add to source->last instead of sutracting from now */
+  g_time_val_add (&now, -diff * 1000);
+  diff = my_time_val_difference (&source->last, &now);
+
+  return diff;
+}
+
+static gboolean
+swfdec_iterate_prepare (GSource *source, gint *timeout)
+{
+  glong diff = swfdec_iterate_get_msecs_to_next_event (source);
+
+  if (diff == G_MAXLONG) {
+    *timeout = -1;
+    return FALSE;
+  } else if (diff <= 0) {
+    *timeout = 0;
+    return TRUE;
+  } else {
+    *timeout = diff;
+    return FALSE;
+  }
+}
+
+static gboolean
+swfdec_iterate_check (GSource *source)
+{
+  glong diff = swfdec_iterate_get_msecs_to_next_event (source);
+
+  return diff < 0;
+}
+
+static gboolean
+swfdec_iterate_dispatch (GSource *source_, GSourceFunc callback, gpointer user_data)
+{
+  SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
+  glong diff = swfdec_iterate_get_msecs_to_next_event (source_);
+
+  if (diff > 0)
+    return TRUE;
+  diff = swfdec_player_get_next_event (source->player) - diff;
+  swfdec_player_advance (source->player, diff);
+  return TRUE;
+}
+
+static void
+swfdec_iterate_finalize (GSource *source_)
+{
+  SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
+
+  if (source->notify) {
+    g_signal_handler_disconnect (source->player, source->notify);
+  }
+  g_object_unref (source->player);
+}
+
+GSourceFuncs swfdec_iterate_funcs = {
+  swfdec_iterate_prepare,
+  swfdec_iterate_check,
+  swfdec_iterate_dispatch,
+  swfdec_iterate_finalize
+};
+
+static void
+swfdec_iterate_source_advance_cb (SwfdecPlayer *player, guint msecs, 
+    guint audio_frames, SwfdecIterateSource *source)
+{
+  g_time_val_add (&source->last, msecs * 1000 * source->speed);
+}
+
+GSource *
+swfdec_iterate_source_new (SwfdecPlayer *player, double speed)
+{
+  SwfdecIterateSource *source;
+
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  g_return_val_if_fail (speed > 0.0, NULL);
+
+  source = (SwfdecIterateSource *) g_source_new (&swfdec_iterate_funcs, 
+      sizeof (SwfdecIterateSource));
+  source->player = g_object_ref (player);
+  source->speed = 1.0 / speed;
+  source->notify = g_signal_connect (player, "advance",
+      G_CALLBACK (swfdec_iterate_source_advance_cb), source);
+  g_get_current_time (&source->last);
+  
+  return (GSource *) source;
+}
+
+guint
+swfdec_iterate_add (SwfdecPlayer *player)
+{
+  GSource *source;
+  guint id;
+  
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), 0);
+
+  source = swfdec_iterate_source_new (player, 1.0);
+
+  id = g_source_attach (source, NULL);
+  g_source_unref (source);
+
+  return id;
+}
diff --git a/libswfdec-gtk/swfdec_source.h b/libswfdec-gtk/swfdec_source.h
new file mode 100644
index 0000000..4321d6d
--- /dev/null
+++ b/libswfdec-gtk/swfdec_source.h
@@ -0,0 +1,32 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_SOURCE_H_
+#define _SWFDEC_SOURCE_H_
+
+#include <libswfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+GSource *	swfdec_iterate_source_new	(SwfdecPlayer *		player,
+						 double			speed);
+guint		swfdec_iterate_add		(SwfdecPlayer *		player);
+
+G_END_DECLS
+#endif
diff --git a/libswfdec-gtk/swfdec_widget.c b/libswfdec-gtk/swfdec_widget.c
new file mode 100644
index 0000000..99b414e
--- /dev/null
+++ b/libswfdec-gtk/swfdec_widget.c
@@ -0,0 +1,450 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include "swfdec_widget.h"
+
+enum {
+  PROP_0,
+  PROP_PLAYER
+};
+
+G_DEFINE_TYPE (SwfdecWidget, swfdec_widget, GTK_TYPE_WIDGET)
+
+static gboolean
+swfdec_widget_motion_notify (GtkWidget *gtkwidget, GdkEventMotion *event)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+  int x, y;
+
+  gdk_window_get_pointer (gtkwidget->window, &x, &y, NULL);
+
+  if (widget->interactive)
+    swfdec_player_handle_mouse (widget->player, 
+	x / widget->real_scale, y / widget->real_scale, widget->button);
+  
+  return FALSE;
+}
+
+static gboolean
+swfdec_widget_leave_notify (GtkWidget *gtkwidget, GdkEventCrossing *event)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+
+  if (widget->interactive) {
+    widget->button = 0;
+    swfdec_player_handle_mouse (widget->player, 
+	event->x / widget->real_scale, event->y / widget->real_scale, 0);
+  }
+  return FALSE;
+}
+
+static gboolean
+swfdec_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+
+  if (event->button == 1) {
+    widget->button = 1;
+    if (widget->interactive)
+      swfdec_player_handle_mouse (widget->player, 
+	  event->x / widget->real_scale, event->y / widget->real_scale, 1);
+  }
+  return FALSE;
+}
+
+static gboolean
+swfdec_widget_button_release (GtkWidget *gtkwidget, GdkEventButton *event)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+
+  if (event->button == 1) {
+    widget->button = 0;
+    if (widget->interactive)
+      swfdec_player_handle_mouse (widget->player, 
+	  event->x / widget->real_scale, event->y / widget->real_scale, 0);
+  }
+  return FALSE;
+}
+
+static gboolean
+swfdec_widget_expose (GtkWidget *gtkwidget, GdkEventExpose *event)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+  cairo_t *cr;
+  cairo_surface_t *surface = NULL;
+
+  if (event->window != gtkwidget->window)
+    return FALSE;
+
+  if (!widget->use_image) {
+    cr = gdk_cairo_create (gtkwidget->window);
+  } else {
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 
+      event->area.width, event->area.height);
+    cr = cairo_create (surface);
+    cairo_translate (cr, -event->area.x, -event->area.y);
+    cairo_surface_destroy (surface);
+  }
+  cairo_scale (cr, widget->real_scale, widget->real_scale);
+  swfdec_player_render (widget->player, cr,
+      event->area.x / widget->real_scale, event->area.y / widget->real_scale, 
+      event->area.width / widget->real_scale, event->area.height / widget->real_scale);
+  if (widget->use_image) {
+    cairo_t *crw = gdk_cairo_create (gtkwidget->window);
+    cairo_set_source_surface (crw, surface, event->area.x, event->area.y);
+    cairo_paint (crw);
+    cairo_destroy (crw);
+  }
+
+  cairo_destroy (cr);
+
+  return FALSE;
+}
+
+static void
+swfdec_widget_get_property (GObject *object, guint param_id, GValue *value, 
+    GParamSpec * pspec)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (object);
+  
+  switch (param_id) {
+    case PROP_PLAYER:
+      g_value_set_object (value, widget->player);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_widget_set_property (GObject *object, guint param_id, const GValue *value,
+    GParamSpec *pspec)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (object);
+  
+  switch (param_id) {
+    case PROP_PLAYER:
+      swfdec_widget_set_player (widget, g_value_get_object (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+      break;
+  }
+}
+
+static void
+swfdec_widget_dispose (GObject *object)
+{
+  SwfdecWidget *widget = SWFDEC_WIDGET (object);
+
+  swfdec_widget_set_player (widget, NULL);
+
+  G_OBJECT_CLASS (swfdec_widget_parent_class)->dispose (object);
+}
+
+static void
+swfdec_widget_size_allocate (GtkWidget *gtkwidget, GtkAllocation *allocation)
+{
+  double scale;
+  int w, h;
+  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
+
+  gtkwidget->allocation = *allocation;
+
+  swfdec_player_get_image_size (widget->player, &w, &h);
+  if (widget->set_scale > 0.0) {
+    scale = widget->set_scale;
+  } else if (widget->player == NULL) {
+    scale = 1.0;
+  } else {
+    if (w != 0 && h != 0)
+      scale = MIN ((double) allocation->width / w, (double) allocation->height / h);
+    else
+      scale = 1.0;
+  }
+  w = ceil (w * scale);
+  h = ceil (h * scale);
+  if (w > allocation->width)
+    w = allocation->width;
+  if (h > allocation->height)
+    h = allocation->height;
+
+  if (GTK_WIDGET_REALIZED (gtkwidget)) {
+    gdk_window_move_resize (gtkwidget->window, 
+	allocation->x + (allocation->width - w) / 2,
+	allocation->y + (allocation->height - h) / 2,
+	w, h);
+  }
+  widget->real_scale = scale;
+}
+
+static void
+swfdec_widget_size_request (GtkWidget *gtkwidget, GtkRequisition *req)
+{
+  double scale;
+  SwfdecWidget * widget = SWFDEC_WIDGET (gtkwidget);
+
+  if (widget->player == NULL) {
+    req->width = req->height = 0;
+  } else {
+    swfdec_player_get_image_size (widget->player, 
+	  &req->width, &req->height);
+  } 
+  if (widget->set_scale != 0.0)
+    scale = widget->set_scale;
+  else
+    scale = 1.0;
+  req->width = ceil (req->width * scale);
+  req->height = ceil (req->height * scale);
+}
+
+static void
+swfdec_widget_update_cursor (SwfdecWidget *widget)
+{
+  GdkWindow *window = GTK_WIDGET (widget)->window;
+  GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (widget));
+  SwfdecMouseCursor swfcursor;
+  GdkCursor *cursor;
+
+  if (window == NULL)
+    return;
+  g_object_get (widget->player, "mouse-cursor", &swfcursor, NULL);
+
+  switch (swfcursor) {
+    case SWFDEC_MOUSE_CURSOR_NONE:
+      {
+	GdkBitmap *bitmap;
+	GdkColor color = { 0, 0, 0, 0 };
+	char data = 0;
+
+	bitmap = gdk_bitmap_create_from_data (window, &data, 1, 1);
+	if (bitmap == NULL)
+	  return;
+	cursor = gdk_cursor_new_from_pixmap (bitmap, bitmap, &color, &color, 0, 0);
+	gdk_window_set_cursor (window, cursor);
+	gdk_cursor_unref (cursor);
+	g_object_unref (bitmap);
+	break;
+      }
+    case SWFDEC_MOUSE_CURSOR_TEXT:
+      cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
+      gdk_window_set_cursor (window, cursor);
+      gdk_cursor_unref (cursor);
+      break;
+    case SWFDEC_MOUSE_CURSOR_CLICK:
+      cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
+      gdk_window_set_cursor (window, cursor);
+      gdk_cursor_unref (cursor);
+      break;
+    case SWFDEC_MOUSE_CURSOR_NORMAL:
+      cursor = gdk_cursor_new_for_display (display, GDK_LEFT_PTR);
+      gdk_window_set_cursor (window, cursor);
+      gdk_cursor_unref (cursor);
+      break;
+    default:
+      g_warning ("invalid cursor %d", (int) swfcursor);
+      gdk_window_set_cursor (window, NULL);
+      break;
+  }
+}
+
+static void
+swfdec_widget_realize (GtkWidget *widget)
+{
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x;
+  attributes.y = widget->allocation.y;
+  attributes.width = widget->allocation.width;
+  attributes.height = widget->allocation.height;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |= GDK_EXPOSURE_MASK | 
+			   GDK_BUTTON_PRESS_MASK |
+			   GDK_BUTTON_RELEASE_MASK |
+			   GDK_LEAVE_NOTIFY_MASK | 
+			   GDK_POINTER_MOTION_MASK | 
+			   GDK_POINTER_MOTION_HINT_MASK;
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+      &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, widget);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
+
+  if (SWFDEC_WIDGET (widget)->player) {
+    swfdec_widget_update_cursor (SWFDEC_WIDGET (widget));
+  }
+}
+
+static void
+swfdec_widget_class_init (SwfdecWidgetClass * g_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (g_class);
+
+  object_class->dispose = swfdec_widget_dispose;
+  object_class->get_property = swfdec_widget_get_property;
+  object_class->set_property = swfdec_widget_set_property;
+
+  g_object_class_install_property (object_class, PROP_PLAYER,
+      g_param_spec_object ("player", "player", "player that is displayed",
+	  SWFDEC_TYPE_PLAYER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  widget_class->realize = swfdec_widget_realize;
+  widget_class->size_request = swfdec_widget_size_request;
+  widget_class->size_allocate = swfdec_widget_size_allocate;
+  widget_class->expose_event = swfdec_widget_expose;
+  widget_class->button_press_event = swfdec_widget_button_press;
+  widget_class->button_release_event = swfdec_widget_button_release;
+  widget_class->motion_notify_event = swfdec_widget_motion_notify;
+  widget_class->leave_notify_event = swfdec_widget_leave_notify;
+}
+
+static void
+swfdec_widget_init (SwfdecWidget * widget)
+{
+  widget->real_scale = 1.0;
+  widget->interactive = TRUE;
+}
+
+static void
+swfdec_widget_invalidate_cb (SwfdecPlayer *player, double x, double y, 
+    double width, double height, SwfdecWidget *widget)
+{
+  GdkRectangle rect;
+
+  if (!GTK_WIDGET_REALIZED (widget))
+    return;
+  rect.x = floor (x * widget->real_scale);
+  rect.y = floor (y * widget->real_scale);
+  rect.width = ceil ((x + width) * widget->real_scale) - rect.x;
+  rect.height = ceil ((y + height) * widget->real_scale) - rect.y;
+  gdk_window_invalidate_rect (GTK_WIDGET (widget)->window, &rect, FALSE);
+}
+
+static void
+swfdec_widget_notify_cb (SwfdecPlayer *player, GParamSpec *pspec, SwfdecWidget *widget)
+{
+  if (g_str_equal (pspec->name, "mouse-cursor")) {
+    swfdec_widget_update_cursor (widget);
+  } else if (g_str_equal (pspec->name, "initialized")) {
+    gtk_widget_queue_resize (GTK_WIDGET (widget));
+  }
+}
+
+void
+swfdec_widget_set_player (SwfdecWidget *widget, SwfdecPlayer *player)
+{
+  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
+  g_return_if_fail (player == NULL || SWFDEC_IS_PLAYER (player));
+  
+  if (widget->player) {
+    g_signal_handlers_disconnect_by_func (widget->player, swfdec_widget_invalidate_cb, widget);
+    g_signal_handlers_disconnect_by_func (widget->player, swfdec_widget_notify_cb, widget);
+    g_object_unref (widget->player);
+  }
+  widget->player = player;
+  if (player) {
+    g_signal_connect (player, "invalidate", G_CALLBACK (swfdec_widget_invalidate_cb), widget);
+    g_signal_connect (player, "notify", G_CALLBACK (swfdec_widget_notify_cb), widget);
+    g_object_ref (player);
+    swfdec_widget_update_cursor (widget);
+  } else {
+    if (GTK_WIDGET (widget)->window)
+      gdk_window_set_cursor (GTK_WIDGET (widget)->window, NULL); 
+  }
+  gtk_widget_queue_resize (GTK_WIDGET (widget));
+}
+
+GtkWidget *
+swfdec_widget_new (SwfdecPlayer *player)
+{
+  SwfdecWidget *widget;
+  
+  g_return_val_if_fail (player == NULL || SWFDEC_IS_PLAYER (player), NULL);
+
+  widget = g_object_new (SWFDEC_TYPE_WIDGET, "player", player, NULL);
+
+  return GTK_WIDGET (widget);
+}
+
+void
+swfdec_widget_set_scale	(SwfdecWidget *widget, double scale)
+{
+  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
+  g_return_if_fail (scale >= 0.0);
+
+  widget->set_scale = scale;
+  gtk_widget_queue_resize (GTK_WIDGET (widget));
+}
+
+double
+swfdec_widget_get_scale (SwfdecWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), 1.0);
+
+  return widget->set_scale;
+}
+
+void
+swfdec_widget_set_use_image (SwfdecWidget *widget, gboolean use_image)
+{
+  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
+
+  widget->use_image = use_image;
+  gtk_widget_queue_draw (GTK_WIDGET (widget));
+}
+
+gboolean
+swfdec_widget_get_use_image (SwfdecWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), 1.0);
+
+  return widget->use_image;
+}
+
+void
+swfdec_widget_set_interactive (SwfdecWidget *widget, gboolean interactive)
+{
+  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
+
+  widget->interactive = interactive;
+}
+
+gboolean
+swfdec_widget_get_interactive (SwfdecWidget *widget)
+{
+  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), FALSE);
+
+  return widget->interactive;
+}
+
diff --git a/libswfdec-gtk/swfdec_widget.h b/libswfdec-gtk/swfdec_widget.h
new file mode 100644
index 0000000..1988f20
--- /dev/null
+++ b/libswfdec-gtk/swfdec_widget.h
@@ -0,0 +1,73 @@
+/* Swfdec
+ * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_WIDGET_H_
+#define _SWFDEC_WIDGET_H_
+
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecWidget SwfdecWidget;
+typedef struct _SwfdecWidgetClass SwfdecWidgetClass;
+
+#define SWFDEC_TYPE_WIDGET                    (swfdec_widget_get_type())
+#define SWFDEC_IS_WIDGET(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_WIDGET))
+#define SWFDEC_IS_WIDGET_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_WIDGET))
+#define SWFDEC_WIDGET(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_WIDGET, SwfdecWidget))
+#define SWFDEC_WIDGET_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_WIDGET, SwfdecWidgetClass))
+
+struct _SwfdecWidget
+{
+  GtkWidget		widget;
+
+  SwfdecPlayer *	player;		/* the video we play */
+
+  double		real_scale;	/* the real scale factor used */
+  double		set_scale;    	/* the set scale factor of the video */
+  gboolean		use_image;	/* TRUE to draw to an image first before rendering to Gtk */
+  gboolean		interactive;	/* if this widget propagates keyboard and mouse events */
+
+  int			button;		/* status of mouse button in displayed movie */
+};
+
+struct _SwfdecWidgetClass
+{
+  GtkWidgetClass	widget_class;
+};
+
+GType		swfdec_widget_get_type		(void);
+
+GtkWidget *	swfdec_widget_new		(SwfdecPlayer *	player);
+
+void		swfdec_widget_set_scale		(SwfdecWidget *	widget,
+						 double		scale);
+double		swfdec_widget_get_scale		(SwfdecWidget *	widget);
+void		swfdec_widget_set_use_image	(SwfdecWidget *	widget,
+						 gboolean	use_image);
+gboolean	swfdec_widget_get_use_image	(SwfdecWidget *	widget);
+void		swfdec_widget_set_interactive	(SwfdecWidget * widget,
+						 gboolean	interactive);
+gboolean	swfdec_widget_get_interactive	(SwfdecWidget * widget);
+void		swfdec_widget_set_player	(SwfdecWidget *	widget,
+						 SwfdecPlayer *	player);
+
+G_END_DECLS
+#endif
diff --git a/player/.gitignore b/player/.gitignore
index c5a38e3..212cc97 100644
--- a/player/.gitignore
+++ b/player/.gitignore
@@ -9,9 +9,7 @@ Makefile.in
 *.o
 *.lo
 *.loT
-swfdec_playback.c
 
-libswfdecui.la
 swfdebug
 swfplay
 
diff --git a/player/Makefile.am b/player/Makefile.am
index f08f448..d22e527 100644
--- a/player/Makefile.am
+++ b/player/Makefile.am
@@ -1,21 +1,7 @@
 if WITH_GTK
 
-# this workaround is needed or autotools don't generate the .deps/*.Plo files correctly
-swfdec_playback.c: swfdec_playback_$(AUDIO_TYPE).c Makefile
-	cmp -s $(srcdir)/swfdec_playback_$(AUDIO_TYPE).c swfdec_playback.c \
-	|| cp $(srcdir)/swfdec_playback_$(AUDIO_TYPE).c swfdec_playback.c
-
-BUILT_SOURCES = swfdec_playback.c
-CLEANFILES = swfdec_playback.c
-
-noinst_LTLIBRARIES = libswfdecui.la
 noinst_PROGRAMS = swfplay swfdebug
 
-libswfdecui_la_SOURCES = \
-	swfdec_playback.c \
-	swfdec_source.c \
-	swfdec_widget.c
-
 swfplay_SOURCES = \
 	swfdec_slow_loader.c \
 	swfplay.c 
@@ -35,23 +21,16 @@ noinst_HEADERS = \
 	swfdec_debug_scripts.h \
 	swfdec_debug_stack.h \
 	swfdec_debug_widget.h \
-	swfdec_playback.h \
 	swfdec_player_manager.h \
-	swfdec_source.h \
-	swfdec_slow_loader.h \
-	swfdec_widget.h 
-
-libswfdecui_la_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_CFLAGS) $(AUDIO_CFLAGS)
-libswfdecui_la_LDFLAGS = $(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
-swfplay_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_CFLAGS)
-swfplay_LDFLAGS = $(GTK_LIBS) $(SWFDEC_LIBS)
-swfplay_LDADD = libswfdecui.la
-swfdebug_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-swfdebug_LDFLAGS = $(GTK_LIBS) $(SWFDEC_LIBS)
-swfdebug_LDADD = libswfdecui.la $(top_builddir)/libswfdec/js/libjs.la
+	swfdec_slow_loader.h
+
+swfplay_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_GTK_CFLAGS)
+swfplay_LDFLAGS = $(GTK_LIBS) $(SWFDEC_GTK_LIBS)
+
+swfdebug_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfdebug_LDFLAGS = $(GTK_LIBS) $(SWFDEC_GTK_LIBS)
+swfdebug_LDADD = $(top_builddir)/libswfdec/js/libjs.la
+
 endif
 
-EXTRA_DIST = \
-	swfdec_playback_alsa.c \
-	swfdec_playback_none.c
 
diff --git a/player/swfdec_debug_widget.h b/player/swfdec_debug_widget.h
index e4a34bf..c11c8a4 100644
--- a/player/swfdec_debug_widget.h
+++ b/player/swfdec_debug_widget.h
@@ -20,8 +20,7 @@
 #ifndef _SWFDEC_DEBUG_WIDGET_H_
 #define _SWFDEC_DEBUG_WIDGET_H_
 
-#include <gtk/gtk.h>
-#include "swfdec_widget.h"
+#include <libswfdec-gtk/swfdec_widget.h>
 
 G_BEGIN_DECLS
 
diff --git a/player/swfdec_playback.h b/player/swfdec_playback.h
deleted file mode 100644
index 8b894cf..0000000
--- a/player/swfdec_playback.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _SWFDEC_PLAYBACK_H_
-#define _SWFDEC_PLAYBACK_H_
-
-#include <libswfdec/swfdec.h>
-
-G_BEGIN_DECLS
-
-gpointer	swfdec_playback_open	(SwfdecPlayer *	player,
-					 GMainContext *	context);
-
-void		swfdec_playback_close	(gpointer	sound);
-
-G_END_DECLS
-#endif
diff --git a/player/swfdec_playback_alsa.c b/player/swfdec_playback_alsa.c
deleted file mode 100644
index ea47099..0000000
--- a/player/swfdec_playback_alsa.c
+++ /dev/null
@@ -1,355 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <alsa/asoundlib.h>
-#include "swfdec_source.h"
-
-/* Why ALSA sucks for beginners:
- * - snd_pcm_delay is not sample-exact, but period-exact most of the time.
- *   Yay for getting told the time every 512 samples when a human notices
- *   a delay of 100 samples (oooops)
- * - lots of functions are simply not implemented. So the super-smart idea
- *   of using snd_pcm_rewind to avoid XRUNS and still get low latency has
- *   some issues when dmix just returns -EIO all of the time. That wouldn't
- *   be so bad if there was actually a way to query if it's supported.
- * - But to make up for all this, you have 10 hardware parameters, 10 
- *   software parameters and 10 configuration parameters. All of this is
- *   naturally supported on 10 driver APIs depending on kernel. So if your
- *   sound card seems to do weird stuff, that is not my fault.
- * Welcome to Linux sound in the 21st century.
- */
-
-/*** DEFINITIONS ***/
-
-typedef struct {
-  SwfdecPlayer *	player;
-  GList *		streams;	/* all Stream objects */
-  GMainContext *	context;	/* context we work in */
-} Sound;
-
-typedef struct {
-  Sound *		sound;		/* reference to sound object */
-  SwfdecAudio *		audio;		/* the audio we play back */
-  snd_pcm_t *		pcm;		/* the pcm we play back to */
-  GSource **		sources;	/* sources for writing data */
-  guint			n_sources;	/* number of sources */
-  guint			offset;		/* offset into sound */
-} Stream;
-
-#define ALSA_TRY(func,msg) G_STMT_START{ \
-  int err = func; \
-  if (err < 0) \
-    g_printerr (msg ": %s\n", snd_strerror (err)); \
-}G_STMT_END
-
-#define ALSA_ERROR(func,msg,retval) G_STMT_START { \
-  int err = func; \
-  if (err < 0) { \
-    g_printerr (msg ": %s\n", snd_strerror (err)); \
-    return retval; \
-  } \
-}G_STMT_END
-
-/*** STREAMS ***/
-
-static snd_pcm_uframes_t
-write_player (Stream *stream, const snd_pcm_channel_area_t *dst, 
-    snd_pcm_uframes_t offset, snd_pcm_uframes_t avail)
-{
-  /* FIXME: do a long path if this doesn't hold */
-  g_assert (dst[1].first - dst[0].first == 16);
-  g_assert (dst[0].addr == dst[1].addr);
-  g_assert (dst[0].step == dst[1].step);
-  g_assert (dst[0].step == 32);
-
-  memset (dst[0].addr + offset * dst[0].step / 8, 0, avail * 4);
-  swfdec_audio_render (stream->audio, dst[0].addr + offset * dst[0].step / 8, 
-      stream->offset, avail);
-  //g_print ("rendering %u %u\n", stream->offset, (guint) avail);
-  return avail;
-}
-
-static gboolean
-try_write (Stream *stream)
-{
-  snd_pcm_sframes_t avail_result;
-  snd_pcm_uframes_t offset, avail;
-  const snd_pcm_channel_area_t *dst;
-
-  while (TRUE) {
-    avail_result = snd_pcm_avail_update (stream->pcm);
-    ALSA_ERROR (avail_result, "snd_pcm_avail_update failed", FALSE);
-    if (avail_result == 0)
-      return TRUE;
-    avail = avail_result;
-    ALSA_ERROR (snd_pcm_mmap_begin (stream->pcm, &dst, &offset, &avail),
-	"snd_pcm_mmap_begin failed", FALSE);
-    //g_print ("  avail = %u\n", (guint) avail);
-
-    avail = write_player (stream, dst, offset, avail);
-    if (snd_pcm_mmap_commit (stream->pcm, offset, avail) < 0) {
-      g_printerr ("snd_pcm_mmap_commit failed\n");
-      return FALSE;
-    }
-    stream->offset += avail;
-    //g_print ("offset: %u (+%u)\n", stream->offset, (guint) avail);
-  }
-  return TRUE;
-}
-
-static void
-swfdec_stream_remove_handlers (Stream *stream)
-{
-  unsigned int i;
-
-  for (i = 0; i < stream->n_sources; i++) {
-    if (stream->sources[i]) {
-      g_source_destroy (stream->sources[i]);
-      g_source_unref (stream->sources[i]);
-      stream->sources[i] = NULL;
-    }
-  }
-}
-
-static void swfdec_stream_start (Stream *stream);
-static gboolean
-handle_stream (GIOChannel *source, GIOCondition cond, gpointer data)
-{
-  Stream *stream = data;
-  snd_pcm_state_t state;
-
-  state = snd_pcm_state (stream->pcm);
-  if (state != SND_PCM_STATE_RUNNING) {
-    swfdec_stream_start (stream);
-  } else {
-    try_write (stream);
-  }
-  return TRUE;
-}
-
-static void
-swfdec_stream_install_handlers (Stream *stream)
-{
-  if (stream->n_sources > 0) {
-    struct pollfd polls[stream->n_sources];
-    unsigned int i, count;
-    if (stream->n_sources > 1)
-      g_printerr ("attention: more than one fd!\n");
-    count = snd_pcm_poll_descriptors (stream->pcm, polls, stream->n_sources);
-    for (i = 0; i < count; i++) {
-      if (stream->sources[i] != NULL)
-	continue;
-      GIOChannel *channel = g_io_channel_unix_new (polls[i].fd);
-      stream->sources[i] = g_io_create_watch (channel, polls[i].events);
-      g_source_set_priority (stream->sources[i], G_PRIORITY_HIGH);
-      g_source_set_callback (stream->sources[i], (GSourceFunc) handle_stream, stream, NULL);
-      g_io_channel_unref (channel);
-      g_source_attach (stream->sources[i], stream->sound->context);
-    }
-  }
-}
-
-static void
-swfdec_stream_start (Stream *stream)
-{
-  snd_pcm_state_t state = snd_pcm_state (stream->pcm);
-  switch (state) {
-    case SND_PCM_STATE_XRUN:
-      ALSA_ERROR (snd_pcm_prepare (stream->pcm), "no prepare",);
-      //g_print ("XRUN!\n");
-      /* fall through */
-    case SND_PCM_STATE_SUSPENDED:
-    case SND_PCM_STATE_PREPARED:
-      stream->offset = 0;
-      //g_print ("offset: %u (delay: %ld)\n", sound->offset, delay);
-      if (try_write (stream)) {
-	ALSA_ERROR (snd_pcm_start (stream->pcm), "error starting",);
-	swfdec_stream_install_handlers (stream);
-      }
-      break;
-    default:
-      break;
-  }
-}
-
-static void
-swfdec_stream_open (Sound *sound, SwfdecAudio *audio)
-{
-  Stream *stream;
-  snd_pcm_t *ret;
-  snd_pcm_hw_params_t *hw_params;
-  unsigned int rate;
-  snd_pcm_uframes_t uframes;
-
-  /* "default" uses dmix, and dmix ticks way slow, so this thingy here stutters */
-  ALSA_ERROR (snd_pcm_open (&ret, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK),
-      "Failed to open sound device", );
-
-  snd_pcm_hw_params_alloca (&hw_params);
-  if (snd_pcm_hw_params_any (ret, hw_params) < 0) {
-    g_printerr ("No sound format available\n");
-    return;
-  }
-  if (snd_pcm_hw_params_set_access (ret, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) {
-    g_printerr ("Failed setting access\n");
-    goto fail;
-  }
-  if (snd_pcm_hw_params_set_format (ret, hw_params, SND_PCM_FORMAT_S16) < 0) {
-    g_printerr ("Failed setting format\n");
-    goto fail;
-  }
-  if (snd_pcm_hw_params_set_channels (ret, hw_params, 2) < 0) {
-    g_printerr ("Failed setting channels\n");
-    goto fail;
-  }
-  rate = 44100;
-  if (snd_pcm_hw_params_set_rate_near (ret, hw_params, &rate, 0) < 0) {
-    g_printerr ("Failed setting rate\n");
-    goto fail;
-  }
-  uframes = 16384;
-  if (snd_pcm_hw_params_set_buffer_size_near (ret, hw_params, &uframes) < 0) {
-    g_printerr ("Failed setting buffer size\n");
-    goto fail;
-  }
-  if (snd_pcm_hw_params (ret, hw_params) < 0) {
-    g_printerr ("Could not set hardware parameters\n");
-    goto fail;
-  }
-#if 0
-  {
-    snd_output_t *log;
-    snd_output_stdio_attach (&log, stderr, 0);
-    snd_pcm_hw_params_dump (hw_params, log);
-  }
-#endif
-  stream = g_new0 (Stream, 1);
-  stream->sound = sound;
-  stream->audio = g_object_ref (audio);
-  stream->pcm = ret;
-  stream->n_sources = snd_pcm_poll_descriptors_count (ret);
-  if (stream->n_sources > 0)
-    stream->sources = g_new0 (GSource *, stream->n_sources);
-  sound->streams = g_list_prepend (sound->streams, stream);
-  swfdec_stream_start (stream);
-  return;
-
-fail:
-  snd_pcm_close (ret);
-}
-
-static void
-swfdec_stream_close (Stream *stream)
-{
-  ALSA_TRY (snd_pcm_close (stream->pcm), "failed closing");
-  swfdec_stream_remove_handlers (stream);
-  g_free (stream->sources);
-  stream->sound->streams = g_list_remove (stream->sound->streams, stream);
-  g_object_unref (stream->audio);
-  g_free (stream);
-}
-
-/*** SOUND ***/
-
-static void
-advance_before (SwfdecPlayer *player, guint msecs, guint audio_samples, gpointer data)
-{
-  Sound *sound = data;
-  GList *walk;
-
-  for (walk = sound->streams; walk; walk = walk->next) {
-    Stream *stream = walk->data;
-    if (audio_samples >= stream->offset) {
-      stream->offset = 0;
-    } else {
-      stream->offset -= audio_samples;
-    }
-  }
-}
-
-static void
-audio_added (SwfdecPlayer *player, SwfdecAudio *audio, Sound *sound)
-{
-  swfdec_stream_open (sound, audio);
-}
-
-static void
-audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, Sound *sound)
-{
-  GList *walk;
-
-  for (walk = sound->streams; walk; walk = walk->next) {
-    Stream *stream = walk->data;
-    if (stream->audio == audio) {
-      swfdec_stream_close (stream);
-      return;
-    }
-  }
-  g_assert_not_reached ();
-}
-
-gpointer
-swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
-{
-  Sound *sound;
-  const GList *walk;
-
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
-  g_return_val_if_fail (context != NULL, NULL);
-
-  sound = g_new0 (Sound, 1);
-  sound->player = g_object_ref (player);
-  g_signal_connect (player, "advance", G_CALLBACK (advance_before), sound);
-  g_signal_connect (player, "audio-added", G_CALLBACK (audio_added), sound);
-  g_signal_connect (player, "audio-removed", G_CALLBACK (audio_removed), sound);
-  for (walk = swfdec_player_get_audio (player); walk; walk = walk->next) {
-    swfdec_stream_open (sound, walk->data);
-  }
-  g_main_context_ref (context);
-  sound->context = context;
-  return sound;
-}
-
-void
-swfdec_playback_close (gpointer data)
-{
-  Sound *sound = data;
-#define REMOVE_HANDLER_FULL(obj,func,data,count) G_STMT_START {\
-  if (g_signal_handlers_disconnect_by_func ((obj), \
-	G_CALLBACK (func), (data)) != (count)) { \
-    g_assert_not_reached (); \
-  } \
-} G_STMT_END
-#define REMOVE_HANDLER(obj,func,data) REMOVE_HANDLER_FULL (obj, func, data, 1)
-
-  while (sound->streams)
-    swfdec_stream_close (sound->streams->data);
-  REMOVE_HANDLER (sound->player, advance_before, sound);
-  REMOVE_HANDLER (sound->player, audio_added, sound);
-  REMOVE_HANDLER (sound->player, audio_removed, sound);
-  g_object_unref (sound->player);
-  g_main_context_unref (sound->context);
-  g_free (sound);
-}
-
-
diff --git a/player/swfdec_playback_none.c b/player/swfdec_playback_none.c
deleted file mode 100644
index 6464a4a..0000000
--- a/player/swfdec_playback_none.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "swfdec_playback.h"
-
-/* STUBS ONLY - audio is disabled */
-
-gpointer
-swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
-{
-  return GINT_TO_POINTER (-1);
-}
-
-void
-swfdec_playback_close (gpointer sound)
-{
-  g_assert (sound == GINT_TO_POINTER (-1));
-}
diff --git a/player/swfdec_player_manager.c b/player/swfdec_player_manager.c
index 0d22ab3..299c9ab 100644
--- a/player/swfdec_player_manager.c
+++ b/player/swfdec_player_manager.c
@@ -28,7 +28,7 @@
 #include <libswfdec/js/jsdbgapi.h>
 #include <libswfdec/js/jsinterp.h>
 #include "swfdec_player_manager.h"
-#include "swfdec_source.h"
+#include <libswfdec-gtk/swfdec_source.h>
 
 enum {
   PROP_0,
diff --git a/player/swfdec_source.c b/player/swfdec_source.c
deleted file mode 100644
index 81e383b..0000000
--- a/player/swfdec_source.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include "swfdec_source.h"
-
-static glong
-my_time_val_difference (const GTimeVal *compare, const GTimeVal *now)
-{
-  return (compare->tv_sec - now->tv_sec) * 1000 + 
-    (compare->tv_usec - now->tv_usec) / 1000;
-}
-
-/*** SwfdecIterateSource ***/
-
-typedef struct _SwfdecIterateSource SwfdecIterateSource;
-struct _SwfdecIterateSource {
-  GSource		source;
-  SwfdecPlayer *	player;
-  double		speed;		/* inverse playback speed (so 0.5 means double speed) */
-  gulong		notify;		/* set for iterate notifications */
-  GTimeVal		last;		/* last time */
-};
-
-static glong
-swfdec_iterate_get_msecs_to_next_event (GSource *source_)
-{
-  SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
-  GTimeVal now;
-  glong diff;
-
-  diff = swfdec_player_get_next_event (source->player);
-  if (diff == 0)
-    return G_MAXLONG;
-  diff *= source->speed;
-  g_source_get_current_time (source_, &now);
-  /* should really add to source->last instead of sutracting from now */
-  g_time_val_add (&now, -diff * 1000);
-  diff = my_time_val_difference (&source->last, &now);
-
-  return diff;
-}
-
-static gboolean
-swfdec_iterate_prepare (GSource *source, gint *timeout)
-{
-  glong diff = swfdec_iterate_get_msecs_to_next_event (source);
-
-  if (diff == G_MAXLONG) {
-    *timeout = -1;
-    return FALSE;
-  } else if (diff <= 0) {
-    *timeout = 0;
-    return TRUE;
-  } else {
-    *timeout = diff;
-    return FALSE;
-  }
-}
-
-static gboolean
-swfdec_iterate_check (GSource *source)
-{
-  glong diff = swfdec_iterate_get_msecs_to_next_event (source);
-
-  return diff < 0;
-}
-
-static gboolean
-swfdec_iterate_dispatch (GSource *source_, GSourceFunc callback, gpointer user_data)
-{
-  SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
-  glong diff = swfdec_iterate_get_msecs_to_next_event (source_);
-
-  if (diff > 0)
-    return TRUE;
-  diff = swfdec_player_get_next_event (source->player) - diff;
-  swfdec_player_advance (source->player, diff);
-  return TRUE;
-}
-
-static void
-swfdec_iterate_finalize (GSource *source_)
-{
-  SwfdecIterateSource *source = (SwfdecIterateSource *) source_;
-
-  if (source->notify) {
-    g_signal_handler_disconnect (source->player, source->notify);
-  }
-  g_object_unref (source->player);
-}
-
-GSourceFuncs swfdec_iterate_funcs = {
-  swfdec_iterate_prepare,
-  swfdec_iterate_check,
-  swfdec_iterate_dispatch,
-  swfdec_iterate_finalize
-};
-
-static void
-swfdec_iterate_source_advance_cb (SwfdecPlayer *player, guint msecs, 
-    guint audio_frames, SwfdecIterateSource *source)
-{
-  g_time_val_add (&source->last, msecs * 1000 * source->speed);
-}
-
-GSource *
-swfdec_iterate_source_new (SwfdecPlayer *player, double speed)
-{
-  SwfdecIterateSource *source;
-
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
-  g_return_val_if_fail (speed > 0.0, NULL);
-
-  source = (SwfdecIterateSource *) g_source_new (&swfdec_iterate_funcs, 
-      sizeof (SwfdecIterateSource));
-  source->player = g_object_ref (player);
-  source->speed = 1.0 / speed;
-  source->notify = g_signal_connect (player, "advance",
-      G_CALLBACK (swfdec_iterate_source_advance_cb), source);
-  g_get_current_time (&source->last);
-  
-  return (GSource *) source;
-}
-
-guint
-swfdec_iterate_add (SwfdecPlayer *player)
-{
-  GSource *source;
-  guint id;
-  
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), 0);
-
-  source = swfdec_iterate_source_new (player, 1.0);
-
-  id = g_source_attach (source, NULL);
-  g_source_unref (source);
-
-  return id;
-}
diff --git a/player/swfdec_source.h b/player/swfdec_source.h
deleted file mode 100644
index 4321d6d..0000000
--- a/player/swfdec_source.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _SWFDEC_SOURCE_H_
-#define _SWFDEC_SOURCE_H_
-
-#include <libswfdec/swfdec.h>
-
-G_BEGIN_DECLS
-
-GSource *	swfdec_iterate_source_new	(SwfdecPlayer *		player,
-						 double			speed);
-guint		swfdec_iterate_add		(SwfdecPlayer *		player);
-
-G_END_DECLS
-#endif
diff --git a/player/swfdec_widget.c b/player/swfdec_widget.c
deleted file mode 100644
index 99b414e..0000000
--- a/player/swfdec_widget.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <math.h>
-#include "swfdec_widget.h"
-
-enum {
-  PROP_0,
-  PROP_PLAYER
-};
-
-G_DEFINE_TYPE (SwfdecWidget, swfdec_widget, GTK_TYPE_WIDGET)
-
-static gboolean
-swfdec_widget_motion_notify (GtkWidget *gtkwidget, GdkEventMotion *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-  int x, y;
-
-  gdk_window_get_pointer (gtkwidget->window, &x, &y, NULL);
-
-  if (widget->interactive)
-    swfdec_player_handle_mouse (widget->player, 
-	x / widget->real_scale, y / widget->real_scale, widget->button);
-  
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_leave_notify (GtkWidget *gtkwidget, GdkEventCrossing *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (widget->interactive) {
-    widget->button = 0;
-    swfdec_player_handle_mouse (widget->player, 
-	event->x / widget->real_scale, event->y / widget->real_scale, 0);
-  }
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_button_press (GtkWidget *gtkwidget, GdkEventButton *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (event->button == 1) {
-    widget->button = 1;
-    if (widget->interactive)
-      swfdec_player_handle_mouse (widget->player, 
-	  event->x / widget->real_scale, event->y / widget->real_scale, 1);
-  }
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_button_release (GtkWidget *gtkwidget, GdkEventButton *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (event->button == 1) {
-    widget->button = 0;
-    if (widget->interactive)
-      swfdec_player_handle_mouse (widget->player, 
-	  event->x / widget->real_scale, event->y / widget->real_scale, 0);
-  }
-  return FALSE;
-}
-
-static gboolean
-swfdec_widget_expose (GtkWidget *gtkwidget, GdkEventExpose *event)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-  cairo_t *cr;
-  cairo_surface_t *surface = NULL;
-
-  if (event->window != gtkwidget->window)
-    return FALSE;
-
-  if (!widget->use_image) {
-    cr = gdk_cairo_create (gtkwidget->window);
-  } else {
-    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 
-      event->area.width, event->area.height);
-    cr = cairo_create (surface);
-    cairo_translate (cr, -event->area.x, -event->area.y);
-    cairo_surface_destroy (surface);
-  }
-  cairo_scale (cr, widget->real_scale, widget->real_scale);
-  swfdec_player_render (widget->player, cr,
-      event->area.x / widget->real_scale, event->area.y / widget->real_scale, 
-      event->area.width / widget->real_scale, event->area.height / widget->real_scale);
-  if (widget->use_image) {
-    cairo_t *crw = gdk_cairo_create (gtkwidget->window);
-    cairo_set_source_surface (crw, surface, event->area.x, event->area.y);
-    cairo_paint (crw);
-    cairo_destroy (crw);
-  }
-
-  cairo_destroy (cr);
-
-  return FALSE;
-}
-
-static void
-swfdec_widget_get_property (GObject *object, guint param_id, GValue *value, 
-    GParamSpec * pspec)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (object);
-  
-  switch (param_id) {
-    case PROP_PLAYER:
-      g_value_set_object (value, widget->player);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-  }
-}
-
-static void
-swfdec_widget_set_property (GObject *object, guint param_id, const GValue *value,
-    GParamSpec *pspec)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (object);
-  
-  switch (param_id) {
-    case PROP_PLAYER:
-      swfdec_widget_set_player (widget, g_value_get_object (value));
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
-      break;
-  }
-}
-
-static void
-swfdec_widget_dispose (GObject *object)
-{
-  SwfdecWidget *widget = SWFDEC_WIDGET (object);
-
-  swfdec_widget_set_player (widget, NULL);
-
-  G_OBJECT_CLASS (swfdec_widget_parent_class)->dispose (object);
-}
-
-static void
-swfdec_widget_size_allocate (GtkWidget *gtkwidget, GtkAllocation *allocation)
-{
-  double scale;
-  int w, h;
-  SwfdecWidget *widget = SWFDEC_WIDGET (gtkwidget);
-
-  gtkwidget->allocation = *allocation;
-
-  swfdec_player_get_image_size (widget->player, &w, &h);
-  if (widget->set_scale > 0.0) {
-    scale = widget->set_scale;
-  } else if (widget->player == NULL) {
-    scale = 1.0;
-  } else {
-    if (w != 0 && h != 0)
-      scale = MIN ((double) allocation->width / w, (double) allocation->height / h);
-    else
-      scale = 1.0;
-  }
-  w = ceil (w * scale);
-  h = ceil (h * scale);
-  if (w > allocation->width)
-    w = allocation->width;
-  if (h > allocation->height)
-    h = allocation->height;
-
-  if (GTK_WIDGET_REALIZED (gtkwidget)) {
-    gdk_window_move_resize (gtkwidget->window, 
-	allocation->x + (allocation->width - w) / 2,
-	allocation->y + (allocation->height - h) / 2,
-	w, h);
-  }
-  widget->real_scale = scale;
-}
-
-static void
-swfdec_widget_size_request (GtkWidget *gtkwidget, GtkRequisition *req)
-{
-  double scale;
-  SwfdecWidget * widget = SWFDEC_WIDGET (gtkwidget);
-
-  if (widget->player == NULL) {
-    req->width = req->height = 0;
-  } else {
-    swfdec_player_get_image_size (widget->player, 
-	  &req->width, &req->height);
-  } 
-  if (widget->set_scale != 0.0)
-    scale = widget->set_scale;
-  else
-    scale = 1.0;
-  req->width = ceil (req->width * scale);
-  req->height = ceil (req->height * scale);
-}
-
-static void
-swfdec_widget_update_cursor (SwfdecWidget *widget)
-{
-  GdkWindow *window = GTK_WIDGET (widget)->window;
-  GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (widget));
-  SwfdecMouseCursor swfcursor;
-  GdkCursor *cursor;
-
-  if (window == NULL)
-    return;
-  g_object_get (widget->player, "mouse-cursor", &swfcursor, NULL);
-
-  switch (swfcursor) {
-    case SWFDEC_MOUSE_CURSOR_NONE:
-      {
-	GdkBitmap *bitmap;
-	GdkColor color = { 0, 0, 0, 0 };
-	char data = 0;
-
-	bitmap = gdk_bitmap_create_from_data (window, &data, 1, 1);
-	if (bitmap == NULL)
-	  return;
-	cursor = gdk_cursor_new_from_pixmap (bitmap, bitmap, &color, &color, 0, 0);
-	gdk_window_set_cursor (window, cursor);
-	gdk_cursor_unref (cursor);
-	g_object_unref (bitmap);
-	break;
-      }
-    case SWFDEC_MOUSE_CURSOR_TEXT:
-      cursor = gdk_cursor_new_for_display (display, GDK_XTERM);
-      gdk_window_set_cursor (window, cursor);
-      gdk_cursor_unref (cursor);
-      break;
-    case SWFDEC_MOUSE_CURSOR_CLICK:
-      cursor = gdk_cursor_new_for_display (display, GDK_HAND2);
-      gdk_window_set_cursor (window, cursor);
-      gdk_cursor_unref (cursor);
-      break;
-    case SWFDEC_MOUSE_CURSOR_NORMAL:
-      cursor = gdk_cursor_new_for_display (display, GDK_LEFT_PTR);
-      gdk_window_set_cursor (window, cursor);
-      gdk_cursor_unref (cursor);
-      break;
-    default:
-      g_warning ("invalid cursor %d", (int) swfcursor);
-      gdk_window_set_cursor (window, NULL);
-      break;
-  }
-}
-
-static void
-swfdec_widget_realize (GtkWidget *widget)
-{
-  GdkWindowAttr attributes;
-  gint attributes_mask;
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
-  attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = widget->allocation.x;
-  attributes.y = widget->allocation.y;
-  attributes.width = widget->allocation.width;
-  attributes.height = widget->allocation.height;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.event_mask = gtk_widget_get_events (widget);
-  attributes.event_mask |= GDK_EXPOSURE_MASK | 
-			   GDK_BUTTON_PRESS_MASK |
-			   GDK_BUTTON_RELEASE_MASK |
-			   GDK_LEAVE_NOTIFY_MASK | 
-			   GDK_POINTER_MOTION_MASK | 
-			   GDK_POINTER_MOTION_HINT_MASK;
-
-  attributes_mask = GDK_WA_X | GDK_WA_Y;
-
-  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
-      &attributes, attributes_mask);
-  gdk_window_set_user_data (widget->window, widget);
-
-  widget->style = gtk_style_attach (widget->style, widget->window);
-
-  if (SWFDEC_WIDGET (widget)->player) {
-    swfdec_widget_update_cursor (SWFDEC_WIDGET (widget));
-  }
-}
-
-static void
-swfdec_widget_class_init (SwfdecWidgetClass * g_class)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (g_class);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (g_class);
-
-  object_class->dispose = swfdec_widget_dispose;
-  object_class->get_property = swfdec_widget_get_property;
-  object_class->set_property = swfdec_widget_set_property;
-
-  g_object_class_install_property (object_class, PROP_PLAYER,
-      g_param_spec_object ("player", "player", "player that is displayed",
-	  SWFDEC_TYPE_PLAYER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
-  widget_class->realize = swfdec_widget_realize;
-  widget_class->size_request = swfdec_widget_size_request;
-  widget_class->size_allocate = swfdec_widget_size_allocate;
-  widget_class->expose_event = swfdec_widget_expose;
-  widget_class->button_press_event = swfdec_widget_button_press;
-  widget_class->button_release_event = swfdec_widget_button_release;
-  widget_class->motion_notify_event = swfdec_widget_motion_notify;
-  widget_class->leave_notify_event = swfdec_widget_leave_notify;
-}
-
-static void
-swfdec_widget_init (SwfdecWidget * widget)
-{
-  widget->real_scale = 1.0;
-  widget->interactive = TRUE;
-}
-
-static void
-swfdec_widget_invalidate_cb (SwfdecPlayer *player, double x, double y, 
-    double width, double height, SwfdecWidget *widget)
-{
-  GdkRectangle rect;
-
-  if (!GTK_WIDGET_REALIZED (widget))
-    return;
-  rect.x = floor (x * widget->real_scale);
-  rect.y = floor (y * widget->real_scale);
-  rect.width = ceil ((x + width) * widget->real_scale) - rect.x;
-  rect.height = ceil ((y + height) * widget->real_scale) - rect.y;
-  gdk_window_invalidate_rect (GTK_WIDGET (widget)->window, &rect, FALSE);
-}
-
-static void
-swfdec_widget_notify_cb (SwfdecPlayer *player, GParamSpec *pspec, SwfdecWidget *widget)
-{
-  if (g_str_equal (pspec->name, "mouse-cursor")) {
-    swfdec_widget_update_cursor (widget);
-  } else if (g_str_equal (pspec->name, "initialized")) {
-    gtk_widget_queue_resize (GTK_WIDGET (widget));
-  }
-}
-
-void
-swfdec_widget_set_player (SwfdecWidget *widget, SwfdecPlayer *player)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-  g_return_if_fail (player == NULL || SWFDEC_IS_PLAYER (player));
-  
-  if (widget->player) {
-    g_signal_handlers_disconnect_by_func (widget->player, swfdec_widget_invalidate_cb, widget);
-    g_signal_handlers_disconnect_by_func (widget->player, swfdec_widget_notify_cb, widget);
-    g_object_unref (widget->player);
-  }
-  widget->player = player;
-  if (player) {
-    g_signal_connect (player, "invalidate", G_CALLBACK (swfdec_widget_invalidate_cb), widget);
-    g_signal_connect (player, "notify", G_CALLBACK (swfdec_widget_notify_cb), widget);
-    g_object_ref (player);
-    swfdec_widget_update_cursor (widget);
-  } else {
-    if (GTK_WIDGET (widget)->window)
-      gdk_window_set_cursor (GTK_WIDGET (widget)->window, NULL); 
-  }
-  gtk_widget_queue_resize (GTK_WIDGET (widget));
-}
-
-GtkWidget *
-swfdec_widget_new (SwfdecPlayer *player)
-{
-  SwfdecWidget *widget;
-  
-  g_return_val_if_fail (player == NULL || SWFDEC_IS_PLAYER (player), NULL);
-
-  widget = g_object_new (SWFDEC_TYPE_WIDGET, "player", player, NULL);
-
-  return GTK_WIDGET (widget);
-}
-
-void
-swfdec_widget_set_scale	(SwfdecWidget *widget, double scale)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-  g_return_if_fail (scale >= 0.0);
-
-  widget->set_scale = scale;
-  gtk_widget_queue_resize (GTK_WIDGET (widget));
-}
-
-double
-swfdec_widget_get_scale (SwfdecWidget *widget)
-{
-  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), 1.0);
-
-  return widget->set_scale;
-}
-
-void
-swfdec_widget_set_use_image (SwfdecWidget *widget, gboolean use_image)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-
-  widget->use_image = use_image;
-  gtk_widget_queue_draw (GTK_WIDGET (widget));
-}
-
-gboolean
-swfdec_widget_get_use_image (SwfdecWidget *widget)
-{
-  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), 1.0);
-
-  return widget->use_image;
-}
-
-void
-swfdec_widget_set_interactive (SwfdecWidget *widget, gboolean interactive)
-{
-  g_return_if_fail (SWFDEC_IS_WIDGET (widget));
-
-  widget->interactive = interactive;
-}
-
-gboolean
-swfdec_widget_get_interactive (SwfdecWidget *widget)
-{
-  g_return_val_if_fail (SWFDEC_IS_WIDGET (widget), FALSE);
-
-  return widget->interactive;
-}
-
diff --git a/player/swfdec_widget.h b/player/swfdec_widget.h
deleted file mode 100644
index 1988f20..0000000
--- a/player/swfdec_widget.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Swfdec
- * Copyright (C) 2006 Benjamin Otte <otte at gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _SWFDEC_WIDGET_H_
-#define _SWFDEC_WIDGET_H_
-
-#include <gtk/gtk.h>
-#include <libswfdec/swfdec.h>
-
-G_BEGIN_DECLS
-
-typedef struct _SwfdecWidget SwfdecWidget;
-typedef struct _SwfdecWidgetClass SwfdecWidgetClass;
-
-#define SWFDEC_TYPE_WIDGET                    (swfdec_widget_get_type())
-#define SWFDEC_IS_WIDGET(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_WIDGET))
-#define SWFDEC_IS_WIDGET_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_WIDGET))
-#define SWFDEC_WIDGET(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_WIDGET, SwfdecWidget))
-#define SWFDEC_WIDGET_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_WIDGET, SwfdecWidgetClass))
-
-struct _SwfdecWidget
-{
-  GtkWidget		widget;
-
-  SwfdecPlayer *	player;		/* the video we play */
-
-  double		real_scale;	/* the real scale factor used */
-  double		set_scale;    	/* the set scale factor of the video */
-  gboolean		use_image;	/* TRUE to draw to an image first before rendering to Gtk */
-  gboolean		interactive;	/* if this widget propagates keyboard and mouse events */
-
-  int			button;		/* status of mouse button in displayed movie */
-};
-
-struct _SwfdecWidgetClass
-{
-  GtkWidgetClass	widget_class;
-};
-
-GType		swfdec_widget_get_type		(void);
-
-GtkWidget *	swfdec_widget_new		(SwfdecPlayer *	player);
-
-void		swfdec_widget_set_scale		(SwfdecWidget *	widget,
-						 double		scale);
-double		swfdec_widget_get_scale		(SwfdecWidget *	widget);
-void		swfdec_widget_set_use_image	(SwfdecWidget *	widget,
-						 gboolean	use_image);
-gboolean	swfdec_widget_get_use_image	(SwfdecWidget *	widget);
-void		swfdec_widget_set_interactive	(SwfdecWidget * widget,
-						 gboolean	interactive);
-gboolean	swfdec_widget_get_interactive	(SwfdecWidget * widget);
-void		swfdec_widget_set_player	(SwfdecWidget *	widget,
-						 SwfdecPlayer *	player);
-
-G_END_DECLS
-#endif
diff --git a/player/swfplay.c b/player/swfplay.c
index 6941529..e9d62ad 100644
--- a/player/swfplay.c
+++ b/player/swfplay.c
@@ -24,10 +24,11 @@
 #include <math.h>
 #include <libswfdec/swfdec.h>
 
-#include "swfdec_playback.h"
+#include <libswfdec-gtk/swfdec_playback.h>
+#include <libswfdec-gtk/swfdec_source.h>
+#include <libswfdec-gtk/swfdec_widget.h>
+
 #include "swfdec_slow_loader.h"
-#include "swfdec_source.h"
-#include "swfdec_widget.h"
 
 static gpointer playback;
 
diff-tree a6845d55ff3420aa75dd666e70ecf5dfb4fb5dd4 (from 269d33989c8bd3c9328b80bb3e78527fa845f011)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 12:21:27 2007 +0200

    s/SWF_(CFLAGS|LIBS)/SWFDEC_\1/

diff --git a/configure.ac b/configure.ac
index d56afba..5ac3db0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -202,10 +202,10 @@ AM_CONDITIONAL(HAVE_FFMPEG, [test "x$HAV
 
 AC_SUBST(GLOBAL_CFLAGS)
 
-SWF_CFLAGS="$SWF_CFLAGS -I\$(top_srcdir) $GLIB_CFLAGS"
-SWF_LIBS="$SWF_LIBS \$(top_builddir)/libswfdec/libswfdec-$SWFDEC_MAJORMINOR.la $MAD_LIBS $GLIB_LIBS -lz"
-AC_SUBST(SWF_LIBS)
-AC_SUBST(SWF_CFLAGS)
+SWFDEC_CFLAGS="-I\$(top_srcdir) $GLIB_CFLAGS"
+SWFDEC_LIBS="\$(top_builddir)/libswfdec/libswfdec-$SWFDEC_MAJORMINOR.la $GLIB_LIBS -lz"
+AC_SUBST(SWFDEC_LIBS)
+AC_SUBST(SWFDEC_CFLAGS)
 
 GTK_DOC_CHECK([1.6])
 
diff --git a/doc/Makefile.am b/doc/Makefile.am
index ba9c4cb..fdb3962 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -126,8 +126,8 @@ expand_content_files=
 # signals and properties.
 # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
 # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-INCLUDES=$(SWF_CFLAGS) $(CAIRO_CFLAGS)
-GTKDOC_LIBS=$(SWF_LIBS)
+INCLUDES=$(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+GTKDOC_LIBS=$(SWFDEC_LIBS)
 
 # This includes the standard gtk-doc make rules, copied by gtkdocize.
 include $(top_srcdir)/gtk-doc.make
diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 1270262..f7be47f 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -85,14 +85,14 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
 	swfdec_xml.c
 
 libswfdec_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
-	$(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) \
+	$(GLOBAL_CFLAGS) $(CAIRO_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) \
 	-I$(srcdir)/jpeg/ $(js_cflags) $(LIBOIL_CFLAGS) $(FFMPEG_CFLAGS) \
 	-DG_LOG_DOMAIN=\"Swfdec\"
 libswfdec_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
 	-version-info $(SWFDEC_LIBVERSION) \
 	-export-symbols-regex '^(swfdec_.*)' \
 	$(CAIRO_LIBS) $(GLIB_LIBS) $(PANGO_LIBS) $(MAD_LIBS) $(FFMPEG_LIBS) \
-	$(LIBOIL_LIBS)
+	$(LIBOIL_LIBS) -lz
 
 public_headers = \
 	swfdec.h \
diff --git a/libswfdec/js/Makefile.am b/libswfdec/js/Makefile.am
index 9350a6d..eda1132 100644
--- a/libswfdec/js/Makefile.am
+++ b/libswfdec/js/Makefile.am
@@ -89,7 +89,7 @@ jscpucfg_SOURCES = \
 	jscpucfg.c  \
 	jscpucfg.h
 
-libjs_la_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GLIB_CFLAGS) -I. -I$(top_builddir)/libswfdec/js \
+libjs_la_CFLAGS = $(GLOBAL_CFLAGS) $(GLIB_CFLAGS) -I. -I$(top_builddir)/libswfdec/js \
 	-DXP_UNIX -DDEBUG -fno-strict-aliasing
 libjs_la_LDFLAGS = -lm
 
diff --git a/player/Makefile.am b/player/Makefile.am
index 03217f0..f08f448 100644
--- a/player/Makefile.am
+++ b/player/Makefile.am
@@ -41,13 +41,13 @@ noinst_HEADERS = \
 	swfdec_slow_loader.h \
 	swfdec_widget.h 
 
-libswfdecui_la_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS) $(AUDIO_CFLAGS)
-libswfdecui_la_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS) $(AUDIO_LIBS)
-swfplay_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS)
-swfplay_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS)
+libswfdecui_la_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_CFLAGS) $(AUDIO_CFLAGS)
+libswfdecui_la_LDFLAGS = $(GTK_LIBS) $(SWFDEC_LIBS) $(AUDIO_LIBS)
+swfplay_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_CFLAGS)
+swfplay_LDFLAGS = $(GTK_LIBS) $(SWFDEC_LIBS)
 swfplay_LDADD = libswfdecui.la
-swfdebug_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-swfdebug_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS)
+swfdebug_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWFDEC_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfdebug_LDFLAGS = $(GTK_LIBS) $(SWFDEC_LIBS)
 swfdebug_LDADD = libswfdecui.la $(top_builddir)/libswfdec/js/libjs.la
 endif
 
diff --git a/test/Makefile.am b/test/Makefile.am
index e31046b..a38faf4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -8,24 +8,24 @@ else
 noinst_PROGRAMS = swfdec-extract dump parse 
 endif
 
-dump_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) $(PANGO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-dump_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
+dump_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS) $(PANGO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+dump_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
 
-parse_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS)
-parse_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+parse_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+parse_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
-swfdec_extract_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-swfdec_extract_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+swfdec_extract_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfdec_extract_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
-libswfedit_la_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-libswfedit_la_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS)
+libswfedit_la_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+libswfedit_la_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
 
-swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-swfedit_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS)
+swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfedit_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
 swfedit_LDADD = libswfedit.la
 
-swfscript_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-swfscript_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS)
+swfscript_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfscript_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
 swfscript_LDADD = libswfedit.la
 
 libswfedit_la_SOURCES = \
diff --git a/test/image/Makefile.am b/test/image/Makefile.am
index 84bed85..bbdbb2d 100644
--- a/test/image/Makefile.am
+++ b/test/image/Makefile.am
@@ -2,8 +2,8 @@ check_PROGRAMS = image
 TESTS = $(check_PROGRAMS)
 
 image_SOURCES = image.c
-image_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS)
-image_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+image_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+image_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
 EXTRA_DIST = \
 	README \
diff --git a/test/sound/Makefile.am b/test/sound/Makefile.am
index 411d1d1..9face8b 100644
--- a/test/sound/Makefile.am
+++ b/test/sound/Makefile.am
@@ -13,8 +13,8 @@ downsample_CFLAGS = $(GLOBAL_CFLAGS) $(G
 downsample_LDFLAGS = $(GLIB_LIBS)
 
 sound_SOURCES = sound.c
-sound_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS)
-sound_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+sound_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+sound_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
 EXTRA_DIST = \
 	README \
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index f11d827..c7b4870 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -4,8 +4,8 @@ TESTS = $(check_PROGRAMS)
 
 trace_SOURCES = trace.c
 
-trace_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS)
-trace_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+trace_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+trace_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
 EXTRA_DIST = \
 	README \
diff --git a/test/various/Makefile.am b/test/various/Makefile.am
index b16762f..59beb05 100644
--- a/test/various/Makefile.am
+++ b/test/various/Makefile.am
@@ -2,10 +2,10 @@ check_PROGRAMS = ringbuffer urlencode
 TESTS = $(check_PROGRAMS)
 
 ringbuffer_SOURCES = ringbuffer.c
-ringbuffer_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS)
-ringbuffer_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+ringbuffer_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+ringbuffer_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
 urlencode_SOURCES = urlencode.c
-urlencode_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS)
-urlencode_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+urlencode_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(CAIRO_CFLAGS)
+urlencode_LDFLAGS = $(SWFDEC_LIBS) $(CAIRO_LIBS)
 
diff-tree 269d33989c8bd3c9328b80bb3e78527fa845f011 (from 20fce106dfb4e4f314fa9ed2eb639448a0b5d854)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Mar 26 12:04:30 2007 +0200

    Add build infrastructure for a libswfdec-gtk

diff --git a/Makefile.am b/Makefile.am
index da1c94a..25bbed2 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,6 @@
 SUBDIRS= \
 	libswfdec \
+	libswfdec-gtk \
 	player \
 	doc \
 	test
@@ -18,13 +19,20 @@ EXTRA_DIST=depcomp \
 	m4/ax_create_stdint_h.m4
 
 pkgconfigdir = $(libdir)/pkgconfig
+if WITH_GTK
+pkgconfig_DATA = swfdec- at SWFDEC_MAJORMINOR@.pc swfdec-gtk- at SWFDEC_MAJORMINOR@.pc
+else
 pkgconfig_DATA = swfdec- at SWFDEC_MAJORMINOR@.pc
+endif
 
-CLEANFILES = swfdec-$(SWFDEC_MAJORMINOR).pc
+CLEANFILES = swfdec-$(SWFDEC_MAJORMINOR).pc swfdec-gtk-$(SWFDEC_MAJORMINOR).pc
 
 swfdec- at SWFDEC_MAJORMINOR@.pc: swfdec.pc
 	cp swfdec.pc swfdec- at SWFDEC_MAJORMINOR@.pc
 
+swfdec-gtk- at SWFDEC_MAJORMINOR@.pc: swfdec-gtk.pc
+	cp swfdec-gtk.pc swfdec-gtk- at SWFDEC_MAJORMINOR@.pc
+
 # build documentation when doing distcheck
 DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
 
diff --git a/configure.ac b/configure.ac
index 70976c9..d56afba 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,13 +82,31 @@ fi
 AC_SUBST(PANGO_LIBS)
 AC_SUBST(PANGO_CFLAGS)
 
-PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, HAVE_GTK=yes, HAVE_GTK=no)
-AC_SUBST(GTK_LIBS)
-AC_SUBST(GTK_CFLAGS)
-if test "$HAVE_GTK" = "no"; then
-  AC_MSG_WARN([cannot find GTK+-2.0, player will be disabled])
+AC_ARG_ENABLE(gtk,
+	AS_HELP_STRING([--enable-gtk],
+			[enable Gtk integration (default=yes)])],
+	enable_gtk=$enableval,
+	enable_gtk="yes")
+
+dnl 
+dnl GTK: We want this for swfdec-gtk
+dnl
+GTK_REQUIRES=2.8.0
+AC_SUBST(GTK_REQUIRES)
+if test "$enable_gtk" = "yes"; then
+	PKG_CHECK_MODULES(GTK, gtk+-2.0 >= $GTK_REQUIRES, HAVE_GTK=yes, HAVE_GTK=no)
+	if test "$HAVE_GTK" = "no"; then
+	  AC_MSG_WARN([cannot find GTK+-2.0, player will be disabled])
+	fi
+	if test "x$HAVE_GTK" = xyes; then
+	  AC_DEFINE(HAVE_GTK, 1, [Define if Gtk is enabled])
+	else
+	  AC_MSG_ERROR([Couldn't find a suitable Gtk version. You need at least version $GTK_REQUIRES])
+	fi
+else
+	AC_MSG_WARN([*** Gtk support was not enabled. ***])
 fi
-AM_CONDITIONAL(WITH_GTK,[test "$HAVE_GTK" != "no"])
+AM_CONDITIONAL(WITH_GTK, [test "x$HAVE_GTK" = xyes])
 
 dnl
 dnl audio backend
@@ -211,6 +229,7 @@ doc/Makefile
 libswfdec/Makefile
 libswfdec/jpeg/Makefile
 libswfdec/js/Makefile
+libswfdec-gtk/Makefile
 player/Makefile
 test/Makefile
 test/image/Makefile
@@ -218,6 +237,7 @@ test/sound/Makefile
 test/trace/Makefile
 test/various/Makefile
 swfdec.pc
+swfdec-gtk.pc
 swfdec.spec
 )
 
diff --git a/libswfdec-gtk/.gitignore b/libswfdec-gtk/.gitignore
new file mode 100644
index 0000000..87c0f2d
--- /dev/null
+++ b/libswfdec-gtk/.gitignore
@@ -0,0 +1,13 @@
+*~
+CVS
+.cvsignore
+.deps
+.libs
+
+Makefile
+Makefile.in
+*.o
+*.la
+*.lo
+*.loT
+
diff --git a/libswfdec-gtk/Makefile.am b/libswfdec-gtk/Makefile.am
new file mode 100644
index 0000000..e69de29
diff --git a/swfdec-gtk.pc.in b/swfdec-gtk.pc.in
new file mode 100644
index 0000000..1b866f0
--- /dev/null
+++ b/swfdec-gtk.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@/swfdec- at SWFDEC_MAJORMINOR@
+
+Name: swfdec-gtk
+Description: Support for playing Flash files in Gtk using Swfdec
+Version: @VERSION@
+Requires: swfdec- at SWFDEC_MAJORMINOR@ = @PACKAGE_VERSION@ gtk+-2.0 >= @GTK_REQUIRES@
+Libs: -L${libdir} -lswfdec- at SWFDEC_MAJORMINOR@
+Cflags: -I${includedir}


More information about the Swfdec mailing list