Beispiel #1
0
std::string fontRenderClass::AddFont(const std::string &filename, const std::string &name, int scale, int renderflags)
{
	eDebugNoNewLineStart("[FONT] adding font %s...", filename.c_str());
	fflush(stdout);
	int error;
	fontListEntry *n=new fontListEntry;

	n->scale=scale;
	FT_Face face;
	singleLock s(ftlock);

	if ((error=FT_New_Face(library, filename.c_str(), 0, &face)))
		eDebugNoNewLineEnd(" failed: %s", strerror(error));

	n->filename=filename;
	n->face=name;
	n->renderflags=renderflags;
	FT_Done_Face(face);

	n->next=font;
	eDebugNoNewLineEnd("OK (%s)", n->face.c_str());
	font=n;

	return n->face;
}
int eDVBCICAManagerSession::receivedAPDU(const unsigned char *tag, const void *data, int len)
{
    eDebugNoNewLine("[CI CA] SESSION(%d)/CA %02x %02x %02x: ", session_nb, tag[0], tag[1],tag[2]);
    for (int i=0; i<len; i++)
        eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
    eDebugNoNewLine("\n");

    if ((tag[0]==0x9f) && (tag[1]==0x80))
    {
        switch (tag[2])
        {
        case 0x31:
            eDebugNoNewLineStart("[CI CA]ca info:");
            for (int i=0; i<len; i+=2)
            {
                eDebugNoNewLine("%04x ", (((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1]));
                caids.push_back((((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1]));
            }
            std::sort(caids.begin(), caids.end());
            eDebugNoNewLine("\n");
            eDVBCIInterfaces::getInstance()->recheckPMTHandlers();
            break;
        default:
            eDebug("[CI CA] unknown APDU tag 9F 80 %02x", tag[2]);
            break;
        }
    }
    return 0;
}
Beispiel #3
0
int eDVBCIResourceManagerSession::receivedAPDU(const unsigned char *tag,const void *data, int len)
{
#ifdef __sh__
	eDebug("eDVBCIResourceManagerSession::%s >", __func__);
	eDebugNoNewLineStart("SESSION(%d) %02x %02x %02x (len = %d): ", session_nb, tag[0], tag[1], tag[2], len);
#else
	eDebugNoNewLineStart("SESSION(%d) %02x %02x %02x: ", session_nb, tag[0], tag[1], tag[2]);
#endif
	for (int i=0; i<len; i++)
		eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
	eDebugNoNewLineEnd("");
	if ((tag[0]==0x9f) && (tag[1]==0x80))
	{
		switch (tag[2])
		{
		case 0x10:  // profile enquiry
			eDebug("cam fragt was ich kann.");
			state=stateProfileEnquiry;
			return 1;
			break;
		case 0x11: // Tprofile
			eDebugNoNewLineStart("mein cam kann: ");
			if (!len)
				eDebugNoNewLineEnd("nichts");
			else
			{
				for (int i=0; i<len; i++)
					eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
				eDebugNoNewLineEnd("");
			}
			if (state == stateFirstProfileEnquiry)
			{
				// profile change
				return 1;
			}
			state=stateFinal;
			break;
		default:
			eDebug("unknown APDU tag 9F 80 %02x", tag[2]);
		}
	}

	return 0;
}
Beispiel #4
0
int eDVBCIResourceManagerSession::receivedAPDU(const unsigned char *tag,const void *data, int len)
{
	eDebugNoNewLineStart("[CI RM] SESSION(%d) %02x %02x %02x: ", session_nb, tag[0], tag[1], tag[2]);
	for (int i=0; i<len; i++)
		eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
	eDebugNoNewLine("\n");
	if ((tag[0]==0x9f) && (tag[1]==0x80))
	{
		switch (tag[2])
		{
		case 0x10:  // profile enquiry
			eDebug("[CI RM] cam profile inquiry");
			state=stateProfileEnquiry;
			return 1;
			break;
		case 0x11: // Tprofile
			eDebugNoNewLineStart("[CI RM] can do: ");
			if (!len)
				eDebugNoNewLine("nothing");
			else
			{
				for (int i=0; i<len; i++)
					eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
				eDebugNoNewLine("\n");
			}
			if (state == stateFirstProfileEnquiry)
			{
				// profile change
				return 1;
			}
			state=stateFinal;
			break;
		default:
			eDebug("[CI RM] unknown APDU tag 9F 80 %02x", tag[2]);
		}
	}

	return 0;
}
Beispiel #5
0
int eDVBCIMMISession::receivedAPDU(const unsigned char *tag, const void *data, int len)
{
	eDebugNoNewLineStart("SESSION(%d)/MMI %02x %02x %02x: ", session_nb, tag[0], tag[1],tag[2]);
	for (int i=0; i<len; i++)
		eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
	eDebugNoNewLineEnd("");

	if ((tag[0]==0x9f) && (tag[1]==0x88))
		if (eDVBCI_UI::getInstance()->processMMIData(slot->getSlotID(), tag, data, len) == 1)
		{
			state=stateDisplayReply;
			return 1;
		}

	return 0;
}
int eListboxServiceContent::setCurrentMarked(bool state)
{
	bool prev = m_current_marked;
	m_current_marked = state;

	if (state != prev && m_listbox)
	{
		m_listbox->entryChanged(cursorResolve(m_cursor_number));
		if (!state)
		{
			if (!m_lst)
				m_service_center->list(m_root, m_lst);
			if (m_lst)
			{
				ePtr<iMutableServiceList> list;
				if (m_lst->startEdit(list))
					eDebug("no editable list");
				else
				{
					eServiceReference ref;
					getCurrent(ref);
					if(!ref)
						eDebug("no valid service selected");
					else
					{
						int pos = cursorGet();
						eDebugNoNewLineStart("move %s to %d ", ref.toString().c_str(), pos);
						if (list->moveService(ref, cursorGet()))
							eDebugNoNewLineEnd("failed");
						else
							eDebugNoNewLineEnd("ok");
					}
				}
			}
			else
				eDebug("no list available!");
		}
	}

	return 0;
}
int eDVBCIDateTimeSession::receivedAPDU(const unsigned char *tag,const void *data, int len)
{
	eDebugNoNewLineStart("SESSION(%d)/DATETIME %02x %02x %02x: ", session_nb, tag[0],tag[1], tag[2]);
	for (int i=0; i<len; i++)
		eDebugNoNewLine("%02x ", ((const unsigned char*)data)[i]);
	eDebugEOL();

	if ((tag[0]==0x9f) && (tag[1]==0x84))
	{
		switch (tag[2])
		{
		case 0x40:
			state=stateSendDateTime;
			return 1;
			break;
		default:
			eDebug("unknown APDU tag 9F 84 %02x", tag[2]);
			break;
		}
	}
	return 0;
}
Beispiel #8
0
int eDVBServiceRecord::doRecord()
{
	int err = doPrepare();
	if (err)
	{
		m_error = errTuneFailed;
		m_event((iRecordableService*)this, evRecordFailed);
		return err;
	}

	if (!m_tuned)
		return 0; /* try it again when we are tuned in */

	if (!m_record && m_tuned && !m_streaming && !m_simulate)
	{
		eDebug("Recording to %s...", m_filename.c_str());
		::remove(m_filename.c_str());
		int fd = ::open(m_filename.c_str(), O_WRONLY | O_CREAT | O_LARGEFILE | O_CLOEXEC, 0666);
		if (fd == -1)
		{
			eDebug("eDVBServiceRecord - can't open recording file!");
			m_error = errOpenRecordFile;
			m_event((iRecordableService*)this, evRecordFailed);
			return errOpenRecordFile;
		}

		ePtr<iDVBDemux> demux;
		if (m_service_handler.getDataDemux(demux))
		{
			eDebug("eDVBServiceRecord - NO DEMUX available!");
			m_error = errNoDemuxAvailable;
			m_event((iRecordableService*)this, evRecordFailed);
			return errNoDemuxAvailable;
		}
		demux->createTSRecorder(m_record);
		if (!m_record)
		{
			eDebug("eDVBServiceRecord - no ts recorder available.");
			m_error = errNoTsRecorderAvailable;
			m_event((iRecordableService*)this, evRecordFailed);
			return errNoTsRecorderAvailable;
		}
		m_record->setTargetFD(fd);
		m_record->setTargetFilename(m_filename);
		m_record->connectEvent(slot(*this, &eDVBServiceRecord::recordEvent), m_con_record_event);

		m_target_fd = fd;
	}

	if (m_streaming)
	{
		m_state = stateRecording;
		eDebug("start streaming...");
	} else
	{
		eDebugNoNewLineStart("start recording...");

		eDVBServicePMTHandler::program program;
		if (m_service_handler.getProgramInfo(program))
			eDebug("getting program info failed.");
		else
		{
			std::set<int> pids_to_record;

			pids_to_record.insert(0); // PAT

			if (program.pmtPid != -1)
				pids_to_record.insert(program.pmtPid); // PMT

			int timing_pid = -1, timing_stream_type = -1;
			iDVBTSRecorder::timing_pid_type timing_pid_type = iDVBTSRecorder::none;

			eDebugNoNewLine("RECORD: have %zd video stream(s)", program.videoStreams.size());
			if (!program.videoStreams.empty())
			{
				eDebugNoNewLine(" (");
				for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
					i(program.videoStreams.begin());
					i != program.videoStreams.end(); ++i)
				{
					pids_to_record.insert(i->pid);

					if (timing_pid == -1)
					{
						timing_pid = i->pid;
						timing_stream_type = i->type;
						timing_pid_type = iDVBTSRecorder::video_pid;
					}

					if (i != program.videoStreams.begin())
							eDebugNoNewLine(", ");
					eDebugNoNewLine("%04x", i->pid);
				}
				eDebugNoNewLine(")");
			}
			eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
			if (!program.audioStreams.empty())
			{
				eDebugNoNewLine(" (");
				for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
					i(program.audioStreams.begin());
					i != program.audioStreams.end(); ++i)
				{
					pids_to_record.insert(i->pid);

					if (timing_pid == -1)
					{
						timing_pid = i->pid;
						timing_stream_type = i->type;
						timing_pid_type = iDVBTSRecorder::audio_pid;
					}

					if (i != program.audioStreams.begin())
						eDebugNoNewLine(", ");
					eDebugNoNewLine("%04x", i->pid);
				}
				eDebugNoNewLine(")");
			}
			if (!program.subtitleStreams.empty())
			{
				eDebugNoNewLine(" (");
				for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
					i(program.subtitleStreams.begin());
					i != program.subtitleStreams.end(); ++i)
				{
					pids_to_record.insert(i->pid);

					if (i != program.subtitleStreams.begin())
						eDebugNoNewLine(", ");
					eDebugNoNewLine("%04x", i->pid);
				}
				eDebugNoNewLine(")");
			}
			eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
			if (program.pcrPid >= 0 && program.pcrPid < 0x1fff)
				pids_to_record.insert(program.pcrPid);
			eDebugNoNewLineEnd(", and the text pid is %04x", program.textPid);
			if (program.textPid != -1)
				pids_to_record.insert(program.textPid); // Videotext

			if (m_record_ecm)
			{
				for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(program.caids.begin());
							i != program.caids.end(); ++i)
				{
					if (i->capid >= 0) pids_to_record.insert(i->capid);
				}
			}

			bool include_ait = eConfigManager::getConfigBoolValue("config.recording.include_ait");
			if (include_ait)
			{
				/* add AIT pid (if any) */
				if (program.aitPid >= 0) pids_to_record.insert(program.aitPid);
			}

			/* find out which pids are NEW and which pids are obsolete.. */
			std::set<int> new_pids, obsolete_pids;

			std::set_difference(pids_to_record.begin(), pids_to_record.end(),
					m_pids_active.begin(), m_pids_active.end(),
					std::inserter(new_pids, new_pids.begin()));

			std::set_difference(
					m_pids_active.begin(), m_pids_active.end(),
					pids_to_record.begin(), pids_to_record.end(),
					std::inserter(obsolete_pids, obsolete_pids.begin())
					);

			for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
			{
				eDebug("ADD PID: %04x", *i);
				m_record->addPID(*i);
			}

			for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
			{
				eDebug("REMOVED PID: %04x", *i);
				m_record->removePID(*i);
			}

			if (timing_pid != -1)
				m_record->setTimingPID(timing_pid, timing_pid_type, timing_stream_type);

			m_pids_active = pids_to_record;

			if (m_state != stateRecording)
			{
				m_record->start();
				m_state = stateRecording;
			}
		}
	}
	m_error = 0;
	m_event((iRecordableService*)this, evRecordRunning);
	return 0;
}
Beispiel #9
0
int eDVBServiceStream::doRecord()
{
	int err = doPrepare();
	if (err)
	{
		eDebug("[eDVBServiceStream] doPrerare err %d", err);
		return err;
	}

	if (!m_tuned)
	{
		eDebug("[eDVBServiceStream] try it again when we are tuned in");
		return 0; /* try it again when we are tuned in */
	}

	if (!m_record && m_tuned)
	{
		ePtr<iDVBDemux> demux;
		if (m_service_handler.getDataDemux(demux))
		{
			eDebug("eDVBServiceStream - NO DEMUX available");
			return -1;
		}
		demux->createTSRecorder(m_record, /*packetsize*/ 188, /*streaming*/ true);
		if (!m_record)
		{
			eDebug("eDVBServiceStream - no ts recorder available.");
			return -1;
		}
		m_record->setTargetFD(m_target_fd);
		m_record->connectEvent(sigc::mem_fun(*this, &eDVBServiceStream::recordEvent), m_con_record_event);
	}

	eDebug("start streaming...");

	if (recordCachedPids())
	{
		eDebug("[eDVBServiceStream] streaming pids from cache.");
		return 0;
	}

	eDVBServicePMTHandler::program program;
	if (m_service_handler.getProgramInfo(program))
	{
		eDebug("getting program info failed.");
	}
	else
	{
		std::set<int> pids_to_record;

		eServiceReferenceDVB ref = m_ref.getParentServiceReference();
		ePtr<eDVBService> service;

		if (!ref.valid())
			ref = m_ref;

		if(!eDVBDB::getInstance()->getService(ref, service))
		{
			// cached pids
			for (int x = 0; x < eDVBService::cacheMax; ++x)
			{
				if (x == 5)
				{
					x += 3; // ignore cVTYPE, cACHANNEL, cAC3DELAY, cPCMDELAY
					continue;
				}
				int entry = service->getCacheEntry((eDVBService::cacheID)x);
				if (entry != -1)
				{
					if (eDVBService::cSUBTITLE == (eDVBService::cacheID)x)
					{
						entry = (entry&0xFFFF0000)>>16;
					}
					pids_to_record.insert(entry);
				}
			}
		}

		pids_to_record.insert(0); // PAT

		if (program.pmtPid != -1)
			pids_to_record.insert(program.pmtPid); // PMT

		int timing_pid = -1, timing_stream_type = -1;
		iDVBTSRecorder::timing_pid_type timing_pid_type = iDVBTSRecorder::none;

		eDebugNoNewLineStart("STREAM: have %zd video stream(s)", program.videoStreams.size());
		if (!program.videoStreams.empty())
		{
			eDebugNoNewLine(" (");
			for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
				i(program.videoStreams.begin());
				i != program.videoStreams.end(); ++i)
			{
				pids_to_record.insert(i->pid);

				if (timing_pid == -1)
				{
					timing_pid = i->pid;
					timing_stream_type = i->type;
					timing_pid_type = iDVBTSRecorder::video_pid;
				}

				if (i != program.videoStreams.begin())
						eDebugNoNewLine(", ");
				eDebugNoNewLine("%04x", i->pid);
			}
			eDebugNoNewLine(")");
		}
		eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
		if (!program.audioStreams.empty())
		{
			eDebugNoNewLine(" (");
			for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
				i(program.audioStreams.begin());
				i != program.audioStreams.end(); ++i)
			{
				pids_to_record.insert(i->pid);

				if (timing_pid == -1)
				{
					timing_pid = i->pid;
					timing_stream_type = i->type;
					timing_pid_type = iDVBTSRecorder::audio_pid;
				}

				if (i != program.audioStreams.begin())
					eDebugNoNewLine(", ");
				eDebugNoNewLine("%04x", i->pid);
			}
			eDebugNoNewLine(")");
		}
		if (!program.subtitleStreams.empty())
		{
			eDebugNoNewLine(" (");
			for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
				i(program.subtitleStreams.begin());
				i != program.subtitleStreams.end(); ++i)
			{
				pids_to_record.insert(i->pid);

				if (i != program.subtitleStreams.begin())
					eDebugNoNewLine(", ");
				eDebugNoNewLine("%04x", i->pid);
			}
			eDebugNoNewLine(")");
		}
		eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
		if (program.pcrPid >= 0 && program.pcrPid < 0x1fff)
			pids_to_record.insert(program.pcrPid);
		eDebugNoNewLineEnd(", and the text pid is %04x", program.textPid);
		if (program.textPid != -1)
			pids_to_record.insert(program.textPid); // Videotext

		if (m_stream_ecm)
		{
			for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(program.caids.begin());
						i != program.caids.end(); ++i)
			{
				if (i->capid >= 0) pids_to_record.insert(i->capid);
			}
		}

		if (m_stream_ait)
		{
			if (program.aitPid >= 0) pids_to_record.insert(program.aitPid);
		}

		if (m_stream_eit)
		{
			pids_to_record.insert(0x12);
		}

		/* include TDT pid, really low bandwidth, should not hurt anyone */
		pids_to_record.insert(0x14);

		recordPids(pids_to_record, timing_pid, timing_stream_type, timing_pid_type);
	}
