X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/d6ad23c5be62bc24cc08a5c8db91f64ae2d8cf3b..672640e924d5c61ec03919b977d38fa2783ad1c8:/lib/service/servicemp3.cpp diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index d3eaa262..e453a2b3 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -1,5 +1,3 @@ -#ifdef HAVE_GSTREAMER - /* note: this requires gstreamer 0.10.x and a big list of plugins. */ /* it's currently hardcoded to use a big-endian alsasink as sink. */ #include @@ -20,6 +18,8 @@ #include #include +#define HTTP_TIMEOUT 10 + // eServiceFactoryMP3 eServiceFactoryMP3::eServiceFactoryMP3() @@ -189,6 +189,25 @@ int eStaticServiceMP3Info::getLength(const eServiceReference &ref) return -1; } +int eStaticServiceMP3Info::getInfo(const eServiceReference &ref, int w) +{ + switch (w) + { + case iServiceInformation::sTimeCreate: + { + struct stat s; + if(stat(ref.path.c_str(), &s) == 0) + { + return s.st_mtime; + } + return iServiceInformation::resNA; + } + default: break; + } + return iServiceInformation::resNA; +} + + // eServiceMP3 int eServiceMP3::ac3_delay, eServiceMP3::pcm_delay; @@ -198,6 +217,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) { m_seekTimeout = eTimer::create(eApp); m_subtitle_sync_timer = eTimer::create(eApp); + m_streamingsrc_timeout = 0; m_stream_tags = 0; m_currentAudioStream = -1; m_currentSubtitleStream = 0; @@ -218,63 +238,73 @@ eServiceMP3::eServiceMP3(eServiceReference ref) if (!ext) ext = filename; - sourceStream sourceinfo; - sourceinfo.is_video = FALSE; - sourceinfo.audiotype = atUnknown; + m_sourceinfo.is_video = FALSE; + m_sourceinfo.audiotype = atUnknown; if ( (strcasecmp(ext, ".mpeg") && strcasecmp(ext, ".mpg") && strcasecmp(ext, ".vob") && strcasecmp(ext, ".bin") && strcasecmp(ext, ".dat") ) == 0 ) { - sourceinfo.containertype = ctMPEGPS; - sourceinfo.is_video = TRUE; + m_sourceinfo.containertype = ctMPEGPS; + m_sourceinfo.is_video = TRUE; } else if ( strcasecmp(ext, ".ts") == 0 ) { - sourceinfo.containertype = ctMPEGTS; - sourceinfo.is_video = TRUE; + m_sourceinfo.containertype = ctMPEGTS; + m_sourceinfo.is_video = TRUE; } else if ( strcasecmp(ext, ".mkv") == 0 ) { - sourceinfo.containertype = ctMKV; - sourceinfo.is_video = TRUE; + m_sourceinfo.containertype = ctMKV; + m_sourceinfo.is_video = TRUE; } else if ( strcasecmp(ext, ".avi") == 0 || strcasecmp(ext, ".divx") == 0) { - sourceinfo.containertype = ctAVI; - sourceinfo.is_video = TRUE; + m_sourceinfo.containertype = ctAVI; + m_sourceinfo.is_video = TRUE; } else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0 || strcasecmp(ext, ".m4v") == 0) { - sourceinfo.containertype = ctMP4; - sourceinfo.is_video = TRUE; + m_sourceinfo.containertype = ctMP4; + m_sourceinfo.is_video = TRUE; } else if ( strcasecmp(ext, ".m4a") == 0 ) { - sourceinfo.containertype = ctMP4; - sourceinfo.audiotype = atAAC; + m_sourceinfo.containertype = ctMP4; + m_sourceinfo.audiotype = atAAC; } else if ( strcasecmp(ext, ".mp3") == 0 ) - sourceinfo.audiotype = atMP3; + m_sourceinfo.audiotype = atMP3; else if ( (strncmp(filename, "/autofs/", 8) || strncmp(filename+strlen(filename)-13, "/track-", 7) || strcasecmp(ext, ".wav")) == 0 ) - sourceinfo.containertype = ctCDA; + m_sourceinfo.containertype = ctCDA; if ( strcasecmp(ext, ".dat") == 0 ) { - sourceinfo.containertype = ctVCD; - sourceinfo.is_video = TRUE; + m_sourceinfo.containertype = ctVCD; + m_sourceinfo.is_video = TRUE; } - if ( (strncmp(filename, "http://", 7)) == 0 || (strncmp(filename, "udp://", 6)) == 0 || (strncmp(filename, "rtp://", 6)) == 0 || (strncmp(filename, "https://", 8)) == 0 || (strncmp(filename, "mms://", 6)) == 0 || (strncmp(filename, "rtsp://", 7)) == 0 ) - sourceinfo.is_streaming = TRUE; + if ( (strncmp(filename, "http://", 7)) == 0 || (strncmp(filename, "udp://", 6)) == 0 || (strncmp(filename, "rtp://", 6)) == 0 || (strncmp(filename, "https://", 8)) == 0 || (strncmp(filename, "mms://", 6)) == 0 || (strncmp(filename, "rtsp://", 7)) == 0 || (strncmp(filename, "rtspt://", 7)) == 0 ) + m_sourceinfo.is_streaming = TRUE; gchar *uri; - if ( sourceinfo.is_streaming ) + if ( m_sourceinfo.is_streaming ) { uri = g_strdup_printf ("%s", filename); + m_streamingsrc_timeout = eTimer::create(eApp);; + CONNECT(m_streamingsrc_timeout->timeout, eServiceMP3::sourceTimeout); + + std::string config_str; + if( ePythonConfigQuery::getConfigValue("config.mediaplayer.useAlternateUserAgent", config_str) == 0 ) + { + if ( config_str == "True" ) + ePythonConfigQuery::getConfigValue("config.mediaplayer.alternateUserAgent", m_useragent); + } + if ( m_useragent.length() == 0 ) + m_useragent = "Dream Multimedia Dreambox Enigma2 Mediaplayer"; } - else if ( sourceinfo.containertype == ctCDA ) + else if ( m_sourceinfo.containertype == ctCDA ) { int i_track = atoi(filename+18); uri = g_strdup_printf ("cdda://%i", i_track); } - else if ( sourceinfo.containertype == ctVCD ) + else if ( m_sourceinfo.containertype == ctVCD ) { int fd = open(filename,O_RDONLY); char tmp[128*1024]; @@ -283,11 +313,11 @@ eServiceMP3::eServiceMP3(eServiceReference ref) if ( ret == -1 ) // this is a "REAL" VCD uri = g_strdup_printf ("vcd://"); else - uri = g_strdup_printf ("file://%s", filename); + uri = g_filename_to_uri(filename, NULL, NULL); } else - uri = g_strdup_printf ("file://%s", filename); + uri = g_filename_to_uri(filename, NULL, NULL); eDebug("eServiceMP3::playbin2 uri=%s", uri); @@ -308,6 +338,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref) else { m_subs_to_pull_handler_id = g_signal_connect (subsink, "new-buffer", G_CALLBACK (gstCBsubtitleAvail), this); + g_object_set (G_OBJECT (subsink), "caps", gst_caps_from_string("text/plain; text/x-plain; text/x-pango-markup"), NULL); g_object_set (G_OBJECT (m_gst_playbin), "text-sink", subsink, NULL); } @@ -321,14 +352,17 @@ eServiceMP3::eServiceMP3(eServiceReference ref) struct stat buffer; if (stat(srt_filename, &buffer) == 0) { - std::string suburi = "file://" + (std::string)srt_filename; - eDebug("eServiceMP3::subtitle uri: %s",suburi.c_str()); - g_object_set (G_OBJECT (m_gst_playbin), "suburi", suburi.c_str(), NULL); + eDebug("eServiceMP3::subtitle uri: %s", g_filename_to_uri(srt_filename, NULL, NULL)); + g_object_set (G_OBJECT (m_gst_playbin), "suburi", g_filename_to_uri(srt_filename, NULL, NULL), NULL); subtitleStream subs; subs.type = stSRT; subs.language_code = std::string("und"); m_subtitleStreams.push_back(subs); } + if ( m_sourceinfo.is_streaming ) + { + g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (gstHTTPSourceSetAgent), this); + } } else { m_event((iPlayableService*)this, evUser+12); @@ -396,6 +430,12 @@ RESULT eServiceMP3::start() return 0; } +void eServiceMP3::sourceTimeout() +{ + eDebug("eServiceMP3::http source timeout! issuing eof..."); + m_event((iPlayableService*)this, evEOF); +} + RESULT eServiceMP3::stop() { ASSERT(m_state != stIdle); @@ -640,7 +680,31 @@ RESULT eServiceMP3::setTrickmode(int trick) RESULT eServiceMP3::isCurrentlySeekable() { - return 1; + int ret = 3; // seeking and fast/slow winding possible + GstElement *sink; + + if (!m_gst_playbin) + return 0; + if (m_state != stRunning) + return 0; + + g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL); + + // disable fast winding yet when a dvbvideosink or dvbaudiosink is used + // for this we must do some changes on different places.. (gstreamer.. our sinks.. enigma2) + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + else { + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + } + + return ret; } RESULT eServiceMP3::info(ePtr&i) @@ -1108,6 +1172,8 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) } 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: { @@ -1259,6 +1325,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) // g_free (g_type); } m_event((iPlayableService*)this, evUpdatedEventInfo); + break; } case GST_MESSAGE_ELEMENT: { @@ -1307,6 +1374,37 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg) 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; @@ -1322,6 +1420,15 @@ GstBusSyncReply eServiceMP3::gstBusSyncHandler(GstBus *bus, GstMessage *message, 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) @@ -1682,6 +1789,3 @@ void eServiceMP3::setPCMDelay(int delay) } } -#else -#warning gstreamer not available, not building media player -#endif