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() ));
	}
}
Beispiel #2
0
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
Beispiel #3
0
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;
}
Beispiel #4
0
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;
	}