add background file eraser class for asynchronous file deletion
[enigma2.git] / lib / service / servicedvb.cpp
index 248a548265e616407a808b21e84d51d6188c1a13..033d13d3906702be1a6fb0ae843a59a1a6e162c6 100644 (file)
@@ -10,7 +10,9 @@
 #include <lib/dvb/db.h>
 #include <lib/dvb/decoder.h>
 
+#include <lib/components/file_eraser.h>
 #include <lib/service/servicedvbrecord.h>
+#include <lib/service/event.h>
 #include <lib/dvb/metaparser.h>
 #include <lib/dvb/tstools.h>
 #include <lib/python/python.h>
@@ -20,6 +22,8 @@
 #include <byteswap.h>
 #include <netinet/in.h>
 
+#include <dvbsi++/event_information_section.h>
+
 #ifndef BYTE_ORDER
 #error no byte order defined!
 #endif
@@ -230,11 +234,18 @@ RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
                if (getListOfFilenames(res))
                        return -1;
                
+               eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
+               if (!eraser)
+                       eDebug("FATAL !! can't get background file eraser");
+               
                                /* TODO: deferred removing.. */
                for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
                {
                        eDebug("Removing %s...", i->c_str());
-                       ::unlink(i->c_str());
+                       if (eraser)
+                               eraser->erase(i->c_str());
+                       else
+                               ::unlink(i->c_str());
                }
                
                return 0;
@@ -245,7 +256,25 @@ RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string
 {
        res.clear();
        res.push_back(m_ref.path);
+
+// handling for old splitted recordings (enigma 1)
+       char buf[255];
+       int slice=1;
+       while(true)
+       {
+               snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
+               struct stat s;
+               if (stat(buf, &s) < 0)
+                       break;
+               res.push_back(buf);
+       }       
+
        res.push_back(m_ref.path + ".meta");
+       res.push_back(m_ref.path + ".ap");
+       res.push_back(m_ref.path + ".cuts");
+       std::string tmp = m_ref.path;
+       tmp.erase(m_ref.path.length()-3);
+       res.push_back(tmp + ".eit");
        return 0;
 }
 
@@ -545,9 +574,7 @@ eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *serv
        CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
 
        m_cuesheet_changed = 0;
-       
-       if (m_is_pvr)
-               loadCuesheet();
+       m_cutlist_enabled = 1;
 }
 
 eDVBServicePlay::~eDVBServicePlay()
@@ -629,6 +656,9 @@ void eDVBServicePlay::serviceEventTimeshift(int event)
                if (m_timeshift_active)
                        updateDecoder();
                break;
+       case eDVBServicePMTHandler::eventSOF:
+               m_event((iPlayableService*)this, evSOF);
+               break;
        case eDVBServicePMTHandler::eventEOF:
                switchToLive();
                break;
@@ -642,8 +672,39 @@ RESULT eDVBServicePlay::start()
                   two (one for decoding, one for data source), as we must be prepared
                   to start recording from the data demux. */
        m_cue = new eCueSheet();
+
        m_first_program_info = 1;
-       r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr, m_cue);
+       eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
+       r = m_service_handler.tune(service, m_is_pvr, m_cue);
+       
+               /* inject EIT if there is a stored one */
+       if (m_is_pvr)
+       {
+               std::string filename = service.path;
+               filename.erase(filename.length()-2, 2);
+               filename+="eit";
+               int fd = ::open( filename.c_str(), O_RDONLY );
+               if ( fd > -1 )
+               {
+                       __u8 buf[4096];
+                       int rd = ::read(fd, buf, 4096);
+                       ::close(fd);
+                       if ( rd > 12 /*EIT_LOOP_SIZE*/ )
+                       {
+                               Event ev(buf);
+                               ePtr<eServiceEvent> event = new eServiceEvent;
+                               ePtr<eServiceEvent> empty;
+                               event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
+                               m_event_handler.inject(event, 0);
+                               m_event_handler.inject(empty, 1);
+                               eDebug("injected");
+                       }
+               }
+       }
+       
+       if (m_is_pvr)
+               loadCuesheet();
+
        m_event(this, evStart);
        m_event((iPlayableService*)this, evSeekableStatusChanged);
        return 0;
@@ -802,12 +863,18 @@ RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
        if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
                return -1;
        
