fix seekable status when service is already running, only show infobar if InfoBarShow...
[enigma2.git] / lib / service / servicedvb.cpp
index ea014a19f61702ab07307793417243722d041e3d..173f471bf733f65362395e54443e4503b4cc3a35 100644 (file)
@@ -65,16 +65,7 @@ RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::
                                if (!service_center->info(parent, service_info))
                                {
                                        if (!service_info->getName(parent, name))
-                                       {
-                                               // just show short name
-                                               unsigned int pos = name.find("\xc2\x86");
-                                               if ( pos != std::string::npos )
-                                                       name.erase(0, pos+2);
-                                               pos = name.find("\xc2\x87");
-                                               if ( pos != std::string::npos )
-                                                       name.erase(pos);
-                                               name+=" - ";
-                                       }
+                                               name=buildShortName(name) + " - ";
                                }
                        }
                }
@@ -730,6 +721,7 @@ RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sort
 //   S = Service Reference (as python string object .. same as ref.toString())
 //   C = Service Reference (as python string object .. same as ref.toCompareString())
 //   N = Service Name (as python string object)
+//   n = Short Service Name (short name brakets used) (as python string object)
 //   when exactly one return value per service is selected in the format string,
 //   then each value is directly a list entry
 //   when more than one value is returned per service, then the list is a list of
@@ -750,7 +742,7 @@ PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
                ePtr<iStaticServiceInformation> sptr;
                eServiceCenterPtr service_center;
 
-               if (strchr(format, 'N'))
+               if (strchr(format, 'N') || strchr(format, 'n'))
                        eServiceCenter::getPrivInstance(service_center);
 
                ret = PyList_New(services);
@@ -782,6 +774,30 @@ PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
                                                {
                                                        std::string name;
                                                        sptr->getName(ref, name);
+
+                                                       // filter short name brakets
+                                                       unsigned int pos;
+                                                       while((pos = name.find("\xc2\x86")) != std::string::npos)
+                                                               name.erase(pos,2);
+                                                       while((pos = name.find("\xc2\x87")) != std::string::npos)
+                                                               name.erase(pos,2);
+
+                                                       if (name.length())
+                                                               tmp = PyString_FromString(name.c_str());
+                                               }
+                                       }
+                                       if (!tmp)
+                                               tmp = PyString_FromString("<n/a>");
+                                       break;
+                               case 'n':  // short service name
+                                       if (service_center)
+                                       {
+                                               service_center->info(ref, sptr);
+                                               if (sptr)
+                                               {
+                                                       std::string name;
+                                                       sptr->getName(ref, name);
+                                                       name = buildShortName(name);
                                                        if (name.length())
                                                                tmp = PyString_FromString(name.c_str());
                                                }
@@ -1049,6 +1065,7 @@ void eDVBServicePlay::serviceEvent(int event)
                }
                break;
        }
+       case eDVBServicePMTHandler::eventNoResources:
        case eDVBServicePMTHandler::eventNoPAT:
        case eDVBServicePMTHandler::eventNoPATEntry:
        case eDVBServicePMTHandler::eventNoPMT:
@@ -1094,7 +1111,8 @@ void eDVBServicePlay::serviceEventTimeshift(int event)
                m_event((iPlayableService*)this, evSOF);
                break;
        case eDVBServicePMTHandler::eventEOF:
-               switchToLive();
+               if ((!m_is_paused) && (m_skipmode >= 0))
+                       switchToLive();
                break;
        }
 }
@@ -1107,6 +1125,8 @@ RESULT eDVBServicePlay::start()
                   to start recording from the data demux. */
        if (m_is_pvr)
                m_cue = new eCueSheet();
+       else
+               m_event(this, evStart);
 
        m_first_program_info = 1;
        eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
@@ -1128,10 +1148,10 @@ RESULT eDVBServicePlay::start()
        }
 
        if (m_is_pvr)
+       {
                loadCuesheet();
-
-       m_event(this, evStart);
-       m_event((iPlayableService*)this, evSeekableStatusChanged);
+               m_event(this, evStart);
+       }
        return 0;
 }
 
@@ -1140,7 +1160,7 @@ RESULT eDVBServicePlay::stop()
                /* add bookmark for last play position */
        if (m_is_pvr)
        {
-               pts_t play_position;
+               pts_t play_position, length;
                if (!getPlayPosition(play_position))
                {
                                /* remove last position */
@@ -1155,7 +1175,17 @@ RESULT eDVBServicePlay::stop()
                                        ++i;
                        }
                        
-                       m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
+                       if (getLength(length))
+                               length = 0;
+                       
+                       if (length)
+                       {
+                               int perc = play_position * 100LL / length;
+                       
+                                       /* only store last play position when between 5% and 95% */
+                               if ((5 < perc) && (perc < 95))
+                                       m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
+                       }
                        m_cuesheet_changed = 1;
                }
        }
@@ -1172,7 +1202,7 @@ RESULT eDVBServicePlay::stop()
                if (!::stat(m_reference.path.c_str(), &s))
                        saveCuesheet();
        }
