diff --git a/gst/autoplug/gstautoplugcache.c b/gst/autoplug/gstautoplugcache.c index cd2c1a6bd5..9af4172bf3 100644 --- a/gst/autoplug/gstautoplugcache.c +++ b/gst/autoplug/gstautoplugcache.c @@ -49,6 +49,8 @@ struct _GstAutoplugCache { GstPad *sinkpad, *srcpad; + gboolean caps_proxy; + GList *cache; GList *cache_start; gint buffer_count; @@ -59,12 +61,14 @@ struct _GstAutoplugCache { struct _GstAutoplugCacheClass { GstElementClass parent_class; + void (*first_buffer) (GstElement *element, GstBuffer *buf); void (*cache_empty) (GstElement *element); }; /* Cache signals and args */ enum { + FIRST_BUFFER, CACHE_EMPTY, LAST_SIGNAL }; @@ -72,6 +76,7 @@ enum { enum { ARG_0, ARG_BUFFER_COUNT, + ARG_CAPS_PROXY, ARG_RESET }; @@ -123,6 +128,11 @@ gst_autoplugcache_class_init (GstAutoplugCacheClass *klass) parent_class = gtk_type_class (GST_TYPE_ELEMENT); + gst_autoplugcache_signals[FIRST_BUFFER] = + gtk_signal_new ("first_buffer", GTK_RUN_LAST, gtkobject_class->type, + GTK_SIGNAL_OFFSET (GstAutoplugCacheClass, first_buffer), + gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, + GTK_TYPE_POINTER); gst_autoplugcache_signals[CACHE_EMPTY] = gtk_signal_new ("cache_empty", GTK_RUN_LAST, gtkobject_class->type, GTK_SIGNAL_OFFSET (GstAutoplugCacheClass, cache_empty), @@ -131,6 +141,8 @@ gst_autoplugcache_class_init (GstAutoplugCacheClass *klass) gtk_object_add_arg_type ("GstAutoplugCache::buffer_count", GTK_TYPE_INT, GTK_ARG_READABLE, ARG_BUFFER_COUNT); + gtk_object_add_arg_type ("GstAutoplugCache::caps_proxy", GTK_TYPE_BOOL, + GTK_ARG_READWRITE, ARG_CAPS_PROXY); gtk_object_add_arg_type ("GstAutoplugCache::reset", GTK_TYPE_BOOL, GTK_ARG_WRITABLE, ARG_RESET); @@ -146,13 +158,15 @@ gst_autoplugcache_init (GstAutoplugCache *cache) gst_element_set_loop_function(GST_ELEMENT(cache), GST_DEBUG_FUNCPTR(gst_autoplugcache_loop)); cache->sinkpad = gst_pad_new ("sink", GST_PAD_SINK); - gst_pad_set_negotiate_function (cache->sinkpad, gst_autoplugcache_nego_sink); +// gst_pad_set_negotiate_function (cache->sinkpad, gst_autoplugcache_nego_sink); gst_element_add_pad (GST_ELEMENT(cache), cache->sinkpad); cache->srcpad = gst_pad_new ("src", GST_PAD_SRC); - gst_pad_set_negotiate_function (cache->sinkpad, gst_autoplugcache_nego_src); +// gst_pad_set_negotiate_function (cache->srcpad, gst_autoplugcache_nego_src); gst_element_add_pad (GST_ELEMENT(cache), cache->srcpad); + cache->caps_proxy = FALSE; + // provide a zero basis for the cache cache->cache = g_list_prepend(NULL, NULL); cache->cache_start = cache->cache; @@ -196,6 +210,8 @@ gst_autoplugcache_loop (GstElement *element) // set the current_playout pointer cache->current_playout = cache->cache; + gtk_signal_emit (GTK_OBJECT(cache), gst_autoplugcache_signals[FIRST_BUFFER], buf); + // send the buffer on its way gst_pad_push (cache->srcpad, buf); } @@ -275,6 +291,16 @@ gst_autoplugcache_set_arg (GtkObject *object, GtkArg *arg, guint id) cache = GST_AUTOPLUGCACHE (object); switch (id) { + case ARG_CAPS_PROXY: + cache->caps_proxy = GTK_VALUE_BOOL(*arg); + if (cache->caps_proxy) { + gst_pad_set_negotiate_function (cache->sinkpad, gst_autoplugcache_nego_sink); + gst_pad_set_negotiate_function (cache->srcpad, gst_autoplugcache_nego_src); + } else { + gst_pad_set_negotiate_function (cache->sinkpad, NULL); + gst_pad_set_negotiate_function (cache->srcpad, NULL); + } + break; case ARG_RESET: // no idea why anyone would set this to FALSE, but just in case ;-) if (GTK_VALUE_BOOL(*arg)) { @@ -301,6 +327,8 @@ gst_autoplugcache_get_arg (GtkObject *object, GtkArg *arg, guint id) case ARG_BUFFER_COUNT: GTK_VALUE_INT(*arg) = cache->buffer_count; break; + case ARG_CAPS_PROXY: + GTK_VALUE_BOOL(*arg) = cache->caps_proxy; default: arg->type = GTK_TYPE_INVALID; break; diff --git a/gst/autoplug/gstautoplugger.c b/gst/autoplug/gstautoplugger.c index 53145992e9..eab5c51907 100644 --- a/gst/autoplug/gstautoplugger.c +++ b/gst/autoplug/gstautoplugger.c @@ -47,9 +47,14 @@ typedef struct _GstAutopluggerClass GstAutopluggerClass; struct _GstAutoplugger { GstBin bin; - GstGhostPad *srcghost, *sinkghost; + GstElement *cache; + GstPad *cache_sinkpad, *cache_srcpad; - GstElement *cache, *typefind; + GstElement *typefind; + GstPad *typefind_sinkpad; + + GstPad *sinkpadpeer, *srcpadpeer; + GstCaps *sinkcaps, *srccaps; }; struct _GstAutopluggerClass { @@ -67,7 +72,7 @@ enum { }; -static void gst_autoplugger_class_init (GstAutopluggerClass *klass); +static void gst_autoplugger_class_init (GstAutopluggerClass *klass); static void gst_autoplugger_init (GstAutoplugger *queue); static void gst_autoplugger_set_arg (GtkObject *object, GtkArg *arg, guint id); @@ -79,6 +84,12 @@ static void gst_autoplugger_get_arg (GtkObject *object, GtkArg *arg, guint id static void gst_autoplugger_external_sink_caps_changed (GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger); static void gst_autoplugger_external_src_caps_changed (GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger); +static void gst_autoplugger_external_sink_connected (GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger); +static void gst_autoplugger_external_src_connected (GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger); + +static void gst_autoplugger_typefind_have_type (GstElement *element, GstCaps *caps, GstAutoplugger *autoplugger); +static void gst_autoplugger_cache_first_buffer (GstElement *element,GstBuffer *buf,GstAutoplugger *autoplugger); + static GstElementClass *parent_class = NULL; //static guint gst_autoplugger_signals[LAST_SIGNAL] = { 0 }; @@ -137,30 +148,36 @@ gst_autoplugger_class_init (GstAutopluggerClass *klass) static void gst_autoplugger_init (GstAutoplugger *autoplugger) { - GstPad *srcpad, *sinkpad; - // create the autoplugger cache, which is the fundamental unit of the autopluggerger // FIXME we need to find a way to set element's name before _init // FIXME ... so we can name the subelements uniquely autoplugger->cache = gst_elementfactory_make("autoplugcache", "unnamed_autoplugcache"); g_return_if_fail (autoplugger->cache != NULL); + // attach signals to the cache + gtk_signal_connect (GTK_OBJECT (autoplugger->cache), "first_buffer", + GTK_SIGNAL_FUNC (gst_autoplugger_cache_first_buffer), autoplugger); + // add the cache to self gst_bin_add (GST_BIN(autoplugger), autoplugger->cache); // get the cache's pads so we can attach stuff to them - sinkpad = gst_element_get_pad (autoplugger->cache, "sink"); - srcpad = gst_element_get_pad (autoplugger->cache, "src"); + autoplugger->cache_sinkpad = gst_element_get_pad (autoplugger->cache, "sink"); + autoplugger->cache_srcpad = gst_element_get_pad (autoplugger->cache, "src"); // attach handlers to the typefind pads - gtk_signal_connect (GTK_OBJECT (sinkpad), "caps_changed", + gtk_signal_connect (GTK_OBJECT (autoplugger->cache_sinkpad), "caps_changed", GTK_SIGNAL_FUNC (gst_autoplugger_external_sink_caps_changed), autoplugger); - gtk_signal_connect (GTK_OBJECT (srcpad), "caps_changed", + gtk_signal_connect (GTK_OBJECT (autoplugger->cache_srcpad), "caps_changed", GTK_SIGNAL_FUNC (gst_autoplugger_external_src_caps_changed), autoplugger); + gtk_signal_connect (GTK_OBJECT (autoplugger->cache_sinkpad), "connected", + GTK_SIGNAL_FUNC (gst_autoplugger_external_sink_connected), autoplugger); + gtk_signal_connect (GTK_OBJECT (autoplugger->cache_srcpad), "connected", + GTK_SIGNAL_FUNC (gst_autoplugger_external_src_connected), autoplugger); // ghost both of these pads to the outside world - gst_element_add_ghost_pad (GST_ELEMENT(autoplugger), sinkpad, "sink"); - gst_element_add_ghost_pad (GST_ELEMENT(autoplugger), srcpad, "src"); + gst_element_add_ghost_pad (GST_ELEMENT(autoplugger), autoplugger->cache_sinkpad, "sink"); + gst_element_add_ghost_pad (GST_ELEMENT(autoplugger), autoplugger->cache_srcpad, "src"); } @@ -168,12 +185,146 @@ static void gst_autoplugger_external_sink_caps_changed(GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger) { GST_INFO(GST_CAT_AUTOPLUG, "have cache:sink caps of %s\n",gst_caps_get_mime(caps)); + autoplugger->sinkcaps = caps; } static void gst_autoplugger_external_src_caps_changed(GstPad *pad, GstCaps *caps, GstAutoplugger *autoplugger) { GST_INFO(GST_CAT_AUTOPLUG, "have cache:src caps of %s\n",gst_caps_get_mime(caps)); + autoplugger->srccaps = caps; +} + +static void +gst_autoplugger_external_sink_connected(GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger) +{ + GstPadTemplate *peertemplate; + GstCaps *peercaps, *peertemplatecaps; + + GST_INFO(GST_CAT_AUTOPLUG, "have cache:sink connected\n"); + autoplugger->sinkpadpeer = peerpad; + + if (autoplugger->sinkpadpeer) { + peercaps = GST_PAD_CAPS(autoplugger->sinkpadpeer); + if (peercaps) + GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer: %s\n", + gst_caps_get_mime(peercaps)); + peertemplate = GST_PAD_PADTEMPLATE(autoplugger->sinkpadpeer); + if (peertemplate) { + peertemplatecaps = GST_PADTEMPLATE_CAPS(peertemplate); + if (peertemplatecaps) { + GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer's padtemplate %s\n", + gst_caps_get_mime(peertemplatecaps)); + GST_DEBUG(GST_CAT_AUTOPLUG, "turning on caps nego proxying in cache\n"); + gtk_object_set(GTK_OBJECT(autoplugger->cache),"caps_proxy",TRUE,NULL); + } + } + } +} + +static void +gst_autoplugger_external_src_connected(GstPad *pad, GstPad *peerpad, GstAutoplugger *autoplugger) +{ + GstPadTemplate *peertemplate; + GstCaps *peercaps, *peertemplatecaps; + + GST_INFO(GST_CAT_AUTOPLUG, "have cache:src connected\n"); + autoplugger->srcpadpeer = peerpad; + + if (autoplugger->srcpadpeer) { + peercaps = GST_PAD_CAPS(autoplugger->srcpadpeer); + if (peercaps) + GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer: %s\n", + gst_caps_get_mime(peercaps)); + peertemplate = GST_PAD_PADTEMPLATE(autoplugger->srcpadpeer); + if (peertemplate) { + peertemplatecaps = GST_PADTEMPLATE_CAPS(peertemplate); + if (peertemplatecaps) { + GST_INFO(GST_CAT_AUTOPLUG, "there are some caps on this pad's peer's padtemplate %s\n", + gst_caps_get_mime(peertemplatecaps)); + GST_DEBUG(GST_CAT_AUTOPLUG, "turning on caps nego proxying in cache\n"); + gtk_object_set(GTK_OBJECT(autoplugger->cache),"caps_proxy",TRUE,NULL); + } + } + } +} + +static void +gst_autoplugger_typefind_have_type(GstElement *element, GstCaps *caps, GstAutoplugger *autoplugger) +{ + GST_INFO(GST_CAT_AUTOPLUG, "typefind claims to have a type: %s",gst_caps_get_mime(caps)); + +gst_schedule_show(GST_ELEMENT_SCHED(autoplugger)); + +// try to PAUSE the whole thing +gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED); + + // first disconnect the typefind and shut it down + GST_DEBUG(GST_CAT_AUTOPLUG, "disconnecting typefind from the cache\n"); + gst_element_disconnect(autoplugger->cache,"src",autoplugger->typefind,"sink"); + gst_bin_remove(GST_BIN(autoplugger),autoplugger->typefind); + + // FIXME FIXME now we'd compare caps and see if we need to autoplug something in the middle, but for + // now we're going to just reconnect where we left off + + // re-attach the srcpad's original peer to the cache + GST_DEBUG(GST_CAT_AUTOPLUG, "reconnecting the cache to the downstream peer\n"); + gst_pad_connect(autoplugger->cache_srcpad,autoplugger->srcpadpeer); + + // now reset the autoplugcache + GST_DEBUG(GST_CAT_AUTOPLUG, "resetting the cache to send first buffer(s) again\n"); + gtk_object_set(GTK_OBJECT(autoplugger->cache),"reset",TRUE,NULL); + +// try to PLAY the whole thing +gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING); + + GST_INFO(GST_CAT_AUTOPLUG, "typefind_have_type finished"); +gst_schedule_show(GST_ELEMENT_SCHED(autoplugger)); +} + +static void +gst_autoplugger_cache_first_buffer(GstElement *element,GstBuffer *buf,GstAutoplugger *autoplugger) +{ + GST_INFO(GST_CAT_AUTOPLUG, "have first buffer through cache"); + + // if there are no established caps, worry + if (!autoplugger->sinkcaps && !autoplugger->srccaps) { + GST_INFO(GST_CAT_AUTOPLUG, "have no caps for the buffer, Danger Will Robinson!"); + +gst_schedule_show(GST_ELEMENT_SCHED(autoplugger)); + +// try to PAUSE the whole thing +gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PAUSED); + + // detach the srcpad + GST_DEBUG(GST_CAT_AUTOPLUG, "disconnecting cache from its downstream peer\n"); + gst_pad_disconnect(autoplugger->cache_srcpad,autoplugger->srcpadpeer); + + // instantiate the typefind and set up the signal handlers + if (!autoplugger->typefind) { + GST_DEBUG(GST_CAT_AUTOPLUG, "creating typefind and setting signal handler\n"); + autoplugger->typefind = gst_elementfactory_make("typefind","unnamed_typefind"); + autoplugger->typefind_sinkpad = gst_element_get_pad(autoplugger->typefind,"sink"); + gtk_signal_connect(GTK_OBJECT(autoplugger->typefind),"have_type", + GTK_SIGNAL_FUNC (gst_autoplugger_typefind_have_type), autoplugger); + } + // add it to self and attach it + GST_DEBUG(GST_CAT_AUTOPLUG, "adding typefind to self and connecting to cache\n"); + gst_bin_add(GST_BIN(autoplugger),autoplugger->typefind); + gst_pad_connect(autoplugger->cache_srcpad,autoplugger->typefind_sinkpad); + + // bring the typefind into playing state + GST_DEBUG(GST_CAT_AUTOPLUG, "setting typefind state to PLAYING\n"); + gst_element_set_state(autoplugger->cache,GST_STATE_PLAYING); + +// try to PLAY the whole thing +gst_element_set_state(GST_ELEMENT_SCHED(autoplugger)->parent,GST_STATE_PLAYING); + + GST_INFO(GST_CAT_AUTOPLUG,"here we go into nothingness, hoping the typefind will return us to safety"); +gst_schedule_show(GST_ELEMENT_SCHED(autoplugger)); + } else { + GST_INFO(GST_CAT_AUTOPLUG, "caps are set, nothing happening here, move along"); + } } static void diff --git a/gst/cothreads.c b/gst/cothreads.c index bccfa4051e..2a5eb745e0 100644 --- a/gst/cothreads.c +++ b/gst/cothreads.c @@ -108,7 +108,7 @@ cothread_create (cothread_context *ctx) GST_DEBUG (0,"pthread_self() %ld\n",pthread_self()); //if (0) { - if (pthread_self() == 0) { + if (pthread_self() == 0) { // FIXME uh, what does this test really do? s = (cothread_state *)malloc(sizeof(int) * COTHREAD_STACKSIZE); GST_DEBUG (0,"new stack (case 1) at %p\n",s); } else { diff --git a/gst/gstbin.h b/gst/gstbin.h index f947ae8b9d..51489c5715 100644 --- a/gst/gstbin.h +++ b/gst/gstbin.h @@ -47,6 +47,8 @@ extern GstElementDetails gst_bin_details; typedef enum { /* this bin is a manager of child elements, i.e. a pipeline or thread */ GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST, + /* this bin is actually a meta-bin, and may need to be scheduled */ + GST_BIN_SELF_SCHEDULABLE, /* we prefer to have cothreads when its an option, over chain-based */ GST_BIN_FLAG_PREFER_COTHREADS, diff --git a/gst/gstelement.c b/gst/gstelement.c index 6a1239d667..a752951d65 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -857,14 +857,16 @@ gst_element_change_state (GstElement *element) if ((GST_STATE_TRANSITION(element) == GST_STATE_READY_TO_PLAYING) || (GST_STATE_TRANSITION(element) == GST_STATE_PAUSED_TO_PLAYING)) { + g_return_val_if_fail(GST_ELEMENT_SCHED(element), GST_STATE_FAILURE); if (GST_ELEMENT_PARENT(element)) - fprintf(stderr,"READY->PLAYING: element \"%s\" has parent \"%s\" and sched %p\n", + fprintf(stderr,"PAUSED->PLAYING: element \"%s\" has parent \"%s\" and sched %p\n", GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(GST_ELEMENT_PARENT(element)),GST_ELEMENT_SCHED(element)); GST_SCHEDULE_ENABLE_ELEMENT (element->sched,element); } else if ((GST_STATE_TRANSITION(element) == GST_STATE_PLAYING_TO_READY) || - (GST_STATE_TRANSITION(element) == GST_STATE_PLAYING_TO_READY)) + (GST_STATE_TRANSITION(element) == GST_STATE_PLAYING_TO_PAUSED)) { GST_SCHEDULE_DISABLE_ELEMENT (element->sched,element); + } GST_STATE (element) = GST_STATE_PENDING (element); GST_STATE_PENDING (element) = GST_STATE_NONE_PENDING; @@ -876,7 +878,7 @@ GST_ELEMENT_NAME(element),GST_ELEMENT_NAME(GST_ELEMENT_PARENT(element)),GST_ELEM // unlocks, then emits this. gtk_signal_emit (GTK_OBJECT (element), gst_element_signals[STATE_CHANGE], GST_STATE (element)); - return TRUE; + return GST_STATE_SUCCESS; } static void diff --git a/gst/gstobject.c b/gst/gstobject.c index 97f16efd7e..59cabd74bd 100644 --- a/gst/gstobject.c +++ b/gst/gstobject.c @@ -158,7 +158,8 @@ gst_object_ref (GstObject *object) { g_return_val_if_fail (GST_IS_OBJECT (object), NULL); - GST_DEBUG (GST_CAT_REFCOUNTING, "ref\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "ref '%s' %d->%d\n",GST_OBJECT_NAME(object), + GTK_OBJECT(object)->ref_count,GTK_OBJECT(object)->ref_count+1); gtk_object_ref (GTK_OBJECT (object)); @@ -178,7 +179,8 @@ gst_object_unref (GstObject *object) { g_return_if_fail (GST_IS_OBJECT (object)); - GST_DEBUG (GST_CAT_REFCOUNTING, "unref\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "unref '%s' %d->%d\n",GST_OBJECT_NAME(object), + GTK_OBJECT(object)->ref_count,GTK_OBJECT(object)->ref_count-1); gtk_object_unref (GTK_OBJECT (object)); } @@ -198,7 +200,7 @@ gst_object_sink (GstObject *object) g_return_if_fail (object != NULL); g_return_if_fail (GST_IS_OBJECT (object)); - GST_DEBUG (GST_CAT_REFCOUNTING, "sink\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "sink '%s'\n",GST_OBJECT_NAME(object)); if (GST_OBJECT_FLOATING (object)) { GST_FLAG_UNSET (object, GST_FLOATING); @@ -212,7 +214,7 @@ gst_object_destroy (GstObject *object) g_return_if_fail (object != NULL); g_return_if_fail (GST_IS_OBJECT (object)); - GST_DEBUG (GST_CAT_REFCOUNTING, "destroy\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(object)); if (!GST_OBJECT_DESTROYED (object)) { /* need to hold a reference count around all class method @@ -227,7 +229,7 @@ gst_object_destroy (GstObject *object) static void gst_object_shutdown (GtkObject *object) { - GST_DEBUG (GST_CAT_REFCOUNTING, "shutdown\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "shutdown '%s'\n",GST_OBJECT_NAME(object)); GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED); parent_class->shutdown (GTK_OBJECT (object)); } @@ -236,7 +238,7 @@ gst_object_shutdown (GtkObject *object) static void gst_object_real_destroy (GtkObject *gtk_object) { - GST_DEBUG (GST_CAT_REFCOUNTING, "destroy\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(gtk_object)); GST_OBJECT_PARENT (gtk_object) = NULL; @@ -251,7 +253,7 @@ gst_object_finalize (GtkObject *gtk_object) object = GST_OBJECT (gtk_object); - GST_DEBUG (GST_CAT_REFCOUNTING, "finalize\n"); + GST_DEBUG (GST_CAT_REFCOUNTING, "finalize '%s'\n",GST_OBJECT_NAME(object)); if (object->name != NULL) g_free (object->name); diff --git a/gst/gstpad.c b/gst/gstpad.c index 0ac32566f0..41c39598b8 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -79,6 +79,7 @@ gst_pad_init (GstPad *pad) enum { REAL_SET_ACTIVE, REAL_CAPS_CHANGED, + REAL_CAPS_NEGO_FAILED, REAL_CONNECTED, REAL_DISCONNECTED, /* FILL ME */ @@ -147,6 +148,10 @@ gst_real_pad_class_init (GstRealPadClass *klass) GTK_SIGNAL_OFFSET (GstRealPadClass, caps_changed), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); + gst_real_pad_signals[REAL_CAPS_NEGO_FAILED] = + gtk_signal_new ("caps_nego_failed", GTK_RUN_LAST, gtkobject_class->type, + GTK_SIGNAL_OFFSET (GstRealPadClass, caps_nego_failed), + gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); gst_real_pad_signals[REAL_CONNECTED] = gtk_signal_new ("connected", GTK_RUN_LAST, gtkobject_class->type, GTK_SIGNAL_OFFSET (GstRealPadClass, connected), @@ -633,18 +638,6 @@ gst_pad_connect (GstPad *srcpad, GST_RPAD_PEER(realsrc) = realsink; GST_RPAD_PEER(realsink) = realsrc; - /* FIXME: set connected flag */ - - /* fire off a signal to each of the pads telling them that they've been connected */ - gtk_signal_emit(GTK_OBJECT(realsrc), gst_real_pad_signals[REAL_CONNECTED], realsink); - gtk_signal_emit(GTK_OBJECT(realsink), gst_real_pad_signals[REAL_CONNECTED], realsrc); - - // now tell the scheduler(s) - if (realsrc->sched) - GST_SCHEDULE_PAD_CONNECT (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); - else if (realsink->sched) - GST_SCHEDULE_PAD_CONNECT (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink); - if (GST_PAD_CAPS (srcpad)) { negotiated = gst_pad_renegotiate (srcpad); } @@ -661,6 +654,16 @@ gst_pad_connect (GstPad *srcpad, return FALSE; } + /* fire off a signal to each of the pads telling them that they've been connected */ + gtk_signal_emit(GTK_OBJECT(realsrc), gst_real_pad_signals[REAL_CONNECTED], realsink); + gtk_signal_emit(GTK_OBJECT(realsink), gst_real_pad_signals[REAL_CONNECTED], realsrc); + + // now tell the scheduler(s) + if (realsrc->sched) + GST_SCHEDULE_PAD_CONNECT (realsrc->sched, (GstPad *)realsrc, (GstPad *)realsink); + else if (realsink->sched) + GST_SCHEDULE_PAD_CONNECT (realsink->sched, (GstPad *)realsrc, (GstPad *)realsink); + GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s", GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); return TRUE; @@ -1272,6 +1275,13 @@ gst_pad_renegotiate (GstPad *pad) gst_real_pad_signals[REAL_CAPS_CHANGED],GST_PAD_CAPS(currentpad)); gtk_signal_emit (GTK_OBJECT(otherpad), gst_real_pad_signals[REAL_CAPS_CHANGED],GST_PAD_CAPS(otherpad)); + } else { + GST_DEBUG (GST_CAT_NEGOTIATION, "firing caps_nego_failed signal on %s:%s and %s:%s\n", + GST_DEBUG_PAD_NAME(currentpad),GST_DEBUG_PAD_NAME(otherpad)); + gtk_signal_emit (GTK_OBJECT(currentpad), + gst_real_pad_signals[REAL_CAPS_NEGO_FAILED]); + gtk_signal_emit (GTK_OBJECT(otherpad), + gst_real_pad_signals[REAL_CAPS_NEGO_FAILED]); } return result; diff --git a/gst/gstpad.h b/gst/gstpad.h index ee0306a826..2511d7cfd5 100644 --- a/gst/gstpad.h +++ b/gst/gstpad.h @@ -165,12 +165,13 @@ struct _GstRealPadClass { GstPadClass parent_class; /* signal callbacks */ - void (*set_active) (GstPad *pad, gboolean active); - void (*caps_changed) (GstPad *pad, GstCaps *newcaps); - void (*connected) (GstPad *pad, GstPad *peer); - void (*disconnected) (GstPad *pad, GstPad *peer); + void (*set_active) (GstPad *pad, gboolean active); + void (*caps_changed) (GstPad *pad, GstCaps *newcaps); + void (*caps_nego_failed) (GstPad *pad); + void (*connected) (GstPad *pad, GstPad *peer); + void (*disconnected) (GstPad *pad, GstPad *peer); - void (*eos) (GstPad *pad); + void (*eos) (GstPad *pad); }; struct _GstGhostPad { diff --git a/gst/gstscheduler.c b/gst/gstscheduler.c index 173dd19f8b..1652ebf015 100644 --- a/gst/gstscheduler.c +++ b/gst/gstscheduler.c @@ -1186,7 +1186,8 @@ gst_schedule_add_element (GstSchedule *sched, GstElement *element) GST_ELEMENT_SCHED(element) = sched; // only deal with elements after this point, not bins - if (GST_IS_BIN (element)) return; + // exception is made for Bin's that are schedulable, like the autoplugger + if (GST_IS_BIN (element) && !GST_FLAG_IS_SET(element, GST_BIN_SELF_SCHEDULABLE)) return; // first add it to the list of elements that are to be scheduled sched->elements = g_list_prepend (sched->elements, element); diff --git a/gst/gsttypefind.c b/gst/gsttypefind.c index 7a69baae90..4be2265728 100644 --- a/gst/gsttypefind.c +++ b/gst/gsttypefind.c @@ -183,8 +183,17 @@ gst_typefind_chain (GstPad *pad, GstBuffer *buf) GST_DEBUG (0,"found type :%d \"%s\" \"%s\"\n", caps->id, type->mime, gst_caps_get_name (caps)); typefind->caps = caps; + +{ + int oldstate = GST_STATE(typefind); gtk_signal_emit (GTK_OBJECT (typefind), gst_typefind_signals[HAVE_TYPE], typefind->caps); + if (GST_STATE(typefind) != oldstate) { + GST_DEBUG(0, "state changed during signal, aborting\n"); + cothread_switch(cothread_current_main()); + } +} + gst_pad_set_caps (pad, caps); goto end; }