add ability to copy providers or all services from satellites to favourites (this...
[enigma2.git] / lib / service / servicedvb.cpp
index d8567fd83fd6930d736760c3f373b3dfea1cec8d..827b7f362702ec89f734852ded841dd453c0ad4b 100644 (file)
@@ -13,6 +13,7 @@
 #include <lib/service/servicedvbrecord.h>
 #include <lib/dvb/metaparser.h>
 #include <lib/dvb/tstools.h>
+#include <lib/python/python.h>
 
 class eStaticServiceDVBInformation: public iStaticServiceInformation
 {
@@ -305,7 +306,32 @@ RESULT eDVBServiceList::startQuery()
        return 0;
 }
 
-RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
+RESULT eDVBServiceList::getContent(PyObject *list, bool sorted)
+{
+       eServiceReferenceDVB ref;
+
+       if (!m_query || !list || !PyList_Check(list))
+               return -1;
+
+       std::list<eServiceReferenceDVB> tmplist;
+
+       while (!m_query->getNextResult(ref))
+               tmplist.push_back(ref);
+
+       if (sorted)
+               tmplist.sort(iListableServiceCompare(this));
+
+       for (std::list<eServiceReferenceDVB>::iterator it(tmplist.begin());
+               it != tmplist.end(); ++it)
+       {
+               PyObject *refobj = New_eServiceReference(*it);
+               PyList_Append(list, refobj);
+               Py_DECREF(refobj);
+       }
+       return 0;
+}
+
+RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
 {
        eServiceReferenceDVB ref;
        
@@ -314,6 +340,10 @@ RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
        
        while (!m_query->getNextResult(ref))
                list.push_back(ref);
+
+       if (sorted)
+               list.sort(iListableServiceCompare(this));
+
        return 0;
 }
 
@@ -379,6 +409,13 @@ RESULT eDVBServiceList::flushChanges()
        return m_bouquet->flushChanges();
 }
 
+RESULT eDVBServiceList::setListName(const std::string &name)
+{
+       if (!m_bouquet)
+               return -1;
+       return m_bouquet->setListName(name);
+}
+
 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
 {
        ePtr<eDVBService> service;
@@ -553,7 +590,10 @@ void eDVBServicePlay::serviceEvent(int event)
                break;
        }
        case eDVBServicePMTHandler::eventEOF:
+       {
                m_event((iPlayableService*)this, evEnd);
+               break;
+       }
        }
 }
 
@@ -565,6 +605,9 @@ void eDVBServicePlay::serviceEventTimeshift(int event)
                if (m_timeshift_active)
                        updateDecoder();
                break;
+       case eDVBServicePMTHandler::eventEOF:
+               switchToLive();
+               break;
        }
 }
 
@@ -576,6 +619,7 @@ RESULT eDVBServicePlay::start()
                   to start recording from the data demux. */
        r = m_service_handler.tune((eServiceReferenceDVB&)m_reference, m_is_pvr);
        m_event(this, evStart);
+       m_event((iPlayableService*)this, evSeekableStatusChanged);
        return 0;
 }
 
