void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) { int state; channel->getState(state); if ((m_last_channel_state != iDVBChannel::state_ok) && (state == iDVBChannel::state_ok)) { if (!m_demux && m_channel) { if (m_pvr_demux_tmp) { m_demux = m_pvr_demux_tmp; m_pvr_demux_tmp = NULL; } else if (m_channel->getDemux(m_demux, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) eDebug("[eDVBServicePMTHandler] Allocating %s-decoding a demux for now tuned-in channel failed.", m_use_decode_demux ? "" : "non-"); } if (m_demux) { eDebug("[eDVBServicePMTHandler] ok ... now we start!!"); m_have_cached_program = false; if (m_service && !m_service->cacheEmpty()) { serviceEvent(eventNewProgramInfo); if (m_use_decode_demux) { if (!m_ca_servicePtr) { registerCAService(); } if (m_ca_servicePtr && !m_service->usePMT()) { eDebug("[eDVBServicePMTHandler] create cached caPMT"); eDVBCAHandler::getInstance()->handlePMT(m_reference, m_service); } } } if (!m_service || m_service->usePMT()) { if (m_pmt_pid == -1) m_PAT.begin(eApp, eDVBPATSpec(), m_demux); else m_PMT.begin(eApp, eDVBPMTSpec(m_pmt_pid, m_reference.getServiceID().get()), m_demux); } serviceEvent(eventTuned); } } else if ((m_last_channel_state != iDVBChannel::state_failed) && (state == iDVBChannel::state_failed)) { eDebug("[eDVBServicePMTHandler] tune failed."); serviceEvent(eventTuneFailed); } }
void eDVBServicePMTHandler::PMTready(int error) { if (error) serviceEvent(eventNoPMT); else { m_have_cached_program = false; serviceEvent(eventNewProgramInfo); switch (m_service_type) { case livetv: case recording: case scrambled_recording: case timeshift_recording: case scrambled_timeshift_recording: case streamserver: case scrambled_streamserver: case streamclient: eEPGCache::getInstance()->PMTready(this); break; default: /* do not start epg caching for other types of services */ break; } if (doDescramble) { if (!m_ca_servicePtr) { int demuxes[2] = {0,0}; uint8_t demuxid; uint8_t adapterid; m_demux->getCADemuxID(demuxid); m_demux->getCAAdapterID(adapterid); demuxes[0]=demuxid; if (m_decode_demux_num != 0xFF) demuxes[1]=m_decode_demux_num; else demuxes[1]=demuxes[0]; eDVBCAHandler::getInstance()->registerService(m_reference, adapterid, demuxes, (int)m_service_type, m_ca_servicePtr); eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); } eDVBCIInterfaces::getInstance()->gotPMT(this); } if (m_ca_servicePtr) { ePtr<eTable<ProgramMapSection> > ptr; if (!m_PMT.getCurrent(ptr)) eDVBCAHandler::getInstance()->handlePMT(m_reference, ptr); else eDebug("eDVBServicePMTHandler cannot call buildCAPMT"); } } }
void eServiceHandlerDVB::switchedService(const eServiceReferenceDVB &s, int err) { if ( !s ) return; int oldstate=state; error = err; if (error) state=stateError; else state=statePlaying; if (state != oldstate) serviceEvent(eServiceEvent(eServiceEvent::evtStateChanged)); serviceEvent(eServiceEvent(eServiceEvent::evtStart)); }
void eDVBServicePMTHandler::channelEvent(iDVBChannel *channel, int event) { switch (event) { case iDVBChannel::evtPreStart: serviceEvent(eventPreStart); break; case iDVBChannel::evtEOF: serviceEvent(eventEOF); break; case iDVBChannel::evtSOF: serviceEvent(eventSOF); break; default: break; } }
void eServiceHandlerDVB::handleDVBEvent( const eDVBEvent & e ) { switch ( e.type ) { case eDVBEvent::eventRecordWriteError: serviceEvent(eServiceEvent(eServiceEvent::evtRecordFailed)); break; } }
void eServiceHandlerDVB::gotPMT(PMT *) { serviceEvent(eServiceEvent(eServiceEvent::evtGotPMT)); if ( decoder ) { eDVBServiceController *sapi=eDVB::getInstance()->getServiceAPI(); if ( sapi ) decoder->messages.send(eDVRPlayerThread::eDVRPlayerThreadMessage(eDVRPlayerThread::eDVRPlayerThreadMessage::updateAudioTracks, sapi->audioStreams.size())); } }
void eDVBServicePMTHandler::PMTready(int error) { if (error) serviceEvent(eventNoPMT); else { m_have_cached_program = false; serviceEvent(eventNewProgramInfo); switch (m_service_type) { case livetv: case recording: case scrambled_recording: case timeshift_recording: case scrambled_timeshift_recording: case streamserver: case scrambled_streamserver: case streamclient: eEPGCache::getInstance()->PMTready(this); break; default: /* do not start epg caching for other types of services */ break; } if (doDescramble) { if (!m_ca_servicePtr) { registerCAService(); } eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); eDVBCIInterfaces::getInstance()->gotPMT(this); } if (m_ca_servicePtr) { ePtr<eTable<ProgramMapSection> > ptr; if (!m_PMT.getCurrent(ptr)) eDVBCAHandler::getInstance()->handlePMT(m_reference, ptr); else eDebug("eDVBServicePMTHandler cannot call buildCAPMT"); } } }
void eServiceHandlerDVB::gotMessage(const eDVRPlayerThreadMessage &message) { if (message.type == eDVRPlayerThreadMessage::done) { state=stateStopped; serviceEvent(eServiceEvent(eServiceEvent::evtEnd)); } else if (message.type == eDVRPlayerThreadMessage::liveeof) stopPlayback(1); }
void eServiceHandlerDVB::scrambledStatusChanged(bool scrambled) { int oldflags=flags; if (scrambled) flags |= flagIsScrambled; else flags &= ~flagIsScrambled; if (oldflags != flags) serviceEvent(eServiceEvent(eServiceEvent::evtFlagsChanged) ); }
void eServiceHandlerDVB::stopPlayback( int waslivemode ) { if (decoder) { // reenable pcrpid Decoder::parms.pcrpid = pcrpid; Decoder::Set(); flags&=~(flagIsSeekable|flagSupportPosition); serviceEvent(eServiceEvent(eServiceEvent::evtFlagsChanged) ); delete decoder; decoder=0; } }
void eDVBServicePMTHandler::PMTready(int error) { if (error) serviceEvent(eventNoPMT); else { m_have_cached_program = false; serviceEvent(eventNewProgramInfo); if (!m_pvr_channel) // don't send campmt to camd.socket for playbacked services { eEPGCache::getInstance()->PMTready(this); if(!m_ca_servicePtr) { int demuxes[2] = {0,0}; uint8_t demuxid; uint8_t adapterid; m_demux->getCADemuxID(demuxid); m_demux->getCAAdapterID(adapterid); demuxes[0]=demuxid; if (m_decode_demux_num != 0xFF) demuxes[1]=m_decode_demux_num; else demuxes[1]=demuxes[0]; eDVBCAHandler::getInstance()->registerService(m_reference, adapterid, demuxes, m_ca_servicePtr); eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); } eDVBCIInterfaces::getInstance()->gotPMT(this); } if (m_ca_servicePtr) { ePtr<eTable<ProgramMapSection> > ptr; if (!m_PMT.getCurrent(ptr)) eDVBCAHandler::getInstance()->handlePMT(m_reference, ptr); else eDebug("eDVBServicePMTHandler cannot call buildCAPMT"); } } }
void eDVBServicePMTHandler::PATready(int) { eDebug("PATready"); ePtr<eTable<ProgramAssociationSection> > ptr; if (!m_PAT.getCurrent(ptr)) { int service_id_single = -1; int pmtpid_single = -1; int pmtpid = -1; int cnt=0; int tsid=-1; std::vector<ProgramAssociationSection*>::const_iterator i = ptr->getSections().begin(); tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id eDebug("PAT TSID: 0x%04x (%d)", tsid, tsid); for (i = ptr->getSections().begin(); pmtpid == -1 && i != ptr->getSections().end(); ++i) { const ProgramAssociationSection &pat = **i; ProgramAssociationConstIterator program; for (program = pat.getPrograms()->begin(); pmtpid == -1 && program != pat.getPrograms()->end(); ++program) { if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID()) pmtpid = (*program)->getProgramMapPid(); if (++cnt == 1 && pmtpid_single == -1 && pmtpid == -1) { pmtpid_single = (*program)->getProgramMapPid(); service_id_single = (*program)->getProgramNumber(); } else pmtpid_single = service_id_single = -1; } } if (pmtpid_single != -1) // only one PAT entry .. and not valid pmtpid found { eDebug("use single pat entry!"); m_reference.setServiceID(eServiceID(service_id_single)); pmtpid = pmtpid_single; } if (pmtpid == -1) { eDebug("no PAT entry found.. start delay"); m_no_pat_entry_delay->start(1000, true); } else { eDebug("use pmtpid %04x for service_id %04x", pmtpid, m_reference.getServiceID().get()); m_no_pat_entry_delay->stop(); m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux); } } else serviceEvent(eventNoPAT); }
int eServiceHandlerDVB::play(const eServiceReference &service, int workaround ) { eDVBServiceController *sapi=eDVB::getInstance()->getServiceAPI(); if (service.type != eServiceReference::idDVB) return -1; #ifndef DISABLE_FILE if ( !workaround ) decoder=0; if (service.path.length()) { if ( !workaround ) { struct stat64 s; if (::stat64(service.path.c_str(), &s)) { eDebug("file %s not exist.. don't play", service.path.c_str() ); return -1; } if ( eDVB::getInstance()->recorder && service.path == eDVB::getInstance()->recorder->getFilename() ) startPlayback(service.path, 2); else startPlayback(service.path, 0); } else flags |= (flagIsSeekable|flagSupportPosition); } else #endif { flags &= ~(flagIsSeekable|flagSupportPosition); serviceEvent(eServiceEvent(eServiceEvent::evtFlagsChanged) ); } if (sapi) return sapi->switchService((const eServiceReferenceDVB&)service); return -1; }
void eServiceHandlerDVB::startPlayback(const eString &filename, int livemode, bool startpaused) { stopPlayback(); decoder=new eDVRPlayerThread(filename.c_str(), this, livemode,playingPermanentTimeshift); if (startpaused) { decoder->messages.send(eDVRPlayerThread::eDVRPlayerThreadMessage(eDVRPlayerThread::eDVRPlayerThreadMessage::startPaused, livemode)); } else { decoder->messages.send(eDVRPlayerThread::eDVRPlayerThreadMessage(eDVRPlayerThread::eDVRPlayerThreadMessage::start, livemode)); } flags=flagIsSeekable|flagSupportPosition; state= statePlaying; if ( livemode ) flags|=flagStartTimeshift; pcrpid = Decoder::current.pcrpid; // stop pcrpid Decoder::parms.pcrpid = -1; Decoder::Set(); serviceEvent(eServiceEvent(eServiceEvent::evtFlagsChanged) ); if ( livemode ) flags&=~flagStartTimeshift; }
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 eDVBServicePMTHandler::AITready(int error) { eDebug("AITready"); ePtr<eTable<ApplicationInformationSection> > ptr; m_aitInfoList.clear(); if (!m_AIT.getCurrent(ptr)) { m_HBBTVUrl = ""; for (std::vector<ApplicationInformationSection*>::const_iterator it = ptr->getSections().begin(); it != ptr->getSections().end(); ++it) { for (std::list<ApplicationInformation *>::const_iterator i = (*it)->getApplicationInformation()->begin(); i != (*it)->getApplicationInformation()->end(); ++i) { struct aitInfo aitinfo; aitinfo.id = ((ApplicationIdentifier*)(*i)->getApplicationIdentifier())->getApplicationId(); for (DescriptorConstIterator desc = (*i)->getDescriptors()->begin(); desc != (*i)->getDescriptors()->end(); ++desc) { switch ((*desc)->getTag()) { case APPLICATION_DESCRIPTOR: break; case APPLICATION_NAME_DESCRIPTOR: { ApplicationNameDescriptor *appname = (ApplicationNameDescriptor*)(*desc); for (ApplicationNameConstIterator appnamesit = appname->getApplicationNames()->begin(); appnamesit != appname->getApplicationNames()->end(); ++appnamesit) { aitinfo.name = (*appnamesit)->getApplicationName(); } break; } case TRANSPORT_PROTOCOL_DESCRIPTOR: { TransportProtocolDescriptor *transport = (TransportProtocolDescriptor*)(*desc); switch (transport->getProtocolId()) { case 1: /* object carousel */ if (m_dsmcc_pid >= 0) { m_OC.begin(eApp, eDVBDSMCCDLDataSpec(m_dsmcc_pid), m_demux); } break; case 2: /* ip */ break; case 3: /* interaction */ for (InterActionTransportConstIterator interactionit = transport->getInteractionTransports()->begin(); interactionit != transport->getInteractionTransports()->end(); ++interactionit) { if ((*i)->getApplicationControlCode() == 0x01) /* AUTOSTART */ { m_HBBTVUrl = (*interactionit)->getUrlBase()->getUrl(); } aitinfo.url = (*interactionit)->getUrlBase()->getUrl(); break; } break; } break; } case GRAPHICS_CONSTRAINTS_DESCRIPTOR: break; case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR: { SimpleApplicationLocationDescriptor *applicationlocation = (SimpleApplicationLocationDescriptor*)(*desc); if ((*i)->getApplicationControlCode() == 0x01) /* AUTOSTART */ { m_HBBTVUrl += applicationlocation->getInitialPath(); } aitinfo.url += applicationlocation->getInitialPath(); m_aitInfoList.push_back(aitinfo); break; } case APPLICATION_USAGE_DESCRIPTOR: break; case SIMPLE_APPLICATION_BOUNDARY_DESCRIPTOR: break; } } } } if (!m_HBBTVUrl.empty()) { serviceEvent(eventHBBTVInfo); } } /* for now, do not keep listening for table updates */ m_AIT.stop(); }
void eDVBServicePMTHandler::sendEventNoPatEntry() { serviceEvent(eventNoPATEntry); }
void eServiceHandlerDVB::gotEIT(EIT *, int) { serviceEvent(eServiceEvent(eServiceEvent::evtGotEIT)); }
void eServiceHandlerDVB::gotSDT(SDT *) { serviceEvent(eServiceEvent(eServiceEvent::evtGotSDT)); }
void eServiceHandlerDVB::leaveService(const eServiceReferenceDVB &e) { if ( e ) serviceEvent(eServiceEvent(eServiceEvent::evtStop)); }
void eServiceHandlerDVB::aspectRatioChanged(int isanamorph) { aspect=isanamorph; serviceEvent(eServiceEvent(eServiceEvent::evtAspectChanged)); }