int eDVBServiceRecord::doRecord()
{
	int err = doPrepare();
	if (err)
	{
		m_error = errTuneFailed;
		m_event((iRecordableService*)this, evRecordFailed);
		return err;
	}

	if (!m_tuned)
		return 0; /* try it again when we are tuned in */

	if (!m_record && m_tuned && !m_streaming && !m_simulate)
	{
		eDebug("[eDVBServiceRecord] Recording to %s...", m_filename.c_str());
		::remove(m_filename.c_str());
		int fd = ::open(m_filename.c_str(), O_WRONLY | O_CREAT | O_LARGEFILE | O_CLOEXEC, 0666);
		if (fd == -1)
		{
			eDebug("[eDVBServiceRecord] can't open recording file: %m");
			m_error = errOpenRecordFile;
			m_event((iRecordableService*)this, evRecordFailed);
			return errOpenRecordFile;
		}

		ePtr<iDVBDemux> demux;
		if (m_service_handler.getDataDemux(demux))
		{
			eDebug("[eDVBServiceRecord] NO DEMUX available!");
			m_error = errNoDemuxAvailable;
			m_event((iRecordableService*)this, evRecordFailed);
			::close(fd);
			return errNoDemuxAvailable;
		}
		demux->createTSRecorder(m_record);
		if (!m_record)
		{
			eDebug("[eDVBServiceRecord] no ts recorder available.");
			m_error = errNoTsRecorderAvailable;
			m_event((iRecordableService*)this, evRecordFailed);
			::close(fd);
			return errNoTsRecorderAvailable;
		}
		m_record->setTargetFD(fd);
		m_record->setTargetFilename(m_filename);
		m_record->connectEvent(slot(*this, &eDVBServiceRecord::recordEvent), m_con_record_event);

		m_target_fd = fd;
	}

	if (m_streaming)
	{
		m_state = stateRecording;
		eDebug("[eDVBServiceRecord] start streaming...");
	} else
	{
		eDebug("[eDVBServiceRecord] start recording...");

		eDVBServicePMTHandler::program program;
		if (m_service_handler.getProgramInfo(program))
			eDebug("[eDVBServiceRecord] getting program info failed.");
		else
		{
			std::set<int> pids_to_record;

			eServiceReferenceDVB ref = m_ref.getParentServiceReference();
			ePtr<eDVBService> service;

			if (!ref.valid())
				ref = m_ref;

			if(!eDVBDB::getInstance()->getService(ref, service))
			{
				// cached pids
				for (int x = 0; x < eDVBService::cacheMax; ++x)
				{
					if (x == 5)
					{
						x += 3; // ignore cVTYPE, cACHANNEL, cAC3DELAY, cPCMDELAY
						continue;
					}
					int entry = service->getCacheEntry((eDVBService::cacheID)x);
					if (entry != -1)
					{
						if (eDVBService::cSUBTITLE == (eDVBService::cacheID)x)
						{
							entry = (entry&0xFFFF0000)>>16;
						}
						pids_to_record.insert(entry);
					}
				}
			}

			pids_to_record.insert(0); // PAT

			if (program.pmtPid != -1)
				pids_to_record.insert(program.pmtPid); // PMT

			int timing_pid = -1, timing_stream_type = -1;
			iDVBTSRecorder::timing_pid_type timing_pid_type = iDVBTSRecorder::none;

			eDebugNoNewLineStart("[eDVBServiceRecord] RECORD: have %zd video stream(s)", program.videoStreams.size());
			if (!program.videoStreams.empty())
			{
				eDebugNoNewLine(" (");
				for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
					i(program.videoStreams.begin());
					i != program.videoStreams.end(); ++i)
				{
					pids_to_record.insert(i->pid);

					if (timing_pid == -1)
					{
						timing_pid = i->pid;
						timing_stream_type = i->type;
						timing_pid_type = iDVBTSRecorder::video_pid;
					}

					if (i != program.videoStreams.begin())
							eDebugNoNewLine(", ");
					eDebugNoNewLine("%04x", i->pid);
				}
				eDebugNoNewLine(")");
			}
			eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
			if (!program.audioStreams.empty())
			{
				eDebugNoNewLine(" (");
				for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
					i(program.audioStreams.begin());
					i != program.audioStreams.end(); ++i)
				{
					pids_to_record.insert(i->pid);

					if (timing_pid == -1)
					{
						timing_pid = i->pid;
						timing_stream_type = i->type;
						timing_pid_type = iDVBTSRecorder::audio_pid;
					}

					if (i != program.audioStreams.begin())
						eDebugNoNewLine(", ");
					eDebugNoNewLine("%04x", i->pid);
				}
				eDebugNoNewLine(")");
			}
			if (!program.subtitleStreams.empty())
			{
				eDebugNoNewLine(" (");
				for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
					i(program.subtitleStreams.begin());
					i != program.subtitleStreams.end(); ++i)
				{
					pids_to_record.insert(i->pid);

					if (i != program.subtitleStreams.begin())
						eDebugNoNewLine(", ");
					eDebugNoNewLine("%04x", i->pid);
				}
				eDebugNoNewLine(")");
			}
			eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
			if (program.pcrPid >= 0 && program.pcrPid < 0x1fff)
				pids_to_record.insert(program.pcrPid);
			eDebugNoNewLine(", and the text pid is %04x\n", program.textPid);
			if (program.textPid != -1)
				pids_to_record.insert(program.textPid); // Videotext

			if (m_record_ecm)
			{
				for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(program.caids.begin());
							i != program.caids.end(); ++i)
				{
					if (i->capid >= 0) pids_to_record.insert(i->capid);
				}
			}

				/* find out which pids are NEW and which pids are obsolete.. */
			std::set<int> new_pids, obsolete_pids;

			std::set_difference(pids_to_record.begin(), pids_to_record.end(),
					m_pids_active.begin(), m_pids_active.end(),
					std::inserter(new_pids, new_pids.begin()));

			std::set_difference(
					m_pids_active.begin(), m_pids_active.end(),
					pids_to_record.begin(), pids_to_record.end(),
					std::inserter(obsolete_pids, obsolete_pids.begin())
					);

			for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
			{
				eDebug("[eDVBServiceRecord] ADD PID: %04x", *i);
				m_record->addPID(*i);
			}

			for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
			{
				eDebug("[eDVBServiceRecord] REMOVED PID: %04x", *i);
				m_record->removePID(*i);
			}

			if (timing_pid != -1)
				m_record->setTimingPID(timing_pid, timing_pid_type, timing_stream_type);

			m_pids_active = pids_to_record;

			if (m_state != stateRecording)
			{
				m_record->start();
				m_state = stateRecording;
			}
		}
	}
