cache movie filelengths in .meta file, by luke_s
[enigma2.git] / lib / service / servicedvb.cpp
index 8e8fc5e0c3c34d653ec24b7643ad0daa5a89691a..dcd7017c97ab427b3257557d0b4a02690d57caab 100644 (file)
@@ -31,8 +31,6 @@
 #error no byte order defined!
 #endif
 
-#define TSPATH "/media/hdd"
-
 class eStaticServiceDVBInformation: public iStaticServiceInformation
 {
        DECLARE_REF(eStaticServiceDVBInformation);
@@ -98,7 +96,7 @@ int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const
        return false;
 }
 
-static void PutToDict(ePyObject &dict, const char*key, long value)
+static void PutToDictAsStr(ePyObject &dict, const char*key, long value)
 {
        ePyObject item = PyString_FromFormat("%d", value);
        if (item)
@@ -111,15 +109,17 @@ static void PutToDict(ePyObject &dict, const char*key, long value)
                eDebug("could not create PyObject for %s", key);
 }
 
-extern void PutToDict(ePyObject &dict, const char*key, const char *value);
+extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
+extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
+extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
 
 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
 {
        const char *tmp=0;
        PutToDict(dict, "type", "Satellite");
-       PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "symbolrate", feparm.symbol_rate);
-       PutToDict(dict, "orbital position", feparm.orbital_position);
+       PutToDictAsStr(dict, "frequency", feparm.frequency);
+       PutToDictAsStr(dict, "symbolrate", feparm.symbol_rate);
+       PutToDictAsStr(dict, "orbital position", feparm.orbital_position);
        switch (feparm.inversion)
        {
                case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
@@ -166,15 +166,22 @@ void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &fe
                default:
                case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
                case eDVBFrontendParametersSatellite::System::DVB_S2:
-                       switch(feparm.roll_off)
+                       switch(feparm.rolloff)
                        {
+                               default:
                                case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
                                case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
                                case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
-                               default:
-                               case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
                        }
                        PutToDict(dict, "roll off", tmp);
+                       switch(feparm.pilot)
+                       {
+                               case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
+                               case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
+                               default:
+                               case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
+                       }
+                       PutToDict(dict, "pilot", tmp);
                        tmp="DVB-S2";
                        break;
        }
