Support turbo2.
[vuplus_dvbapp] / lib / service / servicemp3.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 0437f59..fbc8811
@@ -6,6 +6,7 @@
 #include <lib/base/init.h>
 #include <lib/base/nconfig.h>
 #include <lib/base/object.h>
+#include <lib/dvb/epgcache.h>
 #include <lib/dvb/decoder.h>
 #include <lib/components/file_eraser.h>
 #include <lib/gui/esubtitle.h>
@@ -134,9 +135,7 @@ eMP3ServiceOfflineOperations::eMP3ServiceOfflineOperations(const eServiceReferen
 
 RESULT eMP3ServiceOfflineOperations::deleteFromDisk(int simulate)
 {
-       if (simulate)
-               return 0;
-       else
+       if (!simulate)
        {
                std::list<std::string> res;
                if (getListOfFilenames(res))
@@ -154,9 +153,8 @@ RESULT eMP3ServiceOfflineOperations::deleteFromDisk(int simulate)
                        else
                                ::unlink(i->c_str());
                }
-               
-               return 0;
        }
+       return 0;
 }
 
 RESULT eMP3ServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
@@ -231,14 +229,28 @@ int eStaticServiceMP3Info::getInfo(const eServiceReference &ref, int w)
        }
        return iServiceInformation::resNA;
 }
+
+RESULT eStaticServiceMP3Info::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
+{
+       if (ref.path.find("://") != std::string::npos)
+       {
+               eServiceReference equivalentref(ref);
+               equivalentref.type = eServiceFactoryMP3::id;
+               equivalentref.path.clear();
+               return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
+       }
+       evt = 0;
+       return -1;
+}
 
 // eServiceMP3
 int eServiceMP3::ac3_delay,
     eServiceMP3::pcm_delay;
 
 eServiceMP3::eServiceMP3(eServiceReference ref)