-       
+       m_event((iPlayableService*)this, evStopped);
        return 0;
 }
 
@@ -1454,7 +1484,7 @@ RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
        return 0;
 }
 
-RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
+RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
 {
        ptr = this;
        return 0;
@@ -1684,8 +1714,8 @@ int eDVBServicePlay::selectAudioStream(int i)
        if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
                return -4;
 
-       if (m_radiotext_parser)
-               m_radiotext_parser->start(program.audioStreams[i].pid);
+       if (m_rds_decoder)
+               m_rds_decoder->start(program.audioStreams[i].pid);
 
        if (m_dvb_service && !m_is_pvr)
        {
@@ -1722,20 +1752,81 @@ RESULT eDVBServicePlay::selectChannel(int i)
        return 0;
 }
 
-std::string eDVBServicePlay::getRadioText(int x)
+std::string eDVBServicePlay::getText(int x)
 {
-       if (m_radiotext_parser)
+       if (m_rds_decoder)
                switch(x)
                {
-                       case 0:
-                               return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
+                       case RadioText:
+                               return convertLatin1UTF8(m_rds_decoder->getRadioText());
+                       case RtpText:
+                               return convertLatin1UTF8(m_rds_decoder->getRtpText());
                }
        return "";
 }
 
-void eDVBServicePlay::radioTextUpdated()
+void eDVBServicePlay::rdsDecoderEvent(int what)
+{
+       switch(what)
+       {
+               case eDVBRdsDecoder::RadioTextChanged:
+                       m_event((iPlayableService*)this, evUpdatedRadioText);
+                       break;
+               case eDVBRdsDecoder::RtpTextChanged:
+                       m_event((iPlayableService*)this, evUpdatedRtpText);
+                       break;
+               case eDVBRdsDecoder::RassInteractivePicMaskChanged:
+                       m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
+                       break;
+               case eDVBRdsDecoder::RecvRassSlidePic:
+                       m_event((iPlayableService*)this, evUpdatedRassSlidePic);
+                       break;
+       }
+}
+
+void eDVBServicePlay::showRassSlidePicture()
+{
+       if (m_rds_decoder)
+       {
+               if (m_decoder)
+               {
+                       std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
+                       if (rass_slide_pic.length())
+                               m_decoder->showSinglePic(rass_slide_pic.c_str());
+                       else
+                               eDebug("empty filename for rass slide picture received!!");
+               }
+               else
+                       eDebug("no MPEG Decoder to show iframes avail");
+       }
+       else
+               eDebug("showRassSlidePicture called.. but not decoder");
+}
+
+void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
+{
+       if (m_rds_decoder)
+       {
+               if (m_decoder)
+               {
+                       std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
+                       if (rass_interactive_pic.length())
+                               m_decoder->showSinglePic(rass_interactive_pic.c_str());
+                       else
+                               eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
+               }
+               else
+                       eDebug("no MPEG Decoder to show iframes avail");
+       }
+       else
+               eDebug("showRassInteractivePic called.. but not decoder");
+}
+
+ePyObject eDVBServicePlay::getRassInteractiveMask()
 {
-       m_event((iPlayableService*)this, evUpdatedRadioText);
+       if (m_rds_decoder)
+               return m_rds_decoder->getRassPictureMask();
+       Py_RETURN_NONE;
 }
 
 int eDVBServiceBase::getFrontendInfo(int w)
@@ -1749,19 +1840,54 @@ int eDVBServiceBase::getFrontendInfo(int w)
        return fe->readFrontendData(w);
 }
 
-PyObject *eDVBServiceBase::getFrontendData(bool original)
+PyObject *eDVBServiceBase::getFrontendData()
 {
-       ePyObject ret;
+       ePyObject ret = PyDict_New();
+       if (ret)
+       {
+               eUsePtr<iDVBChannel> channel;
+               if(!m_service_handler.getChannel(channel))
+               {
+                       ePtr<iDVBFrontend> fe;
+                       if(!channel->getFrontend(fe))
+                               fe->getFrontendData(ret);
+               }
+       }
+       else
+               Py_RETURN_NONE;
+       return ret;
+}
 
-       eUsePtr<iDVBChannel> channel;
-       if(!m_service_handler.getChannel(channel))
+PyObject *eDVBServiceBase::getFrontendStatus()
+{
+       ePyObject ret = PyDict_New();
+       if (ret)
+       {
+               eUsePtr<iDVBChannel> channel;
+               if(!m_service_handler.getChannel(channel))
+               {
+                       ePtr<iDVBFrontend> fe;
+                       if(!channel->getFrontend(fe))
+                               fe->getFrontendStatus(ret);
+               }
+       }
+       else
+               Py_RETURN_NONE;
+       return ret;
+}
+
+PyObject *eDVBServiceBase::getTransponderData(bool original)
+{
+       ePyObject ret = PyDict_New();
+       if (ret)
        {
-               ePtr<iDVBFrontend> fe;
-               if(!channel->getFrontend(fe))
+               eUsePtr<iDVBChannel> channel;
+               if(!m_service_handler.getChannel(channel))
                {
-                       ret = fe->readTransponderData(original);
-                       if (ret)
+                       ePtr<iDVBFrontend> fe;
+                       if(!channel->getFrontend(fe))
                        {
+                               fe->getTransponderData(ret, original);
                                ePtr<iDVBFrontendParameters> feparm;
                                channel->getCurrentFrontendParameters(feparm);
                                if (feparm)
@@ -1787,11 +1913,30 @@ PyObject *eDVBServiceBase::getFrontendData(bool original)
                        }
                }
        }
-       if (!ret)
+       else
                Py_RETURN_NONE;
        return ret;
 }
 
