New mimetypes gone into effect today - this commit changes all old mimetypes over...
[platform/upstream/gst-plugins-good.git] / gst / auparse / gstauparse.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /* 2001/04/03 - Updated parseau to use caps nego
21  *              Zaheer Merali <zaheer@grid9.net
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <gstauparse.h>
31
32
33 /* elementfactory information */
34 static GstElementDetails gst_auparse_details = {
35   ".au parser",
36   "Codec/Parser",
37   "LGPL",
38   "Parse an .au file into raw audio",
39   VERSION,
40   "Erik Walthinsen <omega@cse.ogi.edu>",
41   "(C) 1999",
42 };
43
44 static GstCaps*
45 au_type_find (GstBuffer *buf, gpointer private)
46 {
47   GstCaps *new = NULL;
48   gulong *head = (gulong *) GST_BUFFER_DATA (buf);
49
50   if (*head == 0x2e736e64 || *head == 0x646e732e)
51     new = gst_caps_new ("au_type_find", "audio/au", NULL);
52
53   return new;
54 }
55
56 /* typefactory for 'au' */
57 static GstTypeDefinition audefinition = {
58   "auparse_audio/au",
59   "audio/x-au",
60   ".au",
61   au_type_find,
62 };
63
64 GST_PAD_TEMPLATE_FACTORY (sink_factory_templ,
65   "sink",
66   GST_PAD_SINK,
67   GST_PAD_ALWAYS,
68   GST_CAPS_NEW (
69     "auparse_sink",
70     "audio/x-au",
71     NULL
72   )
73 )
74
75
76 GST_PAD_TEMPLATE_FACTORY (src_factory_templ,
77   "src",
78   GST_PAD_SRC,
79   GST_PAD_ALWAYS,
80   GST_CAPS_NEW (
81     "auparse_src",
82     "audio/x-raw-int",
83       "endianness", GST_PROPS_INT (G_BIG_ENDIAN),
84       "signed",     GST_PROPS_LIST(
85                       GST_PROPS_BOOLEAN (FALSE),
86                       GST_PROPS_BOOLEAN (TRUE)
87                     ),
88       "width",      GST_PROPS_LIST(
89                       GST_PROPS_INT (8),
90                       GST_PROPS_INT (16)
91                     ),
92       "depth",      GST_PROPS_LIST(
93                       GST_PROPS_INT (8),
94                       GST_PROPS_INT (16)
95                     ),
96       "rate",       GST_PROPS_INT_RANGE (8000,48000),
97       "channels",   GST_PROPS_INT_RANGE (1, 2)
98   ),
99   GST_CAPS_NEW (
100     "auparse_src_alaw",
101     "audio/x-alaw",
102       "rate",       GST_PROPS_INT_RANGE (8000,48000),
103       "channels",   GST_PROPS_INT_RANGE (1, 2)
104   )
105 )
106
107 /* AuParse signals and args */
108 enum {
109   /* FILL ME */
110   LAST_SIGNAL
111 };
112
113 enum {
114   ARG_0,
115   /* FILL ME */
116 };
117
118 static void     gst_auparse_class_init          (GstAuParseClass *klass);
119 static void     gst_auparse_init                (GstAuParse *auparse);
120
121 static void     gst_auparse_chain               (GstPad *pad,GstBuffer *buf);
122
123 static GstElementClass *parent_class = NULL;
124 /*static guint gst_auparse_signals[LAST_SIGNAL] = { 0 }; */
125
126 GType
127 gst_auparse_get_type (void) 
128 {
129   static GType auparse_type = 0;
130
131   if (!auparse_type) {
132     static const GTypeInfo auparse_info = {
133       sizeof(GstAuParseClass),      NULL,
134       NULL,
135       (GClassInitFunc) gst_auparse_class_init,
136       NULL,
137       NULL,
138       sizeof(GstAuParse),
139       0,
140       (GInstanceInitFunc) gst_auparse_init,
141     };
142     auparse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAuParse", &auparse_info, 0);
143   }
144   return auparse_type;
145 }
146
147 static void
148 gst_auparse_class_init (GstAuParseClass *klass) 
149 {
150   GstElementClass *gstelement_class;
151
152   gstelement_class = (GstElementClass*) klass;
153
154   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
155 }
156
157 static void 
158 gst_auparse_init (GstAuParse *auparse) 
159 {
160   auparse->sinkpad = gst_pad_new_from_template (
161                   GST_PAD_TEMPLATE_GET (sink_factory_templ), "sink");
162   gst_element_add_pad (GST_ELEMENT (auparse), auparse->sinkpad);
163   gst_pad_set_chain_function (auparse->sinkpad, gst_auparse_chain);
164
165   auparse->srcpad = gst_pad_new_from_template (
166                   GST_PAD_TEMPLATE_GET (src_factory_templ), "src");
167   gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
168
169   auparse->offset = 0;
170   auparse->size = 0;
171   auparse->encoding = 0;
172   auparse->frequency = 0;
173   auparse->channels = 0;
174 }
175
176 static void 
177 gst_auparse_chain (GstPad *pad, GstBuffer *buf) 
178 {
179   GstAuParse *auparse;
180   gchar *data;
181   glong size;
182   GstCaps* tempcaps;
183   gint law, depth;
184   gboolean sign;
185
186   g_return_if_fail (pad != NULL);
187   g_return_if_fail (GST_IS_PAD (pad));
188   g_return_if_fail (buf != NULL);
189
190   auparse = GST_AUPARSE (gst_pad_get_parent (pad));
191   
192   GST_DEBUG ("gst_auparse_chain: got buffer in '%s'",
193           gst_element_get_name (GST_ELEMENT (auparse)));
194
195   data = GST_BUFFER_DATA (buf);
196   size = GST_BUFFER_SIZE (buf);
197
198   /* if we haven't seen any data yet... */
199   if (auparse->size == 0) {
200     GstBuffer *newbuf;
201     guint32 *head = (guint32 *)data;
202
203     /* normal format is big endian (au is a Sparc format) */
204     if (GUINT32_FROM_BE (*head) == 0x2e736e64) {
205       head++;
206       auparse->le = 0;
207       auparse->offset           = GUINT32_FROM_BE (*head);
208       head++;
209       auparse->size             = GUINT32_FROM_BE (*head);
210       head++;
211       auparse->encoding         = GUINT32_FROM_BE (*head);
212       head++;
213       auparse->frequency        = GUINT32_FROM_BE (*head);
214       head++;
215       auparse->channels         = GUINT32_FROM_BE (*head);
216       head++;
217
218     /* and of course, someone had to invent a little endian
219      * version.  Used by DEC systems. */
220     } else if (GUINT32_FROM_LE (*head) == 0x0064732E) {
221       auparse->le = 1;
222       head++;
223       auparse->le = 0;
224       auparse->offset           = GUINT32_FROM_LE (*head);
225       head++;
226       auparse->size             = GUINT32_FROM_LE (*head);
227       head++;
228       auparse->encoding         = GUINT32_FROM_LE (*head);
229       head++;
230       auparse->frequency        = GUINT32_FROM_LE (*head);
231       head++;
232       auparse->channels         = GUINT32_FROM_LE (*head);
233       head++;
234
235     } else {
236       g_warning ("help, dunno what I'm looking at!\n");
237       gst_buffer_unref(buf);
238       return;
239     }
240
241     g_print ("offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld\n",
242              auparse->offset,auparse->size,auparse->encoding,
243              auparse->frequency,auparse->channels);
244     GST_DEBUG ("offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld",
245              auparse->offset,auparse->size,auparse->encoding,
246              auparse->frequency,auparse->channels);
247     
248     switch (auparse->encoding) {
249       case 1:
250         law = 1;
251         depth = 8;
252         sign = FALSE;
253         break;
254       case 2:
255         law = 0;
256         depth = 8;
257         sign = FALSE;
258         break;
259       case 3:
260         law = 0;
261         depth = 16;
262         sign = TRUE;
263         break;
264       default:
265         g_warning ("help!, dont know how to deal with this format yet\n");
266         return;
267     }
268
269     if (law) {
270       tempcaps = GST_CAPS_NEW ("auparse_src",
271                                "audio/x-alaw",
272                                  "rate",     GST_PROPS_INT (auparse->frequency),
273                                  "channels", GST_PROPS_INT (auparse->channels));
274     } else {
275       tempcaps = GST_CAPS_NEW ("auparse_src",
276                                "audio/x-raw-int",
277                                  "endianness", GST_PROPS_INT (G_BIG_ENDIAN),
278                                  "rate",       GST_PROPS_INT (auparse->frequency),
279                                  "channels",   GST_PROPS_INT (auparse->channels),
280                                  "depth",      GST_PROPS_INT (depth),
281                                  "width",      GST_PROPS_INT (depth),
282                                  "signed",     GST_PROPS_BOOLEAN (sign));
283     }
284
285     if (gst_pad_try_set_caps (auparse->srcpad, tempcaps) <= 0) {
286       gst_buffer_unref (buf);
287       gst_element_error (GST_ELEMENT (auparse), "could not set audio caps");
288       return;
289     }
290
291     newbuf = gst_buffer_new ();
292     GST_BUFFER_DATA (newbuf) = (gpointer) malloc (size-(auparse->offset));
293     memcpy (GST_BUFFER_DATA (newbuf), data+24, size-(auparse->offset));
294     GST_BUFFER_SIZE (newbuf) = size-(auparse->offset);
295
296     gst_buffer_unref (buf);
297
298     gst_pad_push (auparse->srcpad, newbuf);
299     return;
300   }
301
302   gst_pad_push (auparse->srcpad, buf);
303 }
304
305
306 static gboolean
307 plugin_init (GModule *module, GstPlugin *plugin)
308 {
309   GstElementFactory *factory;
310   GstTypeFactory *type;
311
312   /* create the plugin structure */
313   /* create an elementfactory for the auparse element and list it */
314   factory = gst_element_factory_new ("auparse", GST_TYPE_AUPARSE,
315                                     &gst_auparse_details);
316   g_return_val_if_fail (factory != NULL, FALSE);
317   gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_SECONDARY);
318
319   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_factory_templ));
320   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_factory_templ));
321
322   type = gst_type_factory_new (&audefinition);
323
324   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
325   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
326
327   return TRUE;
328 }
329
330 GstPluginDesc plugin_desc = {
331   GST_VERSION_MAJOR,
332   GST_VERSION_MINOR,
333   "auparse",
334   plugin_init
335 };
336