+ _this->m_pump.send(Message(2));
+}
+
+gboolean eServiceMP3::gstGhostpadSinkEvent(GstPad * pad, GstEvent * event)
+{
+// eDebug("eServiceMP3::gstGhostpadSinkEvent %s", gst_structure_get_name (event->structure));
+
+// eServiceMP3 *_this = (eServiceMP3*) (gst_pad_get_parent (pad));
+ eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance");
+ gboolean ret;
+ GstFormat format;
+
+ if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && event->structure && strcmp (gst_structure_get_name (event->structure), "subtitleoverlay-flush-subtitle") == 0)
+ {
+ eDebug ("Custom subtitle flush event");
+// GST_SUBTITLE_OVERLAY_LOCK (self);
+// self->subtitle_flush = TRUE;
+// self->subtitle_error = FALSE;
+// if (self->subtitle_block_pad)
+// gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE,
+// _pad_blocked_cb, gst_object_ref (self),
+// (GDestroyNotify) gst_object_unref);
+// if (self->video_block_pad)
+// gst_pad_set_blocked_async_full (self->video_block_pad, TRUE,
+// _pad_blocked_cb, gst_object_ref (self),
+// (GDestroyNotify) gst_object_unref);
+// GST_SUBTITLE_OVERLAY_UNLOCK (self);
+//
+ gst_event_unref (event);
+ event = NULL;
+ ret = TRUE;
+ goto out;
+ } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT)
+ {
+ gst_event_parse_new_segment_full (event, NULL, NULL, NULL, &format, NULL, NULL, NULL);
+ if (_this->m_gst_subtitle_segment.format != GST_FORMAT_UNDEFINED && _this->m_gst_subtitle_segment.format != format)
+ {
+ eDebug("Subtitle segment format changed: %s -> %s", gst_format_get_name(_this->m_gst_subtitle_segment.format), gst_format_get_name(format));
+ gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED);
+ }
+ }
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_STOP:
+ eDebug("Resetting subtitle segment because of flush-stop");
+ gst_segment_init (&_this->m_gst_subtitle_segment, GST_FORMAT_UNDEFINED);
+ /* fall through */
+ case GST_EVENT_FLUSH_START:
+ case GST_EVENT_NEWSEGMENT:
+ case GST_EVENT_EOS:
+// eDebug("GST_EVENT_FLUSH_START GST_EVENT_NEWSEGMENT GST_EVENT_EOS");
+ /* Add our event marker to make sure no events from here go ever outside
+ * the element, they're only interesting for our internal elements */
+// event =
+// GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST
+// (event)));
+// if (!event->structure) {
+// event->structure =
+// gst_structure_id_empty_new (_subtitle_overlay_event_marker_id);
+// gst_structure_set_parent_refcount (event->structure,
+// &event->mini_object.refcount);
+// }
+// gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id,
+// G_TYPE_BOOLEAN, TRUE, NULL);
+ break;
+ default:
+ eDebug("GST_EVENT_TYPE other: %i", GST_EVENT_TYPE (event));
+ break;
+ }
+
+ ret = _this->m_ghost_pad_subtitle_sink_event (pad, gst_event_ref (event));
+// eDebug("original EVENTFUNC returned %i", ret);
+
+ if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
+ gboolean update;
+ gdouble rate, applied_rate;
+ gint64 start, stop, position;
+
+ GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT,
+ event->structure);
+ gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
+ &format, &start, &stop, &position);
+
+ GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT,
+ &_this->m_gst_subtitle_segment);
+ if (_this->m_gst_subtitle_segment.format != format) {
+ GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s",
+ gst_format_get_name (_this->m_gst_subtitle_segment.format),
+ gst_format_get_name (format));
+ gst_segment_init (&_this->m_gst_subtitle_segment, format);
+ }
+
+ gst_segment_set_newsegment_full (&_this->m_gst_subtitle_segment, update, rate,
+ applied_rate, format, start, stop, position);
+ GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT,
+ &_this->m_gst_subtitle_segment);
+ }
+ gst_event_unref (event);
+//
+out:
+// gst_object_unref (_this);
+ return ret;
+}
+
+GstCaps* eServiceMP3::gstGhostpadGetCAPS(GstPad * pad)
+{
+// eDebug("eServiceMP3::gstGhostpadGetCAPS");
+ return gst_static_pad_template_get_caps(&subsinktemplate);
+}
+
+gboolean eServiceMP3::gstGhostpadAcceptCAPS(GstPad * pad, GstCaps * caps)
+{
+ GstCaps *templ_caps = gst_static_pad_template_get_caps (&subsinktemplate);
+ gboolean ret = gst_caps_can_intersect (templ_caps, caps);
+
+// eDebug("gstGhostpadAcceptCAPS templ=%s, given=%s ret=%i", gst_caps_to_string(templ_caps), gst_caps_to_string(caps), ret);
+ gst_caps_unref (templ_caps);
+
+ return ret;
+}
+
+void eServiceMP3::gstGhostpadLink(gpointer user_data, GstCaps * caps)
+{
+ GstStructure *s;
+ GstPad *sinkpad;
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+
+ // FIXME: Need to cache events from the ghostpad and pass them forward
+ // now... and keep track of the segment and pass newsegment events
+ // downstream.
+ s = gst_caps_get_structure (caps, 0);
+
+ GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink");
+ GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink");
+ GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder");
+
+ gst_ghost_pad_set_target(GST_GHOST_PAD(ghostpad), NULL);
+ gst_element_unlink(dvdsubdec, appsink);
+ int ret = -1;
+
+ if ( gst_structure_has_name (s, "video/x-dvd-subpicture") && dvdsubdec )
+ {
+ sinkpad = gst_element_get_static_pad (dvdsubdec, "sink");
+ ret = gst_element_link_pads (dvdsubdec, "src", appsink, "sink");
+// eDebug("gstGhostpadLink:: dvdsubdec+appsink = %i", ret);
+ }
+ else
+ {
+ sinkpad = gst_element_get_static_pad (appsink, "sink");
+// eDebug("gstGhostpadLink:: appsink");
+ }
+
+ gst_ghost_pad_set_target (GST_GHOST_PAD(ghostpad), sinkpad);
+}
+
+GstFlowReturn eServiceMP3::gstGhostpadBufferAlloc(GstPad *pad, guint64 offset, guint size, GstCaps *caps, GstBuffer **buf)
+{
+ eServiceMP3 *_this = (eServiceMP3*) g_object_get_data (G_OBJECT (pad), "application-instance");
+
+// eDebug("eServiceMP3::gstGhostpadBufferAlloc prevcaps=%s newcaps=%s", gst_caps_to_string(_this->m_gst_prev_subtitle_caps), gst_caps_to_string(caps));
+ if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (_this->m_gst_prev_subtitle_caps, caps))
+ gstGhostpadLink (_this, caps);
+
+ return _this->m_ghost_pad_buffer_alloc (pad, offset, size, caps, buf);
+}
+
+void eServiceMP3::gstGhostpadHasCAPS(GstPad *pad, GParamSpec * unused, gpointer user_data)
+{
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+
+ gst_object_ref (pad);
+
+ _this->m_pump.send(Message(3, pad));
+}
+
+// after messagepump
+void eServiceMP3::gstGhostpadHasCAPS_synced(GstPad *pad)
+{
+ GstCaps *caps;
+
+ g_object_get (G_OBJECT (pad), "caps", &caps, NULL);
+
+// eDebug("gstGhostpadHasCAPS:: signal::caps = %s", gst_caps_to_string(caps));
+
+ if (caps)
+ {
+ subtitleStream subs;
+
+// eDebug("gstGhostpadHasCAPS_synced %p %d", pad, m_subtitleStreams.size());
+
+ if (!m_subtitleStreams.empty())
+ subs = m_subtitleStreams[m_currentSubtitleStream];
+ else {
+ subs.type = stUnknown;
+ subs.pad = pad;
+ }
+
+ if ( subs.type == stUnknown )
+ {
+ GstTagList *tags;
+// eDebug("gstGhostpadHasCAPS::m_subtitleStreams[%i].type == stUnknown...", m_currentSubtitleStream);
+
+ gchar *g_lang;
+ g_signal_emit_by_name (m_gst_playbin, "get-text-tags", m_currentSubtitleStream, &tags);
+
+ g_lang = g_strdup_printf ("und");
+ if ( tags && gst_is_tag_list(tags) )
+ gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
+
+ subs.language_code = std::string(g_lang);
+ GstPad *ghostpad = gst_element_get_static_pad(m_gst_subtitlebin, "sink");
+ subs.type = getSubtitleType(ghostpad);
+
+ if (!m_subtitleStreams.empty())
+ m_subtitleStreams[m_currentSubtitleStream] = subs;
+ else
+ m_subtitleStreams.push_back(subs);
+
+ g_free (g_lang);
+ }
+
+// eDebug("gstGhostpadHasCAPS:: m_gst_prev_subtitle_caps=%s equal=%i",gst_caps_to_string(m_gst_prev_subtitle_caps),gst_caps_is_equal(m_gst_prev_subtitle_caps, caps));
+
+ if (!GST_PAD_CAPS (pad) || !gst_caps_is_equal (m_gst_prev_subtitle_caps, caps))
+ gstGhostpadLink(this, caps);
+
+ m_gst_prev_subtitle_caps = gst_caps_copy(caps);
+
+ gst_caps_unref (caps);
+ }
+
+ gst_object_unref (pad);