@@ -184,7 +191,7 @@ void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &fe
 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
 {
        PutToDict(dict, "type", "Terrestrial");
-       PutToDict(dict, "frequency", feparm.frequency);
+       PutToDictAsStr(dict, "frequency", feparm.frequency);
        const char *tmp=0;
        switch (feparm.bandwidth)
        {
@@ -268,8 +275,8 @@ void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
 {
        const char *tmp=0;
        PutToDict(dict, "type", "Cable");
-       PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "symbolrate", feparm.symbol_rate);
+       PutToDictAsStr(dict, "frequency", feparm.frequency);
+       PutToDictAsStr(dict, "symbolrate", feparm.symbol_rate);
        switch (feparm.modulation)
        {
        case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
@@ -402,7 +409,7 @@ RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref
                return -1;
 }
 
-int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
+int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
 {
        if (ref.flags & eServiceReference::isGroup)
        {
@@ -443,7 +450,7 @@ int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref
                                { 2, 1, 3 }  // -T -S -C
                        };
                        ((const eServiceReferenceDVB&)*it).getChannelID(chid);
-                       int tmp=res->canAllocateChannel(chid, chid_ignore);
+                       int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
                        switch(tmp)
                        {
                                case 0:
@@ -529,14 +536,25 @@ int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
        
        eDVBTSTools tstools;
        
+       struct stat s;
+       stat(ref.path.c_str(), &s);
+
        if (tstools.openFile(ref.path.c_str()))
                return 0;
 
+                       /* check if cached data is still valid */
+       if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
+               return m_parser.m_length / 90000;
+
+                       /* otherwise, re-calc length and update meta file */
        pts_t len;
        if (tstools.calcLen(len))
                return 0;
 
-       return len / 90000;
+       m_parser.m_length = len;
+       m_parser.m_filesize = s.st_size;
+       m_parser.updateMeta(ref.path);
+       return m_parser.m_length / 90000;
 }
 
 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
@@ -668,7 +686,11 @@ eServiceFactoryDVB::eServiceFactoryDVB()
        
        eServiceCenter::getPrivInstance(sc);
        if (sc)
-               sc->addServiceFactory(eServiceFactoryDVB::id, this);
+       {
+               std::list<std::string> extensions;
+               extensions.push_back("ts");
+               sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
+       }
 
        m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
        m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
@@ -809,7 +831,7 @@ PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
                                                        sptr->getName(ref, name);
 
                                                        // filter short name brakets
-                                                       unsigned int pos;
+                                                       size_t pos;
                                                        while((pos = name.find("\xc2\x86")) != std::string::npos)
                                                                name.erase(pos,2);
                                                        while((pos = name.find("\xc2\x87")) != std::string::npos)
@@ -1033,7 +1055,6 @@ RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServ
 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
        m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
 {
-       memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
        m_is_primary = 1;
        m_is_pvr = !m_reference.path.empty();
        
@@ -1051,7 +1072,9 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
        
        m_tune_state = -1;
 
-       CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
+       m_subtitle_sync_timer = eTimer::create(eApp);
+
+       CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
 }
 
 eDVBServicePlay::~eDVBServicePlay()
@@ -1096,6 +1119,7 @@ void eDVBServicePlay::serviceEvent(int event)
                        else
                                m_event_handler.start(m_demux, sid);
                }
+               m_event((iPlayableService*)this, evTunedIn);
                break;
        }
        case eDVBServicePMTHandler::eventNoResources:
@@ -1216,8 +1240,8 @@ RESULT eDVBServicePlay::stop()
                        {
                                int perc = play_position * 100LL / length;
                        
-                                       /* only store last play position when between 5% and 95% */
-                               if ((5 < perc) && (perc < 95))
+                                       /* only store last play position when between 1% and 99% */
+                               if ((1 < perc) && (perc < 99))
                                        m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
                        }
                        m_cuesheet_changed = 1;
@@ -1480,9 +1504,16 @@ RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
        {
                if (!m_timeshift_enabled)
                {
-                               /* we need enough diskspace */
+                       /* query config path */
+                       std::string tspath;
+                       if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
+                               eDebug("could not query ts path from config");
+                               return -4;
+                       }
+                       tspath.append("/");
+                       /* we need enough diskspace */
                        struct statfs fs;
-                       if (statfs(TSPATH "/.", &fs) < 0)
+                       if (statfs(tspath.c_str(), &fs) < 0)
                        {
                                eDebug("statfs failed!");
                                return -2;
@@ -1557,42 +1588,43 @@ RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
 int eDVBServicePlay::getInfo(int w)
 {
        eDVBServicePMTHandler::program program;
-       
+
        if (w == sCAIDs)
                return resIsPyObject;
 
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
-       
+
        int no_program_info = 0;
-       
+
        if (h.getProgramInfo(program))
                no_program_info = 1;
-       
+
        switch (w)
        {
-#if HAVE_DVB_API_VERSION >= 3
        case sVideoHeight:
-               if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
-                       return m_videoEventData.height;
-               return -1;
+               if (m_decoder)
+                       return m_decoder->getVideoHeight();
+               break;
        case sVideoWidth:
-               if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
-                       return m_videoEventData.width;
-               return -1;
-#else
-#warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
-#endif
+               if (m_decoder)
+                       return m_decoder->getVideoWidth();
+               break;
+       case sFrameRate:
+               if (m_decoder)
+                       return m_decoder->getVideoFrameRate();
+               break;
+       case sProgressive:
+               if (m_decoder)
+                       return m_decoder->getVideoProgressive();
+               break;
        case sAspect:
-#if HAVE_DVB_API_VERSION >= 3
-               if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
-                       return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
-               else
-#else
-#warning "FIXMEE implement sAspect for old DVB API"
-#endif
+       {
+               int aspect = -1;
+               if (m_decoder)
+                       aspect = m_decoder->getVideoAspect();
                if (no_program_info)
-                       return -1; 
-               else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
+                       break;
+               else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
                {
                        ePtr<eServiceEvent> evt;
                        if (!m_event_handler.getEvent(evt, 0))
@@ -1629,7 +1661,10 @@ int eDVBServicePlay::getInfo(int w)
                                }
                        }
                }
-               return -1;
+               else
+                       return aspect;
+               break;
+       }
        case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
        case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
        case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
@@ -1645,8 +1680,9 @@ int eDVBServicePlay::getInfo(int w)
        case sServiceref: return resIsString;
        case sDVBState: return m_tune_state;
        default:
-               return -1;
+               break;
        }
+       return -1;
 }
 
 std::string eDVBServicePlay::getInfoString(int w)
@@ -1991,8 +2027,6 @@ PyObject *eDVBServiceBase::getTransponderData(bool original)
                                        eDVBFrontendParametersSatellite osat;
                                        if (!feparm->getDVBS(osat))
                                        {
-                                               void PutToDict(ePyObject &, const char*, long);
-                                               void PutToDict(ePyObject &, const char*, const char*);
                                                PutToDict(ret, "orbital_position", osat.orbital_position);
                                                const char *tmp = "UNKNOWN";
                                                switch(osat.polarisation)
@@ -2070,12 +2104,23 @@ RESULT eDVBServicePlay::startTimeshift()
        if (!m_record)
                return -3;
 
-       char templ[]=TSPATH "/timeshift.XXXXXX";
+       std::string tspath;
+       if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
+               eDebug("could not query ts path");
+               return -5;
+       }
+       tspath.append("/timeshift.XXXXXX");
+       char* templ;
+       templ = new char[tspath.length() + 1];
+       strcpy(templ, tspath.c_str());
+
        m_timeshift_fd = mkstemp(templ);
-       m_timeshift_file = templ;
-       
+       m_timeshift_file = std::string(templ);
+
        eDebug("recording to %s", templ);
-       
+
+       delete [] templ;
+
        if (m_timeshift_fd < 0)
        {
                m_record = 0;
@@ -2137,8 +2182,8 @@ PyObject *eDVBServicePlay::getCutList()
        for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
        {
                ePyObject tuple = PyTuple_New(2);
-               PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
-               PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
+               PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
+               PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
                PyList_Append(list, tuple);
                Py_DECREF(tuple);
        }
@@ -2881,7 +2926,7 @@ void eDVBServicePlay::checkSubtitleTiming()
                } else
                {
                        eDebug("start subtitle delay %d", diff / 90);
-                       m_subtitle_sync_timer.start(diff / 90, 1);
+                       m_subtitle_sync_timer->start(diff / 90, 1);
                        break;
                }
        }
