aiffparse: Add support for 32 bit and 64 bit floating point formats
[platform/upstream/gstreamer.git] / gst / aiff / aiffparse.c
1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
2 /* GStreamer AIFF parser
3  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
4  *               <2006> Nokia Corporation, Stefan Kost <stefan.kost@nokia.com>.
5  *               <2008> Pioneers of the Inevitable <songbird@songbirdnest.com>
6  *
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:element-aiffparse
26  *
27  * <refsect2>
28  * <para>
29  * Parse a .aiff file into raw or compressed audio.
30  * </para>
31  * <para>
32  * AIFFparse supports both push and pull mode operations, making it possible to
33  * stream from a network source.
34  * </para>
35  * <title>Example launch line</title>
36  * <para>
37  * <programlisting>
38  * gst-launch filesrc location=sine.aiff ! aiffparse ! audioconvert ! alsasink
39  * </programlisting>
40  * Read a aiff file and output to the soundcard using the ALSA element. The
41  * aiff file is assumed to contain raw uncompressed samples.
42  * </para>
43  * <para>
44  * <programlisting>
45  * gst-launch gnomevfssrc location=http://www.example.org/sine.aiff ! queue ! aiffparse ! audioconvert ! alsasink
46  * </programlisting>
47  * Stream data from a network url.
48  * </para>
49  * </refsect2>
50  */
51
52 #ifdef HAVE_CONFIG_H
53 #include "config.h"
54 #endif
55 #include <string.h>
56 #include <math.h>
57
58 #include "aiffparse.h"
59 #include <gst/audio/audio.h>
60 #include <gst/gst-i18n-plugin.h>
61
62 GST_DEBUG_CATEGORY (aiffparse_debug);
63 #define GST_CAT_DEFAULT (aiffparse_debug)
64
65 static void gst_aiff_parse_dispose (GObject * object);
66
67 static gboolean gst_aiff_parse_sink_activate (GstPad * sinkpad);
68 static gboolean gst_aiff_parse_sink_activate_pull (GstPad * sinkpad,
69     gboolean active);
70 static gboolean gst_aiff_parse_send_event (GstElement * element,
71     GstEvent * event);
72 static GstStateChangeReturn gst_aiff_parse_change_state (GstElement * element,
73     GstStateChange transition);
74
75 static const GstQueryType *gst_aiff_parse_get_query_types (GstPad * pad);
76 static gboolean gst_aiff_parse_pad_query (GstPad * pad, GstQuery * query);
77 static gboolean gst_aiff_parse_pad_convert (GstPad * pad,
78     GstFormat src_format,
79     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
80
81 static GstFlowReturn gst_aiff_parse_chain (GstPad * pad, GstBuffer * buf);
82 static void gst_aiff_parse_loop (GstPad * pad);
83 static gboolean gst_aiff_parse_srcpad_event (GstPad * pad, GstEvent * event);
84
85 static GstStaticPadTemplate sink_template_factory =
86 GST_STATIC_PAD_TEMPLATE ("sink",
87     GST_PAD_SINK,
88     GST_PAD_ALWAYS,
89     GST_STATIC_CAPS ("audio/x-aiff")
90     );
91
92 static GstStaticPadTemplate src_template_factory =
93 GST_STATIC_PAD_TEMPLATE ("src",
94     GST_PAD_SRC,
95     GST_PAD_ALWAYS,
96     GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS)
97     );
98
99 GST_BOILERPLATE (GstAiffParse, gst_aiff_parse, GstElement, GST_TYPE_ELEMENT);
100
101 static void
102 gst_aiff_parse_base_init (gpointer g_class)
103 {
104   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
105
106   gst_element_class_add_pad_template (element_class,
107       gst_static_pad_template_get (&sink_template_factory));
108   gst_element_class_add_pad_template (element_class,
109       gst_static_pad_template_get (&src_template_factory));
110
111   gst_element_class_set_details_simple (element_class,
112       "AIFF audio demuxer", "Codec/Demuxer/Audio",
113       "Parse a .aiff file into raw audio",
114       "Pioneers of the Inevitable <songbird@songbirdnest.com>");
115 }
116
117 static void
118 gst_aiff_parse_class_init (GstAiffParseClass * klass)
119 {
120   GstElementClass *gstelement_class;
121   GObjectClass *object_class;
122
123   gstelement_class = (GstElementClass *) klass;
124   object_class = (GObjectClass *) klass;
125
126   parent_class = g_type_class_peek_parent (klass);
127
128   object_class->dispose = gst_aiff_parse_dispose;
129
130   gstelement_class->change_state =
131       GST_DEBUG_FUNCPTR (gst_aiff_parse_change_state);
132   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_aiff_parse_send_event);
133 }
134
135 static void
136 gst_aiff_parse_reset (GstAiffParse * aiff)
137 {
138   aiff->state = AIFF_PARSE_START;
139
140   /* These will all be set correctly in the fmt chunk */
141   aiff->rate = 0;
142   aiff->width = 0;
143   aiff->depth = 0;
144   aiff->channels = 0;
145   aiff->bps = 0;
146   aiff->offset = 0;
147   aiff->end_offset = 0;
148   aiff->dataleft = 0;
149   aiff->datasize = 0;
150   aiff->datastart = 0;
151   aiff->duration = 0;
152   aiff->got_comm = FALSE;
153
154   if (aiff->caps) {
155     gst_caps_unref (aiff->caps);
156     aiff->caps = NULL;
157   }
158   if (aiff->seek_event)
159     gst_event_unref (aiff->seek_event);
160   aiff->seek_event = NULL;
161   if (aiff->adapter) {
162     gst_adapter_clear (aiff->adapter);
163     aiff->adapter = NULL;
164   }
165 }
166
167 static void
168 gst_aiff_parse_dispose (GObject * object)
169 {
170   GstAiffParse *aiff = GST_AIFF_PARSE (object);
171
172   GST_DEBUG_OBJECT (aiff, "AIFF: Dispose");
173   gst_aiff_parse_reset (aiff);
174
175   G_OBJECT_CLASS (parent_class)->dispose (object);
176 }
177
178 static void
179 gst_aiff_parse_init (GstAiffParse * aiffparse, GstAiffParseClass * g_class)
180 {
181   gst_aiff_parse_reset (aiffparse);
182
183   /* sink */
184   aiffparse->sinkpad =
185       gst_pad_new_from_static_template (&sink_template_factory, "sink");
186   gst_pad_set_activate_function (aiffparse->sinkpad,
187       GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate));
188   gst_pad_set_activatepull_function (aiffparse->sinkpad,
189       GST_DEBUG_FUNCPTR (gst_aiff_parse_sink_activate_pull));
190   gst_pad_set_chain_function (aiffparse->sinkpad,
191       GST_DEBUG_FUNCPTR (gst_aiff_parse_chain));
192   gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->sinkpad);
193
194   /* source */
195   aiffparse->srcpad =
196       gst_pad_new_from_static_template (&src_template_factory, "src");
197   gst_pad_use_fixed_caps (aiffparse->srcpad);
198   gst_pad_set_query_type_function (aiffparse->srcpad,
199       GST_DEBUG_FUNCPTR (gst_aiff_parse_get_query_types));
200   gst_pad_set_query_function (aiffparse->srcpad,
201       GST_DEBUG_FUNCPTR (gst_aiff_parse_pad_query));
202   gst_pad_set_event_function (aiffparse->srcpad,
203       GST_DEBUG_FUNCPTR (gst_aiff_parse_srcpad_event));
204   gst_element_add_pad (GST_ELEMENT_CAST (aiffparse), aiffparse->srcpad);
205 }
206
207 static gboolean
208 gst_aiff_parse_parse_file_header (GstAiffParse * aiff, GstBuffer * buf)
209 {
210   guint8 *data;
211   guint32 header, type = 0;
212
213   if (GST_BUFFER_SIZE (buf) < 12) {
214     GST_WARNING_OBJECT (aiff, "Buffer too short");
215     goto not_aiff;
216   }
217
218   data = GST_BUFFER_DATA (buf);
219
220   header = GST_READ_UINT32_LE (data);
221   type = GST_READ_UINT32_LE (data + 8);
222
223   if (header != GST_MAKE_FOURCC ('F', 'O', 'R', 'M'))
224     goto not_aiff;
225
226   if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'F'))
227     aiff->is_aifc = FALSE;
228   else if (type == GST_MAKE_FOURCC ('A', 'I', 'F', 'C'))
229     aiff->is_aifc = TRUE;
230   else
231     goto not_aiff;
232
233   gst_buffer_unref (buf);
234   return TRUE;
235
236   /* ERRORS */
237 not_aiff:
238   {
239     GST_ELEMENT_ERROR (aiff, STREAM, WRONG_TYPE, (NULL),
240         ("File is not an AIFF file: %" GST_FOURCC_FORMAT,
241             GST_FOURCC_ARGS (type)));
242     gst_buffer_unref (buf);
243     return FALSE;
244   }
245 }
246
247 static GstFlowReturn
248 gst_aiff_parse_stream_init (GstAiffParse * aiff)
249 {
250   GstFlowReturn res;
251   GstBuffer *buf = NULL;
252
253   if ((res = gst_pad_pull_range (aiff->sinkpad,
254               aiff->offset, 12, &buf)) != GST_FLOW_OK)
255     return res;
256   else if (!gst_aiff_parse_parse_file_header (aiff, buf))
257     return GST_FLOW_ERROR;
258
259   aiff->offset += 12;
260
261   return GST_FLOW_OK;
262 }
263
264 /* This function is used to perform seeks on the element in
265  * pull mode.
266  *
267  * It also works when event is NULL, in which case it will just
268  * start from the last configured segment. This technique is
269  * used when activating the element and to perform the seek in
270  * READY.
271  */
272 static gboolean
273 gst_aiff_parse_perform_seek (GstAiffParse * aiff, GstEvent * event)
274 {
275   gboolean res;
276   gdouble rate;
277   GstFormat format, bformat;
278   GstSeekFlags flags;
279   GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type;
280   gint64 cur, stop, upstream_size;
281   gboolean flush;
282   gboolean update;
283   GstSegment seeksegment = { 0, };
284   gint64 last_stop;
285
286   if (event) {
287     GST_DEBUG_OBJECT (aiff, "doing seek with event");
288
289     gst_event_parse_seek (event, &rate, &format, &flags,
290         &cur_type, &cur, &stop_type, &stop);
291
292     /* no negative rates yet */
293     if (rate < 0.0)
294       goto negative_rate;
295
296     if (format != aiff->segment.format) {
297       GST_INFO_OBJECT (aiff, "converting seek-event from %s to %s",
298           gst_format_get_name (format),
299           gst_format_get_name (aiff->segment.format));
300       res = TRUE;
301       if (cur_type != GST_SEEK_TYPE_NONE)
302         res =
303             gst_pad_query_convert (aiff->srcpad, format, cur,
304             &aiff->segment.format, &cur);
305       if (res && stop_type != GST_SEEK_TYPE_NONE)
306         res =
307             gst_pad_query_convert (aiff->srcpad, format, stop,
308             &aiff->segment.format, &stop);
309       if (!res)
310         goto no_format;
311
312       format = aiff->segment.format;
313     }
314   } else {
315     GST_DEBUG_OBJECT (aiff, "doing seek without event");
316     flags = 0;
317     rate = 1.0;
318     cur_type = GST_SEEK_TYPE_SET;
319     stop_type = GST_SEEK_TYPE_SET;
320   }
321
322   /* get flush flag */
323   flush = flags & GST_SEEK_FLAG_FLUSH;
324
325   /* now we need to make sure the streaming thread is stopped. We do this by
326    * either sending a FLUSH_START event downstream which will cause the
327    * streaming thread to stop with a WRONG_STATE.
328    * For a non-flushing seek we simply pause the task, which will happen as soon
329    * as it completes one iteration (and thus might block when the sink is
330    * blocking in preroll). */
331   if (flush) {
332     GST_DEBUG_OBJECT (aiff, "sending flush start");
333     gst_pad_push_event (aiff->srcpad, gst_event_new_flush_start ());
334   } else {
335     gst_pad_pause_task (aiff->sinkpad);
336   }
337
338   /* we should now be able to grab the streaming thread because we stopped it
339    * with the above flush/pause code */
340   GST_PAD_STREAM_LOCK (aiff->sinkpad);
341
342   /* save current position */
343   last_stop = aiff->segment.last_stop;
344
345   GST_DEBUG_OBJECT (aiff, "stopped streaming at %" G_GINT64_FORMAT, last_stop);
346
347   /* copy segment, we need this because we still need the old
348    * segment when we close the current segment. */
349   memcpy (&seeksegment, &aiff->segment, sizeof (GstSegment));
350
351   /* configure the seek parameters in the seeksegment. We will then have the
352    * right values in the segment to perform the seek */
353   if (event) {
354     GST_DEBUG_OBJECT (aiff, "configuring seek");
355     gst_segment_set_seek (&seeksegment, rate, format, flags,
356         cur_type, cur, stop_type, stop, &update);
357   }
358
359   /* figure out the last position we need to play. If it's configured (stop !=
360    * -1), use that, else we play until the total duration of the file */
361   if ((stop = seeksegment.stop) == -1)
362     stop = seeksegment.duration;
363
364   GST_DEBUG_OBJECT (aiff, "cur_type =%d", cur_type);
365   if ((cur_type != GST_SEEK_TYPE_NONE)) {
366     /* bring offset to bytes, if the bps is 0, we have the segment in BYTES and
367      * we can just copy the last_stop. If not, we use the bps to convert TIME to
368      * bytes. */
369     if (aiff->bps > 0)
370       aiff->offset =
371           gst_util_uint64_scale_ceil (seeksegment.last_stop,
372           (guint64) aiff->bps, GST_SECOND);
373     else
374       aiff->offset = seeksegment.last_stop;
375     GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
376     aiff->offset -= (aiff->offset % aiff->bytes_per_sample);
377     GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
378     aiff->offset += aiff->datastart;
379     GST_LOG_OBJECT (aiff, "offset=%" G_GUINT64_FORMAT, aiff->offset);
380   } else {
381     GST_LOG_OBJECT (aiff, "continue from offset=%" G_GUINT64_FORMAT,
382         aiff->offset);
383   }
384
385   if (stop_type != GST_SEEK_TYPE_NONE) {
386     if (aiff->bps > 0)
387       aiff->end_offset =
388           gst_util_uint64_scale_ceil (stop, (guint64) aiff->bps, GST_SECOND);
389     else
390       aiff->end_offset = stop;
391     GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
392     aiff->end_offset -= (aiff->end_offset % aiff->bytes_per_sample);
393     GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
394     aiff->end_offset += aiff->datastart;
395     GST_LOG_OBJECT (aiff, "end_offset=%" G_GUINT64_FORMAT, aiff->end_offset);
396   } else {
397     GST_LOG_OBJECT (aiff, "continue to end_offset=%" G_GUINT64_FORMAT,
398         aiff->end_offset);
399   }
400
401   /* make sure filesize is not exceeded due to rounding errors or so,
402    * same precaution as in _stream_headers */
403   bformat = GST_FORMAT_BYTES;
404   if (gst_pad_query_peer_duration (aiff->sinkpad, &bformat, &upstream_size))
405     aiff->end_offset = MIN (aiff->end_offset, upstream_size);
406
407   /* this is the range of bytes we will use for playback */
408   aiff->offset = MIN (aiff->offset, aiff->end_offset);
409   aiff->dataleft = aiff->end_offset - aiff->offset;
410
411   GST_DEBUG_OBJECT (aiff,
412       "seek: rate %lf, offset %" G_GUINT64_FORMAT ", end %" G_GUINT64_FORMAT
413       ", segment %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, rate, aiff->offset,
414       aiff->end_offset, GST_TIME_ARGS (seeksegment.start),
415       GST_TIME_ARGS (stop));
416
417   /* prepare for streaming again */
418   if (flush) {
419     /* if we sent a FLUSH_START, we now send a FLUSH_STOP */
420     GST_DEBUG_OBJECT (aiff, "sending flush stop");
421     gst_pad_push_event (aiff->srcpad, gst_event_new_flush_stop ());
422   } else if (aiff->segment_running) {
423     /* we are running the current segment and doing a non-flushing seek,
424      * close the segment first based on the previous last_stop. */
425     GST_DEBUG_OBJECT (aiff, "closing running segment %" G_GINT64_FORMAT
426         " to %" G_GINT64_FORMAT, aiff->segment.accum, aiff->segment.last_stop);
427
428     /* queue the segment for sending in the stream thread */
429     if (aiff->close_segment)
430       gst_event_unref (aiff->close_segment);
431     aiff->close_segment = gst_event_new_new_segment (TRUE,
432         aiff->segment.rate, aiff->segment.format,
433         aiff->segment.accum, aiff->segment.last_stop, aiff->segment.accum);
434
435     /* keep track of our last_stop */
436     seeksegment.accum = aiff->segment.last_stop;
437   }
438
439   /* now we did the seek and can activate the new segment values */
440   memcpy (&aiff->segment, &seeksegment, sizeof (GstSegment));
441
442   /* if we're doing a segment seek, post a SEGMENT_START message */
443   if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
444     gst_element_post_message (GST_ELEMENT_CAST (aiff),
445         gst_message_new_segment_start (GST_OBJECT_CAST (aiff),
446             aiff->segment.format, aiff->segment.last_stop));
447   }
448
449   /* now create the newsegment */
450   GST_DEBUG_OBJECT (aiff, "Creating newsegment from %" G_GINT64_FORMAT
451       " to %" G_GINT64_FORMAT, aiff->segment.last_stop, stop);
452
453   /* store the newsegment event so it can be sent from the streaming thread. */
454   if (aiff->start_segment)
455     gst_event_unref (aiff->start_segment);
456   aiff->start_segment =
457       gst_event_new_new_segment (FALSE, aiff->segment.rate,
458       aiff->segment.format, aiff->segment.last_stop, stop,
459       aiff->segment.last_stop);
460
461   /* mark discont if we are going to stream from another position. */
462   if (last_stop != aiff->segment.last_stop) {
463     GST_DEBUG_OBJECT (aiff, "mark DISCONT, we did a seek to another position");
464     aiff->discont = TRUE;
465   }
466
467   /* and start the streaming task again */
468   aiff->segment_running = TRUE;
469   if (!aiff->streaming) {
470     gst_pad_start_task (aiff->sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
471         aiff->sinkpad);
472   }
473
474   GST_PAD_STREAM_UNLOCK (aiff->sinkpad);
475
476   return TRUE;
477
478   /* ERRORS */
479 negative_rate:
480   {
481     GST_DEBUG_OBJECT (aiff, "negative playback rates are not supported yet.");
482     return FALSE;
483   }
484 no_format:
485   {
486     GST_DEBUG_OBJECT (aiff, "unsupported format given, seek aborted.");
487     return FALSE;
488   }
489 }
490
491 /*
492  * gst_aiff_parse_peek_chunk_info:
493  * @aiff AIFFparse object
494  * @tag holder for tag
495  * @size holder for tag size
496  *
497  * Peek next chunk info (tag and size)
498  *
499  * Returns: %TRUE when the chunk info (header) is available
500  */
501 static gboolean
502 gst_aiff_parse_peek_chunk_info (GstAiffParse * aiff, guint32 * tag,
503     guint32 * size)
504 {
505   const guint8 *data = NULL;
506
507   if (gst_adapter_available (aiff->adapter) < 8)
508     return FALSE;
509
510   data = gst_adapter_peek (aiff->adapter, 8);
511   *tag = GST_READ_UINT32_LE (data);
512   *size = GST_READ_UINT32_BE (data + 4);
513
514   GST_DEBUG ("Next chunk size is %d bytes, type %" GST_FOURCC_FORMAT, *size,
515       GST_FOURCC_ARGS (*tag));
516
517   return TRUE;
518 }
519
520 /*
521  * gst_aiff_parse_peek_chunk:
522  * @aiff AIFFparse object
523  * @tag holder for tag
524  * @size holder for tag size
525  *
526  * Peek enough data for one full chunk
527  *
528  * Returns: %TRUE when the full chunk is available
529  */
530 static gboolean
531 gst_aiff_parse_peek_chunk (GstAiffParse * aiff, guint32 * tag, guint32 * size)
532 {
533   guint32 peek_size = 0;
534   guint available;
535
536   if (!gst_aiff_parse_peek_chunk_info (aiff, tag, size))
537     return FALSE;
538
539   GST_DEBUG ("Need to peek chunk of %d bytes", *size);
540   peek_size = (*size + 1) & ~1;
541
542   available = gst_adapter_available (aiff->adapter);
543   if (available >= (8 + peek_size)) {
544     return TRUE;
545   } else {
546     GST_LOG ("but only %u bytes available now", available);
547     return FALSE;
548   }
549 }
550
551 static gboolean
552 gst_aiff_parse_peek_data (GstAiffParse * aiff, guint32 size,
553     const guint8 ** data)
554 {
555   if (gst_adapter_available (aiff->adapter) < size)
556     return FALSE;
557
558   *data = gst_adapter_peek (aiff->adapter, size);
559   return TRUE;
560 }
561
562 /*
563  * gst_aiff_parse_calculate_duration:
564  * @aiff: aiffparse object
565  *
566  * Calculate duration on demand and store in @aiff.
567  *
568  * Returns: %TRUE if duration is available.
569  */
570 static gboolean
571 gst_aiff_parse_calculate_duration (GstAiffParse * aiff)
572 {
573   if (aiff->duration > 0)
574     return TRUE;
575
576   if (aiff->datasize > 0 && aiff->bps > 0) {
577     aiff->duration =
578         gst_util_uint64_scale_ceil (aiff->datasize, GST_SECOND,
579         (guint64) aiff->bps);
580     GST_INFO_OBJECT (aiff, "Got duration %" GST_TIME_FORMAT,
581         GST_TIME_ARGS (aiff->duration));
582     return TRUE;
583   }
584   return FALSE;
585 }
586
587 static void
588 gst_aiff_parse_ignore_chunk (GstAiffParse * aiff, GstBuffer * buf, guint32 tag,
589     guint32 size)
590 {
591   guint flush;
592
593   if (aiff->streaming) {
594     if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
595       return;
596   }
597   GST_DEBUG_OBJECT (aiff, "Ignoring tag %" GST_FOURCC_FORMAT,
598       GST_FOURCC_ARGS (tag));
599   flush = 8 + ((size + 1) & ~1);
600   aiff->offset += flush;
601   if (aiff->streaming) {
602     gst_adapter_flush (aiff->adapter, flush);
603   } else {
604     gst_buffer_unref (buf);
605   }
606 }
607
608 static double
609 gst_aiff_parse_read_IEEE80 (guint8 * buf)
610 {
611   int s = buf[0] & 0xff;
612   int e = ((buf[0] & 0x7f) << 8) | (buf[1] & 0xff);
613   double f = ((unsigned long) (buf[2] & 0xff) << 24) |
614       ((buf[3] & 0xff) << 16) | ((buf[4] & 0xff) << 8) | (buf[5] & 0xff);
615
616   if (e == 32767) {
617     if (buf[2] & 0x80)
618       return HUGE_VAL;          /* Really NaN, but this won't happen in reality */
619     else {
620       if (s)
621         return -HUGE_VAL;
622       else
623         return HUGE_VAL;
624     }
625   }
626
627   f = ldexp (f, 32);
628   f += ((buf[6] & 0xff) << 24) |
629       ((buf[7] & 0xff) << 16) | ((buf[8] & 0xff) << 8) | (buf[9] & 0xff);
630
631   return ldexp (f, e - 16446);
632 }
633
634 static gboolean
635 gst_aiff_parse_parse_comm (GstAiffParse * aiff, GstBuffer * buf)
636 {
637   guint8 *data;
638   int size;
639
640   if (aiff->is_aifc)
641     size = 22;
642   else
643     size = 18;
644
645   if (GST_BUFFER_SIZE (buf) < size) {
646     GST_WARNING_OBJECT (aiff, "COMM chunk too short, cannot parse header");
647     return FALSE;
648   }
649
650   data = GST_BUFFER_DATA (buf);
651
652   aiff->channels = GST_READ_UINT16_BE (data);
653   aiff->total_frames = GST_READ_UINT32_BE (data + 2);
654   aiff->depth = GST_READ_UINT16_BE (data + 6);
655   aiff->width = GST_ROUND_UP_8 (aiff->depth);
656   aiff->rate = (int) gst_aiff_parse_read_IEEE80 (data + 8);
657
658   aiff->floating_point = FALSE;
659
660   if (aiff->is_aifc) {
661     guint32 fourcc = GST_READ_UINT32_LE (data + 18);
662
663     /* We only support the 'trivial' uncompressed AIFC, but it can be
664      * either big or little endian */
665     switch (fourcc) {
666       case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
667         aiff->endianness = G_BIG_ENDIAN;
668         break;
669       case GST_MAKE_FOURCC ('s', 'o', 'w', 't'):
670         aiff->endianness = G_LITTLE_ENDIAN;
671         break;
672       case GST_MAKE_FOURCC ('F', 'L', '3', '2'):
673       case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
674         aiff->floating_point = TRUE;
675         aiff->width = aiff->depth = 32;
676         aiff->endianness = G_BIG_ENDIAN;
677         break;
678       case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
679         aiff->floating_point = TRUE;
680         aiff->width = aiff->depth = 64;
681         aiff->endianness = G_BIG_ENDIAN;
682         break;
683       default:
684         GST_WARNING_OBJECT (aiff, "Unsupported compression in AIFC "
685             "file: %" GST_FOURCC_FORMAT,
686             GST_FOURCC_ARGS (GST_READ_UINT32_LE (data + 18)));
687         return FALSE;
688
689     }
690   } else
691     aiff->endianness = G_BIG_ENDIAN;
692
693   return TRUE;
694 }
695
696 static GstFlowReturn
697 gst_aiff_parse_read_chunk (GstAiffParse * aiff, guint64 * offset, guint32 * tag,
698     GstBuffer ** data)
699 {
700   guint size;
701   GstFlowReturn res;
702   GstBuffer *buf;
703
704   if ((res =
705           gst_pad_pull_range (aiff->sinkpad, *offset, 8, &buf)) != GST_FLOW_OK)
706     return res;
707
708   *tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
709   size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + 4);
710
711   if ((res =
712           gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
713               &buf)) != GST_FLOW_OK)
714     return res;
715   else if (GST_BUFFER_SIZE (buf) < size)
716     goto too_small;
717
718   *data = buf;
719   *offset += 8 + GST_ROUND_UP_2 (size);
720
721   return GST_FLOW_OK;
722
723   /* ERRORS */
724 too_small:
725   {
726     /* short read, we return UNEXPECTED to mark the EOS case */
727     GST_DEBUG_OBJECT (aiff, "not enough data (available=%u, needed=%u)",
728         GST_BUFFER_SIZE (buf), size);
729     gst_buffer_unref (buf);
730     return GST_FLOW_UNEXPECTED;
731   }
732
733 }
734
735 static GstCaps *
736 gst_aiff_parse_create_caps (GstAiffParse * aiff)
737 {
738   GstCaps *caps;
739
740   if (aiff->floating_point) {
741     caps = gst_caps_new_simple ("audio/x-raw-float",
742         "width", G_TYPE_INT, aiff->width,
743         "channels", G_TYPE_INT, aiff->channels,
744         "endianness", G_TYPE_INT, aiff->endianness,
745         "rate", G_TYPE_INT, aiff->rate, NULL);
746   } else {
747     caps = gst_caps_new_simple ("audio/x-raw-int",
748         "width", G_TYPE_INT, aiff->width,
749         "depth", G_TYPE_INT, aiff->depth,
750         "channels", G_TYPE_INT, aiff->channels,
751         "endianness", G_TYPE_INT, aiff->endianness,
752         "rate", G_TYPE_INT, aiff->rate, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
753   }
754
755   GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
756   return caps;
757 }
758
759 static GstFlowReturn
760 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
761 {
762   GstFlowReturn res;
763   GstBuffer *buf;
764   guint32 tag, size;
765   gboolean gotdata = FALSE;
766   gboolean done = FALSE;
767   GstEvent **event_p;
768   GstFormat bformat;
769   gint64 upstream_size = 0;
770
771   bformat = GST_FORMAT_BYTES;
772   gst_pad_query_peer_duration (aiff->sinkpad, &bformat, &upstream_size);
773   GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
774
775   /* loop headers until we get data */
776   while (!done) {
777     if (aiff->streaming) {
778       if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
779         return GST_FLOW_OK;
780     } else {
781       if ((res =
782               gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
783                   &buf)) != GST_FLOW_OK)
784         goto header_read_error;
785       tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
786       size = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf) + 4);
787     }
788
789     GST_INFO_OBJECT (aiff,
790         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
791         GST_FOURCC_ARGS (tag), aiff->offset);
792
793     /* We just keep reading chunks until we find the one we're interested in.
794      */
795     switch (tag) {
796       case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
797         if (aiff->streaming) {
798           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
799             return GST_FLOW_OK;
800
801           gst_adapter_flush (aiff->adapter, 8);
802           aiff->offset += 8;
803
804           buf = gst_adapter_take_buffer (aiff->adapter, size);
805         } else {
806           if ((res = gst_aiff_parse_read_chunk (aiff,
807                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
808             return res;
809         }
810
811         if (!gst_aiff_parse_parse_comm (aiff, buf)) {
812           gst_buffer_unref (buf);
813           goto parse_header_error;
814         }
815
816         gst_buffer_unref (buf);
817
818         /* do sanity checks of header fields */
819         if (aiff->channels == 0)
820           goto no_channels;
821         if (aiff->rate == 0)
822           goto no_rate;
823
824         GST_DEBUG_OBJECT (aiff, "creating the caps");
825
826         aiff->caps = gst_aiff_parse_create_caps (aiff);
827         if (!aiff->caps)
828           goto unknown_format;
829
830         gst_pad_set_caps (aiff->srcpad, aiff->caps);
831
832         aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
833         aiff->bps = aiff->bytes_per_sample * aiff->rate;
834
835         if (aiff->bytes_per_sample <= 0)
836           goto no_bytes_per_sample;
837
838         aiff->got_comm = TRUE;
839         break;
840       }
841       case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
842         GstFormat fmt;
843         GstBuffer *ssndbuf = NULL;
844         const guint8 *ssnddata = NULL;
845         guint32 datasize;
846
847         GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
848
849         /* Now, read the 8-byte header in the SSND chunk */
850         if (aiff->streaming) {
851           if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
852             return GST_FLOW_OK;
853         } else {
854           gst_buffer_unref (buf);
855           if ((res =
856                   gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
857                       &ssndbuf)) != GST_FLOW_OK)
858             goto header_read_error;
859           ssnddata = GST_BUFFER_DATA (ssndbuf);
860         }
861
862         aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8);
863         aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12);
864
865         gotdata = TRUE;
866         if (aiff->streaming) {
867           gst_adapter_flush (aiff->adapter, 16);
868         } else {
869           gst_buffer_unref (ssndbuf);
870         }
871         /* 8 byte chunk header, 8 byte SSND header */
872         aiff->offset += 16;
873
874         datasize = size - 16;
875
876         aiff->datastart = aiff->offset + aiff->ssnd_offset;
877         /* file might be truncated */
878         fmt = GST_FORMAT_BYTES;
879         if (upstream_size) {
880           size = MIN (datasize, (upstream_size - aiff->datastart));
881         }
882         aiff->datasize = (guint64) datasize;
883         aiff->dataleft = (guint64) datasize;
884         aiff->end_offset = datasize + aiff->datastart;
885         if (!aiff->streaming) {
886           /* We will continue looking at chunks until the end - to read tags,
887            * etc. */
888           aiff->offset += datasize;
889         }
890         GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
891         if (aiff->streaming) {
892           done = TRUE;
893         }
894         break;
895       }
896       default:
897         gst_aiff_parse_ignore_chunk (aiff, buf, tag, size);
898     }
899
900     if (upstream_size && (aiff->offset >= upstream_size)) {
901       /* Now we have gone through the whole file */
902       done = TRUE;
903     }
904   }
905
906   /* We read all the chunks (in pull mode) or reached the SSND chunk
907    * (in push mode). We must have both COMM and SSND now; error out 
908    * otherwise.
909    */
910   if (!aiff->got_comm) {
911     GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
912     goto no_header;
913   }
914   if (!gotdata) {
915     GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
916     goto no_data;
917   }
918
919   GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
920
921   if (gst_aiff_parse_calculate_duration (aiff)) {
922     gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
923     gst_segment_set_duration (&aiff->segment, GST_FORMAT_TIME, aiff->duration);
924   } else {
925     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
926     gst_segment_init (&aiff->segment, GST_FORMAT_BYTES);
927     gst_segment_set_duration (&aiff->segment, GST_FORMAT_BYTES, aiff->datasize);
928   }
929
930   /* now we have all the info to perform a pending seek if any, if no
931    * event, this will still do the right thing and it will also send
932    * the right newsegment event downstream. */
933   gst_aiff_parse_perform_seek (aiff, aiff->seek_event);
934   /* remove pending event */
935   event_p = &aiff->seek_event;
936   gst_event_replace (event_p, NULL);
937
938   /* we just started, we are discont */
939   aiff->discont = TRUE;
940
941   aiff->state = AIFF_PARSE_DATA;
942
943   return GST_FLOW_OK;
944
945   /* ERROR */
946 no_header:
947   {
948     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
949         ("Invalid AIFF header (no COMM found)"));
950     return GST_FLOW_ERROR;
951   }
952 no_data:
953   {
954     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
955         ("Invalid AIFF: no SSND found"));
956     return GST_FLOW_ERROR;
957   }
958 parse_header_error:
959   {
960     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
961         ("Couldn't parse audio header"));
962     return GST_FLOW_ERROR;
963   }
964 no_channels:
965   {
966     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
967         ("Stream claims to contain no channels - invalid data"));
968     return GST_FLOW_ERROR;
969   }
970 no_rate:
971   {
972     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
973         ("Stream with sample_rate == 0 - invalid data"));
974     return GST_FLOW_ERROR;
975   }
976 no_bytes_per_sample:
977   {
978     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
979         ("Could not caluclate bytes per sample - invalid data"));
980     return GST_FLOW_ERROR;
981   }
982 unknown_format:
983   {
984     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
985         ("No caps found for format 0x%x, %d channels, %d Hz",
986             aiff->format, aiff->channels, aiff->rate));
987     return GST_FLOW_ERROR;
988   }
989 header_read_error:
990   {
991     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
992         ("Couldn't read in header"));
993     return GST_FLOW_ERROR;
994   }
995 }
996
997 /*
998  * Read AIFF file tag when streaming
999  */
1000 static GstFlowReturn
1001 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1002 {
1003   if (gst_adapter_available (aiff->adapter) >= 12) {
1004     GstBuffer *tmp;
1005
1006     /* _take flushes the data */
1007     tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1008
1009     GST_DEBUG ("Parsing aiff header");
1010     if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1011       return GST_FLOW_ERROR;
1012
1013     aiff->offset += 12;
1014     /* Go to next state */
1015     aiff->state = AIFF_PARSE_HEADER;
1016   }
1017   return GST_FLOW_OK;
1018 }
1019
1020 /* handle an event sent directly to the element.
1021  *
1022  * This event can be sent either in the READY state or the
1023  * >READY state. The only event of interest really is the seek
1024  * event.
1025  *
1026  * In the READY state we can only store the event and try to
1027  * respect it when going to PAUSED. We assume we are in the
1028  * READY state when our parsing state != AIFF_PARSE_DATA.
1029  *
1030  * When we are steaming, we can simply perform the seek right
1031  * away.
1032  */
1033 static gboolean
1034 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1035 {
1036   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1037   gboolean res = FALSE;
1038   GstEvent **event_p;
1039
1040   GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1041
1042   switch (GST_EVENT_TYPE (event)) {
1043     case GST_EVENT_SEEK:
1044       if (aiff->state == AIFF_PARSE_DATA) {
1045         /* we can handle the seek directly when streaming data */
1046         res = gst_aiff_parse_perform_seek (aiff, event);
1047       } else {
1048         GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1049
1050         event_p = &aiff->seek_event;
1051         gst_event_replace (event_p, event);
1052
1053         /* we always return true */
1054         res = TRUE;
1055       }
1056       break;
1057     default:
1058       break;
1059   }
1060   gst_event_unref (event);
1061   return res;
1062 }
1063
1064 #define MAX_BUFFER_SIZE 4096
1065
1066 static GstFlowReturn
1067 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1068 {
1069   GstBuffer *buf = NULL;
1070   GstFlowReturn res = GST_FLOW_OK;
1071   guint64 desired, obtained;
1072   GstClockTime timestamp, next_timestamp, duration;
1073   guint64 pos, nextpos;
1074
1075 iterate_adapter:
1076   GST_LOG_OBJECT (aiff,
1077       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1078       G_GINT64_FORMAT, aiff->offset, aiff->end_offset, aiff->dataleft);
1079
1080   /* Get the next n bytes and output them */
1081   if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1082     goto found_eos;
1083
1084   /* scale the amount of data by the segment rate so we get equal
1085    * amounts of data regardless of the playback rate */
1086   desired =
1087       MIN (gst_guint64_to_gdouble (aiff->dataleft),
1088       MAX_BUFFER_SIZE * aiff->segment.abs_rate);
1089
1090   if (desired >= aiff->bytes_per_sample && aiff->bytes_per_sample > 0)
1091     desired -= (desired % aiff->bytes_per_sample);
1092
1093   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1094       "from the sinkpad", desired);
1095
1096   if (aiff->streaming) {
1097     guint avail = gst_adapter_available (aiff->adapter);
1098
1099     if (avail < desired) {
1100       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1101           avail);
1102       return GST_FLOW_OK;
1103     }
1104
1105     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1106   } else {
1107     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1108                 desired, &buf)) != GST_FLOW_OK)
1109       goto pull_error;
1110   }
1111
1112   /* If we have a pending close/start segment, send it now. */
1113   if (G_UNLIKELY (aiff->close_segment != NULL)) {
1114     gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1115     aiff->close_segment = NULL;
1116   }
1117   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1118     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1119     aiff->start_segment = NULL;
1120   }
1121
1122   obtained = GST_BUFFER_SIZE (buf);
1123
1124   /* our positions in bytes */
1125   pos = aiff->offset - aiff->datastart;
1126   nextpos = pos + obtained;
1127
1128   /* update offsets, does not overflow. */
1129   GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1130   GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1131
1132   if (aiff->bps > 0) {
1133     /* and timestamps if we have a bitrate, be careful for overflows */
1134     timestamp =
1135         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1136     next_timestamp =
1137         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1138     duration = next_timestamp - timestamp;
1139
1140     /* update current running segment position */
1141     gst_segment_set_last_stop (&aiff->segment, GST_FORMAT_TIME, next_timestamp);
1142   } else {
1143     /* no bitrate, all we know is that the first sample has timestamp 0, all
1144      * other positions and durations have unknown timestamp. */
1145     if (pos == 0)
1146       timestamp = 0;
1147     else
1148       timestamp = GST_CLOCK_TIME_NONE;
1149     duration = GST_CLOCK_TIME_NONE;
1150     /* update current running segment position with byte offset */
1151     gst_segment_set_last_stop (&aiff->segment, GST_FORMAT_BYTES, nextpos);
1152   }
1153   if (aiff->discont) {
1154     GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1155     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1156     aiff->discont = FALSE;
1157   }
1158
1159   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1160   GST_BUFFER_DURATION (buf) = duration;
1161   gst_buffer_set_caps (buf, aiff->caps);
1162
1163   GST_LOG_OBJECT (aiff,
1164       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1165       ", size:%u", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration),
1166       GST_BUFFER_SIZE (buf));
1167
1168   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1169     goto push_error;
1170
1171   if (obtained < aiff->dataleft) {
1172     aiff->offset += obtained;
1173     aiff->dataleft -= obtained;
1174   } else {
1175     aiff->offset += aiff->dataleft;
1176     aiff->dataleft = 0;
1177   }
1178
1179   /* Iterate until need more data, so adapter size won't grow */
1180   if (aiff->streaming) {
1181     GST_LOG_OBJECT (aiff,
1182         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1183         aiff->end_offset);
1184     goto iterate_adapter;
1185   }
1186   return res;
1187
1188   /* ERROR */
1189 found_eos:
1190   {
1191     GST_DEBUG_OBJECT (aiff, "found EOS");
1192     return GST_FLOW_UNEXPECTED;
1193   }
1194 pull_error:
1195   {
1196     /* check if we got EOS */
1197     if (res == GST_FLOW_UNEXPECTED)
1198       goto found_eos;
1199
1200     GST_WARNING_OBJECT (aiff,
1201         "Error getting %" G_GINT64_FORMAT " bytes from the "
1202         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1203     return res;
1204   }
1205 push_error:
1206   {
1207     GST_INFO_OBJECT (aiff,
1208         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1209         GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1210         gst_pad_is_linked (aiff->srcpad));
1211     return res;
1212   }
1213 }
1214
1215 static void
1216 gst_aiff_parse_loop (GstPad * pad)
1217 {
1218   GstFlowReturn ret;
1219   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1220
1221   GST_LOG_OBJECT (aiff, "process data");
1222
1223   switch (aiff->state) {
1224     case AIFF_PARSE_START:
1225       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1226       if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1227         goto pause;
1228
1229       aiff->state = AIFF_PARSE_HEADER;
1230       /* fall-through */
1231
1232     case AIFF_PARSE_HEADER:
1233       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1234       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1235         goto pause;
1236
1237       aiff->state = AIFF_PARSE_DATA;
1238       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1239       /* fall-through */
1240
1241     case AIFF_PARSE_DATA:
1242       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1243         goto pause;
1244       break;
1245     default:
1246       g_assert_not_reached ();
1247   }
1248   return;
1249
1250   /* ERRORS */
1251 pause:
1252   {
1253     const gchar *reason = gst_flow_get_name (ret);
1254
1255     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1256     aiff->segment_running = FALSE;
1257     gst_pad_pause_task (pad);
1258
1259     if (ret == GST_FLOW_UNEXPECTED) {
1260       /* perform EOS logic */
1261       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1262         GstClockTime stop;
1263
1264         if ((stop = aiff->segment.stop) == -1)
1265           stop = aiff->segment.duration;
1266
1267         gst_element_post_message (GST_ELEMENT_CAST (aiff),
1268             gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1269                 aiff->segment.format, stop));
1270       } else {
1271         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1272       }
1273     } else if (ret < GST_FLOW_UNEXPECTED || ret == GST_FLOW_NOT_LINKED) {
1274       /* for fatal errors we post an error message, post the error
1275        * first so the app knows about the error first. */
1276       GST_ELEMENT_ERROR (aiff, STREAM, FAILED,
1277           (_("Internal data flow error.")),
1278           ("streaming task paused, reason %s (%d)", reason, ret));
1279       gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1280     }
1281     return;
1282   }
1283 }
1284
1285 static GstFlowReturn
1286 gst_aiff_parse_chain (GstPad * pad, GstBuffer * buf)
1287 {
1288   GstFlowReturn ret;
1289   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1290
1291   GST_LOG_OBJECT (aiff, "adapter_push %u bytes", GST_BUFFER_SIZE (buf));
1292
1293   gst_adapter_push (aiff->adapter, buf);
1294
1295   switch (aiff->state) {
1296     case AIFF_PARSE_START:
1297       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1298       if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1299         goto done;
1300
1301       if (aiff->state != AIFF_PARSE_HEADER)
1302         break;
1303
1304       /* otherwise fall-through */
1305     case AIFF_PARSE_HEADER:
1306       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1307       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1308         goto done;
1309
1310       if (!aiff->got_comm || aiff->datastart == 0)
1311         break;
1312
1313       aiff->state = AIFF_PARSE_DATA;
1314       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1315
1316       /* fall-through */
1317     case AIFF_PARSE_DATA:
1318       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1319         goto done;
1320       break;
1321     default:
1322       g_return_val_if_reached (GST_FLOW_ERROR);
1323   }
1324 done:
1325   return ret;
1326 }
1327
1328 static gboolean
1329 gst_aiff_parse_pad_convert (GstPad * pad,
1330     GstFormat src_format, gint64 src_value,
1331     GstFormat * dest_format, gint64 * dest_value)
1332 {
1333   GstAiffParse *aiffparse;
1334   gboolean res = TRUE;
1335
1336   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1337
1338   if (*dest_format == src_format) {
1339     *dest_value = src_value;
1340     return TRUE;
1341   }
1342
1343   if (aiffparse->bytes_per_sample <= 0)
1344     return FALSE;
1345
1346   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1347       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1348
1349   switch (src_format) {
1350     case GST_FORMAT_BYTES:
1351       switch (*dest_format) {
1352         case GST_FORMAT_DEFAULT:
1353           *dest_value = src_value / aiffparse->bytes_per_sample;
1354           break;
1355         case GST_FORMAT_TIME:
1356           if (aiffparse->bps > 0) {
1357             *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1358                 (guint64) aiffparse->bps);
1359             break;
1360           }
1361           /* Else fallthrough */
1362         default:
1363           res = FALSE;
1364           goto done;
1365       }
1366       break;
1367
1368     case GST_FORMAT_DEFAULT:
1369       switch (*dest_format) {
1370         case GST_FORMAT_BYTES:
1371           *dest_value = src_value * aiffparse->bytes_per_sample;
1372           break;
1373         case GST_FORMAT_TIME:
1374           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1375               (guint64) aiffparse->rate);
1376           break;
1377         default:
1378           res = FALSE;
1379           goto done;
1380       }
1381       break;
1382
1383     case GST_FORMAT_TIME:
1384       switch (*dest_format) {
1385         case GST_FORMAT_BYTES:
1386           if (aiffparse->bps > 0) {
1387             *dest_value = gst_util_uint64_scale (src_value,
1388                 (guint64) aiffparse->bps, GST_SECOND);
1389             break;
1390           }
1391           /* Else fallthrough */
1392           break;
1393         case GST_FORMAT_DEFAULT:
1394           *dest_value = gst_util_uint64_scale (src_value,
1395               (guint64) aiffparse->rate, GST_SECOND);
1396           break;
1397         default:
1398           res = FALSE;
1399           goto done;
1400       }
1401       break;
1402
1403     default:
1404       res = FALSE;
1405       goto done;
1406   }
1407
1408 done:
1409   return res;
1410
1411 }
1412
1413 static const GstQueryType *
1414 gst_aiff_parse_get_query_types (GstPad * pad)
1415 {
1416   static const GstQueryType types[] = {
1417     GST_QUERY_DURATION,
1418     GST_QUERY_CONVERT,
1419     GST_QUERY_SEEKING,
1420     0
1421   };
1422
1423   return types;
1424 }
1425
1426 /* handle queries for location and length in requested format */
1427 static gboolean
1428 gst_aiff_parse_pad_query (GstPad * pad, GstQuery * query)
1429 {
1430   gboolean res = TRUE;
1431   GstAiffParse *aiff = GST_AIFF_PARSE (gst_pad_get_parent (pad));
1432
1433   /* only if we know */
1434   if (aiff->state != AIFF_PARSE_DATA) {
1435     gst_object_unref (aiff);
1436     return FALSE;
1437   }
1438
1439   switch (GST_QUERY_TYPE (query)) {
1440     case GST_QUERY_DURATION:
1441     {
1442       gint64 duration = 0;
1443       GstFormat format;
1444
1445       gst_query_parse_duration (query, &format, NULL);
1446
1447       switch (format) {
1448         case GST_FORMAT_TIME:{
1449           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1450             duration = aiff->duration;
1451           }
1452           break;
1453         }
1454         default:
1455           format = GST_FORMAT_BYTES;
1456           duration = aiff->datasize;
1457           break;
1458       }
1459       gst_query_set_duration (query, format, duration);
1460       break;
1461     }
1462     case GST_QUERY_CONVERT:
1463     {
1464       gint64 srcvalue, dstvalue;
1465       GstFormat srcformat, dstformat;
1466
1467       gst_query_parse_convert (query, &srcformat, &srcvalue,
1468           &dstformat, &dstvalue);
1469       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1470           &dstformat, &dstvalue);
1471       if (res)
1472         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1473       break;
1474     }
1475     case GST_QUERY_SEEKING:{
1476       GstFormat fmt;
1477
1478       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1479       if (fmt == GST_FORMAT_TIME) {
1480         gboolean seekable = TRUE;
1481
1482         if (!gst_aiff_parse_calculate_duration (aiff)) {
1483           seekable = FALSE;
1484         }
1485         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1486             0, aiff->duration);
1487         res = TRUE;
1488       }
1489       break;
1490     }
1491     default:
1492       res = gst_pad_query_default (pad, query);
1493       break;
1494   }
1495   gst_object_unref (aiff);
1496   return res;
1497 }
1498
1499 static gboolean
1500 gst_aiff_parse_srcpad_event (GstPad * pad, GstEvent * event)
1501 {
1502   GstAiffParse *aiffparse = GST_AIFF_PARSE (gst_pad_get_parent (pad));
1503   gboolean res = FALSE;
1504
1505   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1506
1507   switch (GST_EVENT_TYPE (event)) {
1508     case GST_EVENT_SEEK:
1509       /* can only handle events when we are in the data state */
1510       if (aiffparse->state == AIFF_PARSE_DATA) {
1511         res = gst_aiff_parse_perform_seek (aiffparse, event);
1512       }
1513       gst_event_unref (event);
1514       break;
1515     default:
1516       res = gst_pad_push_event (aiffparse->sinkpad, event);
1517       break;
1518   }
1519   gst_object_unref (aiffparse);
1520   return res;
1521 }
1522
1523 static gboolean
1524 gst_aiff_parse_sink_activate (GstPad * sinkpad)
1525 {
1526   GstAiffParse *aiff = GST_AIFF_PARSE (gst_pad_get_parent (sinkpad));
1527   gboolean res;
1528
1529   if (aiff->adapter)
1530     g_object_unref (aiff->adapter);
1531
1532   if (gst_pad_check_pull_range (sinkpad)) {
1533     GST_DEBUG ("going to pull mode");
1534     aiff->streaming = FALSE;
1535     aiff->adapter = NULL;
1536     res = gst_pad_activate_pull (sinkpad, TRUE);
1537   } else {
1538     GST_DEBUG ("going to push (streaming) mode");
1539     aiff->streaming = TRUE;
1540     aiff->adapter = gst_adapter_new ();
1541     res = gst_pad_activate_push (sinkpad, TRUE);
1542   }
1543   gst_object_unref (aiff);
1544   return res;
1545 }
1546
1547
1548 static gboolean
1549 gst_aiff_parse_sink_activate_pull (GstPad * sinkpad, gboolean active)
1550 {
1551   GstAiffParse *aiff = GST_AIFF_PARSE (GST_OBJECT_PARENT (sinkpad));
1552
1553   if (active) {
1554     aiff->segment_running = TRUE;
1555     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1556         sinkpad);
1557   } else {
1558     aiff->segment_running = FALSE;
1559     return gst_pad_stop_task (sinkpad);
1560   }
1561 };
1562
1563 static GstStateChangeReturn
1564 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1565 {
1566   GstStateChangeReturn ret;
1567   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1568
1569   switch (transition) {
1570     case GST_STATE_CHANGE_NULL_TO_READY:
1571       break;
1572     case GST_STATE_CHANGE_READY_TO_PAUSED:
1573       gst_aiff_parse_reset (aiff);
1574       break;
1575     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1576       break;
1577     default:
1578       break;
1579   }
1580
1581   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1582
1583   switch (transition) {
1584     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1585       break;
1586     case GST_STATE_CHANGE_PAUSED_TO_READY:
1587       gst_aiff_parse_reset (aiff);
1588       break;
1589     case GST_STATE_CHANGE_READY_TO_NULL:
1590       break;
1591     default:
1592       break;
1593   }
1594   return ret;
1595 }