fix build for --disable-gtk-doc
[swfdec.git] / swfdec / swfdec_audio_stream.c
blob857fecdc31d9720ca6ddbad0e28dc049763bc649
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include <string.h>
27 #include "swfdec_audio_stream.h"
28 #include "swfdec_debug.h"
29 #include "swfdec_sound.h"
30 #include "swfdec_sprite.h"
33 G_DEFINE_TYPE (SwfdecAudioStream, swfdec_audio_stream, SWFDEC_TYPE_AUDIO)
35 static void
36 swfdec_audio_stream_dispose (GObject *object)
38 SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (object);
40 if (stream->decoder != NULL) {
41 g_object_unref (stream->decoder);
42 stream->decoder = NULL;
44 g_queue_foreach (stream->queue, (GFunc) swfdec_buffer_unref, NULL);
45 g_queue_free (stream->queue);
47 G_OBJECT_CLASS (swfdec_audio_stream_parent_class)->dispose (object);
50 /* returns: number of samples available */
51 static void
52 swfdec_audio_stream_require (SwfdecAudioStream *stream, guint n_samples)
54 SwfdecAudioStreamClass *klass = SWFDEC_AUDIO_STREAM_GET_CLASS (stream);
55 SwfdecBuffer *buffer;
57 /* subclasses are responsible for having set a proper decoder */
58 g_assert (SWFDEC_IS_AUDIO_DECODER (stream->decoder));
60 while (stream->queue_size < n_samples && !stream->done) {
61 /* if the decoder still has data */
62 buffer = swfdec_audio_decoder_pull (stream->decoder);
63 if (buffer) {
64 g_queue_push_tail (stream->queue, buffer);
65 stream->queue_size += buffer->length / 4;
66 continue;
68 /* otherwise get a new buffer from the decoder */
69 buffer = klass->pull (stream);
70 if (buffer == NULL) {
71 stream->buffering = TRUE;
72 break;
74 swfdec_audio_decoder_push (stream->decoder, buffer);
75 swfdec_buffer_unref (buffer);
79 static gsize
80 swfdec_audio_stream_render (SwfdecAudio *audio, gint16* dest,
81 gsize start, gsize n_samples)
83 SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (audio);
84 GList *walk;
85 gsize samples, rendered, skip;
86 SwfdecBuffer *buffer;
88 g_assert (start < G_MAXINT);
89 SWFDEC_LOG ("stream %p rendering offset %"G_GSIZE_FORMAT", samples %"G_GSIZE_FORMAT,
90 stream, start, n_samples);
91 swfdec_audio_stream_require (stream, start + n_samples);
92 if (stream->queue_size <= start)
93 return 0;
94 n_samples = MIN (stream->queue_size, n_samples + start);
96 rendered = 0;
97 for (walk = g_queue_peek_head_link (stream->queue);
98 rendered < n_samples; walk = walk->next) {
99 /* must hold, we check above that enough data is available */
100 g_assert (walk);
101 buffer = walk->data;
102 samples = buffer->length / 4;
103 if (rendered < start) {
104 skip = MIN (samples, start - rendered);
105 samples -= skip;
106 samples = MIN (n_samples - start, samples);
107 } else {
108 skip = 0;
109 samples = MIN (n_samples - rendered, samples);
111 samples = MIN (n_samples - MAX (start, rendered), samples);
112 if (samples)
113 swfdec_sound_buffer_render (dest, buffer, skip, samples);
115 rendered += skip + samples;
116 dest += 2 * samples;
119 return rendered - start;
122 static gboolean
123 swfdec_audio_stream_check_buffering (SwfdecAudioStream *stream)
125 SwfdecAudioStreamClass *klass;
126 SwfdecBuffer *buffer;
128 if (!stream->buffering || stream->done)
129 return FALSE;
131 klass = SWFDEC_AUDIO_STREAM_GET_CLASS (stream);
132 buffer = klass->pull (stream);
133 if (buffer == NULL)
134 return FALSE;
136 swfdec_audio_decoder_push (stream->decoder, buffer);
137 swfdec_buffer_unref (buffer);
138 stream->buffering = FALSE;
139 g_signal_emit_by_name (stream, "new-data");
140 return stream->queue_size == 0;
143 static gsize
144 swfdec_audio_stream_iterate (SwfdecAudio *audio, gsize remove)
146 SwfdecAudioStream *stream = SWFDEC_AUDIO_STREAM (audio);
147 SwfdecBuffer *buffer;
148 gsize samples, cur_samples;
150 if (swfdec_audio_stream_check_buffering (stream))
151 return G_MAXUINT;
152 swfdec_audio_stream_require (stream, remove);
153 samples = MIN (remove, stream->queue_size);
155 while (samples > 0) {
156 buffer = g_queue_pop_head (stream->queue);
157 cur_samples = buffer->length / 4;
158 if (samples < cur_samples) {
159 SwfdecBuffer *sub = swfdec_buffer_new_subbuffer (buffer,
160 samples * 4, buffer->length - samples * 4);
161 g_queue_push_head (stream->queue, sub);
162 cur_samples = samples;
164 stream->queue_size -= cur_samples;
165 samples -= cur_samples;
168 if (!stream->done) {
169 return G_MAXUINT;
170 } else {
171 return stream->queue_size;
175 static void
176 swfdec_audio_stream_class_init (SwfdecAudioStreamClass *klass)
178 GObjectClass *object_class = G_OBJECT_CLASS (klass);
179 SwfdecAudioClass *audio_class = SWFDEC_AUDIO_CLASS (klass);
181 object_class->dispose = swfdec_audio_stream_dispose;
183 audio_class->iterate = swfdec_audio_stream_iterate;
184 audio_class->render = swfdec_audio_stream_render;
187 static void
188 swfdec_audio_stream_init (SwfdecAudioStream *stream)
190 stream->queue = g_queue_new ();
193 void
194 swfdec_audio_stream_use_decoder (SwfdecAudioStream *stream,
195 guint codec, SwfdecAudioFormat format)
197 g_return_if_fail (SWFDEC_IS_AUDIO_STREAM (stream));
198 g_return_if_fail (SWFDEC_IS_AUDIO_FORMAT (format));
200 if (stream->decoder) {
201 if (swfdec_audio_decoder_uses_format (stream->decoder, codec, format))
202 return;
203 /* FIXME: send NULL buffer */
204 g_object_unref (stream->decoder);
206 stream->decoder = swfdec_audio_decoder_new (codec, format);
209 void
210 swfdec_audio_stream_done (SwfdecAudioStream *stream)
212 g_return_if_fail (SWFDEC_IS_AUDIO_STREAM (stream));
213 g_return_if_fail (!stream->done);
215 stream->done = TRUE;