@@ -2938,8 +2983,19 @@ void eDVBServicePlay::setPCMDelay(int delay)
 
 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
 {
-       memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
-       m_event((iPlayableService*)this, evVideoSizeChanged);
+       switch(event.type) {
+               case iTSMPEGDecoder::videoEvent::eventSizeChanged:
+                       m_event((iPlayableService*)this, evVideoSizeChanged);
+                       break;
+               case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
+                       m_event((iPlayableService*)this, evVideoFramerateChanged);
+                       break;
+               case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
+                       m_event((iPlayableService*)this, evVideoProgressiveChanged);
+                       break;
+               default:
+                       break;
+       }
 }
 
 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
@@ -2953,18 +3009,16 @@ PyObject *eDVBServicePlay::getStreamingData()
        eDVBServicePMTHandler::program program;
        if (m_service_handler.getProgramInfo(program))
        {
-               Py_INCREF(Py_None);
-               return Py_None;
+               Py_RETURN_NONE;
        }
 
-       PyObject *r = program.createPythonObject();
+       ePyObject r = program.createPythonObject();
        ePtr<iDVBDemux> demux;
        if (!m_service_handler.getDataDemux(demux))
        {
                uint8_t demux_id;
-               demux->getCADemuxID(demux_id);
-               
-               PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
+               if (!demux->getCADemuxID(demux_id))
+                       PutToDict(r, "demux", demux_id);
        }
 
        return r;