[Swfdec-commits] swfdec-gtk/swfdec_playback_pa.c swfdec-gtk/swfdec_playback_pulse.c

Eric Anholt anholt at kemper.freedesktop.org
Tue Apr 29 22:26:36 PDT 2008


 swfdec-gtk/swfdec_playback_pa.c    |  357 -------------------------------------
 swfdec-gtk/swfdec_playback_pulse.c |  357 +++++++++++++++++++++++++++++++++++++
 2 files changed, 357 insertions(+), 357 deletions(-)

New commits:
commit 9a10dab0eec40b5cc4f96c822d98b381816ada20
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Apr 29 22:25:14 2008 -0700

    Fix swfdec PA build after configure.ac rename of the option.

diff --git a/swfdec-gtk/swfdec_playback_pa.c b/swfdec-gtk/swfdec_playback_pa.c
deleted file mode 100644
index 55b05c2..0000000
--- a/swfdec-gtk/swfdec_playback_pa.c
+++ /dev/null
@@ -1,357 +0,0 @@
-/* Swfdec
- * Copyright © 2006 Benjamin Otte <otte at gnome.org>
- * Copyright © 2007 Eric Anholt <eric at anholt.net>
- *
- * 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 <stdlib.h>
-#include <string.h>
-
-#include "swfdec_playback.h"
-#include "pulse/pulseaudio.h"
-#include "pulse/glib-mainloop.h"
-
-/** @file Implements swfdec audio playback by dumping swfdec streams out
- * using pulseaudio streams.
- */
-
-/*** DEFINITIONS ***/
-
-struct _SwfdecPlayback {
-  SwfdecPlayer *	player;
-  GList *		streams;	/* all Stream objects */
-  GMainContext *	context;	/* glib context we work in */
-  pa_glib_mainloop *	pa_mainloop;	/* PA to glib mainloop connection */
-  pa_context *		pa;		/* PA context for sound rendering */
-};
-
-typedef struct {
-  SwfdecPlayback *     	sound;		/* reference to sound object */
-  SwfdecAudio *		audio;		/* the audio we play back */
-  guint			offset;		/* offset into sound */
-  pa_stream *		pa;		/* PA stream */
-  pa_cvolume		volume;		/* Volume control.  Not yet used. */
-  gboolean		no_more;
-} Stream;
-
-/* Size of one of our audio samples, in bytes */
-#define SAMPLESIZE	2
-#define CHANNELS	2
-
-/*** STREAMS ***/
-
-static void
-stream_write_callback (pa_stream *pa,
-		       size_t bytes,
-		       void *data)
-{
-  Stream *stream = data;
-  char *frag;
-  unsigned int samples = bytes / SAMPLESIZE / CHANNELS;
-  int err;
-
-  if (stream->no_more)
-    return;
-
-  /* Adjust to our rounded-down number */
-  bytes = samples * SAMPLESIZE * CHANNELS;
-
-  frag = malloc (bytes);
-  if (frag == NULL) {
-    g_printerr ("Failed to allocate fragment of size %d\n", (int)bytes);
-    return;
-  }
-
-  /* Set up our fragment and render swfdec's audio into it. The swfdec audio
-   * decoder renders deltas from the existing data in the fragment.
-   */
-  memset (frag, 0, bytes);
-  swfdec_audio_render (stream->audio, (gint16 *)frag, stream->offset,
-		       samples);
-
-  /* Send the new fragment out the PA stream */
-  err = pa_stream_write (pa, frag, bytes, NULL, 0, PA_SEEK_RELATIVE);
-  if (err != 0) {
-    g_printerr ("Failed to write fragment to PA stream: %s\n",
-		pa_strerror(pa_context_errno(stream->sound->pa)));
-  }
-
-  /* Advance playback pointer */
-  stream->offset += samples;
-
-  free(frag);
-}
-
-static void
-stream_drain_complete (pa_stream *pa, int success, void *data)
-{
-  Stream *stream = data;
-
-  pa_stream_disconnect (stream->pa);
-  pa_stream_unref (stream->pa);
-  g_object_unref (stream->audio);
-  g_free (stream);
-}
-
-static void
-swfdec_playback_stream_close (Stream *stream)
-{
-  /* Pull it off of the active stream list. */
-  stream->sound->streams = g_list_remove (stream->sound->streams, stream);
-
-  /* If we have created a PA stream, defer freeing until we drain it. */
-  if (stream->pa != NULL) {
-    pa_operation *o;
-
-    stream->no_more = 1;
-
-    o = pa_stream_drain (stream->pa, stream_drain_complete, stream);
-    if (o != NULL) {
-      pa_operation_unref (o);
-      return;
-    } else {
-      g_printerr("PA stream drain failed: %s\n",
-		 pa_strerror(pa_context_errno(stream->sound->pa)));
-    }
-  }
-  g_object_unref (stream->audio);
-  g_free (stream);
-}
-
-static void
-stream_state_callback (pa_stream *pa, void *data)
-{
-  switch (pa_stream_get_state(pa)) {
-  case PA_STREAM_CREATING:
-  case PA_STREAM_TERMINATED:
-  case PA_STREAM_READY:
-  case PA_STREAM_UNCONNECTED:
-    break;
-
-  case PA_STREAM_FAILED:
-    g_printerr("PA stream failed: %s\n",
-	       pa_strerror(pa_context_errno(pa_stream_get_context(pa))));
-  default:
-    break;
-  }
-}
-
-static void
-swfdec_playback_stream_open (SwfdecPlayback *sound, SwfdecAudio *audio)
-{
-  Stream *stream;
-  pa_sample_spec spec = {
-    .format = PA_SAMPLE_S16LE,
-    .rate = 44100,
-    .channels = CHANNELS,
-  };
-  int err;
-
-  stream = g_new0 (Stream, 1);
-  stream->sound = sound;
-  stream->audio = g_object_ref (audio);
-  sound->streams = g_list_prepend (sound->streams, stream);
-
-  /* If we failed to initialize the context, don't try to create the stream.
-   * We still have to get put in the list, because swfdec_playback.c expects
-   * to find it in the list for removal later.
-   */
-  if (sound->pa == NULL)
-    return;
-
-  /* Create our stream */
-  stream->pa = pa_stream_new(sound->pa,
-			     "swfdec stream",
-			     &spec,
-			     NULL /* Default channel map */
-			     );
-  if (stream->pa == NULL) {
-    g_printerr("Failed to create PA stream\n");
-    swfdec_playback_stream_close(stream);
-    return;
-  }
-
-  /* Start at default volume */
-  pa_cvolume_set(&stream->volume, CHANNELS, PA_VOLUME_NORM);
-
-  /* Hook up our stream write callback for when new data is needed */
-  pa_stream_set_state_callback(stream->pa, stream_state_callback, stream);
-  pa_stream_set_write_callback(stream->pa, stream_write_callback, stream);
-
-  /* Connect it up as a playback stream. */
-  err = pa_stream_connect_playback(stream->pa,
-				   NULL, /* Default device */
-				   NULL /* Default buffering */,
-				   0, /* No flags */
-				   &stream->volume,
-				   NULL /* Don't sync to any stream */
-				   );
-  if (err != 0) {
-    g_printerr ("Failed to connect PA stream: %s\n",
-		pa_strerror(pa_context_errno(sound->pa)));
-    swfdec_playback_stream_close(stream);
-    return;
-  }
-}
-
-/*** SOUND ***/
-
-static void
-advance_before (SwfdecPlayer *player, guint msecs, guint audio_samples, gpointer data)
-{
-  SwfdecPlayback *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, SwfdecPlayback *sound)
-{
-  swfdec_playback_stream_open (sound, audio);
-}
-
-static void
-audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, SwfdecPlayback *sound)
-{
-  GList *walk;
-
-  for (walk = sound->streams; walk; walk = walk->next) {
-    Stream *stream = walk->data;
-    if (stream->audio == audio) {
-      swfdec_playback_stream_close (stream);
-      return;
-    }
-  }
-  g_assert_not_reached ();
-}
-static void
-context_state_callback (pa_context *pa, void *data)
-{
-  SwfdecPlayback *sound = data;
-
-  switch (pa_context_get_state(pa)) {
-  case PA_CONTEXT_FAILED:
-    g_printerr ("PA context failed\n");
-    pa_context_unref (pa);
-    sound->pa = NULL;
-    break;
-
-  default:
-  case PA_CONTEXT_TERMINATED:
-  case PA_CONTEXT_UNCONNECTED:
-  case PA_CONTEXT_CONNECTING:
-  case PA_CONTEXT_AUTHORIZING:
-  case PA_CONTEXT_SETTING_NAME:
-  case PA_CONTEXT_READY:
-    break;
-
-  }
-}
-
-SwfdecPlayback *
-swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
-{
-  SwfdecPlayback *sound;
-  const GList *walk;
-  pa_mainloop_api *pa_api;
-
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
-  g_return_val_if_fail (context != NULL, NULL);
-
-  sound = g_new0 (SwfdecPlayback, 1);
-  sound->player = 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);
-
-  /* Create our mainloop attachment to glib.  XXX: I hope this means we don't
-   * have to run the main loop using pa functions.
-   */
-  sound->pa_mainloop = pa_glib_mainloop_new (context);
-  pa_api = pa_glib_mainloop_get_api (sound->pa_mainloop);
-
-  sound->pa = pa_context_new (pa_api, "swfdec");
-
-  pa_context_set_state_callback (sound->pa, context_state_callback, sound);
-  pa_context_connect (sound->pa,
-		      NULL, /* default server */
-		      0, /* default flags */
-		      NULL /* spawning api */
-		      );
-
-  for (walk = swfdec_player_get_audio (player); walk; walk = walk->next) {
-    swfdec_playback_stream_open (sound, walk->data);
-  }
-  g_main_context_ref (context);
-  sound->context = context;
-  return sound;
-}
-
-static void
-context_drain_complete (pa_context *pa, void *data)
-{
-  pa_context_disconnect (pa);
-  pa_context_unref (pa);
-}
-
-void
-swfdec_playback_close (SwfdecPlayback *sound)
-{
-  pa_operation *op;
-
-#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_playback_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);
-
-  if (sound->pa != NULL) {
-    op = pa_context_drain (sound->pa, context_drain_complete, NULL);
-    if (op == NULL) {
-      pa_context_disconnect (sound->pa);
-      pa_context_unref (sound->pa);
-    } else {
-      pa_operation_unref (op);
-    }
-    pa_glib_mainloop_free (sound->pa_mainloop);
-  }
-
-  g_main_context_unref (sound->context);
-  g_free (sound);
-}
-
-
diff --git a/swfdec-gtk/swfdec_playback_pulse.c b/swfdec-gtk/swfdec_playback_pulse.c
new file mode 100644
index 0000000..55b05c2
--- /dev/null
+++ b/swfdec-gtk/swfdec_playback_pulse.c
@@ -0,0 +1,357 @@
+/* Swfdec
+ * Copyright © 2006 Benjamin Otte <otte at gnome.org>
+ * Copyright © 2007 Eric Anholt <eric at anholt.net>
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include "swfdec_playback.h"
+#include "pulse/pulseaudio.h"
+#include "pulse/glib-mainloop.h"
+
+/** @file Implements swfdec audio playback by dumping swfdec streams out
+ * using pulseaudio streams.
+ */
+
+/*** DEFINITIONS ***/
+
+struct _SwfdecPlayback {
+  SwfdecPlayer *	player;
+  GList *		streams;	/* all Stream objects */
+  GMainContext *	context;	/* glib context we work in */
+  pa_glib_mainloop *	pa_mainloop;	/* PA to glib mainloop connection */
+  pa_context *		pa;		/* PA context for sound rendering */
+};
+
+typedef struct {
+  SwfdecPlayback *     	sound;		/* reference to sound object */
+  SwfdecAudio *		audio;		/* the audio we play back */
+  guint			offset;		/* offset into sound */
+  pa_stream *		pa;		/* PA stream */
+  pa_cvolume		volume;		/* Volume control.  Not yet used. */
+  gboolean		no_more;
+} Stream;
+
+/* Size of one of our audio samples, in bytes */
+#define SAMPLESIZE	2
+#define CHANNELS	2
+
+/*** STREAMS ***/
+
+static void
+stream_write_callback (pa_stream *pa,
+		       size_t bytes,
+		       void *data)
+{
+  Stream *stream = data;
+  char *frag;
+  unsigned int samples = bytes / SAMPLESIZE / CHANNELS;
+  int err;
+
+  if (stream->no_more)
+    return;
+
+  /* Adjust to our rounded-down number */
+  bytes = samples * SAMPLESIZE * CHANNELS;
+
+  frag = malloc (bytes);
+  if (frag == NULL) {
+    g_printerr ("Failed to allocate fragment of size %d\n", (int)bytes);
+    return;
+  }
+
+  /* Set up our fragment and render swfdec's audio into it. The swfdec audio
+   * decoder renders deltas from the existing data in the fragment.
+   */
+  memset (frag, 0, bytes);
+  swfdec_audio_render (stream->audio, (gint16 *)frag, stream->offset,
+		       samples);
+
+  /* Send the new fragment out the PA stream */
+  err = pa_stream_write (pa, frag, bytes, NULL, 0, PA_SEEK_RELATIVE);
+  if (err != 0) {
+    g_printerr ("Failed to write fragment to PA stream: %s\n",
+		pa_strerror(pa_context_errno(stream->sound->pa)));
+  }
+
+  /* Advance playback pointer */
+  stream->offset += samples;
+
+  free(frag);
+}
+
+static void
+stream_drain_complete (pa_stream *pa, int success, void *data)
+{
+  Stream *stream = data;
+
+  pa_stream_disconnect (stream->pa);
+  pa_stream_unref (stream->pa);
+  g_object_unref (stream->audio);
+  g_free (stream);
+}
+
+static void
+swfdec_playback_stream_close (Stream *stream)
+{
+  /* Pull it off of the active stream list. */
+  stream->sound->streams = g_list_remove (stream->sound->streams, stream);
+
+  /* If we have created a PA stream, defer freeing until we drain it. */
+  if (stream->pa != NULL) {
+    pa_operation *o;
+
+    stream->no_more = 1;
+
+    o = pa_stream_drain (stream->pa, stream_drain_complete, stream);
+    if (o != NULL) {
+      pa_operation_unref (o);
+      return;
+    } else {
+      g_printerr("PA stream drain failed: %s\n",
+		 pa_strerror(pa_context_errno(stream->sound->pa)));
+    }
+  }
+  g_object_unref (stream->audio);
+  g_free (stream);
+}
+
+static void
+stream_state_callback (pa_stream *pa, void *data)
+{
+  switch (pa_stream_get_state(pa)) {
+  case PA_STREAM_CREATING:
+  case PA_STREAM_TERMINATED:
+  case PA_STREAM_READY:
+  case PA_STREAM_UNCONNECTED:
+    break;
+
+  case PA_STREAM_FAILED:
+    g_printerr("PA stream failed: %s\n",
+	       pa_strerror(pa_context_errno(pa_stream_get_context(pa))));
+  default:
+    break;
+  }
+}
+
+static void
+swfdec_playback_stream_open (SwfdecPlayback *sound, SwfdecAudio *audio)
+{
+  Stream *stream;
+  pa_sample_spec spec = {
+    .format = PA_SAMPLE_S16LE,
+    .rate = 44100,
+    .channels = CHANNELS,
+  };
+  int err;
+
+  stream = g_new0 (Stream, 1);
+  stream->sound = sound;
+  stream->audio = g_object_ref (audio);
+  sound->streams = g_list_prepend (sound->streams, stream);
+
+  /* If we failed to initialize the context, don't try to create the stream.
+   * We still have to get put in the list, because swfdec_playback.c expects
+   * to find it in the list for removal later.
+   */
+  if (sound->pa == NULL)
+    return;
+
+  /* Create our stream */
+  stream->pa = pa_stream_new(sound->pa,
+			     "swfdec stream",
+			     &spec,
+			     NULL /* Default channel map */
+			     );
+  if (stream->pa == NULL) {
+    g_printerr("Failed to create PA stream\n");
+    swfdec_playback_stream_close(stream);
+    return;
+  }
+
+  /* Start at default volume */
+  pa_cvolume_set(&stream->volume, CHANNELS, PA_VOLUME_NORM);
+
+  /* Hook up our stream write callback for when new data is needed */
+  pa_stream_set_state_callback(stream->pa, stream_state_callback, stream);
+  pa_stream_set_write_callback(stream->pa, stream_write_callback, stream);
+
+  /* Connect it up as a playback stream. */
+  err = pa_stream_connect_playback(stream->pa,
+				   NULL, /* Default device */
+				   NULL /* Default buffering */,
+				   0, /* No flags */
+				   &stream->volume,
+				   NULL /* Don't sync to any stream */
+				   );
+  if (err != 0) {
+    g_printerr ("Failed to connect PA stream: %s\n",
+		pa_strerror(pa_context_errno(sound->pa)));
+    swfdec_playback_stream_close(stream);
+    return;
+  }
+}
+
+/*** SOUND ***/
+
+static void
+advance_before (SwfdecPlayer *player, guint msecs, guint audio_samples, gpointer data)
+{
+  SwfdecPlayback *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, SwfdecPlayback *sound)
+{
+  swfdec_playback_stream_open (sound, audio);
+}
+
+static void
+audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, SwfdecPlayback *sound)
+{
+  GList *walk;
+
+  for (walk = sound->streams; walk; walk = walk->next) {
+    Stream *stream = walk->data;
+    if (stream->audio == audio) {
+      swfdec_playback_stream_close (stream);
+      return;
+    }
+  }
+  g_assert_not_reached ();
+}
+static void
+context_state_callback (pa_context *pa, void *data)
+{
+  SwfdecPlayback *sound = data;
+
+  switch (pa_context_get_state(pa)) {
+  case PA_CONTEXT_FAILED:
+    g_printerr ("PA context failed\n");
+    pa_context_unref (pa);
+    sound->pa = NULL;
+    break;
+
+  default:
+  case PA_CONTEXT_TERMINATED:
+  case PA_CONTEXT_UNCONNECTED:
+  case PA_CONTEXT_CONNECTING:
+  case PA_CONTEXT_AUTHORIZING:
+  case PA_CONTEXT_SETTING_NAME:
+  case PA_CONTEXT_READY:
+    break;
+
+  }
+}
+
+SwfdecPlayback *
+swfdec_playback_open (SwfdecPlayer *player, GMainContext *context)
+{
+  SwfdecPlayback *sound;
+  const GList *walk;
+  pa_mainloop_api *pa_api;
+
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  g_return_val_if_fail (context != NULL, NULL);
+
+  sound = g_new0 (SwfdecPlayback, 1);
+  sound->player = 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);
+
+  /* Create our mainloop attachment to glib.  XXX: I hope this means we don't
+   * have to run the main loop using pa functions.
+   */
+  sound->pa_mainloop = pa_glib_mainloop_new (context);
+  pa_api = pa_glib_mainloop_get_api (sound->pa_mainloop);
+
+  sound->pa = pa_context_new (pa_api, "swfdec");
+
+  pa_context_set_state_callback (sound->pa, context_state_callback, sound);
+  pa_context_connect (sound->pa,
+		      NULL, /* default server */
+		      0, /* default flags */
+		      NULL /* spawning api */
+		      );
+
+  for (walk = swfdec_player_get_audio (player); walk; walk = walk->next) {
+    swfdec_playback_stream_open (sound, walk->data);
+  }
+  g_main_context_ref (context);
+  sound->context = context;
+  return sound;
+}
+
+static void
+context_drain_complete (pa_context *pa, void *data)
+{
+  pa_context_disconnect (pa);
+  pa_context_unref (pa);
+}
+
+void
+swfdec_playback_close (SwfdecPlayback *sound)
+{
+  pa_operation *op;
+
+#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_playback_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);
+
+  if (sound->pa != NULL) {
+    op = pa_context_drain (sound->pa, context_drain_complete, NULL);
+    if (op == NULL) {
+      pa_context_disconnect (sound->pa);
+      pa_context_unref (sound->pa);
+    } else {
+      pa_operation_unref (op);
+    }
+    pa_glib_mainloop_free (sound->pa_mainloop);
+  }
+
+  g_main_context_unref (sound->context);
+  g_free (sound);
+}
+
+


More information about the Swfdec-commits mailing list