+int eServiceMP3::getInfo(int w)
+{
+ const gchar *tag = 0;
+
+ switch (w)
+ {
+ case sServiceref: return m_ref;
+ case sVideoHeight: return m_height;
+ case sVideoWidth: return m_width;
+ case sFrameRate: return m_framerate;
+ case sProgressive: return m_progressive;
+ case sAspect: return m_aspect;
+ case sTagTitle:
+ case sTagArtist:
+ case sTagAlbum:
+ case sTagTitleSortname:
+ case sTagArtistSortname:
+ case sTagAlbumSortname:
+ case sTagDate:
+ case sTagComposer:
+ case sTagGenre:
+ case sTagComment:
+ case sTagExtendedComment:
+ case sTagLocation:
+ case sTagHomepage:
+ case sTagDescription:
+ case sTagVersion:
+ case sTagISRC:
+ case sTagOrganization:
+ case sTagCopyright:
+ case sTagCopyrightURI:
+ case sTagContact:
+ case sTagLicense:
+ case sTagLicenseURI:
+ case sTagCodec:
+ case sTagAudioCodec:
+ case sTagVideoCodec:
+ case sTagEncoder:
+ case sTagLanguageCode:
+ case sTagKeywords:
+ case sTagChannelMode:
+ case sUser+12:
+ return resIsString;
+ case sTagTrackGain:
+ case sTagTrackPeak:
+ case sTagAlbumGain:
+ case sTagAlbumPeak:
+ case sTagReferenceLevel:
+ case sTagBeatsPerMinute:
+ case sTagImage:
+ case sTagPreviewImage:
+ case sTagAttachment:
+ return resIsPyObject;
+ case sTagTrackNumber:
+ tag = GST_TAG_TRACK_NUMBER;
+ break;
+ case sTagTrackCount:
+ tag = GST_TAG_TRACK_COUNT;
+ break;
+ case sTagAlbumVolumeNumber:
+ tag = GST_TAG_ALBUM_VOLUME_NUMBER;
+ break;
+ case sTagAlbumVolumeCount:
+ tag = GST_TAG_ALBUM_VOLUME_COUNT;
+ break;
+ case sTagBitrate:
+ tag = GST_TAG_BITRATE;
+ break;
+ case sTagNominalBitrate:
+ tag = GST_TAG_NOMINAL_BITRATE;
+ break;
+ case sTagMinimumBitrate:
+ tag = GST_TAG_MINIMUM_BITRATE;
+ break;
+ case sTagMaximumBitrate:
+ tag = GST_TAG_MAXIMUM_BITRATE;
+ break;
+ case sTagSerial:
+ tag = GST_TAG_SERIAL;
+ break;
+ case sTagEncoderVersion:
+ tag = GST_TAG_ENCODER_VERSION;
+ break;
+ case sTagCRC:
+ tag = "has-crc";
+ break;
+ default:
+ return resNA;
+ }
+
+ if (!m_stream_tags || !tag)
+ return 0;
+
+ guint value;
+ if (gst_tag_list_get_uint(m_stream_tags, tag, &value))
+ return (int) value;
+
+ return 0;
+}
+
+std::string eServiceMP3::getInfoString(int w)
+{
+ if ( !m_stream_tags && w < sUser && w > 26 )
+ return "";
+ const gchar *tag = 0;
+ switch (w)
+ {
+ case sTagTitle:
+ tag = GST_TAG_TITLE;
+ break;
+ case sTagArtist:
+ tag = GST_TAG_ARTIST;
+ break;
+ case sTagAlbum:
+ tag = GST_TAG_ALBUM;
+ break;
+ case sTagTitleSortname:
+ tag = GST_TAG_TITLE_SORTNAME;
+ break;
+ case sTagArtistSortname:
+ tag = GST_TAG_ARTIST_SORTNAME;
+ break;
+ case sTagAlbumSortname:
+ tag = GST_TAG_ALBUM_SORTNAME;
+ break;
+ case sTagDate:
+ GDate *date;
+ if (gst_tag_list_get_date(m_stream_tags, GST_TAG_DATE, &date))
+ {
+ gchar res[5];
+ g_date_strftime (res, sizeof(res), "%Y-%M-%D", date);
+ return (std::string)res;
+ }
+ break;
+ case sTagComposer:
+ tag = GST_TAG_COMPOSER;
+ break;
+ case sTagGenre:
+ tag = GST_TAG_GENRE;
+ break;
+ case sTagComment:
+ tag = GST_TAG_COMMENT;
+ break;
+ case sTagExtendedComment:
+ tag = GST_TAG_EXTENDED_COMMENT;
+ break;
+ case sTagLocation:
+ tag = GST_TAG_LOCATION;
+ break;
+ case sTagHomepage:
+ tag = GST_TAG_HOMEPAGE;
+ break;
+ case sTagDescription:
+ tag = GST_TAG_DESCRIPTION;
+ break;
+ case sTagVersion:
+ tag = GST_TAG_VERSION;
+ break;
+ case sTagISRC:
+ tag = GST_TAG_ISRC;
+ break;
+ case sTagOrganization:
+ tag = GST_TAG_ORGANIZATION;
+ break;
+ case sTagCopyright:
+ tag = GST_TAG_COPYRIGHT;
+ break;
+ case sTagCopyrightURI:
+ tag = GST_TAG_COPYRIGHT_URI;
+ break;
+ case sTagContact:
+ tag = GST_TAG_CONTACT;
+ break;
+ case sTagLicense:
+ tag = GST_TAG_LICENSE;
+ break;
+ case sTagLicenseURI:
+ tag = GST_TAG_LICENSE_URI;
+ break;
+ case sTagCodec:
+ tag = GST_TAG_CODEC;
+ break;
+ case sTagAudioCodec:
+ tag = GST_TAG_AUDIO_CODEC;
+ break;
+ case sTagVideoCodec:
+ tag = GST_TAG_VIDEO_CODEC;
+ break;
+ case sTagEncoder:
+ tag = GST_TAG_ENCODER;
+ break;
+ case sTagLanguageCode:
+ tag = GST_TAG_LANGUAGE_CODE;
+ break;
+ case sTagKeywords:
+ tag = GST_TAG_KEYWORDS;
+ break;
+ case sTagChannelMode:
+ tag = "channel-mode";
+ break;
+ case sUser+12:
+ return m_error_message;
+ default:
+ return "";
+ }
+ if ( !tag )
+ return "";
+ gchar *value;
+ if (gst_tag_list_get_string(m_stream_tags, tag, &value))
+ {
+ std::string res = value;
+ g_free(value);
+ return res;
+ }
+ return "";
+}
+
+PyObject *eServiceMP3::getInfoObject(int w)
+{
+ const gchar *tag = 0;
+ bool isBuffer = false;
+ switch (w)
+ {
+ case sTagTrackGain:
+ tag = GST_TAG_TRACK_GAIN;
+ break;
+ case sTagTrackPeak:
+ tag = GST_TAG_TRACK_PEAK;
+ break;
+ case sTagAlbumGain:
+ tag = GST_TAG_ALBUM_GAIN;
+ break;
+ case sTagAlbumPeak:
+ tag = GST_TAG_ALBUM_PEAK;
+ break;
+ case sTagReferenceLevel:
+ tag = GST_TAG_REFERENCE_LEVEL;
+ break;
+ case sTagBeatsPerMinute:
+ tag = GST_TAG_BEATS_PER_MINUTE;
+ break;
+ case sTagImage:
+ tag = GST_TAG_IMAGE;
+ isBuffer = true;
+ break;
+ case sTagPreviewImage:
+ tag = GST_TAG_PREVIEW_IMAGE;
+ isBuffer = true;
+ break;
+ case sTagAttachment:
+ tag = GST_TAG_ATTACHMENT;
+ isBuffer = true;
+ break;
+ default:
+ break;
+ }
+
+ if ( isBuffer )
+ {
+ const GValue *gv_buffer = gst_tag_list_get_value_index(m_stream_tags, tag, 0);
+ if ( gv_buffer )
+ {
+ GstBuffer *buffer;
+ buffer = gst_value_get_buffer (gv_buffer);
+ return PyBuffer_FromMemory(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
+ }
+ }
+ else
+ {
+ gdouble value = 0.0;
+ gst_tag_list_get_double(m_stream_tags, tag, &value);
+ return PyFloat_FromDouble(value);
+ }
+
+ return 0;
+}
+
+RESULT eServiceMP3::audioChannel(ePtr<iAudioChannelSelection> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
+RESULT eServiceMP3::audioTracks(ePtr<iAudioTrackSelection> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
+RESULT eServiceMP3::subtitle(ePtr<iSubtitleOutput> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
+RESULT eServiceMP3::audioDelay(ePtr<iAudioDelay> &ptr)
+{
+ ptr = this;
+ return 0;
+}
+
+int eServiceMP3::getNumberOfTracks()
+{
+ return m_audioStreams.size();
+}
+
+int eServiceMP3::getCurrentTrack()
+{
+ if (m_currentAudioStream == -1)
+ g_object_get (G_OBJECT (m_gst_playbin), "current-audio", &m_currentAudioStream, NULL);
+ return m_currentAudioStream;
+}
+
+RESULT eServiceMP3::selectTrack(unsigned int i)
+{
+ pts_t ppos;
+ getPlayPosition(ppos);
+ ppos -= 90000;
+ if (ppos < 0)
+ ppos = 0;
+
+ int ret = selectAudioStream(i);
+ if (!ret) {
+ /* flush */
+ seekTo(ppos);
+ }
+
+ return ret;
+}
+
+int eServiceMP3::selectAudioStream(int i)
+{
+ int current_audio;
+ g_object_set (G_OBJECT (m_gst_playbin), "current-audio", i, NULL);
+ g_object_get (G_OBJECT (m_gst_playbin), "current-audio", ¤t_audio, NULL);
+ if ( current_audio == i )
+ {
+ eDebug ("eServiceMP3::switched to audio stream %i", current_audio);
+ m_currentAudioStream = i;
+ return 0;
+ }
+ return -1;
+}
+
+int eServiceMP3::getCurrentChannel()
+{
+ return STEREO;
+}
+
+RESULT eServiceMP3::selectChannel(int i)
+{
+ eDebug("eServiceMP3::selectChannel(%i)",i);
+ return 0;
+}
+
+RESULT eServiceMP3::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
+{
+ if (i >= m_audioStreams.size())
+ return -2;
+ info.m_description = m_audioStreams[i].codec;
+/* if (m_audioStreams[i].type == atMPEG)
+ info.m_description = "MPEG";
+ else if (m_audioStreams[i].type == atMP3)
+ info.m_description = "MP3";
+ else if (m_audioStreams[i].type == atAC3)
+ info.m_description = "AC3";
+ else if (m_audioStreams[i].type == atAAC)
+ info.m_description = "AAC";
+ else if (m_audioStreams[i].type == atDTS)
+ info.m_description = "DTS";
+ else if (m_audioStreams[i].type == atPCM)
+ info.m_description = "PCM";
+ else if (m_audioStreams[i].type == atOGG)
+ info.m_description = "OGG";
+ else if (m_audioStreams[i].type == atFLAC)
+ info.m_description = "FLAC";
+ else
+ info.m_description = "???";*/
+ if (info.m_language.empty())
+ info.m_language = m_audioStreams[i].language_code;
+ return 0;
+}
+
+subtype_t getSubtitleType(GstPad* pad, gchar *g_codec=NULL)
+{
+ subtype_t type = stUnknown;
+ GstCaps* caps = gst_pad_get_negotiated_caps(pad);
+
+ if ( caps )
+ {
+ GstStructure* str = gst_caps_get_structure(caps, 0);
+ const gchar *g_type = gst_structure_get_name(str);
+ eDebug("getSubtitleType::subtitle probe caps type=%s", g_type);
+
+ if ( !strcmp(g_type, "video/x-dvd-subpicture") )
+ type = stVOB;
+ else if ( !strcmp(g_type, "text/x-pango-markup") )
+ type = stSSA;
+ else if ( !strcmp(g_type, "text/plain") )
+ type = stPlainText;
+ else if ( !strcmp(g_type, "subpicture/x-pgs") )
+ type = stPGS;
+ else
+ eDebug("getSubtitleType::unsupported subtitle caps %s (%s)", g_type, g_codec);
+ }
+ else if ( g_codec )
+ {
+ eDebug("getSubtitleType::subtitle probe codec tag=%s", g_codec);
+ if ( !strcmp(g_codec, "VOB") )
+ type = stVOB;
+ else if ( !strcmp(g_codec, "SubStation Alpha") || !strcmp(g_codec, "SSA") )
+ type = stSSA;
+ else if ( !strcmp(g_codec, "ASS") )
+ type = stASS;
+ else if ( !strcmp(g_codec, "UTF-8 plain text") )
+ type = stPlainText;
+ else
+ eDebug("getSubtitleType::unsupported subtitle codec %s", g_codec);
+ }
+ else
+ eDebug("getSubtitleType::unidentifiable subtitle stream!");
+
+ return type;
+}
+
+void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
+{
+ if (!msg)
+ return;
+ gchar *sourceName;
+ GstObject *source;
+
+ source = GST_MESSAGE_SRC(msg);
+ sourceName = gst_object_get_name(source);
+#if 0
+ if (gst_message_get_structure(msg))
+ {
+ gchar *string = gst_structure_to_string(gst_message_get_structure(msg));
+ eDebug("eServiceMP3::gst_message from %s: %s", sourceName, string);
+ g_free(string);
+ }
+ else
+ eDebug("eServiceMP3::gst_message from %s: %s (without structure)", sourceName, GST_MESSAGE_TYPE_NAME(msg));
+#endif
+ switch (GST_MESSAGE_TYPE (msg))
+ {
+ case GST_MESSAGE_EOS:
+ m_event((iPlayableService*)this, evEOF);
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+ if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
+ break;
+
+ GstState old_state, new_state;
+ gst_message_parse_state_changed(msg, &old_state, &new_state, NULL);
+
+ if(old_state == new_state)
+ break;
+
+ eDebug("eServiceMP3::state transition %s -> %s", gst_element_state_get_name(old_state), gst_element_state_get_name(new_state));
+
+ GstStateChange transition = (GstStateChange)GST_STATE_TRANSITION(old_state, new_state);
+
+ switch(transition)
+ {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ {
+ } break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ {
+ GstElement *appsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
+ if (appsink)
+ {
+ g_object_set (G_OBJECT (appsink), "max-buffers", 2, NULL);
+ g_object_set (G_OBJECT (appsink), "sync", FALSE, NULL);
+ g_object_set (G_OBJECT (appsink), "emit-signals", TRUE, NULL);
+ eDebug("eServiceMP3::appsink properties set!");
+ gst_object_unref(appsink);
+ }
+ setAC3Delay(ac3_delay);
+ setPCMDelay(pcm_delay);
+ } break;
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ {
+ if ( m_sourceinfo.is_streaming && m_streamingsrc_timeout )
+ m_streamingsrc_timeout->stop();
+ } break;
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ {
+ } break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ {
+ } break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ {
+ } break;
+ }
+ break;
+ }
+ case GST_MESSAGE_ERROR:
+ {
+ gchar *debug;
+ GError *err;
+ gst_message_parse_error (msg, &err, &debug);
+ g_free (debug);
+ eWarning("Gstreamer error: %s (%i) from %s", err->message, err->code, sourceName );
+ if ( err->domain == GST_STREAM_ERROR )
+ {
+ if ( err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND )
+ {
+ if ( g_strrstr(sourceName, "videosink") )
+ m_event((iPlayableService*)this, evUser+11);
+ else if ( g_strrstr(sourceName, "audiosink") )
+ m_event((iPlayableService*)this, evUser+10);
+ }
+ }
+ g_error_free(err);
+ break;
+ }
+ case GST_MESSAGE_INFO:
+ {
+ gchar *debug;
+ GError *inf;
+
+ gst_message_parse_info (msg, &inf, &debug);
+ g_free (debug);
+ if ( inf->domain == GST_STREAM_ERROR && inf->code == GST_STREAM_ERROR_DECODE )
+ {
+ if ( g_strrstr(sourceName, "videosink") )
+ m_event((iPlayableService*)this, evUser+14);
+ }
+ g_error_free(inf);
+ break;
+ }
+ case GST_MESSAGE_TAG:
+ {
+ GstTagList *tags, *result;
+ gst_message_parse_tag(msg, &tags);
+
+ result = gst_tag_list_merge(m_stream_tags, tags, GST_TAG_MERGE_REPLACE);
+ if (result)
+ {
+ if (m_stream_tags)
+ gst_tag_list_free(m_stream_tags);
+ m_stream_tags = result;
+ }
+
+ const GValue *gv_image = gst_tag_list_get_value_index(tags, GST_TAG_IMAGE, 0);
+ if ( gv_image )
+ {
+ GstBuffer *buf_image;
+ buf_image = gst_value_get_buffer (gv_image);
+ int fd = open("/tmp/.id3coverart", O_CREAT|O_WRONLY|O_TRUNC, 0644);
+ int ret = write(fd, GST_BUFFER_DATA(buf_image), GST_BUFFER_SIZE(buf_image));
+ close(fd);
+ eDebug("eServiceMP3::/tmp/.id3coverart %d bytes written ", ret);
+ m_event((iPlayableService*)this, evUser+13);
+ }
+ gst_tag_list_free(tags);
+ m_event((iPlayableService*)this, evUpdatedInfo);
+ break;
+ }
+ case GST_MESSAGE_ASYNC_DONE:
+ {
+ if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
+ break;
+
+ GstTagList *tags;
+ gint i, active_idx, n_video = 0, n_audio = 0, n_text = 0;
+
+ g_object_get (m_gst_playbin, "n-video", &n_video, NULL);
+ g_object_get (m_gst_playbin, "n-audio", &n_audio, NULL);
+ g_object_get (m_gst_playbin, "n-text", &n_text, NULL);
+
+ eDebug("eServiceMP3::async-done - %d video, %d audio, %d subtitle", n_video, n_audio, n_text);
+
+ if ( n_video + n_audio <= 0 )
+ stop();
+
+ active_idx = 0;
+
+ m_audioStreams.clear();
+ m_subtitleStreams.clear();
+
+ for (i = 0; i < n_audio; i++)
+ {
+ audioStream audio;
+ gchar *g_codec, *g_lang;
+ GstPad* pad = 0;
+ g_signal_emit_by_name (m_gst_playbin, "get-audio-pad", i, &pad);
+ GstCaps* caps = gst_pad_get_negotiated_caps(pad);
+ if (!caps)
+ continue;
+ GstStructure* str = gst_caps_get_structure(caps, 0);
+ const gchar *g_type = gst_structure_get_name(str);
+ audio.type = gstCheckAudioPad(str);
+ g_codec = g_strdup(g_type);
+ g_lang = g_strdup_printf ("und");
+ g_signal_emit_by_name (m_gst_playbin, "get-audio-tags", i, &tags);
+ if ( tags && gst_is_tag_list(tags) )
+ {
+ gst_tag_list_get_string(tags, GST_TAG_AUDIO_CODEC, &g_codec);
+ gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &g_lang);
+ gst_tag_list_free(tags);
+ }
+ audio.language_code = std::string(g_lang);
+ audio.codec = std::string(g_codec);
+ eDebug("eServiceMP3::audio stream=%i codec=%s language=%s", i, g_codec, g_lang);
+ m_audioStreams.push_back(audio);
+ g_free (g_lang);
+ g_free (g_codec);
+ gst_caps_unref(caps);
+ }
+
+ for (i = 0; i < n_text; i++)
+ {
+ gchar *g_codec = NULL, *g_lang = NULL;
+ g_signal_emit_by_name (m_gst_playbin, "get-text-tags", i, &tags);
+ subtitleStream subs;
+// int ret;
+
+ 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);
+ gst_tag_list_get_string(tags, GST_TAG_SUBTITLE_CODEC, &g_codec);
+ gst_tag_list_free(tags);
+ }
+
+ subs.language_code = std::string(g_lang);
+ eDebug("eServiceMP3::subtitle stream=%i language=%s codec=%s", i, g_lang, g_codec);
+
+ GstPad* pad = 0;
+ g_signal_emit_by_name (m_gst_playbin, "get-text-pad", i, &pad);
+ if ( pad )
+ g_signal_connect (G_OBJECT (pad), "notify::caps", G_CALLBACK (gstTextpadHasCAPS), this);
+ subs.type = getSubtitleType(pad, g_codec);
+
+ m_subtitleStreams.push_back(subs);
+ g_free (g_lang);
+ }
+ m_event((iPlayableService*)this, evUpdatedEventInfo);
+ break;
+ }
+ case GST_MESSAGE_ELEMENT:
+ {
+ if ( gst_is_missing_plugin_message(msg) )
+ {
+ gchar *description = gst_missing_plugin_message_get_description(msg);
+ if ( description )
+ {
+ m_error_message = "GStreamer plugin " + (std::string)description + " not available!\n";
+ g_free(description);
+ m_event((iPlayableService*)this, evUser+12);
+ }
+ }
+ else if (const GstStructure *msgstruct = gst_message_get_structure(msg))
+ {
+ const gchar *eventname = gst_structure_get_name(msgstruct);
+ if ( eventname )
+ {
+ if (!strcmp(eventname, "eventSizeChanged") || !strcmp(eventname, "eventSizeAvail"))
+ {
+ gst_structure_get_int (msgstruct, "aspect_ratio", &m_aspect);
+ gst_structure_get_int (msgstruct, "width", &m_width);
+ gst_structure_get_int (msgstruct, "height", &m_height);
+ if (strstr(eventname, "Changed"))
+ m_event((iPlayableService*)this, evVideoSizeChanged);
+ }
+ else if (!strcmp(eventname, "eventFrameRateChanged") || !strcmp(eventname, "eventFrameRateAvail"))
+ {
+ gst_structure_get_int (msgstruct, "frame_rate", &m_framerate);
+ if (strstr(eventname, "Changed"))
+ m_event((iPlayableService*)this, evVideoFramerateChanged);
+ }
+ else if (!strcmp(eventname, "eventProgressiveChanged") || !strcmp(eventname, "eventProgressiveAvail"))
+ {
+ gst_structure_get_int (msgstruct, "progressive", &m_progressive);
+ if (strstr(eventname, "Changed"))
+ m_event((iPlayableService*)this, evVideoProgressiveChanged);
+ }
+ }
+ }
+ break;
+ }
+ case GST_MESSAGE_BUFFERING:
+ {
+ GstBufferingMode mode;
+ gst_message_parse_buffering(msg, &(m_bufferInfo.bufferPercent));
+ gst_message_parse_buffering_stats(msg, &mode, &(m_bufferInfo.avgInRate), &(m_bufferInfo.avgOutRate), &(m_bufferInfo.bufferingLeft));
+ m_event((iPlayableService*)this, evBuffering);
+ break;
+ }
+ case GST_MESSAGE_STREAM_STATUS:
+ {
+ GstStreamStatusType type;
+ GstElement *owner;
+ gst_message_parse_stream_status (msg, &type, &owner);
+ if ( type == GST_STREAM_STATUS_TYPE_CREATE && m_sourceinfo.is_streaming )
+ {
+ if ( GST_IS_PAD(source) )
+ owner = gst_pad_get_parent_element(GST_PAD(source));
+ else if ( GST_IS_ELEMENT(source) )
+ owner = GST_ELEMENT(source);
+ else
+ owner = 0;
+ if ( owner )
+ {
+ GstElementFactory *factory = gst_element_get_factory(GST_ELEMENT(owner));
+ const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
+ if (!strcmp(name, "souphttpsrc"))
+ {
+ m_streamingsrc_timeout->start(HTTP_TIMEOUT*1000, true);
+ g_object_set (G_OBJECT (owner), "timeout", HTTP_TIMEOUT, NULL);
+ eDebug("eServiceMP3::GST_STREAM_STATUS_TYPE_CREATE -> setting timeout on %s to %is", name, HTTP_TIMEOUT);
+ }
+
+ }
+ if ( GST_IS_PAD(source) )
+ gst_object_unref(owner);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ g_free (sourceName);
+}
+
+GstBusSyncReply eServiceMP3::gstBusSyncHandler(GstBus *bus, GstMessage *message, gpointer user_data)
+{
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+ _this->m_pump.send(Message(1));
+ /* wake */
+ return GST_BUS_PASS;
+}
+
+void eServiceMP3::gstHTTPSourceSetAgent(GObject *object, GParamSpec *unused, gpointer user_data)
+{
+ eServiceMP3 *_this = (eServiceMP3*)user_data;
+ 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 Message &msg)
+{
+ if (msg.type == 1)
+ {
+ GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (m_gst_playbin));
+ GstMessage *message;
+ while ((message = gst_bus_pop(bus)))
+ {
+ gstBusCall(bus, message);
+ gst_message_unref (message);
+ }
+ }
+ else if (msg.type == 2)
+ pullSubtitle();
+ else if (msg.type == 3)
+ gstTextpadHasCAPS_synced(msg.d.pad);
+ else
+ eDebug("gstPoll unhandled Message %d\n", msg.type);
+}
+