[Swfdec] 3 commits - autogen.sh configure.ac player/.gitignore
player/Makefile.am player/swfdec_playback_alsa.c
player/swfdec_playback.c player/swfdec_playback_none.c
Benjamin Otte
company at kemper.freedesktop.org
Mon Jan 29 13:37:22 PST 2007
autogen.sh | 2 +-
configure.ac | 39 +++++++++++++++++++++++++++++++++------
player/.gitignore | 1 +
player/Makefile.am | 28 +++++++++++++++++++---------
player/swfdec_playback_none.c | 38 ++++++++++++++++++++++++++++++++++++++
5 files changed, 92 insertions(+), 16 deletions(-)
New commits:
diff-tree 133819a86a6435cce34751911118b74dd51f9bfc (from parents)
Merge: d3add5d691f7832d56e3126003ce242822bfe11d 4e7806e7020535920cbb2009ed8b039fd64c046c
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 22:34:49 2007 +0100
Merge branch 'master' of ssh://company@git.freedesktop.org/git/swfdec
diff-tree d3add5d691f7832d56e3126003ce242822bfe11d (from f9f53b7a60b641e2ba5c846430f2fb48ac013eb0)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 22:33:27 2007 +0100
rework audio configuration subsystem
- make it easier to plug new backends
- add a "none" backend when alsa isn't available
diff --git a/configure.ac b/configure.ac
index eb69535..e02adfd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -86,13 +86,40 @@ if test "$HAVE_GTK" = "no"; then
fi
AM_CONDITIONAL(WITH_GTK,[test "$HAVE_GTK" != "no"])
-PKG_CHECK_MODULES(ALSA, alsa >= 1.0, HAVE_ALSA=yes, HAVE_ALSA=no)
-AC_SUBST(ALSA_LIBS)
-AC_SUBST(ALSA_CFLAGS)
-if test "$HAVE_ALSA" = "no"; then
- AC_MSG_WARN([cannot find alsa, player will be disabled])
+dnl
+dnl audio backend
+dnl
+AC_ARG_WITH(audio,
+ [AC_HELP_STRING([--with-audio=@<:@auto/alsa/none@:>@],
+ [audio backend to use])],,
+ [with_audio=auto])
+
+AUDIO_TYPE=
+if test "$with_audio" = "auto" -o "$with_audio" = "alsa"; then
+ PKG_CHECK_MODULES(ALSA, alsa >= 1.0, AUDIO_TYPE=alsa)
+ if test "$AUDIO_TYPE" = "alsa"; then
+ with_audio=alsa
+ else
+ AC_MSG_WARN([no alsa audio support])
+ fi
+ AUDIO_CFLAGS=$ALSA_CFLAGS
+ AUDIO_LIBS=$ALSA_LIBS
+fi
+
+if test "$with_audio" = "auto" -o "$with_audio" = "none"; then
+ AUDIO_CFLAGS=
+ AUDIO_LIBS=
+ AUDIO_TYPE=none
fi
-AM_CONDITIONAL(WITH_ALSA,[test "$HAVE_ALSA" != "no"])
+
+if test "x$AUDIO_TYPE" = "x"; then
+ AC_MSG_ERROR([desired audio support could not be used])
+else
+ AC_MSG_NOTICE([audio backend: $AUDIO_TYPE])
+fi
+AC_SUBST(AUDIO_LIBS)
+AC_SUBST(AUDIO_CFLAGS)
+AC_SUBST(AUDIO_TYPE)
PKG_CHECK_MODULES(LIBOIL, liboil-0.3 >= 0.3.1.1, HAVE_LIBOIL=yes, HAVE_LIBOIL=no)
AC_SUBST(LIBOIL_LIBS)
diff --git a/player/.gitignore b/player/.gitignore
index 3e3d43c..f2dfbf1 100644
--- a/player/.gitignore
+++ b/player/.gitignore
@@ -9,6 +9,7 @@ Makefile.in
*.o
*.lo
*.loT
+swfdec_playback.c
libswfdecui.la
swfdebug
diff --git a/player/Makefile.am b/player/Makefile.am
index 0a29cc5..c56ee91 100644
--- a/player/Makefile.am
+++ b/player/Makefile.am
@@ -1,5 +1,13 @@
if WITH_GTK
-if WITH_ALSA
+
+# 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
@@ -31,15 +39,17 @@ noinst_HEADERS = \
swfdec_slow_loader.h \
swfdec_widget.h
-libswfdecui_la_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS) $(ALSA_CFLAGS)
-libswfdecui_la_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS) $(ALSA_LIBS)
-swfplay_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS) $(ALSA_CFLAGS)
-swfplay_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS) $(ALSA_LIBS)
+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)
swfplay_LDADD = libswfdecui.la
-swfdebug_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS) $(ALSA_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
-swfdebug_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS) $(ALSA_LIBS)
+swfdebug_CFLAGS = $(GLOBAL_CFLAGS) $(GTK_CFLAGS) $(SWF_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfdebug_LDFLAGS = $(GTK_LIBS) $(SWF_LIBS)
swfdebug_LDADD = libswfdecui.la $(top_builddir)/libswfdec/js/libjs.la
endif
-endif
-EXTRA_DIST = swfdebug.c swfplay.c swfdec_widget.c swfdec_widget.h swfdec_playback.c swfdec_playback.h
+EXTRA_DIST = \
+ swfdec_playback_alsa.c \
+ swfdec_playback_none.c
+
diff --git a/player/swfdec_playback.c b/player/swfdec_playback.c
deleted file mode 100644
index ea47099..0000000
--- a/player/swfdec_playback.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_alsa.c b/player/swfdec_playback_alsa.c
new file mode 100644
index 0000000..ea47099
--- /dev/null
+++ b/player/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/player/swfdec_playback_none.c b/player/swfdec_playback_none.c
new file mode 100644
index 0000000..6464a4a
--- /dev/null
+++ b/player/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-tree f9f53b7a60b641e2ba5c846430f2fb48ac013eb0 (from 2cb8680a8577ff5d018b50e7da55c233e8eaa4af)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 22:31:13 2007 +0100
enable gtk-doc in autogen.sh
developers are supposed to ensure that docs build and make dist requires it
diff --git a/autogen.sh b/autogen.sh
index 13824b4..fee343b 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,3 +1,3 @@
#!/bin/sh
autoreconf -i -f &&
-./configure --enable-maintainer-mode --disable-static $@
+./configure --enable-maintainer-mode --disable-static --enable-gtk-doc $@
More information about the Swfdec
mailing list