+PyObject *eDVBServiceBase::getAll(bool original)
+{
+       ePyObject ret = getTransponderData(original);
+       if (ret != Py_None)
+       {
+               eUsePtr<iDVBChannel> channel;
+               if(!m_service_handler.getChannel(channel))
+               {
+                       ePtr<iDVBFrontend> fe;
+                       if(!channel->getFrontend(fe))
+                       {
+                               fe->getFrontendData(ret);
+                               fe->getFrontendStatus(ret);
+                       }
+               }
+       }
+       return ret;
+}
+
 int eDVBServicePlay::getNumberOfSubservices()
 {
        ePtr<eServiceEvent> evt;
@@ -1865,7 +2010,7 @@ RESULT eDVBServicePlay::stopTimeshift()
        
        close(m_timeshift_fd);
        eDebug("remove timeshift file");
-       remove(m_timeshift_file.c_str());
+       eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
        
        return 0;
 }
@@ -1980,6 +2125,11 @@ void eDVBServicePlay::updateTimeshiftPids()
                        i != program.audioStreams.end(); ++i)
                                pids_to_record.insert(i->pid);
 
+               for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
+                       i(program.subtitleStreams.begin());
+                       i != program.subtitleStreams.end(); ++i)
+                               pids_to_record.insert(i->pid);
+
                std::set<int> new_pids, obsolete_pids;
                
                std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
@@ -2009,11 +2159,12 @@ void eDVBServicePlay::switchToLive()
        m_decoder = 0;
        m_decode_demux = 0;
        m_teletext_parser = 0;
-       m_radiotext_parser = 0;
+       m_rds_decoder = 0;
        m_subtitle_parser = 0;
        m_new_dvb_subtitle_page_connection = 0;
        m_new_subtitle_page_connection = 0;
-       m_radiotext_updated_connection = 0;
+       m_rds_decoder_event_connection = 0;
+       m_video_event_connection = 0;
 
                /* free the timeshift service handler, we need the resources */
        m_service_handler_timeshift.free();
@@ -2032,22 +2183,26 @@ void eDVBServicePlay::switchToTimeshift()
        m_decode_demux = 0;
        m_decoder = 0;
        m_teletext_parser = 0;
-       m_radiotext_parser = 0;
+       m_rds_decoder = 0;
        m_subtitle_parser = 0;
        m_new_subtitle_page_connection = 0;
        m_new_dvb_subtitle_page_connection = 0;
-       m_radiotext_updated_connection = 0;
+       m_rds_decoder_event_connection = 0;
+       m_video_event_connection = 0;
 
        m_timeshift_active = 1;
 
-       m_event((iPlayableService*)this, evSeekableStatusChanged);
-
        eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
        r.path = m_timeshift_file;
 
        m_cue = new eCueSheet();
        m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
-       updateDecoder(); /* mainly to switch off PCR */
+
+       eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
+       pause();
+       updateDecoder(); /* mainly to switch off PCR, and to set pause */
+       
+       m_event((iPlayableService*)this, evSeekableStatusChanged);
 }
 
 void eDVBServicePlay::updateDecoder()
@@ -2177,9 +2332,9 @@ void eDVBServicePlay::updateDecoder()
                                ePtr<iDVBDemux> data_demux;
                                if (!h.getDataDemux(data_demux))
                                {
-                                       m_radiotext_parser = new eDVBRadioTextParser(data_demux);
-                                       m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
-                                       m_radiotext_parser->start(apid);
+                                       m_rds_decoder = new eDVBRdsDecoder(data_demux);
+                                       m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
+                                       m_rds_decoder->start(apid);
                                }
                        }
                }
@@ -2193,7 +2348,10 @@ void eDVBServicePlay::updateDecoder()
                if (!m_is_primary)
                        m_decoder->setTrickmode(1);
 
-               m_decoder->start();
+               if (m_is_paused)
+                       m_decoder->preroll();
+               else
+                       m_decoder->start();
 
                if (vpid > 0 && vpid < 0x2000)
                        ;
@@ -2700,7 +2858,6 @@ void eDVBServicePlay::setPCMDelay(int delay)
 
 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
 {
-       eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
        memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
        m_event((iPlayableService*)this, evVideoSizeChanged);
 }