wavparse: Update for libgstriff API changes
[platform/upstream/gst-plugins-good.git] / gst / wavparse / gstwavparse.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* GStreamer
3  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4  * Copyright (C) <2006> Nokia Corporation, Stefan Kost <stefan.kost@nokia.com>.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
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  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /**
23  * SECTION:element-wavparse
24  *
25  * Parse a .wav file into raw or compressed audio.
26  *
27  * Wavparse supports both push and pull mode operations, making it possible to
28  * stream from a network source.
29  *
30  * <refsect2>
31  * <title>Example launch line</title>
32  * |[
33  * gst-launch filesrc location=sine.wav ! wavparse ! audioconvert ! alsasink
34  * ]| Read a wav file and output to the soundcard using the ALSA element. The
35  * wav file is assumed to contain raw uncompressed samples.
36  * |[
37  * gst-launch gnomevfssrc location=http://www.example.org/sine.wav ! queue ! wavparse ! audioconvert ! alsasink
38  * ]| Stream data from a network url.
39  * </refsect2>
40  *
41  * Last reviewed on 2007-02-14 (0.10.6)
42  */
43
44 /*
45  * TODO:
46  * http://replaygain.hydrogenaudio.org/file_format_wav.html
47  */
48
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52 #include <string.h>
53 #include <math.h>
54
55 #include "gstwavparse.h"
56 #include "gst/riff/riff-ids.h"
57 #include "gst/riff/riff-media.h"
58 #include <gst/base/gsttypefindhelper.h>
59 #include <gst/gst-i18n-plugin.h>
60
61 GST_DEBUG_CATEGORY_STATIC (wavparse_debug);
62 #define GST_CAT_DEFAULT (wavparse_debug)
63
64 static void gst_wavparse_dispose (GObject * object);
65
66 static gboolean gst_wavparse_sink_activate (GstPad * sinkpad,
67     GstObject * parent);
68 static gboolean gst_wavparse_sink_activate_mode (GstPad * sinkpad,
69     GstObject * parent, GstPadMode mode, gboolean active);
70 static gboolean gst_wavparse_send_event (GstElement * element,
71     GstEvent * event);
72 static GstStateChangeReturn gst_wavparse_change_state (GstElement * element,
73     GstStateChange transition);
74
75 static gboolean gst_wavparse_pad_query (GstPad * pad, GstObject * parent,
76     GstQuery * query);
77 static gboolean gst_wavparse_pad_convert (GstPad * pad, GstFormat src_format,
78     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
79
80 static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstObject * parent,
81     GstBuffer * buf);
82 static gboolean gst_wavparse_sink_event (GstPad * pad, GstObject * parent,
83     GstEvent * event);
84 static void gst_wavparse_loop (GstPad * pad);
85 static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstObject * parent,
86     GstEvent * event);
87
88 static GstStaticPadTemplate sink_template_factory =
89 GST_STATIC_PAD_TEMPLATE ("sink",
90     GST_PAD_SINK,
91     GST_PAD_ALWAYS,
92     GST_STATIC_CAPS ("audio/x-wav")
93     );
94
95 #define DEBUG_INIT \
96   GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
97
98 #define gst_wavparse_parent_class parent_class
99 G_DEFINE_TYPE_WITH_CODE (GstWavParse, gst_wavparse, GST_TYPE_ELEMENT,
100     DEBUG_INIT);
101
102 static void
103 gst_wavparse_class_init (GstWavParseClass * klass)
104 {
105   GstElementClass *gstelement_class;
106   GObjectClass *object_class;
107   GstPadTemplate *src_template;
108
109   gstelement_class = (GstElementClass *) klass;
110   object_class = (GObjectClass *) klass;
111
112   parent_class = g_type_class_peek_parent (klass);
113
114   object_class->dispose = gst_wavparse_dispose;
115
116   gstelement_class->change_state = gst_wavparse_change_state;
117   gstelement_class->send_event = gst_wavparse_send_event;
118
119   /* register pads */
120   gst_element_class_add_pad_template (gstelement_class,
121       gst_static_pad_template_get (&sink_template_factory));
122
123   src_template = gst_pad_template_new ("src", GST_PAD_SRC,
124       GST_PAD_ALWAYS, gst_riff_create_audio_template_caps ());
125   gst_element_class_add_pad_template (gstelement_class, src_template);
126
127   gst_element_class_set_details_simple (gstelement_class, "WAV audio demuxer",
128       "Codec/Demuxer/Audio",
129       "Parse a .wav file into raw audio",
130       "Erik Walthinsen <omega@cse.ogi.edu>");
131 }
132
133 static void
134 gst_wavparse_reset (GstWavParse * wav)
135 {
136   wav->state = GST_WAVPARSE_START;
137
138   /* These will all be set correctly in the fmt chunk */
139   wav->depth = 0;
140   wav->rate = 0;
141   wav->width = 0;
142   wav->channels = 0;
143   wav->blockalign = 0;
144   wav->bps = 0;
145   wav->fact = 0;
146   wav->offset = 0;
147   wav->end_offset = 0;
148   wav->dataleft = 0;
149   wav->datasize = 0;
150   wav->datastart = 0;
151   wav->duration = 0;
152   wav->got_fmt = FALSE;
153   wav->first = TRUE;
154
155   if (wav->seek_event)
156     gst_event_unref (wav->seek_event);
157   wav->seek_event = NULL;
158   if (wav->adapter) {
159     gst_adapter_clear (wav->adapter);
160     g_object_unref (wav->adapter);
161     wav->adapter = NULL;
162   }
163   if (wav->tags)
164     gst_tag_list_free (wav->tags);
165   wav->tags = NULL;
166   if (wav->caps)
167     gst_caps_unref (wav->caps);
168   wav->caps = NULL;
169   if (wav->start_segment)
170     gst_event_unref (wav->start_segment);
171   wav->start_segment = NULL;
172 }
173
174 static void
175 gst_wavparse_dispose (GObject * object)
176 {
177   GstWavParse *wav = GST_WAVPARSE (object);
178
179   GST_DEBUG_OBJECT (wav, "WAV: Dispose");
180   gst_wavparse_reset (wav);
181
182   G_OBJECT_CLASS (parent_class)->dispose (object);
183 }
184
185 static void
186 gst_wavparse_init (GstWavParse * wavparse)
187 {
188   gst_wavparse_reset (wavparse);
189
190   /* sink */
191   wavparse->sinkpad =
192       gst_pad_new_from_static_template (&sink_template_factory, "sink");
193   gst_pad_set_activate_function (wavparse->sinkpad,
194       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate));
195   gst_pad_set_activatemode_function (wavparse->sinkpad,
196       GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate_mode));
197   gst_pad_set_chain_function (wavparse->sinkpad,
198       GST_DEBUG_FUNCPTR (gst_wavparse_chain));
199   gst_pad_set_event_function (wavparse->sinkpad,
200       GST_DEBUG_FUNCPTR (gst_wavparse_sink_event));
201   gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->sinkpad);
202
203   /* src */
204   wavparse->srcpad =
205       gst_pad_new_from_template (gst_element_class_get_pad_template
206       (GST_ELEMENT_GET_CLASS (wavparse), "src"), "src");
207   gst_pad_use_fixed_caps (wavparse->srcpad);
208   gst_pad_set_query_function (wavparse->srcpad,
209       GST_DEBUG_FUNCPTR (gst_wavparse_pad_query));
210   gst_pad_set_event_function (wavparse->srcpad,
211       GST_DEBUG_FUNCPTR (gst_wavparse_srcpad_event));
212   gst_element_add_pad (GST_ELEMENT_CAST (wavparse), wavparse->srcpad);
213 }
214
215 /* Compute (value * nom) % denom, avoiding overflow.  This can be used
216  * to perform ceiling or rounding division together with
217  * gst_util_uint64_scale[_int]. */
218 #define uint64_scale_modulo(val, nom, denom) \
219   ((val % denom) * (nom % denom) % denom)
220
221 /* Like gst_util_uint64_scale, but performs ceiling division. */
222 static guint64
223 uint64_ceiling_scale_int (guint64 val, gint num, gint denom)
224 {
225   guint64 result = gst_util_uint64_scale_int (val, num, denom);
226
227   if (uint64_scale_modulo (val, num, denom) == 0)
228     return result;
229   else
230     return result + 1;
231 }
232
233 /* Like gst_util_uint64_scale, but performs ceiling division. */
234 static guint64
235 uint64_ceiling_scale (guint64 val, guint64 num, guint64 denom)
236 {
237   guint64 result = gst_util_uint64_scale (val, num, denom);
238
239   if (uint64_scale_modulo (val, num, denom) == 0)
240     return result;
241   else
242     return result + 1;
243 }
244
245
246 /* FIXME: why is that not in use? */
247 #if 0
248 static void
249 gst_wavparse_parse_adtl (GstWavParse * wavparse, int len)
250 {
251   guint32 got_bytes;
252   GstByteStream *bs = wavparse->bs;
253   gst_riff_chunk *temp_chunk, chunk;
254   guint8 *tempdata;
255   struct _gst_riff_labl labl, *temp_labl;
256   struct _gst_riff_ltxt ltxt, *temp_ltxt;
257   struct _gst_riff_note note, *temp_note;
258   char *label_name;
259   GstProps *props;
260   GstPropsEntry *entry;
261   GstCaps *new_caps;
262   GList *caps = NULL;
263
264   props = wavparse->metadata->properties;
265
266   while (len > 0) {
267     got_bytes =
268         gst_bytestream_peek_bytes (bs, &tempdata, sizeof (gst_riff_chunk));
269     if (got_bytes != sizeof (gst_riff_chunk)) {
270       return;
271     }
272     temp_chunk = (gst_riff_chunk *) tempdata;
273
274     chunk.id = GUINT32_FROM_LE (temp_chunk->id);
275     chunk.size = GUINT32_FROM_LE (temp_chunk->size);
276
277     if (chunk.size == 0) {
278       gst_bytestream_flush (bs, sizeof (gst_riff_chunk));
279       len -= sizeof (gst_riff_chunk);
280       continue;
281     }
282
283     switch (chunk.id) {
284       case GST_RIFF_adtl_labl:
285         got_bytes =
286             gst_bytestream_peek_bytes (bs, &tempdata,
287             sizeof (struct _gst_riff_labl));
288         if (got_bytes != sizeof (struct _gst_riff_labl)) {
289           return;
290         }
291
292         temp_labl = (struct _gst_riff_labl *) tempdata;
293         labl.id = GUINT32_FROM_LE (temp_labl->id);
294         labl.size = GUINT32_FROM_LE (temp_labl->size);
295         labl.identifier = GUINT32_FROM_LE (temp_labl->identifier);
296
297         gst_bytestream_flush (bs, sizeof (struct _gst_riff_labl));
298         len -= sizeof (struct _gst_riff_labl);
299
300         got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, labl.size - 4);
301         if (got_bytes != labl.size - 4) {
302           return;
303         }
304
305         label_name = (char *) tempdata;
306
307         gst_bytestream_flush (bs, ((labl.size - 4) + 1) & ~1);
308         len -= (((labl.size - 4) + 1) & ~1);
309
310         new_caps = gst_caps_new ("label",
311             "application/x-gst-metadata",
312             gst_props_new ("identifier", G_TYPE_INT (labl.identifier),
313                 "name", G_TYPE_STRING (label_name), NULL));
314
315         if (gst_props_get (props, "labels", &caps, NULL)) {
316           caps = g_list_append (caps, new_caps);
317         } else {
318           caps = g_list_append (NULL, new_caps);
319
320           entry = gst_props_entry_new ("labels", GST_PROPS_GLIST (caps));
321           gst_props_add_entry (props, entry);
322         }
323
324         break;
325
326       case GST_RIFF_adtl_ltxt:
327         got_bytes =
328             gst_bytestream_peek_bytes (bs, &tempdata,
329             sizeof (struct _gst_riff_ltxt));
330         if (got_bytes != sizeof (struct _gst_riff_ltxt)) {
331           return;
332         }
333
334         temp_ltxt = (struct _gst_riff_ltxt *) tempdata;
335         ltxt.id = GUINT32_FROM_LE (temp_ltxt->id);
336         ltxt.size = GUINT32_FROM_LE (temp_ltxt->size);
337         ltxt.identifier = GUINT32_FROM_LE (temp_ltxt->identifier);
338         ltxt.length = GUINT32_FROM_LE (temp_ltxt->length);
339         ltxt.purpose = GUINT32_FROM_LE (temp_ltxt->purpose);
340         ltxt.country = GUINT16_FROM_LE (temp_ltxt->country);
341         ltxt.language = GUINT16_FROM_LE (temp_ltxt->language);
342         ltxt.dialect = GUINT16_FROM_LE (temp_ltxt->dialect);
343         ltxt.codepage = GUINT16_FROM_LE (temp_ltxt->codepage);
344
345         gst_bytestream_flush (bs, sizeof (struct _gst_riff_ltxt));
346         len -= sizeof (struct _gst_riff_ltxt);
347
348         if (ltxt.size - 20 > 0) {
349           got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, ltxt.size - 20);
350           if (got_bytes != ltxt.size - 20) {
351             return;
352           }
353
354           gst_bytestream_flush (bs, ((ltxt.size - 20) + 1) & ~1);
355           len -= (((ltxt.size - 20) + 1) & ~1);
356
357           label_name = (char *) tempdata;
358         } else {
359           label_name = "";
360         }
361
362         new_caps = gst_caps_new ("ltxt",
363             "application/x-gst-metadata",
364             gst_props_new ("identifier", G_TYPE_INT (ltxt.identifier),
365                 "name", G_TYPE_STRING (label_name),
366                 "length", G_TYPE_INT (ltxt.length), NULL));
367
368         if (gst_props_get (props, "ltxts", &caps, NULL)) {
369           caps = g_list_append (caps, new_caps);
370         } else {
371           caps = g_list_append (NULL, new_caps);
372
373           entry = gst_props_entry_new ("ltxts", GST_PROPS_GLIST (caps));
374           gst_props_add_entry (props, entry);
375         }
376
377         break;
378
379       case GST_RIFF_adtl_note:
380         got_bytes =
381             gst_bytestream_peek_bytes (bs, &tempdata,
382             sizeof (struct _gst_riff_note));
383         if (got_bytes != sizeof (struct _gst_riff_note)) {
384           return;
385         }
386
387         temp_note = (struct _gst_riff_note *) tempdata;
388         note.id = GUINT32_FROM_LE (temp_note->id);
389         note.size = GUINT32_FROM_LE (temp_note->size);
390         note.identifier = GUINT32_FROM_LE (temp_note->identifier);
391
392         gst_bytestream_flush (bs, sizeof (struct _gst_riff_note));
393         len -= sizeof (struct _gst_riff_note);
394
395         got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, note.size - 4);
396         if (got_bytes != note.size - 4) {
397           return;
398         }
399
400         gst_bytestream_flush (bs, ((note.size - 4) + 1) & ~1);
401         len -= (((note.size - 4) + 1) & ~1);
402
403         label_name = (char *) tempdata;
404
405         new_caps = gst_caps_new ("note",
406             "application/x-gst-metadata",
407             gst_props_new ("identifier", G_TYPE_INT (note.identifier),
408                 "name", G_TYPE_STRING (label_name), NULL));
409
410         if (gst_props_get (props, "notes", &caps, NULL)) {
411           caps = g_list_append (caps, new_caps);
412         } else {
413           caps = g_list_append (NULL, new_caps);
414
415           entry = gst_props_entry_new ("notes", GST_PROPS_GLIST (caps));
416           gst_props_add_entry (props, entry);
417         }
418
419         break;
420
421       default:
422         g_print ("Unknown chunk: %" GST_FOURCC_FORMAT "\n",
423             GST_FOURCC_ARGS (chunk.id));
424         return;
425     }
426   }
427
428   g_object_notify (G_OBJECT (wavparse), "metadata");
429 }
430
431 static void
432 gst_wavparse_parse_cues (GstWavParse * wavparse, int len)
433 {
434   guint32 got_bytes;
435   GstByteStream *bs = wavparse->bs;
436   struct _gst_riff_cue *temp_cue, cue;
437   struct _gst_riff_cuepoints *points;
438   guint8 *tempdata;
439   int i;
440   GList *cues = NULL;
441   GstPropsEntry *entry;
442
443   while (len > 0) {
444     int required;
445
446     got_bytes =
447         gst_bytestream_peek_bytes (bs, &tempdata,
448         sizeof (struct _gst_riff_cue));
449     temp_cue = (struct _gst_riff_cue *) tempdata;
450
451     /* fixup for our big endian friends */
452     cue.id = GUINT32_FROM_LE (temp_cue->id);
453     cue.size = GUINT32_FROM_LE (temp_cue->size);
454     cue.cuepoints = GUINT32_FROM_LE (temp_cue->cuepoints);
455
456     gst_bytestream_flush (bs, sizeof (struct _gst_riff_cue));
457     if (got_bytes != sizeof (struct _gst_riff_cue)) {
458       return;
459     }
460
461     len -= sizeof (struct _gst_riff_cue);
462
463     /* -4 because cue.size contains the cuepoints size
464        and we've already flushed that out of the system */
465     required = cue.size - 4;
466     got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, required);
467     gst_bytestream_flush (bs, ((required) + 1) & ~1);
468     if (got_bytes != required) {
469       return;
470     }
471
472     len -= (((cue.size - 4) + 1) & ~1);
473
474     /* now we have an array of struct _gst_riff_cuepoints in tempdata */
475     points = (struct _gst_riff_cuepoints *) tempdata;
476
477     for (i = 0; i < cue.cuepoints; i++) {
478       GstCaps *caps;
479
480       caps = gst_caps_new ("cues",
481           "application/x-gst-metadata",
482           gst_props_new ("identifier", G_TYPE_INT (points[i].identifier),
483               "position", G_TYPE_INT (points[i].offset), NULL));
484       cues = g_list_append (cues, caps);
485     }
486
487     entry = gst_props_entry_new ("cues", GST_PROPS_GLIST (cues));
488     gst_props_add_entry (wavparse->metadata->properties, entry);
489   }
490
491   g_object_notify (G_OBJECT (wavparse), "metadata");
492 }
493
494 /* Read 'fmt ' header */
495 static gboolean
496 gst_wavparse_fmt (GstWavParse * wav)
497 {
498   gst_riff_strf_auds *header = NULL;
499   GstCaps *caps;
500
501   if (!gst_riff_read_strf_auds (wav, &header))
502     goto no_fmt;
503
504   wav->format = header->format;
505   wav->rate = header->rate;
506   wav->channels = header->channels;
507   if (wav->channels == 0)
508     goto no_channels;
509
510   wav->blockalign = header->blockalign;
511   wav->width = (header->blockalign * 8) / header->channels;
512   wav->depth = header->size;
513   wav->bps = header->av_bps;
514   if (wav->bps <= 0)
515     goto no_bps;
516
517   /* Note: gst_riff_create_audio_caps might need to fix values in
518    * the header header depending on the format, so call it first */
519   /* FIXME: Need to handle the channel reorder map */
520   caps = gst_riff_create_audio_caps (header->format, NULL, header, NULL, NULL);
521   g_free (header);
522
523   if (caps == NULL)
524     goto no_caps;
525
526   gst_wavparse_create_sourcepad (wav);
527   gst_pad_use_fixed_caps (wav->srcpad);
528   gst_pad_set_active (wav->srcpad, TRUE);
529   gst_pad_set_caps (wav->srcpad, caps);
530   gst_caps_free (caps);
531   gst_element_add_pad (GST_ELEMENT_CAST (wav), wav->srcpad);
532   gst_element_no_more_pads (GST_ELEMENT_CAST (wav));
533
534   GST_DEBUG ("frequency %d, channels %d", wav->rate, wav->channels);
535
536   return TRUE;
537
538   /* ERRORS */
539 no_fmt:
540   {
541     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
542         ("No FMT tag found"));
543     return FALSE;
544   }
545 no_channels:
546   {
547     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
548         ("Stream claims to contain zero channels - invalid data"));
549     g_free (header);
550     return FALSE;
551   }
552 no_bps:
553   {
554     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
555         ("Stream claims to bitrate of <= zero - invalid data"));
556     g_free (header);
557     return FALSE;
558   }
559 no_caps:
560   {
561     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
562     return FALSE;
563   }
564 }
565
566 static gboolean
567 gst_wavparse_other (GstWavParse * wav)
568 {
569   guint32 tag, length;
570
571   if (!gst_riff_peek_head (wav, &tag, &length, NULL)) {
572     GST_WARNING_OBJECT (wav, "could not peek head");
573     return FALSE;
574   }
575   GST_DEBUG_OBJECT (wav, "got tag (%08x) %4.4s, length %d", tag,
576       (gchar *) & tag, length);
577
578   switch (tag) {
579     case GST_RIFF_TAG_LIST:
580       if (!(tag = gst_riff_peek_list (wav))) {
581         GST_WARNING_OBJECT (wav, "could not peek list");
582         return FALSE;
583       }
584
585       switch (tag) {
586         case GST_RIFF_LIST_INFO:
587           if (!gst_riff_read_list (wav, &tag) || !gst_riff_read_info (wav)) {
588             GST_WARNING_OBJECT (wav, "could not read list");
589             return FALSE;
590           }
591           break;
592
593         case GST_RIFF_LIST_adtl:
594           if (!gst_riff_read_skip (wav)) {
595             GST_WARNING_OBJECT (wav, "could not read skip");
596             return FALSE;
597           }
598           break;
599
600         default:
601           GST_DEBUG_OBJECT (wav, "skipping tag (%08x) %4.4s", tag,
602               (gchar *) & tag);
603           if (!gst_riff_read_skip (wav)) {
604             GST_WARNING_OBJECT (wav, "could not read skip");
605             return FALSE;
606           }
607           break;
608       }
609
610       break;
611
612     case GST_RIFF_TAG_data:
613       if (!gst_bytestream_flush (wav->bs, 8)) {
614         GST_WARNING_OBJECT (wav, "could not flush 8 bytes");
615         return FALSE;
616       }
617
618       GST_DEBUG_OBJECT (wav, "switching to data mode");
619       wav->state = GST_WAVPARSE_DATA;
620       wav->datastart = gst_bytestream_tell (wav->bs);
621       if (length == 0) {
622         guint64 file_length;
623
624         /* length is 0, data probably stretches to the end
625          * of file */
626         GST_DEBUG_OBJECT (wav, "length is 0 trying to find length");
627         /* get length of file */
628         file_length = gst_bytestream_length (wav->bs);
629         if (file_length == -1) {
630           GST_DEBUG_OBJECT (wav,
631               "could not get file length, assuming data to eof");
632           /* could not get length, assuming till eof */
633           length = G_MAXUINT32;
634         }
635         if (file_length > G_MAXUINT32) {
636           GST_DEBUG_OBJECT (wav, "file length %" G_GUINT64_FORMAT
637               ", clipping to 32 bits", file_length);
638           /* could not get length, assuming till eof */
639           length = G_MAXUINT32;
640         } else {
641           GST_DEBUG_OBJECT (wav, "file length %" G_GUINT64_FORMAT
642               ", datalength %u", file_length, length);
643           /* substract offset of datastart from length */
644           length = file_length - wav->datastart;
645           GST_DEBUG_OBJECT (wav, "datalength %u", length);
646         }
647       }
648       wav->datasize = (guint64) length;
649       GST_DEBUG_OBJECT (wav, "datasize = %ld", length)
650           break;
651
652     case GST_RIFF_TAG_cue:
653       if (!gst_riff_read_skip (wav)) {
654         GST_WARNING_OBJECT (wav, "could not read skip");
655         return FALSE;
656       }
657       break;
658
659     default:
660       GST_DEBUG_OBJECT (wav, "skipping tag (%08x) %4.4s", tag, (gchar *) & tag);
661       if (!gst_riff_read_skip (wav))
662         return FALSE;
663       break;
664   }
665
666   return TRUE;
667 }
668 #endif
669
670
671 static gboolean
672 gst_wavparse_parse_file_header (GstElement * element, GstBuffer * buf)
673 {
674   guint32 doctype;
675
676   if (!gst_riff_parse_file_header (element, buf, &doctype))
677     return FALSE;
678
679   if (doctype != GST_RIFF_RIFF_WAVE)
680     goto not_wav;
681
682   return TRUE;
683
684   /* ERRORS */
685 not_wav:
686   {
687     GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
688         ("File is not a WAVE file: %" GST_FOURCC_FORMAT,
689             GST_FOURCC_ARGS (doctype)));
690     return FALSE;
691   }
692 }
693
694 static GstFlowReturn
695 gst_wavparse_stream_init (GstWavParse * wav)
696 {
697   GstFlowReturn res;
698   GstBuffer *buf = NULL;
699
700   if ((res = gst_pad_pull_range (wav->sinkpad,
701               wav->offset, 12, &buf)) != GST_FLOW_OK)
702     return res;
703   else if (!gst_wavparse_parse_file_header (GST_ELEMENT_CAST (wav), buf))
704     return GST_FLOW_ERROR;
705
706   wav->offset += 12;
707
708   return GST_FLOW_OK;
709 }
710
711 static gboolean
712 gst_wavparse_time_to_bytepos (GstWavParse * wav, gint64 ts, gint64 * bytepos)
713 {
714   /* -1 always maps to -1 */
715   if (ts == -1) {
716     *bytepos = -1;
717     return TRUE;
718   }
719
720   /* 0 always maps to 0 */
721   if (ts == 0) {
722     *bytepos = 0;
723     return TRUE;
724   }
725
726   if (wav->bps > 0) {
727     *bytepos = uint64_ceiling_scale (ts, (guint64) wav->bps, GST_SECOND);
728     return TRUE;
729   } else if (wav->fact) {
730     guint64 bps =
731         gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
732     *bytepos = uint64_ceiling_scale (ts, bps, GST_SECOND);
733     return TRUE;
734   }
735
736   return FALSE;
737 }
738
739 /* This function is used to perform seeks on the element.
740  *
741  * It also works when event is NULL, in which case it will just
742  * start from the last configured segment. This technique is
743  * used when activating the element and to perform the seek in
744  * READY.
745  */
746 static gboolean
747 gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)
748 {
749   gboolean res;
750   gdouble rate;
751   GstFormat format, bformat;
752   GstSeekFlags flags;
753   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
754   gint64 cur, stop, upstream_size;
755   gboolean flush;
756   gboolean update;
757   GstSegment seeksegment = { 0, };
758   gint64 last_stop;
759
760   if (event) {
761     GST_DEBUG_OBJECT (wav, "doing seek with event");
762
763     gst_event_parse_seek (event, &rate, &format, &flags,
764         &cur_type, &cur, &stop_type, &stop);
765
766     /* no negative rates yet */
767     if (rate < 0.0)
768       goto negative_rate;
769
770     if (format != wav->segment.format) {
771       GST_INFO_OBJECT (wav, "converting seek-event from %s to %s",
772           gst_format_get_name (format),
773           gst_format_get_name (wav->segment.format));
774       res = TRUE;
775       if (cur_type != GST_SEEK_TYPE_NONE)
776         res =
777             gst_pad_query_convert (wav->srcpad, format, cur,
778             wav->segment.format, &cur);
779       if (res && stop_type != GST_SEEK_TYPE_NONE)
780         res =
781             gst_pad_query_convert (wav->srcpad, format, stop,
782             wav->segment.format, &stop);
783       if (!res)
784         goto no_format;
785
786       format = wav->segment.format;
787     }
788   } else {
789     GST_DEBUG_OBJECT (wav, "doing seek without event");
790     flags = 0;
791     rate = 1.0;
792     cur_type = GST_SEEK_TYPE_SET;
793     stop_type = GST_SEEK_TYPE_SET;
794   }
795
796   /* in push mode, we must delegate to upstream */
797   if (wav->streaming) {
798     gboolean res = FALSE;
799
800     /* if streaming not yet started; only prepare initial newsegment */
801     if (!event || wav->state != GST_WAVPARSE_DATA) {
802       if (wav->start_segment)
803         gst_event_unref (wav->start_segment);
804       // TODO
805 /*      wav->start_segment =
806           gst_event_new_new_segment (FALSE, wav->segment.rate,
807           wav->segment.format, wav->segment.last_stop, wav->segment.duration,
808           wav->segment.last_stop);*/
809       res = TRUE;
810     } else {
811       /* convert seek positions to byte positions in data sections */
812       if (format == GST_FORMAT_TIME) {
813         /* should not fail */
814         if (!gst_wavparse_time_to_bytepos (wav, cur, &cur))
815           goto no_position;
816         if (!gst_wavparse_time_to_bytepos (wav, stop, &stop))
817           goto no_position;
818       }
819       /* mind sample boundary and header */
820       if (cur >= 0) {
821         cur -= (cur % wav->bytes_per_sample);
822         cur += wav->datastart;
823       }
824       if (stop >= 0) {
825         stop -= (stop % wav->bytes_per_sample);
826         stop += wav->datastart;
827       }
828       GST_DEBUG_OBJECT (wav, "Pushing BYTE seek rate %g, "
829           "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur,
830           stop);
831       /* BYTE seek event */
832       event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
833           stop_type, stop);
834       res = gst_pad_push_event (wav->sinkpad, event);
835     }
836     return res;
837   }
838
839   /* get flush flag */
840   flush = flags & GST_SEEK_FLAG_FLUSH;
841
842   /* now we need to make sure the streaming thread is stopped. We do this by
843    * either sending a FLUSH_START event downstream which will cause the
844    * streaming thread to stop with a WRONG_STATE.
845    * For a non-flushing seek we simply pause the task, which will happen as soon
846    * as it completes one iteration (and thus might block when the sink is
847    * blocking in preroll). */
848   if (flush) {
849     GST_DEBUG_OBJECT (wav, "sending flush start");
850     gst_pad_push_event (wav->srcpad, gst_event_new_flush_start ());
851   } else {
852     gst_pad_pause_task (wav->sinkpad);
853   }
854
855   /* we should now be able to grab the streaming thread because we stopped it
856    * with the above flush/pause code */
857   GST_PAD_STREAM_LOCK (wav->sinkpad);
858
859   /* save current position */
860   last_stop = wav->segment.position;
861
862   GST_DEBUG_OBJECT (wav, "stopped streaming at %" G_GINT64_FORMAT, last_stop);
863
864   /* copy segment, we need this because we still need the old
865    * segment when we close the current segment. */
866   memcpy (&seeksegment, &wav->segment, sizeof (GstSegment));
867
868   /* configure the seek parameters in the seeksegment. We will then have the
869    * right values in the segment to perform the seek */
870   if (event) {
871     GST_DEBUG_OBJECT (wav, "configuring seek");
872     gst_segment_do_seek (&seeksegment, rate, format, flags,
873         cur_type, cur, stop_type, stop, &update);
874   }
875
876   /* figure out the last position we need to play. If it's configured (stop !=
877    * -1), use that, else we play until the total duration of the file */
878   if ((stop = seeksegment.stop) == -1)
879     stop = seeksegment.duration;
880
881   GST_DEBUG_OBJECT (wav, "cur_type =%d", cur_type);
882   if ((cur_type != GST_SEEK_TYPE_NONE)) {
883     /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
884      * we can just copy the last_stop. If not, we use the bps to convert TIME to
885      * bytes. */
886     if (!gst_wavparse_time_to_bytepos (wav, seeksegment.position,
887             (gint64 *) & wav->offset))
888       wav->offset = seeksegment.position;
889     GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
890     wav->offset -= (wav->offset % wav->bytes_per_sample);
891     GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
892     wav->offset += wav->datastart;
893     GST_LOG_OBJECT (wav, "offset=%" G_GUINT64_FORMAT, wav->offset);
894   } else {
895     GST_LOG_OBJECT (wav, "continue from offset=%" G_GUINT64_FORMAT,
896         wav->offset);
897   }
898
899   if (stop_type != GST_SEEK_TYPE_NONE) {
900     if (!gst_wavparse_time_to_bytepos (wav, stop, (gint64 *) & wav->end_offset))
901       wav->end_offset = stop;
902     GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
903     wav->end_offset -= (wav->end_offset % wav->bytes_per_sample);
904     GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
905     wav->end_offset += wav->datastart;
906     GST_LOG_OBJECT (wav, "end_offset=%" G_GUINT64_FORMAT, wav->end_offset);
907   } else {
908     GST_LOG_OBJECT (wav, "continue to end_offset=%" G_GUINT64_FORMAT,
909         wav->end_offset);
910   }
911
912   /* make sure filesize is not exceeded due to rounding errors or so,
913    * same precaution as in _stream_headers */
914   bformat = GST_FORMAT_BYTES;
915   if (gst_pad_peer_query_duration (wav->sinkpad, bformat, &upstream_size))
916     wav->end_offset = MIN (wav->end_offset, upstream_size);
917
918   /* this is the range of bytes we will use for playback */
919   wav->offset = MIN (wav->offset, wav->end_offset);
920   wav->dataleft = wav->end_offset - wav->offset;
921
922   GST_DEBUG_OBJECT (wav,
923       "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
924       ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, wav->offset,
925       wav->end_offset, GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (stop));
926
927   /* prepare for streaming again */
928   if (flush) {
929     /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
930     GST_DEBUG_OBJECT (wav, "sending flush stop");
931     gst_pad_push_event (wav->srcpad, gst_event_new_flush_stop (TRUE));
932   }
933
934   /* now we did the seek and can activate the new segment values */
935   memcpy (&wav->segment, &seeksegment, sizeof (GstSegment));
936
937   /* if we're doing a segment seek, post a SEGMENT_START message */
938   if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
939     gst_element_post_message (GST_ELEMENT_CAST (wav),
940         gst_message_new_segment_start (GST_OBJECT_CAST (wav),
941             wav->segment.format, wav->segment.position));
942   }
943
944   /* now create the newsegment */
945   GST_DEBUG_OBJECT (wav, "Creating newsegment from %" G_GINT64_FORMAT
946       " to %" G_GINT64_FORMAT, wav->segment.position, stop);
947
948   /* store the newsegment event so it can be sent from the streaming thread. */
949   if (wav->start_segment)
950     gst_event_unref (wav->start_segment);
951   wav->start_segment = gst_event_new_segment (&wav->segment);
952
953   /* mark discont if we are going to stream from another position. */
954   if (last_stop != wav->segment.position) {
955     GST_DEBUG_OBJECT (wav, "mark DISCONT, we did a seek to another position");
956     wav->discont = TRUE;
957   }
958
959   /* and start the streaming task again */
960   if (!wav->streaming) {
961     gst_pad_start_task (wav->sinkpad, (GstTaskFunction) gst_wavparse_loop,
962         wav->sinkpad);
963   }
964
965   GST_PAD_STREAM_UNLOCK (wav->sinkpad);
966
967   return TRUE;
968
969   /* ERRORS */
970 negative_rate:
971   {
972     GST_DEBUG_OBJECT (wav, "negative playback rates are not supported yet.");
973     return FALSE;
974   }
975 no_format:
976   {
977     GST_DEBUG_OBJECT (wav, "unsupported format given, seek aborted.");
978     return FALSE;
979   }
980 no_position:
981   {
982     GST_DEBUG_OBJECT (wav,
983         "Could not determine byte position for desired time");
984     return FALSE;
985   }
986 }
987
988 /*
989  * gst_wavparse_peek_chunk_info:
990  * @wav Wavparse object
991  * @tag holder for tag
992  * @size holder for tag size
993  *
994  * Peek next chunk info (tag and size)
995  *
996  * Returns: %TRUE when the chunk info (header) is available
997  */
998 static gboolean
999 gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
1000 {
1001   const guint8 *data = NULL;
1002
1003   if (gst_adapter_available (wav->adapter) < 8)
1004     return FALSE;
1005
1006   data = gst_adapter_map (wav->adapter, 8);
1007   *tag = GST_READ_UINT32_LE (data);
1008   *size = GST_READ_UINT32_LE (data + 4);
1009   gst_adapter_unmap (wav->adapter);
1010
1011   GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
1012       GST_FOURCC_ARGS (*tag));
1013
1014   return TRUE;
1015 }
1016
1017 /*
1018  * gst_wavparse_peek_chunk:
1019  * @wav Wavparse object
1020  * @tag holder for tag
1021  * @size holder for tag size
1022  *
1023  * Peek enough data for one full chunk
1024  *
1025  * Returns: %TRUE when the full chunk is available
1026  */
1027 static gboolean
1028 gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
1029 {
1030   guint32 peek_size = 0;
1031   guint available;
1032
1033   if (!gst_wavparse_peek_chunk_info (wav, tag, size))
1034     return FALSE;
1035
1036   /* size 0 -> empty data buffer would surprise most callers,
1037    * large size -> do not bother trying to squeeze that into adapter,
1038    * so we throw poor man's exception, which can be caught if caller really
1039    * wants to handle 0 size chunk */
1040   if (!(*size) || (*size) >= (1 << 30)) {
1041     GST_INFO ("Invalid/unexpected chunk size %d for tag %" GST_FOURCC_FORMAT,
1042         *size, GST_FOURCC_ARGS (*tag));
1043     /* chain should give up */
1044     wav->abort_buffering = TRUE;
1045     return FALSE;
1046   }
1047   peek_size = (*size + 1) & ~1;
1048   available = gst_adapter_available (wav->adapter);
1049
1050   if (available >= (8 + peek_size)) {
1051     return TRUE;
1052   } else {
1053     GST_LOG ("but only %u bytes available now", available);
1054     return FALSE;
1055   }
1056 }
1057
1058 /*
1059  * gst_wavparse_calculate_duration:
1060  * @wav: wavparse object
1061  *
1062  * Calculate duration on demand and store in @wav. Prefer bps, but use fact as a
1063  * fallback.
1064  *
1065  * Returns: %TRUE if duration is available.
1066  */
1067 static gboolean
1068 gst_wavparse_calculate_duration (GstWavParse * wav)
1069 {
1070   if (wav->duration > 0)
1071     return TRUE;
1072
1073   if (wav->bps > 0) {
1074     GST_INFO_OBJECT (wav, "Got datasize %" G_GUINT64_FORMAT, wav->datasize);
1075     wav->duration =
1076         uint64_ceiling_scale (wav->datasize, GST_SECOND, (guint64) wav->bps);
1077     GST_INFO_OBJECT (wav, "Got duration (bps) %" GST_TIME_FORMAT,
1078         GST_TIME_ARGS (wav->duration));
1079     return TRUE;
1080   } else if (wav->fact) {
1081     wav->duration = uint64_ceiling_scale_int (GST_SECOND, wav->fact, wav->rate);
1082     GST_INFO_OBJECT (wav, "Got duration (fact) %" GST_TIME_FORMAT,
1083         GST_TIME_ARGS (wav->duration));
1084     return TRUE;
1085   }
1086   return FALSE;
1087 }
1088
1089 static gboolean
1090 gst_waveparse_ignore_chunk (GstWavParse * wav, GstBuffer * buf, guint32 tag,
1091     guint32 size)
1092 {
1093   guint flush;
1094
1095   if (wav->streaming) {
1096     if (!gst_wavparse_peek_chunk (wav, &tag, &size))
1097       return FALSE;
1098   }
1099   GST_DEBUG_OBJECT (wav, "Ignoring tag %" GST_FOURCC_FORMAT,
1100       GST_FOURCC_ARGS (tag));
1101   flush = 8 + ((size + 1) & ~1);
1102   wav->offset += flush;
1103   if (wav->streaming) {
1104     gst_adapter_flush (wav->adapter, flush);
1105   } else {
1106     gst_buffer_unref (buf);
1107   }
1108
1109   return TRUE;
1110 }
1111
1112 #define MAX_BUFFER_SIZE 4096
1113
1114 static GstFlowReturn
1115 gst_wavparse_stream_headers (GstWavParse * wav)
1116 {
1117   GstFlowReturn res = GST_FLOW_OK;
1118   GstBuffer *buf = NULL;
1119   gst_riff_strf_auds *header = NULL;
1120   guint32 tag, size;
1121   gboolean gotdata = FALSE;
1122   GstCaps *caps = NULL;
1123   gchar *codec_name = NULL;
1124   GstEvent **event_p;
1125   gint64 upstream_size = 0;
1126
1127   /* search for "_fmt" chunk, which should be first */
1128   while (!wav->got_fmt) {
1129     GstBuffer *extra;
1130
1131     /* The header starts with a 'fmt ' tag */
1132     if (wav->streaming) {
1133       if (!gst_wavparse_peek_chunk (wav, &tag, &size))
1134         return res;
1135
1136       gst_adapter_flush (wav->adapter, 8);
1137       wav->offset += 8;
1138
1139       if (size) {
1140         buf = gst_adapter_take_buffer (wav->adapter, size);
1141         if (size & 1)
1142           gst_adapter_flush (wav->adapter, 1);
1143         wav->offset += GST_ROUND_UP_2 (size);
1144       } else {
1145         buf = gst_buffer_new ();
1146       }
1147     } else {
1148       if ((res = gst_riff_read_chunk (GST_ELEMENT_CAST (wav), wav->sinkpad,
1149                   &wav->offset, &tag, &buf)) != GST_FLOW_OK)
1150         return res;
1151     }
1152
1153     if (tag == GST_RIFF_TAG_JUNK || tag == GST_RIFF_TAG_JUNQ ||
1154         tag == GST_RIFF_TAG_bext || tag == GST_RIFF_TAG_BEXT ||
1155         tag == GST_RIFF_TAG_LIST || tag == GST_RIFF_TAG_ID32 ||
1156         tag == GST_RIFF_TAG_IDVX) {
1157       GST_DEBUG_OBJECT (wav, "skipping %" GST_FOURCC_FORMAT " chunk",
1158           GST_FOURCC_ARGS (tag));
1159       gst_buffer_unref (buf);
1160       buf = NULL;
1161       continue;
1162     }
1163
1164     if (tag != GST_RIFF_TAG_fmt)
1165       goto invalid_wav;
1166
1167     if (!(gst_riff_parse_strf_auds (GST_ELEMENT_CAST (wav), buf, &header,
1168                 &extra)))
1169       goto parse_header_error;
1170
1171     buf = NULL;                 /* parse_strf_auds() took ownership of buffer */
1172
1173     /* do sanity checks of header fields */
1174     if (header->channels == 0)
1175       goto no_channels;
1176     if (header->rate == 0)
1177       goto no_rate;
1178
1179     GST_DEBUG_OBJECT (wav, "creating the caps");
1180
1181     /* Note: gst_riff_create_audio_caps might need to fix values in
1182      * the header header depending on the format, so call it first */
1183     /* FIXME: Need to handle the channel reorder map */
1184     caps = gst_riff_create_audio_caps (header->format, NULL, header, extra,
1185         NULL, &codec_name, NULL);
1186
1187     if (extra)
1188       gst_buffer_unref (extra);
1189
1190     if (!caps)
1191       goto unknown_format;
1192
1193     /* do more sanity checks of header fields
1194      * (these can be sanitized by gst_riff_create_audio_caps()
1195      */
1196     wav->format = header->format;
1197     wav->rate = header->rate;
1198     wav->channels = header->channels;
1199     wav->blockalign = header->blockalign;
1200     wav->depth = header->size;
1201     wav->av_bps = header->av_bps;
1202     wav->vbr = FALSE;
1203
1204     g_free (header);
1205     header = NULL;
1206
1207     /* do format specific handling */
1208     switch (wav->format) {
1209       case GST_RIFF_WAVE_FORMAT_MPEGL12:
1210       case GST_RIFF_WAVE_FORMAT_MPEGL3:
1211       {
1212         /* Note: workaround for mp2/mp3 embedded in wav, that relies on the
1213          * bitrate inside the mpeg stream */
1214         GST_INFO ("resetting bps from %d to 0 for mp2/3", wav->av_bps);
1215         wav->bps = 0;
1216         break;
1217       }
1218       case GST_RIFF_WAVE_FORMAT_PCM:
1219         if (wav->blockalign > wav->channels * (guint) ceil (wav->depth / 8.0))
1220           goto invalid_blockalign;
1221         /* fall through */
1222       default:
1223         if (wav->av_bps > wav->blockalign * wav->rate)
1224           goto invalid_bps;
1225         /* use the configured bps */
1226         wav->bps = wav->av_bps;
1227         break;
1228     }
1229
1230     wav->width = (wav->blockalign * 8) / wav->channels;
1231     wav->bytes_per_sample = wav->channels * wav->width / 8;
1232
1233     if (wav->bytes_per_sample <= 0)
1234       goto no_bytes_per_sample;
1235
1236     GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
1237     GST_DEBUG_OBJECT (wav, "width      = %u", (guint) wav->width);
1238     GST_DEBUG_OBJECT (wav, "depth      = %u", (guint) wav->depth);
1239     GST_DEBUG_OBJECT (wav, "av_bps     = %u", (guint) wav->av_bps);
1240     GST_DEBUG_OBJECT (wav, "frequency  = %u", (guint) wav->rate);
1241     GST_DEBUG_OBJECT (wav, "channels   = %u", (guint) wav->channels);
1242     GST_DEBUG_OBJECT (wav, "bytes_per_sample = %u", wav->bytes_per_sample);
1243
1244     /* bps can be 0 when we don't have a valid bitrate (mostly for compressed
1245      * formats). This will make the element output a BYTE format segment and
1246      * will not timestamp the outgoing buffers.
1247      */
1248     GST_DEBUG_OBJECT (wav, "bps        = %u", (guint) wav->bps);
1249
1250     GST_DEBUG_OBJECT (wav, "caps = %" GST_PTR_FORMAT, caps);
1251
1252     /* create pad later so we can sniff the first few bytes
1253      * of the real data and correct our caps if necessary */
1254     gst_caps_replace (&wav->caps, caps);
1255     gst_caps_replace (&caps, NULL);
1256
1257     wav->got_fmt = TRUE;
1258
1259     if (codec_name) {
1260       wav->tags = gst_tag_list_new_empty ();
1261
1262       gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
1263           GST_TAG_AUDIO_CODEC, codec_name, NULL);
1264
1265       g_free (codec_name);
1266       codec_name = NULL;
1267     }
1268
1269   }
1270
1271   gst_pad_peer_query_duration (wav->sinkpad, GST_FORMAT_BYTES, &upstream_size);
1272   GST_DEBUG_OBJECT (wav, "upstream size %" G_GUINT64_FORMAT, upstream_size);
1273
1274   /* loop headers until we get data */
1275   while (!gotdata) {
1276     if (wav->streaming) {
1277       if (!gst_wavparse_peek_chunk_info (wav, &tag, &size))
1278         goto exit;
1279     } else {
1280       guint8 *data;
1281
1282       if ((res =
1283               gst_pad_pull_range (wav->sinkpad, wav->offset, 8,
1284                   &buf)) != GST_FLOW_OK)
1285         goto header_read_error;
1286       data = gst_buffer_map (buf, NULL, NULL, -1);
1287       tag = GST_READ_UINT32_LE (data);
1288       size = GST_READ_UINT32_LE (data + 4);
1289       gst_buffer_unmap (buf, data, -1);
1290     }
1291
1292     GST_INFO_OBJECT (wav,
1293         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
1294         GST_FOURCC_ARGS (tag), wav->offset);
1295
1296     /* wav is a st00pid format, we don't know for sure where data starts.
1297      * So we have to go bit by bit until we find the 'data' header
1298      */
1299     switch (tag) {
1300       case GST_RIFF_TAG_data:{
1301         GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
1302         if (wav->streaming) {
1303           gst_adapter_flush (wav->adapter, 8);
1304           gotdata = TRUE;
1305         } else {
1306           gst_buffer_unref (buf);
1307         }
1308         wav->offset += 8;
1309         wav->datastart = wav->offset;
1310         /* If size is zero, then the data chunk probably actually extends to
1311            the end of the file */
1312         if (size == 0 && upstream_size) {
1313           size = upstream_size - wav->datastart;
1314         }
1315         /* Or the file might be truncated */
1316         else if (upstream_size) {
1317           size = MIN (size, (upstream_size - wav->datastart));
1318         }
1319         wav->datasize = (guint64) size;
1320         wav->dataleft = (guint64) size;
1321         wav->end_offset = size + wav->datastart;
1322         if (!wav->streaming) {
1323           /* We will continue parsing tags 'till end */
1324           wav->offset += size;
1325         }
1326         GST_DEBUG_OBJECT (wav, "datasize = %d", size);
1327         break;
1328       }
1329       case GST_RIFF_TAG_fact:{
1330         if (wav->format != GST_RIFF_WAVE_FORMAT_MPEGL12 &&
1331             wav->format != GST_RIFF_WAVE_FORMAT_MPEGL3) {
1332           const guint data_size = 4;
1333
1334           GST_INFO_OBJECT (wav, "Have fact chunk");
1335           if (size < data_size) {
1336             if (!gst_waveparse_ignore_chunk (wav, buf, tag, size)) {
1337               /* need more data */
1338               goto exit;
1339             }
1340             GST_DEBUG_OBJECT (wav, "need %d, available %d; ignoring chunk",
1341                 data_size, size);
1342             break;
1343           }
1344           /* number of samples (for compressed formats) */
1345           if (wav->streaming) {
1346             const guint8 *data = NULL;
1347
1348             if (!gst_wavparse_peek_chunk (wav, &tag, &size)) {
1349               goto exit;
1350             }
1351             gst_adapter_flush (wav->adapter, 8);
1352             data = gst_adapter_map (wav->adapter, data_size);
1353             wav->fact = GST_READ_UINT32_LE (data);
1354             gst_adapter_unmap (wav->adapter);
1355             gst_adapter_flush (wav->adapter, GST_ROUND_UP_2 (size));
1356           } else {
1357             gst_buffer_unref (buf);
1358             if ((res =
1359                     gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
1360                         data_size, &buf)) != GST_FLOW_OK)
1361               goto header_read_error;
1362             gst_buffer_extract (buf, 0, &wav->fact, 4);
1363             wav->fact = GUINT32_FROM_LE (wav->fact);
1364             gst_buffer_unref (buf);
1365           }
1366           GST_DEBUG_OBJECT (wav, "have fact %u", wav->fact);
1367           wav->offset += 8 + GST_ROUND_UP_2 (size);
1368           break;
1369         } else {
1370           if (!gst_waveparse_ignore_chunk (wav, buf, tag, size)) {
1371             /* need more data */
1372             goto exit;
1373           }
1374         }
1375         break;
1376       }
1377       case GST_RIFF_TAG_acid:{
1378         const gst_riff_acid *acid = NULL;
1379         const guint data_size = sizeof (gst_riff_acid);
1380         gfloat tempo;
1381
1382         GST_INFO_OBJECT (wav, "Have acid chunk");
1383         if (size < data_size) {
1384           if (!gst_waveparse_ignore_chunk (wav, buf, tag, size)) {
1385             /* need more data */
1386             goto exit;
1387           }
1388           GST_DEBUG_OBJECT (wav, "need %d, available %d; ignoring chunk",
1389               data_size, size);
1390           break;
1391         }
1392         if (wav->streaming) {
1393           if (!gst_wavparse_peek_chunk (wav, &tag, &size)) {
1394             goto exit;
1395           }
1396           gst_adapter_flush (wav->adapter, 8);
1397           acid = (const gst_riff_acid *) gst_adapter_map (wav->adapter,
1398               data_size);
1399           tempo = acid->tempo;
1400           gst_adapter_unmap (wav->adapter);
1401         } else {
1402           gst_buffer_unref (buf);
1403           if ((res =
1404                   gst_pad_pull_range (wav->sinkpad, wav->offset + 8,
1405                       size, &buf)) != GST_FLOW_OK)
1406             goto header_read_error;
1407           acid = (const gst_riff_acid *) gst_buffer_map (buf, NULL, NULL,
1408               GST_MAP_READ);
1409           tempo = acid->tempo;
1410           gst_buffer_unmap (buf, (guint8 *) acid, -1);
1411         }
1412         /* send data as tags */
1413         if (!wav->tags)
1414           wav->tags = gst_tag_list_new_empty ();
1415         gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
1416             GST_TAG_BEATS_PER_MINUTE, tempo, NULL);
1417
1418         size = GST_ROUND_UP_2 (size);
1419         if (wav->streaming) {
1420           gst_adapter_flush (wav->adapter, size);
1421         } else {
1422           gst_buffer_unref (buf);
1423         }
1424         wav->offset += 8 + size;
1425         break;
1426       }
1427         /* FIXME: all list tags after data are ignored in streaming mode */
1428       case GST_RIFF_TAG_LIST:{
1429         guint32 ltag;
1430
1431         if (wav->streaming) {
1432           const guint8 *data = NULL;
1433
1434           if (gst_adapter_available (wav->adapter) < 12) {
1435             goto exit;
1436           }
1437           data = gst_adapter_map (wav->adapter, 12);
1438           ltag = GST_READ_UINT32_LE (data + 8);
1439           gst_adapter_unmap (wav->adapter);
1440         } else {
1441           gst_buffer_unref (buf);
1442           if ((res =
1443                   gst_pad_pull_range (wav->sinkpad, wav->offset, 12,
1444                       &buf)) != GST_FLOW_OK)
1445             goto header_read_error;
1446           gst_buffer_extract (buf, 8, &ltag, 4);
1447           ltag = GUINT32_FROM_LE (ltag);
1448         }
1449         switch (ltag) {
1450           case GST_RIFF_LIST_INFO:{
1451             const gint data_size = size - 4;
1452             GstTagList *new;
1453
1454             GST_INFO_OBJECT (wav, "Have LIST chunk INFO size %u", data_size);
1455             if (wav->streaming) {
1456               if (!gst_wavparse_peek_chunk (wav, &tag, &size)) {
1457                 goto exit;
1458               }
1459               gst_adapter_flush (wav->adapter, 12);
1460               wav->offset += 12;
1461               if (data_size > 0) {
1462                 buf = gst_adapter_take_buffer (wav->adapter, data_size);
1463                 if (data_size & 1)
1464                   gst_adapter_flush (wav->adapter, 1);
1465               }
1466             } else {
1467               wav->offset += 12;
1468               gst_buffer_unref (buf);
1469               if (data_size > 0) {
1470                 if ((res =
1471                         gst_pad_pull_range (wav->sinkpad, wav->offset,
1472                             data_size, &buf)) != GST_FLOW_OK)
1473                   goto header_read_error;
1474               }
1475             }
1476             if (data_size > 0) {
1477               /* parse tags */
1478               gst_riff_parse_info (GST_ELEMENT (wav), buf, &new);
1479               if (new) {
1480                 GstTagList *old = wav->tags;
1481                 wav->tags =
1482                     gst_tag_list_merge (old, new, GST_TAG_MERGE_REPLACE);
1483                 if (old)
1484                   gst_tag_list_free (old);
1485                 gst_tag_list_free (new);
1486               }
1487               gst_buffer_unref (buf);
1488               wav->offset += GST_ROUND_UP_2 (data_size);
1489             }
1490             break;
1491           }
1492           default:
1493             GST_INFO_OBJECT (wav, "Ignoring LIST chunk %" GST_FOURCC_FORMAT,
1494                 GST_FOURCC_ARGS (ltag));
1495             if (!gst_waveparse_ignore_chunk (wav, buf, tag, size))
1496               /* need more data */
1497               goto exit;
1498             break;
1499         }
1500         break;
1501       }
1502       default:
1503         if (!gst_waveparse_ignore_chunk (wav, buf, tag, size))
1504           /* need more data */
1505           goto exit;
1506         break;
1507     }
1508
1509     if (upstream_size && (wav->offset >= upstream_size)) {
1510       /* Now we are gone through the whole file */
1511       gotdata = TRUE;
1512     }
1513   }
1514
1515   GST_DEBUG_OBJECT (wav, "Finished parsing headers");
1516
1517   if (wav->bps <= 0 && wav->fact) {
1518 #if 0
1519     /* not a good idea, as for embedded mp2/mp3 we set bps to 0 earlier */
1520     wav->bps =
1521         (guint32) gst_util_uint64_scale ((guint64) wav->rate, wav->datasize,
1522         (guint64) wav->fact);
1523     GST_INFO_OBJECT (wav, "calculated bps : %d, enabling VBR", wav->bps);
1524 #endif
1525     wav->vbr = TRUE;
1526   }
1527
1528   if (gst_wavparse_calculate_duration (wav)) {
1529     gst_segment_init (&wav->segment, GST_FORMAT_TIME);
1530     wav->segment.duration = wav->duration;
1531   } else {
1532     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
1533     gst_segment_init (&wav->segment, GST_FORMAT_BYTES);
1534     wav->segment.duration = wav->datasize;
1535   }
1536
1537   /* now we have all the info to perform a pending seek if any, if no
1538    * event, this will still do the right thing and it will also send
1539    * the right newsegment event downstream. */
1540   gst_wavparse_perform_seek (wav, wav->seek_event);
1541   /* remove pending event */
1542   event_p = &wav->seek_event;
1543   gst_event_replace (event_p, NULL);
1544
1545   /* we just started, we are discont */
1546   wav->discont = TRUE;
1547
1548   wav->state = GST_WAVPARSE_DATA;
1549
1550   /* determine reasonable max buffer size,
1551    * that is, buffers not too small either size or time wise
1552    * so we do not end up with too many of them */
1553   /* var abuse */
1554   upstream_size = 0;
1555   gst_wavparse_time_to_bytepos (wav, 40 * GST_MSECOND, &upstream_size);
1556   wav->max_buf_size = upstream_size;
1557   wav->max_buf_size = MAX (wav->max_buf_size, MAX_BUFFER_SIZE);
1558   if (wav->blockalign > 0)
1559     wav->max_buf_size -= (wav->max_buf_size % wav->blockalign);
1560
1561   GST_DEBUG_OBJECT (wav, "max buffer size %d", wav->max_buf_size);
1562
1563   return GST_FLOW_OK;
1564
1565   /* ERROR */
1566 exit:
1567   {
1568     if (codec_name)
1569       g_free (codec_name);
1570     if (header)
1571       g_free (header);
1572     if (caps)
1573       gst_caps_unref (caps);
1574     return res;
1575   }
1576 fail:
1577   {
1578     res = GST_FLOW_ERROR;
1579     goto exit;
1580   }
1581 invalid_wav:
1582   {
1583     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
1584         ("Invalid WAV header (no fmt at start): %"
1585             GST_FOURCC_FORMAT, GST_FOURCC_ARGS (tag)));
1586     goto fail;
1587   }
1588 parse_header_error:
1589   {
1590     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
1591         ("Couldn't parse audio header"));
1592     goto fail;
1593   }
1594 no_channels:
1595   {
1596     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
1597         ("Stream claims to contain no channels - invalid data"));
1598     goto fail;
1599   }
1600 no_rate:
1601   {
1602     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
1603         ("Stream with sample_rate == 0 - invalid data"));
1604     goto fail;
1605   }
1606 invalid_blockalign:
1607   {
1608     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
1609         ("Stream claims blockalign = %u, which is more than %u - invalid data",
1610             wav->blockalign, wav->channels * (guint) ceil (wav->depth / 8.0)));
1611     goto fail;
1612   }
1613 invalid_bps:
1614   {
1615     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
1616         ("Stream claims av_bsp = %u, which is more than %u - invalid data",
1617             wav->av_bps, wav->blockalign * wav->rate));
1618     goto fail;
1619   }
1620 no_bytes_per_sample:
1621   {
1622     GST_ELEMENT_ERROR (wav, STREAM, FAILED, (NULL),
1623         ("Could not caluclate bytes per sample - invalid data"));
1624     goto fail;
1625   }
1626 unknown_format:
1627   {
1628     GST_ELEMENT_ERROR (wav, STREAM, TYPE_NOT_FOUND, (NULL),
1629         ("No caps found for format 0x%x, %d channels, %d Hz",
1630             wav->format, wav->channels, wav->rate));
1631     goto fail;
1632   }
1633 header_read_error:
1634   {
1635     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL),
1636         ("Couldn't read in header %d (%s)", res, gst_flow_get_name (res)));
1637     goto fail;
1638   }
1639 }
1640
1641 /*
1642  * Read WAV file tag when streaming
1643  */
1644 static GstFlowReturn
1645 gst_wavparse_parse_stream_init (GstWavParse * wav)
1646 {
1647   if (gst_adapter_available (wav->adapter) >= 12) {
1648     GstBuffer *tmp;
1649
1650     /* _take flushes the data */
1651     tmp = gst_adapter_take_buffer (wav->adapter, 12);
1652
1653     GST_DEBUG ("Parsing wav header");
1654     if (!gst_wavparse_parse_file_header (GST_ELEMENT_CAST (wav), tmp))
1655       return GST_FLOW_ERROR;
1656
1657     wav->offset += 12;
1658     /* Go to next state */
1659     wav->state = GST_WAVPARSE_HEADER;
1660   }
1661   return GST_FLOW_OK;
1662 }
1663
1664 /* handle an event sent directly to the element.
1665  *
1666  * This event can be sent either in the READY state or the
1667  * >READY state. The only event of interest really is the seek
1668  * event.
1669  *
1670  * In the READY state we can only store the event and try to
1671  * respect it when going to PAUSED. We assume we are in the
1672  * READY state when our parsing state != GST_WAVPARSE_DATA.
1673  *
1674  * When we are steaming, we can simply perform the seek right
1675  * away.
1676  */
1677 static gboolean
1678 gst_wavparse_send_event (GstElement * element, GstEvent * event)
1679 {
1680   GstWavParse *wav = GST_WAVPARSE (element);
1681   gboolean res = FALSE;
1682   GstEvent **event_p;
1683
1684   GST_DEBUG_OBJECT (wav, "received event %s", GST_EVENT_TYPE_NAME (event));
1685
1686   switch (GST_EVENT_TYPE (event)) {
1687     case GST_EVENT_SEEK:
1688       if (wav->state == GST_WAVPARSE_DATA) {
1689         /* we can handle the seek directly when streaming data */
1690         res = gst_wavparse_perform_seek (wav, event);
1691       } else {
1692         GST_DEBUG_OBJECT (wav, "queuing seek for later");
1693
1694         event_p = &wav->seek_event;
1695         gst_event_replace (event_p, event);
1696
1697         /* we always return true */
1698         res = TRUE;
1699       }
1700       break;
1701     default:
1702       break;
1703   }
1704   gst_event_unref (event);
1705   return res;
1706 }
1707
1708 static gboolean
1709 gst_wavparse_have_dts_caps (const GstCaps * caps, GstTypeFindProbability prob)
1710 {
1711   GstStructure *s;
1712
1713   s = gst_caps_get_structure (caps, 0);
1714   if (!gst_structure_has_name (s, "audio/x-dts"))
1715     return FALSE;
1716   if (prob >= GST_TYPE_FIND_LIKELY)
1717     return TRUE;
1718   /* DTS at non-0 offsets and without second sync may yield POSSIBLE .. */
1719   if (prob < GST_TYPE_FIND_POSSIBLE)
1720     return FALSE;
1721   /* .. in which case we want at least a valid-looking rate and channels */
1722   if (!gst_structure_has_field (s, "channels"))
1723     return FALSE;
1724   /* and for extra assurance we could also check the rate from the DTS frame
1725    * against the one in the wav header, but for now let's not do that */
1726   return gst_structure_has_field (s, "rate");
1727 }
1728
1729 static void
1730 gst_wavparse_add_src_pad (GstWavParse * wav, GstBuffer * buf)
1731 {
1732   GstStructure *s;
1733
1734   GST_DEBUG_OBJECT (wav, "adding src pad");
1735
1736   if (wav->caps) {
1737     s = gst_caps_get_structure (wav->caps, 0);
1738     if (s && gst_structure_has_name (s, "audio/x-raw") && buf != NULL) {
1739       GstTypeFindProbability prob;
1740       GstCaps *tf_caps;
1741
1742       tf_caps = gst_type_find_helper_for_buffer (GST_OBJECT (wav), buf, &prob);
1743       if (tf_caps != NULL) {
1744         GST_LOG ("typefind caps = %" GST_PTR_FORMAT ", P=%d", tf_caps, prob);
1745         if (gst_wavparse_have_dts_caps (tf_caps, prob)) {
1746           GST_INFO_OBJECT (wav, "Found DTS marker in file marked as raw PCM");
1747           gst_caps_unref (wav->caps);
1748           wav->caps = tf_caps;
1749
1750           gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
1751               GST_TAG_AUDIO_CODEC, "dts", NULL);
1752         } else {
1753           GST_DEBUG_OBJECT (wav, "found caps %" GST_PTR_FORMAT " for stream "
1754               "marked as raw PCM audio, but ignoring for now", tf_caps);
1755           gst_caps_unref (tf_caps);
1756         }
1757       }
1758     }
1759   }
1760
1761   gst_pad_set_caps (wav->srcpad, wav->caps);
1762   gst_caps_replace (&wav->caps, NULL);
1763
1764   if (wav->start_segment) {
1765     GST_DEBUG_OBJECT (wav, "Send start segment event on newpad");
1766     gst_pad_push_event (wav->srcpad, wav->start_segment);
1767     wav->start_segment = NULL;
1768   }
1769
1770   if (wav->tags) {
1771     gst_pad_push_event (wav->srcpad, gst_event_new_tag (wav->tags));
1772     wav->tags = NULL;
1773   }
1774 }
1775
1776 static GstFlowReturn
1777 gst_wavparse_stream_data (GstWavParse * wav)
1778 {
1779   GstBuffer *buf = NULL;
1780   GstFlowReturn res = GST_FLOW_OK;
1781   guint64 desired, obtained;
1782   GstClockTime timestamp, next_timestamp, duration;
1783   guint64 pos, nextpos;
1784
1785 iterate_adapter:
1786   GST_LOG_OBJECT (wav,
1787       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1788       G_GINT64_FORMAT, wav->offset, wav->end_offset, wav->dataleft);
1789
1790   /* Get the next n bytes and output them */
1791   if (wav->dataleft == 0 || wav->dataleft < wav->blockalign)
1792     goto found_eos;
1793
1794   /* scale the amount of data by the segment rate so we get equal
1795    * amounts of data regardless of the playback rate */
1796   desired =
1797       MIN (gst_guint64_to_gdouble (wav->dataleft),
1798       wav->max_buf_size * ABS (wav->segment.rate));
1799
1800   if (desired >= wav->blockalign && wav->blockalign > 0)
1801     desired -= (desired % wav->blockalign);
1802
1803   GST_LOG_OBJECT (wav, "Fetching %" G_GINT64_FORMAT " bytes of data "
1804       "from the sinkpad", desired);
1805
1806   if (wav->streaming) {
1807     guint avail = gst_adapter_available (wav->adapter);
1808     guint extra;
1809
1810     /* flush some bytes if evil upstream sends segment that starts
1811      * before data or does is not send sample aligned segment */
1812     if (G_LIKELY (wav->offset >= wav->datastart)) {
1813       extra = (wav->offset - wav->datastart) % wav->bytes_per_sample;
1814     } else {
1815       extra = wav->datastart - wav->offset;
1816     }
1817
1818     if (G_UNLIKELY (extra)) {
1819       extra = wav->bytes_per_sample - extra;
1820       if (extra <= avail) {
1821         GST_DEBUG_OBJECT (wav, "flushing %d bytes to sample boundary", extra);
1822         gst_adapter_flush (wav->adapter, extra);
1823         wav->offset += extra;
1824         wav->dataleft -= extra;
1825         goto iterate_adapter;
1826       } else {
1827         GST_DEBUG_OBJECT (wav, "flushing %d bytes", avail);
1828         gst_adapter_clear (wav->adapter);
1829         wav->offset += avail;
1830         wav->dataleft -= avail;
1831         return GST_FLOW_OK;
1832       }
1833     }
1834
1835     if (avail < desired) {
1836       GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
1837       return GST_FLOW_OK;
1838     }
1839
1840     buf = gst_adapter_take_buffer (wav->adapter, desired);
1841   } else {
1842     if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset,
1843                 desired, &buf)) != GST_FLOW_OK)
1844       goto pull_error;
1845
1846     /* we may get a short buffer at the end of the file */
1847     if (gst_buffer_get_size (buf) < desired) {
1848       gsize size = gst_buffer_get_size (buf);
1849
1850       GST_LOG_OBJECT (wav, "Got only %" G_GSIZE_FORMAT " bytes of data", size);
1851       if (size >= wav->blockalign) {
1852         buf = gst_buffer_make_writable (buf);
1853         gst_buffer_resize (buf, 0, size - (size % wav->blockalign));
1854       } else {
1855         gst_buffer_unref (buf);
1856         goto found_eos;
1857       }
1858     }
1859   }
1860
1861   obtained = gst_buffer_get_size (buf);
1862
1863   /* our positions in bytes */
1864   pos = wav->offset - wav->datastart;
1865   nextpos = pos + obtained;
1866
1867   /* update offsets, does not overflow. */
1868   buf = gst_buffer_make_writable (buf);
1869   GST_BUFFER_OFFSET (buf) = pos / wav->bytes_per_sample;
1870   GST_BUFFER_OFFSET_END (buf) = nextpos / wav->bytes_per_sample;
1871
1872   /* first chunk of data? create the source pad. We do this only here so
1873    * we can detect broken .wav files with dts disguised as raw PCM (sigh) */
1874   if (G_UNLIKELY (wav->first)) {
1875     wav->first = FALSE;
1876     /* this will also push the segment events */
1877     gst_wavparse_add_src_pad (wav, buf);
1878   } else {
1879     /* If we have a pending start segment, send it now. */
1880     if (G_UNLIKELY (wav->start_segment != NULL)) {
1881       gst_pad_push_event (wav->srcpad, wav->start_segment);
1882       wav->start_segment = NULL;
1883     }
1884   }
1885
1886   if (wav->bps > 0) {
1887     /* and timestamps if we have a bitrate, be careful for overflows */
1888     timestamp = uint64_ceiling_scale (pos, GST_SECOND, (guint64) wav->bps);
1889     next_timestamp =
1890         uint64_ceiling_scale (nextpos, GST_SECOND, (guint64) wav->bps);
1891     duration = next_timestamp - timestamp;
1892
1893     /* update current running segment position */
1894     if (G_LIKELY (next_timestamp >= wav->segment.start))
1895       wav->segment.position = next_timestamp;
1896   } else if (wav->fact) {
1897     guint64 bps =
1898         gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
1899     /* and timestamps if we have a bitrate, be careful for overflows */
1900     timestamp = uint64_ceiling_scale (pos, GST_SECOND, bps);
1901     next_timestamp = uint64_ceiling_scale (nextpos, GST_SECOND, bps);
1902     duration = next_timestamp - timestamp;
1903   } else {
1904     /* no bitrate, all we know is that the first sample has timestamp 0, all
1905      * other positions and durations have unknown timestamp. */
1906     if (pos == 0)
1907       timestamp = 0;
1908     else
1909       timestamp = GST_CLOCK_TIME_NONE;
1910     duration = GST_CLOCK_TIME_NONE;
1911     /* update current running segment position with byte offset */
1912     if (G_LIKELY (nextpos >= wav->segment.start))
1913       wav->segment.position = nextpos;
1914   }
1915   if ((pos > 0) && wav->vbr) {
1916     /* don't set timestamps for VBR files if it's not the first buffer */
1917     timestamp = GST_CLOCK_TIME_NONE;
1918     duration = GST_CLOCK_TIME_NONE;
1919   }
1920   if (wav->discont) {
1921     GST_DEBUG_OBJECT (wav, "marking DISCONT");
1922     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1923     wav->discont = FALSE;
1924   }
1925
1926   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1927   GST_BUFFER_DURATION (buf) = duration;
1928
1929   GST_LOG_OBJECT (wav,
1930       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1931       ", size:%" G_GSIZE_FORMAT, GST_TIME_ARGS (timestamp),
1932       GST_TIME_ARGS (duration), gst_buffer_get_size (buf));
1933
1934   if ((res = gst_pad_push (wav->srcpad, buf)) != GST_FLOW_OK)
1935     goto push_error;
1936
1937   if (obtained < wav->dataleft) {
1938     wav->offset += obtained;
1939     wav->dataleft -= obtained;
1940   } else {
1941     wav->offset += wav->dataleft;
1942     wav->dataleft = 0;
1943   }
1944
1945   /* Iterate until need more data, so adapter size won't grow */
1946   if (wav->streaming) {
1947     GST_LOG_OBJECT (wav,
1948         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, wav->offset,
1949         wav->end_offset);
1950     goto iterate_adapter;
1951   }
1952   return res;
1953
1954   /* ERROR */
1955 found_eos:
1956   {
1957     GST_DEBUG_OBJECT (wav, "found EOS");
1958     return GST_FLOW_EOS;
1959   }
1960 pull_error:
1961   {
1962     /* check if we got EOS */
1963     if (res == GST_FLOW_EOS)
1964       goto found_eos;
1965
1966     GST_WARNING_OBJECT (wav,
1967         "Error getting %" G_GINT64_FORMAT " bytes from the "
1968         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, wav->dataleft);
1969     return res;
1970   }
1971 push_error:
1972   {
1973     GST_INFO_OBJECT (wav,
1974         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1975         GST_DEBUG_PAD_NAME (wav->srcpad), gst_flow_get_name (res),
1976         gst_pad_is_linked (wav->srcpad));
1977     return res;
1978   }
1979 }
1980
1981 static void
1982 gst_wavparse_loop (GstPad * pad)
1983 {
1984   GstFlowReturn ret;
1985   GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
1986
1987   GST_LOG_OBJECT (wav, "process data");
1988
1989   switch (wav->state) {
1990     case GST_WAVPARSE_START:
1991       GST_INFO_OBJECT (wav, "GST_WAVPARSE_START");
1992       if ((ret = gst_wavparse_stream_init (wav)) != GST_FLOW_OK)
1993         goto pause;
1994
1995       wav->state = GST_WAVPARSE_HEADER;
1996       /* fall-through */
1997
1998     case GST_WAVPARSE_HEADER:
1999       GST_INFO_OBJECT (wav, "GST_WAVPARSE_HEADER");
2000       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
2001         goto pause;
2002
2003       wav->state = GST_WAVPARSE_DATA;
2004       GST_INFO_OBJECT (wav, "GST_WAVPARSE_DATA");
2005       /* fall-through */
2006
2007     case GST_WAVPARSE_DATA:
2008       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
2009         goto pause;
2010       break;
2011     default:
2012       g_assert_not_reached ();
2013   }
2014   return;
2015
2016   /* ERRORS */
2017 pause:
2018   {
2019     const gchar *reason = gst_flow_get_name (ret);
2020
2021     GST_DEBUG_OBJECT (wav, "pausing task, reason %s", reason);
2022     gst_pad_pause_task (pad);
2023
2024     if (ret == GST_FLOW_EOS) {
2025       /* handle end-of-stream/segment */
2026       /* so align our position with the end of it, if there is one
2027        * this ensures a subsequent will arrive at correct base/acc time */
2028       if (wav->segment.format == GST_FORMAT_TIME) {
2029         if (wav->segment.rate > 0.0 &&
2030             GST_CLOCK_TIME_IS_VALID (wav->segment.stop))
2031           wav->segment.position = wav->segment.stop;
2032         else if (wav->segment.rate < 0.0)
2033           wav->segment.position = wav->segment.start;
2034       }
2035       /* add pad before we perform EOS */
2036       if (G_UNLIKELY (wav->first)) {
2037         wav->first = FALSE;
2038         gst_wavparse_add_src_pad (wav, NULL);
2039       }
2040
2041       if (wav->state == GST_WAVPARSE_START)
2042         GST_ELEMENT_ERROR (wav, STREAM, WRONG_TYPE,
2043             ("No valid input found before end of stream"), (NULL));
2044
2045       /* perform EOS logic */
2046       if (wav->segment.flags & GST_SEEK_FLAG_SEGMENT) {
2047         GstClockTime stop;
2048
2049         if ((stop = wav->segment.stop) == -1)
2050           stop = wav->segment.duration;
2051
2052         gst_element_post_message (GST_ELEMENT_CAST (wav),
2053             gst_message_new_segment_done (GST_OBJECT_CAST (wav),
2054                 wav->segment.format, stop));
2055       } else {
2056         gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
2057       }
2058     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2059       /* for fatal errors we post an error message, post the error
2060        * first so the app knows about the error first. */
2061       GST_ELEMENT_ERROR (wav, STREAM, FAILED,
2062           (_("Internal data flow error.")),
2063           ("streaming task paused, reason %s (%d)", reason, ret));
2064       gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
2065     }
2066     return;
2067   }
2068 }
2069
2070 static GstFlowReturn
2071 gst_wavparse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
2072 {
2073   GstFlowReturn ret;
2074   GstWavParse *wav = GST_WAVPARSE (parent);
2075
2076   GST_LOG_OBJECT (wav, "adapter_push %" G_GSIZE_FORMAT " bytes",
2077       gst_buffer_get_size (buf));
2078
2079   gst_adapter_push (wav->adapter, buf);
2080
2081   switch (wav->state) {
2082     case GST_WAVPARSE_START:
2083       GST_INFO_OBJECT (wav, "GST_WAVPARSE_START");
2084       if ((ret = gst_wavparse_parse_stream_init (wav)) != GST_FLOW_OK)
2085         goto done;
2086
2087       if (wav->state != GST_WAVPARSE_HEADER)
2088         break;
2089
2090       /* otherwise fall-through */
2091     case GST_WAVPARSE_HEADER:
2092       GST_INFO_OBJECT (wav, "GST_WAVPARSE_HEADER");
2093       if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
2094         goto done;
2095
2096       if (!wav->got_fmt || wav->datastart == 0)
2097         break;
2098
2099       wav->state = GST_WAVPARSE_DATA;
2100       GST_INFO_OBJECT (wav, "GST_WAVPARSE_DATA");
2101
2102       /* fall-through */
2103     case GST_WAVPARSE_DATA:
2104       if (buf && GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))
2105         wav->discont = TRUE;
2106       if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
2107         goto done;
2108       break;
2109     default:
2110       g_return_val_if_reached (GST_FLOW_ERROR);
2111   }
2112 done:
2113   if (G_UNLIKELY (wav->abort_buffering)) {
2114     wav->abort_buffering = FALSE;
2115     ret = GST_FLOW_ERROR;
2116     /* sort of demux/parse error */
2117     GST_ELEMENT_ERROR (wav, STREAM, DEMUX, (NULL), ("unhandled buffer size"));
2118   }
2119
2120   return ret;
2121 }
2122
2123 static GstFlowReturn
2124 gst_wavparse_flush_data (GstWavParse * wav)
2125 {
2126   GstFlowReturn ret = GST_FLOW_OK;
2127   guint av;
2128
2129   if ((av = gst_adapter_available (wav->adapter)) > 0) {
2130     wav->dataleft = av;
2131     wav->end_offset = wav->offset + av;
2132     ret = gst_wavparse_stream_data (wav);
2133   }
2134
2135   return ret;
2136 }
2137
2138 static gboolean
2139 gst_wavparse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
2140 {
2141   GstWavParse *wav = GST_WAVPARSE (parent);
2142   gboolean ret = TRUE;
2143
2144   GST_LOG_OBJECT (wav, "handling %s event", GST_EVENT_TYPE_NAME (event));
2145
2146   switch (GST_EVENT_TYPE (event)) {
2147     case GST_EVENT_CAPS:
2148     {
2149       /* discard, we'll come up with proper src caps */
2150       gst_event_unref (event);
2151       break;
2152     }
2153     case GST_EVENT_SEGMENT:
2154     {
2155       gint64 start, stop, offset = 0, end_offset = -1;
2156       GstSegment segment;
2157
2158       /* some debug output */
2159       gst_event_copy_segment (event, &segment);
2160       GST_DEBUG_OBJECT (wav, "received newsegment %" GST_SEGMENT_FORMAT,
2161           &segment);
2162
2163       if (wav->state != GST_WAVPARSE_DATA) {
2164         GST_DEBUG_OBJECT (wav, "still starting, eating event");
2165         goto exit;
2166       }
2167
2168       /* now we are either committed to TIME or BYTE format,
2169        * and we only expect a BYTE segment, e.g. following a seek */
2170       if (segment.format == GST_FORMAT_BYTES) {
2171         /* handle (un)signed issues */
2172         start = segment.start;
2173         stop = segment.stop;
2174         if (start > 0) {
2175           offset = start;
2176           start -= wav->datastart;
2177           start = MAX (start, 0);
2178         }
2179         if (stop > 0) {
2180           end_offset = stop;
2181           segment.stop -= wav->datastart;
2182           segment.stop = MAX (stop, 0);
2183         }
2184         if (wav->segment.format == GST_FORMAT_TIME) {
2185           guint64 bps = wav->bps;
2186
2187           /* operating in format TIME, so we can convert */
2188           if (!bps && wav->fact)
2189             bps =
2190                 gst_util_uint64_scale_int (wav->datasize, wav->rate, wav->fact);
2191           if (bps) {
2192             if (start >= 0)
2193               start =
2194                   uint64_ceiling_scale (start, GST_SECOND, (guint64) wav->bps);
2195             if (stop >= 0)
2196               stop =
2197                   uint64_ceiling_scale (stop, GST_SECOND, (guint64) wav->bps);
2198           }
2199         }
2200       } else {
2201         GST_DEBUG_OBJECT (wav, "unsupported segment format, ignoring");
2202         goto exit;
2203       }
2204
2205       segment.start = start;
2206       segment.stop = stop;
2207
2208       /* accept upstream's notion of segment and distribute along */
2209       segment.time = segment.start = segment.position;
2210       segment.duration = wav->segment.duration;
2211       segment.base = gst_segment_to_running_time (&wav->segment,
2212           GST_FORMAT_TIME, wav->segment.position);
2213
2214       gst_segment_copy_into (&segment, &wav->segment);
2215
2216       /* also store the newsegment event for the streaming thread */
2217       if (wav->start_segment)
2218         gst_event_unref (wav->start_segment);
2219       GST_DEBUG_OBJECT (wav, "Storing newseg %" GST_SEGMENT_FORMAT, &segment);
2220       wav->start_segment = gst_event_new_segment (&segment);
2221
2222       /* stream leftover data in current segment */
2223       gst_wavparse_flush_data (wav);
2224       /* and set up streaming thread for next one */
2225       wav->offset = offset;
2226       wav->end_offset = end_offset;
2227       if (wav->end_offset > 0) {
2228         wav->dataleft = wav->end_offset - wav->offset;
2229       } else {
2230         /* infinity; upstream will EOS when done */
2231         wav->dataleft = G_MAXUINT64;
2232       }
2233     exit:
2234       gst_event_unref (event);
2235       break;
2236     }
2237     case GST_EVENT_EOS:
2238       /* add pad if needed so EOS is seen downstream */
2239       if (G_UNLIKELY (wav->first)) {
2240         wav->first = FALSE;
2241         gst_wavparse_add_src_pad (wav, NULL);
2242       } else {
2243         /* stream leftover data in current segment */
2244         gst_wavparse_flush_data (wav);
2245       }
2246
2247       if (wav->state == GST_WAVPARSE_START)
2248         GST_ELEMENT_ERROR (wav, STREAM, WRONG_TYPE,
2249             ("No valid input found before end of stream"), (NULL));
2250
2251       /* fall-through */
2252     case GST_EVENT_FLUSH_STOP:
2253     {
2254       GstClockTime dur;
2255
2256       gst_adapter_clear (wav->adapter);
2257       wav->discont = TRUE;
2258       dur = wav->segment.duration;
2259       gst_segment_init (&wav->segment, wav->segment.format);
2260       wav->segment.duration = dur;
2261       /* fall-through */
2262     }
2263     default:
2264       ret = gst_pad_event_default (wav->sinkpad, parent, event);
2265       break;
2266   }
2267
2268   return ret;
2269 }
2270
2271 #if 0
2272 /* convert and query stuff */
2273 static const GstFormat *
2274 gst_wavparse_get_formats (GstPad * pad)
2275 {
2276   static GstFormat formats[] = {
2277     GST_FORMAT_TIME,
2278     GST_FORMAT_BYTES,
2279     GST_FORMAT_DEFAULT,         /* a "frame", ie a set of samples per Hz */
2280     0
2281   };
2282
2283   return formats;
2284 }
2285 #endif
2286
2287 static gboolean
2288 gst_wavparse_pad_convert (GstPad * pad,
2289     GstFormat src_format, gint64 src_value,
2290     GstFormat * dest_format, gint64 * dest_value)
2291 {
2292   GstWavParse *wavparse;
2293   gboolean res = TRUE;
2294
2295   wavparse = GST_WAVPARSE (GST_PAD_PARENT (pad));
2296
2297   if (*dest_format == src_format) {
2298     *dest_value = src_value;
2299     return TRUE;
2300   }
2301
2302   if ((wavparse->bps == 0) && !wavparse->fact)
2303     goto no_bps_fact;
2304
2305   GST_INFO_OBJECT (wavparse, "converting value from %s to %s",
2306       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
2307
2308   switch (src_format) {
2309     case GST_FORMAT_BYTES:
2310       switch (*dest_format) {
2311         case GST_FORMAT_DEFAULT:
2312           *dest_value = src_value / wavparse->bytes_per_sample;
2313           /* make sure we end up on a sample boundary */
2314           *dest_value -= *dest_value % wavparse->bytes_per_sample;
2315           break;
2316         case GST_FORMAT_TIME:
2317           /* src_value + datastart = offset */
2318           GST_INFO_OBJECT (wavparse,
2319               "src=%" G_GINT64_FORMAT ", offset=%" G_GINT64_FORMAT, src_value,
2320               wavparse->offset);
2321           if (wavparse->bps > 0)
2322             *dest_value = uint64_ceiling_scale (src_value, GST_SECOND,
2323                 (guint64) wavparse->bps);
2324           else if (wavparse->fact) {
2325             guint64 bps = uint64_ceiling_scale_int (wavparse->datasize,
2326                 wavparse->rate, wavparse->fact);
2327
2328             *dest_value = uint64_ceiling_scale_int (src_value, GST_SECOND, bps);
2329           } else {
2330             res = FALSE;
2331           }
2332           break;
2333         default:
2334           res = FALSE;
2335           goto done;
2336       }
2337       break;
2338
2339     case GST_FORMAT_DEFAULT:
2340       switch (*dest_format) {
2341         case GST_FORMAT_BYTES:
2342           *dest_value = src_value * wavparse->bytes_per_sample;
2343           break;
2344         case GST_FORMAT_TIME:
2345           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
2346               (guint64) wavparse->rate);
2347           break;
2348         default:
2349           res = FALSE;
2350           goto done;
2351       }
2352       break;
2353
2354     case GST_FORMAT_TIME:
2355       switch (*dest_format) {
2356         case GST_FORMAT_BYTES:
2357           if (wavparse->bps > 0)
2358             *dest_value = gst_util_uint64_scale (src_value,
2359                 (guint64) wavparse->bps, GST_SECOND);
2360           else {
2361             guint64 bps = gst_util_uint64_scale_int (wavparse->datasize,
2362                 wavparse->rate, wavparse->fact);
2363
2364             *dest_value = gst_util_uint64_scale (src_value, bps, GST_SECOND);
2365           }
2366           /* make sure we end up on a sample boundary */
2367           *dest_value -= *dest_value % wavparse->blockalign;
2368           break;
2369         case GST_FORMAT_DEFAULT:
2370           *dest_value = gst_util_uint64_scale (src_value,
2371               (guint64) wavparse->rate, GST_SECOND);
2372           break;
2373         default:
2374           res = FALSE;
2375           goto done;
2376       }
2377       break;
2378
2379     default:
2380       res = FALSE;
2381       goto done;
2382   }
2383
2384 done:
2385   return res;
2386
2387   /* ERRORS */
2388 no_bps_fact:
2389   {
2390     GST_DEBUG_OBJECT (wavparse, "bps 0 or no fact chunk, cannot convert");
2391     res = FALSE;
2392     goto done;
2393   }
2394 }
2395
2396 /* handle queries for location and length in requested format */
2397 static gboolean
2398 gst_wavparse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
2399 {
2400   gboolean res = TRUE;
2401   GstWavParse *wav = GST_WAVPARSE (parent);
2402
2403   /* only if we know */
2404   if (wav->state != GST_WAVPARSE_DATA) {
2405     return FALSE;
2406   }
2407
2408   GST_LOG_OBJECT (pad, "%s query", GST_QUERY_TYPE_NAME (query));
2409
2410   switch (GST_QUERY_TYPE (query)) {
2411     case GST_QUERY_POSITION:
2412     {
2413       gint64 curb;
2414       gint64 cur;
2415       GstFormat format;
2416
2417       /* this is not very precise, as we have pushed severla buffer upstream for prerolling */
2418       curb = wav->offset - wav->datastart;
2419       gst_query_parse_position (query, &format, NULL);
2420       GST_INFO_OBJECT (wav, "pos query at %" G_GINT64_FORMAT, curb);
2421
2422       switch (format) {
2423         case GST_FORMAT_TIME:
2424           res = gst_wavparse_pad_convert (pad, GST_FORMAT_BYTES, curb,
2425               &format, &cur);
2426           break;
2427         default:
2428           format = GST_FORMAT_BYTES;
2429           cur = curb;
2430           break;
2431       }
2432       if (res)
2433         gst_query_set_position (query, format, cur);
2434       break;
2435     }
2436     case GST_QUERY_DURATION:
2437     {
2438       gint64 duration = 0;
2439       GstFormat format;
2440
2441       gst_query_parse_duration (query, &format, NULL);
2442
2443       switch (format) {
2444         case GST_FORMAT_TIME:{
2445           if ((res = gst_wavparse_calculate_duration (wav))) {
2446             duration = wav->duration;
2447           }
2448           break;
2449         }
2450         default:
2451           format = GST_FORMAT_BYTES;
2452           duration = wav->datasize;
2453           break;
2454       }
2455       gst_query_set_duration (query, format, duration);
2456       break;
2457     }
2458     case GST_QUERY_CONVERT:
2459     {
2460       gint64 srcvalue, dstvalue;
2461       GstFormat srcformat, dstformat;
2462
2463       gst_query_parse_convert (query, &srcformat, &srcvalue,
2464           &dstformat, &dstvalue);
2465       res = gst_wavparse_pad_convert (pad, srcformat, srcvalue,
2466           &dstformat, &dstvalue);
2467       if (res)
2468         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
2469       break;
2470     }
2471     case GST_QUERY_SEEKING:{
2472       GstFormat fmt;
2473       gboolean seekable = FALSE;
2474
2475       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
2476       if (fmt == wav->segment.format) {
2477         if (wav->streaming) {
2478           GstQuery *q;
2479
2480           q = gst_query_new_seeking (GST_FORMAT_BYTES);
2481           if ((res = gst_pad_peer_query (wav->sinkpad, q))) {
2482             gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
2483             GST_LOG_OBJECT (wav, "upstream BYTE seekable %d", seekable);
2484           }
2485           gst_query_unref (q);
2486         } else {
2487           GST_LOG_OBJECT (wav, "looping => seekable");
2488           seekable = TRUE;
2489           res = TRUE;
2490         }
2491       } else if (fmt == GST_FORMAT_TIME) {
2492         res = TRUE;
2493       }
2494       if (res) {
2495         gst_query_set_seeking (query, fmt, seekable, 0, wav->segment.duration);
2496       }
2497       break;
2498     }
2499     default:
2500       res = gst_pad_query_default (pad, parent, query);
2501       break;
2502   }
2503   return res;
2504 }
2505
2506 static gboolean
2507 gst_wavparse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
2508 {
2509   GstWavParse *wavparse = GST_WAVPARSE (parent);
2510   gboolean res = FALSE;
2511
2512   GST_DEBUG_OBJECT (wavparse, "%s event", GST_EVENT_TYPE_NAME (event));
2513
2514   switch (GST_EVENT_TYPE (event)) {
2515     case GST_EVENT_SEEK:
2516       /* can only handle events when we are in the data state */
2517       if (wavparse->state == GST_WAVPARSE_DATA) {
2518         res = gst_wavparse_perform_seek (wavparse, event);
2519       }
2520       gst_event_unref (event);
2521       break;
2522     default:
2523       res = gst_pad_push_event (wavparse->sinkpad, event);
2524       break;
2525   }
2526   return res;
2527 }
2528
2529 static gboolean
2530 gst_wavparse_sink_activate (GstPad * sinkpad, GstObject * parent)
2531 {
2532   GstWavParse *wav = GST_WAVPARSE (parent);
2533   GstQuery *query;
2534   gboolean pull_mode;
2535
2536   if (wav->adapter) {
2537     gst_adapter_clear (wav->adapter);
2538     g_object_unref (wav->adapter);
2539     wav->adapter = NULL;
2540   }
2541
2542   query = gst_query_new_scheduling ();
2543
2544   if (!gst_pad_peer_query (sinkpad, query)) {
2545     gst_query_unref (query);
2546     goto activate_push;
2547   }
2548
2549   pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
2550   gst_query_unref (query);
2551
2552   if (!pull_mode)
2553     goto activate_push;
2554
2555   GST_DEBUG_OBJECT (sinkpad, "activating pull");
2556   wav->streaming = FALSE;
2557   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
2558
2559 activate_push:
2560   {
2561     GST_DEBUG_OBJECT (sinkpad, "activating push");
2562     wav->streaming = TRUE;
2563     wav->adapter = gst_adapter_new ();
2564     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
2565   }
2566 }
2567
2568
2569 static gboolean
2570 gst_wavparse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
2571     GstPadMode mode, gboolean active)
2572 {
2573   gboolean res;
2574
2575   switch (mode) {
2576     case GST_PAD_MODE_PUSH:
2577       res = TRUE;
2578       break;
2579     case GST_PAD_MODE_PULL:
2580       if (active) {
2581         /* if we have a scheduler we can start the task */
2582         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop,
2583             sinkpad);
2584       } else {
2585         res = gst_pad_stop_task (sinkpad);
2586       }
2587       break;
2588     default:
2589       res = FALSE;
2590       break;
2591   }
2592   return res;
2593 }
2594
2595 static GstStateChangeReturn
2596 gst_wavparse_change_state (GstElement * element, GstStateChange transition)
2597 {
2598   GstStateChangeReturn ret;
2599   GstWavParse *wav = GST_WAVPARSE (element);
2600
2601   switch (transition) {
2602     case GST_STATE_CHANGE_NULL_TO_READY:
2603       break;
2604     case GST_STATE_CHANGE_READY_TO_PAUSED:
2605       gst_wavparse_reset (wav);
2606       break;
2607     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
2608       break;
2609     default:
2610       break;
2611   }
2612
2613   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2614
2615   switch (transition) {
2616     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2617       break;
2618     case GST_STATE_CHANGE_PAUSED_TO_READY:
2619       gst_wavparse_reset (wav);
2620       break;
2621     case GST_STATE_CHANGE_READY_TO_NULL:
2622       break;
2623     default:
2624       break;
2625   }
2626   return ret;
2627 }
2628
2629 static gboolean
2630 plugin_init (GstPlugin * plugin)
2631 {
2632   gst_riff_init ();
2633
2634   return gst_element_register (plugin, "wavparse", GST_RANK_PRIMARY,
2635       GST_TYPE_WAVPARSE);
2636 }
2637
2638 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2639     GST_VERSION_MINOR,
2640     "wavparse",
2641     "Parse a .wav file into raw audio",
2642     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)