-       :m_ref(ref), m_pump(eApp, 1)
+       :m_ref(ref),
+       m_pump(eApp, 1),
+       m_nownext_timer(eTimer::create(eApp))
 {
        m_subtitle_sync_timer = eTimer::create(eApp);
        m_streamingsrc_timeout = 0;
@@ -251,11 +263,11 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
        m_prev_decoder_time = -1;
        m_decoder_time_valid_state = 0;
        m_errorInfo.missing_codec = "";
-       //vuplus
-       m_is_hls_stream = 0;
+
        audioSink = videoSink = NULL;
        CONNECT(m_subtitle_sync_timer->timeout, eServiceMP3::pushSubtitles);
        CONNECT(m_pump.recv_msg, eServiceMP3::gstPoll);
+       CONNECT(m_nownext_timer->timeout, eServiceMP3::updateEpgCacheNowNext);
        m_aspect = m_width = m_height = m_framerate = m_progressive = -1;
 
        m_state = stIdle;
@@ -315,9 +327,12 @@ eServiceMP3::eServiceMP3(eServiceReference ref)
        if ( m_sourceinfo.is_streaming )
        {
                uri = g_strdup_printf ("%s", filename);
-               m_streamingsrc_timeout = eTimer::create(eApp);;
-               CONNECT(m_streamingsrc_timeout->timeout, eServiceMP3::sourceTimeout);
-
+               if (strstr(filename, "rtmp://") || strstr(filename, "rtsp://")) {
+                       m_streamingsrc_timeout = eTimer::create(eApp);
+               }
+               if (m_streamingsrc_timeout) {
+                       CONNECT(m_streamingsrc_timeout->timeout, eServiceMP3::sourceTimeout);
+               }
                std::string config_str;
                if( ePythonConfigQuery::getConfigValue("config.mediaplayer.useAlternateUserAgent", config_str) == 0 )
                {
@@ -463,6 +478,53 @@ eServiceMP3::~eServiceMP3()
        }
 }
 
+void eServiceMP3::updateEpgCacheNowNext()
+{
+       bool update = false;
+       ePtr<eServiceEvent> next = 0;
+       ePtr<eServiceEvent> ptr = 0;
+       eServiceReference ref(m_ref);
+       ref.type = eServiceFactoryMP3::id;
+       ref.path.clear();
+
+       if (eEPGCache::getInstance() && eEPGCache::getInstance()->lookupEventTime(ref, -1, ptr) >= 0)
+       {
+               ePtr<eServiceEvent> current = m_event_now;
+               if (!current || !ptr || current->getEventId() != ptr->getEventId())
+               {
+                       update = true;
+                       m_event_now = ptr;
+                       time_t next_time = ptr->getBeginTime() + ptr->getDuration();
+                       if (eEPGCache::getInstance()->lookupEventTime(ref, next_time, ptr) >= 0)
+                       {
+                               next = ptr;
+                               m_event_next = ptr;
+                       }
+               }
+       }
+
+       int refreshtime = 60;
+       if (!next)
+       {
+               next = m_event_next;
+       }
+       if (next)
+       {
+               time_t now = ::time(0);
+               refreshtime = (int)(next->getBeginTime() - now) + 3;
+               if (refreshtime <= 0 || refreshtime > 60)
+               {
+                       refreshtime = 60;
+               }
+       }
+
+       m_nownext_timer->startLongTimer(refreshtime);
+       if (update)
+       {
+               m_event((iPlayableService*)this, evUpdatedEventInfo);
+       }
+}
+
 DEFINE_REF(eServiceMP3);
 
 RESULT eServiceMP3::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
@@ -497,7 +559,7 @@ RESULT eServiceMP3::stop()
 {
        ASSERT(m_state != stIdle);
 
-       if (m_state == stStopped)
+       if (!m_gst_playbin || m_state == stStopped)
                return -1;
        
        //GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(m_gst_playbin),GST_DEBUG_GRAPH_SHOW_ALL,"e2-playbin");
@@ -505,6 +567,7 @@ RESULT eServiceMP3::stop()
        //eDebug("eServiceMP3::stop %s", m_ref.path.c_str());
        gst_element_set_state(m_gst_playbin, GST_STATE_NULL);
        m_state = stStopped;
+       m_nownext_timer->stop();
 
        return 0;
 }
@@ -567,10 +630,7 @@ RESULT eServiceMP3::seek(ePtr<iSeekableService> &ptr)
 
 RESULT eServiceMP3::getLength(pts_t &pts)
 {
-       if (!m_gst_playbin)
-               return -1;
-
-       if (m_state != stRunning)
+       if (!m_gst_playbin || m_state != stRunning)
                return -1;
 
        GstFormat fmt = GST_FORMAT_TIME;
@@ -706,9 +766,7 @@ RESULT eServiceMP3::getPlayPosition(pts_t &pts)
        gint64 pos;
        pts = 0;
 
-       if (!m_gst_playbin)
-               return -1;
-       if (m_state != stRunning)
+       if (!m_gst_playbin || m_state != stRunning)
                return -1;
 
        if (audioSink || videoSink)
@@ -792,6 +850,14 @@ RESULT eServiceMP3::getName(std::string &name)
        return 0;
 }
 
+RESULT eServiceMP3::getEvent(ePtr<eServiceEvent> &evt, int nownext)
+{
+       evt = nownext ? m_event_next : m_event_now;
+       if (!evt)
+               return -1;
+       return 0;
+}
+
 int eServiceMP3::getInfo(int w)
 {
        const gchar *tag = 0;
@@ -894,6 +960,24 @@ int eServiceMP3::getInfo(int w)
 
 std::string eServiceMP3::getInfoString(int w)
 {
+       if ( m_sourceinfo.is_streaming )
+       {
+               switch (w)
+               {
+               case sProvider:
+                       return "IPTV";
+               case sServiceref:
+               {
+                       eServiceReference ref(m_ref);
+                       ref.type = eServiceFactoryMP3::id;
+                       ref.path.clear();
+                       return ref.toString();
+               }
+               default:
+                       break;
+               }
+       }
+
        if ( !m_stream_tags && w < sUser && w > 26 )
                return "";
        const gchar *tag = 0;
@@ -1283,8 +1367,9 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
 {
        if (!msg)
                return;
-       gchar *sourceName;
-       GstObject *source;
+       gchar *sourceName = NULL;
+       GstObject *source = NULL;
+       GstElement *subsink = NULL;
        source = GST_MESSAGE_SRC(msg);
        if (!GST_IS_OBJECT(source))
                return;
@@ -1307,12 +1392,6 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                {
                        if(GST_MESSAGE_SRC(msg) != GST_OBJECT(m_gst_playbin))
                        {
-                               //vuplus
-                               if(!strncmp(sourceName, "hls", 3))
-                               {
-                                       //eDebug("HLS Protocol detected : source [%s]", sourceName);
-                                       m_is_hls_stream = 1;
-                               }
                                break;
                        }
 
@@ -1337,9 +1416,9 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                        GValue result = { 0, };
 #endif
                                        GstIterator *children;
-                                       GstElement *subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
-                                       if (subsink)
-                                       {
+                                       subsink = gst_bin_get_by_name(GST_BIN(m_gst_playbin), "subtitle_sink");
+                                       if (subsink)
+                                       {
 #ifdef GSTREAMER_SUBTITLE_SYNC_MODE_BUG
                                                g_object_set (G_OBJECT (subsink), "sync", FALSE, NULL);
 #endif
@@ -1383,6 +1462,9 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
 
                                        setAC3Delay(ac3_delay);
                                        setPCMDelay(pcm_delay);
+
+                                       updateEpgCacheNowNext();
+
                                }       break;
                                case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
                                {
@@ -1428,10 +1510,12 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                                m_event((iPlayableService*)this, evUser+10);
                                }
                        }
-                       else //if( err->domain == 1232 )
+                       else if ( err->domain == GST_RESOURCE_ERROR )
                        {
-                               if ( err->code == 5 )
-                                       m_event((iPlayableService*)this, evUser+20);
+                               if ( err->code == GST_RESOURCE_ERROR_OPEN_READ || err->code == GST_RESOURCE_ERROR_READ )
+                               {
+                                       sourceTimeout();
+                               }
                        }
                        g_error_free(err);
                        break;
@@ -1593,7 +1677,7 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                m_subtitleStreams.push_back(subs);
                                g_free (g_lang);
                        }
-                       m_event((iPlayableService*)this, evUpdatedEventInfo);
+                       m_event((iPlayableService*)this, evUpdatedInfo);
 
                        if ( m_errorInfo.missing_codec != "" )
                        {
@@ -1681,17 +1765,12 @@ void eServiceMP3::gstBusCall(GstBus *bus, GstMessage *msg)
                                        const gchar *name = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
                                        if (!strcmp(name, "souphttpsrc"))
                                        {
-                                               m_streamingsrc_timeout->start(HTTP_TIMEOUT*1000, true);
+                                               if (m_streamingsrc_timeout) {
+                                                       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);
                                        }
-                                       //vuplus
-                                       else if (m_is_hls_stream && !strncmp(name, "queue", 5))
-                                       {
-                                               m_streamingsrc_timeout->stop();
-                                               m_is_hls_stream = 0;
-                                               //eDebug("Stoped response timeout!! : HLS");
-                                       }
                                }
                                if ( GST_IS_PAD(source) )
                                        gst_object_unref(owner);
@@ -1720,6 +1799,18 @@ void eServiceMP3::gstHTTPSourceSetAgent(GObject *object, GParamSpec *unused, gpo
        if (source)
        {
 #if GST_VERSION_MAJOR >= 1
+               if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "timeout") != 0)
+               {
+                       GstElementFactory *factory = gst_element_get_factory(source);
+                       if (factory)
+                       {
+                               const gchar *sourcename = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory));
+                               if (!strcmp(sourcename, "souphttpsrc"))
+                               {
+                                       g_object_set(G_OBJECT(source), "timeout", HTTP_TIMEOUT, NULL);
+                               }
+                       }
+               }
                if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "ssl-strict") != 0)
                {
                        g_object_set(G_OBJECT(source), "ssl-strict", FALSE, NULL);
@@ -1913,6 +2004,13 @@ void eServiceMP3::pullSubtitle(GstBuffer *buffer)
                {
                        if ( subType < stVOB )
                        {
+                               int delay = ePythonConfigQuery::getConfigIntValue("config.subtitles.pango_subtitles_delay");
+                               int subtitle_fps = ePythonConfigQuery::getConfigIntValue("config.subtitles.pango_subtitles_fps");
+
+                               double convert_fps = 1.0;
+                               if (subtitle_fps > 1 && m_framerate > 0)
+                                       convert_fps = subtitle_fps / (double)m_framerate;
+
                                unsigned char line[len+1];
                                SubtitlePage page;
 #if GST_VERSION_MAJOR < 1
@@ -1927,7 +2025,7 @@ void eServiceMP3::pullSubtitle(GstBuffer *buffer)
                                gRGB rgbcol(0xD0,0xD0,0xD0);
                                page.type = SubtitlePage::Pango;
                                page.pango_page.m_elements.push_back(ePangoSubtitlePageElement(rgbcol, (const char*)line));
-                               page.pango_page.m_show_pts = buf_pos / 11111LL;
+                               page.pango_page.m_show_pts = buf_pos / 11111LL + convert_fps + delay;
                                page.pango_page.m_timeout = duration_ns / 1000000;
                                m_subtitle_pages.push_back(page);
                                m_subtitle_sync_timer->start(1, true);
@@ -2110,6 +2208,26 @@ RESULT eServiceMP3::disableSubtitles(eWidget *parent)
 PyObject *eServiceMP3::getCachedSubtitle()
 {
 //     eDebug("eServiceMP3::getCachedSubtitle");
+       bool autoturnon = ePythonConfigQuery::getConfigBoolValue("config.subtitles.pango_autoturnon", true);
+       if (!autoturnon)
+               Py_RETURN_NONE;
+
+       if (!m_subtitleStreams.empty())
+       {
+               int index = 0;
+               if (m_currentSubtitleStream >= 0 && m_currentSubtitleStream < (int)m_subtitleStreams.size())
+               {
+                       index = m_currentSubtitleStream;
+               }
+               ePyObject tuple = PyTuple_New(5);
+               PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2));
+               PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(index));
+               PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(int(m_subtitleStreams[index].type)));
+               PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(0));
+               PyTuple_SET_ITEM(tuple, 4, PyString_FromString(m_subtitleStreams[index].language_code.c_str()));
+               return tuple;
+       }
+
        Py_RETURN_NONE;
 }