comment out unused caps_changed related functions and prototypes
[platform/upstream/gstreamer.git] / gst / autoplug / gstautoplugger.c
1 /* GStreamer
2  * Copyright (C) 2001 RidgeRun, Inc. (www.ridgerun.com)
3  *
4  * gstautoplugger.c: Data  for the dynamic autopluggerger
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #include <gst/gst.h>
23
24 GstElementDetails gst_autoplugger_details = {
25   "Dynamic autoplugger",
26   "Generic",
27   "LGPL",
28   "Magic element that converts from any type to any other",
29   VERSION,
30   "Erik Walthinsen <omega@temple-baptist.com>",
31   "(C) 2001 RidgeRun, Inc. (www.ridgerun.com)",
32 };
33
34 #define GST_TYPE_AUTOPLUGGER \
35   (gst_autoplugger_get_type())
36 #define GST_AUTOPLUGGER(obj) \
37   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUTOPLUGGER,GstAutoplugger))
38 #define GST_AUTOPLUGGER_CLASS(klass) \
39   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUTOPLUGGER,GstAutopluggerClass))
40 #define GST_IS_AUTOPLUGGER(obj) \
41   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUTOPLUGGER))
42 #define GST_IS_AUTOPLUGGER_CLASS(obj) \
43   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUTOPLUGGER))
44
45 typedef struct _GstAutoplugger GstAutoplugger;
46 typedef struct _GstAutopluggerClass GstAutopluggerClass;
47
48 struct _GstAutoplugger {
49   GstBin bin;
50   gint paused;
51
52   GstElement *cache;
53   gboolean cache_first_buffer;
54   GstPad *cache_sinkpad, *cache_srcpad;
55
56   GstElement *typefind;
57   GstPad *typefind_sinkpad;
58
59   GstPad *sinkpadpeer, *srcpadpeer;
60   GstCaps *sinkcaps, *srccaps;
61
62   GstCaps *sinktemplatecaps;
63
64   GstAutoplug *autoplug;
65   GstElement *autobin;
66
67   gboolean disable_nocaps;
68 };
69
70 struct _GstAutopluggerClass {
71   GstBinClass parent_class;
72 };
73
74
75 /*  signals and args */
76 enum {
77   LAST_SIGNAL
78 };
79
80 enum {
81   ARG_0,
82 };
83
84
85 static void                     gst_autoplugger_class_init      (GstAutopluggerClass *klass);
86 static void                     gst_autoplugger_init            (GstAutoplugger *queue);
87
88 static void                     gst_autoplugger_set_property            (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
89 static void                     gst_autoplugger_get_property            (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
90
91 /*static GstElementStateReturn  gst_autoplugger_change_state    (GstElement *element);*/
92
93
94 /*
95 static void     gst_autoplugger_external_sink_caps_changed      (GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger);
96 static void     gst_autoplugger_external_src_caps_changed       (GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger);
97 */
98 static void     gst_autoplugger_external_sink_caps_nego_failed  (GstPad *pad, gboolean *result, GstAutoplugger *autoplugger);
99 static void     gst_autoplugger_external_src_caps_nego_failed   (GstPad *pad, gboolean *result, GstAutoplugger *autoplugger);
100 /* defined but not used
101 static void     gst_autoplugger_external_sink_linked            (GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger);
102 static void     gst_autoplugger_external_src_linked             (GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger);
103 */
104 static void     gst_autoplugger_cache_first_buffer              (GstElement *element,GstBuffer *buf,GstAutoplugger *autoplugger);
105 static void     gst_autoplugger_cache_empty                     (GstElement *element, GstAutoplugger *autoplugger);
106 static void     gst_autoplugger_type_find_have_type             (GstElement *element, GstCaps *caps, GstAutoplugger *autoplugger);
107
108 static GstElementClass *parent_class = NULL;
109 /*static guint gst_autoplugger_signals[LAST_SIGNAL] = { 0 };*/
110
111 GType
112 gst_autoplugger_get_type(void) {
113   static GType autoplugger_type = 0;
114
115   if (!autoplugger_type) {
116     static const GTypeInfo autoplugger_info = {
117       sizeof(GstAutopluggerClass),
118       NULL,
119       NULL,
120       (GClassInitFunc)gst_autoplugger_class_init,
121       NULL,
122       NULL,
123       sizeof(GstAutoplugger),
124       0,
125       (GInstanceInitFunc)gst_autoplugger_init,
126     };
127     autoplugger_type = g_type_register_static (GST_TYPE_BIN, "GstAutoplugger", &autoplugger_info, 0);
128   }
129   return autoplugger_type;
130 }
131
132 static void
133 gst_autoplugger_class_init (GstAutopluggerClass *klass)
134 {
135   GObjectClass *gobject_class;
136   GstElementClass *gstelement_class;
137
138   gobject_class = (GObjectClass*)klass;
139   gstelement_class = (GstElementClass*)klass;
140
141   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
142
143 /*
144   gst_autoplugger_signals[_EMPTY] =
145     g_signal_new ("_empty", G_OBJECT_TYPE(gobject_class), G_SIGNAL_RUN_LAST,
146                     G_STRUCT_OFFSET (GstAutopluggerClass, _empty), NULL, NULL,
147                     g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
148 */
149
150 /*
151   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_BUFFER_COUNT,
152     g_param_spec_int("buffer_count","buffer_count","buffer_count",
153                       0,G_MAXINT,0,G_PARAM_READABLE)); * CHECKME! *
154   g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_RESET,
155     g_param_spec_boolean("reset","reset","reset",
156                          FALSE,G_PARAM_WRITABLE)); * CHECKME! *
157 */
158
159   gobject_class->set_property = gst_autoplugger_set_property;
160   gobject_class->get_property = gst_autoplugger_get_property;
161
162 /*  gstelement_class->change_state = gst_autoplugger_change_state; */
163 }
164
165 static void
166 gst_autoplugger_init (GstAutoplugger *autoplugger)
167 {
168   /* create the autoplugger cache, which is the fundamental unit of the autopluggerger */
169   /* FIXME we need to find a way to set element's name before _init */
170   /* FIXME ... so we can name the subelements uniquely              */
171   autoplugger->cache = gst_element_factory_make("autoplugcache", "unnamed_autoplugcache");
172   g_return_if_fail (autoplugger->cache != NULL);
173
174   GST_DEBUG(GST_CAT_AUTOPLUG, "turning on caps nego proxying in cache");
175   g_object_set(G_OBJECT(autoplugger->cache),"caps_proxy",TRUE,NULL);
176
177   /* attach signals to the cache */
178   g_signal_connect (G_OBJECT (autoplugger->cache), "first_buffer",
179                      G_CALLBACK (gst_autoplugger_cache_first_buffer), autoplugger);
180
181   /* add the cache to self */
182   gst_bin_add (GST_BIN(autoplugger), autoplugger->cache);
183
184   /* get the cache's pads so we can attach stuff to them */
185   autoplugger->cache_sinkpad = gst_element_get_pad (autoplugger->cache, "sink");
186   autoplugger->cache_srcpad = gst_element_get_pad (autoplugger->cache, "src");
187
188   /* attach handlers to the typefind pads */
189   /* FIXME "caps_changed" no longer exists
190   g_signal_connect (G_OBJECT (autoplugger->cache_sinkpad), "caps_changed",
191                      G_CALLBACK (gst_autoplugger_external_sink_caps_changed), autoplugger);
192   g_signal_connect (G_OBJECT (autoplugger->cache_srcpad), "caps_changed",
193                      G_CALLBACK (gst_autoplugger_external_src_caps_changed), autoplugger);
194   */
195   g_signal_connect (G_OBJECT (autoplugger->cache_sinkpad), "caps_nego_failed",
196                      G_CALLBACK (gst_autoplugger_external_sink_caps_nego_failed), autoplugger);
197   g_signal_connect (G_OBJECT (autoplugger->cache_srcpad), "caps_nego_failed",
198                      G_CALLBACK (gst_autoplugger_external_src_caps_nego_failed), autoplugger);
199 /*  g_signal_connect (G_OBJECT (autoplugger->cache_sinkpad), "linked",    */
200 /*                     gst_autoplugger_external_sink_linked, autoplugger);*/
201 /*  g_signal_connect (G_OBJECT (autoplugger->cache_srcpad), "linked",     */    
202 /*                     gst_autoplugger_external_src_linked, autoplugger); */
203
204   /* ghost both of these pads to the outside world */
205   gst_element_add_ghost_pad (GST_ELEMENT(autoplugger), autoplugger->cache_sinkpad, "sink");
206   gst_element_add_ghost_pad (GST_ELEMENT(autoplugger), autoplugger->cache_srcpad, "src");
207 }
208
209 /* defined but not used
210 G_GNUC_UNUSED static void
211 gst_autoplugger_external_sink_linked(GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger)
212 {
213   GstPadTemplate *peertemplate;
214   GstCaps *peercaps, *peertemplatecaps;
215
216   GST_INFO(GST_CAT_AUTOPLUG, "have cache:sink linked");*/
217 /*  autoplugger->sinkpadpeer = peerpad; */
218 /*
219   if (autoplugger->sinkpadpeer) {
220     peercaps = GST_PAD_CAPS(autoplugger->sinkpadpeer);
221     if (peercaps)
222       GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer: %s",
223                gst_caps_get_mime(peercaps));
224     peertemplate = GST_PAD_PAD_TEMPLATE(autoplugger->sinkpadpeer);
225     if (peertemplate) {
226       peertemplatecaps = GST_PAD_TEMPLATE_CAPS(peertemplate);
227       if (peertemplatecaps) {
228         GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer's padtemplate %s",
229                  gst_caps_get_mime(peertemplatecaps));
230       }
231     }
232   }
233 }
234
235 G_GNUC_UNUSED static void
236 gst_autoplugger_external_src_linked(GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger)
237 {
238   GstPadTemplate *peertemplate;
239   GstCaps *peercaps, *peertemplatecaps;
240
241   GST_INFO(GST_CAT_AUTOPLUG, "have cache:src linked");*/
242 /*  autoplugger->srcpadpeer = peerpad; */
243 /*
244   if (autoplugger->srcpadpeer) {
245     peercaps = GST_PAD_CAPS(autoplugger->srcpadpeer);
246     if (peercaps)
247       GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer: %s",
248                gst_caps_get_mime(peercaps));
249     peertemplate = GST_PAD_PAD_TEMPLATE(autoplugger->srcpadpeer);
250     if (peertemplate) {
251       peertemplatecaps = GST_PAD_TEMPLATE_CAPS(peertemplate);
252       if (peertemplatecaps) {
253         GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer's padtemplate %s",
254                  gst_caps_get_mime(peertemplatecaps));
255         autoplugger->sinktemplatecaps = peertemplatecaps;*/
256 /*        GST_DEBUG(GST_CAT_AUTOPLUG, "turning on caps nego proxying in cache"); */
257 /*        gtk_object_set(G_OBJECT(autoplugger->cache),"caps_proxy",TRUE,NULL);*/
258 /*      }
259     }
260   }
261 }*/
262
263
264 /*
265 static void
266 gst_autoplugger_external_sink_caps_changed(GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger)
267 {
268   GST_INFO(GST_CAT_AUTOPLUG, "have cache:sink caps of %s\n",gst_caps_get_mime(caps));
269   autoplugger->sinkcaps = caps;
270 }
271
272 static void
273 gst_autoplugger_external_src_caps_changed(GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger)
274 {
275   GST_INFO(GST_CAT_AUTOPLUG, "have cache:src caps of %s\n",gst_caps_get_mime(caps));
276   autoplugger->srccaps = caps;
277 }
278 */
279
280
281 static gboolean
282 gst_autoplugger_autoplug(GstAutoplugger *autoplugger,GstPad *srcpad,GstCaps *srccaps,GstCaps *sinkcaps)
283 {
284   GstPad *sinkpad;
285
286   sinkpad = GST_PAD(GST_PAD_PEER(srcpad));
287   GST_DEBUG(GST_CAT_AUTOPLUG,"unlinking %s:%s and %s:%s to autoplug between them",
288             GST_DEBUG_PAD_NAME(srcpad),GST_DEBUG_PAD_NAME(sinkpad));
289   GST_DEBUG(GST_CAT_AUTOPLUG,"srcpadcaps are of type %s",gst_caps_get_mime(srccaps));
290   GST_DEBUG(GST_CAT_AUTOPLUG,"sinkpadcaps are of type %s",gst_caps_get_mime(sinkcaps));
291
292   /* unlink the pads */
293   GST_DEBUG(GST_CAT_AUTOPLUG, "unlinking the pads that will be joined by an autobin");
294   gst_pad_unlink(srcpad,sinkpad);
295
296   if (!autoplugger->autoplug) {
297     autoplugger->autoplug = gst_autoplug_factory_make("static");
298     g_return_val_if_fail(autoplugger->autoplug != NULL, FALSE);
299   }
300   GST_DEBUG(GST_CAT_AUTOPLUG, "building autoplugged bin between caps");
301   autoplugger->autobin = gst_autoplug_to_caps(autoplugger->autoplug,
302     srccaps,sinkcaps,NULL);
303   g_return_val_if_fail(autoplugger->autobin != NULL, FALSE);
304   gst_bin_add(GST_BIN(autoplugger),autoplugger->autobin);
305
306 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
307
308   /* FIXME this is a hack */
309 /*  GST_DEBUG(GST_CAT_AUTOPLUG, "copying failed caps to srcpad %s:%s to ensure renego",GST_DEBUG_PAD_NAME(autoplugger->cache_srcpad)); */
310 /*  gst_pad_set_caps(srcpad,srccaps); */
311
312   if (GST_PAD_CAPS(srcpad) == NULL) GST_DEBUG(GST_CAT_AUTOPLUG,"no caps on cache:src!");
313
314   /* attach the autoplugged bin */
315   GST_DEBUG(GST_CAT_AUTOPLUG, "attaching the autoplugged bin between the two pads");
316   gst_pad_link(srcpad,gst_element_get_pad(autoplugger->autobin,"sink"));
317 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
318   gst_pad_link(gst_element_get_pad(autoplugger->autobin,"src_00"),sinkpad);
319 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
320
321   /* FIXME try to force the renego */
322 /*  GST_DEBUG(GST_CAT_AUTOPLUG, "trying to force everyone to nego"); */
323 /*  gst_pad_renegotiate(gst_element_get_pad(autoplugger->autobin,"sink")); */
324 /*  gst_pad_renegotiate(sinkpad); */
325
326   return TRUE;
327 }
328
329 static void
330 gst_autoplugger_external_sink_caps_nego_failed(GstPad *pad, gboolean *result, GstAutoplugger *autoplugger)
331 {
332   GstPad *srcpad_peer;
333   GstPadTemplate *srcpad_peer_template;
334   GstCaps *srcpad_peer_caps;
335   GstPad *sinkpad_peer;
336   GstCaps *sinkpad_peer_caps;
337
338   GST_INFO(GST_CAT_AUTOPLUG, "have caps nego failure on sinkpad %s:%s!!!",GST_DEBUG_PAD_NAME(pad));
339
340   autoplugger->paused++;
341   if (autoplugger->paused == 1)
342     /* try to PAUSE the whole thing */
343     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED);
344
345   srcpad_peer = GST_PAD(GST_PAD_PEER(autoplugger->cache_srcpad));
346   g_return_if_fail(srcpad_peer != NULL);
347   srcpad_peer_template = GST_PAD_PAD_TEMPLATE(srcpad_peer);
348   g_return_if_fail(srcpad_peer_template != NULL);
349   srcpad_peer_caps = GST_PAD_TEMPLATE_CAPS(srcpad_peer_template);
350   g_return_if_fail(srcpad_peer_caps != NULL);
351
352   sinkpad_peer = GST_PAD(GST_PAD_PEER(pad));
353   g_return_if_fail(sinkpad_peer != NULL);
354   sinkpad_peer_caps = GST_PAD_CAPS(sinkpad_peer);
355   g_return_if_fail(sinkpad_peer_caps != NULL);
356
357   if (gst_autoplugger_autoplug(autoplugger,autoplugger->cache_srcpad,sinkpad_peer_caps,srcpad_peer_caps))
358     *result = TRUE;
359
360   autoplugger->paused--;
361   if (autoplugger->paused == 0)
362     /* try to PLAY the whole thing */
363     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
364
365   GST_INFO(GST_CAT_AUTOPLUG, "done dealing with caps nego failure on sinkpad %s:%s",GST_DEBUG_PAD_NAME(pad));
366 }
367
368 static void
369 gst_autoplugger_external_src_caps_nego_failed(GstPad *pad, gboolean *result, GstAutoplugger *autoplugger)
370 {
371   GstCaps *srcpad_caps;
372   GstPad *srcpad_peer;
373   GstPadTemplate *srcpad_peer_template;
374   GstCaps *srcpad_peer_caps;
375
376   GST_INFO(GST_CAT_AUTOPLUG, "have caps nego failure on srcpad %s:%s!!!",GST_DEBUG_PAD_NAME(pad));
377
378   autoplugger->paused++;
379   if (autoplugger->paused == 1)
380     /* try to PAUSE the whole thing */
381     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED);
382
383   srcpad_caps = GST_PAD_CAPS(autoplugger->cache_srcpad);
384
385   srcpad_peer = GST_PAD(GST_PAD_PEER(autoplugger->cache_srcpad));
386   g_return_if_fail(srcpad_peer != NULL);
387   srcpad_peer_template = GST_PAD_PAD_TEMPLATE(srcpad_peer);
388   g_return_if_fail(srcpad_peer_template != NULL);
389   srcpad_peer_caps = GST_PAD_TEMPLATE_CAPS(srcpad_peer_template);
390   g_return_if_fail(srcpad_peer_caps != NULL);
391
392   if (gst_autoplugger_autoplug(autoplugger,autoplugger->cache_srcpad,srcpad_caps,srcpad_peer_caps))
393     *result = TRUE;
394
395   autoplugger->paused--;
396   if (autoplugger->paused == 0)
397     /* try to PLAY the whole thing */
398     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
399
400   autoplugger->disable_nocaps = TRUE;
401
402   GST_INFO(GST_CAT_AUTOPLUG, "done dealing with caps nego failure on srcpad %s:%s",GST_DEBUG_PAD_NAME(pad));
403 }
404
405
406 static void
407 gst_autoplugger_cache_empty(GstElement *element, GstAutoplugger *autoplugger)
408 {
409   GstPad *cache_sinkpad_peer,*cache_srcpad_peer;
410
411   GST_INFO(GST_CAT_AUTOPLUG, "autoplugger cache has hit empty, we can now remove it");
412
413   autoplugger->paused++;
414   if (autoplugger->paused == 1)
415     /* try to PAUSE the whole thing */
416     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED);
417
418   /* unlink the cache from its peers */
419   GST_DEBUG(GST_CAT_AUTOPLUG, "unlinking autoplugcache from its peers");
420   cache_sinkpad_peer = GST_PAD (GST_PAD_PEER(autoplugger->cache_sinkpad));
421   cache_srcpad_peer = GST_PAD (GST_PAD_PEER(autoplugger->cache_srcpad));
422   gst_pad_unlink(cache_sinkpad_peer,autoplugger->cache_sinkpad);
423   gst_pad_unlink(autoplugger->cache_srcpad,cache_srcpad_peer);
424
425   /* remove the cache from self */
426   GST_DEBUG(GST_CAT_AUTOPLUG, "removing the cache from the autoplugger");
427   gst_bin_remove (GST_BIN(autoplugger), autoplugger->cache);
428
429   /* link the two pads */
430   GST_DEBUG(GST_CAT_AUTOPLUG, "relinking the autoplugcache's former peers");
431   gst_pad_link(cache_sinkpad_peer,cache_srcpad_peer);
432
433   autoplugger->paused--;
434   if (autoplugger->paused == 0)
435     /* try to PLAY the whole thing */
436     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
437
438 /*  xmlSaveFile("autoplugger.gst", gst_xml_write(GST_ELEMENT_SCHED(autoplugger)->parent)); */
439
440   GST_INFO(GST_CAT_AUTOPLUG, "autoplugger_cache_empty finished");
441 }
442
443 static void
444 gst_autoplugger_type_find_have_type(GstElement *element, GstCaps *caps, GstAutoplugger *autoplugger) 
445 {
446   GST_INFO(GST_CAT_AUTOPLUG, "typefind claims to have a type: %s",gst_caps_get_mime(caps));
447
448 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
449
450   autoplugger->paused++;
451   if (autoplugger->paused == 1)
452     /* try to PAUSE the whole thing */
453     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED);
454
455   /* first unlink the typefind and shut it down */
456   GST_DEBUG(GST_CAT_AUTOPLUG, "unlinking typefind from the cache");
457   gst_pad_unlink(autoplugger->cache_srcpad,autoplugger->typefind_sinkpad);
458   gst_bin_remove(GST_BIN(autoplugger),autoplugger->typefind);
459
460   /* FIXME FIXME now we'd compare caps and see if we need to autoplug something in the middle, but for  */
461   /* now we're going to just relink where we left off */
462   /* FIXME FIXME FIXME!!!: this should really be done in the caps failure!!! */
463 /*
464   if (!autoplugger->autoplug) {
465     autoplugger->autoplug = gst_autoplug_factory_make("static");
466   }
467   autoplugger->autobin = gst_autoplug_to_caps(autoplugger->autoplug,
468       caps,autoplugger->sinktemplatecaps,NULL);
469   g_return_if_fail(autoplugger->autobin != NULL);
470   gst_bin_add(GST_BIN(autoplugger),autoplugger->autobin);
471
472 *  * re-attach the srcpad's original peer to the cache *
473 *  GST_DEBUG(GST_CAT_AUTOPLUG, "relinking the cache to the downstream peer"); *
474 *  gst_pad_link(autoplugger->cache_srcpad,autoplugger->srcpadpeer); *
475
476   * attach the autoplugged bin *
477   GST_DEBUG(GST_CAT_AUTOPLUG, "attaching the autoplugged bin between cache and downstream peer");
478   gst_pad_link(autoplugger->cache_srcpad,gst_element_get_pad(autoplugger->autobin,"sink"));
479   gst_pad_link(gst_element_get_pad(autoplugger->autobin,"src_00"),autoplugger->srcpadpeer);
480 */
481
482   /* FIXME set the caps on the new link
483    *  GST_DEBUG(GST_CAT_AUTOPLUG,"forcing caps on the typefound pad");
484    * gst_pad_set_caps(autoplugger->cache_srcpad,caps);
485    * reattach the original outside srcpad
486    */ 
487    GST_DEBUG(GST_CAT_AUTOPLUG,"re-attaching downstream peer to autoplugcache");
488   gst_pad_link(autoplugger->cache_srcpad,autoplugger->srcpadpeer);
489
490   /* now reset the autoplugcache */
491   GST_DEBUG(GST_CAT_AUTOPLUG, "resetting the cache to send first buffer(s) again");
492   g_object_set(G_OBJECT(autoplugger->cache),"reset",TRUE,NULL);
493
494   /* attach the cache_empty handler */
495   /* FIXME this is the wrong place, it shouldn't be done until we get successful caps nego! */
496   g_signal_connect (G_OBJECT(autoplugger->cache),"cache_empty",
497                      G_CALLBACK (gst_autoplugger_cache_empty), autoplugger);
498
499   autoplugger->paused--;
500   if (autoplugger->paused == 0)
501     /* try to PLAY the whole thing */
502     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
503
504   GST_INFO(GST_CAT_AUTOPLUG, "typefind_have_type finished");
505 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
506 }
507
508 static void
509 gst_autoplugger_cache_first_buffer(GstElement *element,GstBuffer *buf,GstAutoplugger *autoplugger)
510 {
511   GST_INFO(GST_CAT_AUTOPLUG, "have first buffer through cache");
512   autoplugger->cache_first_buffer = TRUE;
513
514   /* if there are no established caps, worry */
515   if (!autoplugger->sinkcaps) {
516     GST_INFO(GST_CAT_AUTOPLUG, "have no caps for the buffer, Danger Will Robinson!");
517
518 if (autoplugger->disable_nocaps) {
519   GST_DEBUG(GST_CAT_AUTOPLUG, "not dealing with lack of caps this time");
520   return;
521 }
522
523 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
524
525   autoplugger->paused++;
526   if (autoplugger->paused == 1)
527     /* try to PAUSE the whole thing */
528     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED);
529
530     /* detach the srcpad */
531     GST_DEBUG(GST_CAT_AUTOPLUG, "unlinking cache from its downstream peer");
532     autoplugger->srcpadpeer = GST_PAD(GST_PAD_PEER(autoplugger->cache_srcpad));
533     gst_pad_unlink(autoplugger->cache_srcpad,autoplugger->srcpadpeer);
534
535     /* instantiate the typefind and set up the signal handlers */
536     if (!autoplugger->typefind) {
537       GST_DEBUG(GST_CAT_AUTOPLUG, "creating typefind and setting signal handler");
538       autoplugger->typefind = gst_element_factory_make("typefind","unnamed_type_find");
539       autoplugger->typefind_sinkpad = gst_element_get_pad(autoplugger->typefind,"sink");
540       g_signal_connect (G_OBJECT(autoplugger->typefind),"have_type",
541                          G_CALLBACK (gst_autoplugger_type_find_have_type), autoplugger);
542     }
543     /* add it to self and attach it */
544     GST_DEBUG(GST_CAT_AUTOPLUG, "adding typefind to self and linking to cache");
545     gst_bin_add(GST_BIN(autoplugger),autoplugger->typefind);
546     gst_pad_link(autoplugger->cache_srcpad,autoplugger->typefind_sinkpad);
547
548     /* bring the typefind into playing state */
549     GST_DEBUG(GST_CAT_AUTOPLUG, "setting typefind state to PLAYING");
550     gst_element_set_state(autoplugger->cache,GST_STATE_PLAYING);
551
552   autoplugger->paused--;
553   if (autoplugger->paused == 0)
554     /* try to PLAY the whole thing */
555     gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING);
556
557     GST_INFO(GST_CAT_AUTOPLUG,"here we go into nothingness, hoping the typefind will return us to safety");
558 gst_scheduler_show(GST_ELEMENT_SCHED(autoplugger));
559   } else {
560 /*    * attach the cache_empty handler, since the cache simply isn't needed *
561  *    g_signal_connect (G_OBJECT(autoplugger->cache),"cache_empty",
562  *                       gst_autoplugger_cache_empty,autoplugger);
563  */ 
564   }
565 }
566
567 static void
568 gst_autoplugger_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
569 {
570   GstAutoplugger *autoplugger;
571
572   autoplugger = GST_AUTOPLUGGER (object);
573
574   switch (prop_id) {
575     default:
576       break;
577   }
578 }
579
580 static void
581 gst_autoplugger_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
582 {
583   GstAutoplugger *autoplugger;
584
585   autoplugger = GST_AUTOPLUGGER (object);
586
587   switch (prop_id) {
588     default:
589       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
590       break;
591   }
592 }
593
594 static gboolean
595 plugin_init (GModule *module, GstPlugin *plugin)
596 {
597   GstElementFactory *factory;
598
599   factory = gst_element_factory_new ("autoplugger", GST_TYPE_AUTOPLUGGER,
600                                     &gst_autoplugger_details);
601   g_return_val_if_fail (factory != NULL, FALSE);
602
603   gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
604
605   return TRUE;
606 }
607
608 GstPluginDesc plugin_desc = {
609   GST_VERSION_MAJOR,
610   GST_VERSION_MINOR,
611   "autoplugger",
612   plugin_init
613 };
614