+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);
+}
+
+GstFlowReturn eServiceMP3::gstGhostpadChainFunction(GstPad * pad, GstBuffer * buffer)
+{
+ GstFlowReturn ret = GST_FLOW_OK;
+
+ eServiceMP3 *_this = (eServiceMP3*)g_object_get_data (G_OBJECT (pad), "application-instance");
+
+// gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer);
+// gint64 duration_ns = GST_BUFFER_DURATION(buffer);
+ size_t len = GST_BUFFER_SIZE(buffer);
+
+ unsigned char line[len+1];
+ memcpy(line, GST_BUFFER_DATA(buffer), len);
+ line[len] = 0;
+// eDebug("gstGhostpadChainFunction buffer: '%s' caps: %s ", line, gst_caps_to_string(GST_BUFFER_CAPS(buffer)));
+
+ ret = _this->m_ghost_pad_chain_function(pad, buffer);
+// eDebug("original chain func returns %i", ret);
+ return ret;
+}
+
+
+// void eServiceMP3::gstCBsubtitleLink(GObject *obj, GParamSpec *pspec, gpointer user_data)
+// {
+//
+// eServiceMP3 *_this = (eServiceMP3*)user_data;
+// eDebug("gstCBsubtitleCAPS:: m_currentSubtitleStream=%i, m_subtitleStreams.size()=%i", _this->m_currentSubtitleStream, _this->m_subtitleStreams.size());
+//
+// if ( _this->m_currentSubtitleStream >= (int)_this->m_subtitleStreams.size() )
+// {
+// eDebug("return invalid stream count");
+// return;
+// }
+//
+// subtitleStream subs = _this->m_subtitleStreams[_this->m_currentSubtitleStream];
+//
+// if ( subs.type == stUnknown )
+// {
+// GstTagList *tags;
+// eDebug("gstCBsubtitleCAPS::m_subtitleStreams[%i].type == stUnknown...", _this->m_currentSubtitleStream);
+//
+// gchar *g_lang;
+// g_signal_emit_by_name (_this->m_gst_playbin, "get-text-tags", _this->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);
+//
+// subs.type = getSubtitleType(GST_PAD(obj));
+//
+// _this->m_subtitleStreams[_this->m_currentSubtitleStream] = subs;
+//
+// g_free (g_lang);
+// }
+//
+// gstCBsubtitleLink(subs.type, _this);
+// }
+
+// void eServiceMP3::gstCBsubtitleLink(subtype_t type, gpointer user_data)
+// {
+// eServiceMP3 *_this = (eServiceMP3*)user_data;
+//
+// if ( type == stVOB )
+// {
+// GstPad *ghostpad = gst_element_get_static_pad(_this->m_gst_subtitlebin, "sink");
+// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder");
+// GstPad *subdecsinkpad = gst_element_get_static_pad (dvdsubdec, "sink");
+// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, subdecsinkpad);
+// GstElement *appsink = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "subtitle_sink");
+// ret += gst_element_link(dvdsubdec, appsink);
+// eDebug("gstCBsubtitleLink:: dvdsubdec=%p, subdecsinkpad=%p, ghostpad=%p, set target & link=%i", dvdsubdec, subdecsinkpad, ghostpad, ret);
+// }
+// else if ( type < stVOB && type > stUnknown )
+// {
+// 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");
+// GstPad *appsinkpad = gst_element_get_static_pad (appsink, "sink");
+// GstElement *dvdsubdec = gst_bin_get_by_name(GST_BIN(_this->m_gst_subtitlebin), "vobsubtitle_decoder");
+// gst_element_unlink(dvdsubdec, appsink);
+// int ret = gst_ghost_pad_set_target((GstGhostPad*)ghostpad, appsinkpad);
+// eDebug("gstCBsubtitleLink:: appsink=%p, appsinkpad=%p, ghostpad=%p, set target=%i", appsink, appsinkpad, ghostpad, ret);
+// }
+// else
+// {
+// eDebug("gstCBsubtitleLink:: unsupported subtitles");
+// }
+// }
+/*
+gboolean eServiceMP3::gstCBsubtitleDrop(GstPad *pad, GstBuffer *buffer, gpointer user_data)
+{
+ eDebug("gstCBsubtitleDrop");
+
+ gint64 buf_pos = GST_BUFFER_TIMESTAMP(buffer);
+ gint64 duration_ns = GST_BUFFER_DURATION(buffer);
+ size_t len = GST_BUFFER_SIZE(buffer);
+
+ unsigned char line[len+1];
+ memcpy(line, GST_BUFFER_DATA(buffer), len);
+ line[len] = 0;
+ eDebug("dropping buffer '%s' ", line);
+ return false;
+}*/
+
+