@@ -592,6 +636,9 @@ RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &ev
 
 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
 {
+               /* note: we check for timeshift to be enabled,
+                  not neccessary active. if you pause when timeshift
+                  is not active, you should activate it when unpausing */
        if ((!m_is_pvr) && (!m_timeshift_enabled))
        {
                ptr = 0;
@@ -620,7 +667,7 @@ RESULT eDVBServicePlay::setFastForward(int ratio)
     
 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
 {
-       if (m_is_pvr || m_timeshift_enabled)
+       if (m_is_pvr || m_timeshift_active)
        {
                ptr = this;
                return 0;
@@ -645,11 +692,6 @@ RESULT eDVBServicePlay::getLength(pts_t &len)
 
 RESULT eDVBServicePlay::pause()
 {
-       if (m_timeshift_enabled && !m_timeshift_active)
-       {
-               switchToTimeshift();
-               return 0;
-       }
        if (!m_is_paused && m_decoder)
        {
                m_is_paused = 1;
@@ -677,7 +719,7 @@ RESULT eDVBServicePlay::seekTo(pts_t to)
 
        ePtr<iDVBPVRChannel> pvr_channel;
        
-       if (m_service_handler.getPVRChannel(pvr_channel))
+       if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
                return -1;
        
        return pvr_channel->seekTo(m_decode_demux, 0, to);
@@ -692,7 +734,7 @@ RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
 
        ePtr<iDVBPVRChannel> pvr_channel;
        
-       if (m_service_handler.getPVRChannel(pvr_channel))
+       if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
                return -1;
        
        to *= direction;
@@ -707,7 +749,7 @@ RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
        if (!m_decode_demux)
                return -1;
        
-       if (m_service_handler.getPVRChannel(pvr_channel))
+       if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
                return -1;
        
        return pvr_channel->getCurrentPosition(m_decode_demux, pos, 1);
@@ -757,6 +799,11 @@ RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
 
 RESULT eDVBServicePlay::getName(std::string &name)
 {
+       if (m_is_pvr)
+       {
+               ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
+               return i->getName(m_reference, name);
+       }
        if (m_dvb_service)
        {
                m_dvb_service->getName(m_reference, name);
@@ -828,7 +875,7 @@ int eDVBServicePlay::getInfo(int w)
        case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
        case sPCRPID: return program.pcrPid;
        case sPMTPID: return program.pmtPid;
-       case sTXTPID: return -1;
+       case sTXTPID: return program.textPid;
        case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
        case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
        case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
@@ -997,7 +1044,7 @@ RESULT eDVBServicePlay::startTimeshift()
        
        if (m_timeshift_fd < 0)
        {
-               delete m_record;
+               m_record = 0;
                return -4;
        }
                
@@ -1021,15 +1068,33 @@ RESULT eDVBServicePlay::stopTimeshift()
        m_timeshift_enabled = 0;
        
        m_record->stop();
-       delete m_record;
+       m_record = 0;
        
        close(m_timeshift_fd);
        remove(m_timeshift_file.c_str());
        
-       eDebug("timeshift disabled");
        return 0;
 }
 
+int eDVBServicePlay::isTimeshiftActive()
+{
+       return m_timeshift_enabled && m_timeshift_active;
+}
+
+RESULT eDVBServicePlay::activateTimeshift()
+{
+       if (!m_timeshift_enabled)
+               return -1;
+       
+       if (!m_timeshift_active)
+       {
+               switchToTimeshift();
+               return 0;
+       }
+       
+       return -2;
+}
+
 void eDVBServicePlay::updateTimeshiftPids()
 {
        if (!m_record)
@@ -1044,7 +1109,10 @@ void eDVBServicePlay::updateTimeshiftPids()
                pids_to_record.insert(0); // PAT
                if (program.pmtPid != -1)
                        pids_to_record.insert(program.pmtPid); // PMT
-               
+
+               if (program.textPid != -1)
+                       pids_to_record.insert(program.textPid); // Videotext
+
                for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
                        i(program.videoStreams.begin()); 
                        i != program.videoStreams.end(); ++i)
@@ -1066,7 +1134,7 @@ void eDVBServicePlay::updateTimeshiftPids()
                                pids_to_record.begin(), pids_to_record.end(), 
                                std::inserter(new_pids, new_pids.begin())
                                );
-               
+
                for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
                        m_record->addPID(*i);
 
@@ -1077,7 +1145,6 @@ void eDVBServicePlay::updateTimeshiftPids()
 
 void eDVBServicePlay::switchToLive()
 {
-       eDebug("SwitchToLive");
        if (!m_timeshift_active)
                return;
        
@@ -1087,12 +1154,13 @@ void eDVBServicePlay::switchToLive()
        m_service_handler_timeshift.free();
        m_timeshift_active = 0;
        
+       m_event((iPlayableService*)this, evSeekableStatusChanged);
+       
        updateDecoder();
 }
 
 void eDVBServicePlay::switchToTimeshift()
 {
-       eDebug("SwitchToTimeshift");
        if (m_timeshift_active)
                return;
        
@@ -1100,17 +1168,18 @@ void eDVBServicePlay::switchToTimeshift()
        m_decoder = 0;
        
        m_timeshift_active = 1;
+
+       m_event((iPlayableService*)this, evSeekableStatusChanged);
        
        eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
        r.path = m_timeshift_file;
        
-       eDebug("ok, re-tuning to %s", r.toString().c_str());
        m_service_handler_timeshift.tune(r, 1); /* use the decoder demux for everything */
 }
 
 void eDVBServicePlay::updateDecoder()
 {
-       int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1;
+       int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
        eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
 
        eDVBServicePMTHandler::program program;
@@ -1153,9 +1222,10 @@ void eDVBServicePlay::updateDecoder()
                        }
                        eDebugNoNewLine(")");
                }
-               eDebug(", and the pcr pid is %04x", program.pcrPid);
-               if (program.pcrPid != 0x1fff)
-                       pcrpid = program.pcrPid;
+               eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
+               pcrpid = program.pcrPid;
+               eDebug(", and the text pid is %04x", program.textPid);
+               tpid = program.textPid;
        }
 
        if (!m_decoder)
@@ -1174,27 +1244,29 @@ void eDVBServicePlay::updateDecoder()
                        m_decoder->setSyncPCR(pcrpid);
                else
                        m_decoder->setSyncPCR(-1);
+               m_decoder->setTextPID(tpid);
                m_decoder->start();
 // how we can do this better?
 // update cache pid when the user changed the audio track or video track
 // TODO handling of difference audio types.. default audio types..
                                
-                               /* don't worry about non-existing services, nor pvr services */
-                       if (m_dvb_service && !m_is_pvr)
+               /* don't worry about non-existing services, nor pvr services */
+               if (m_dvb_service && !m_is_pvr)
+               {
+                       if (apidtype == eDVBAudio::aMPEG)
                        {
-                               if (apidtype == eDVBAudio::aMPEG)
-                               {
-                                       m_dvb_service->setCachePID(eDVBService::cAPID, apid);
-                                       m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
-                               }
-                               else
-                               {
-                                       m_dvb_service->setCachePID(eDVBService::cAPID, -1);
-                                       m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
-                               }
-                               m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
-                               m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
+                               m_dvb_service->setCachePID(eDVBService::cAPID, apid);
+                               m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
                        }
+                       else
+                       {
+                               m_dvb_service->setCachePID(eDVBService::cAPID, -1);
+                               m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
+                       }
+                       m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
+                       m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
+                       m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
+               }
        }
 }