aiff: port to 1.0
[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;
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
724   if ((res =
725           gst_pad_pull_range (aiff->sinkpad, (*offset) + 8, size,
726               &buf)) != GST_FLOW_OK)
727     return res;
728   else if (gst_buffer_get_size (buf) < size)
729     goto too_small;
730
731   *data = buf;
732   *offset += 8 + GST_ROUND_UP_2 (size);
733
734   return GST_FLOW_OK;
735
736   /* ERRORS */
737 too_small:
738   {
739     /* short read, we return EOS to mark the EOS case */
740     GST_DEBUG_OBJECT (aiff,
741         "not enough data (available=%" G_GSIZE_FORMAT ", needed=%u)",
742         gst_buffer_get_size (buf), size);
743     gst_buffer_unref (buf);
744     return GST_FLOW_EOS;
745   }
746
747 }
748
749 static GstCaps *
750 gst_aiff_parse_create_caps (GstAiffParse * aiff)
751 {
752   GstCaps *caps = NULL;
753   const gchar *format = NULL;
754
755   if (aiff->floating_point) {
756     if (aiff->endianness == G_BIG_ENDIAN) {
757       if (aiff->width == 32)
758         format = "F32BE";
759       else if (aiff->width == 32)
760         format = "F64BE";
761     }
762   } else {
763     if (aiff->endianness == G_BIG_ENDIAN) {
764       if (aiff->width == 8)
765         format = "S8";
766       else if (aiff->width == 16)
767         format = "S16BE";
768       else if (aiff->width == 24)
769         format = "S24BE";
770       else if (aiff->width == 32)
771         format = "S32BE";
772     } else {
773       if (aiff->width == 8)
774         format = "S8";
775       else if (aiff->width == 16)
776         format = "S16LE";
777       else if (aiff->width == 24)
778         format = "S24LE";
779       else if (aiff->width == 32)
780         format = "S32LE";
781     }
782   }
783   if (format) {
784     caps = gst_caps_new_simple ("audio/x-raw",
785         "format", G_TYPE_STRING, format,
786         "channels", G_TYPE_INT, aiff->channels,
787         "rate", G_TYPE_INT, aiff->rate, NULL);
788   }
789
790   GST_DEBUG_OBJECT (aiff, "Created caps: %" GST_PTR_FORMAT, caps);
791
792   return caps;
793 }
794
795 static GstFlowReturn
796 gst_aiff_parse_stream_headers (GstAiffParse * aiff)
797 {
798   GstFlowReturn res;
799   GstBuffer *buf;
800   guint32 tag, size;
801   gboolean gotdata = FALSE;
802   gboolean done = FALSE;
803   GstEvent **event_p;
804   gint64 upstream_size = 0;
805
806   gst_pad_peer_query_duration (aiff->sinkpad, GST_FORMAT_BYTES, &upstream_size);
807   GST_DEBUG_OBJECT (aiff, "upstream size %" G_GUINT64_FORMAT, upstream_size);
808
809   /* loop headers until we get data */
810   while (!done) {
811     if (aiff->streaming) {
812       if (!gst_aiff_parse_peek_chunk_info (aiff, &tag, &size))
813         return GST_FLOW_OK;
814     } else {
815       GstMapInfo info;
816
817       if ((res =
818               gst_pad_pull_range (aiff->sinkpad, aiff->offset, 8,
819                   &buf)) != GST_FLOW_OK)
820         goto header_read_error;
821
822       gst_buffer_map (buf, &info, GST_MAP_READ);
823       tag = GST_READ_UINT32_LE (info.data);
824       size = GST_READ_UINT32_BE (info.data + 4);
825       gst_buffer_unmap (buf, &info);
826     }
827
828     GST_INFO_OBJECT (aiff,
829         "Got TAG: %" GST_FOURCC_FORMAT ", offset %" G_GUINT64_FORMAT,
830         GST_FOURCC_ARGS (tag), aiff->offset);
831
832     /* We just keep reading chunks until we find the one we're interested in.
833      */
834     switch (tag) {
835       case GST_MAKE_FOURCC ('C', 'O', 'M', 'M'):{
836         GstCaps *caps;
837
838         if (aiff->streaming) {
839           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
840             return GST_FLOW_OK;
841
842           gst_adapter_flush (aiff->adapter, 8);
843           aiff->offset += 8;
844
845           buf = gst_adapter_take_buffer (aiff->adapter, size);
846         } else {
847           if ((res = gst_aiff_parse_read_chunk (aiff,
848                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
849             return res;
850         }
851
852         if (!gst_aiff_parse_parse_comm (aiff, buf))
853           goto parse_header_error;
854
855         /* do sanity checks of header fields */
856         if (aiff->channels == 0)
857           goto no_channels;
858         if (aiff->rate == 0)
859           goto no_rate;
860
861         GST_DEBUG_OBJECT (aiff, "creating the caps");
862
863         caps = gst_aiff_parse_create_caps (aiff);
864         if (caps == NULL)
865           goto unknown_format;
866
867         gst_pad_push_event (aiff->srcpad, gst_event_new_caps (caps));
868         gst_caps_unref (caps);
869
870         aiff->bytes_per_sample = aiff->channels * aiff->width / 8;
871         aiff->bps = aiff->bytes_per_sample * aiff->rate;
872
873         if (aiff->bytes_per_sample <= 0)
874           goto no_bytes_per_sample;
875
876         aiff->got_comm = TRUE;
877         break;
878       }
879       case GST_MAKE_FOURCC ('S', 'S', 'N', 'D'):{
880         guint32 datasize;
881
882         GST_DEBUG_OBJECT (aiff, "Got 'SSND' TAG, size : %d", size);
883
884         /* Now, read the 8-byte header in the SSND chunk */
885         if (aiff->streaming) {
886           const guint8 *ssnddata = NULL;
887
888           if (!gst_aiff_parse_peek_data (aiff, 16, &ssnddata))
889             return GST_FLOW_OK;
890
891           aiff->ssnd_offset = GST_READ_UINT32_BE (ssnddata + 8);
892           aiff->ssnd_blocksize = GST_READ_UINT32_BE (ssnddata + 12);
893           gst_adapter_unmap (aiff->adapter);
894           gst_adapter_flush (aiff->adapter, 16);
895         } else {
896           GstBuffer *ssndbuf = NULL;
897           GstMapInfo info;
898
899           gst_buffer_unref (buf);
900           if ((res =
901                   gst_pad_pull_range (aiff->sinkpad, aiff->offset, 16,
902                       &ssndbuf)) != GST_FLOW_OK)
903             goto header_read_error;
904
905           gst_buffer_map (ssndbuf, &info, GST_MAP_READ);
906           aiff->ssnd_offset = GST_READ_UINT32_BE (info.data + 8);
907           aiff->ssnd_blocksize = GST_READ_UINT32_BE (info.data + 12);
908           gst_buffer_unmap (ssndbuf, &info);
909           gst_buffer_unref (ssndbuf);
910         }
911
912         gotdata = TRUE;
913
914         /* 8 byte chunk header, 8 byte SSND header */
915         aiff->offset += 16;
916         datasize = size - 16;
917
918         aiff->datastart = aiff->offset + aiff->ssnd_offset;
919         /* file might be truncated */
920         if (upstream_size) {
921           size = MIN (datasize, (upstream_size - aiff->datastart));
922         }
923         aiff->datasize = (guint64) datasize;
924         aiff->dataleft = (guint64) datasize;
925         aiff->end_offset = datasize + aiff->datastart;
926         if (!aiff->streaming) {
927           /* We will continue looking at chunks until the end - to read tags,
928            * etc. */
929           aiff->offset += datasize;
930         }
931         GST_DEBUG_OBJECT (aiff, "datasize = %d", datasize);
932         if (aiff->streaming) {
933           done = TRUE;
934         }
935         break;
936       }
937       case GST_MAKE_FOURCC ('I', 'D', '3', ' '):{
938         GstTagList *tags;
939
940         if (aiff->streaming) {
941           if (!gst_aiff_parse_peek_chunk (aiff, &tag, &size))
942             return GST_FLOW_OK;
943
944           gst_adapter_flush (aiff->adapter, 8);
945           aiff->offset += 8;
946
947           buf = gst_adapter_take_buffer (aiff->adapter, size);
948         } else {
949           if ((res = gst_aiff_parse_read_chunk (aiff,
950                       &aiff->offset, &tag, &buf)) != GST_FLOW_OK)
951             return res;
952         }
953
954         GST_LOG_OBJECT (aiff, "ID3 chunk of size %" G_GSIZE_FORMAT,
955             gst_buffer_get_size (buf));
956
957         tags = gst_tag_list_from_id3v2_tag (buf);
958         gst_buffer_unref (buf);
959
960         GST_INFO_OBJECT (aiff, "ID3 tags: %" GST_PTR_FORMAT, tags);
961
962         if (aiff->tags == NULL) {
963           aiff->tags = tags;
964         } else {
965           gst_tag_list_insert (aiff->tags, tags, GST_TAG_MERGE_APPEND);
966           gst_tag_list_unref (tags);
967         }
968         break;
969       }
970       default:
971         gst_aiff_parse_ignore_chunk (aiff, buf, tag, size);
972     }
973
974     if (upstream_size && (aiff->offset >= upstream_size)) {
975       /* Now we have gone through the whole file */
976       done = TRUE;
977     }
978   }
979
980   /* We read all the chunks (in pull mode) or reached the SSND chunk
981    * (in push mode). We must have both COMM and SSND now; error out 
982    * otherwise.
983    */
984   if (!aiff->got_comm) {
985     GST_WARNING_OBJECT (aiff, "Failed to find COMM chunk");
986     goto no_header;
987   }
988   if (!gotdata) {
989     GST_WARNING_OBJECT (aiff, "Failed to find SSND chunk");
990     goto no_data;
991   }
992
993   GST_DEBUG_OBJECT (aiff, "Finished parsing headers");
994
995   if (gst_aiff_parse_calculate_duration (aiff)) {
996     gst_segment_init (&aiff->segment, GST_FORMAT_TIME);
997     aiff->segment.duration = aiff->duration;
998   } else {
999     /* no bitrate, let downstream peer do the math, we'll feed it bytes. */
1000     gst_segment_init (&aiff->segment, GST_FORMAT_BYTES);
1001     aiff->segment.duration = aiff->datasize;
1002   }
1003
1004   /* now we have all the info to perform a pending seek if any, if no
1005    * event, this will still do the right thing and it will also send
1006    * the right newsegment event downstream. */
1007   gst_aiff_parse_perform_seek (aiff, aiff->seek_event);
1008   /* remove pending event */
1009   event_p = &aiff->seek_event;
1010   gst_event_replace (event_p, NULL);
1011
1012   /* we just started, we are discont */
1013   aiff->discont = TRUE;
1014
1015   aiff->state = AIFF_PARSE_DATA;
1016
1017   return GST_FLOW_OK;
1018
1019   /* ERROR */
1020 no_header:
1021   {
1022     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1023         ("Invalid AIFF header (no COMM found)"));
1024     return GST_FLOW_ERROR;
1025   }
1026 no_data:
1027   {
1028     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1029         ("Invalid AIFF: no SSND found"));
1030     return GST_FLOW_ERROR;
1031   }
1032 parse_header_error:
1033   {
1034     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1035         ("Couldn't parse audio header"));
1036     return GST_FLOW_ERROR;
1037   }
1038 no_channels:
1039   {
1040     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1041         ("Stream claims to contain no channels - invalid data"));
1042     return GST_FLOW_ERROR;
1043   }
1044 no_rate:
1045   {
1046     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1047         ("Stream with sample_rate == 0 - invalid data"));
1048     return GST_FLOW_ERROR;
1049   }
1050 no_bytes_per_sample:
1051   {
1052     GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (NULL),
1053         ("Could not caluclate bytes per sample - invalid data"));
1054     return GST_FLOW_ERROR;
1055   }
1056 unknown_format:
1057   {
1058     GST_ELEMENT_ERROR (aiff, STREAM, TYPE_NOT_FOUND, (NULL),
1059         ("No caps found for format 0x%x, %d channels, %d Hz",
1060             aiff->format, aiff->channels, aiff->rate));
1061     return GST_FLOW_ERROR;
1062   }
1063 header_read_error:
1064   {
1065     GST_ELEMENT_ERROR (aiff, STREAM, DEMUX, (NULL),
1066         ("Couldn't read in header"));
1067     return GST_FLOW_ERROR;
1068   }
1069 }
1070
1071 /*
1072  * Read AIFF file tag when streaming
1073  */
1074 static GstFlowReturn
1075 gst_aiff_parse_parse_stream_init (GstAiffParse * aiff)
1076 {
1077   if (gst_adapter_available (aiff->adapter) >= 12) {
1078     GstBuffer *tmp;
1079
1080     /* _take flushes the data */
1081     tmp = gst_adapter_take_buffer (aiff->adapter, 12);
1082
1083     GST_DEBUG ("Parsing aiff header");
1084     if (!gst_aiff_parse_parse_file_header (aiff, tmp))
1085       return GST_FLOW_ERROR;
1086
1087     aiff->offset += 12;
1088     /* Go to next state */
1089     aiff->state = AIFF_PARSE_HEADER;
1090   }
1091   return GST_FLOW_OK;
1092 }
1093
1094 /* handle an event sent directly to the element.
1095  *
1096  * This event can be sent either in the READY state or the
1097  * >READY state. The only event of interest really is the seek
1098  * event.
1099  *
1100  * In the READY state we can only store the event and try to
1101  * respect it when going to PAUSED. We assume we are in the
1102  * READY state when our parsing state != AIFF_PARSE_DATA.
1103  *
1104  * When we are steaming, we can simply perform the seek right
1105  * away.
1106  */
1107 static gboolean
1108 gst_aiff_parse_send_event (GstElement * element, GstEvent * event)
1109 {
1110   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1111   gboolean res = FALSE;
1112   GstEvent **event_p;
1113
1114   GST_DEBUG_OBJECT (aiff, "received event %s", GST_EVENT_TYPE_NAME (event));
1115
1116   switch (GST_EVENT_TYPE (event)) {
1117     case GST_EVENT_SEEK:
1118       if (aiff->state == AIFF_PARSE_DATA) {
1119         /* we can handle the seek directly when streaming data */
1120         res = gst_aiff_parse_perform_seek (aiff, event);
1121       } else {
1122         GST_DEBUG_OBJECT (aiff, "queuing seek for later");
1123
1124         event_p = &aiff->seek_event;
1125         gst_event_replace (event_p, event);
1126
1127         /* we always return true */
1128         res = TRUE;
1129       }
1130       break;
1131     default:
1132       break;
1133   }
1134   gst_event_unref (event);
1135   return res;
1136 }
1137
1138 #define MAX_BUFFER_SIZE 4096
1139
1140 static GstFlowReturn
1141 gst_aiff_parse_stream_data (GstAiffParse * aiff)
1142 {
1143   GstBuffer *buf = NULL;
1144   GstFlowReturn res = GST_FLOW_OK;
1145   guint64 desired, obtained;
1146   GstClockTime timestamp, next_timestamp, duration;
1147   guint64 pos, nextpos;
1148
1149 iterate_adapter:
1150   GST_LOG_OBJECT (aiff,
1151       "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
1152       G_GINT64_FORMAT, aiff->offset, aiff->end_offset, aiff->dataleft);
1153
1154   /* Get the next n bytes and output them */
1155   if (aiff->dataleft == 0 || aiff->dataleft < aiff->bytes_per_sample)
1156     goto found_eos;
1157
1158   /* scale the amount of data by the segment rate so we get equal
1159    * amounts of data regardless of the playback rate */
1160   desired =
1161       MIN (gst_guint64_to_gdouble (aiff->dataleft),
1162       MAX_BUFFER_SIZE * ABS (aiff->segment.rate));
1163
1164   if (desired >= aiff->bytes_per_sample && aiff->bytes_per_sample > 0)
1165     desired -= (desired % aiff->bytes_per_sample);
1166
1167   GST_LOG_OBJECT (aiff, "Fetching %" G_GINT64_FORMAT " bytes of data "
1168       "from the sinkpad", desired);
1169
1170   if (aiff->streaming) {
1171     guint avail = gst_adapter_available (aiff->adapter);
1172
1173     if (avail < desired) {
1174       GST_LOG_OBJECT (aiff, "Got only %d bytes of data from the sinkpad",
1175           avail);
1176       return GST_FLOW_OK;
1177     }
1178
1179     buf = gst_adapter_take_buffer (aiff->adapter, desired);
1180   } else {
1181     if ((res = gst_pad_pull_range (aiff->sinkpad, aiff->offset,
1182                 desired, &buf)) != GST_FLOW_OK)
1183       goto pull_error;
1184   }
1185
1186   /* If we have a pending close/start segment, send it now. */
1187   if (G_UNLIKELY (aiff->close_segment != NULL)) {
1188     gst_pad_push_event (aiff->srcpad, aiff->close_segment);
1189     aiff->close_segment = NULL;
1190   }
1191   if (G_UNLIKELY (aiff->start_segment != NULL)) {
1192     gst_pad_push_event (aiff->srcpad, aiff->start_segment);
1193     aiff->start_segment = NULL;
1194   }
1195   if (G_UNLIKELY (aiff->tags != NULL)) {
1196     gst_pad_push_event (aiff->srcpad, gst_event_new_tag (aiff->tags));
1197     aiff->tags = NULL;
1198   }
1199
1200   obtained = gst_buffer_get_size (buf);
1201
1202   /* our positions in bytes */
1203   pos = aiff->offset - aiff->datastart;
1204   nextpos = pos + obtained;
1205
1206   /* update offsets, does not overflow. */
1207   GST_BUFFER_OFFSET (buf) = pos / aiff->bytes_per_sample;
1208   GST_BUFFER_OFFSET_END (buf) = nextpos / aiff->bytes_per_sample;
1209
1210   if (aiff->bps > 0) {
1211     /* and timestamps if we have a bitrate, be careful for overflows */
1212     timestamp =
1213         gst_util_uint64_scale_ceil (pos, GST_SECOND, (guint64) aiff->bps);
1214     next_timestamp =
1215         gst_util_uint64_scale_ceil (nextpos, GST_SECOND, (guint64) aiff->bps);
1216     duration = next_timestamp - timestamp;
1217
1218     /* update current running segment position */
1219     aiff->segment.position = next_timestamp;
1220   } else {
1221     /* no bitrate, all we know is that the first sample has timestamp 0, all
1222      * other positions and durations have unknown timestamp. */
1223     if (pos == 0)
1224       timestamp = 0;
1225     else
1226       timestamp = GST_CLOCK_TIME_NONE;
1227     duration = GST_CLOCK_TIME_NONE;
1228     /* update current running segment position with byte offset */
1229     aiff->segment.position = nextpos;
1230   }
1231   if (aiff->discont) {
1232     GST_DEBUG_OBJECT (aiff, "marking DISCONT");
1233     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1234     aiff->discont = FALSE;
1235   }
1236
1237   GST_BUFFER_TIMESTAMP (buf) = timestamp;
1238   GST_BUFFER_DURATION (buf) = duration;
1239
1240   GST_LOG_OBJECT (aiff,
1241       "Got buffer. timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT
1242       ", size:%" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp),
1243       GST_TIME_ARGS (duration), obtained);
1244
1245   if ((res = gst_pad_push (aiff->srcpad, buf)) != GST_FLOW_OK)
1246     goto push_error;
1247
1248   if (obtained < aiff->dataleft) {
1249     aiff->offset += obtained;
1250     aiff->dataleft -= obtained;
1251   } else {
1252     aiff->offset += aiff->dataleft;
1253     aiff->dataleft = 0;
1254   }
1255
1256   /* Iterate until need more data, so adapter size won't grow */
1257   if (aiff->streaming) {
1258     GST_LOG_OBJECT (aiff,
1259         "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, aiff->offset,
1260         aiff->end_offset);
1261     goto iterate_adapter;
1262   }
1263   return res;
1264
1265   /* ERROR */
1266 found_eos:
1267   {
1268     GST_DEBUG_OBJECT (aiff, "found EOS");
1269     return GST_FLOW_EOS;
1270   }
1271 pull_error:
1272   {
1273     /* check if we got EOS */
1274     if (res == GST_FLOW_EOS)
1275       goto found_eos;
1276
1277     GST_WARNING_OBJECT (aiff,
1278         "Error getting %" G_GINT64_FORMAT " bytes from the "
1279         "sinkpad (dataleft = %" G_GINT64_FORMAT ")", desired, aiff->dataleft);
1280     return res;
1281   }
1282 push_error:
1283   {
1284     GST_INFO_OBJECT (aiff,
1285         "Error pushing on srcpad %s:%s, reason %s, is linked? = %d",
1286         GST_DEBUG_PAD_NAME (aiff->srcpad), gst_flow_get_name (res),
1287         gst_pad_is_linked (aiff->srcpad));
1288     return res;
1289   }
1290 }
1291
1292 static void
1293 gst_aiff_parse_loop (GstPad * pad)
1294 {
1295   GstFlowReturn ret;
1296   GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1297
1298   GST_LOG_OBJECT (aiff, "process data");
1299
1300   switch (aiff->state) {
1301     case AIFF_PARSE_START:
1302       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1303       if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK)
1304         goto pause;
1305
1306       aiff->state = AIFF_PARSE_HEADER;
1307       /* fall-through */
1308
1309     case AIFF_PARSE_HEADER:
1310       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1311       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1312         goto pause;
1313
1314       aiff->state = AIFF_PARSE_DATA;
1315       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1316       /* fall-through */
1317
1318     case AIFF_PARSE_DATA:
1319       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1320         goto pause;
1321       break;
1322     default:
1323       g_assert_not_reached ();
1324   }
1325   return;
1326
1327   /* ERRORS */
1328 pause:
1329   {
1330     const gchar *reason = gst_flow_get_name (ret);
1331
1332     GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason);
1333     aiff->segment_running = FALSE;
1334     gst_pad_pause_task (pad);
1335
1336     if (ret == GST_FLOW_EOS) {
1337       /* perform EOS logic */
1338       if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1339         GstClockTime stop;
1340
1341         if ((stop = aiff->segment.stop) == -1)
1342           stop = aiff->segment.duration;
1343
1344         gst_element_post_message (GST_ELEMENT_CAST (aiff),
1345             gst_message_new_segment_done (GST_OBJECT_CAST (aiff),
1346                 aiff->segment.format, stop));
1347         gst_pad_push_event (aiff->srcpad,
1348             gst_event_new_segment_done (aiff->segment.format, stop));
1349       } else {
1350         gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1351       }
1352     } else if (ret < GST_FLOW_EOS || ret == GST_FLOW_NOT_LINKED) {
1353       /* for fatal errors we post an error message, post the error
1354        * first so the app knows about the error first. */
1355       GST_ELEMENT_ERROR (aiff, STREAM, FAILED,
1356           (_("Internal data flow error.")),
1357           ("streaming task paused, reason %s (%d)", reason, ret));
1358       gst_pad_push_event (aiff->srcpad, gst_event_new_eos ());
1359     }
1360     return;
1361   }
1362 }
1363
1364 static GstFlowReturn
1365 gst_aiff_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1366 {
1367   GstFlowReturn ret;
1368   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1369
1370   GST_LOG_OBJECT (aiff, "adapter_push %" G_GSIZE_FORMAT " bytes",
1371       gst_buffer_get_size (buf));
1372
1373   gst_adapter_push (aiff->adapter, buf);
1374
1375   switch (aiff->state) {
1376     case AIFF_PARSE_START:
1377       GST_INFO_OBJECT (aiff, "AIFF_PARSE_START");
1378       if ((ret = gst_aiff_parse_parse_stream_init (aiff)) != GST_FLOW_OK)
1379         goto done;
1380
1381       if (aiff->state != AIFF_PARSE_HEADER)
1382         break;
1383
1384       /* otherwise fall-through */
1385     case AIFF_PARSE_HEADER:
1386       GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER");
1387       if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK)
1388         goto done;
1389
1390       if (!aiff->got_comm || aiff->datastart == 0)
1391         break;
1392
1393       aiff->state = AIFF_PARSE_DATA;
1394       GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA");
1395
1396       /* fall-through */
1397     case AIFF_PARSE_DATA:
1398       if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK)
1399         goto done;
1400       break;
1401     default:
1402       g_return_val_if_reached (GST_FLOW_ERROR);
1403   }
1404 done:
1405   return ret;
1406 }
1407
1408 static gboolean
1409 gst_aiff_parse_pad_convert (GstPad * pad,
1410     GstFormat src_format, gint64 src_value,
1411     GstFormat * dest_format, gint64 * dest_value)
1412 {
1413   GstAiffParse *aiffparse;
1414   gboolean res = TRUE;
1415
1416   aiffparse = GST_AIFF_PARSE (GST_PAD_PARENT (pad));
1417
1418   if (*dest_format == src_format) {
1419     *dest_value = src_value;
1420     return TRUE;
1421   }
1422
1423   if (aiffparse->bytes_per_sample <= 0)
1424     return FALSE;
1425
1426   GST_INFO_OBJECT (aiffparse, "converting value from %s to %s",
1427       gst_format_get_name (src_format), gst_format_get_name (*dest_format));
1428
1429   switch (src_format) {
1430     case GST_FORMAT_BYTES:
1431       switch (*dest_format) {
1432         case GST_FORMAT_DEFAULT:
1433           *dest_value = src_value / aiffparse->bytes_per_sample;
1434           break;
1435         case GST_FORMAT_TIME:
1436           if (aiffparse->bps > 0) {
1437             *dest_value = gst_util_uint64_scale_ceil (src_value, GST_SECOND,
1438                 (guint64) aiffparse->bps);
1439             break;
1440           }
1441           /* Else fallthrough */
1442         default:
1443           res = FALSE;
1444           goto done;
1445       }
1446       break;
1447
1448     case GST_FORMAT_DEFAULT:
1449       switch (*dest_format) {
1450         case GST_FORMAT_BYTES:
1451           *dest_value = src_value * aiffparse->bytes_per_sample;
1452           break;
1453         case GST_FORMAT_TIME:
1454           *dest_value = gst_util_uint64_scale (src_value, GST_SECOND,
1455               (guint64) aiffparse->rate);
1456           break;
1457         default:
1458           res = FALSE;
1459           goto done;
1460       }
1461       break;
1462
1463     case GST_FORMAT_TIME:
1464       switch (*dest_format) {
1465         case GST_FORMAT_BYTES:
1466           if (aiffparse->bps > 0) {
1467             *dest_value = gst_util_uint64_scale (src_value,
1468                 (guint64) aiffparse->bps, GST_SECOND);
1469             break;
1470           }
1471           /* Else fallthrough */
1472           break;
1473         case GST_FORMAT_DEFAULT:
1474           *dest_value = gst_util_uint64_scale (src_value,
1475               (guint64) aiffparse->rate, GST_SECOND);
1476           break;
1477         default:
1478           res = FALSE;
1479           goto done;
1480       }
1481       break;
1482
1483     default:
1484       res = FALSE;
1485       goto done;
1486   }
1487
1488 done:
1489   return res;
1490
1491 }
1492
1493 /* handle queries for location and length in requested format */
1494 static gboolean
1495 gst_aiff_parse_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
1496 {
1497   gboolean res = TRUE;
1498   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1499
1500   /* only if we know */
1501   if (aiff->state != AIFF_PARSE_DATA) {
1502     return FALSE;
1503   }
1504
1505   switch (GST_QUERY_TYPE (query)) {
1506     case GST_QUERY_DURATION:
1507     {
1508       gint64 duration = 0;
1509       GstFormat format;
1510
1511       gst_query_parse_duration (query, &format, NULL);
1512
1513       switch (format) {
1514         case GST_FORMAT_TIME:{
1515           if ((res = gst_aiff_parse_calculate_duration (aiff))) {
1516             duration = aiff->duration;
1517           }
1518           break;
1519         }
1520         default:
1521           format = GST_FORMAT_BYTES;
1522           duration = aiff->datasize;
1523           break;
1524       }
1525       gst_query_set_duration (query, format, duration);
1526       break;
1527     }
1528     case GST_QUERY_CONVERT:
1529     {
1530       gint64 srcvalue, dstvalue;
1531       GstFormat srcformat, dstformat;
1532
1533       gst_query_parse_convert (query, &srcformat, &srcvalue,
1534           &dstformat, &dstvalue);
1535       res = gst_aiff_parse_pad_convert (pad, srcformat, srcvalue,
1536           &dstformat, &dstvalue);
1537       if (res)
1538         gst_query_set_convert (query, srcformat, srcvalue, dstformat, dstvalue);
1539       break;
1540     }
1541     case GST_QUERY_SEEKING:{
1542       GstFormat fmt;
1543
1544       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
1545       if (fmt == GST_FORMAT_TIME) {
1546         gboolean seekable = TRUE;
1547
1548         if (!gst_aiff_parse_calculate_duration (aiff)) {
1549           seekable = FALSE;
1550         }
1551         gst_query_set_seeking (query, GST_FORMAT_TIME, seekable,
1552             0, aiff->duration);
1553         res = TRUE;
1554       }
1555       break;
1556     }
1557     default:
1558       res = gst_pad_query_default (pad, parent, query);
1559       break;
1560   }
1561   return res;
1562 }
1563
1564 static gboolean
1565 gst_aiff_parse_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
1566 {
1567   GstAiffParse *aiffparse = GST_AIFF_PARSE (parent);
1568   gboolean res = FALSE;
1569
1570   GST_DEBUG_OBJECT (aiffparse, "%s event", GST_EVENT_TYPE_NAME (event));
1571
1572   switch (GST_EVENT_TYPE (event)) {
1573     case GST_EVENT_SEEK:
1574       /* can only handle events when we are in the data state */
1575       if (aiffparse->state == AIFF_PARSE_DATA) {
1576         res = gst_aiff_parse_perform_seek (aiffparse, event);
1577       }
1578       gst_event_unref (event);
1579       break;
1580     default:
1581       res = gst_pad_push_event (aiffparse->sinkpad, event);
1582       break;
1583   }
1584   return res;
1585 }
1586
1587 static gboolean
1588 gst_aiff_parse_sink_activate (GstPad * sinkpad, GstObject * parent)
1589 {
1590   GstQuery *query;
1591   gboolean pull_mode;
1592
1593   query = gst_query_new_scheduling ();
1594
1595   if (!gst_pad_peer_query (sinkpad, query)) {
1596     gst_query_unref (query);
1597     goto activate_push;
1598   }
1599
1600   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1601       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1602   gst_query_unref (query);
1603
1604   if (!pull_mode)
1605     goto activate_push;
1606
1607   GST_DEBUG_OBJECT (sinkpad, "going to pull mode");
1608   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1609
1610 activate_push:
1611   {
1612     GST_DEBUG_OBJECT (sinkpad, "going to push (streaming) mode");
1613     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1614   }
1615 }
1616
1617
1618 static gboolean
1619 gst_aiff_parse_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1620     GstPadMode mode, gboolean active)
1621 {
1622   gboolean res;
1623   GstAiffParse *aiff = GST_AIFF_PARSE (parent);
1624
1625   if (aiff->adapter)
1626     g_object_unref (aiff->adapter);
1627
1628   switch (mode) {
1629     case GST_PAD_MODE_PUSH:
1630       aiff->streaming = TRUE;
1631       aiff->adapter = gst_adapter_new ();
1632       res = TRUE;
1633       break;
1634     case GST_PAD_MODE_PULL:
1635       if (active) {
1636         aiff->streaming = FALSE;
1637         aiff->adapter = NULL;
1638         aiff->segment_running = TRUE;
1639         res =
1640             gst_pad_start_task (sinkpad, (GstTaskFunction) gst_aiff_parse_loop,
1641             sinkpad, NULL);
1642       } else {
1643         aiff->segment_running = FALSE;
1644         res = gst_pad_stop_task (sinkpad);
1645       }
1646       break;
1647     default:
1648       res = FALSE;
1649       break;
1650   }
1651   return res;
1652 };
1653
1654 static GstStateChangeReturn
1655 gst_aiff_parse_change_state (GstElement * element, GstStateChange transition)
1656 {
1657   GstStateChangeReturn ret;
1658   GstAiffParse *aiff = GST_AIFF_PARSE (element);
1659
1660   switch (transition) {
1661     case GST_STATE_CHANGE_NULL_TO_READY:
1662       break;
1663     case GST_STATE_CHANGE_READY_TO_PAUSED:
1664       gst_aiff_parse_reset (aiff);
1665       break;
1666     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1667       break;
1668     default:
1669       break;
1670   }
1671
1672   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1673
1674   switch (transition) {
1675     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1676       break;
1677     case GST_STATE_CHANGE_PAUSED_TO_READY:
1678       gst_aiff_parse_reset (aiff);
1679       break;
1680     case GST_STATE_CHANGE_READY_TO_NULL:
1681       break;
1682     default:
1683       break;
1684   }
1685   return ret;
1686 }