converted gst_element_error to new format in gst/ - gettext pending
[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 (GST_BUFFER_SIZE (buf) < 4)
51     return NULL;
52
53   if (*head == 0x2e736e64 || *head == 0x646e732e)
54     new = gst_caps_new ("au_type_find", "audio/x-au", NULL);
55
56   return new;
57 }
58
59 /* typefactory for 'au' */
60 static GstTypeDefinition audefinition = {
61   "auparse_audio/au",
62   "audio/x-au",
63   ".au",
64   au_type_find,
65 };
66
67 GST_PAD_TEMPLATE_FACTORY (sink_factory_templ,
68   "sink",
69   GST_PAD_SINK,
70   GST_PAD_ALWAYS,
71   GST_CAPS_NEW (
72     "auparse_sink",
73     "audio/x-au",
74     NULL
75   )
76 )
77
78
79 GST_PAD_TEMPLATE_FACTORY (src_factory_templ,
80   "src",
81   GST_PAD_SRC,
82   GST_PAD_ALWAYS,
83   GST_CAPS_NEW (
84     "auparse_src",
85     "audio/x-raw-int",
86       "endianness", GST_PROPS_INT (G_BIG_ENDIAN),
87       "signed",     GST_PROPS_LIST(
88                       GST_PROPS_BOOLEAN (FALSE),
89                       GST_PROPS_BOOLEAN (TRUE)
90                     ),
91       "width",      GST_PROPS_LIST(
92                       GST_PROPS_INT (8),
93                       GST_PROPS_INT (16)
94                     ),
95       "depth",      GST_PROPS_LIST(
96                       GST_PROPS_INT (8),
97                       GST_PROPS_INT (16)
98                     ),
99       "rate",       GST_PROPS_INT_RANGE (8000,48000),
100       "channels",   GST_PROPS_INT_RANGE (1, 2)
101   ),
102   GST_CAPS_NEW (
103     "auparse_src_alaw",
104     "audio/x-alaw",
105       "rate",       GST_PROPS_INT_RANGE (8000,48000),
106       "channels",   GST_PROPS_INT_RANGE (1, 2)
107   )
108 )
109
110 /* AuParse signals and args */
111 enum {
112   /* FILL ME */
113   LAST_SIGNAL
114 };
115
116 enum {
117   ARG_0,
118   /* FILL ME */
119 };
120
121 static void     gst_auparse_class_init          (GstAuParseClass *klass);
122 static void     gst_auparse_init                (GstAuParse *auparse);
123
124 static void     gst_auparse_chain               (GstPad *pad,GstBuffer *buf);
125
126 static GstElementClass *parent_class = NULL;
127 /*static guint gst_auparse_signals[LAST_SIGNAL] = { 0 }; */
128
129 GType
130 gst_auparse_get_type (void) 
131 {
132   static GType auparse_type = 0;
133
134   if (!auparse_type) {
135     static const GTypeInfo auparse_info = {
136       sizeof(GstAuParseClass),      NULL,
137       NULL,
138       (GClassInitFunc) gst_auparse_class_init,
139       NULL,
140       NULL,
141       sizeof(GstAuParse),
142       0,
143       (GInstanceInitFunc) gst_auparse_init,
144     };
145     auparse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstAuParse", &auparse_info, 0);
146   }
147   return auparse_type;
148 }
149
150 static void
151 gst_auparse_class_init (GstAuParseClass *klass) 
152 {
153   GstElementClass *gstelement_class;
154
155   gstelement_class = (GstElementClass*) klass;
156
157   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
158 }
159
160 static void 
161 gst_auparse_init (GstAuParse *auparse) 
162 {
163   auparse->sinkpad = gst_pad_new_from_template (
164                   GST_PAD_TEMPLATE_GET (sink_factory_templ), "sink");
165   gst_element_add_pad (GST_ELEMENT (auparse), auparse->sinkpad);
166   gst_pad_set_chain_function (auparse->sinkpad, gst_auparse_chain);
167
168   auparse->srcpad = gst_pad_new_from_template (
169                   GST_PAD_TEMPLATE_GET (src_factory_templ), "src");
170   gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
171
172   auparse->offset = 0;
173   auparse->size = 0;
174   auparse->encoding = 0;
175   auparse->frequency = 0;
176   auparse->channels = 0;
177 }
178
179 static void 
180 gst_auparse_chain (GstPad *pad, GstBuffer *buf) 
181 {
182   GstAuParse *auparse;
183   gchar *data;
184   glong size;
185   GstCaps* tempcaps;
186   gint law, depth;
187   gboolean sign;
188
189   g_return_if_fail (pad != NULL);
190   g_return_if_fail (GST_IS_PAD (pad));
191   g_return_if_fail (buf != NULL);
192
193   auparse = GST_AUPARSE (gst_pad_get_parent (pad));
194   
195   GST_DEBUG ("gst_auparse_chain: got buffer in '%s'",
196           gst_element_get_name (GST_ELEMENT (auparse)));
197
198   data = GST_BUFFER_DATA (buf);
199   size = GST_BUFFER_SIZE (buf);
200
201   /* if we haven't seen any data yet... */
202   if (auparse->size == 0) {
203     GstBuffer *newbuf;
204     guint32 *head = (guint32 *)data;
205
206     /* normal format is big endian (au is a Sparc format) */
207     if (GUINT32_FROM_BE (*head) == 0x2e736e64) {
208       head++;
209       auparse->le = 0;
210       auparse->offset           = GUINT32_FROM_BE (*head);
211       head++;
212       auparse->size             = GUINT32_FROM_BE (*head);
213       head++;
214       auparse->encoding         = GUINT32_FROM_BE (*head);
215       head++;
216       auparse->frequency        = GUINT32_FROM_BE (*head);
217       head++;
218       auparse->channels         = GUINT32_FROM_BE (*head);
219       head++;
220
221     /* and of course, someone had to invent a little endian
222      * version.  Used by DEC systems. */
223     } else if (GUINT32_FROM_LE (*head) == 0x0064732E) {
224       auparse->le = 1;
225       head++;
226       auparse->le = 0;
227       auparse->offset           = GUINT32_FROM_LE (*head);
228       head++;
229       auparse->size             = GUINT32_FROM_LE (*head);
230       head++;
231       auparse->encoding         = GUINT32_FROM_LE (*head);
232       head++;
233       auparse->frequency        = GUINT32_FROM_LE (*head);
234       head++;
235       auparse->channels         = GUINT32_FROM_LE (*head);
236       head++;
237
238     } else {
239       g_warning ("help, dunno what I'm looking at!\n");
240       gst_buffer_unref(buf);
241       return;
242     }
243
244     g_print ("offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld\n",
245              auparse->offset,auparse->size,auparse->encoding,
246              auparse->frequency,auparse->channels);
247     GST_DEBUG ("offset %ld, size %ld, encoding %ld, frequency %ld, channels %ld",
248              auparse->offset,auparse->size,auparse->encoding,
249              auparse->frequency,auparse->channels);
250     
251     switch (auparse->encoding) {
252       case 1:
253         law = 1;
254         depth = 8;
255         sign = FALSE;
256         break;
257       case 2:
258         law = 0;
259         depth = 8;
260         sign = FALSE;
261         break;
262       case 3:
263         law = 0;
264         depth = 16;
265         sign = TRUE;
266         break;
267       default:
268         g_warning ("help!, dont know how to deal with this format yet\n");
269         return;
270     }
271
272     if (law) {
273       tempcaps = GST_CAPS_NEW ("auparse_src",
274                                "audio/x-alaw",
275                                  "rate",     GST_PROPS_INT (auparse->frequency),
276                                  "channels", GST_PROPS_INT (auparse->channels));
277     } else {
278       tempcaps = GST_CAPS_NEW ("auparse_src",
279                                "audio/x-raw-int",
280                                  "endianness", GST_PROPS_INT (G_BIG_ENDIAN),
281                                  "rate",       GST_PROPS_INT (auparse->frequency),
282                                  "channels",   GST_PROPS_INT (auparse->channels),
283                                  "depth",      GST_PROPS_INT (depth),
284                                  "width",      GST_PROPS_INT (depth),
285                                  "signed",     GST_PROPS_BOOLEAN (sign));
286     }
287
288     if (gst_pad_try_set_caps (auparse->srcpad, tempcaps) <= 0) {
289       gst_buffer_unref (buf);
290       gst_element_gerror(GST_ELEMENT (auparse), GST_ERROR_UNKNOWN,
291         g_strdup ("unconverted error, file a bug"),
292         g_strdup_printf("could not set audio caps"));
293       return;
294     }
295
296     newbuf = gst_buffer_new ();
297     GST_BUFFER_DATA (newbuf) = (gpointer) malloc (size-(auparse->offset));
298     memcpy (GST_BUFFER_DATA (newbuf), data+24, size-(auparse->offset));
299     GST_BUFFER_SIZE (newbuf) = size-(auparse->offset);
300
301     gst_buffer_unref (buf);
302
303     gst_pad_push (auparse->srcpad, newbuf);
304     return;
305   }
306
307   gst_pad_push (auparse->srcpad, buf);
308 }
309
310
311 static gboolean
312 plugin_init (GModule *module, GstPlugin *plugin)
313 {
314   GstElementFactory *factory;
315   GstTypeFactory *type;
316
317   /* create the plugin structure */
318   /* create an elementfactory for the auparse element and list it */
319   factory = gst_element_factory_new ("auparse", GST_TYPE_AUPARSE,
320                                     &gst_auparse_details);
321   g_return_val_if_fail (factory != NULL, FALSE);
322   gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_SECONDARY);
323
324   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_factory_templ));
325   gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_factory_templ));
326
327   type = gst_type_factory_new (&audefinition);
328
329   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
330   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
331
332   return TRUE;
333 }
334
335 GstPluginDesc plugin_desc = {
336   GST_VERSION_MAJOR,
337   GST_VERSION_MINOR,
338   "auparse",
339   plugin_init
340 };
341