This is an attempt at not segfaulting on errors but reporting some usefull info instead.
[platform/upstream/gstreamer.git] / gst / gsttypefind.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gsttypefind.c: 
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23
24 #include "gst_private.h"
25
26 #include "gsttype.h"
27
28 #include "gsttypefind.h"
29
30 /* #define GST_DEBUG_ENABLED */
31
32 GstElementDetails gst_typefind_details = {
33   "TypeFind",
34   "TypeFind",
35   "Finds the media type",
36   VERSION,
37   "Erik Walthinsen <omega@cse.ogi.edu>"
38   "Wim Taymans <wim.taymans@chello.be>",
39   "(C) 1999",
40 };
41
42
43 /* TypeFind signals and args */
44 enum {
45   HAVE_TYPE,
46   LAST_SIGNAL
47 };
48
49 enum {
50   ARG_0,
51   ARG_CAPS,
52 };
53
54
55 static void     gst_typefind_class_init         (GstTypeFindClass *klass);
56 static void     gst_typefind_init               (GstTypeFind *typefind);
57
58 static void     gst_typefind_set_property       (GObject *object, guint prop_id, 
59                                                  const GValue *value, GParamSpec *pspec);
60 static void     gst_typefind_get_property       (GObject *object, guint prop_id, 
61                                                  GValue *value, GParamSpec *pspec);
62
63 static void     gst_typefind_chain              (GstPad *pad, GstBuffer *buf);
64
65 static GstElementClass *parent_class = NULL;
66 static guint gst_typefind_signals[LAST_SIGNAL] = { 0 };
67
68 GType
69 gst_typefind_get_type (void)
70 {
71   static GType typefind_type = 0;
72
73   if (!typefind_type) {
74     static const GTypeInfo typefind_info = {
75       sizeof(GstTypeFindClass),
76       NULL,
77       NULL,
78       (GClassInitFunc)gst_typefind_class_init,
79       NULL,
80       NULL,
81       sizeof(GstTypeFind),
82       0,
83       (GInstanceInitFunc)gst_typefind_init,
84       NULL
85     };
86     typefind_type = g_type_register_static (GST_TYPE_ELEMENT, "GstTypeFind", &typefind_info, 0);
87   }
88   return typefind_type;
89 }
90
91 static void
92 gst_typefind_class_init (GstTypeFindClass *klass)
93 {
94   GObjectClass *gobject_class;
95
96   gobject_class = (GObjectClass*)klass;
97
98   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
99
100   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_CAPS,
101     g_param_spec_pointer("caps", "Caps", "Found capabilities", G_PARAM_READABLE));
102
103   gst_typefind_signals[HAVE_TYPE] =
104       g_signal_new ("have_type", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
105                      G_STRUCT_OFFSET (GstTypeFindClass, have_type), NULL, NULL,
106                      g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
107                      G_TYPE_POINTER);
108
109   gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_typefind_set_property);
110   gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_typefind_get_property);
111 }
112
113 static void
114 gst_typefind_init (GstTypeFind *typefind)
115 {
116   typefind->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
117   gst_element_add_pad (GST_ELEMENT (typefind), typefind->sinkpad);
118   gst_pad_set_chain_function (typefind->sinkpad, gst_typefind_chain);
119 }
120
121 static void
122 gst_typefind_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
123 {
124   GstTypeFind *typefind;
125
126   /* it's not null if we got it, but it might not be ours */
127   g_return_if_fail (GST_IS_TYPEFIND (object));
128
129   typefind = GST_TYPEFIND (object);
130
131   switch (prop_id) {
132     default:
133       break;
134   }
135 }
136
137 static void
138 gst_typefind_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
139 {
140   GstTypeFind *typefind;
141
142   /* it's not null if we got it, but it might not be ours */
143   g_return_if_fail (GST_IS_TYPEFIND (object));
144
145   typefind = GST_TYPEFIND (object);
146
147   switch (prop_id) {
148     case ARG_CAPS:
149       g_value_set_pointer(value, typefind->caps);
150       break;
151     default:
152       break;
153   }
154 }
155
156 static void
157 gst_typefind_chain (GstPad *pad, GstBuffer *buf)
158 {
159   GstTypeFind *typefind;
160   GList *type_list;
161   GstType *type;
162
163   g_return_if_fail (pad != NULL);
164   g_return_if_fail (GST_IS_PAD (pad));
165   g_return_if_fail (buf != NULL);
166
167   typefind = GST_TYPEFIND (GST_OBJECT_PARENT (pad));
168   GST_DEBUG (0,"got buffer of %d bytes in '%s'\n",
169         GST_BUFFER_SIZE (buf), GST_OBJECT_NAME (typefind));
170
171   type_list = gst_type_get_list ();
172
173   while (type_list) {
174     GSList *factories;
175     type = (GstType *)type_list->data;
176
177     factories = type->factories;
178
179     while (factories) {
180       GstTypeFactory *factory = GST_TYPEFACTORY (factories->data);
181       GstTypeFindFunc typefindfunc = (GstTypeFindFunc)factory->typefindfunc;
182       GstCaps *caps;
183
184       GST_DEBUG (0,"try type :%d \"%s\"\n", type->id, type->mime);
185       if (typefindfunc && (caps = typefindfunc (buf, factory))) {
186         GST_DEBUG (0,"found type :%d \"%s\" \"%s\"\n", caps->id, type->mime, 
187                         gst_caps_get_name (caps));
188         typefind->caps = caps;
189
190         gst_pad_set_caps (pad, caps);
191
192 { /* FIXME: this should all be in an _emit() wrapper eventually */
193         int oldstate = GST_STATE(typefind);
194         gst_object_ref (GST_OBJECT (typefind));
195         g_signal_emit (G_OBJECT (typefind), gst_typefind_signals[HAVE_TYPE], 0,
196                               typefind->caps);
197         if (GST_STATE(typefind) != oldstate) {
198           gst_object_unref (GST_OBJECT (typefind));
199           GST_DEBUG(0, "state changed during signal, aborting\n");
200           gst_element_yield (typefind);
201         }
202         gst_object_unref (GST_OBJECT (typefind));
203 }
204
205         goto end;
206       }
207       factories = g_slist_next (factories);
208     }
209
210     type_list = g_list_next (type_list);
211   }
212 end:
213   gst_buffer_unref (buf);
214 }