+ GstElement *source;
+ g_object_get(_this->m_gst_playbin, "source", &source, NULL);
+ g_object_set (G_OBJECT (source), "user-agent", _this->m_useragent.c_str(), NULL);
+ gst_object_unref(source);
+}
+
+audiotype_t eServiceMP3::gstCheckAudioPad(GstStructure* structure)
+{
+ if (!structure)
+ return atUnknown;
+
+ if ( gst_structure_has_name (structure, "audio/mpeg"))
+ {
+ gint mpegversion, layer = -1;
+ if (!gst_structure_get_int (structure, "mpegversion", &mpegversion))
+ return atUnknown;
+
+ switch (mpegversion) {
+ case 1:
+ {
+ gst_structure_get_int (structure, "layer", &layer);
+ if ( layer == 3 )
+ return atMP3;
+ else
+ return atMPEG;
+ break;
+ }
+ case 2:
+ return atAAC;
+ case 4:
+ return atAAC;
+ default:
+ return atUnknown;
+ }
+ }
+
+ else if ( gst_structure_has_name (structure, "audio/x-ac3") || gst_structure_has_name (structure, "audio/ac3") )
+ return atAC3;
+ else if ( gst_structure_has_name (structure, "audio/x-dts") || gst_structure_has_name (structure, "audio/dts") )
+ return atDTS;
+ else if ( gst_structure_has_name (structure, "audio/x-raw-int") )
+ return atPCM;
+
+ return atUnknown;
+}
+
+void eServiceMP3::gstPoll(const int &msg)
+{
+ /* ok, we have a serious problem here. gstBusSyncHandler sends
+ us the wakup signal, but likely before it was posted.
+ the usleep, an EVIL HACK (DON'T DO THAT!!!) works around this.
+
+ I need to understand the API a bit more to make this work
+ proplerly. */
+ if (msg == 1)
+ {
+ GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin));
+ GstMessage *message;
+ usleep(1);
+ while ((message = gst_bus_pop (bus)))
+ {
+ gstBusCall(bus, message);
+ gst_message_unref (message);
+ }
+ }
+ else
+ pullSubtitle();
+}
+
+eAutoInitPtr<eServiceFactoryMP3> init_eServiceFactoryMP3(eAutoInitNumbers::service+1, "eServiceFactoryMP3");
+
+void eServiceMP3::gstCBsubtitleAvail(GstElement *appsink, gpointer user_data)
+{
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+ eSingleLocker l(_this->m_subs_to_pull_lock);
+ ++_this->m_subs_to_pull;
+ _this->m_pump.send(2);
+}
+
+void eServiceMP3::pullSubtitle()
+{
+ GstElement *sink;
+ g_object_get (G_OBJECT (m_gst_playbin), "text-sink", &sink, NULL);
+ if (sink)
+ {
+ while (m_subs_to_pull && m_subtitle_pages.size() < 2)
+ {
+ GstBuffer *buffer;
+ {
+ eSingleLocker l(m_subs_to_pull_lock);
+ --m_subs_to_pull;
+ g_signal_emit_by_name (sink, "pull-buffer", &buffer);
+ }
+ if (buffer)
+ {
+ 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("got new subtitle @ buf_pos = %lld ns (in pts=%lld): '%s' ", buf_pos, buf_pos/11111, line);
+ ePangoSubtitlePage page;
+ gRGB rgbcol(0xD0,0xD0,0xD0);
+ page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line));
+ page.show_pts = buf_pos / 11111L;
+ page.m_timeout = duration_ns / 1000000;
+ m_subtitle_pages.push_back(page);
+ pushSubtitles();
+ gst_buffer_unref(buffer);
+ }
+ }
+ gst_object_unref(sink);
+ }
+ else
+ eDebug("no subtitle sink!");
+}
+
+void eServiceMP3::pushSubtitles()
+{
+ ePangoSubtitlePage page;
+ pts_t running_pts;
+ while ( !m_subtitle_pages.empty() )
+ {
+ getPlayPosition(running_pts);
+ page = m_subtitle_pages.front();
+ gint64 diff_ms = ( page.show_pts - running_pts ) / 90;
+ eDebug("eServiceMP3::pushSubtitles show_pts = %lld running_pts = %lld diff = %lld", page.show_pts, running_pts, diff_ms);
+ if (diff_ms < -100)