void eDVBServiceController::leaveService( const eServiceReferenceDVB &service) { if (!service) return; std::map<eServiceReferenceDVB,int>::iterator it = CIServices.find(service); if ( it != CIServices.end() ) { // eDebug("[eDVBCIHandler] leave service %s", service.toString().c_str() ); CIServices.erase(it); if ( DVBCI ) DVBCI->messages.send(eDVBCI::eDVBCIMessage(eDVBCI::eDVBCIMessage::PMTflush, service.getServiceID().get() )); if ( DVBCI2 ) DVBCI2->messages.send(eDVBCI::eDVBCIMessage(eDVBCI::eDVBCIMessage::PMTflush, service.getServiceID().get() )); } }
void eChannelInfo::getServiceInfo( const eServiceReferenceDVB& service ) { closeEIT(); delete eit; eit=0; // eService *service=eServiceInterface::getInstance()->addRef(service); if (!service.path.size()) { DescriptionForEPGSearch = ""; cdescr.show(); cname.setFlags(RS_FADE); cname.resize( eSize( clientrect.width()/8*7-4, clientrect.height()/3) ); int opos=service.getDVBNamespace().get()>>16; if ( eSystemInfo::getInstance()->getFEType() == eSystemInfo::feSatellite ) copos.setText(eString().sprintf("%d.%d\xC2\xB0%c", abs(opos / 10), abs(opos % 10), opos>0?'E':'W') ); EITEvent *e = 0; e = eEPGCache::getInstance()->lookupEvent(service); if (e && eListBoxEntryService::nownextEPG) { time_t t = e->start_time+e->duration+61; delete e; e = eEPGCache::getInstance()->lookupEvent((const eServiceReferenceDVB&)service,t); } if (e) // data is in cache... { ParseEITInfo(e); delete e; } else // we parse the eit... { cname.setText(_("no data for this service avail")); eDVBServiceController *sapi=eDVB::getInstance()->getServiceAPI(); if (!sapi) return; eServiceReferenceDVB &ref = sapi->service; int type = ((service.getTransportStreamID()==ref.getTransportStreamID()) && (service.getOriginalNetworkID()==ref.getOriginalNetworkID())) ? EIT::tsActual:EIT::tsOther; eit = new EIT( EIT::typeNowNext, service.getServiceID().get(), type ); CONNECT( eit->tableReady, eChannelInfo::EITready ); eit->start(); } } else
int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_demux, ePtr<iTsSource> &source, const char *streaminfo_file, eCueSheet *cue, bool simulate, eDVBService *service, serviceType type, bool descramble) { RESULT res=0; m_reference = ref; m_use_decode_demux = use_decode_demux; m_no_pat_entry_delay->stop(); m_service_type = type; doDescramble = descramble; /* use given service as backup. This is used for timeshift where we want to clone the live stream using the cache, but in fact have a PVR channel */ m_service = service; /* is this a normal (non PVR) channel? */ if (ref.path.empty()) { eDVBChannelID chid; ref.getChannelID(chid); res = m_resourceManager->allocateChannel(chid, m_channel, simulate); if (!simulate) eDebug("allocate Channel: res %d", res); ePtr<iDVBChannelList> db; if (!m_resourceManager->getChannelList(db)) db->getService((eServiceReferenceDVB&)m_reference, m_service); if (!res && !simulate) eDVBCIInterfaces::getInstance()->addPMTHandler(this); } else if (!simulate) // no simulation of playback services { if (!ref.getServiceID().get() /* incorrect sid in meta file or recordings.epl*/ ) { eDVBTSTools tstools; bool b = source || !tstools.openFile(ref.path.c_str(), 1); eWarning("no .meta file found, trying to find PMT pid"); if (source) tstools.setSource(source, NULL); if (b) { eDVBPMTParser::program program; if (!tstools.findPMT(program)) { m_pmt_pid = program.pmtPid; eDebug("PMT pid found on pid %04x, service id %d", m_pmt_pid, program.serviceId); m_reference.setServiceID(program.serviceId); } } else eWarning("no valid source to find PMT pid!"); } eDebug("alloc PVR"); /* allocate PVR */ eDVBChannelID chid; if (m_service_type == streamclient) ref.getChannelID(chid); res = m_resourceManager->allocatePVRChannel(chid, m_pvr_channel); if (res) eDebug("allocatePVRChannel failed!\n"); m_channel = m_pvr_channel; } if (!simulate) { if (m_channel) { m_channel->connectStateChange( slot(*this, &eDVBServicePMTHandler::channelStateChanged), m_channelStateChanged_connection); m_last_channel_state = -1; channelStateChanged(m_channel); m_channel->connectEvent( slot(*this, &eDVBServicePMTHandler::channelEvent), m_channelEvent_connection); if (ref.path.empty()) { m_dvb_scan = new eDVBScan(m_channel, true, false); if (!eConfigManager::getConfigBoolValue("config.misc.disable_background_scan")) { /* * not starting a dvb scan triggers what appears to be a * refcount bug (channel?/demux?), so we always start a scan, * but ignore the results when background scanning is disabled */ m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); } } } else { if (res == eDVBResourceManager::errAllSourcesBusy) serviceEvent(eventNoResources); else /* errChidNotFound, errNoChannelList, errChannelNotInList, errNoSourceFound */ serviceEvent(eventMisconfiguration); return res; } if (m_pvr_channel) { m_pvr_channel->setCueSheet(cue); if (m_pvr_channel->getDemux(m_pvr_demux_tmp, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) eDebug("Allocating %s-decoding a demux for PVR channel failed.", m_use_decode_demux ? "" : "non-"); else if (source) m_pvr_channel->playSource(source, streaminfo_file); else m_pvr_channel->playFile(ref.path.c_str()); if (m_service_type == offline) { m_pvr_channel->setOfflineDecodeMode(eConfigManager::getConfigIntValue("config.recording.offline_decode_delay")); } } } return res; }
void eDVB::recBegin(const char *filename, eServiceReferenceDVB service) { if (recorder) recEnd(); PMT *pmt=getPMT(); PAT *pat=tPAT.ready()?tPAT.getCurrent():0; recorder=new eDVBRecorder(pmt, pat); if ( pat ) pat->unlock(); recorder->recRef=(eServiceReferenceDVB&)eServiceInterface::getInstance()->service; eServiceHandler *handler = eServiceInterface::getInstance()->getService(); recorder->scrambled = handler->getFlags() & eServiceHandler::flagIsScrambled; recorder->open(filename); CONNECT(recorder->recMessage, eDVB::recMessage); // recorder->addNewPID(0); // PAT // if (Decoder::parms.pmtpid != -1) // recorder->addNewPID(Decoder::parms.pmtpid); if (!pmt) { if (Decoder::parms.apid != -1) recorder->addNewPID(Decoder::parms.apid); if (Decoder::parms.vpid != -1) recorder->addNewPID(Decoder::parms.vpid); if (Decoder::parms.tpid != -1) recorder->addNewPID(Decoder::parms.tpid); if (Decoder::parms.pcrpid != -1) recorder->addNewPID(Decoder::parms.pcrpid); } else { recorder->addNewPID(pmt->PCR_PID); #ifdef RECORD_ECM for (ePtrList<Descriptor>::iterator i(pmt->program_info.begin()); i != pmt->program_info.end(); ++i) if (i->Tag() == 9) recorder->addNewPID(((CADescriptor*)*i)->CA_PID); #endif for (ePtrList<PMTEntry>::iterator i(pmt->streams); i != pmt->streams.end(); ++i) { int record=0; int isUndocumentedNA = 0; switch (i->stream_type) { case 1: // video.. case 2: record=1; break; case 3: // audio.. case 4: record=1; break; case 0x80: case 0x81: case 0x82: case 0x83: isUndocumentedNA = 1; case 6: for (ePtrList<Descriptor>::iterator it(i->ES_info); it != i->ES_info.end(); ++it) { switch (it->Tag()) { case DESCR_AC3: { int norecord=0; eConfig::getInstance()->getKey("/enigma/noac3recording", norecord); if (!norecord) record=1; break; } case DESCR_ISO639_LANGUAGE: if (isUndocumentedNA) { record = 1; } break; #ifdef RECORD_TELETEXT case DESCR_TELETEXT: { int norecord=0; eConfig::getInstance()->getKey("/enigma/nottxrecording", norecord); if (!norecord) record=2; // low bitrate break; } #endif #ifdef RECORD_SUBTITLES case DESCR_SUBTITLING: { record=2; // low bitrate break; } #endif } } break; } if (record) recorder->addNewPID(i->elementary_PID, record==2?DMX_LOW_BITRATE:0); #ifdef RECORD_ECM for (ePtrList<Descriptor>::iterator it(i->ES_info); it != i->ES_info.end(); ++it) if (it->Tag() == 9) recorder->addNewPID(((CADescriptor*)*it)->CA_PID); #endif } pmt->unlock(); } // build SMI table. // build SIT: __u8 sit[4096]; int pos=0; sit[pos++]=0x7F; // TID sit[pos++]=0x80; // section_syntax_indicator, length sit[pos++]=0; // length sit[pos++]=0; sit[pos++]=0; // reserved sit[pos++]=1; // reserved, version number, current/next indicator sit[pos++]=0; // section number sit[pos++]=0; // last section number sit[pos++]=0; // loop length sit[pos++]=0; // " " int loop_pos=pos; // TODO: build Partitial Transport Stream descriptor containing valid values about rate sit[loop_pos-2]|=(pos-loop_pos)>>8; sit[loop_pos-1]|=(pos-loop_pos)&0xFF; // create one single entry: our service... sit[pos++]=service.getServiceID().get()>>8; sit[pos++]=service.getServiceID().get()&0xFF; sit[pos++]=3<<4; // running state sit[pos++]=0; loop_pos=pos; // create our special descriptor: sit[pos++]=0x80; // private sit[pos++]=0; int descr_pos=pos; memcpy(sit+pos, "ENIGMA", 6); pos+=6; if (Decoder::parms.vpid != -1) { sit[pos++]=eServiceDVB::cVPID; sit[pos++]=2; sit[pos++]=Decoder::parms.vpid>>8; sit[pos++]=Decoder::parms.vpid&0xFF; }