implement configurable http user-agent (fixes #224)
[enigma2.git] / lib / service / servicemp3.cpp
index 93d2ec7ef213e7f7544cbc6a5c45aacb8238339c..3ab4924a7cc276c8f760da90fcd0a3e0f28859fb 100644 (file)
@@ -37,6 +37,7 @@ eServiceFactoryMP3::eServiceFactoryMP3()
                extensions.push_back("vob");
                extensions.push_back("wav");
                extensions.push_back("wave");
+               extensions.push_back("m4v");
                extensions.push_back("mkv");
                extensions.push_back("avi");
                extensions.push_back("divx");
@@ -188,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;
@@ -240,7 +260,7 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
                sourceinfo.containertype = ctAVI;
                sourceinfo.is_video = TRUE;
        }
-       else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0)
+       else if ( strcasecmp(ext, ".mp4") == 0 || strcasecmp(ext, ".mov") == 0 || strcasecmp(ext, ".m4v") == 0)
        {
                sourceinfo.containertype = ctMP4;
                sourceinfo.is_video = TRUE;
@@ -267,6 +287,15 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
        if ( sourceinfo.is_streaming )
        {
                uri = g_strdup_printf ("%s", filename);
+
+               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 )
        {
@@ -282,11 +311,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);
 
@@ -320,14 +349,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 ( sourceinfo.is_streaming )
+               {
+                       g_signal_connect (G_OBJECT (m_gst_playbin), "notify::source", G_CALLBACK (gstHTTPSourceSetAgent), this);
+               }
        } else
        {
                m_event((iPlayableService*)this, evUser+12);
@@ -639,7 +671,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<iServiceInformation>&i)
@@ -1321,6 +1377,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)
@@ -1602,23 +1667,33 @@ int eServiceMP3::getPCMDelay()
 
 void eServiceMP3::setAC3Delay(int delay)
 {
+       ac3_delay = delay;
        if (!m_gst_playbin || m_state != stRunning)
                return;
        else
        {
                GstElement *sink;
-               std::string config_delay;
                int config_delay_int = delay;
-               if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
-                       config_delay_int += atoi(config_delay.c_str());
+               g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL);
+
+               if (sink)
+               {
+                       std::string config_delay;
+                       if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
+                               config_delay_int += atoi(config_delay.c_str());
+                       gst_object_unref(sink);
+               }
+               else
+               {
+                       eDebug("dont apply ac3 delay when no video is running!");
+                       config_delay_int = 0;
+               }
 
                g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL);
 
-               if (!sink)
-                       return;
-               else {
+               if (sink)
+               {
                        gchar *name = gst_element_get_name(sink);
-
                        if (strstr(name, "dvbaudiosink"))
                                eTSMPEGDecoder::setHwAC3Delay(config_delay_int);
                        g_free(name);
@@ -1629,26 +1704,37 @@ void eServiceMP3::setAC3Delay(int delay)
 
 void eServiceMP3::setPCMDelay(int delay)
 {
+       pcm_delay = delay;
        if (!m_gst_playbin || m_state != stRunning)
                return;
        else
        {
                GstElement *sink;
-               std::string config_delay;
                int config_delay_int = delay;
-               if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
-                       config_delay_int += atoi(config_delay.c_str());
+               g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL);
+
+               if (sink)
+               {
+                       std::string config_delay;
+                       if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
+                               config_delay_int += atoi(config_delay.c_str());
+                       gst_object_unref(sink);
+               }
+               else
+               {
+                       eDebug("dont apply pcm delay when no video is running!");
+                       config_delay_int = 0;
+               }
 
                g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL);
 
-               if (!sink)
-                       return;
-               else {
+               if (sink)
+               {
                        gchar *name = gst_element_get_name(sink);
-
                        if (strstr(name, "dvbaudiosink"))
                                eTSMPEGDecoder::setHwPCMDelay(config_delay_int);
-                       else {
+                       else
+                       {
                                // this is realy untested..and not used yet
                                gint64 offset = config_delay_int;
                                offset *= 1000000; // milli to nano