int eDVBServiceStream::doRecord()
{
	int err = doPrepare();
	if (err)
	{
		eDebug("[eDVBServiceStream] doPrerare err %d", err);
		return err;
	}

	if (!m_tuned)
	{
		eDebug("[eDVBServiceStream] try it again when we are tuned in");
		return 0; /* try it again when we are tuned in */
	}

	if (!m_record && m_tuned)
	{
		ePtr<iDVBDemux> demux;
		if (m_service_handler.getDataDemux(demux))
		{
			eDebug("[eDVBServiceStream] NO DEMUX available");
			return -1;
		}
		demux->createTSRecorder(m_record, /*packetsize*/ 188, /*streaming*/ true);
		if (!m_record)
		{
			eDebug("[eDVBServiceStream] no ts recorder available.");
			return -1;
		}
		m_record->setTargetFD(m_target_fd);
		m_record->connectEvent(slot(*this, &eDVBServiceStream::recordEvent), m_con_record_event);
	}

	eDebug("[eDVBServiceStream] start streaming...");

	if (recordCachedPids())
	{
		eDebug("[eDVBServiceStream] streaming pids from cache.");
		return 0;
	}

	eDVBServicePMTHandler::program program;
	if (m_service_handler.getProgramInfo(program))
	{
		eDebug("[eDVBServiceStream] getting program info failed.");
	}
	else
	{
		std::set<int> pids_to_record;

		pids_to_record.insert(0); // PAT

		if (program.pmtPid != -1)
			pids_to_record.insert(program.pmtPid); // PMT

		int timing_pid = -1, timing_stream_type = -1;
		iDVBTSRecorder::timing_pid_type timing_pid_type = iDVBTSRecorder::none;

		eDebugNoNewLineStart("[eDVBServiceStream] have %zd video stream(s)", program.videoStreams.size());
		if (!program.videoStreams.empty())
		{
			eDebugNoNewLine(" (");
			for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
				i(program.videoStreams.begin());
				i != program.videoStreams.end(); ++i)
			{
				pids_to_record.insert(i->pid);

				if (timing_pid == -1)
				{
					timing_pid = i->pid;
					timing_stream_type = i->type;
					timing_pid_type = iDVBTSRecorder::video_pid;
				}

				if (i != program.videoStreams.begin())
						eDebugNoNewLine(", ");
				eDebugNoNewLine("%04x", i->pid);
			}
			eDebugNoNewLine(")");
		}
		eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
		if (!program.audioStreams.empty())
		{
			eDebugNoNewLine(" (");
			for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
				i(program.audioStreams.begin());
				i != program.audioStreams.end(); ++i)
			{
				pids_to_record.insert(i->pid);

				if (timing_pid == -1)
				{
					timing_pid = i->pid;
					timing_stream_type = i->type;
					timing_pid_type = iDVBTSRecorder::audio_pid;
				}

				if (i != program.audioStreams.begin())
					eDebugNoNewLine(", ");
				eDebugNoNewLine("%04x", i->pid);
			}
			eDebugNoNewLine(")");
		}
		if (!program.subtitleStreams.empty())
		{
			eDebugNoNewLine(" (");
			for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
				i(program.subtitleStreams.begin());
				i != program.subtitleStreams.end(); ++i)
			{
				pids_to_record.insert(i->pid);

				if (i != program.subtitleStreams.begin())
					eDebugNoNewLine(", ");
				eDebugNoNewLine("%04x", i->pid);
			}
			eDebugNoNewLine(")");
		}
		eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
		if (program.pcrPid >= 0 && program.pcrPid < 0x1fff)
			pids_to_record.insert(program.pcrPid);
		eDebugNoNewLine(", and the text pid is %04x\n", program.textPid);
		if (program.textPid != -1)
			pids_to_record.insert(program.textPid); // Videotext

		if (m_stream_ecm)
		{
			for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(program.caids.begin());
						i != program.caids.end(); ++i)
			{
				if (i->capid >= 0) pids_to_record.insert(i->capid);
			}
		}

		if (m_stream_ait)
		{
			if (program.aitPid >= 0) pids_to_record.insert(program.aitPid);
		}

		if (m_stream_eit)
		{
			pids_to_record.insert(0x12);
		}

		/* include TDT pid, really low bandwidth, should not hurt anyone */
		pids_to_record.insert(0x14);

		recordPids(pids_to_record, timing_pid, timing_stream_type, timing_pid_type);
	}

	return 0;
}
ssize_t eM2TSFile::read(off_t offset, void *b, size_t count)
{
	eSingleLocker l(m_lock);
	unsigned char tmp[192*3];
	unsigned char *buf = (unsigned char*)b;

	size_t rd=0;
	offset = (offset % 188) + (offset * 192) / 188;

sync:
	if ((offset+m_sync_offset) != m_current_offset)
	{
//		eDebug("[eM2TSFile] seekTo %lld", offset+m_sync_offset);
		m_current_offset = lseek_internal(offset+m_sync_offset, SEEK_SET);
		if (m_current_offset < 0)
			return m_current_offset;
	}

	while (rd < count) {
		size_t ret;
		ret = ::read(m_fd, tmp, 192);
		if (ret < 192)
			return rd ? rd : ret;

		if (tmp[4] != 0x47)
		{
			if (rd > 0) {
				eDebug("[eM2TSFile] short read at pos %lld async!!", m_current_offset);
				return rd;
			}
			else {
				int x=0;
				ret = ::read(m_fd, tmp+192, 384);

#if 0
				eDebugNoNewLineStart("[eM2TSFile] m2ts out of sync at pos %lld, real %lld:", offset + m_sync_offset, m_current_offset);
				for (; x < 192; ++x)
					eDebugNoNewLine(" %02x", tmp[x]);
				eDebugNoNewLine("\n");
				x=0;
#else
				eDebug("[eM2TSFile] m2ts out of sync at pos %lld, real %lld", offset + m_sync_offset, m_current_offset);
#endif
				for (; x < 192; ++x)
				{
					if (tmp[x] == 0x47 && tmp[x+192] == 0x47)
					{
						int add_offs = (x - 4);
						eDebug("[eM2TSFile] sync found at pos %d, sync_offset is now %d, old was %d", x, add_offs + m_sync_offset, m_sync_offset);
						m_sync_offset += add_offs;
						goto sync;
					}
				}
			}
		}

		memcpy(buf+rd, tmp+4, 188);

		rd += 188;
		m_current_offset += 188;
	}

	m_sync_offset %= 188;

	return rd;
}