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