+       int mode = 1;
+       
+                       /* HACK until we have skip-AP api */
+       if ((to > 0) && (to < 100))
+               mode = 2;
+       
        to *= direction;
        
        if (!m_cue)
                return 0;
        
-       m_cue->seekTo(1, to);
+       m_cue->seekTo(mode, to);
        return 0;
 }
 
@@ -1111,6 +1178,52 @@ int eDVBServicePlay::getFrontendInfo(int w)
        return fe->readFrontendData(w);
 }
 
+PyObject *eDVBServicePlay::getFrontendData(bool original)
+{
+       PyObject *ret=0;
+
+       eUsePtr<iDVBChannel> channel;
+       if(!m_service_handler.getChannel(channel))
+       {
+               ePtr<iDVBFrontend> fe;
+               if(!channel->getFrontend(fe))
+               {
+                       ret = fe->readTransponderData(original);
+                       if (ret)
+                       {
+                               ePtr<iDVBFrontendParameters> feparm;
+                               channel->getCurrentFrontendParameters(feparm);
+                               if (feparm)
+                               {
+                                       eDVBFrontendParametersSatellite osat;
+                                       if (!feparm->getDVBS(osat))
+                                       {
+                                               void PutToDict(PyObject *, const char*, long);
+                                               void PutToDict(PyObject *, const char*, const char*);
+                                               PutToDict(ret, "orbital_position", osat.orbital_position);
+                                               const char *tmp = "UNKNOWN";
+                                               switch(osat.polarisation)
+                                               {
+                                                       case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
+                                                       case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
+                                                       case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
+                                                       case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
+                                                       default:break;
+                                               }
+                                               PutToDict(ret, "polarization", tmp);
+                                       }
+                               }
+                       }
+               }
+       }
+       if (!ret)
+       {
+               ret = Py_None;
+               Py_INCREF(ret);
+       }
+       return ret;
+}
+
 int eDVBServicePlay::getNumberOfSubservices()
 {
        ePtr<eServiceEvent> evt;
@@ -1258,6 +1371,15 @@ void eDVBServicePlay::setCutList(PyObject *list)
                eDebug("adding %08llx, %d", pts, type);
        }
        m_cuesheet_changed = 1;
+       
+       cutlistToCuesheet();
+       m_event((iPlayableService*)this, evCuesheetChanged);
+}
+
+void eDVBServicePlay::setCutListEnable(int enable)
+{
+       m_cutlist_enabled = enable;
+       cutlistToCuesheet();
 }
 
 void eDVBServicePlay::updateTimeshiftPids()
@@ -1340,6 +1462,7 @@ void eDVBServicePlay::switchToTimeshift()
        r.path = m_timeshift_file;
        
        m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
+       updateDecoder(); /* mainly to switch off PCR */
 }
 
 void eDVBServicePlay::updateDecoder()
@@ -1474,6 +1597,8 @@ void eDVBServicePlay::loadCuesheet()
                eDebug("cutfile not found!");
        
        m_cuesheet_changed = 0;
+       cutlistToCuesheet();
+       m_event((iPlayableService*)this, evCuesheetChanged);
 }
 
 void eDVBServicePlay::saveCuesheet()
@@ -1505,6 +1630,57 @@ void eDVBServicePlay::saveCuesheet()
        m_cuesheet_changed = 0;
 }
 
+void eDVBServicePlay::cutlistToCuesheet()
+{
+       if (!m_cue)
+       {
+               eDebug("no cue sheet");
+               return;
+       }       
+       m_cue->clear();
+       
+       if (!m_cutlist_enabled)
+       {
+               m_cue->commitSpans();
+               eDebug("cutlists where disabled");
+               return;
+       }
+
+       pts_t in = 0, out = 0, length = 0;
+       
+       getLength(length);
+               
+       std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
+       
+       while (1)
+       {
+               if (i == m_cue_entries.end())
+                       out = length;
+               else {
+                       if (i->what == 0) /* in */
+                       {
+                               in = i++->where;
+                               continue;
+                       } else if (i->what == 1) /* out */
+                               out = i++->where;
+                       else /* mark */
+                       {
+                               i++;
+                               continue;
+                       }
+               }
+               
+               if (in != out)
+                       m_cue->addSourceSpan(in, out);
+               
+               in = length;
+               
+               if (i == m_cue_entries.end())
+                       break;
+       }
+       m_cue->commitSpans();
+}
+
 DEFINE_REF(eDVBServicePlay)
 
 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");