From c79fe413d69712417a53e0b6c5eb6c9c653091a0 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 13:53:54 +0400 Subject: [PATCH 001/737] Add CFEManager class --- src/zapit/include/zapit/femanager.h | 119 ++++++ src/zapit/src/Makefile.am | 2 +- src/zapit/src/femanager.cpp | 614 ++++++++++++++++++++++++++++ 3 files changed, 734 insertions(+), 1 deletion(-) create mode 100644 src/zapit/include/zapit/femanager.h create mode 100644 src/zapit/src/femanager.cpp diff --git a/src/zapit/include/zapit/femanager.h b/src/zapit/include/zapit/femanager.h new file mode 100644 index 000000000..4ae542bd7 --- /dev/null +++ b/src/zapit/include/zapit/femanager.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __femanager_h__ +#define __femanager_h__ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_FE 2 +#define MAX_ADAPTERS 1 +#define MAKE_FE_KEY(adapter, number) ((adapter << 8) | (number & 0xFF)) + +#define FECONFIGFILE CONFIGDIR "/zapit/frontend.conf" + +typedef std::map fe_map_t; +typedef fe_map_t::iterator fe_map_iterator_t; + +typedef std::map fe_channel_map_t; +typedef fe_channel_map_t::iterator fe_channel_map_iterator_t; + +typedef struct common_fe_config { + double gotoXXLatitude, gotoXXLongitude; + int gotoXXLaDirection, gotoXXLoDirection; + int repeatUsals; + int feTimeout; +} common_fe_config_t; + +class CFEManager +{ + public: + typedef enum { + FE_MODE_SINGLE, + FE_MODE_LOOP, + FE_MODE_TWIN, + FE_MODE_ALONE + } fe_mode_t; + private: + fe_map_t femap; + fe_mode_t mode; + CConfigFile configfile; + common_fe_config_t config; + bool config_exist; + /* loop cache */ + bool high_band; + uint8_t polarization; + + bool have_locked; + OpenThreads::Mutex mutex; + + CFrontend * livefe; + + CFrontend * findFrontend(CZapitChannel * channel); + uint32_t getConfigValue(CFrontend * fe, const char * name, uint32_t defval); + void setConfigValue(CFrontend * fe, const char * name, uint32_t val); + void setSatelliteConfig(CFrontend * fe, sat_config_t &satconfig); + bool getSatelliteConfig(CFrontend * fe, sat_config_t &satconfig); + + static CFEManager * manager; + CFEManager(); + public: + static CFEManager *getInstance(); + ~CFEManager(); + + bool Init(); + void Close(); + void Open(); + + CFrontend * getFE(int index = 0); + CFrontend * getLiveFE() { return livefe; }; + void setLiveFE(CFrontend * fe); + + transponder * getChannelTransponder(CZapitChannel * channel); + CFrontend * allocateFE(CZapitChannel * channel); + bool loopCanTune(CFrontend * fe, CZapitChannel * channel); + CFrontend * getLoopFE(CZapitChannel * channel); + CFrontend * getIndependentFE(CZapitChannel * channel); + + fe_mode_t getMode() { return mode; }; + void setMode(fe_mode_t newmode, bool initial = false); + + int getFrontendCount() { return femap.size(); }; + + CFrontend * getScanFrontend(t_satellite_position satellitePosition); + bool canTune(CZapitChannel * channel); + + bool configExist() { return config_exist; }; + bool loadSettings(); + void saveSettings(bool write = true); + + bool lockFrontend(CFrontend * fe); + bool unlockFrontend(CFrontend * fe); + bool haveFreeFrontend(); +}; +#endif /* __femanager_h__ */ diff --git a/src/zapit/src/Makefile.am b/src/zapit/src/Makefile.am index 94f11c0e9..813aa055e 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -20,7 +20,7 @@ noinst_LIBRARIES = libzapit.a libzapit_a_SOURCES = \ bouquets.cpp channel.cpp dvbstring.cpp getservices.cpp \ - scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp \ + scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp femanager.cpp \ descriptors.cpp nit.cpp pat.cpp pmt.cpp sdt.cpp fastscan.cpp bin_PROGRAMS = pzapit diff --git a/src/zapit/src/femanager.cpp b/src/zapit/src/femanager.cpp new file mode 100644 index 000000000..9cd2bc541 --- /dev/null +++ b/src/zapit/src/femanager.cpp @@ -0,0 +1,614 @@ +/* + Neutrino-GUI - DBoxII-Project + + Copyright (C) 2011 CoolStream International Ltd + + License: GPLv2 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +extern transponder_list_t transponders; + +CFEManager * CFEManager::manager = NULL; + +CFEManager::CFEManager() : configfile(',', true) +{ + livefe = NULL; + mode = FE_MODE_SINGLE; + config_exist = false; + have_locked = false; +} + +bool CFEManager::Init() +{ + CFrontend * fe; + unsigned short fekey; + + for(int i = 0; i < MAX_ADAPTERS; i++) { + for(int j = 0; j < MAX_FE; j++) { + fe = new CFrontend(j, i); + if(fe->Open()) { + fekey = MAKE_FE_KEY(i, j); + femap.insert(std::pair (fekey, fe)); + INFO("add fe %d", fe->fenumber); + if(livefe == NULL) + livefe = fe; + } else + delete fe; + } + } + INFO("found %d frontends\n", femap.size()); + if(femap.size() == 0) + return false; +#if 0 + if(femap.size() == 1) + mode = FE_MODE_SINGLE; +#endif + return true; +} + +CFEManager::~CFEManager() +{ + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) + delete it->second; +} + +CFEManager * CFEManager::getInstance() +{ + if(manager == NULL) + manager = new CFEManager(); + return manager; +} + +uint32_t CFEManager::getConfigValue(CFrontend * fe, const char * name, uint32_t defval) +{ + char cfg_key[81]; + sprintf(cfg_key, "fe%d_%s", fe->fenumber, name); + return configfile.getInt32(cfg_key, defval); +} + +void CFEManager::setConfigValue(CFrontend * fe, const char * name, uint32_t val) +{ + char cfg_key[81]; + sprintf(cfg_key, "fe%d_%s", fe->fenumber, name); + configfile.setInt32(cfg_key, val); +} + +#define SATCONFIG_SIZE 12 +void CFEManager::setSatelliteConfig(CFrontend * fe, sat_config_t &satconfig) +{ + char cfg_key[81]; + std::vector satConfig; + + satConfig.push_back(satconfig.position); + satConfig.push_back(satconfig.diseqc); + satConfig.push_back(satconfig.commited); + satConfig.push_back(satconfig.uncommited); + satConfig.push_back(satconfig.motor_position); + satConfig.push_back(satconfig.diseqc_order); + satConfig.push_back(satconfig.lnbOffsetLow); + satConfig.push_back(satconfig.lnbOffsetHigh); + satConfig.push_back(satconfig.lnbSwitch); + satConfig.push_back(satconfig.use_in_scan); + satConfig.push_back(satconfig.use_usals); + satConfig.push_back(satconfig.configured); + + sprintf(cfg_key, "fe%d_position_%d", fe->fenumber, satconfig.position); + //INFO("set %s", cfg_key); + configfile.setInt32Vector(cfg_key, satConfig); +} + +bool CFEManager::getSatelliteConfig(CFrontend * fe, sat_config_t &satconfig) +{ + char cfg_key[81]; + int i = 1; + + sprintf(cfg_key, "fe%d_position_%d", fe->fenumber, satconfig.position); + std::vector satConfig = configfile.getInt32Vector(cfg_key); + //INFO("get %s: size %d", cfg_key, satConfig.size()); + if(satConfig.size() >= SATCONFIG_SIZE) { + satconfig.diseqc = satConfig[i++]; + satconfig.commited = satConfig[i++]; + satconfig.uncommited = satConfig[i++]; + satconfig.motor_position = satConfig[i++]; + satconfig.diseqc_order = satConfig[i++]; + satconfig.lnbOffsetLow = satConfig[i++]; + satconfig.lnbOffsetHigh = satConfig[i++]; + satconfig.lnbSwitch = satConfig[i++]; + satconfig.use_in_scan = satConfig[i++]; + satconfig.use_usals = satConfig[i++]; + satconfig.configured = satConfig[i++]; + return true; + } + return false; +} + +bool CFEManager::loadSettings() +{ + config_exist = true; + if (!configfile.loadConfig(FECONFIGFILE)) { + WARN("%s not found", FECONFIGFILE); + config_exist = false; + //return false; + } + + fe_mode_t newmode = (fe_mode_t) configfile.getInt32("mode", (int) FE_MODE_SINGLE); + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + frontend_config_t & fe_config = fe->getConfig(); + INFO("load config for fe%d", fe->fenumber); + + //fe_config.diseqcType = (diseqc_t) getConfigValue(fe, "diseqcType", NO_DISEQC); + diseqc_t diseqcType = (diseqc_t) getConfigValue(fe, "diseqcType", NO_DISEQC); + fe_config.diseqcRepeats = getConfigValue(fe, "diseqcRepeats", 0); + fe_config.motorRotationSpeed = getConfigValue(fe, "motorRotationSpeed", 18); + fe_config.highVoltage = getConfigValue(fe, "highVoltage", 0); + fe_config.uni_scr = getConfigValue(fe, "uni_scr", -1); + fe_config.uni_qrg = getConfigValue(fe, "uni_qrg", 0); + + fe->setCurrentSatellitePosition(getConfigValue(fe, "lastSatellitePosition", 0)); + + //fe->setDiseqcType((diseqc_t) fe_config.diseqcType); + fe->setDiseqcType(diseqcType); + + char cfg_key[81]; + sprintf(cfg_key, "fe%d_satellites", fe->fenumber); + std::vector satList = configfile.getInt32Vector(cfg_key); + satellite_map_t & satmap = fe->getSatellites(); +#if 0 + for(unsigned int i = 0; i < satList.size(); i++) + t_satellite_position position = satList[i]; +#endif + satellite_map_t satlist = CServiceManager::getInstance()->SatelliteList(); + for(sat_iterator_t sit = satlist.begin(); sit != satlist.end(); ++sit) + { + t_satellite_position position = sit->first; + sat_config_t satconfig; + /* defaults, to replace CServiceManager::InitSatPosition/LoadMotorPositions + * in the future */ + satconfig.position = position; + satconfig.diseqc = -1; + satconfig.commited = -1; + satconfig.uncommited = -1; + satconfig.motor_position = 0; + satconfig.diseqc_order = 0; + satconfig.lnbOffsetLow = 9750; + satconfig.lnbOffsetHigh = 10600; + satconfig.lnbSwitch = 11700; + satconfig.use_in_scan = 0; + satconfig.use_usals = 0; + satconfig.input = 0; + satconfig.configured = 0; + + satmap.insert(satellite_pair_t(position, satconfig)); + + if(getSatelliteConfig(fe, satconfig)) + satmap[position] = satconfig; // overwrite if exist + + } + } + setMode(newmode, true); + return true; +} + +void CFEManager::saveSettings(bool write) +{ + configfile.setInt32("mode", (int) mode); + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + frontend_config_t & fe_config = fe->getConfig(); + + INFO("fe%d", fe->fenumber); + if(fe->fenumber && mode != FE_MODE_ALONE) { + CFrontend * fe0 = getFE(0); + fe->setConfig(fe0->getConfig()); + fe->setSatellites(fe0->getSatellites()); + } + + setConfigValue(fe, "diseqcType", fe_config.diseqcType); + setConfigValue(fe, "diseqcRepeats", fe_config.diseqcRepeats); + setConfigValue(fe, "motorRotationSpeed", fe_config.motorRotationSpeed); + setConfigValue(fe, "highVoltage", fe_config.highVoltage); + setConfigValue(fe, "uni_scr", fe_config.uni_scr); + setConfigValue(fe, "uni_qrg", fe_config.uni_qrg); + setConfigValue(fe, "lastSatellitePosition", fe->getCurrentSatellitePosition()); + + std::vector satList; + satellite_map_t satellites = fe->getSatellites(); + for(sat_iterator_t sit = satellites.begin(); sit != satellites.end(); ++sit) { + satList.push_back(sit->first); + setSatelliteConfig(fe, sit->second); + } + char cfg_key[81]; + sprintf(cfg_key, "fe%d_satellites", fe->fenumber); + configfile.setInt32Vector(cfg_key, satList); + } + //setInt32Vector dont set modified flag ! + if (write /*&& configfile.getModifiedFlag()*/) { + config_exist = configfile.saveConfig(FECONFIGFILE); + //configfile.setModifiedFlag(false); + } +} + +void CFEManager::setMode(fe_mode_t newmode, bool initial) +{ + if(newmode == mode) + return; + + if(femap.size() == 1) { + mode = FE_MODE_SINGLE; + return; + } + mode = newmode; + bool setslave = (mode == FE_MODE_LOOP); + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + if(it != femap.begin()) { + CFrontend * fe = it->second; + INFO("Frontend %d as slave: %s", fe->fenumber, setslave ? "yes" : "no"); + fe->setMasterSlave(setslave); + } + } + if(setslave && !initial) { + CFrontend * fe = getFE(0); + fe->Close(); + fe->Open(); + } +} + +void CFEManager::Open() +{ + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + if(!fe->Locked()) + fe->Open(); + } +} + +void CFEManager::Close() +{ + if(have_locked && (mode == FE_MODE_LOOP)) + return; + + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + if(!fe->Locked()) + fe->Close(); + } +} + +CFrontend * CFEManager::getFE(int index) +{ + if((unsigned int) index < femap.size()) + return femap[index]; + INFO("Frontend #%d not found", index); + return NULL; +} + +transponder * CFEManager::getChannelTransponder(CZapitChannel * channel) +{ + transponder_list_t::iterator tpI = transponders.find(channel->getTransponderId()); + if(tpI != transponders.end()) + return &tpI->second; + + INFO("Transponder %llx not found", channel->getTransponderId()); + return NULL; +} + +/* try to find fe with same tid, or unlocked. fe with same tid is preffered */ +CFrontend * CFEManager::findFrontend(CZapitChannel * channel) +{ + CFrontend * same_tid_fe = NULL; + CFrontend * free_frontend = NULL; + transponder_id_t channel_tid = channel->getTransponderId(); + + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + INFO("Check fe%d: locked %d TP %llx - channel TP %llx", fe->fenumber, fe->Locked(), fe->getTsidOnid(), channel_tid); + if(fe->tuned && fe->sameTsidOnid(channel->getTransponderId())) { + same_tid_fe = fe; + break; + } + else if(!fe->Locked() && !free_frontend) + free_frontend = fe; + } + + CFrontend * ret = same_tid_fe ? same_tid_fe : free_frontend; + INFO("Selected fe: %d", ret ? ret->fenumber : -1); + return ret; +} + +/* compare polarization and band with fe values */ +bool CFEManager::loopCanTune(CFrontend * fe, CZapitChannel * channel) +{ + if(fe->getInfo()->type != FE_QPSK) + return true; + + if(fe->tuned && (fe->getCurrentSatellitePosition() != channel->getSatellitePosition())) + return false; + +#if 0 + transponder * tp = getChannelTransponder(channel); + if(tp == NULL) + return false; + + bool tp_band = ((int)tp->feparams.frequency >= fe->lnbSwitch); + uint8_t tp_pol = tp->polarization & 1; +#else + bool tp_band = ((int)channel->getFreqId()*1000 >= fe->lnbSwitch); + uint8_t tp_pol = channel->polarization & 1; +#endif + uint8_t fe_pol = fe->getPolarization() & 1; + + INFO("Check fe%d: locked %d pol:band %d:%d vs %d:%d (%d:%d)", fe->fenumber, fe->Locked(), fe_pol, fe->getHighBand(), tp_pol, tp_band, fe->getFrequency(), channel->getFreqId()*1000); + if(!fe->tuned || (fe_pol == tp_pol && fe->getHighBand() == tp_band)) + return true; + return false; +} + +CFrontend * CFEManager::getLoopFE(CZapitChannel * channel) +{ + CFrontend * free_frontend = NULL; + CFrontend * same_tid_fe = NULL; + + /* check is there any locked fe, remember fe with same transponder */ + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + INFO("Check fe%d: locked %d freq %d TP %llx - channel freq %d TP %llx", fe->fenumber, fe->Locked(), fe->getFrequency(), fe->getTsidOnid(), channel->getFreqId(), channel->getTransponderId()); +#if 0 + if(fe->tuned && fe->sameTsidOnid(channel->getTransponderId())) { + same_tid_fe = fe; // first with same tp id + break; + } +#endif + if(fe->Locked() /* && !same_tid_fe*/) { + INFO("fe %d locked", fe->fenumber); + if(!loopCanTune(fe, channel)) { + free_frontend = NULL; + break; + } + if(fe->tuned && fe->sameTsidOnid(channel->getTransponderId())) { + same_tid_fe = fe; // first with same tp id + } + } else if(!free_frontend) + free_frontend = fe; // first unlocked + } + + CFrontend * ret = same_tid_fe ? same_tid_fe : free_frontend; + INFO("Selected fe: %d", ret ? ret->fenumber : -1); + return ret; +} + +CFrontend * CFEManager::getIndependentFE(CZapitChannel * channel) +{ + CFrontend * free_frontend = NULL; + CFrontend * same_tid_fe = NULL; + + t_satellite_position satellitePosition = channel->getSatellitePosition(); + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + satellite_map_t & satmap = fe->getSatellites(); + sat_iterator_t sit = satmap.find(satellitePosition); + bool configured = ((sit != satmap.end()) && sit->second.configured); + INFO("Check fe%d: locked %d freq %d TP %llx - channel freq %d TP %llx has sat %d: %s", + fe->fenumber, fe->Locked(), fe->getFrequency(), fe->getTsidOnid(), + channel->getFreqId(), channel->getTransponderId(), satellitePosition, configured ? "yes" : "no"); + if(!configured) + continue; + + if(fe->tuned && fe->sameTsidOnid(channel->getTransponderId())) { + same_tid_fe = fe; + break; + } + else if(!fe->Locked() && !free_frontend) + free_frontend = fe; + } + CFrontend * ret = same_tid_fe ? same_tid_fe : free_frontend; + INFO("Selected fe: %d", ret ? ret->fenumber : -1); + return ret; +} + +CFrontend * CFEManager::allocateFE(CZapitChannel * channel) +{ + CFrontend * frontend = NULL, *fe; + + mutex.lock(); + switch(mode) { + case FE_MODE_SINGLE: + if((fe = getFE(0))) { + if(!fe->Locked() || fe->sameTsidOnid(channel->getTransponderId())) + frontend = fe; + } + break; + case FE_MODE_LOOP: + frontend = getLoopFE(channel); + break; + case FE_MODE_TWIN: + frontend = findFrontend(channel); + break; + case FE_MODE_ALONE: + frontend = getIndependentFE(channel); + break; + } + //FIXME for testing only + if(frontend) { + channel->setRecordDemux(frontend->fenumber+1); + if(femap.size() > 1) + cDemux::SetSource(frontend->fenumber+1, frontend->fenumber); + } + mutex.unlock(); + return frontend; +} + +void CFEManager::setLiveFE(CFrontend * fe) +{ + mutex.lock(); + livefe = fe; + if(femap.size() > 1) + cDemux::SetSource(0, livefe->fenumber); + mutex.unlock(); +}; + +bool CFEManager::canTune(CZapitChannel * channel) +{ + /* TODO: for faster processing, cache ? FE_MODE_LOOP: pol and band, + * is there unlocked or not, what else ? + */ + CFrontend * fe; + bool ret = false; +#if 0 + if(!have_locked) + return true; +#endif + switch(mode) { + case FE_MODE_SINGLE: + if((fe = getFE(0))) { + if(!fe->Locked() || fe->sameTsidOnid(channel->getTransponderId())) + ret = true; + } + break; + case FE_MODE_LOOP: +#if 1 + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + fe = it->second; + if(fe->tuned && fe->sameTsidOnid(channel->getTransponderId())) + return true; + if(fe->Locked()) { + if(!loopCanTune(fe, channel)) { + return false; + } + } else + ret = true; + } +#else + ret = (getLoopFE(channel) != NULL); +#endif + break; + case FE_MODE_TWIN: + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + fe = it->second; + if(!fe->Locked() || fe->sameTsidOnid(channel->getTransponderId())) + return true; + } + break; + case FE_MODE_ALONE: + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + fe = it->second; + satellite_map_t & satmap = fe->getSatellites(); + sat_iterator_t sit = satmap.find(channel->getSatellitePosition()); + if(((sit != satmap.end()) && sit->second.configured)) { + if(!fe->Locked() || fe->sameTsidOnid(channel->getTransponderId())) + return true; + } + } + break; + } + return ret; +} + +CFrontend * CFEManager::getScanFrontend(t_satellite_position satellitePosition) +{ + CFrontend * frontend = NULL; + switch(mode) { + case FE_MODE_SINGLE: + case FE_MODE_LOOP: + //FIXME scan while recording ? + case FE_MODE_TWIN: + frontend = getFE(0); + break; + case FE_MODE_ALONE: + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + satellite_map_t & satmap = fe->getSatellites(); + sat_iterator_t sit = satmap.find(satellitePosition); + if(((sit != satmap.end()) && sit->second.configured)) { + frontend = fe; + break; + } + } + break; + } + INFO("Selected fe: %d", frontend ? frontend->fenumber : -1); + return frontend; +} + +bool CFEManager::lockFrontend(CFrontend * frontend) +{ + mutex.lock(); + frontend->Lock(); + have_locked = true; + polarization = frontend->getPolarization() & 1; + high_band = frontend->getHighBand(); + mutex.unlock(); + return true; +} + +bool CFEManager::unlockFrontend(CFrontend * frontend) +{ + mutex.lock(); + have_locked = false; + frontend->Unlock(); + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + CFrontend * fe = it->second; + if(fe->Locked()) { + have_locked = true; + polarization = fe->getPolarization() & 1; + high_band = fe->getHighBand(); + break; + } + } + mutex.unlock(); + return true; +} + +bool CFEManager::haveFreeFrontend() +{ + if(have_locked) { + CFrontend * fe = getFE(0); + if((mode == FE_MODE_TWIN) || (fe->getInfo()->type != FE_QPSK)) { + for(fe_map_iterator_t it = femap.begin(); it != femap.end(); it++) { + fe = it->second; + INFO("check %d: locked %d", fe->fenumber, fe->Locked()); + if(!fe->Locked()) + return true; + } + } +#if 0 + if(mode == FE_MODE_LOOP) + return false; +#endif + return false; + } + return true; +} From c242a61ea2a60c855bd4d2a8aa8e46855a267aba Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 13:55:52 +0400 Subject: [PATCH 002/737] New CPat class to parse PAT, replace old code --- src/zapit/include/zapit/pat.h | 38 ++++++-- src/zapit/src/pat.cpp | 169 ++++++++++++---------------------- 2 files changed, 87 insertions(+), 120 deletions(-) diff --git a/src/zapit/include/zapit/pat.h b/src/zapit/include/zapit/pat.h index d87964bcf..c5a5fb676 100644 --- a/src/zapit/include/zapit/pat.h +++ b/src/zapit/include/zapit/pat.h @@ -1,12 +1,13 @@ /* - * $Id: pat.h,v 1.18 2003/01/30 17:21:16 obi Exp $ + * Neutrino-GUI - DBoxII-Project * - * (C) 2002-2003 Andreas Oberritter + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,11 +23,30 @@ #ifndef __zapit_pat_h__ #define __zapit_pat_h__ -#include "channel.h" +#include +#include -int parse_pat(CZapitChannel * const channel); -int scan_parse_pat( std::vector > &sidpmt ); -int parse_pat(void); -int pat_get_pmt_pid (CZapitChannel * const channel); +#define PAT_SECTION_SIZE 1024 + +typedef std::map sidpmt_map_t; +typedef sidpmt_map_t::iterator sidpmt_map_iterator_t; +typedef std::pair sidpmt_map_pair_t; + +class CPat +{ + private: + cDemux * dmx; + int dmxnum; + bool parsed; + sidpmt_map_t sidpmt; + + public: + CPat(int dnum = 0); + ~CPat(); + void Reset(); + bool Parse(); + unsigned short GetPmtPid(t_service_id sid); + bool Parse(CZapitChannel * const channel); +}; #endif /* __zapit_pat_h__ */ diff --git a/src/zapit/src/pat.cpp b/src/zapit/src/pat.cpp index 6c0d8f620..20f1a49aa 100644 --- a/src/zapit/src/pat.cpp +++ b/src/zapit/src/pat.cpp @@ -1,12 +1,13 @@ /* - * $Id: pat.cpp,v 1.44 2003/01/30 17:21:17 obi Exp $ + * Neutrino-GUI - DBoxII-Project * - * (C) 2002 by Andreas Oberritter + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -23,18 +24,34 @@ #include #include -#define PAT_SIZE 1024 - -int parse_pat(CZapitChannel * const channel) +CPat::CPat(int dnum) { - if (!channel) - return -1; + parsed = false; + dmxnum = dnum; +} - cDemux * dmx = new cDemux(); +CPat::~CPat() +{ + sidpmt.clear(); +} + +void CPat::Reset() +{ + sidpmt.clear(); + parsed = false; +} + +bool CPat::Parse() +{ + //INFO("parsed: %s", parsed ? "yes" : "no"); + if(parsed) + return true; + + dmx = new cDemux(dmxnum); dmx->Open(DMX_PSI_CHANNEL); /* buffer for program association table */ - unsigned char buffer[PAT_SIZE]; + unsigned char buffer[PAT_SECTION_SIZE]; /* current positon in buffer */ unsigned short i; @@ -51,113 +68,43 @@ int parse_pat(CZapitChannel * const channel) do { /* set filter for program association section */ /* read section */ - if ((dmx->sectionFilter(0, filter, mask, 5) < 0) || (i = dmx->Read(buffer, PAT_SIZE) < 0)) + if ((dmx->sectionFilter(0, filter, mask, 5) < 0) || (i = dmx->Read(buffer, PAT_SECTION_SIZE) < 0)) { delete dmx; printf("[pat.cpp] dmx read failed\n"); - return -1; + return false; } -if(buffer[7]) printf("[PAT] ***************************************************** section %X last %X\n", buffer[6], buffer[7]); -//printf("[pat.cpp] dmx read %d len %d\n", i, ( (buffer[1] & 0x0F) << 8) | buffer[2]); /* loop over service id / program map table pid pairs */ for (i = 8; i < (((buffer[1] & 0x0F) << 8) | buffer[2]) + 3; i += 4) { - /* compare service id */ - if (channel->getServiceId() == ((buffer[i] << 8) | buffer[i+1])) { - /* store program map table pid */ - channel->setPmtPid(((buffer[i+2] & 0x1F) << 8) | buffer[i+3]); - delete dmx; - return 0; - } - } - } while (filter[4]++ != buffer[7]); - delete dmx; - - printf("[pat.cpp] sid %X not found..\n", channel->getServiceId()); - return -1; -} - -int scan_parse_pat( std::vector > &sidpmt ) -{ - - cDemux * dmx = new cDemux(); - dmx->Open(DMX_PSI_CHANNEL); - - /* buffer for program association table */ - unsigned char buffer[PAT_SIZE]; - - /* current positon in buffer */ - unsigned short i; - - unsigned char filter[DMX_FILTER_SIZE]; - unsigned char mask[DMX_FILTER_SIZE]; - - memset(filter, 0x00, DMX_FILTER_SIZE); - memset(mask, 0x00, DMX_FILTER_SIZE); - - mask[0] = 0xFF; - mask[4] = 0xFF; - - do { - /* set filter for program association section */ - /* read section */ - if ((dmx->sectionFilter(0, filter, mask, 5) < 0) || (i = dmx->Read(buffer, PAT_SIZE) < 0)) - { - delete dmx; - printf("[%s] dmx read failed\n",__FILE__); - return -1; - } - dmx->Stop(); - for (i = 8; i < (((buffer[1] & 0x0F) << 8) | buffer[2]) + 3; i += 4) { - int service_id = ((buffer[i] << 8) | buffer[i+1]); - if (service_id != 0) - sidpmt.push_back(std::make_pair( service_id , (((buffer[i+2] & 0x1F) << 8) | buffer[i+3]) ) ); - } - } while (filter[4]++ != buffer[7]); - delete dmx; - return 1; -} - -static unsigned char pbuffer[PAT_SIZE]; -int parse_pat() -{ - int ret = 0; - - printf("[scan] Parsing pat ...\n"); - cDemux * dmx = new cDemux(); - dmx->Open(DMX_PSI_CHANNEL); - - unsigned char filter[DMX_FILTER_SIZE]; - unsigned char mask[DMX_FILTER_SIZE]; - - memset(filter, 0x00, DMX_FILTER_SIZE); - memset(mask, 0x00, DMX_FILTER_SIZE); - - mask[0] = 0xFF; - mask[4] = 0xFF; - - memset(pbuffer, 0x00, PAT_SIZE); - if ((dmx->sectionFilter(0, filter, mask, 5) < 0) || (dmx->Read(pbuffer, PAT_SIZE) < 0)) - { - printf("[pat.cpp] dmx read failed\n"); - ret = -1; - } - delete dmx; - return ret; -} - -int pat_get_pmt_pid (CZapitChannel * const channel) -{ - unsigned short i; - - for (i = 8; i < (((pbuffer[1] & 0x0F) << 8) | pbuffer[2]) + 3; i += 4) { - /* compare service id */ - if (channel->getServiceId() == ((pbuffer[i] << 8) | pbuffer[i+1])) { /* store program map table pid */ - channel->setPmtPid(((pbuffer[i+2] & 0x1F) << 8) | pbuffer[i+3]); - return 0; + int service_id = ((buffer[i] << 8) | buffer[i+1]); + int pmt_pid = (((buffer[i+2] & 0x1F) << 8) | buffer[i+3]); + sidpmt.insert(sidpmt_map_pair_t(service_id, pmt_pid)); } - } - printf("[pat.cpp] sid %X not found..\n", channel->getServiceId()); - return -1; + } while (filter[4]++ != buffer[7]); + parsed = true; + delete dmx; + return true; } +unsigned short CPat::GetPmtPid(t_service_id sid) +{ + unsigned short pid = 0; + + if(Parse()) { + sidpmt_map_iterator_t it = sidpmt.find(sid); + if(it != sidpmt.end()) + pid = it->second; + } + return pid; +} + +bool CPat::Parse(CZapitChannel * const channel) +{ + unsigned short pid = GetPmtPid(channel->getServiceId()); + if(pid > 0) { + channel->setPmtPid(pid); + return true; + } + return false; +} From c49ccd0b78fce58db8fe3cf6b063876e05cd4b22 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:09:13 +0400 Subject: [PATCH 003/737] * Add struct to keep frontend settigs * Add satellite map to keep configured satellites * Change Lock() to handle usecount * Use slave member to protect diseqc/voltage/tone operations * Change debug to include frontend number --- src/zapit/include/zapit/frontend_c.h | 67 ++++---- src/zapit/src/frontend.cpp | 226 +++++++++++++++------------ 2 files changed, 170 insertions(+), 123 deletions(-) diff --git a/src/zapit/include/zapit/frontend_c.h b/src/zapit/include/zapit/frontend_c.h index 77ebd4d41..e10d9566e 100644 --- a/src/zapit/include/zapit/frontend_c.h +++ b/src/zapit/include/zapit/frontend_c.h @@ -3,6 +3,8 @@ * * (C) 2002-2003 Andreas Oberritter * + * Copyright (C) 2011 CoolStream International Ltd + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -23,8 +25,9 @@ #define __zapit_frontend_h__ #include -#include "types.h" -#include "channel.h" +#include +#include +#include #include #define FEC_S2_QPSK_1_2 (fe_code_rate_t)(FEC_AUTO+1) //10 @@ -76,9 +79,16 @@ typedef struct dvb_frontend_parameters FrontendParameters; #define MAX_LNBS 64 /* due to Diseqc 1.1 (2003-01-10 rasc) */ -class CFrontend; -typedef std::map fe_map_t; -typedef fe_map_t::iterator fe_map_iterator_t; +class CFEManager; + +typedef struct frontend_config { + int diseqcRepeats; + int diseqcType; + int uni_scr; + int uni_qrg; + int motorRotationSpeed; + int highVoltage; +} frontend_config_t; class CFrontend { @@ -104,17 +114,9 @@ class CFrontend int32_t currentSatellitePosition; /* SETTINGS */ - /* how often to repeat DiSEqC 1.1 commands */ - uint8_t diseqcRepeats; - /* DiSEqC type of attached hardware */ - diseqc_t diseqcType; + frontend_config_t config; - /* variables for EN 50494 (a.k.a Unicable) */ - int uni_scr; /* the unicable SCR address, -1 == no unicable */ - int uni_qrg; /* the unicable frequency in MHz, 0 == from spec */ - - int motorRotationSpeed; //in 0.1 degrees per second - bool highVoltage; + satellite_map_t satellites; double gotoXXLatitude, gotoXXLongitude; int gotoXXLaDirection, gotoXXLoDirection; @@ -155,16 +157,17 @@ class CFrontend /* Private constructor */ CFrontend(int Number = 0, int Adapter = 0); + static CFrontend *getInstance(int Number = 0, int Adapter = 0); friend class CFEManager; public: ~CFrontend(void); - static CFrontend *getInstance(int Number = 0, int Adapter = 0); static fe_code_rate_t getCodeRate(const uint8_t fec_inner, int system = 0); uint8_t getDiseqcPosition(void) const { return currentTransponder.diseqc; } - uint8_t getDiseqcRepeats(void) const { return diseqcRepeats; } - diseqc_t getDiseqcType(void) const { return diseqcType; } - uint32_t getFrequency(void) const; + uint8_t getDiseqcRepeats(void) const { return config.diseqcRepeats; } + diseqc_t getDiseqcType(void) const { return (diseqc_t) config.diseqcType; } + uint32_t getFrequency(void) const { return curfe.frequency; } + bool getHighBand() { return (int) getFrequency() >= lnbSwitch; } static fe_modulation_t getModulation(const uint8_t modulation); uint8_t getPolarization(void) const; const struct dvb_frontend_info *getInfo(void) const { return &info; }; @@ -178,7 +181,7 @@ class CFrontend int32_t getCurrentSatellitePosition() { return currentSatellitePosition; } - void setDiseqcRepeats(const uint8_t repeats) { diseqcRepeats = repeats; } + void setDiseqcRepeats(const uint8_t repeats) { config.diseqcRepeats = repeats; } void setDiseqcType(const diseqc_t type); void setTimeout(int timeout) { feTimeout = timeout; }; void configUsals(double Latitude, double Longitude, int LaDirection, int LoDirection, bool _repeatUsals) @@ -190,8 +193,11 @@ class CFrontend repeatUsals = _repeatUsals; }; void configRotor(int _motorRotationSpeed, bool _highVoltage) - { motorRotationSpeed = _motorRotationSpeed; highVoltage = _highVoltage; }; - void configUnicable(int scr, int qrg) { uni_scr = scr; uni_qrg = qrg; }; + { config.motorRotationSpeed = _motorRotationSpeed; config.highVoltage = _highVoltage; }; + void configUnicable(int scr, int qrg) { config.uni_scr = scr; config.uni_qrg = qrg; }; + + frontend_config_t& getConfig() { return config; }; + void setConfig(frontend_config_t cfg) { setDiseqcType((diseqc_t) cfg.diseqcType); config = cfg; }; int setParameters(TP_params *TP, bool nowait = 0); int tuneFrequency (struct dvb_frontend_parameters * feparams, uint8_t polarization, bool nowait = false); @@ -208,24 +214,31 @@ class CFrontend fe_code_rate_t getCFEC (); transponder_id_t getTsidOnid() { return currentTransponder.TP_id; } + bool sameTsidOnid(transponder_id_t tpid) + { + return (currentTransponder.TP_id == 0) + || (tpid == currentTransponder.TP_id); + } void setTsidOnid(transponder_id_t newid) { currentTransponder.TP_id = newid; } uint32_t getRate (); bool Open(); void Close(); - void Lock() { locked = true; }; - void Unlock() { locked = false; }; + void Lock(); + void Unlock(); bool sendUncommittedSwitchesCommand(int input); bool setInput(CZapitChannel *channel, bool nvod); void setInput(t_satellite_position satellitePosition, uint32_t frequency, uint8_t polarization); bool setDiseqcSimple(int sat_no, const uint8_t pol, const uint32_t frequency); void setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequency); - void setMasterSlave(bool _slave) { slave = _slave; }; + void setMasterSlave(bool _slave); int driveToSatellitePosition(t_satellite_position satellitePosition, bool from_scan = false); void setLnbOffsets(int32_t _lnbOffsetLow, int32_t _lnbOffsetHigh, int32_t _lnbSwitch); struct dvb_frontend_event getEvent(void); - bool Locked() { return locked; }; + bool Locked() { return usecount; }; + satellite_map_t & getSatellites() { return satellites; } + void setSatellites(satellite_map_t satmap) { satellites = satmap; } + int getNumber() { return fenumber; }; }; - #endif /* __zapit_frontend_h__ */ diff --git a/src/zapit/src/frontend.cpp b/src/zapit/src/frontend.cpp index aa913c206..acc99e82c 100644 --- a/src/zapit/src/frontend.cpp +++ b/src/zapit/src/frontend.cpp @@ -3,6 +3,8 @@ * * (C) 2002-2003 Andreas Oberritter * + * Copyright (C) 2011 CoolStream International Ltd + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -114,8 +116,8 @@ static const struct dtv_property dvbc_cmdargs[] = { ((tv2.tv_usec-tv.tv_usec) / 1000); \ if(tmin > timer_msec) tmin = timer_msec; \ if(tmax < timer_msec) tmax = timer_msec; \ - printf("%s: %u msec (min %u max %u)\n", \ - label, timer_msec, tmin, tmax); + printf("[fe%d] %s: %u msec (min %u max %u)\n", \ + fenumber, label, timer_msec, tmin, tmax); // Internal Inner FEC representation typedef enum dvb_fec { @@ -132,6 +134,7 @@ typedef enum dvb_fec { fNone = 15 } dvb_fec_t; +/*********************************************************************************************************/ // Global fe instance CFrontend *CFrontend::currentFe = NULL; @@ -150,10 +153,10 @@ CFrontend::CFrontend(int Number, int Adapter) fd = -1; fenumber = Number; adapter = Adapter; - slave = fenumber; // FIXME - diseqcType = NO_DISEQC; + slave = false; standby = true; locked = false; + usecount = 0; memset(&curfe, 0, sizeof(curfe)); @@ -169,23 +172,27 @@ CFrontend::CFrontend(int Number, int Adapter) currentTransponder.TP_id = 0; currentTransponder.diseqc = 255; - uni_scr = -1; /* the unicable SCR address, -1 == no unicable */ - uni_qrg = 0; /* the unicable frequency in MHz, 0 == from spec */ + config.diseqcType = NO_DISEQC; + config.diseqcRepeats = 0; + config.uni_scr = -1; /* the unicable SCR address, -1 == no unicable */ + config.uni_qrg = 0; /* the unicable frequency in MHz, 0 == from spec */ + config.highVoltage = false; + config.motorRotationSpeed = 0; //in 0.1 degrees per second feTimeout = 40; - highVoltage = false; - motorRotationSpeed = 0; //in 0.1 degrees per second - + // to allow Open() switch it off + currentVoltage = SEC_VOLTAGE_OFF; //SEC_VOLTAGE_13; + currentToneMode = SEC_TONE_ON; } CFrontend::~CFrontend(void) { + printf("[fe%d] close frontend fd %d\n", fenumber, fd); if(fd >= 0) { - if (diseqcType > MINI_DISEQC) - sendDiseqcStandby(); + Close(); close(fd); } - currentFe = NULL; + //currentFe = NULL; } bool CFrontend::Open(void) @@ -205,11 +212,12 @@ bool CFrontend::Open(void) return false; } fop(ioctl, FE_GET_INFO, &info); - printf("[fe0] frontend fd %d type %d\n", fd, info.type); + printf("[fe%d] frontend fd %d type %d\n", fenumber, fd, info.type); } //FIXME info.type = FE_QAM; - currentVoltage = SEC_VOLTAGE_OFF; + //currentVoltage = SEC_VOLTAGE_OFF; + //secSetVoltage(SEC_VOLTAGE_OFF, 15); secSetVoltage(SEC_VOLTAGE_13, 15); secSetTone(SEC_TONE_OFF, 15); sendDiseqcPowerOn(); @@ -225,7 +233,7 @@ void CFrontend::Close(void) if(standby) return; - if (!slave && diseqcType > MINI_DISEQC) + if (!slave && config.diseqcType > MINI_DISEQC) sendDiseqcStandby(); secSetVoltage(SEC_VOLTAGE_OFF, 0); @@ -234,11 +242,44 @@ void CFrontend::Close(void) standby = true;; } +void CFrontend::setMasterSlave(bool _slave) +{ + if(slave == _slave) + return; + + if(_slave) { + secSetVoltage(SEC_VOLTAGE_OFF, 0); + secSetTone(SEC_TONE_OFF, 15); + } + slave = _slave; + if(!slave) { + secSetVoltage(SEC_VOLTAGE_13, 0); +#if 1 + diseqc_t diseqcType = (diseqc_t) config.diseqcType; + config.diseqcType = NO_DISEQC; + setDiseqcType(diseqcType); +#endif + } +} + void CFrontend::reset(void) { // No-op } +void CFrontend::Lock() +{ + usecount++; + INFO("[fe%d] usecount %d tp %llx\n", fenumber, usecount, getTsidOnid()); +} + +void CFrontend::Unlock() +{ + if(usecount > 0) + usecount--; + INFO("[fe%d] usecount %d tp %llx\n", fenumber, usecount, getTsidOnid()); +} + fe_code_rate_t CFrontend::getCFEC() { if (info.type == FE_QPSK) { @@ -320,22 +361,6 @@ fe_modulation_t CFrontend::getModulation(const uint8_t modulation) } } -uint32_t CFrontend::getFrequency(void) const -{ - switch (info.type) { - case FE_QPSK: - if (currentToneMode == SEC_TONE_OFF) - return curfe.frequency; - else - return curfe.frequency; - - case FE_QAM: - case FE_OFDM: - default: - return curfe.frequency; - } -} - uint8_t CFrontend::getPolarization(void) const { return currentTransponder.polarization; @@ -415,7 +440,7 @@ struct dvb_frontend_event CFrontend::getEvent(void) memset(&event, 0, sizeof(struct dvb_frontend_event)); - printf("[fe0] getEvent: max timeout: %d\n", TIMEOUT_MAX_MS); + printf("[fe%d] getEvent: max timeout: %d\n", fenumber, TIMEOUT_MAX_MS); FE_TIMER_START(); //while (msec <= TIMEOUT_MAX_MS ) { @@ -427,12 +452,12 @@ struct dvb_frontend_event CFrontend::getEvent(void) continue; } if (ret == 0) { - FE_TIMER_STOP("[fe0] ############################## poll timeout, time"); + FE_TIMER_STOP("############################## poll timeout, time"); continue; } if (pfd.revents & (POLLIN | POLLPRI)) { - FE_TIMER_STOP("[fe0] poll has event after"); + FE_TIMER_STOP("poll has event after"); memset(&event, 0, sizeof(struct dvb_frontend_event)); //fop(ioctl, FE_READ_STATUS, &event.status); @@ -441,7 +466,7 @@ struct dvb_frontend_event CFrontend::getEvent(void) perror("CFrontend::getEvent ioctl"); continue; } - //printf("[fe0] poll events %d status %x\n", pfd.revents, event.status); + //printf("[fe%d] poll events %d status %x\n", fenumber, pfd.revents, event.status); if (event.status & FE_HAS_LOCK) { printf("[fe%d] ****************************** FE_HAS_LOCK: freq %lu\n", fenumber, (long unsigned int)event.parameters.frequency); @@ -466,7 +491,7 @@ struct dvb_frontend_event CFrontend::getEvent(void) /* msec = TIME_STEP; */ } } else if (pfd.revents & POLLHUP) { - FE_TIMER_STOP("[fe0] poll hup after"); + FE_TIMER_STOP("poll hup after"); reset(); } } @@ -560,7 +585,7 @@ void CFrontend::getDelSys(int f, int m, char *&fec, char *&sys, char *&mod) fec = (char *)"9/10"; break; default: - printf("[fe0] getDelSys: unknown FEC: %d !!!\n", f); + printf("[frontend] getDelSys: unknown FEC: %d !!!\n", f); case FEC_AUTO: fec = (char *)"AUTO"; break; @@ -652,7 +677,7 @@ bool CFrontend::buildProperties(const struct dvb_frontend_parameters *feparams, fec = FEC_9_10; break; default: - printf("[fe0] DEMOD: unknown FEC: %d\n", fec_inner); + printf("[fe%d] DEMOD: unknown FEC: %d\n", fenumber, fec_inner); case FEC_AUTO: case FEC_S2_AUTO: fec = FEC_AUTO; @@ -693,7 +718,7 @@ bool CFrontend::buildProperties(const struct dvb_frontend_parameters *feparams, } - if (uni_scr >= 0) + if (config.uni_scr >= 0) cmdseq.props[FREQUENCY].u.data = sendEN50494TuningCommand(feparams->frequency, currentToneMode == SEC_TONE_ON, currentVoltage == SEC_VOLTAGE_18, @@ -714,18 +739,18 @@ int CFrontend::setFrontend(const struct dvb_frontend_parameters *feparams, bool tuned = false; - //printf("[fe0] DEMOD: FEC %s system %s modulation %s pilot %s\n", f, s, m, pilot == PILOT_ON ? "on" : "off"); + //printf("[fe%d] DEMOD: FEC %s system %s modulation %s pilot %s\n", fenumber, f, s, m, pilot == PILOT_ON ? "on" : "off"); struct dvb_frontend_event ev; { // Erase previous events while (1) { if (ioctl(fd, FE_GET_EVENT, &ev) < 0) break; - printf("[fe0] DEMOD: event status %d\n", ev.status); + //printf("[fe%d] DEMOD: event status %d\n", fenumber, ev.status); } } - //printf("[fe0] DEMOD: FEC %s system %s modulation %s pilot %s, freq %d\n", f, s, m, pilot == PILOT_ON ? "on" : "off", p->props[FREQUENCY].u.data); + //printf("[fe%d] DEMOD: FEC %s system %s modulation %s pilot %s, freq %d\n", fenumber, f, s, m, pilot == PILOT_ON ? "on" : "off", p->props[FREQUENCY].u.data); if (!buildProperties(feparams, cmdseq)) return 0; @@ -736,7 +761,7 @@ int CFrontend::setFrontend(const struct dvb_frontend_parameters *feparams, bool perror("FE_SET_PROPERTY failed"); return false; } - FE_TIMER_STOP("[fe0] FE_SET_PROPERTY took"); + FE_TIMER_STOP("FE_SET_PROPERTY took"); } { FE_TIMER_INIT(); @@ -745,7 +770,7 @@ int CFrontend::setFrontend(const struct dvb_frontend_parameters *feparams, bool struct dvb_frontend_event event; event = getEvent(); - FE_TIMER_STOP("[fe0] tuning took"); + FE_TIMER_STOP("tuning took"); } return tuned; @@ -753,13 +778,13 @@ int CFrontend::setFrontend(const struct dvb_frontend_parameters *feparams, bool void CFrontend::secSetTone(const fe_sec_tone_mode_t toneMode, const uint32_t ms) { - if (info.type != FE_QPSK) + if (slave || info.type != FE_QPSK) return; if (currentToneMode == toneMode) return; - if (uni_scr >= 0) { + if (config.uni_scr >= 0) { /* this is too ugly for words. the "currentToneMode" is the only place where the global "highband" state is saved. So we need to fake it for unicable and still set the tone on... */ @@ -774,24 +799,27 @@ void CFrontend::secSetTone(const fe_sec_tone_mode_t toneMode, const uint32_t ms) FE_TIMER_START(); if (fop(ioctl, FE_SET_TONE, toneMode) == 0) { currentToneMode = toneMode; - FE_TIMER_STOP("[fe0] FE_SET_TONE took"); + FE_TIMER_STOP("FE_SET_TONE took"); usleep(1000 * ms); } } void CFrontend::secSetVoltage(const fe_sec_voltage_t voltage, const uint32_t ms) { + if (slave || info.type != FE_QPSK) + return; + if (currentVoltage == voltage) return; printf("[fe%d] voltage %s\n", fenumber, voltage == SEC_VOLTAGE_OFF ? "OFF" : voltage == SEC_VOLTAGE_13 ? "13" : "18"); - //printf("[fe%d] voltage %s high %d\n", fenumber, voltage == SEC_VOLTAGE_OFF ? "OFF" : voltage == SEC_VOLTAGE_13 ? "13" : "18", highVoltage); - //int val = highVoltage; + //printf("[fe%d] voltage %s high %d\n", fenumber, voltage == SEC_VOLTAGE_OFF ? "OFF" : voltage == SEC_VOLTAGE_13 ? "13" : "18", config.highVoltage); + //int val = config.highVoltage; //fop(ioctl, FE_ENABLE_HIGH_LNB_VOLTAGE, val); //FE_TIMER_INIT(); //FE_TIMER_START(); - if (uni_scr >= 0) { + if (config.uni_scr >= 0) { /* see my comment in secSetTone... */ currentVoltage = voltage; /* need to know polarization for unicable */ fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_13); /* voltage must not be 18V */ @@ -800,7 +828,7 @@ void CFrontend::secSetVoltage(const fe_sec_voltage_t voltage, const uint32_t ms) if (fop(ioctl, FE_SET_VOLTAGE, voltage) == 0) { currentVoltage = voltage; - //FE_TIMER_STOP("[fe0] FE_SET_VOLTAGE took"); + //FE_TIMER_STOP("[frontend] FE_SET_VOLTAGE took"); usleep(1000 * ms); // FIXME : is needed ? } } @@ -811,10 +839,12 @@ void CFrontend::secResetOverload(void) void CFrontend::sendDiseqcCommand(const struct dvb_diseqc_master_cmd *cmd, const uint32_t ms) { - printf("[fe0] Diseqc cmd: "); + printf("[fe%d] Diseqc cmd: ", fenumber); for (int i = 0; i < cmd->msg_len; i++) printf("0x%X ", cmd->msg[i]); printf("\n"); + if(slave) + return; if (fop(ioctl, FE_DISEQC_SEND_MASTER_CMD, cmd) == 0) usleep(1000 * ms); } @@ -834,25 +864,25 @@ void CFrontend::setDiseqcType(const diseqc_t newDiseqcType) { switch (newDiseqcType) { case NO_DISEQC: - INFO("NO_DISEQC"); + INFO("fe%d: NO_DISEQC", fenumber); break; case MINI_DISEQC: - INFO("MINI_DISEQC"); + INFO("fe%d: MINI_DISEQC", fenumber); break; case SMATV_REMOTE_TUNING: - INFO("SMATV_REMOTE_TUNING"); + INFO("fe%d: SMATV_REMOTE_TUNING", fenumber); break; case DISEQC_1_0: - INFO("DISEQC_1_0"); + INFO("fe%d: DISEQC_1_0", fenumber); break; case DISEQC_1_1: - INFO("DISEQC_1_1"); + INFO("fe%d: DISEQC_1_1", fenumber); break; case DISEQC_1_2: - INFO("DISEQC_1_2"); + INFO("fe%d: DISEQC_1_2", fenumber); break; case DISEQC_ADVANCED: - INFO("DISEQC_ADVANCED"); + INFO("fe%d: DISEQC_ADVANCED", fenumber); break; #if 0 case DISEQC_2_0: @@ -871,20 +901,20 @@ void CFrontend::setDiseqcType(const diseqc_t newDiseqcType) } #if 0 - if (!slave && (diseqcType <= MINI_DISEQC) + if (!slave && (config.diseqcType <= MINI_DISEQC) && (newDiseqcType > MINI_DISEQC)) { sendDiseqcPowerOn(); sendDiseqcReset(); } #else - if (diseqcType != newDiseqcType) { + if (config.diseqcType != newDiseqcType) { sendDiseqcPowerOn(); sendDiseqcReset(); } #endif - diseqcType = newDiseqcType; + config.diseqcType = newDiseqcType; } void CFrontend::setLnbOffsets(int32_t _lnbOffsetLow, int32_t _lnbOffsetHigh, int32_t _lnbSwitch) @@ -892,7 +922,7 @@ void CFrontend::setLnbOffsets(int32_t _lnbOffsetLow, int32_t _lnbOffsetHigh, int lnbOffsetLow = _lnbOffsetLow * 1000; lnbOffsetHigh = _lnbOffsetHigh * 1000; lnbSwitch = _lnbSwitch * 1000; - printf("[fe0] setLnbOffsets %d/%d/%d\n", lnbOffsetLow, lnbOffsetHigh, lnbSwitch); + printf("[fe%d] setLnbOffsets %d/%d/%d\n", fenumber, lnbOffsetLow, lnbOffsetHigh, lnbSwitch); } void CFrontend::sendMotorCommand(uint8_t cmdtype, uint8_t address, uint8_t command, uint8_t num_parameters, uint8_t parameter1, uint8_t parameter2, int repeat) @@ -912,7 +942,7 @@ void CFrontend::sendMotorCommand(uint8_t cmdtype, uint8_t address, uint8_t comma cmd.msg[4] = parameter2; cmd.msg_len = 3 + num_parameters; - //secSetVoltage(highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); + //secSetVoltage(config.highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); secSetVoltage(SEC_VOLTAGE_13, 15); secSetTone(SEC_TONE_OFF, 15); @@ -932,7 +962,7 @@ void CFrontend::positionMotor(uint8_t motorPosition) }; if (motorPosition != 0) { - secSetVoltage(highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); + secSetVoltage(config.highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); secSetTone(SEC_TONE_OFF, 25); cmd.msg[3] = motorPosition; @@ -972,14 +1002,14 @@ bool CFrontend::setInput(CZapitChannel * channel, bool nvod) void CFrontend::setInput(t_satellite_position satellitePosition, uint32_t frequency, uint8_t polarization) { - sat_iterator_t sit = satellitePositions.find(satellitePosition); + sat_iterator_t sit = satellites.find(satellitePosition); #if 0 - printf("[fe0] setInput: SatellitePosition %d -> %d\n", currentSatellitePosition, satellitePosition); + printf("[fe%d] setInput: SatellitePosition %d -> %d\n", fenumber, currentSatellitePosition, satellitePosition); if (currentSatellitePosition != satellitePosition) #endif setLnbOffsets(sit->second.lnbOffsetLow, sit->second.lnbOffsetHigh, sit->second.lnbSwitch); - if (diseqcType != DISEQC_ADVANCED) { + if (config.diseqcType != DISEQC_ADVANCED) { setDiseqc(sit->second.diseqc, polarization, frequency); return; } @@ -1002,20 +1032,20 @@ uint32_t CFrontend::sendEN50494TuningCommand(const uint32_t frequency, const int { uint32_t uni_qrgs[] = { 1284, 1400, 1516, 1632, 1748, 1864, 1980, 2096 }; uint32_t bpf; - if (uni_qrg == 0) - bpf = uni_qrgs[uni_scr]; + if (config.uni_qrg == 0) + bpf = uni_qrgs[config.uni_scr]; else - bpf = uni_qrg; + bpf = config.uni_qrg; struct dvb_diseqc_master_cmd cmd = { {0xe0, 0x10, 0x5a, 0x00, 0x00, 0x00}, 5 }; unsigned int t = (frequency / 1000 + bpf + 2) / 4 - 350; - if (t < 1024 && uni_scr >= 0 && uni_scr < 8) + if (t < 1024 && config.uni_scr >= 0 && config.uni_scr < 8) { fprintf(stderr, "VOLT18=%d TONE_ON=%d, freq=%d bpf=%d ret=%d\n", currentVoltage == SEC_VOLTAGE_18, currentToneMode == SEC_TONE_ON, frequency, bpf, (t + 350) * 4000 - frequency); cmd.msg[3] = (t >> 8) | /* highest 3 bits of t */ - (uni_scr << 5) | /* adress */ + (config.uni_scr << 5) | /* adress */ (bank << 4) | /* not implemented yet */ (horizontal << 3) | /* horizontal == 0x08 */ (high_band) << 2; /* high_band == 0x04 */ @@ -1026,7 +1056,7 @@ uint32_t CFrontend::sendEN50494TuningCommand(const uint32_t frequency, const int fop(ioctl, FE_SET_VOLTAGE, SEC_VOLTAGE_13); return (t + 350) * 4000 - frequency; } - WARN("ooops. t > 1024? (%d) or uni_scr out of range? (%d)", t, uni_scr); + WARN("ooops. t > 1024? (%d) or uni_scr out of range? (%d)", t, config.uni_scr); return 0; } @@ -1104,7 +1134,7 @@ int CFrontend::setParameters(TP_params *TP, bool /*nowait*/) #endif } - printf("[fe0] tuner to frequency %d (offset %d)\n", feparams->frequency, freq_offset); + printf("[fe%d] tuner to frequency %d (offset %d)\n", fenumber, feparams->frequency, freq_offset); setFrontend(feparams); #if 0 @@ -1134,7 +1164,7 @@ bool CFrontend::sendUncommittedSwitchesCommand(int input) {0xe0, 0x10, 0x39, 0x00, 0x00, 0x00}, 4 }; - printf("[fe0] uncommitted %d -> %d\n", uncommitedInput, input); + printf("[fe%d] uncommitted %d -> %d\n", fenumber, uncommitedInput, input); if ((input < 0) || (uncommitedInput == input)) return false; @@ -1158,8 +1188,10 @@ bool CFrontend::setDiseqcSimple(int sat_no, const uint8_t pol, const uint32_t fr {0xe0, 0x10, 0x38, 0x00, 0x00, 0x00}, 4 }; - printf("[fe0] diseqc input %d -> %d\n", diseqc, sat_no); + INFO("[fe%d] diseqc input %d -> %d", fenumber, diseqc, sat_no); currentTransponder.diseqc = sat_no; + if (slave) + return true; if ((sat_no >= 0) && (diseqc != sat_no)) { diseqc = sat_no; printf("[fe%d] diseqc no. %d\n", fenumber, sat_no); @@ -1176,10 +1208,10 @@ bool CFrontend::setDiseqcSimple(int sat_no, const uint8_t pol, const uint32_t fr } return false; #if 0 //do we need this in advanced setup ? - if (diseqcType == SMATV_REMOTE_TUNING) + if (config.diseqcType == SMATV_REMOTE_TUNING) sendDiseqcSmatvRemoteTuningCommand(frequency); - if (diseqcType == MINI_DISEQC) + if (config.diseqcType == MINI_DISEQC) sendToneBurst(b, 15); currentTransponder.diseqc = sat_no; #endif @@ -1195,6 +1227,7 @@ void CFrontend::setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequenc fe_sec_mini_cmd_t b = (sat_no & 1) ? SEC_MINI_B : SEC_MINI_A; int delay = 0; + INFO("[fe%d] diseqc input %d -> %d", fenumber, diseqc, sat_no); if (slave) return; @@ -1204,14 +1237,14 @@ void CFrontend::setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequenc //secSetVoltage(SEC_VOLTAGE_13, 15);//FIXME for test secSetTone(SEC_TONE_OFF, 20); - for (loop = 0; loop <= diseqcRepeats; loop++) { + for (loop = 0; loop <= config.diseqcRepeats; loop++) { //usleep(50*1000); /* sleep at least 50 milli seconds */ - if (diseqcType == MINI_DISEQC) + if (config.diseqcType == MINI_DISEQC) sendToneBurst(b, 1); delay = 0; - if (diseqcType == DISEQC_1_1) { /* setup the uncommited switch first */ + if (config.diseqcType == DISEQC_1_1) { /* setup the uncommited switch first */ delay = 60; // delay for 1.0 after 1.1 command cmd.msg[2] = 0x39; /* port group = uncommited switches */ @@ -1230,7 +1263,7 @@ void CFrontend::setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequenc sendDiseqcCommand(&cmd, 100); /* send the command to setup second uncommited switch and wait 100 ms !!! */ #endif } - if (diseqcType >= DISEQC_1_0) { /* DISEQC 1.0 */ + if (config.diseqcType >= DISEQC_1_0) { /* DISEQC 1.0 */ usleep(delay * 1000); //cmd.msg[0] |= 0x01; /* repeated transmission */ @@ -1244,7 +1277,7 @@ void CFrontend::setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequenc usleep(25 * 1000); - if (diseqcType == SMATV_REMOTE_TUNING) + if (config.diseqcType == SMATV_REMOTE_TUNING) sendDiseqcSmatvRemoteTuningCommand(frequency); #if 0 // setSec do this, when tune called @@ -1330,24 +1363,24 @@ int CFrontend::driveToSatellitePosition(t_satellite_position satellitePosition, int new_position = 0, old_position = 0; bool use_usals = 0; - //if(diseqcType == DISEQC_ADVANCED) //FIXME testing + //if(config.diseqcType == DISEQC_ADVANCED) //FIXME testing { - printf("[fe0] SatellitePosition %d -> %d\n", currentSatellitePosition, satellitePosition); + printf("[fe%d] SatellitePosition %d -> %d\n", fenumber, currentSatellitePosition, satellitePosition); bool moved = false; - sat_iterator_t sit = satellitePositions.find(satellitePosition); - if (sit == satellitePositions.end()) { - printf("[fe0] satellite position %d not found!\n", satellitePosition); + sat_iterator_t sit = satellites.find(satellitePosition); + if (sit == satellites.end()) { + printf("[fe%d] satellite position %d not found!\n", fenumber, satellitePosition); return 0; } else { new_position = sit->second.motor_position; use_usals = sit->second.use_usals; } - sit = satellitePositions.find(currentSatellitePosition); - if (sit != satellitePositions.end()) + sit = satellites.find(currentSatellitePosition); + if (sit != satellites.end()) old_position = sit->second.motor_position; - printf("[fe0] motorPosition %d -> %d usals %s\n", old_position, new_position, use_usals ? "on" : "off"); + printf("[fe%d] motorPosition %d -> %d usals %s\n", fenumber, old_position, new_position, use_usals ? "on" : "off"); if (currentSatellitePosition == satellitePosition) return 0; @@ -1363,15 +1396,16 @@ int CFrontend::driveToSatellitePosition(t_satellite_position satellitePosition, } if (from_scan || (new_position > 0 && old_position > 0)) { - waitForMotor = motorRotationSpeed ? 2 + abs(satellitePosition - currentSatellitePosition) / motorRotationSpeed : 0; + waitForMotor = config.motorRotationSpeed ? 2 + abs(satellitePosition - currentSatellitePosition) / config.motorRotationSpeed : 0; } if (moved) { //currentSatellitePosition = satellitePosition; - waitForMotor = motorRotationSpeed ? 2 + abs(satellitePosition - currentSatellitePosition) / motorRotationSpeed : 0; + waitForMotor = config.motorRotationSpeed ? 2 + abs(satellitePosition - currentSatellitePosition) / config.motorRotationSpeed : 0; currentSatellitePosition = satellitePosition; } } - //currentSatellitePosition = satellitePosition; + //FIXME we never remember currentSatellitePosition for non-rotor ? + currentSatellitePosition = satellitePosition; return waitForMotor; } @@ -1626,5 +1660,5 @@ void CFrontend::gotoXX(t_satellite_position pos) printf("RotorCmd = %04x\n", RotorCmd); sendMotorCommand(0xE0, 0x31, 0x6E, 2, ((RotorCmd & 0xFF00) / 0x100), RotorCmd & 0xFF, repeatUsals); - secSetVoltage(highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); //FIXME ? + secSetVoltage(config.highVoltage ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, 15); //FIXME ? } From cac099966bdb94313b35bb7fef1a7875a372c8d5 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:19:56 +0400 Subject: [PATCH 004/737] channel class: Add record demux, polarization, ca sysmap --- src/zapit/include/zapit/channel.h | 11 +++++++++++ src/zapit/src/channel.cpp | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/zapit/include/zapit/channel.h b/src/zapit/include/zapit/channel.h index 67fab006c..608424e88 100644 --- a/src/zapit/include/zapit/channel.h +++ b/src/zapit/include/zapit/channel.h @@ -29,6 +29,7 @@ #include #include #include +#include /* zapit */ #include "ci.h" @@ -108,6 +109,9 @@ class CZapitAudioChannel class CChannelList; +typedef std::set casys_map_t; +typedef casys_map_t::iterator casys_map_iterator_t; + class CZapitChannel { private: @@ -155,9 +159,13 @@ class CZapitChannel std::string ttx_language_code; + uint8_t record_demux; + friend class CChannelList; public: + casys_map_t camap; + bool bAlwaysLocked; int number; @@ -167,6 +175,7 @@ class CZapitChannel unsigned char scrambled; char * pname; bool has_bouquet; + uint8_t polarization; /* constructor, desctructor */ CZapitChannel(const std::string & p_name, t_service_id p_sid, t_transport_stream_id p_tsid, t_original_network_id p_onid, unsigned char p_service_type, t_satellite_position p_satellite_position, freq_id_t freq); @@ -232,6 +241,8 @@ class CZapitChannel void dumpServiceXml(FILE * fd, const char * action = NULL); void dumpBouquetXml(FILE * fd); + void setRecordDemux(int num) { record_demux = num; }; + int getRecordDemux() { return record_demux; }; }; #endif /* __zapit_channel_h__ */ diff --git a/src/zapit/src/channel.cpp b/src/zapit/src/channel.cpp index db27236ba..5cf65aa35 100644 --- a/src/zapit/src/channel.cpp +++ b/src/zapit/src/channel.cpp @@ -46,6 +46,8 @@ CZapitChannel::CZapitChannel(const std::string & p_name, t_service_id p_sid, t_t last_unlocked_EPGid = 0; last_unlocked_time = 0; has_bouquet = false; + record_demux = 2; + polarization = 0; //printf("NEW CHANNEL %s %x\n", name.c_str(), (int) this); } @@ -55,6 +57,7 @@ CZapitChannel::~CZapitChannel(void) resetPids(); setCaPmt(NULL); setRawPmt(NULL); + camap.clear(); //if(currentEvent) // delete currentEvent; From 4623328db2d1eac1bd6f5fc14e850b5dd36fa50e Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:23:18 +0400 Subject: [PATCH 005/737] Move global satellitePositions to CServiceManager class; add frontendType member to CServiceManager --- src/zapit/include/zapit/getservices.h | 31 +++++++-- src/zapit/include/zapit/satconfig.h | 27 +++++++- src/zapit/src/getservices.cpp | 90 ++++++++++++++------------- 3 files changed, 97 insertions(+), 51 deletions(-) diff --git a/src/zapit/include/zapit/getservices.h b/src/zapit/include/zapit/getservices.h index ed733d4d5..479308fc6 100644 --- a/src/zapit/include/zapit/getservices.h +++ b/src/zapit/include/zapit/getservices.h @@ -26,10 +26,10 @@ #include -#include "ci.h" -#include "descriptors.h" -#include "sdt.h" -#include "types.h" +#include +#include +#include +#include #include #include #include @@ -99,9 +99,12 @@ class CServiceManager tallchans curchans; tallchans nvodchannels; + fe_type_t frontendType; + satellite_map_t satellitePositions; + bool ParseScanXml(); void ParseTransponders(xmlNodePtr node, t_satellite_position satellitePosition, bool cable); - void ParseChannels(xmlNodePtr node, const t_transport_stream_id transport_stream_id, const t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq); + void ParseChannels(xmlNodePtr node, const t_transport_stream_id transport_stream_id, const t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq, uint8_t polarization); void FindTransponder(xmlNodePtr search); void ParseSatTransponders(fe_type_t frontendType, xmlNodePtr search, t_satellite_position satellitePosition); int LoadMotorPositions(void); @@ -120,7 +123,7 @@ class CServiceManager static void CopyFile(char * from, char * to); - void InitSatPosition(t_satellite_position position); + bool InitSatPosition(t_satellite_position position, char * name = NULL, bool force = false); bool LoadServices(bool only_current); void SaveServices(bool tocopy); void SaveMotorPositions(); @@ -148,6 +151,22 @@ class CServiceManager bool GetAllSatelliteChannels(ZapitChannelList &list, t_satellite_position position); bool GetAllUnusedChannels(ZapitChannelList &list); + std::string GetSatelliteName(t_satellite_position position) + { + sat_iterator_t it = satellitePositions.find(position); + if(it != satellitePositions.end()) + return it->second.name; + return ""; + } + t_satellite_position GetSatellitePosition(std::string name) + { + for(sat_iterator_t sit = satellitePositions.begin(); sit != satellitePositions.end(); ++sit) { + if(name == sit->second.name) + return sit->second.position; + } + return 0; + } + satellite_map_t & SatelliteList() { return satellitePositions; } xmlDocPtr ScanXml(); }; #endif /* __getservices_h__ */ diff --git a/src/zapit/include/zapit/satconfig.h b/src/zapit/include/zapit/satconfig.h index ac26dbaea..b5bac4989 100644 --- a/src/zapit/include/zapit/satconfig.h +++ b/src/zapit/include/zapit/satconfig.h @@ -1,7 +1,28 @@ +/* + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + #ifndef _SAT_CONFIG_H_ #define _SAT_CONFIG_H_ typedef struct sat_config { + t_satellite_position position; int diseqc; int commited; int uncommited; @@ -14,8 +35,8 @@ typedef struct sat_config { int use_usals; std::string name; int have_channels; - t_satellite_position position; int input; + int configured; } sat_config_t; typedef enum diseqc_cmd_order { @@ -23,12 +44,14 @@ typedef enum diseqc_cmd_order { COMMITED_FIRST } diseqc_cmd_order_t; +typedef std::pair satellite_pair_t; typedef std::map satellite_map_t; typedef std::map::iterator sat_iterator_t; typedef std::map scan_list_t; typedef std::map ::iterator scan_list_iterator_t; -extern satellite_map_t satellitePositions; +//extern satellite_map_t satellitePositions; extern scan_list_t scanProviders; + #endif diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index ca23ed59a..3dcb612f3 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ extern transponder_list_t transponders; -satellite_map_t satellitePositions; +//satellite_map_t satellitePositions; std::map select_transponders; extern int zapit_debug; @@ -64,7 +64,8 @@ bool CServiceManager::ParseScanXml(void) delete scanInputParser; scanInputParser = NULL; } - switch (CFrontend::getInstance()->getInfo()->type) { + frontendType = CFEManager::getInstance()->getLiveFE()->getInfo()->type; + switch (frontendType) { case FE_QPSK: scanInputParser = parseXmlFile(SATELLITES_XML); break; @@ -74,7 +75,7 @@ bool CServiceManager::ParseScanXml(void) break; default: - WARN("Unknown type %d", CFrontend::getInstance()->getInfo()->type); + WARN("Unknown type %d", frontendType); return false; } return (scanInputParser != NULL); @@ -307,7 +308,7 @@ void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position sa printf("[zapit] duplicate transponder id %llx freq %d\n", tid, feparams.frequency); /* read channels that belong to the current transponder */ - ParseChannels(node->xmlChildrenNode, transport_stream_id, original_network_id, satellitePosition, freq); + ParseChannels(node->xmlChildrenNode, transport_stream_id, original_network_id, satellitePosition, freq, polarization); /* hop to next transponder */ node = node->xmlNextNode; @@ -315,7 +316,7 @@ void CServiceManager::ParseTransponders(xmlNodePtr node, t_satellite_position sa return; } -void CServiceManager::ParseChannels(xmlNodePtr node, const t_transport_stream_id transport_stream_id, const t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq) +void CServiceManager::ParseChannels(xmlNodePtr node, const t_transport_stream_id transport_stream_id, const t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq, uint8_t polarization) { t_service_id service_id; std::string name; @@ -377,6 +378,7 @@ void CServiceManager::ParseChannels(xmlNodePtr node, const t_transport_stream_id } else { service_count++; channel->scrambled = scrambled; + channel->polarization = polarization; service_type = channel->getServiceType(); if(pmtpid != 0 && (((service_type == 2) && (apid > 0)) || ( (service_type == 1) && (vpid > 0) && (apid > 0))) ) { DBG("[getserv] preset chan %s vpid %X sid %X tpid %X onid %X\n", name.c_str(), vpid, service_id, transport_stream_id, transport_stream_id); @@ -415,7 +417,7 @@ void CServiceManager::FindTransponder(xmlNodePtr search) } } -void CServiceManager::ParseSatTransponders(fe_type_t frontendType, xmlNodePtr search, t_satellite_position satellitePosition) +void CServiceManager::ParseSatTransponders(fe_type_t fType, xmlNodePtr search, t_satellite_position satellitePosition) { uint8_t polarization = 0; uint8_t system = 0, modulation = 1; @@ -432,7 +434,7 @@ void CServiceManager::ParseSatTransponders(fe_type_t frontendType, xmlNodePtr se feparams.frequency = xmlGetNumericAttribute(tps, "frequency", 0); freq_id_t freq; - if (frontendType == FE_QAM) { + if (fType == FE_QAM) { if (feparams.frequency > 1000*1000) feparams.frequency=feparams.frequency/1000; //transponderlist was read from tuxbox //feparams.frequency = (int) 1000 * (int) round ((double) feparams.frequency / (double) 1000); @@ -445,12 +447,12 @@ void CServiceManager::ParseSatTransponders(fe_type_t frontendType, xmlNodePtr se feparams.inversion = INVERSION_AUTO; - if (frontendType == FE_QAM) { + if (fType == FE_QAM) { feparams.u.qam.symbol_rate = xmlGetNumericAttribute(tps, "symbol_rate", 0); feparams.u.qam.fec_inner = (fe_code_rate_t) xmlGetNumericAttribute(tps, "fec_inner", 0); feparams.u.qam.modulation = (fe_modulation_t) xmlGetNumericAttribute(tps, "modulation", 0); } - else if (frontendType == FE_QPSK) { + else if (fType == FE_QPSK) { feparams.u.qpsk.symbol_rate = xmlGetNumericAttribute(tps, "symbol_rate", 0); polarization = xmlGetNumericAttribute(tps, "polarization", 0); system = xmlGetNumericAttribute(tps, "system", 0); @@ -496,10 +498,10 @@ int CServiceManager::LoadMotorPositions(void) satellitePosition = spos; sat_iterator_t sit = satellitePositions.find(satellitePosition); if(sit != satellitePositions.end()) { - sit->second.motor_position = mpos; sit->second.diseqc = diseqc; sit->second.commited = com; sit->second.uncommited = uncom; + sit->second.motor_position = mpos; sit->second.lnbOffsetLow = offL; sit->second.lnbOffsetHigh = offH; sit->second.lnbSwitch = sw; @@ -539,20 +541,27 @@ void CServiceManager::SaveMotorPositions() fclose(fd); } -void CServiceManager::InitSatPosition(t_satellite_position position) +bool CServiceManager::InitSatPosition(t_satellite_position position, char * name, bool force) { - satellitePositions[position].position = position; - satellitePositions[position].diseqc = -1; - satellitePositions[position].commited = -1; - satellitePositions[position].uncommited = -1; - satellitePositions[position].motor_position = 0; - satellitePositions[position].diseqc_order = 0; - satellitePositions[position].lnbOffsetLow = 9750; - satellitePositions[position].lnbOffsetHigh = 10600; - satellitePositions[position].lnbSwitch = 11700; - satellitePositions[position].use_in_scan = 0; - satellitePositions[position].use_usals = 0; - satellitePositions[position].input = 0; + if(force || (satellitePositions.find(position) == satellitePositions.end())) { + satellitePositions[position].position = position; + satellitePositions[position].diseqc = -1; + satellitePositions[position].commited = -1; + satellitePositions[position].uncommited = -1; + satellitePositions[position].motor_position = 0; + satellitePositions[position].diseqc_order = 0; + satellitePositions[position].lnbOffsetLow = 9750; + satellitePositions[position].lnbOffsetHigh = 10600; + satellitePositions[position].lnbSwitch = 11700; + satellitePositions[position].use_in_scan = 0; + satellitePositions[position].use_usals = 0; + satellitePositions[position].input = 0; + satellitePositions[position].configured = 0; + if(name) + satellitePositions[position].name = name; + return true; + } + return false; } bool CServiceManager::LoadServices(bool only_current) @@ -561,7 +570,7 @@ bool CServiceManager::LoadServices(bool only_current) static bool satcleared = 0;//clear only once, because menu is static service_count = 0; printf("[zapit] Loading services, channel size %d ..\n", sizeof(CZapitChannel)); - fe_type_t frontendType = CFrontend::getInstance()->getInfo()->type; + frontendType = CFEManager::getInstance()->getLiveFE()->getInfo()->type; if(only_current) goto do_current; @@ -575,8 +584,10 @@ bool CServiceManager::LoadServices(bool only_current) if (ParseScanXml()) { t_satellite_position position = 0; - if(!satcleared) + if(!satcleared) { satellitePositions.clear(); + //satelliteList.clear(); + } satcleared = 1; xmlNodePtr search = xmlDocGetRootElement(scanInputParser)->xmlChildrenNode; @@ -584,17 +595,10 @@ bool CServiceManager::LoadServices(bool only_current) if (!(strcmp(xmlGetName(search), "sat"))) { position = xmlGetSignedNumericAttribute(search, "position", 10); char * name = xmlGetAttribute(search, "name"); - /* FIXME reuse this */ - if(satellitePositions.find(position) == satellitePositions.end()) { - InitSatPosition(position); - } - satellitePositions[position].name = name; + InitSatPosition(position, name); } else if(!(strcmp(xmlGetName(search), "cable"))) { char * name = xmlGetAttribute(search, "name"); - if(satellitePositions.find(position) == satellitePositions.end()) { - InitSatPosition(position); - } - satellitePositions[position].name = name; + InitSatPosition(position, name); } ParseSatTransponders(frontendType, search, position); position++; @@ -609,10 +613,7 @@ bool CServiceManager::LoadServices(bool only_current) if (!(strcmp(xmlGetName(search), "sat"))) { t_satellite_position position = xmlGetSignedNumericAttribute(search, "position", 10); char * name = xmlGetAttribute(search, "name"); - if(satellitePositions.find(position) == satellitePositions.end()) { - InitSatPosition(position); - satellitePositions[position].name = name; - } + InitSatPosition(position, name); } search = search->xmlNextNode; @@ -625,6 +626,9 @@ bool CServiceManager::LoadServices(bool only_current) LoadMotorPositions(); } + //FIXME copy, until global satellitePositions removed + //satelliteList = satellitePositions; + printf("[zapit] %d services loaded (%d)...\n", service_count, allchans.size()); TIMER_STOP("[zapit] service loading took"); @@ -668,7 +672,7 @@ void CServiceManager::CopyFile(char * from, char * to) void CServiceManager::WriteSatHeader(FILE * fd, sat_config_t &config) { - switch (CFrontend::getInstance()->getInfo()->type) { + switch (frontendType) { case FE_QPSK: /* satellite */ fprintf(fd, "\t\n", config.name.c_str(), config.position, config.diseqc, config.uncommited); @@ -684,7 +688,7 @@ void CServiceManager::WriteSatHeader(FILE * fd, sat_config_t &config) void CServiceManager::WriteTransponderHeader(FILE * fd, struct transponder &tp) { - switch (CFrontend::getInstance()->getInfo()->type) { + switch (frontendType) { case FE_QPSK: /* satellite */ fprintf(fd, "\t\t\n", tp.transport_stream_id, tp.original_network_id, @@ -771,7 +775,7 @@ void CServiceManager::SaveServices(bool tocopy) if(tpdone) fprintf(fd, "\t\t\n"); } if(satdone) { - switch (CFrontend::getInstance()->getInfo()->type) { + switch (frontendType) { case FE_QPSK: fprintf(fd, "\t\n"); break; @@ -852,7 +856,7 @@ bool CServiceManager::SaveCurrentServices(transponder_id_t tpid) return false; } - switch (CFrontend::getInstance()->getInfo()->type) { + switch (frontendType) { case FE_QPSK: /* satellite */ sprintf(satstr, "\t<%s name=\"%s\" position=\"%hd\">\n", "sat", spos_it->second.name.c_str(), satellitePosition); break; From 060a58d59c698e2dd1a931e5649fef7b54c6d014 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:36:37 +0400 Subject: [PATCH 006/737] Get satellite name from CServiceManager --- src/gui/bedit/bouqueteditor_channels.cpp | 20 ++++++++----- src/gui/bedit/bouqueteditor_chanselect.cpp | 34 +++++++++++++--------- src/gui/epgplus.cpp | 8 ++--- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/gui/bedit/bouqueteditor_channels.cpp b/src/gui/bedit/bouqueteditor_channels.cpp index 9c9452fdf..6a156b4eb 100644 --- a/src/gui/bedit/bouqueteditor_channels.cpp +++ b/src/gui/bedit/bouqueteditor_channels.cpp @@ -49,7 +49,7 @@ #include #include -#include +#include #include extern CBouquetManager *g_bouquetManager; @@ -177,20 +177,22 @@ void CBEChannelWidget::paintDetails(int index) transponder_id_t ct = (*Channels)[index]->getTransponderId(); transponder_list_t::iterator tpI = transponders.find(ct); - sat_iterator_t sit = satellitePositions.find((*Channels)[index]->getSatellitePosition()); + //sat_iterator_t sit = satellitePositions.find((*Channels)[index]->getSatellitePosition()); + std::string satname = CServiceManager::getInstance()->GetSatelliteName((*Channels)[index]->getSatellitePosition()).c_str(); len = snprintf(buf, sizeof(buf), "%d ", (*Channels)[index]->getFreqId()); if(tpI != transponders.end()) { char * f, *s, *m; - switch(CFrontend::getInstance()->getInfo()->type) + CFrontend * frontend = CFEManager::getInstance()->getLiveFE(); + switch(frontend->getInfo()->type) { case FE_QPSK: - CFrontend::getInstance()->getDelSys(tpI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tpI->second.feparams.u.qpsk.fec_inner), f, s, m); + frontend->getDelSys(tpI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tpI->second.feparams.u.qpsk.fec_inner), f, s, m); len += snprintf(&buf[len], sizeof(buf) - len, "%c %d %s %s %s ", tpI->second.polarization ? 'V' : 'H', tpI->second.feparams.u.qpsk.symbol_rate/1000, f, s, m); break; case FE_QAM: - CFrontend::getInstance()->getDelSys(tpI->second.feparams.u.qam.fec_inner, tpI->second.feparams.u.qam.modulation, f, s, m); + frontend->getDelSys(tpI->second.feparams.u.qam.fec_inner, tpI->second.feparams.u.qam.modulation, f, s, m); len += snprintf(&buf[len], sizeof(buf) - len, "%d %s %s %s ", tpI->second.feparams.u.qam.symbol_rate/1000, f, s, m); break; case FE_OFDM: @@ -203,13 +205,17 @@ void CBEChannelWidget::paintDetails(int index) snprintf(&buf[len], sizeof(buf) - len, "(%s)", (*Channels)[index]->pname); } else { + snprintf(&buf[len], sizeof(buf) - len, "(%s)", satname.c_str()); +#if 0 if(sit != satellitePositions.end()) { snprintf(&buf[len], sizeof(buf) - len, "(%s)", sit->second.name.c_str()); } +#endif } - if(sit != satellitePositions.end()) { - g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ fheight, width - 30, sit->second.name.c_str(), COL_MENUCONTENTDARK, 0, true); + //if(sit != satellitePositions.end()) + { + g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ fheight, width - 30, satname.c_str(), COL_MENUCONTENTDARK, 0, true); } g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ 2*fheight, width - 30, buf, COL_MENUCONTENTDARK, 0, true); } diff --git a/src/gui/bedit/bouqueteditor_chanselect.cpp b/src/gui/bedit/bouqueteditor_chanselect.cpp index 7f0bad20f..e151f678c 100644 --- a/src/gui/bedit/bouqueteditor_chanselect.cpp +++ b/src/gui/bedit/bouqueteditor_chanselect.cpp @@ -203,25 +203,27 @@ void CBEChannelSelectWidget::paintDetails(int index) int len = 0; transponder_id_t ct = Channels[index]->getTransponderId(); transponder_list_t::iterator tpI = transponders.find(ct); - sat_iterator_t sit = satellitePositions.find(Channels[index]->getSatellitePosition()); + //sat_iterator_t sit = satellitePositions.find(Channels[index]->getSatellitePosition()); + std::string satname = CServiceManager::getInstance()->GetSatelliteName(Channels[index]->getSatellitePosition()); len = snprintf(buf, sizeof(buf), "%d ", Channels[index]->getFreqId()); if(tpI != transponders.end()) { char * f, *s, *m; - switch(CFrontend::getInstance()->getInfo()->type) + CFrontend * frontend = CFEManager::getInstance()->getLiveFE(); + switch(frontend->getInfo()->type) { case FE_QPSK: - CFrontend::getInstance()->getDelSys(tpI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tpI->second.feparams.u.qpsk.fec_inner), f, s, m); - len += snprintf(&buf[len], sizeof(buf) - len, "%c %d %s %s %s ", tpI->second.polarization ? 'V' : 'H', tpI->second.feparams.u.qpsk.symbol_rate/1000, f, s, m); - break; - case FE_QAM: - CFrontend::getInstance()->getDelSys(tpI->second.feparams.u.qam.fec_inner, tpI->second.feparams.u.qam.modulation, f, s, m); - len += snprintf(&buf[len], sizeof(buf) - len, "%d %s %s %s ", tpI->second.feparams.u.qam.symbol_rate/1000, f, s, m); - break; - case FE_OFDM: - case FE_ATSC: - break; + frontend->getDelSys(tpI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tpI->second.feparams.u.qpsk.fec_inner), f, s, m); + len += snprintf(&buf[len], sizeof(buf) - len, "%c %d %s %s %s ", tpI->second.polarization ? 'V' : 'H', tpI->second.feparams.u.qpsk.symbol_rate/1000, f, s, m); + break; + case FE_QAM: + frontend->getDelSys(tpI->second.feparams.u.qam.fec_inner, tpI->second.feparams.u.qam.modulation, f, s, m); + len += snprintf(&buf[len], sizeof(buf) - len, "%d %s %s %s ", tpI->second.feparams.u.qam.symbol_rate/1000, f, s, m); + break; + case FE_OFDM: + case FE_ATSC: + break; } } @@ -229,13 +231,17 @@ void CBEChannelSelectWidget::paintDetails(int index) snprintf(&buf[len], sizeof(buf) - len, "(%s)", Channels[index]->pname); } else { + snprintf(&buf[len], sizeof(buf) - len, "(%s)", satname.c_str()); +#if 0 if(sit != satellitePositions.end()) { snprintf(&buf[len], sizeof(buf) - len, "(%s)", sit->second.name.c_str()); } +#endif } - if(sit != satellitePositions.end()) { - g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ fheight, width - 30, sit->second.name.c_str(), COL_MENUCONTENTDARK, 0, true); + //if(sit != satellitePositions.end()) + { + g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ fheight, width - 30, satname.c_str(), COL_MENUCONTENTDARK, 0, true); } g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ 2*fheight, width - 30, buf, COL_MENUCONTENTDARK, 0, true); } diff --git a/src/gui/epgplus.cpp b/src/gui/epgplus.cpp index f9cc57ec3..8b15b9173 100644 --- a/src/gui/epgplus.cpp +++ b/src/gui/epgplus.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -396,10 +397,9 @@ void EpgPlus::ChannelEntry::paint (bool isSelected, time_t selectedTime) if(this->channel->pname) { this->footer->setBouquetChannelName(this->channel->pname, this->channel->getName()); } else { - sat_iterator_t sit = satellitePositions.find(this->channel->getSatellitePosition()); - if(sit != satellitePositions.end()) { - this->footer->setBouquetChannelName(sit->second.name, this->channel->getName()); - } + this->footer->setBouquetChannelName( + CServiceManager::getInstance()->GetSatelliteName(this->channel->getSatellitePosition()), + this->channel->getName()); } } // paint the separation line From 546952f3a1944b410d39a39b5a866f601e2c9dc0 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:38:04 +0400 Subject: [PATCH 007/737] CI menu: add support to change CI clock --- src/gui/cam_menu.cpp | 43 ++++++++++++++++++++++++------------------- src/gui/cam_menu.h | 10 +++++----- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/gui/cam_menu.cpp b/src/gui/cam_menu.cpp index 3148499fb..782f12832 100644 --- a/src/gui/cam_menu.cpp +++ b/src/gui/cam_menu.cpp @@ -1,23 +1,13 @@ /* Neutrino-GUI - DBoxII-Project - Copyright (C) 2001 Steffen Hehn 'McClean' - Homepage: http://dbox.cyberphoria.org/ + Copyright (C) 2011 CoolStream International Ltd - Kommentar: - - Diese GUI wurde von Grund auf neu programmiert und sollte nun vom - Aufbau und auch den Ausbaumoeglichkeiten gut aussehen. Neutrino basiert - auf der Client-Server Idee, diese GUI ist also von der direkten DBox- - Steuerung getrennt. Diese wird dann von Daemons uebernommen. - - - License: GPL + License: GPLv2 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -110,15 +100,20 @@ int CCAMMenuHandler::doMainMenu() char name1[255]={0}; char str1[255]={0}; - CMenuWidget* cammenu = new CMenuWidget(LOCALE_CI_SETTINGS, NEUTRINO_ICON_SETTINGS); - cammenu->addItem( GenericMenuBack ); - cammenu->addItem( GenericMenuSeparatorLine ); + int CiSlots = ca->GetNumberCISlots(); - cammenu->addItem( new CMenuOptionChooser(LOCALE_CI_RESET_STANDBY, &g_settings.ci_standby_reset, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); - cammenu->addItem( GenericMenuSeparatorLine ); + CMenuWidget* cammenu = new CMenuWidget(LOCALE_CI_SETTINGS, NEUTRINO_ICON_SETTINGS); + //cammenu->addItem( GenericMenuBack ); + //cammenu->addItem( GenericMenuSeparatorLine ); + cammenu->addIntroItems(); + + if(true /* CiSlots */) { + cammenu->addItem( new CMenuOptionChooser(LOCALE_CI_RESET_STANDBY, &g_settings.ci_standby_reset, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); + cammenu->addItem( new CMenuOptionNumberChooser(LOCALE_CI_CLOCK, &g_settings.ci_clock, true, 6, 12, this)); + cammenu->addItem( GenericMenuSeparatorLine ); + } CMenuWidget * tempMenu; - int CiSlots = ca->GetNumberCISlots(); int i = 0; cnt = 0; @@ -494,3 +489,13 @@ int CCAMMenuHandler::doMenu(int slot, CA_SLOT_TYPE slotType) printf("CCAMMenuHandler::doMenu: return\n"); return res; } + +bool CCAMMenuHandler::changeNotify(const neutrino_locale_t OptionName, void * /*Data*/) +{ + if (ARE_LOCALES_EQUAL(OptionName, LOCALE_CI_CLOCK)) { + printf("CCAMMenuHandler::changeNotify: ci_clock %d\n", g_settings.ci_clock); + ca->SetTSClock(g_settings.ci_clock * 1000000); + return true; + } + return false; +} diff --git a/src/gui/cam_menu.h b/src/gui/cam_menu.h index 78b8f3749..4a8c1fa43 100644 --- a/src/gui/cam_menu.h +++ b/src/gui/cam_menu.h @@ -1,13 +1,12 @@ /* Neutrino-GUI - DBoxII-Project - - License: GPL + Copyright (C) 2011 CoolStream International Ltd + License: GPLv2 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -32,7 +31,7 @@ using namespace std; -class CCAMMenuHandler : public CMenuTarget +class CCAMMenuHandler : public CMenuTarget, public CChangeObserver { private: CHintBox * hintBox; @@ -48,6 +47,7 @@ class CCAMMenuHandler : public CMenuTarget void init(void); int exec(CMenuTarget* parent, const std::string &actionkey); int handleMsg (const neutrino_msg_t msg, neutrino_msg_data_t data); + bool changeNotify(const neutrino_locale_t OptionName, void * /*data*/); }; #endif From deeb24760ea541d417f247160f96c0c0eb3ae47d Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:41:21 +0400 Subject: [PATCH 008/737] infoviewer: get satellite name from CServiceManager; add tuner number icon; use channel camap to display ca systems --- src/gui/infoviewer.cpp | 144 ++++++++++++++++++++--------------------- src/gui/infoviewer.h | 1 + 2 files changed, 71 insertions(+), 74 deletions(-) diff --git a/src/gui/infoviewer.cpp b/src/gui/infoviewer.cpp index f0319859f..7bac82d78 100644 --- a/src/gui/infoviewer.cpp +++ b/src/gui/infoviewer.cpp @@ -60,7 +60,7 @@ #include #include -#include +#include #include #include @@ -80,16 +80,11 @@ extern cVideo * videoDecoder; event_id_t CInfoViewer::last_curr_id = 0, CInfoViewer::last_next_id = 0; - -extern CZapitClient::SatelliteList satList; static bool sortByDateTime (const CChannelEvent& a, const CChannelEvent& b) { return a.startTime < b.startTime; } -extern bool autoshift; -extern uint32_t shift_timer; -//extern std::string ext_channel_name; extern bool timeset; CInfoViewer::CInfoViewer () @@ -177,7 +172,7 @@ void CInfoViewer::Init() BBarY------+----------------------------------------------------+--+ | * red * green * yellow * blue ====== [DD][16:9]| InfoHeightY_Info +----------------------------------------------------+--+ - | + | asize | | BoxEndX-/ */ void CInfoViewer::start () @@ -416,6 +411,7 @@ void CInfoViewer::paintBackground(int col_NumBox) ChanWidth, ChanHeight, col_NumBox, c_rad_mid); } + void CInfoViewer::paintCA_bar(int left, int right) { int xcnt = (BoxEndX - ChanInfoX) / 4; @@ -468,7 +464,17 @@ void CInfoViewer::paintshowButtonBar() showIcon_VTXT (); showIcon_SubT(); showIcon_Resolution(); + showIcon_Tuner(); +} +void CInfoViewer::showIcon_Tuner() const +{ + //FIXME test + int tuner_x = BoxEndX - 2 - (((g_settings.casystem_display !=2) ? 0:icon_crypt_width )+ icon_xres_width + 2*icon_large_width + 3*icon_small_width + ((g_settings.casystem_display !=2) ?5:6)*2); + int tuner = 1 + CFEManager::getInstance()->getLiveFE()->getNumber(); + char icon_name[3]; + snprintf(icon_name, 3, "%d", tuner); + frameBuffer->paintIcon(icon_name, tuner_x, BBarY, InfoHeightY_Info); } void CInfoViewer::show_current_next(bool new_chan, int epgpos) @@ -718,34 +724,32 @@ void CInfoViewer::showTitle (const int ChanNum, const std::string & Channel, con fprintf(stderr, "after showchannellogo, mode = %d ret = %d logo_ok = %d\n",g_settings.infobar_show_channellogo, ChannelLogoMode, logo_ok); int ChanNumYPos = BoxStartY + ChanHeight; - if (g_settings.infobar_sat_display && !satellitePositions.empty()) { - sat_iterator_t sit = satellitePositions.find(satellitePosition); + //if (g_settings.infobar_sat_display && satellitePosition >= 0 && !satellitePositions.empty()) { + if (g_settings.infobar_sat_display) { + std::string name = CServiceManager::getInstance()->GetSatelliteName(satellitePosition); + int satNameWidth = g_SignalFont->getRenderWidth (name); + std::string satname_tmp = name; + if (satNameWidth > (ChanWidth - 4)) { + satNameWidth = ChanWidth - 4; + size_t pos1 = name.find("(") ; + size_t pos2 = name.find_last_of(")"); + size_t pos0 = name.find(" ") ; + if ((pos1 != std::string::npos) && (pos2 != std::string::npos) && (pos0 != std::string::npos)) { + pos1++; + satname_tmp = name.substr(0, pos0 ); - if (sit != satellitePositions.end()) { - int satNameWidth = g_SignalFont->getRenderWidth (sit->second.name); - std::string satname_tmp = sit->second.name; - if (satNameWidth > (ChanWidth - 4)) { - satNameWidth = ChanWidth - 4; - size_t pos1 = sit->second.name.find("(") ; - size_t pos2 = sit->second.name.find_last_of(")"); - size_t pos0 = sit->second.name.find(" ") ; - if ((pos1 != std::string::npos) && (pos2 != std::string::npos) && (pos0 != std::string::npos)) { - pos1++; - satname_tmp = sit->second.name.substr(0, pos0 ); + if(satname_tmp == "Hot") + satname_tmp = "Hotbird"; - if(satname_tmp == "Hot") - satname_tmp = "Hotbird"; - - satname_tmp +=" "; - satname_tmp += sit->second.name.substr( pos1,pos2-pos1 ); - satNameWidth = g_SignalFont->getRenderWidth (satname_tmp); - if (satNameWidth > (ChanWidth - 4)) - satNameWidth = ChanWidth - 4; - } + satname_tmp +=" "; + satname_tmp += name.substr( pos1,pos2-pos1 ); + satNameWidth = g_SignalFont->getRenderWidth (satname_tmp); + if (satNameWidth > (ChanWidth - 4)) + satNameWidth = ChanWidth - 4; } - int chanH = g_SignalFont->getHeight (); - g_SignalFont->RenderString (3 + BoxStartX + ((ChanWidth - satNameWidth) / 2) , BoxStartY + chanH, satNameWidth, satname_tmp, COL_INFOBAR); } + int chanH = g_SignalFont->getHeight (); + g_SignalFont->RenderString (3 + BoxStartX + ((ChanWidth - satNameWidth) / 2) , BoxStartY + chanH, satNameWidth, satname_tmp, COL_INFOBAR); ChanNumYPos += 10; } @@ -912,22 +916,22 @@ void CInfoViewer::loop(bool show_dot) else res = CNeutrinoApp::getInstance()->handleMsg(msg, data); - } + } #if 0 else if (CMoviePlayerGui::getInstance().start_timeshift && (msg == NeutrinoMessages::EVT_TIMER)) { CMoviePlayerGui::getInstance().start_timeshift = false; - } + } #endif else if (CMoviePlayerGui::getInstance().timeshift && ((msg == (neutrino_msg_t) g_settings.mpkey_rewind) || \ - (msg == (neutrino_msg_t) g_settings.mpkey_forward) || \ - (msg == (neutrino_msg_t) g_settings.mpkey_pause) || \ - (msg == (neutrino_msg_t) g_settings.mpkey_stop) || \ - (msg == (neutrino_msg_t) g_settings.mpkey_play) || \ - (msg == (neutrino_msg_t) g_settings.mpkey_time) || \ - (msg == (neutrino_msg_t) g_settings.key_timeshift))) { + (msg == (neutrino_msg_t) g_settings.mpkey_forward) || \ + (msg == (neutrino_msg_t) g_settings.mpkey_pause) || \ + (msg == (neutrino_msg_t) g_settings.mpkey_stop) || \ + (msg == (neutrino_msg_t) g_settings.mpkey_play) || \ + (msg == (neutrino_msg_t) g_settings.mpkey_time) || \ + (msg == (neutrino_msg_t) g_settings.key_timeshift))) { g_RCInput->postMsg (msg, data); res = messages_return::cancel_info; - } + } } if (hideIt) @@ -1356,6 +1360,7 @@ int CInfoViewer::handleMsg (const neutrino_msg_t msg, neutrino_msg_data_t data) showIcon_SubT(); showIcon_CA_Status (0); showIcon_Resolution(); + showIcon_Tuner(); } } return messages_return::handled; @@ -1541,8 +1546,8 @@ void CInfoViewer::showSNR () } int sw, snr, sig, posx, posy; int height, ChanNumYPos; - ssig = CFrontend::getInstance()->getSignalStrength(); - ssnr = CFrontend::getInstance()->getSignalNoiseRatio(); + ssig = CFEManager::getInstance()->getLiveFE()->getSignalStrength(); + ssnr = CFEManager::getInstance()->getLiveFE()->getSignalNoiseRatio(); sig = (ssig & 0xFFFF) * 100 / 65535; snr = (ssnr & 0xFFFF) * 100 / 65535; @@ -1581,17 +1586,16 @@ void CInfoViewer::showSNR () /* center the scales in the button bar. BBarY + InfoHeightY_Info / 2 is middle, scales are 6 pixels high, icons are 16 pixels, so keep 4 pixels free between the scales */ - varscale->paintProgressBar(BoxEndX - (((g_settings.casystem_display !=2) ? 0:icon_crypt_width )+ icon_xres_width + 2*icon_large_width + 2*icon_small_width + ((g_settings.casystem_display !=2) ?5:6)*2) - hddwidth - 2, - BBarY + InfoHeightY_Info / 2 - 2 - 6, hddwidth , 6, per, 100); + int scale_x = BoxEndX - (((g_settings.casystem_display !=2) ? 0:icon_crypt_width )+ icon_xres_width + 2*icon_large_width + 3*icon_small_width + ((g_settings.casystem_display !=2) ?5:6)*2) - hddwidth - 2; + varscale->paintProgressBar(scale_x, BBarY + InfoHeightY_Info / 2 - 2 - 6, hddwidth , 6, per, 100); per = 0; //HD info - if(!check_dir(g_settings.network_nfs_recordingdir)){ + if(!check_dir(g_settings.network_nfs_recordingdir)) { if (::statfs(g_settings.network_nfs_recordingdir, &s) == 0) { per = (s.f_blocks - s.f_bfree) / (s.f_blocks/100); } } - hddscale->paintProgressBar(BoxEndX - (((g_settings.casystem_display !=2) ? 0:icon_crypt_width )+ icon_xres_width + 2*icon_large_width + 2*icon_small_width + ((g_settings.casystem_display !=2) ?5:6)*2) - hddwidth - 2, - BBarY + InfoHeightY_Info / 2 + 2, hddwidth, 6, per, 100); + hddscale->paintProgressBar(scale_x, BBarY + InfoHeightY_Info / 2 + 2, hddwidth, 6, per, 100); } } @@ -2248,48 +2252,40 @@ void CInfoViewer::showOne_CAIcon(bool fta) void CInfoViewer::showIcon_CA_Status (int notfirst) { - extern int pmt_caids[4][11]; int caids[] = { 0x600, 0x1700, 0x0100, 0x0500, 0x1800, 0xB00, 0xD00, 0x900, 0x2600, 0x4a00, 0x0E00 }; int i = 0; - if (g_settings.casystem_display == 2) { - bool fta = true; - for (i=0; i < (int)(sizeof(caids)/sizeof(int)); i++) { - if (pmt_caids[0][i]) { - fta = false; - break; - } - } - showOne_CAIcon(fta); + + if (g_settings.casystem_display == 3) return; - } - else if (g_settings.casystem_display == 3) { + + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if(!channel) + return; + + if (g_settings.casystem_display == 2) { + bool fta = (channel->camap.size() == 0); + showOne_CAIcon(fta); return; } const char * white = (char *) "white"; const char * yellow = (char *) "yellow"; static int icon_space_offset = 0; - bool paintIconFlag = false; - if (pmt_caids[0][0] != 0 && pmt_caids[0][1] != 0) - pmt_caids[0][1] = 0; - - if (!notfirst) { + if(!notfirst) { if ((g_settings.casystem_display == 1) && (icon_space_offset)) { paintCA_bar(0,icon_space_offset); icon_space_offset = 0; } - for (i=0; i < (int)(sizeof(caids)/sizeof(int)); i++) { - if (!(i == 1 && pmt_caids[0][0] != 0 && pmt_caids[0][1] == 0 )) { - if ((g_settings.casystem_display == 1 ) && pmt_caids[0][i]) { - paintIconFlag = true; - } else if (g_settings.casystem_display == 0 ) - paintIconFlag = true; - } - if (paintIconFlag) { - paint_ca_icons(caids[i], (char *) (pmt_caids[0][i] ? yellow : white),icon_space_offset); - paintIconFlag = false; + for (i = 0; i < (int)(sizeof(caids)/sizeof(int)); i++) { + bool found = false; + for(casys_map_iterator_t it = channel->camap.begin(); it != channel->camap.end(); ++it) { + int caid = (*it) & 0xFF00; + if((found = (caid == caids[i]))) + break; } + if(found || (g_settings.casystem_display == 0)) + paint_ca_icons(caids[i], (char *) (found ? yellow : white), icon_space_offset); } } } diff --git a/src/gui/infoviewer.h b/src/gui/infoviewer.h index fca649661..84e0ca58f 100644 --- a/src/gui/infoviewer.h +++ b/src/gui/infoviewer.h @@ -144,6 +144,7 @@ class CInfoViewer void showRecordIcon(const bool show); void showIcon_SubT() const; void showIcon_Resolution() const; + void showIcon_Tuner() const; void showFailure(); void showMotorMoving(int duration); From 2e11214728be2d739d3ab757d0ed831365462c66 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:43:55 +0400 Subject: [PATCH 009/737] motorcontrol: add frontend member and param to select frontend to use; set live frontend to selected for diseqc commands --- src/gui/motorcontrol.cpp | 53 ++++++++++++++++++++++++++-------------- src/gui/motorcontrol.h | 8 +++--- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/gui/motorcontrol.cpp b/src/gui/motorcontrol.cpp index 07c6d9c2b..627b4dfc7 100644 --- a/src/gui/motorcontrol.cpp +++ b/src/gui/motorcontrol.cpp @@ -44,7 +44,7 @@ #include #include -#include +#include static int g_sig; static int g_snr; @@ -59,11 +59,21 @@ static int moving = 0; #define BAR_WIDTH 100 #define BAR_HEIGHT 16 //(13 + BAR_BORDER*2) -CMotorControl::CMotorControl() +CMotorControl::CMotorControl(int tnum) { + printf("CMotorControl::CMotorControl: tuner %d\n", tnum); + frontend = CFEManager::getInstance()->getFE(tnum); + if(frontend == NULL) { + printf("CMotorControl::CMotorControl: BUG, invalid tuner number %d, using first\n", tnum); + frontend = CFEManager::getInstance()->getFE(0); + } Init(); } +CMotorControl::~CMotorControl() +{ +printf("CMotorControl::~CMotorControl\n"); +} void CMotorControl::Init(void) { frameBuffer = CFrameBuffer::getInstance(); @@ -120,6 +130,7 @@ int CMotorControl::exec(CMenuTarget* parent, const std::string &) x = frameBuffer->getScreenX() + (frameBuffer->getScreenWidth() - width) / 2; y = frameBuffer->getScreenY() + (frameBuffer->getScreenHeight() - height) / 2; +#if 0 /* send satellite list to zapit */ for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { if(!strcmp(sit->second.name.c_str(),scansettings.satNameNoDiseqc)) { @@ -131,23 +142,28 @@ int CMotorControl::exec(CMenuTarget* parent, const std::string &) break; } } - origPosition = motorPosition; +#endif + /* send satellite list to zapit */ + sat.position = CServiceManager::getInstance()->GetSatellitePosition(scansettings.satNameNoDiseqc); + strncpy(sat.satName, scansettings.satNameNoDiseqc, 50); + satList.push_back(sat); + satellite_map_t & satmap = frontend->getSatellites(); + sit = satmap.find(sat.position); + if(sit != satmap.end() && sit->second.motor_position) + motorPosition = sit->second.motor_position; + + origPosition = motorPosition; + //FIXME change cZapit live fe + g_Zapit->stopPlayBack(); g_Zapit->setScanSatelliteList( satList); + CZapit::getInstance()->SetLiveFrontend(frontend); TP.feparams.frequency = atoi(scansettings.TP_freq); TP.feparams.u.qpsk.symbol_rate = atoi(scansettings.TP_rate); TP.feparams.u.qpsk.fec_inner = (fe_code_rate_t)scansettings.TP_fec; TP.polarization = scansettings.TP_pol; -#if 0 - CZapitClient::CCurrentServiceInfo si = g_Zapit->getCurrentServiceInfo (); - TP.feparams.frequency = si.tsfrequency; - TP.feparams.u.qpsk.symbol_rate = si.rate; - TP.feparams.u.qpsk.fec_inner = si.fec; - TP.polarization = si.polarisation; -#endif - g_Zapit->stopPlayBack(); g_Zapit->tune_TP(TP); paint(); @@ -335,15 +351,16 @@ int CMotorControl::exec(CMenuTarget* parent, const std::string &) printf("[motorcontrol] 5 key received... store present satellite number: %d\n", motorPosition); if(motorPosition != origPosition) { printf("[motorcontrol] position changed %d -> %d\n", origPosition, motorPosition); - for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { + for(sit = satmap.begin(); sit != satmap.end(); sit++) { if(sit->second.motor_position == motorPosition) break; } - if(sit != satellitePositions.end()) { - printf("[motorcontrol] new positions configured for %s\n", sit->second.name.c_str()); + if(sit != satmap.end()) { + std::string satname = CServiceManager::getInstance()->GetSatelliteName(sit->first); + printf("[motorcontrol] new positions configured for %s\n", satname.c_str()); std::string buf = g_Locale->getText(LOCALE_MOTORCONTROL_OVERRIDE); buf += " "; - buf += sit->second.name; + buf += satname; buf += " ?"; store = (ShowMsgUTF(LOCALE_MESSAGEBOX_INFO, buf,CMessageBox::mbrNo,CMessageBox::mbNo|CMessageBox::mbYes) == CMessageBox::mbrYes); } @@ -414,7 +431,7 @@ int CMotorControl::exec(CMenuTarget* parent, const std::string &) } hide(); - CFrontend::getInstance()->setTsidOnid(0); + frontend->setTsidOnid(0); return menu_return::RETURN_REPAINT; } @@ -701,8 +718,8 @@ void CMotorControl::showSNR() int sw; - ssig = CFrontend::getInstance()->getSignalStrength(); - ssnr = CFrontend::getInstance()->getSignalNoiseRatio(); + ssig = frontend->getSignalStrength(); + ssnr = frontend->getSignalNoiseRatio(); snr = (ssnr & 0xFFFF) * 100 / 65535; sig = (ssig & 0xFFFF) * 100 / 65535; diff --git a/src/gui/motorcontrol.h b/src/gui/motorcontrol.h index 75854f38f..7ef402417 100644 --- a/src/gui/motorcontrol.h +++ b/src/gui/motorcontrol.h @@ -37,7 +37,7 @@ #include #include #include - +#include #define STEP_MODE_OFF 0 #define STEP_MODE_AUTO 1 @@ -49,6 +49,7 @@ class CMotorControl : public CMenuTarget private: void Init(void); CFrameBuffer *frameBuffer; + CFrontend *frontend; int x; int y; int width; @@ -57,7 +58,7 @@ class CMotorControl : public CMenuTarget int ypos; int ypos_status; int ypos_menue; - + int8_t stepSize; int32_t stepDelay; int stepMode; @@ -81,7 +82,8 @@ class CMotorControl : public CMenuTarget public: - CMotorControl(); + CMotorControl(int tnum = 0); + ~CMotorControl(); void hide(); int exec(CMenuTarget* parent, const std::string & actionKey); }; From 20b61be14a9e9b88164ac15962224d4336862871 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:46:14 +0400 Subject: [PATCH 010/737] scan_setup: re-write to support two frontends; move update of manual scan menu params from neutrino; changeNotify for related params --- src/gui/scan_setup.cpp | 679 ++++++++++++++++++++++++++--------------- src/gui/scan_setup.h | 69 +++-- 2 files changed, 476 insertions(+), 272 deletions(-) diff --git a/src/gui/scan_setup.cpp b/src/gui/scan_setup.cpp index e8170cda5..32096482a 100644 --- a/src/gui/scan_setup.cpp +++ b/src/gui/scan_setup.cpp @@ -9,6 +9,8 @@ Copyright (C) 2011 T. Graf 'dbt' Homepage: http://www.dbox2-tuning.net/ + Copyright (C) 2011 CoolStream International Ltd + License: GPL This program is free software; you can redistribute it and/or modify @@ -50,11 +52,13 @@ #include #include -#include +#include #include #include #include #include +#include +#include extern std::map select_transponders; extern Zapit_config zapitCfg; @@ -64,7 +68,7 @@ extern char zapit_long[20]; extern CHintBox *reloadhintBox; static int all_usals = 1; -sat_iterator_t sit; +//sat_iterator_t sit; #define SCANTS_BOUQUET_OPTION_COUNT 3 const CMenuOptionChooser::keyval SCANTS_BOUQUET_OPTIONS[SCANTS_BOUQUET_OPTION_COUNT] = @@ -140,6 +144,7 @@ const CMenuOptionChooser::keyval SATSETUP_SCANTP_MOD[SATSETUP_SCANTP_MOD_COUNT] { 4, LOCALE_EXTRA_TP_MOD_128}, { 5, LOCALE_EXTRA_TP_MOD_256} }; + #define SATSETUP_SCANTP_POL_COUNT 2 const CMenuOptionChooser::keyval SATSETUP_SCANTP_POL[SATSETUP_SCANTP_POL_COUNT] = { @@ -169,6 +174,7 @@ const CMenuOptionChooser::keyval SECTIONSD_SCAN_OPTIONS[SECTIONSD_SCAN_OPTIONS_C { 1, LOCALE_OPTIONS_ON }, { 2, LOCALE_OPTIONS_ON_WITHOUT_MESSAGES } }; + #define DISEQC_ORDER_OPTION_COUNT 2 const CMenuOptionChooser::keyval DISEQC_ORDER_OPTIONS[DISEQC_ORDER_OPTION_COUNT] = { @@ -176,13 +182,20 @@ const CMenuOptionChooser::keyval DISEQC_ORDER_OPTIONS[DISEQC_ORDER_OPTION_COUNT] { UNCOMMITED_FIRST, LOCALE_SATSETUP_DISEQC_UNCOM_COM } }; +#define SATSETUP_FRONTEND_MODE_COUNT 4 +const CMenuOptionChooser::keyval SATSETUP_FRONTEND_MODE[SATSETUP_FRONTEND_MODE_COUNT] = +{ + { CFEManager::FE_MODE_SINGLE, LOCALE_SATSETUP_FE_MODE_SINGLE }, + { CFEManager::FE_MODE_LOOP, LOCALE_SATSETUP_FE_MODE_LOOP }, + { CFEManager::FE_MODE_TWIN, LOCALE_SATSETUP_FE_MODE_TWIN }, + { CFEManager::FE_MODE_ALONE, LOCALE_SATSETUP_FE_MODE_ALONE } +}; CScanSetup::CScanSetup(bool wizard_mode) { width = w_max (40, 10); selected = -1; - dmode = scansettings.diseqcMode; - sfound = 0; + fselected = -1; r_system = g_info.delivery_system; fec_count = (r_system == DVB_S) ? SATSETUP_SCANTP_FEC_COUNT : CABLESETUP_SCANTP_FEC_COUNT; freq_length = (r_system == DVB_S) ? 8 : 6; @@ -193,8 +206,7 @@ CScanSetup::CScanSetup(bool wizard_mode) satprov_locale = (r_system == DVB_S) ? LOCALE_SATSETUP_SATELLITE : LOCALE_CABLESETUP_PROVIDER; satSelect = NULL; - usalsNotify = NULL; - satNotify = NULL; + frontendSetup = NULL; } CScanSetup* CScanSetup::getInstance() @@ -211,17 +223,17 @@ CScanSetup* CScanSetup::getInstance() CScanSetup::~CScanSetup() { - - } int CScanSetup::exec(CMenuTarget* parent, const std::string &actionKey) { int res = menu_return::RETURN_REPAINT; - + std::string::size_type loc; + if (parent) parent->hide(); - + + printf("[neutrino] CScanSetup::%s: %s \n", __FUNCTION__, actionKey.c_str()); if(actionKey=="save_scansettings") { printf("[neutrino] CScanSetup::%s save_scansettings...\n", __FUNCTION__); @@ -238,6 +250,20 @@ int CScanSetup::exec(CMenuTarget* parent, const std::string &actionKey) reloadhintBox->hide(); return res; } + else if(actionKey=="satsetup") + { + return showScanMenuLnbSetup(); + } + else if(actionKey=="satfind") + { + return showScanMenuSatFind(); + } + else if((loc = actionKey.find("config_frontend", 0)) != std::string::npos) + { + int number = actionKey.at(15) - '0'; + printf("[neutrino] CScanSetup::%s %s, fe %d\n", __FUNCTION__, actionKey.c_str(), number); + return showFrontendSetup(number); + } //starting scan std::string scants_key[] = {"all", "manual", "test", "fast", "auto"/*doesn't exists in CScanTs!*/}; @@ -264,34 +290,15 @@ int CScanSetup::exec(CMenuTarget* parent, const std::string &actionKey) return res; } - -#ifdef ENABLE_FASTSCAN -#define FAST_SCAN_OPTIONS_COUNT 2 -const CMenuOptionChooser::keyval FAST_SCAN_OPTIONS[FAST_SCAN_OPTIONS_COUNT] = -{ - { FAST_SCAN_SD, LOCALE_SATSETUP_FASTSCAN_SD }, - { FAST_SCAN_HD, LOCALE_SATSETUP_FASTSCAN_HD } - /*{ FAST_SCAN_ALL, LOCALE_SATSETUP_FASTSCAN_ALL }*/ -}; - -#define FAST_SCAN_PROV_OPTIONS_COUNT 3 -const CMenuOptionChooser::keyval FAST_SCAN_PROV_OPTIONS[FAST_SCAN_PROV_OPTIONS_COUNT] = -{ - { OPERATOR_CD, LOCALE_SATSETUP_FASTSCAN_PROV_CD }, - { OPERATOR_TVV, LOCALE_SATSETUP_FASTSCAN_PROV_TVV }, - { OPERATOR_TELESAT, LOCALE_SATSETUP_FASTSCAN_PROV_TELESAT } -}; -#endif /*ENABLE_FASTSCAN*/ - //scale to max sat/cable name lenght unsigned int CScanSetup::getSatMenuListWidth() { printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); unsigned int sat_txt_w = 0, max_txt_w = 0; - - for (sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) - { - sat_txt_w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(sit->second.name.c_str(), true); + + satellite_map_t satmap = CServiceManager::getInstance()->SatelliteList(); + for(sat_iterator_t it = satmap.begin(); it != satmap.end(); ++it) { + sat_txt_w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth(it->second.name.c_str(), true); max_txt_w = std::max(max_txt_w, sat_txt_w); } @@ -312,26 +319,16 @@ int CScanSetup::showScanMenu() int shortcut = 1; CMenuWidget *settings = NULL;//main - CMenuWidget *satSetup = NULL;//lnb config sub menu - CMenuForwarder *fsatSetup = NULL;//lnb config - CMenuWidget *motorMenu = NULL;//motor menu - CMenuForwarder *fmotorMenu = NULL;//motor settings CMenuWidget *manualScan = NULL;//manual scan CMenuWidget *autoScanAll = NULL;//auto scan all - CMenuForwarder *fautoScanAll = NULL; #ifdef ENABLE_FASTSCAN CMenuWidget *fastScanMenu = NULL;//fast scan #endif /*ENABLE_FASTSCAN*/ CMenuWidget *autoScan = NULL;//auto scan - - CMenuOptionChooser *ojDiseqc = NULL;//diseqc modes - CMenuOptionNumberChooser *ojDiseqcRepeats = NULL;//diseqc repeats + CMenuWidget *setupMenu = NULL;//sat frontend setup; allow_start = !CRecordManager::getInstance()->RecordingStatus() || CRecordManager::getInstance()->TimeshiftOnly(); - - satNotify = new CSatelliteSetupNotifier(); - usalsNotify = new CAllUsalsNotifier(); - + //main settings = new CMenuWidget(is_wizard ? LOCALE_SERVICEMENU_SCANTS : LOCALE_SERVICEMENU_HEAD, NEUTRINO_ICON_SETTINGS, width); settings->setSelected(selected); @@ -351,69 +348,41 @@ int CScanSetup::showScanMenu() //bouquet generate mode settings->addItem(new CMenuOptionChooser(LOCALE_SCANTS_BOUQUET, (int *)&scansettings.bouquetMode, SCANTS_BOUQUET_OPTIONS, SCANTS_BOUQUET_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++), "", true)); - //t_satellite_position currentSatellitePosition = CFrontend::getInstance()->getCurrentSatellitePosition(); //sat/provider selector satSelect = new CMenuOptionStringChooser(satprov_locale, scansettings.satNameNoDiseqc, true, NULL, CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED, true); - satSetup = new CMenuWidget(satprov_locale, NEUTRINO_ICON_SETTINGS, width); - + satOnOff = new CMenuWidget(satprov_locale, NEUTRINO_ICON_SETTINGS, width); + if (r_system == DVB_S) //sat { - settings->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SCANTS_PREVERENCES_RECEIVING_SYSTEM)); - - //diseqc on/off - ojDiseqc = new CMenuOptionChooser(LOCALE_SATSETUP_DISEQC, (int *)&scansettings.diseqcMode, SATSETUP_DISEQC_OPTIONS, SATSETUP_DISEQC_OPTION_COUNT, true, satNotify, CRCInput::convertDigitToKey(shortcut++), "", true); - //diseqc type - ojDiseqcRepeats = new CMenuOptionNumberChooser(LOCALE_SATSETUP_DISEQCREPEAT, (int *)&scansettings.diseqcRepeat, (dmode != NO_DISEQC) && (dmode != DISEQC_ADVANCED), 0, 2, NULL); - - satNotify->addItem(1, ojDiseqcRepeats); - //-------------------------------------------------------------- - //add diseqc items - settings->addItem(ojDiseqc); - settings->addItem(ojDiseqcRepeats); - //-------------------------------------------------------------- - settings->addItem(GenericMenuSeparatorLine); - //-------------------------------------------------------------- - - //lnb settings - addScanMenuLnbSetup(satSetup); - - //motor settings - motorMenu = new CMenuWidget(LOCALE_SATSETUP_EXTENDED_MOTOR, NEUTRINO_ICON_SETTINGS, width); - addScanMenuMotorMenu(motorMenu); + //settings->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SCANTS_PREVERENCES_RECEIVING_SYSTEM)); + setupMenu = new CMenuWidget(LOCALE_SATSETUP_FE_SETUP, NEUTRINO_ICON_SETTINGS, width); + setupMenu->setSelected(fselected); + addScanMenuFrontendSetup(setupMenu); + CMenuForwarder * fsetupMenu = new CMenuForwarder(LOCALE_SATSETUP_FE_SETUP, true, NULL, setupMenu, "", CRCInput::convertDigitToKey(shortcut++)); + settings->addItem(fsetupMenu); + /* add configured satellites to satSelect */ + fillSatSelect(); } else if (r_system == DVB_C) //cable { //-------------------------------------------------------------- settings->addItem(GenericMenuSeparatorLine); //-------------------------------------------------------------- - //fsatSetup = new CMenuForwarder(LOCALE_CABLESETUP_PROVIDER, true, NULL, satSetup, "", CRCInput::convertDigitToKey(shortcut++)); - addScanMenuProvider(satSetup); + fillCableSelect(); + //tune timeout + settings->addItem(new CMenuOptionNumberChooser(LOCALE_EXTRA_ZAPIT_FE_TIMEOUT, (int *)&zapitCfg.feTimeout, true, 6, 100) ); + if(CFEManager::getInstance()->getFrontendCount() > 1) { + femode = CFEManager::getInstance()->getMode(); + CMenuOptionChooser * mode = new CMenuOptionChooser(LOCALE_SATSETUP_FE_MODE, (int *)&femode, SATSETUP_FRONTEND_MODE, 2, true, this); + settings->addItem(mode); + } + CIntInput* nid = new CIntInput(LOCALE_SATSETUP_CABLE_NID, (int&) scansettings.cable_nid, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); + settings->addItem(new CMenuForwarder(LOCALE_SATSETUP_CABLE_NID, true, nid->getValue(), nid)); } - - //tune timeout - settings->addItem(new CMenuOptionNumberChooser(LOCALE_EXTRA_ZAPIT_FE_TIMEOUT, (int *)&zapitCfg.feTimeout, true, 6, 100) ); - - if (r_system == DVB_S) - { - fmotorMenu = new CMenuForwarder(LOCALE_SATSETUP_EXTENDED_MOTOR, true, NULL, motorMenu, "", CRCInput::convertDigitToKey(shortcut++)); - fsatSetup = new CMenuForwarder(LOCALE_SATSETUP_SAT_SETUP, true, NULL, satSetup, "", CRCInput::convertDigitToKey(shortcut++)); - //-------------------------------------------------------------- - settings->addItem(GenericMenuSeparatorLine); - //-------------------------------------------------------------- - settings->addItem(fmotorMenu); //motor settings - settings->addItem(fsatSetup); //lnb satsetup setup - } - //-------------------------------------------------------------- settings->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SCANTS_PREVERENCES_SCAN)); //-------------------------------------------------------------- - - if (!sfound && satellitePositions.size()) - { - sit = satellitePositions.begin(); - snprintf(scansettings.satNameNoDiseqc, sizeof(scansettings.satNameNoDiseqc), "%s", sit->second.name.c_str()); - } - + int w = getSatMenuListWidth(); //auto scan @@ -434,136 +403,321 @@ int CScanSetup::showScanMenu() //auto scan all autoScanAll = new CMenuWidget(LOCALE_SATSETUP_AUTO_SCAN_ALL, NEUTRINO_ICON_SETTINGS, w/*width*/); addScanMenuAutoScanAll(autoScanAll); - fautoScanAll = new CMenuForwarder(LOCALE_SATSETUP_AUTO_SCAN_ALL, (dmode != NO_DISEQC), NULL, autoScanAll, "", CRCInput::RC_blue, NEUTRINO_ICON_BUTTON_BLUE); - satNotify->addItem(2, fautoScanAll); + fautoScanAll = new CMenuForwarder(LOCALE_SATSETUP_AUTO_SCAN_ALL, true /*(dmode != NO_DISEQC)*/, NULL, autoScanAll, "", CRCInput::RC_blue, NEUTRINO_ICON_BUTTON_BLUE); settings->addItem(fautoScanAll); - } - #ifdef ENABLE_FASTSCAN - if (r_system == DVB_S) - { //fast scan fastScanMenu = new CMenuWidget(LOCALE_SATSETUP_FASTSCAN_HEAD, NEUTRINO_ICON_SETTINGS); addScanMenuFastScan(fastScanMenu); settings->addItem(new CMenuForwarder(LOCALE_SATSETUP_FASTSCAN_HEAD, true, NULL, fastScanMenu, "", CRCInput::convertDigitToKey(shortcut++))); - } #endif /*ENABLE_FASTSCAN*/ + } int res = settings->exec(NULL, ""); settings->hide(); selected = settings->getSelected(); - delete satNotify; - delete usalsNotify; + if(setupMenu) + fselected = setupMenu->getSelected(); + delete satSelect; delete settings; return res; } -//init sat setup menu -void CScanSetup::addScanMenuLnbSetup(CMenuWidget *sat_setup) +void CScanSetup::addScanMenuFrontendSetup(CMenuWidget * setupMenu) { - printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); + int shortcut = 1; + femode = CFEManager::getInstance()->getMode(); + + setupMenu->addIntroItems(); + + int count = CFEManager::getInstance()->getFrontendCount(); + + CMenuOptionChooser * mode = new CMenuOptionChooser(LOCALE_SATSETUP_FE_MODE, (int *)&femode, SATSETUP_FRONTEND_MODE, SATSETUP_FRONTEND_MODE_COUNT, allow_start && (count > 1), this, CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED, true); + setupMenu->addItem(mode); + setupMenu->addItem(new CMenuOptionNumberChooser(LOCALE_EXTRA_ZAPIT_FE_TIMEOUT, (int *)&zapitCfg.feTimeout, true, 6, 100) ); + + for(int i = 0; i < count; i++) { + CFrontend * fe = CFEManager::getInstance()->getFE(i); + + char tmp[32]; + snprintf(tmp, sizeof(tmp), "config_frontend%d", i); + char name[255]; + snprintf(name, sizeof(name), "%s %d: %s", g_Locale->getText(LOCALE_SATSETUP_FE_SETUP), i, fe->getInfo()->name); + + CMenuForwarder * fSetup = new CMenuForwarderNonLocalized(name, ((i == 0) || (femode == CFEManager::FE_MODE_ALONE)), NULL, this, tmp, + (i == 0) ? CRCInput::RC_green : CRCInput::RC_yellow, (i == 0) ? NEUTRINO_ICON_BUTTON_GREEN : NEUTRINO_ICON_BUTTON_YELLOW); + setupMenu->addItem(fSetup); + if(i != 0) + frontendSetup = fSetup; + } + CStringInput *toff = NULL; + sprintf(zapit_lat, "%02.6f", zapitCfg.gotoXXLatitude); + sprintf(zapit_long, "%02.6f", zapitCfg.gotoXXLongitude); + + setupMenu->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SATSETUP_EXTENDED_MOTOR)); + setupMenu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_LADIRECTION, (int *)&zapitCfg.gotoXXLaDirection, OPTIONS_SOUTH0_NORTH1_OPTIONS, OPTIONS_SOUTH0_NORTH1_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++))); + + toff = new CStringInput(LOCALE_EXTRA_LATITUDE, (char *) zapit_lat, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); + setupMenu->addItem(new CMenuForwarder(LOCALE_EXTRA_LATITUDE, true, zapit_lat, toff, "", CRCInput::convertDigitToKey(shortcut++))); + + setupMenu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_LODIRECTION, (int *)&zapitCfg.gotoXXLoDirection, OPTIONS_EAST0_WEST1_OPTIONS, OPTIONS_EAST0_WEST1_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++))); + + toff = new CStringInput(LOCALE_EXTRA_LONGITUDE, (char *) zapit_long, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); + setupMenu->addItem(new CMenuForwarder(LOCALE_EXTRA_LONGITUDE, true, zapit_long, toff, "", CRCInput::convertDigitToKey(shortcut++))); + + setupMenu->addItem(new CMenuOptionNumberChooser(LOCALE_SATSETUP_USALS_REPEAT, (int *)&zapitCfg.repeatUsals, true, 0, 10, NULL, 0, 0, LOCALE_OPTIONS_OFF) ); +} + +int CScanSetup::showFrontendSetup(int number) +{ + int shortcut = 1; + static int feselected = 0; + + printf("[neutrino] CScanSetup::%s fe %d\n", __FUNCTION__, number); + + fenumber = number; + + itemsForAdvancedDiseqc.Clear(); + itemsForNonAdvancedDiseqc.Clear(); + itemsForAnyDiseqc.Clear(); + + CFrontend * fe = CFEManager::getInstance()->getFE(number); + frontend_config_t & fe_config = fe->getConfig(); + dmode = fe_config.diseqcType; + + char name[255]; + snprintf(name, sizeof(name), "%s %d: %s", g_Locale->getText(LOCALE_SATSETUP_FE_SETUP), number, fe->getInfo()->name); + + CMenuWidget * setupMenu = new CMenuWidget(name, NEUTRINO_ICON_SETTINGS, width); + setupMenu->setSelected(feselected); + setupMenu->addIntroItems(); + + CMenuOptionChooser * ojDiseqc = new CMenuOptionChooser(LOCALE_SATSETUP_DISEQC, (int *)&dmode, SATSETUP_DISEQC_OPTIONS, SATSETUP_DISEQC_OPTION_COUNT, allow_start, this, CRCInput::convertDigitToKey(shortcut++), "", true); + CMenuOptionNumberChooser * ojDiseqcRepeats = new CMenuOptionNumberChooser(LOCALE_SATSETUP_DISEQCREPEAT, (int *)&fe_config.diseqcRepeats, (dmode != NO_DISEQC) && (dmode != DISEQC_ADVANCED), 0, 2, NULL); + + itemsForAnyDiseqc.Add(ojDiseqcRepeats); + + setupMenu->addItem(ojDiseqc); + setupMenu->addItem(ojDiseqcRepeats); + + CMenuWidget *satToSelect = new CMenuWidget(LOCALE_SATSETUP_SELECT_SAT, NEUTRINO_ICON_SETTINGS, width); + satToSelect->addIntroItems(); + + satellite_map_t & satmap = fe->getSatellites(); + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); ++sit) + { + std::string satname = CServiceManager::getInstance()->GetSatelliteName(sit->first); + satToSelect->addItem(new CMenuOptionChooser(satname.c_str(), &sit->second.configured, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); + } + setupMenu->addItem(new CMenuForwarder(LOCALE_SATSETUP_SELECT_SAT, true, NULL, satToSelect, "", CRCInput::convertDigitToKey(shortcut++))); + + fsatSetup = new CMenuForwarder(LOCALE_SATSETUP_SAT_SETUP, true, NULL, this, "satsetup", CRCInput::convertDigitToKey(shortcut++)); + setupMenu->addItem(fsatSetup); + + setupMenu->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SATSETUP_EXTENDED_MOTOR)); + setupMenu->addItem(new CMenuOptionNumberChooser(LOCALE_EXTRA_ZAPIT_MOTOR_SPEED, (int *)&fe_config.motorRotationSpeed, true, 0, 64, NULL) ); + setupMenu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_ZAPIT_HVOLTAGE, (int *)&fe_config.highVoltage, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); + + CMenuOptionChooser * allusals = new CMenuOptionChooser(LOCALE_SATSETUP_USE_USALS, &all_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, this); + setupMenu->addItem(allusals); + + setupMenu->addItem(new CMenuForwarder(LOCALE_MOTORCONTROL_HEAD, true, NULL, this, "satfind", CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED)); + + int res = setupMenu->exec(NULL, ""); + setupMenu->hide(); + feselected = setupMenu->getSelected(); + + /* add configured satellites to satSelect in case they changed */ + fillSatSelect(); + + delete setupMenu; + return res; +} + +int CScanSetup::showScanMenuLnbSetup() +{ + printf("[neutrino] CScanSetup call %s fe %d\n", __FUNCTION__, fenumber); + + int count = 0; + int res = menu_return::RETURN_REPAINT; + CFrontend * fe = CFEManager::getInstance()->getFE(fenumber); + + char name[255]; + snprintf(name, sizeof(name), "%s %d: %s", g_Locale->getText(satprov_locale), fenumber, fe->getInfo()->name); + + CMenuWidget * sat_setup = new CMenuWidget(name /*satprov_locale*/, NEUTRINO_ICON_SETTINGS, width); sat_setup->addIntroItems(); - CMenuWidget *satToSelect = new CMenuWidget(LOCALE_SATSETUP_SATELLITE, NEUTRINO_ICON_SETTINGS, width); - - for (sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) + satellite_map_t & satmap = fe->getSatellites(); + INFO("satmap size = %d", satmap.size()); + + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); ++sit) { - /* printf("Adding sat menu for %s position %d\n", sit->second.name.c_str(), sit->first); */ - satSelect->addOption(sit->second.name.c_str()); - - if (strcmp(scansettings.satNameNoDiseqc,sit->second.name.c_str()) == 0) - sfound = 1; - - //create selectable sat item - addScanMenuSatOnOff(satToSelect); - + if(!sit->second.configured) + continue; + + //std::string satname = it->second.name.c_str(); + std::string satname = CServiceManager::getInstance()->GetSatelliteName(sit->first); + //sub menu for sat settings to selectable sat item - CMenuWidget *tempsat = new CMenuWidget(sit->second.name.c_str(), NEUTRINO_ICON_SETTINGS, width); - addScanMenuTempSat(tempsat); - sat_setup->addItem(new CMenuForwarderNonLocalized(sit->second.name.c_str(), true, NULL, tempsat)); + CMenuWidget *tempsat = new CMenuWidget(satname.c_str(), NEUTRINO_ICON_SETTINGS, width); + addScanMenuTempSat(tempsat, sit->second); +#if 0 // option not refreshed. + if(sit->second.motor_position > 0) { + char mpos[10]; + sprintf(mpos, "%d", sit->second.motor_position); + sat_setup->addItem(new CMenuForwarderNonLocalized(satname.c_str(), true, mpos, tempsat)); + } else +#endif + sat_setup->addItem(new CMenuForwarderNonLocalized(satname.c_str(), true, NULL, tempsat)); + count++; + } + if(count) { + res = sat_setup->exec(NULL, ""); + sat_setup->hide(); + } + delete sat_setup; + return res; +} + +void CScanSetup::fillSatSelect() +{ + std::set satpos; + std::set::iterator tmpit; + + satSelect->removeOptions(); + + satOnOff->resetWidget(); + satOnOff->addIntroItems(); + + bool sfound = false; + int count = CFEManager::getInstance()->getFrontendCount(); + for(int i = 0; i < count; i++) { + CFrontend * fe = CFEManager::getInstance()->getFE(i); + satellite_map_t & satmap = fe->getSatellites(); + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); ++sit) { + tmpit = satpos.find(sit->first); + if(sit->second.configured && tmpit == satpos.end()) { + std::string satname = CServiceManager::getInstance()->GetSatelliteName(sit->first); + satSelect->addOption(satname.c_str()); + satpos.insert(sit->first); + + if (!sfound && strcmp(scansettings.satNameNoDiseqc, satname.c_str()) == 0) + sfound = true; + } + } + if(CFEManager::getInstance()->getMode() != CFEManager::FE_MODE_ALONE) + break; + } + if(!sfound && satpos.size()) { + tmpit = satpos.begin(); + std::string satname = CServiceManager::getInstance()->GetSatelliteName(*tmpit); + snprintf(scansettings.satNameNoDiseqc, sizeof(scansettings.satNameNoDiseqc), "%s", satname.c_str()); + } + satellite_map_t & satmap = CServiceManager::getInstance()->SatelliteList(); + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); sit++) { + if(satpos.find(sit->first) != satpos.end()) + satOnOff->addItem(new CMenuOptionChooser(sit->second.name.c_str(), &sit->second.use_in_scan, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); + else + sit->second.use_in_scan = false; } - } //init cable provider menu -void CScanSetup::addScanMenuProvider(CMenuWidget *provider_setup) +void CScanSetup::fillCableSelect() { printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); - provider_setup->addIntroItems(); - //don't misunderstand the name "satSelect", in this context it's actually for cable providers - //satSelect = new CMenuOptionStringChooser(LOCALE_CABLESETUP_PROVIDER, (char*)scansettings.satNameNoDiseqc, true); - - for (sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) + satellite_map_t satmap = CServiceManager::getInstance()->SatelliteList(); + bool sfound = false; + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); sit++) { printf("Adding cable menu for %s position %d\n", sit->second.name.c_str(), sit->first); satSelect->addOption(sit->second.name.c_str()); - if (strcmp(scansettings.satNameNoDiseqc,sit->second.name.c_str()) == 0) - sfound = 1; - + if (!sfound && strcmp(scansettings.satNameNoDiseqc, sit->second.name.c_str()) == 0) + sfound = true; + dprintf(DEBUG_DEBUG, "got scanprovider (cable): %s\n", sit->second.name.c_str()); } - + if (!sfound && satmap.size()) { + sat_iterator_t sit = satmap.begin(); + snprintf(scansettings.satNameNoDiseqc, sizeof(scansettings.satNameNoDiseqc), "%s", sit->second.name.c_str()); + } } -//init sat find menu -void CScanSetup::addScanMenuSatFind(CMenuWidget *sat_findMenu) +int CScanSetup::showScanMenuSatFind() { - printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); + printf("[neutrino] CScanSetup call %s fe %d\n", __FUNCTION__, fenumber); + int count = 0; + CFrontend * fe = CFEManager::getInstance()->getFE(fenumber); + char name[255]; + snprintf(name, sizeof(name), "%s %d: %s", g_Locale->getText(LOCALE_MOTORCONTROL_HEAD), fenumber, fe->getInfo()->name); + + CMenuWidget* sat_findMenu = new CMenuWidget(name /*LOCALE_MOTORCONTROL_HEAD*/, NEUTRINO_ICON_SETTINGS, width); + sat_findMenu->addIntroItems(); - - sat_findMenu->addItem(satSelect); + + CMenuOptionStringChooser * feSatSelect = new CMenuOptionStringChooser(satprov_locale, scansettings.satNameNoDiseqc, true, NULL, CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED, true); + satellite_map_t & satmap = fe->getSatellites(); + bool sfound = false; + std::string firstname; + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); ++sit) { + if(!sit->second.configured) + continue; + std::string satname = CServiceManager::getInstance()->GetSatelliteName(sit->first); + feSatSelect->addOption(satname.c_str()); + if (!sfound && strcmp(scansettings.satNameNoDiseqc, satname.c_str()) == 0) + sfound = true; + if (!sfound && !firstname.size()) + firstname = satname; + count++; + } + if(count && !sfound) + snprintf(scansettings.satNameNoDiseqc, sizeof(scansettings.satNameNoDiseqc), "%s", firstname.c_str()); + + sat_findMenu->addItem(feSatSelect); + sat_findMenu->addItem(new CMenuForwarder(LOCALE_SCANTS_SELECT_TP, true, NULL, new CTPSelectHandler()/*tpSelect*/, "test", CRCInput::RC_green, NEUTRINO_ICON_BUTTON_GREEN)); - sat_findMenu->addItem(GenericMenuSeparatorLine); //-------------------------------------------------------------- addScanOptionsItems(sat_findMenu); //-------------------------------------------------------------- sat_findMenu->addItem(GenericMenuSeparatorLine); + sat_findMenu->addItem(new CMenuForwarder(LOCALE_MOTORCONTROL_HEAD, allow_start, NULL, new CMotorControl(fenumber), "", CRCInput::RC_yellow, NEUTRINO_ICON_BUTTON_YELLOW)); - sat_findMenu->addItem(new CMenuForwarder(LOCALE_MOTORCONTROL_HEAD, true, NULL, new CMotorControl(), "", CRCInput::RC_yellow, NEUTRINO_ICON_BUTTON_YELLOW)); - - if (!sfound && satellitePositions.size()) { - sit = satellitePositions.begin(); - snprintf(scansettings.satNameNoDiseqc, sizeof(scansettings.satNameNoDiseqc), "%s", sit->second.name.c_str()); - } -} - -//init sat on off menu -void CScanSetup::addScanMenuSatOnOff(CMenuWidget *sat_OnOff) -{ - sat_OnOff->addIntroItems(); - //---------------------------------------------------------------------- - sat_OnOff->addItem(new CMenuOptionChooser(sit->second.name.c_str(), &sit->second.use_in_scan, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); + int res = sat_findMenu->exec(NULL, ""); + sat_findMenu->hide(); + delete sat_findMenu; + return res; } //init tempsat menu -void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat) +void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat, sat_config_t & satconfig) { temp_sat->addIntroItems(); - CMenuOptionNumberChooser *diseqc = new CMenuOptionNumberChooser(LOCALE_SATSETUP_DISEQC_INPUT, &sit->second.diseqc, ((dmode != NO_DISEQC) && (dmode != DISEQC_ADVANCED)), -1, 15, NULL, 1, -1, LOCALE_OPTIONS_OFF); - CMenuOptionNumberChooser *comm = new CMenuOptionNumberChooser(LOCALE_SATSETUP_COMM_INPUT, &sit->second.commited, dmode == DISEQC_ADVANCED, -1, 15, NULL, 1, -1, LOCALE_OPTIONS_OFF); - CMenuOptionNumberChooser *uncomm = new CMenuOptionNumberChooser(LOCALE_SATSETUP_UNCOMM_INPUT, &sit->second.uncommited, dmode == DISEQC_ADVANCED, -1, 15, NULL, 1, -1, LOCALE_OPTIONS_OFF); - //CMenuOptionNumberChooser *motor = new CMenuOptionNumberChooser(LOCALE_SATSETUP_MOTOR_POS, &sit->second.motor_position, dmode == DISEQC_ADVANCED, 0, 64, NULL, 0, 0, LOCALE_OPTIONS_OFF); - CMenuOptionNumberChooser *motor = new CMenuOptionNumberChooser(LOCALE_SATSETUP_MOTOR_POS, &sit->second.motor_position, true, 0, 64, NULL, 0, 0, LOCALE_OPTIONS_OFF); - //CMenuOptionChooser *usals = new CMenuOptionChooser(LOCALE_EXTRA_USE_GOTOXX, &sit->second.use_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, dmode == DISEQC_ADVANCED); - CMenuOptionChooser *usals = new CMenuOptionChooser(LOCALE_EXTRA_USE_GOTOXX, &sit->second.use_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true); - - if(!sit->second.use_usals) - all_usals = 0; - - satNotify->addItem(1, diseqc); - satNotify->addItem(0, comm); - satNotify->addItem(0, uncomm); - //satNotify->addItem(0, motor); //FIXME testing motor with not DISEQC_ADVANCED - //satNotify->addItem(0, usals); + CMenuOptionNumberChooser *diseqc = new CMenuOptionNumberChooser(LOCALE_SATSETUP_DISEQC_INPUT, &satconfig.diseqc, ((dmode != NO_DISEQC) && (dmode != DISEQC_ADVANCED)), -1, 15, NULL, 1, -1, LOCALE_OPTIONS_OFF); + CMenuOptionNumberChooser *comm = new CMenuOptionNumberChooser(LOCALE_SATSETUP_COMM_INPUT, &satconfig.commited, dmode == DISEQC_ADVANCED, -1, 15, NULL, 1, -1, LOCALE_OPTIONS_OFF); + CMenuOptionNumberChooser *uncomm = new CMenuOptionNumberChooser(LOCALE_SATSETUP_UNCOMM_INPUT, &satconfig.uncommited, dmode == DISEQC_ADVANCED, -1, 15, NULL, 1, -1, LOCALE_OPTIONS_OFF); + CMenuOptionNumberChooser *motor = new CMenuOptionNumberChooser(LOCALE_SATSETUP_MOTOR_POS, &satconfig.motor_position, true /*dmode == DISEQC_ADVANCED*/, 0, 64, NULL, 0, 0, LOCALE_OPTIONS_OFF); + CMenuOptionChooser *usals = new CMenuOptionChooser(LOCALE_EXTRA_USE_GOTOXX, &satconfig.use_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true /*dmode == DISEQC_ADVANCED*/); - CIntInput* lofL = new CIntInput(LOCALE_SATSETUP_LOFL, (int&) sit->second.lnbOffsetLow, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); - CIntInput* lofH = new CIntInput(LOCALE_SATSETUP_LOFH, (int&) sit->second.lnbOffsetHigh, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); - CIntInput* lofS = new CIntInput(LOCALE_SATSETUP_LOFS, (int&) sit->second.lnbSwitch, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); + if(!satconfig.use_usals) + all_usals = 0; + + itemsForAnyDiseqc.Add(diseqc); + itemsForAdvancedDiseqc.Add(comm); + itemsForAdvancedDiseqc.Add(uncomm); + + //FIXME testing motor without DISEQC_ADVANCED + //itemsForAdvancedDiseqc.Add(motor); + //itemsForAdvancedDiseqc.Add(usals); + + CIntInput* lofL = new CIntInput(LOCALE_SATSETUP_LOFL, (int&) satconfig.lnbOffsetLow, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); + CIntInput* lofH = new CIntInput(LOCALE_SATSETUP_LOFH, (int&) satconfig.lnbOffsetHigh, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); + CIntInput* lofS = new CIntInput(LOCALE_SATSETUP_LOFS, (int&) satconfig.lnbSwitch, 5, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE); temp_sat->addItem(diseqc); temp_sat->addItem(comm); @@ -575,45 +729,6 @@ void CScanSetup::addScanMenuTempSat(CMenuWidget *temp_sat) temp_sat->addItem(new CMenuForwarder(LOCALE_SATSETUP_LOFS, true, lofS->getValue(), lofS)); } -//init motor settings -void CScanSetup::addScanMenuMotorMenu(CMenuWidget *motor_Menu) -{ - printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); - motor_Menu->addIntroItems(); - - CMenuWidget* satfindMenu = new CMenuWidget(LOCALE_MOTORCONTROL_HEAD, NEUTRINO_ICON_SETTINGS, width); - addScanMenuSatFind(satfindMenu); - motor_Menu->addItem(new CMenuForwarder(LOCALE_MOTORCONTROL_HEAD, true, NULL, satfindMenu, "", CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED)); - - //---------------------------------------------------------------------- - motor_Menu->addItem(GenericMenuSeparatorLine); - //---------------------------------------------------------------------- - - motor_Menu->addItem(new CMenuOptionNumberChooser(LOCALE_EXTRA_ZAPIT_MOTOR_SPEED, (int *)&zapitCfg.motorRotationSpeed, true, 0, 64, NULL) ); - motor_Menu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_ZAPIT_HVOLTAGE, (int *)&zapitCfg.highVoltage, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); - //motor_Menu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_USE_GOTOXX, (int *)&zapitCfg.useGotoXX, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); - - CStringInput *toff = NULL; - sprintf(zapit_lat, "%02.6f", zapitCfg.gotoXXLatitude); - sprintf(zapit_long, "%02.6f", zapitCfg.gotoXXLongitude); - - motor_Menu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_LADIRECTION, (int *)&zapitCfg.gotoXXLaDirection, OPTIONS_SOUTH0_NORTH1_OPTIONS, OPTIONS_SOUTH0_NORTH1_OPTION_COUNT, true)); - - toff = new CStringInput(LOCALE_EXTRA_LATITUDE, (char *) zapit_lat, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); - motor_Menu->addItem(new CMenuForwarder(LOCALE_EXTRA_LATITUDE, true, zapit_lat, toff)); - - motor_Menu->addItem(new CMenuOptionChooser(LOCALE_EXTRA_LODIRECTION, (int *)&zapitCfg.gotoXXLoDirection, OPTIONS_EAST0_WEST1_OPTIONS, OPTIONS_EAST0_WEST1_OPTION_COUNT, true)); - - toff = new CStringInput(LOCALE_EXTRA_LONGITUDE, (char *) zapit_long, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); - motor_Menu->addItem(new CMenuForwarder(LOCALE_EXTRA_LONGITUDE, true, zapit_long, toff)); - - motor_Menu->addItem(new CMenuOptionNumberChooser(LOCALE_SATSETUP_USALS_REPEAT, (int *)&zapitCfg.repeatUsals, true, 0, 10, NULL, 0, 0, LOCALE_OPTIONS_OFF) ); - - CMenuOptionChooser * allusals = new CMenuOptionChooser(LOCALE_SATSETUP_USE_USALS, &all_usals, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, usalsNotify); - motor_Menu->addItem(allusals); - -} - //init manual scan menu void CScanSetup::addScanMenuManualScan(CMenuWidget *manual_Scan) { @@ -642,22 +757,7 @@ void CScanSetup::addScanMenuAutoScanAll(CMenuWidget *auto_ScanAll) printf("[neutrino] CScanSetup call %s...\n", __FUNCTION__); auto_ScanAll->addIntroItems(); //---------------------------------------------------------------------- - CMenuWidget* satInUse = new CMenuWidget(satprov_locale, NEUTRINO_ICON_SETTINGS, width); - satInUse->addIntroItems(); - - //ensure, that we have no double options in satlist - satSelect->removeOptions(); - - for (sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) - { - satSelect->addOption(sit->second.name.c_str()); - if (strcmp(scansettings.satNameNoDiseqc,sit->second.name.c_str()) == 0) - sfound = 1; - - satInUse->addItem(new CMenuOptionChooser(sit->second.name.c_str(), &sit->second.use_in_scan, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true)); - } - - auto_ScanAll->addItem(new CMenuForwarder(satprov_locale, true, NULL, satInUse, "", CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED)); + auto_ScanAll->addItem(new CMenuForwarder(satprov_locale, true, NULL, satOnOff, "", CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED)); auto_ScanAll->addItem(GenericMenuSeparatorLine); //---------------------------------------------------------------------- @@ -668,6 +768,22 @@ void CScanSetup::addScanMenuAutoScanAll(CMenuWidget *auto_ScanAll) } #ifdef ENABLE_FASTSCAN +#define FAST_SCAN_OPTIONS_COUNT 2 +const CMenuOptionChooser::keyval FAST_SCAN_OPTIONS[FAST_SCAN_OPTIONS_COUNT] = +{ + { FAST_SCAN_SD, LOCALE_SATSETUP_FASTSCAN_SD }, + { FAST_SCAN_HD, LOCALE_SATSETUP_FASTSCAN_HD } + /*{ FAST_SCAN_ALL, LOCALE_SATSETUP_FASTSCAN_ALL }*/ +}; + +#define FAST_SCAN_PROV_OPTIONS_COUNT 3 +const CMenuOptionChooser::keyval FAST_SCAN_PROV_OPTIONS[FAST_SCAN_PROV_OPTIONS_COUNT] = +{ + { OPERATOR_CD, LOCALE_SATSETUP_FASTSCAN_PROV_CD }, + { OPERATOR_TVV, LOCALE_SATSETUP_FASTSCAN_PROV_TVV }, + { OPERATOR_TELESAT, LOCALE_SATSETUP_FASTSCAN_PROV_TELESAT } +}; + //init fast scan menu void CScanSetup::addScanMenuFastScan(CMenuWidget *fast_ScanMenu) { @@ -699,7 +815,6 @@ void CScanSetup::addScanMenuAutoScan(CMenuWidget *auto_Scan) //---------------------------------------------------------------------- auto_Scan->addItem(GenericMenuSeparatorLine); auto_Scan->addItem(new CMenuForwarder(LOCALE_SCANTS_STARTNOW, allow_start, NULL, this, "auto", CRCInput::RC_green, NEUTRINO_ICON_BUTTON_GREEN)); - } //create scan options items @@ -766,9 +881,84 @@ void CScanSetup::saveScanSetup() zapitCfg.gotoXXLongitude = strtod(zapit_long, NULL); CZapit::getInstance()->SetConfig(&zapitCfg); + CFEManager::getInstance()->saveSettings(true); } +bool CScanSetup::changeNotify(const neutrino_locale_t OptionName, void * /*data*/) +{ + if(ARE_LOCALES_EQUAL(OptionName, LOCALE_SATSETUP_USE_USALS)) { + CFrontend * fe = CFEManager::getInstance()->getFE(fenumber); + printf("[neutrino] CScanSetup::%s: all usals %d \n", __FUNCTION__, all_usals); + satellite_map_t & satmap = fe->getSatellites(); + for (sat_iterator_t sit = satmap.begin(); sit != satmap.end(); sit++) { + sit->second.use_usals = all_usals; + } + } + else if(ARE_LOCALES_EQUAL(OptionName, LOCALE_SATSETUP_DISEQC)) { + printf("[neutrino] CScanSetup::%s: diseqc %d \n", __FUNCTION__, dmode); + //FIXME 2 frontends ?? + fautoScanAll->setActive(dmode != NO_DISEQC); + if(dmode == NO_DISEQC) { + itemsForAdvancedDiseqc.Activate(false); + itemsForNonAdvancedDiseqc.Activate(false); + itemsForAnyDiseqc.Activate(false); + } + else if(dmode < DISEQC_ADVANCED) { + itemsForAdvancedDiseqc.Activate(false); + itemsForNonAdvancedDiseqc.Activate(true); + itemsForAnyDiseqc.Activate(true); + } + else if(dmode == DISEQC_ADVANCED) { + itemsForAdvancedDiseqc.Activate(true); + itemsForNonAdvancedDiseqc.Activate(false); + itemsForAnyDiseqc.Activate(true); + } + CFrontend * fe = CFEManager::getInstance()->getFE(fenumber); + fe->setDiseqcType((diseqc_t) dmode); + } + else if(ARE_LOCALES_EQUAL(OptionName, LOCALE_SATSETUP_FE_MODE)) { + printf("[neutrino] CScanSetup::%s: fe mode %d \n", __FUNCTION__, femode); + /* cable dont have this menu */ + if(frontendSetup) + frontendSetup->setActive(femode == CFEManager::FE_MODE_ALONE); + CFEManager::getInstance()->setMode((CFEManager::fe_mode_t) femode); + /* to copy settings from fe0 */ + if(femode != CFEManager::FE_MODE_ALONE) + CFEManager::getInstance()->saveSettings(true); + fillSatSelect(); + } + return true; +} +void CScanSetup::updateManualSettings() +{ + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if(channel) { + strncpy(scansettings.satNameNoDiseqc, + CServiceManager::getInstance()->GetSatelliteName(channel->getSatellitePosition()).c_str(), 50); + transponder_list_t::iterator tI; + tI = transponders.find(channel->getTransponderId()); + if(tI != transponders.end()) { + sprintf(scansettings.TP_freq, "%d", tI->second.feparams.frequency); + CFrontend * frontend = CFEManager::getInstance()->getLiveFE(); + switch (frontend->getInfo()->type) { + case FE_QPSK: + sprintf(scansettings.TP_rate, "%d", tI->second.feparams.u.qpsk.symbol_rate); + scansettings.TP_fec = tI->second.feparams.u.qpsk.fec_inner; + scansettings.TP_pol = tI->second.polarization; + break; + case FE_QAM: + sprintf(scansettings.TP_rate, "%d", tI->second.feparams.u.qam.symbol_rate); + scansettings.TP_fec = tI->second.feparams.u.qam.fec_inner; + scansettings.TP_mod = tI->second.feparams.u.qam.modulation; + break; + case FE_OFDM: + case FE_ATSC: + break; + } + } + } +} int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/) { @@ -782,18 +972,13 @@ int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/ static int old_selected = 0; static t_satellite_position old_position = 0; + int width = w_max (40, 10); + if (parent) parent->hide(); - for (sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) - { - if (!strcmp(sit->second.name.c_str(), scansettings.satNameNoDiseqc)) - { - position = sit->first; - break; - } - } - + position = CServiceManager::getInstance()->GetSatellitePosition(scansettings.satNameNoDiseqc); + if (old_position != position) { old_selected = 0; @@ -803,9 +988,10 @@ int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/ CMenuWidget menu(LOCALE_SCANTS_SELECT_TP, NEUTRINO_ICON_SETTINGS, width); CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select); menu.addIntroItems(NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, CMenuWidget::BTN_TYPE_CANCEL); //add cancel button, ensures that we have enought space left from item caption - + + CFrontend * frontend = CFEManager::getInstance()->getLiveFE(); i = 0; - for (tI = select_transponders.begin(); tI != select_transponders.end(); tI++) + for (tI = select_transponders.begin(); tI != select_transponders.end(); ++tI) { t_satellite_position satpos = GET_SATELLITEPOSITION_FROM_TRANSPONDER_ID(tI->first) & 0xFFF; if (GET_SATELLITEPOSITION_FROM_TRANSPONDER_ID(tI->first) & 0xF000) @@ -816,14 +1002,14 @@ int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/ char buf[128]; sprintf(cnt, "%d", i); char * f, *s, *m; - switch (CFrontend::getInstance()->getInfo()->type) + switch (frontend->getInfo()->type) { case FE_QPSK: - CFrontend::getInstance()->getDelSys(tI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tI->second.feparams.u.qpsk.fec_inner), f, s, m); + frontend->getDelSys(tI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tI->second.feparams.u.qpsk.fec_inner), f, s, m); snprintf(buf, sizeof(buf), "%d %c %d %s %s %s ", tI->second.feparams.frequency/1000, tI->second.polarization ? 'V' : 'H', tI->second.feparams.u.qpsk.symbol_rate/1000, f, s, m); break; case FE_QAM: - CFrontend::getInstance()->getDelSys(tI->second.feparams.u.qam.fec_inner, tI->second.feparams.u.qam.modulation, f, s, m); + frontend->getDelSys(tI->second.feparams.u.qam.fec_inner, tI->second.feparams.u.qam.modulation, f, s, m); snprintf(buf, sizeof(buf), "%d %d %s %s %s ", tI->second.feparams.frequency/1000, tI->second.feparams.u.qam.symbol_rate/1000, f, s, m); break; case FE_OFDM: @@ -854,12 +1040,12 @@ int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/ ShowHintUTF(LOCALE_MESSAGEBOX_ERROR, text.c_str(), 450, 2); return menu_return::RETURN_REPAINT; } - + menu.setSelected(old_selected); int retval = menu.exec(NULL, ""); delete selector; - + if (select >= 0) { old_selected = select; @@ -871,7 +1057,7 @@ int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/ sprintf(scansettings.TP_freq, "%d", tmpI->second.feparams.frequency); - switch (CFrontend::getInstance()->getInfo()->type) + switch (frontend->getInfo()->type) { case FE_QPSK: sprintf(scansettings.TP_rate, "%d", tmpI->second.feparams.u.qpsk.symbol_rate); @@ -889,10 +1075,9 @@ int CTPSelectHandler::exec(CMenuTarget* parent, const std::string &/*actionkey*/ } } - + if (retval == menu_return::RETURN_EXIT_ALL) return menu_return::RETURN_EXIT_ALL; return menu_return::RETURN_REPAINT; } - diff --git a/src/gui/scan_setup.h b/src/gui/scan_setup.h index e4a47b62d..18821d841 100644 --- a/src/gui/scan_setup.h +++ b/src/gui/scan_setup.h @@ -35,7 +35,7 @@ #include #include - +#include #include @@ -43,39 +43,56 @@ #define ENABLE_FASTSCAN //don't define this to remove fast scan menu -class CScanSetup : public CMenuTarget +class CScanSetup : public CMenuTarget, public CChangeObserver { protected: int width; private: - CSatelliteSetupNotifier *satNotify; - CAllUsalsNotifier *usalsNotify; - CMenuOptionStringChooser *satSelect; - + CMenuWidget *satOnOff; + + /* global items to be enabled/disabled in notify */ + CMenuForwarder *fautoScanAll; + CMenuForwarder *frontendSetup; + CMenuForwarder *fsatSetup; + + /* dynamic frontend items to be enabled/disabled in notify */ + CGenericMenuActivate itemsForAdvancedDiseqc; + CGenericMenuActivate itemsForNonAdvancedDiseqc; + CGenericMenuActivate itemsForAnyDiseqc; + + /* variables for selected frontend */ + /* diseqc mode */ + int dmode; + int fenumber; + + /* flag to allow any operations which can damage recordings */ + bool allow_start; + bool is_wizard; int selected; - int dmode; - int sfound; + int fselected; int fec_count; int freq_length; int r_system; - bool allow_start; - + int femode; + neutrino_locale_t satprov_locale; - + uint getSatMenuListWidth(); - + int showScanMenu(); - - void addScanMenuLnbSetup(CMenuWidget *sat_setup); - void addScanMenuProvider(CMenuWidget *provider_setup); - void addScanMenuSatFind(CMenuWidget *sat_findMenu); - void addScanMenuSatOnOff(CMenuWidget *sat_OnOff); - void addScanMenuTempSat(CMenuWidget *temp_sat); - void addScanMenuMotorMenu(CMenuWidget *motor_Menu); + + int showFrontendSetup(int number); + int showScanMenuLnbSetup(); + int showScanMenuSatFind(); + void fillSatSelect(); + void fillCableSelect(); + + void addScanMenuFrontendSetup(CMenuWidget *settings); + void addScanMenuTempSat(CMenuWidget *temp_sat, sat_config_t &satconfig); void addScanMenuManualScan(CMenuWidget *manual_Scan); void addScanMenuAutoScanAll(CMenuWidget *auto_ScanAll); #ifdef ENABLE_FASTSCAN @@ -85,28 +102,30 @@ class CScanSetup : public CMenuTarget int addScanOptionsItems(CMenuWidget *options_menu, const int &shortcut = 1); int addListFlagsItems(CMenuWidget *listflags_menu, const int &shortcut = 1); - + void saveScanSetup(); + CScanSetup(bool wizard_mode = SCAN_SETUP_MODE_WIZARD_NO); public: enum SCAN_SETUP_MODE { SCAN_SETUP_MODE_WIZARD_NO = 0, SCAN_SETUP_MODE_WIZARD = 1 }; - - CScanSetup(bool wizard_mode = SCAN_SETUP_MODE_WIZARD_NO); + ~CScanSetup(); - + static CScanSetup* getInstance(); - + bool getWizardMode() {return is_wizard;}; void setWizardMode(bool mode); + void updateManualSettings(); int exec(CMenuTarget* parent, const std::string & actionKey = ""); + bool changeNotify(const neutrino_locale_t OptionName, void * /*data*/); }; -class CTPSelectHandler : public CScanSetup +class CTPSelectHandler : public CMenuTarget //CScanSetup { public: int exec(CMenuTarget* parent, const std::string &actionkey); From f42a0e2f8dc2e9cc2499dfb88d5c41d020bcdf9d Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:48:10 +0400 Subject: [PATCH 011/737] locale: add new locales for scan setup, CI clock, cable NID --- data/locale/english.locale | 9 +++++++++ src/system/locals.h | 12 ++++++++++++ src/system/locals_intern.h | 12 ++++++++++++ 3 files changed, 33 insertions(+) diff --git a/data/locale/english.locale b/data/locale/english.locale index e00b90e4d..6cf86290d 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -214,6 +214,7 @@ channellist.sats Satellites channellist.since since channellist.start starts ci.empty No CAM in slot +ci.clock CI clock (Mhz) ci.init_failed CAM init failed ci.init_ok CAM init complete ci.inserted CAM inserted in slot @@ -1109,6 +1110,7 @@ reset_settings Reset settings to defaults satsetup.auto_scan Auto-Scan selected %s satsetup.auto_scan_all Auto-Scan multiple Satellites satsetup.comm_input Commited input +satsetup.cable_nid Network ID satsetup.diseqc DiSEqC satsetup.diseqc10 DiSEqC 1.0 satsetup.diseqc11 DiSEqC 1.1 @@ -1393,3 +1395,10 @@ zapitsetup.last_radio Radio Channel zapitsetup.last_tv TV Channel zapitsetup.last_use from last Channel zaptotimer.announce Zapto timer in one minute +satsetup.fe_setup Setup tuner +satsetup.fe_mode Tuner mode +satsetup.fe_mode_single single +satsetup.fe_mode_loop loop +satsetup.fe_mode_twin twin +satsetup.fe_mode_alone independent +satsetup.select_sat Select satellites diff --git a/src/system/locals.h b/src/system/locals.h index 4465fdebb..c76d30e87 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -240,6 +240,7 @@ typedef enum LOCALE_CHANNELLIST_SATS, LOCALE_CHANNELLIST_SINCE, LOCALE_CHANNELLIST_START, + LOCALE_CI_CLOCK, LOCALE_CI_EMPTY, LOCALE_CI_INIT_FAILED, LOCALE_CI_INIT_OK, @@ -1136,6 +1137,7 @@ typedef enum LOCALE_SATSETUP_AUTO_SCAN, LOCALE_SATSETUP_AUTO_SCAN_ALL, LOCALE_SATSETUP_COMM_INPUT, + LOCALE_SATSETUP_CABLE_NID, LOCALE_SATSETUP_DISEQC, LOCALE_SATSETUP_DISEQC10, LOCALE_SATSETUP_DISEQC11, @@ -1156,6 +1158,16 @@ typedef enum LOCALE_SATSETUP_FASTSCAN_PROV_TVV, LOCALE_SATSETUP_FASTSCAN_SD, LOCALE_SATSETUP_FASTSCAN_TYPE, + + LOCALE_SATSETUP_FE_SETUP, + LOCALE_SATSETUP_FE_MODE, + LOCALE_SATSETUP_FE_MODE_SINGLE, + LOCALE_SATSETUP_FE_MODE_LOOP, + LOCALE_SATSETUP_FE_MODE_TWIN, + LOCALE_SATSETUP_FE_MODE_ALONE, + LOCALE_SATSETUP_CONFIGURE_SAT, + LOCALE_SATSETUP_SELECT_SAT, + LOCALE_SATSETUP_LOFH, LOCALE_SATSETUP_LOFL, LOCALE_SATSETUP_LOFS, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index 9476ca317..f90f973be 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -240,6 +240,7 @@ const char * locale_real_names[] = "channellist.sats", "channellist.since", "channellist.start", + "ci.clock", "ci.empty", "ci.init_failed", "ci.init_ok", @@ -1136,6 +1137,7 @@ const char * locale_real_names[] = "satsetup.auto_scan", "satsetup.auto_scan_all", "satsetup.comm_input", + "satsetup.cable_nid", "satsetup.diseqc", "satsetup.diseqc10", "satsetup.diseqc11", @@ -1156,6 +1158,16 @@ const char * locale_real_names[] = "satsetup.fastscan_prov_tvv", "satsetup.fastscan_sd", "satsetup.fastscan_type", + + "satsetup.fe_setup", + "satsetup.fe_mode", + "satsetup.fe_mode_single", + "satsetup.fe_mode_loop", + "satsetup.fe_mode_twin", + "satsetup.fe_mode_alone", + "satsetup.configure_sat", + "satsetup.select_sat", + "satsetup.lofh", "satsetup.lofl", "satsetup.lofs", From 40ec967468cd9e1e2cc2152358761bdde23342ba Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:49:04 +0400 Subject: [PATCH 012/737] setting_helpers: cleanup unused code --- src/system/setting_helpers.cpp | 317 +-------------------------------- src/system/setting_helpers.h | 64 ++----- 2 files changed, 15 insertions(+), 366 deletions(-) diff --git a/src/system/setting_helpers.cpp b/src/system/setting_helpers.cpp index cdac93341..2cfa96aa5 100644 --- a/src/system/setting_helpers.cpp +++ b/src/system/setting_helpers.cpp @@ -90,160 +90,6 @@ extern cDemux *pcrDemux; extern "C" int pinghost( const char *hostname ); -CSatelliteSetupNotifier::CSatelliteSetupNotifier() -{ -} - -/* items1 enabled for advanced diseqc settings, items2 for diseqc != NO_DISEQC, items3 disabled for NO_DISEQC */ -bool CSatelliteSetupNotifier::changeNotify(const neutrino_locale_t, void * Data) -{ - std::vector::iterator it; - int type = *((int*) Data); - - if (type == NO_DISEQC) { - for(it = items1.begin(); it != items1.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(false); - } - for(it = items2.begin(); it != items2.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(false); - } - for(it = items3.begin(); it != items3.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(false); - } - } - else if(type < DISEQC_ADVANCED) { - for(it = items1.begin(); it != items1.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(false); - } - for(it = items2.begin(); it != items2.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(true); - } - for(it = items3.begin(); it != items3.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(true); - } - } - else if(type == DISEQC_ADVANCED) { - for(it = items1.begin(); it != items1.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(true); - } - for(it = items2.begin(); it != items2.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(false); - } - for(it = items3.begin(); it != items3.end(); it++) { - //(*it)->init(-1, 0, 0, 0); - (*it)->setActive(true); - } - } - g_Zapit->setDiseqcType((diseqc_t) type); - g_Zapit->setDiseqcRepeat( CNeutrinoApp::getInstance()->getScanSettings().diseqcRepeat); - return true; -} - -void CSatelliteSetupNotifier::addItem(int list, CMenuItem* item) -{ - switch(list) { - case 0: - items1.push_back(item); - break; - case 1: - items2.push_back(item); - break; - case 2: - items3.push_back(item); - break; - default: - break; - } -} - -bool CSatDiseqcNotifier::changeNotify(const neutrino_locale_t, void * Data) -{ - if (*((int*) Data) == NO_DISEQC) - { - satMenu->setActive(true); - extMenu->setActive(false); - extMotorMenu->setActive(false); - repeatMenu->init(-1, 0, 0, 0); - repeatMenu->setActive(false); - motorControl->setActive(false); - } - else - if (*((int*) Data) == DISEQC_1_2) - { - satMenu->setActive(true); - extMenu->setActive(true); - extMotorMenu->setActive(true); - repeatMenu->init(-1, 0, 0, 0); - repeatMenu->setActive(true); - motorControl->setActive(true); - } - else - { - satMenu->setActive(true); - extMenu->setActive(true); - extMotorMenu->setActive(false); - repeatMenu->init(-1, 0, 0, 0); - repeatMenu->setActive((*((int*) Data) != DISEQC_1_0)); - motorControl->setActive(false); - } - g_Zapit->setDiseqcType( *((diseqc_t*) Data) ); - g_Zapit->setDiseqcRepeat( CNeutrinoApp::getInstance()->getScanSettings().diseqcRepeat); - return true; -} - -CTP_scanNotifier::CTP_scanNotifier(CMenuOptionChooser* i1, CMenuOptionChooser* i2, CMenuForwarder* i3, CMenuForwarder* i4) -{ - toDisable1[0]=i1; - toDisable1[1]=i2; - toDisable2[0]=i3; - toDisable2[1]=i4; -} - -bool CTP_scanNotifier::changeNotify(const neutrino_locale_t, void * Data) -{ - int val = *((int*) Data); -//printf("CTP_scanNotifier::changeNotify: data %d\n", val); -//FIXME: test - //bool set_true_false=CNeutrinoApp::getInstance()->getScanSettings().TP_scan; - bool set_true_false = (val == 2); - for (int i=0; i<2; i++) - { - toDisable1[i]->setActive(set_true_false); - toDisable2[i]->setActive(set_true_false); - } - return true; -} - -#if 0 // not used -CDHCPNotifier::CDHCPNotifier( CMenuForwarder* a1, CMenuForwarder* a2, CMenuForwarder* a3, CMenuForwarder* a4, CMenuForwarder* a5, CMenuForwarder* a6) -{ - toDisable[0] = a1; - toDisable[1] = a2; - toDisable[2] = a3; - toDisable[3] = a4; - toDisable[4] = a5; - toEnable[0] = a6; -} - - -bool CDHCPNotifier::changeNotify(const neutrino_locale_t, void * data) -{ - CNetworkConfig::getInstance()->inet_static = ((*(int*)(data)) == 0); - for(int x=0;x<5;x++) - toDisable[x]->setActive(CNetworkConfig::getInstance()->inet_static); - - toEnable[0]->setActive(!CNetworkConfig::getInstance()->inet_static); - return true; -} -#endif COnOffNotifier::COnOffNotifier( CMenuItem* a1,CMenuItem* a2,CMenuItem* a3,CMenuItem* a4,CMenuItem* a5) { number = 0; @@ -275,6 +121,7 @@ bool CRecordingSafetyNotifier::changeNotify(const neutrino_locale_t, void *) return true; } +//used in gui/miscsettings_menu.cpp CMiscNotifier::CMiscNotifier( CMenuItem* i1, CMenuItem* i2) { toDisable[0]=i1; @@ -440,7 +287,7 @@ bool CAudioSetupNotifier::changeNotify(const neutrino_locale_t OptionName, void //FIXME #define IOC_IR_SET_F_DELAY _IOW(0xDD, 5, unsigned int) /* set the delay time before the first repetition */ #define IOC_IR_SET_X_DELAY _IOW(0xDD, 6, unsigned int) /* set the delay time between all other repetitions */ - +//used ./gui/keybind_setup.cpp bool CKeySetupNotifier::changeNotify(const neutrino_locale_t, void *) { unsigned int fdelay = atoi(g_settings.repeat_blocker); @@ -455,26 +302,7 @@ bool CKeySetupNotifier::changeNotify(const neutrino_locale_t, void *) return false; } -#if 0 // not used -bool CIPChangeNotifier::changeNotify(const neutrino_locale_t, void * Data) -{ - char ip[16]; - unsigned char _ip[4]; - sscanf((char*) Data, "%hhu.%hhu.%hhu.%hhu", &_ip[0], &_ip[1], &_ip[2], &_ip[3]); - - sprintf(ip, "%hhu.%hhu.%hhu.255", _ip[0], _ip[1], _ip[2]); - CNetworkConfig::getInstance()->broadcast = ip; - - CNetworkConfig::getInstance()->netmask = (_ip[0] == 10) ? "255.0.0.0" : "255.255.255.0"; - - sprintf(ip, "%hhu.%hhu.%hhu.1", _ip[0], _ip[1], _ip[2]); - CNetworkConfig::getInstance()->nameserver = ip; - CNetworkConfig::getInstance()->gateway = ip; - - return true; -} -#endif - +// used in ./gui/osd_setup.cpp: bool CTimingSettingsNotifier::changeNotify(const neutrino_locale_t OptionName, void *) { for (int i = 0; i < SNeutrinoSettings::TIMING_SETTING_COUNT; i++) @@ -488,6 +316,7 @@ bool CTimingSettingsNotifier::changeNotify(const neutrino_locale_t OptionName, v return false; } +// used in ./gui/osd_setup.cpp: bool CFontSizeNotifier::changeNotify(const neutrino_locale_t, void *) { CHintBox hintBox(LOCALE_MESSAGEBOX_INFO, g_Locale->getText(LOCALE_FONTSIZE_HINT)); // UTF-8 @@ -703,130 +532,6 @@ std::string CNetAdapter::getMacAddr(void) } } -#if 0 // not used, moved to gui/network_setup.cpp -const char * mypinghost(const char * const host) -{ - int retvalue = pinghost(host); - switch (retvalue) - { - case 1: return (g_Locale->getText(LOCALE_PING_OK)); - case 0: return (g_Locale->getText(LOCALE_PING_UNREACHABLE)); - case -1: return (g_Locale->getText(LOCALE_PING_PROTOCOL)); - case -2: return (g_Locale->getText(LOCALE_PING_SOCKET)); - } - return ""; -} - - -void testNetworkSettings(const char* ip, const char* netmask, const char* broadcast, const char* gateway, const char* nameserver, bool ip_static) -{ - char our_ip[16]; - char our_mask[16]; - char our_broadcast[16]; - char our_gateway[16]; - char our_nameserver[16]; - std::string text, ethID, testsite; - //set default testdomain and wiki-IP - std::string defaultsite = "www.google.de", wiki_IP = "89.31.143.1"; - - //set physical adress - static CNetAdapter netadapter; ethID=netadapter.getMacAddr(); - - //get www-domain testsite from /.version - CConfigFile config('\t'); - config.loadConfig("/.version"); - testsite = config.getString("homepage",defaultsite); - testsite.replace( 0, testsite.find("www",0), "" ); - - //use default testdomain if testsite missing - if (testsite.length()==0) testsite = defaultsite; - - if (ip_static) - { - strcpy(our_ip, ip); - strcpy(our_mask, netmask); - strcpy(our_broadcast, broadcast); - strcpy(our_gateway, gateway); - strcpy(our_nameserver, nameserver); - } - else - { - char eth[] = "eth0"; - netGetIP(eth, our_ip, our_mask, our_broadcast); - netGetDefaultRoute(our_gateway); - netGetNameserver(our_nameserver); - } - - printf("testNw IP: %s\n", our_ip); - printf("testNw MAC-address: %s\n", ethID.c_str()); - printf("testNw Netmask: %s\n", our_mask); - printf("testNw Broadcast: %s\n", our_broadcast); - printf("testNw Gateway: %s\n", our_gateway); - printf("testNw Nameserver: %s\n", our_nameserver); - printf("testNw Testsite %s\n", testsite.c_str()); - - if (our_ip[0] == 0) - { - text = g_Locale->getText(LOCALE_NETWORKMENU_INACTIVE_NETWORK); - } - else - { - text = "Box: " + ethID + "\n "; - text += (std::string)our_ip + " " + (std::string)mypinghost(our_ip); - text += "\n"; - text += g_Locale->getText(LOCALE_NETWORKMENU_GATEWAY); - text += " (Router)\n "; - text += (std::string)our_gateway + " " +(std::string)mypinghost(our_gateway); - text += "\n"; - text += g_Locale->getText(LOCALE_NETWORKMENU_NAMESERVER); - text += "\n "; - text += (std::string)our_nameserver + " " + (std::string)mypinghost(our_nameserver); - text += "\n"; - text += "wiki.neutrino-hd.de:\n "; - text += "via IP (" + wiki_IP + "): " + (std::string)mypinghost(wiki_IP.c_str()); - text += ":\n "; - if (1 == pinghost(our_nameserver)) - { - text += "via DNS: " + (std::string)mypinghost("wiki.neutrino-hd.de"); - text += "\n"; - text += testsite + ":\n "; - text += "via DNS: " + (std::string)mypinghost(testsite.c_str()) + ":\n"; - } - } - - ShowMsgUTF(LOCALE_NETWORKMENU_TEST, text, CMessageBox::mbrBack, CMessageBox::mbBack); // UTF-8 -} - -void showCurrentNetworkSettings() -{ - char ip[16]; - char mask[16]; - char broadcast[16]; - char router[16]; - char nameserver[16]; - std::string text; - char eth[] = "eth0"; - netGetIP(eth, ip, mask, broadcast); - if (ip[0] == 0) { - text = g_Locale->getText(LOCALE_NETWORKMENU_INACTIVE_NETWORK); - } - else { - netGetNameserver(nameserver); - netGetDefaultRoute(router); - CNetworkConfig networkConfig; - std::string dhcp = networkConfig.inet_static ? g_Locale->getText(LOCALE_OPTIONS_OFF) : g_Locale->getText(LOCALE_OPTIONS_ON); - - text = (std::string)g_Locale->getText(LOCALE_NETWORKMENU_DHCP) + ": " + dhcp + '\n' - + g_Locale->getText(LOCALE_NETWORKMENU_IPADDRESS ) + ": " + ip + '\n' - + g_Locale->getText(LOCALE_NETWORKMENU_NETMASK ) + ": " + mask + '\n' - + g_Locale->getText(LOCALE_NETWORKMENU_BROADCAST ) + ": " + broadcast + '\n' - + g_Locale->getText(LOCALE_NETWORKMENU_NAMESERVER) + ": " + nameserver + '\n' - + g_Locale->getText(LOCALE_NETWORKMENU_GATEWAY ) + ": " + router; - } - ShowMsgUTF(LOCALE_NETWORKMENU_SHOW, text, CMessageBox::mbrBack, CMessageBox::mbBack); // UTF-8 -} -#endif - uint64_t getcurrenttime() { struct timeval tv; @@ -963,18 +668,6 @@ printf("CScreenPresetNotifier::changeNotify preset %d (setting %d)\n", preset, g return true; } #endif -bool CAllUsalsNotifier::changeNotify(const neutrino_locale_t /*OptionName*/, void * data) -{ - int onoff = * (int *) data; -printf("CAllUsalsNotifier::changeNotify: %s\n", onoff ? "ON" : "OFF"); - - sat_iterator_t sit; - - for (sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { - sit->second.use_usals = onoff; - } - return true; -} extern CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[]; bool CAutoModeNotifier::changeNotify(const neutrino_locale_t /*OptionName*/, void * /* data */) @@ -1031,5 +724,3 @@ int check_dir(const char * newdir) } return 1; // error } - - diff --git a/src/system/setting_helpers.h b/src/system/setting_helpers.h index ab5bed395..2224bebaa 100644 --- a/src/system/setting_helpers.h +++ b/src/system/setting_helpers.h @@ -39,53 +39,21 @@ uint64_t getcurrenttime(); -class CSatelliteSetupNotifier : public CChangeObserver +class CGenericMenuActivate { private: - std::vector items1; - std::vector items2; - std::vector items3; + std::vector items; public: - CSatelliteSetupNotifier(); - void addItem(int list, CMenuItem* item); - bool changeNotify(const neutrino_locale_t, void * Data); -}; + CGenericMenuActivate() {}; + ~CGenericMenuActivate() { items.clear(); }; -class CSatDiseqcNotifier : public CChangeObserver -{ - private: - CMenuItem* satMenu; - CMenuItem* extMenu; - CMenuItem* extMotorMenu; - CMenuItem* repeatMenu; - CMenuItem* motorControl; - protected: - CSatDiseqcNotifier( ) : CChangeObserver(){}; // prevent calling constructor without data we need - public: - CSatDiseqcNotifier( CMenuItem* SatMenu, CMenuItem* ExtMenu, CMenuItem* ExtMotorMenu, CMenuItem* RepeatMenu, CMenuItem* MotorControl) : CChangeObserver() - { satMenu = SatMenu; extMenu = ExtMenu; extMotorMenu = ExtMotorMenu; repeatMenu = RepeatMenu; motorControl = MotorControl;}; - bool changeNotify(const neutrino_locale_t, void * Data); -}; - -class CTP_scanNotifier : public CChangeObserver -{ - private: - CMenuOptionChooser* toDisable1[2]; - CMenuForwarder* toDisable2[2]; - - public: - CTP_scanNotifier(CMenuOptionChooser*, CMenuOptionChooser*, CMenuForwarder*, CMenuForwarder*); - bool changeNotify(const neutrino_locale_t, void * Data); -}; - -class CDHCPNotifier : public CChangeObserver -{ - private: - CMenuForwarder* toDisable[5]; - CMenuForwarder* toEnable[1]; - public: - CDHCPNotifier( CMenuForwarder*, CMenuForwarder*, CMenuForwarder*, CMenuForwarder*, CMenuForwarder*, CMenuForwarder*); - bool changeNotify(const neutrino_locale_t, void * data); + void Add(CMenuItem* item) { items.push_back(item); } + void Clear() { items.clear(); } + void Activate(bool enable) + { + for(std::vector::iterator it = items.begin(); it != items.end(); it++) + (*it)->setActive(enable); + } }; class COnOffNotifier : public CChangeObserver @@ -220,12 +188,9 @@ class CUCodeCheckExec : public CMenuTarget int exec(CMenuTarget* parent, const std::string & actionKey); }; -void testNetworkSettings(const char* ip, const char* netmask, const char* broadcast, const char* gateway, const char* nameserver, bool dhcp); -void showCurrentNetworkSettings(); int safe_mkdir(char * path); int check_dir(const char * newdir); - class CTZChangeNotifier : public CChangeObserver { public: @@ -255,7 +220,6 @@ class CCpuFreqNotifier : public CChangeObserver public: bool changeNotify(const neutrino_locale_t, void * data); }; - #if 0 class CScreenPresetNotifier : public CChangeObserver { @@ -263,12 +227,6 @@ public: bool changeNotify(const neutrino_locale_t, void * data); }; #endif -class CAllUsalsNotifier : public CChangeObserver -{ -public: - bool changeNotify(const neutrino_locale_t, void * data); -}; - class CAutoModeNotifier : public CChangeObserver { public: From 8a2f3412e1995105f0379b599471d672b16c069c Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:50:14 +0400 Subject: [PATCH 013/737] settings: add setting for CI clock and scan setting for cable NID --- src/system/settings.cpp | 2 ++ src/system/settings.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/system/settings.cpp b/src/system/settings.cpp index ad6e4e950..c6e258df3 100644 --- a/src/system/settings.cpp +++ b/src/system/settings.cpp @@ -163,6 +163,7 @@ bool CScanSettings::loadSettings(const char * const fileName, const delivery_sys scanSectionsd = configfile.getInt32("scanSectionsd", 0); fast_type = configfile.getInt32("fast_type", 1); fast_op = configfile.getInt32("fast_op", 0); + cable_nid = configfile.getInt32("cable_nid", 0); return true; } @@ -186,6 +187,7 @@ bool CScanSettings::saveSettings(const char * const fileName) configfile.setInt32("scanSectionsd", scanSectionsd ); configfile.setInt32("fast_type", fast_type); configfile.setInt32("fast_op", fast_op); + configfile.setInt32("cable_nid", fast_op); if(configfile.getModifiedFlag()) configfile.saveConfig(fileName); diff --git a/src/system/settings.h b/src/system/settings.h index 6755d723d..77fba4a54 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -101,6 +101,7 @@ struct SNeutrinoSettings int clockrec; int rounded_corners; int ci_standby_reset; + int ci_clock; int radiotext_enable; //vcr @@ -658,6 +659,7 @@ public: char TP_rate[9]; int fast_type; int fast_op; + int cable_nid; CScanSettings(); From a5bee2825414858b5851748d8e48a8a868fdf667 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:52:55 +0400 Subject: [PATCH 014/737] NIT: add thread args struct, use cable NIT setting in NIT parse --- src/zapit/include/zapit/nit.h | 14 ++++++- src/zapit/src/nit.cpp | 72 ++++++++++++++++++++++------------- 2 files changed, 59 insertions(+), 27 deletions(-) diff --git a/src/zapit/include/zapit/nit.h b/src/zapit/include/zapit/nit.h index d68382cb1..6b2c0df0e 100644 --- a/src/zapit/include/zapit/nit.h +++ b/src/zapit/include/zapit/nit.h @@ -22,6 +22,18 @@ #ifndef __zapit_nit_h__ #define __zapit_nit_h__ -int parse_nit(t_satellite_position satellitePosition, freq_id_t freq); +typedef struct nit_thread_args { + t_satellite_position satellitePosition; + freq_id_t freq; + unsigned short nid; + + nit_thread_args(t_satellite_position SatellitePosition, freq_id_t Freq, unsigned short Nid = 0) { + satellitePosition = SatellitePosition; + freq = Freq; + nid = Nid; + } +} nit_thread_args_t; + +int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned short nid = 0); #endif /* __zapit_nit_h__ */ diff --git a/src/zapit/src/nit.cpp b/src/zapit/src/nit.cpp index 0a58e6135..3472b37c1 100644 --- a/src/zapit/src/nit.cpp +++ b/src/zapit/src/nit.cpp @@ -35,10 +35,9 @@ extern short abort_scan; void *nit_thread(void * data) { - int satellitePosition = (int) data; - + nit_thread_args_t *threadArgs = (nit_thread_args_t *)data; printf("[scan] trying to parse NIT\n"); - int status = parse_nit(satellitePosition, 0); + int status = parse_nit(threadArgs->satellitePosition, threadArgs->freq, threadArgs->nid); if(status < 0) printf("[scan] NIT failed !\n"); else @@ -47,16 +46,19 @@ void *nit_thread(void * data) pthread_exit(NULL); } -int parse_nit(t_satellite_position satellitePosition, freq_id_t freq) +int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned short nid) { int ret = 0; - int secdone[255]; - int sectotal = -1; + int secdone[2][255]; + int sectotal[2] = { -1, -1 }; + int nit_index = 0; - for(int i = 0; i < 255; i++) - secdone[i] = 0; + for(int i = 0; i < 2; i++) { + for (int j = 0; j < 255; j++) + secdone[i][j] = 0; + } - cDemux * dmx = new cDemux();; + cDemux * dmx = new cDemux(); dmx->Open(DMX_PSI_CHANNEL); unsigned char buffer[NIT_SIZE]; @@ -82,7 +84,15 @@ int parse_nit(t_satellite_position satellitePosition, freq_id_t freq) filter[0] = 0x40; //filter[4] = 0x00; - mask[0] = 0xFF; + mask[0] = (nid != 0) ? 0xFE : 0xFF; // in case we have network ID we also want the 'other' tables + + if (nid) { // filter for the network ID + filter[1] = (nid >> 8) & 0xff; + filter[2] = (nid >> 0) & 0xff; + mask[1] = 0xff; + mask[2] = 0xff; + } + //mask[4] = 0xFF; //unsigned char sec = 0x00; @@ -90,34 +100,44 @@ int parse_nit(t_satellite_position satellitePosition, freq_id_t freq) delete dmx; return -1; } + do { if (dmx->Read(buffer, NIT_SIZE) < 0) { delete dmx; return -1; } + if (CServiceScan::getInstance()->Aborted()) { ret = -1; goto _return; } -if(buffer[0] != 0x40) - printf("[NIT] ******************************************* Bogus section received: 0x%x\n", buffer[0]); + + if ((buffer[0] != 0x40) && ((nid > 0) && (buffer[0] != 0x41))) { + // NIT actual or NIT other + printf("[NIT] ******************************************* Bogus section received: 0x%x\n", buffer[0]); + ret = -1; + goto _return; + } + + nit_index = buffer[0] & 1; section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; network_id = ((buffer[3] << 8)| buffer [4]); network_descriptors_length = ((buffer[8] & 0x0F) << 8) | buffer[9]; unsigned char secnum = buffer[6]; -printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], network_id, secdone[secnum] ? "skip" : "use"); - if(secdone[secnum]) // mark sec XX done + printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], network_id, secdone[nit_index][secnum] ? "skip" : "use"); + if(secdone[nit_index][secnum]) // mark sec XX done continue; - secdone[secnum] = 1; - sectotal++; + secdone[nit_index][secnum] = 1; + sectotal[nit_index]++; for (pos = 10; pos < network_descriptors_length + 10; pos += buffer[pos + 1] + 2) { switch (buffer[pos]) { - /* case 0x0F: - Private_data_indicator_descriptor(buffer + pos); - break; - */ + /* + case 0x0F: + Private_data_indicator_descriptor(buffer + pos); + break; + */ case 0x40: network_name_descriptor(buffer + pos); break; @@ -129,11 +149,11 @@ printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], ne case 0x5B: multilingual_network_name_descriptor(buffer + pos); break; - - /* case 0x5F: - private_data_specifier_descriptor(buffer + pos); - break; - */ + /* + case 0x5F: + private_data_specifier_descriptor(buffer + pos); + break; + */ case 0x80: /* unknown, Eutelsat 13.0E */ break; @@ -214,7 +234,7 @@ printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], ne } } } - } while(sectotal < buffer[7]); + } while(sectotal[nit_index] < buffer[7]); //} while (filter[4]++ != buffer[7]); _return: dmx->Stop(); From 134a1c4f78626b5b7bcddd77f3f40f549605518d Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:56:26 +0400 Subject: [PATCH 015/737] scan: add cable nid param, use CFEManager to select frontend --- src/zapit/include/zapit/scan.h | 8 ++- src/zapit/src/scan.cpp | 97 ++++++++++++++++------------------ 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/src/zapit/include/zapit/scan.h b/src/zapit/include/zapit/scan.h index 0320a36f4..93bd1118f 100644 --- a/src/zapit/include/zapit/scan.h +++ b/src/zapit/include/zapit/scan.h @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include "bouquets.h" @@ -45,6 +45,7 @@ class CServiceScan : public OpenThreads::Thread uint32_t found_radio_chans; uint32_t found_data_chans; uint32_t failed_transponders; + unsigned short cable_nid; short curr_sat; @@ -78,6 +79,7 @@ class CServiceScan : public OpenThreads::Thread void run(); + CFrontend * frontend; static CServiceScan * scan; CServiceScan(); @@ -96,8 +98,12 @@ class CServiceScan : public OpenThreads::Thread void Abort() { abort_scan = 1; }; bool Aborted() { return abort_scan; }; + bool SetFrontend(t_satellite_position satellitePosition); + CFrontend * GetFrontend() { return frontend; }; + uint32_t & FoundTransponders() { return found_transponders; }; uint32_t & FoundChannels() { return found_channels; }; + void SetCableNID(unsigned short nid) { cable_nid = nid; } }; #endif /* __scan_h__ */ diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index bfa348a6d..c987630aa 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -26,13 +26,11 @@ #include #include -#include #include #include #include #include #include -#include #include #include @@ -63,6 +61,8 @@ CServiceScan::CServiceScan() started = false; scan_nit = false; running = false; + cable_nid = 0; + frontend = CFEManager::getInstance()->getFE(0); } CServiceScan::~CServiceScan() @@ -128,8 +128,8 @@ void CServiceScan::run() bool CServiceScan::tuneFrequency(FrontendParameters *feparams, uint8_t polarization, t_satellite_position satellitePosition) { - CFrontend::getInstance()->setInput(satellitePosition, feparams->frequency, polarization); - int ret = CFrontend::getInstance()->driveToSatellitePosition(satellitePosition, false); //true); + frontend->setInput(satellitePosition, feparams->frequency, polarization); + int ret = frontend->driveToSatellitePosition(satellitePosition, false); //true); if(ret > 0) { printf("[scan] waiting %d seconds for motor to turn satellite dish.\n", ret); CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_PROVIDER, (void *) "moving rotor", 13); @@ -139,7 +139,7 @@ bool CServiceScan::tuneFrequency(FrontendParameters *feparams, uint8_t polarizat return false; } } - return CFrontend::getInstance()->tuneFrequency(feparams, polarization, false); + return frontend->tuneFrequency(feparams, polarization, false); } bool CServiceScan::AddTransponder(transponder_id_t TsidOnid, FrontendParameters *feparams, uint8_t polarity, bool fromnit) @@ -256,19 +256,21 @@ _repeat: if(abort_scan) return false; -#ifdef NIT_THREAD - pthread_t nthread; - if(scan_nit) - if(pthread_create(&nthread, 0, nit_thread, (void*)satellitePosition)) { - ERROR("pthread_create"); - nthread = 0; - } -#endif freq_id_t freq; if(cable) freq = tI->second.feparams.frequency/100; else freq = tI->second.feparams.frequency/1000; + +#ifdef NIT_THREAD + pthread_t nthread; + nit_thread_args_t threadArgs(satellitePosition, freq, cable_nid); + if(scan_nit) + if(pthread_create(&nthread, 0, nit_thread, (void*)&threadArgs)) { + ERROR("pthread_create"); + nthread = 0; + } +#endif //INFO("parsing SDT (tsid:onid %04x:%04x)", tI->second.transport_stream_id, tI->second.original_network_id); int status = parse_sdt(&tI->second.transport_stream_id, &tI->second.original_network_id, satellitePosition, freq /*tI->second.feparams.frequency/1000*/); if(status < 0) { @@ -361,7 +363,7 @@ bool CServiceScan::AddTransponder(xmlNodePtr transponder, uint8_t diseqc_pos, t_ feparams.u.qam.modulation = (fe_modulation_t) xmlGetNumericAttribute(transponder, "modulation", 0); diseqc_pos = 0; } - else if (CFrontend::getInstance()->getInfo()->type == FE_QPSK) { + else if (frontend->getInfo()->type == FE_QPSK) { feparams.u.qpsk.symbol_rate = xmlGetNumericAttribute(transponder, "symbol_rate", 0); polarization = xmlGetNumericAttribute(transponder, "polarization", 0); system = xmlGetNumericAttribute(transponder, "system", 0); @@ -411,14 +413,10 @@ bool CServiceScan::ScanProvider(xmlNodePtr search, t_satellite_position satellit processed_transponders = 0; TIMER_START(); - sat_iterator_t sit = satellitePositions.find(satellitePosition); - if(sit == satellitePositions.end()) { - printf("[zapit] WARNING satellite position %d not found!\n", satellitePosition); - return false; - } + std::string satname = CServiceManager::getInstance()->GetSatelliteName(satellitePosition); CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_REPORT_NUM_SCANNED_TRANSPONDERS, &processed_transponders, sizeof(processed_transponders)); - CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_SATELLITE, sit->second.name.c_str(), sit->second.name.size() + 1); + CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_SATELLITE, satname.c_str(), satname.size() + 1); tps = search->xmlChildrenNode; /* TPs from current service list */ for(tI = transponders.begin(); tI != transponders.end(); tI++) { @@ -470,6 +468,19 @@ void CServiceScan::Cleanup(const bool success) service_types.clear(); } +bool CServiceScan::SetFrontend(t_satellite_position satellitePosition) +{ + CFrontend * fe = CFEManager::getInstance()->getScanFrontend(satellitePosition); + if(fe == NULL) { + INFO("No frontend found for satellite %d\n", satellitePosition); + return false; + } + + frontend = fe; + CFEManager::getInstance()->setLiveFE(frontend); + return true; +} + bool CServiceScan::ScanProviders() { scan_list_iterator_t spI; @@ -482,7 +493,7 @@ bool CServiceScan::ScanProviders() curr_sat = 0; - cable = (CFrontend::getInstance()->getInfo()->type == FE_QAM); + cable = (frontend->getInfo()->type == FE_QAM);//FIXME if (cable) frontendType = "cable"; else @@ -492,7 +503,7 @@ bool CServiceScan::ScanProviders() int scan_sat_mode = mode & 0xFF00; // single = 0, all = 1 printf("[zapit] scan mode %s, satellites %s\n", scan_nit ? "NIT" : "fast", scan_sat_mode ? "all" : "single"); - // CZapitClient myZapitClient; + CZapitClient myZapitClient; /* get first child */ //xmlNodePtr search = xmlDocGetRootElement(scanInputParser)->xmlChildrenNode; @@ -518,6 +529,8 @@ bool CServiceScan::ScanProviders() /* provider is not wanted - jump to the next one */ if (spI != scanProviders.end()) { + if(!SetFrontend(position)) + break; /* get name of current satellite oder cable provider */ strcpy(providerName, xmlGetAttribute(search, "name")); @@ -562,24 +575,10 @@ bool CServiceScan::ScanProviders() g_bouquetManager->loadBouquets(); printf("[scan] save bouquets done\n"); Cleanup(true); -#if 1 - CZapitClient myZapitClient; myZapitClient.reloadCurrentServices(); -#else - /* this can hang as the thread handling the connections - * could already be in g_Zapit->stopScan(), waiting for - * *this* thread to join(). - myZapitClient.reloadCurrentServices(); - * so let's do another ugly, layer-violating hack... - */ - CFrontend::getInstance()->setTsidOnid(0); - t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); - CZapit::getInstance()->ZapIt(live_channel_id, false); - CZapit::getInstance()->SendEvent(CZapitClient::EVT_SERVICES_CHANGED); -#endif } else { Cleanup(false); - CFrontend::getInstance()->setTsidOnid(0); + frontend->setTsidOnid(0); t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); CZapit::getInstance()->ZapIt(live_channel_id, false); } @@ -593,13 +592,18 @@ bool CServiceScan::ScanTransponder() char providerName[32] = ""; t_satellite_position satellitePosition = 0; + satellitePosition = scanProviders.begin()->first; + if(!SetFrontend(satellitePosition)) { + Cleanup(false); + return false; + } + scanBouquetManager = new CBouquetManager(); - cable = (CFrontend::getInstance()->getInfo()->type == FE_QAM); + cable = (frontend->getInfo()->type == FE_QAM);//FIXME strcpy(providerName, scanProviders.size() > 0 ? scanProviders.begin()->second.c_str() : "unknown provider"); - satellitePosition = scanProviders.begin()->first; printf("[scan_transponder] scanning sat %s position %d\n", providerName, satellitePosition); CZapit::getInstance()->SendEvent(CZapitClient::EVT_SCAN_SATELLITE, providerName, strlen(providerName) + 1); @@ -628,7 +632,7 @@ bool CServiceScan::ScanTransponder() if(abort_scan) found_channels = 0; - // CZapitClient myZapitClient; + CZapitClient myZapitClient; //FIXME move to Cleanup() ? if(found_channels) { CServiceManager::getInstance()->SaveServices(true); @@ -639,21 +643,10 @@ bool CServiceScan::ScanTransponder() //g_bouquetManager->clearAll(); g_bouquetManager->loadBouquets(); Cleanup(true); -#if 1 - CZapitClient myZapitClient; myZapitClient.reloadCurrentServices(); -#else - /* see the explanation in CServiceScan::ScanProviders() in why this is a bad idea - myZapitClient.reloadCurrentServices(); - */ - CFrontend::getInstance()->setTsidOnid(0); - t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); - CZapit::getInstance()->ZapIt(live_channel_id, false); - CZapit::getInstance()->SendEvent(CZapitClient::EVT_SERVICES_CHANGED); -#endif } else { Cleanup(false); - CFrontend::getInstance()->setTsidOnid(0); + frontend->setTsidOnid(0); t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); CZapit::getInstance()->ZapIt(live_channel_id, false); } From bcae2e2b89aabe69648cbcbb8b6dc927a9e74455 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 14:58:22 +0400 Subject: [PATCH 016/737] zapit bouquets: force creating Other bouquet for unused channels --- src/zapit/src/bouquets.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/zapit/src/bouquets.cpp b/src/zapit/src/bouquets.cpp index 26e804f9b..1e14f47d5 100644 --- a/src/zapit/src/bouquets.cpp +++ b/src/zapit/src/bouquets.cpp @@ -410,7 +410,8 @@ void CBouquetManager::renumChannels(ZapitChannelList &list, int & counter, char void CBouquetManager::makeRemainingChannelsBouquet(void) { ZapitChannelList unusedChannels; - bool tomake = CZapit::getInstance()->makeRemainingChannelsBouquet(); + //FIXME services loaded before config. + //bool tomake = CZapit::getInstance()->makeRemainingChannelsBouquet(); /* reset channel number and has_bouquet flag */ CServiceManager::getInstance()->ResetChannelNumbers(); @@ -421,7 +422,7 @@ void CBouquetManager::makeRemainingChannelsBouquet(void) renumChannels((*it)->radioChannels, j, (*it)->bUser ? NULL : (char *) (*it)->Name.c_str()); } - if(!tomake || CServiceManager::getInstance()->GetAllUnusedChannels(unusedChannels) == false) + if(/*!tomake ||*/ CServiceManager::getInstance()->GetAllUnusedChannels(unusedChannels) == false) return; sort(unusedChannels.begin(), unusedChannels.end(), CmpChannelByChName()); From 5002cd4c0f00ce4bf33f3a1b737159e848cfbb7e Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:00:09 +0400 Subject: [PATCH 017/737] fastscan: update CServiceManager usage, use CFEManager --- src/zapit/src/fastscan.cpp | 46 +++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/zapit/src/fastscan.cpp b/src/zapit/src/fastscan.cpp index 8797f3156..5a898bedd 100644 --- a/src/zapit/src/fastscan.cpp +++ b/src/zapit/src/fastscan.cpp @@ -23,17 +23,13 @@ #include #include -#include #include #include #include #include -#include #include -#include #include #include -#include #include #include #include @@ -54,26 +50,38 @@ extern transponder_list_t transponders; // defined in zapit.cpp void CServiceScan::InitFastscanLnb(int id) { - CServiceManager::getInstance()->InitSatPosition(192); - CServiceManager::getInstance()->InitSatPosition(235); - CServiceManager::getInstance()->InitSatPosition(282); - CServiceManager::getInstance()->InitSatPosition(130); + CServiceManager::getInstance()->InitSatPosition(192, NULL, true); + CServiceManager::getInstance()->InitSatPosition(235, NULL, true); + CServiceManager::getInstance()->InitSatPosition(282, NULL, true); + CServiceManager::getInstance()->InitSatPosition(130, NULL, true); + satellite_map_t & satmap = CServiceManager::getInstance()->SatelliteList(); + + frontend = CFEManager::getInstance()->getFE(0); + frontend->setSatellites(satmap); + satmap = frontend->getSatellites(); + switch(id) { default: case CD_OPERATOR_ID: case OPERATOR_TVV: - satellitePositions[192].diseqc = 0; - satellitePositions[235].diseqc = 1; - satellitePositions[282].diseqc = 2; - satellitePositions[130].diseqc = 3; + satmap[192].diseqc = 0; + satmap[235].diseqc = 1; + satmap[282].diseqc = 2; + satmap[130].diseqc = 3; break; case OPERATOR_TELESAT: - satellitePositions[130].diseqc = 0; - satellitePositions[192].diseqc = 1; - satellitePositions[235].diseqc = 2; - satellitePositions[282].diseqc = 3; + satmap[130].diseqc = 0; + satmap[192].diseqc = 1; + satmap[235].diseqc = 2; + satmap[282].diseqc = 3; break; } + satmap[130].configured = 1; + satmap[192].configured = 1; + satmap[235].configured = 1; + satmap[282].configured = 1; + CFEManager::getInstance()->saveSettings(); + SetFrontend(192); } bool CServiceScan::ScanFast() @@ -146,7 +154,7 @@ bool CServiceScan::ScanFast() myZapitClient.reloadCurrentServices(); } else { Cleanup(false); - CFrontend::getInstance()->setTsidOnid(0); + frontend->setTsidOnid(0); //zapit(live_channel_id, 0); } fast_services_sat.clear(); @@ -260,10 +268,12 @@ bool CServiceScan::ParseFst(unsigned short pid, fast_scan_operator_t * op) std::map ::iterator sIt = fast_services_sat.find(channel_id); if(sIt != fast_services_sat.end()) { +#if 0 satellitePosition = sIt->second; sat_iterator_t sit = satellitePositions.find(satellitePosition); if(sit != satellitePositions.end()) sit->second.have_channels = true; +#endif } std::map ::iterator fIt = fast_services_freq.find(channel_id); @@ -332,7 +342,7 @@ bool CServiceScan::ParseFst(unsigned short pid, fast_scan_operator_t * op) newchannel->number = num; char pname[100]; - if (CFrontend::getInstance()->getInfo()->type == FE_QPSK) + if (frontend->getInfo()->type == FE_QPSK) snprintf(pname, 100, "[%c%03d.%d] %s", satellitePosition > 0? 'E' : 'W', abs(satellitePosition)/10, abs(satellitePosition)%10, providerName.c_str()); else snprintf(pname, 100, "%s", providerName.c_str()); From 5930d09cb90839e4c27de2b5f450322d918c6873 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:03:23 +0400 Subject: [PATCH 018/737] record: add support to select recording demux; use CFEManager to allocate and lock frontend in use --- src/driver/record.cpp | 53 ++++++++++++++++++++++++++++++++++++++++--- src/driver/record.h | 3 +++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/driver/record.cpp b/src/driver/record.cpp index 8154e01e0..c2f9d29bf 100644 --- a/src/driver/record.cpp +++ b/src/driver/record.cpp @@ -170,7 +170,7 @@ record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList & apids[numpids++] = allpids.PIDs.pmtpid; if(record == NULL) - record = new cRecord(RECORD_DEMUX); + record = new cRecord(channel->getRecordDemux() /*RECORD_DEMUX*/); record->Open(); @@ -184,6 +184,9 @@ record_error_msg_t CRecordInstance::Start(CZapitChannel * channel /*, APIDList & return RECORD_FAILURE; } + if(!autoshift) + CFEManager::getInstance()->lockFrontend(frontend);//FIXME testing + start_time = time(0); SaveXml(); @@ -223,6 +226,9 @@ bool CRecordInstance::Stop(bool remove_event) SaveXml(); record->Stop(); + if(!autoshift) + CFEManager::getInstance()->unlockFrontend(frontend);//FIXME testing + CCamManager::getInstance()->Stop(channel_id, CCamManager::RECORD); if((autoshift && g_settings.auto_delete) /* || autoshift_delete*/) { @@ -806,7 +812,11 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons nextmap.push_back((CTimerd::RecordingInfo *)evt); } } else if(recmap.size() < RECORD_MAX_COUNT) { - if(CutBackNeutrino(eventinfo->channel_id, mode)) { +#if 1//FIXME test + CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(eventinfo->channel_id); + CFrontend * frontend = CFEManager::getInstance()->allocateFE(channel); +#endif + if(frontend && CutBackNeutrino(eventinfo->channel_id, mode)) { std::string newdir; if(dir && strlen(dir)) newdir = std::string(dir); @@ -818,6 +828,7 @@ bool CRecordManager::Record(const CTimerd::RecordingInfo * const eventinfo, cons if (inst == NULL) inst = new CRecordInstance(eventinfo, newdir, timeshift, StreamVTxtPid, StreamPmtPid); + inst->frontend = frontend; error_msg = inst->Record(); if(error_msg == RECORD_OK) { recmap.insert(std::pair(eventinfo->channel_id, inst)); @@ -1452,6 +1463,7 @@ bool CRecordManager::CutBackNeutrino(const t_channel_id channel_id, const int mo g_Zapit->setStandby(false); // this zap to live_channel_id t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); +#if 0 if(live_channel_id != channel_id) { if(SAME_TRANSPONDER(live_channel_id, channel_id)) { printf("%s zapTo_record channel_id %llx\n", __FUNCTION__, channel_id); @@ -1461,7 +1473,7 @@ bool CRecordManager::CutBackNeutrino(const t_channel_id channel_id, const int mo } else { if (mode != last_mode && (last_mode != NeutrinoMessages::mode_standby || mode != CNeutrinoApp::getInstance()->getLastMode())) { CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , mode | NeutrinoMessages::norezap ); - // Wenn wir im Standby waren, dann brauchen wir fürs streamen nicht aufwachen... + // When we were on standby, then we need not wake up for streaming if(last_mode == NeutrinoMessages::mode_standby) CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , NeutrinoMessages::mode_standby); } @@ -1476,7 +1488,36 @@ bool CRecordManager::CutBackNeutrino(const t_channel_id channel_id, const int mo if(!ret) printf("%s: failed to change channel\n", __FUNCTION__); } +#endif + bool mode_changed = false; + if(live_channel_id != channel_id) { + bool found = false; + if(SAME_TRANSPONDER(live_channel_id, channel_id)) { + found = true; + } else { + for(recmap_iterator_t it = recmap.begin(); it != recmap.end(); it++) { + if(SAME_TRANSPONDER(it->first, channel_id)) { + found = true; + break; + } + } + } + if(found) { + ret = g_Zapit->zapTo_record(channel_id) > 0; + printf("%s found same tp, zapTo_record channel_id %llx result %d\n", __FUNCTION__, channel_id, ret); + } + else { + printf("%s mode %d last_mode %d getLastMode %d\n", __FUNCTION__, mode, last_mode, CNeutrinoApp::getInstance()->getLastMode()); + if (mode != last_mode && (last_mode != NeutrinoMessages::mode_standby || mode != CNeutrinoApp::getInstance()->getLastMode())) { + CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , mode | NeutrinoMessages::norezap ); + mode_changed = true; + } + + ret = g_Zapit->zapTo_serviceID(channel_id) > 0; + printf("%s zapTo_serviceID channel_id %llx result %d\n", __FUNCTION__, channel_id, ret); + } + } if(ret) { if(StopSectionsd) { printf("%s: g_Sectionsd->setPauseScanning(true)\n", __FUNCTION__); @@ -1488,6 +1529,12 @@ bool CRecordManager::CutBackNeutrino(const t_channel_id channel_id, const int mo if(last_mode == NeutrinoMessages::mode_standby) g_Zapit->stopPlayBack(); } + if(last_mode == NeutrinoMessages::mode_standby) { + //CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , NeutrinoMessages::mode_standby); + g_RCInput->postMsg( NeutrinoMessages::CHANGEMODE , last_mode); + } else if(!ret && mode_changed /*mode != last_mode*/) + CNeutrinoApp::getInstance()->handleMsg( NeutrinoMessages::CHANGEMODE , last_mode); + printf("%s channel_id %llx mode %d : result %s\n", __FUNCTION__, channel_id, mode, ret ? "OK" : "BAD"); return ret; } diff --git a/src/driver/record.h b/src/driver/record.h index 36bac7246..e4e5367e9 100644 --- a/src/driver/record.h +++ b/src/driver/record.h @@ -35,6 +35,7 @@ #include #include #include +#include #if HAVE_COOL_HARDWARE #include @@ -123,6 +124,8 @@ class CRecordInstance bool Timeshift() { return autoshift; }; int tshift_mode; void SetStopMessage(const char* text) {rec_stop_msg = text;} ; + + CFrontend * frontend; }; typedef std::map recmap_t; From 7a5d87d6b14d7975a34b84abde72d4ccdefbef09 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:08:14 +0400 Subject: [PATCH 019/737] channellist: new SameTP with channel param; use CFEManager to get frontend and check is it possible to zap --- src/gui/channellist.cpp | 59 +++++++++++++++++++++++++++++------------ src/gui/channellist.h | 3 ++- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/gui/channellist.cpp b/src/gui/channellist.cpp index b386ebe8f..f83e606c1 100644 --- a/src/gui/channellist.cpp +++ b/src/gui/channellist.cpp @@ -67,7 +67,8 @@ #include #include #include -#include +#include +#include extern CBouquetList * bouquetList; /* neutrino.cpp */ extern CRemoteControl * g_RemoteControl; /* neutrino.cpp */ @@ -146,7 +147,7 @@ void CChannelList::putChannel(CZapitChannel* channel) { int num = channel->number - 1; if(num < 0) { - printf("CChannelList::addChannel error inserting at %d\n", num); + printf("CChannelList::addChannel error inserting at %d : %s\n", num, channel->name.c_str()); return; } if(num >= (int) chanlist.size()) { @@ -1286,7 +1287,7 @@ int CChannelList::numericZap(int key) } } else { for ( unsigned int i = 0 ; i < orgList->chanlist.size(); i++) { - if(SameTP(orgList->chanlist[i]->channel_id)) + if(SameTP(orgList->chanlist[i])) channelList->addChannel(orgList->chanlist[i]); } } @@ -1425,7 +1426,7 @@ int CChannelList::numericZap(int key) if ( doZap ) { if(g_settings.timing[SNeutrinoSettings::TIMING_INFOBAR] == 0) g_InfoViewer->killTitle(); - if(SameTP(chanlist[chn]->channel_id)) { + if(SameTP(chanlist[chn])) { zapTo( chn ); res = 0; } else @@ -1538,7 +1539,7 @@ void CChannelList::virtual_zap_mode(bool up) { if(g_settings.timing[SNeutrinoSettings::TIMING_INFOBAR] == 0) g_InfoViewer->killTitle(); - if(SameTP(chanlist[chn]->channel_id)) + if(SameTP(chanlist[chn])) zapTo( chn ); else g_InfoViewer->killTitle(); @@ -1691,13 +1692,16 @@ void CChannelList::paintDetails(int index) while ( text2.find_first_of("[ -.+*#?=!$%&/]+") == 0 ) text2 = text2.substr( 1 ); text2 = text2.substr( 0, text2.find('\n') ); +#if 0 //FIXME: to discuss, eat too much cpu time if string long enough int pos = 0; while ( ( pos != -1 ) && (g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->getRenderWidth(text2, true) > (width - 30 - noch_len) ) ) { pos = text2.find_last_of(" "); - if ( pos!=-1 ) + if ( pos!=-1 ) { text2 = text2.substr( 0, pos ); + } } +#endif g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->RenderString(x+ xstart, y+ height+ 5+ 2* fheight, width- xstart- 30- noch_len, text2, colored_event_C ? COL_COLORED_EVENTS_CHANNELLIST : COL_MENUCONTENTDARK, 0, true); } @@ -1715,13 +1719,14 @@ void CChannelList::paintDetails(int index) if(tpI != transponders.end()) { char * f, *s, *m; - switch(CFrontend::getInstance()->getInfo()->type) { + CFrontend * frontend = CFEManager::getInstance()->getLiveFE(); + switch(frontend->getInfo()->type) { case FE_QPSK: - CFrontend::getInstance()->getDelSys(tpI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tpI->second.feparams.u.qpsk.fec_inner), f, s, m); + frontend->getDelSys(tpI->second.feparams.u.qpsk.fec_inner, dvbs_get_modulation(tpI->second.feparams.u.qpsk.fec_inner), f, s, m); len += snprintf(&buf[len], sizeof(buf) - len, "%c %d %s %s %s ", tpI->second.polarization ? 'V' : 'H', tpI->second.feparams.u.qpsk.symbol_rate/1000, f, s, m); break; case FE_QAM: - CFrontend::getInstance()->getDelSys(tpI->second.feparams.u.qam.fec_inner, tpI->second.feparams.u.qam.modulation, f, s, m); + frontend->getDelSys(tpI->second.feparams.u.qam.fec_inner, tpI->second.feparams.u.qam.modulation, f, s, m); len += snprintf(&buf[len], sizeof(buf) - len, "%d %s %s %s ", tpI->second.feparams.u.qam.symbol_rate/1000, f, s, m); break; case FE_OFDM: @@ -1733,11 +1738,13 @@ void CChannelList::paintDetails(int index) if(chanlist[index]->pname) snprintf(&buf[len], sizeof(buf) - len, "(%s)", chanlist[index]->pname); else { - sat_iterator_t sit = satellitePositions.find(chanlist[index]->getSatellitePosition()); - if(sit != satellitePositions.end()) { - //int satNameWidth = g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST_DESCR]->getRenderWidth (sit->second.name); - snprintf(&buf[len], sizeof(buf) - len, "(%s)", sit->second.name.c_str()); - } +#if 0 + const char * satname = CServiceManager::getInstance()->GetSatelliteName(chanlist[index]->getSatellitePosition()); + if(satname) + snprintf(&buf[len], sizeof(buf) - len, "(%s)", satname); +#endif + snprintf(&buf[len], sizeof(buf) - len, "(%s)", + CServiceManager::getInstance()->GetSatelliteName(chanlist[index]->getSatellitePosition()).c_str()); } g_Font[SNeutrinoSettings::FONT_TYPE_CHANNELLIST]->RenderString(x+ 10, y+ height+ 5+ 3*fheight, width - 30, buf, COL_MENUCONTENTDARK, 0, true); } @@ -1878,7 +1885,7 @@ void CChannelList::paintItem(int pos) } #endif if(curr < chanlist.size()) - iscurrent = SameTP(chanlist[curr]->channel_id); + iscurrent = SameTP(chanlist[curr]); if (curr == selected) { color = COL_MENUCONTENTSELECTED; @@ -1892,7 +1899,7 @@ void CChannelList::paintItem(int pos) bgcolor = iscurrent ? COL_MENUCONTENT_PLUS_0 : COL_MENUCONTENTINACTIVE_PLUS_0; frameBuffer->paintBoxRel(x,ypos, width- 15, fheight, bgcolor, 0); } - + if(curr < chanlist.size()) { char nameAndDescription[255]; char tmp[10]; @@ -2165,10 +2172,28 @@ bool CChannelList::SameTP(t_channel_id channel_id) iscurrent = (channel_id >> 16) == (rec_channel_id >> 16); #endif if(CNeutrinoApp::getInstance()->recordingstatus) { +#if 0 if(channel_id == 0) channel_id = chanlist[selected]->channel_id; iscurrent = CRecordManager::getInstance()->SameTransponder(channel_id); +#endif + CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id); + if(channel) + iscurrent = SameTP(channel); + else + iscurrent = false; + } + return iscurrent; +} + +bool CChannelList::SameTP(CZapitChannel * channel) +{ + bool iscurrent = true; + + if(CNeutrinoApp::getInstance()->recordingstatus) { + if(channel == NULL) + channel = chanlist[selected]; + iscurrent = CFEManager::getInstance()->canTune(channel); } - return iscurrent; } diff --git a/src/gui/channellist.h b/src/gui/channellist.h index 4fc3c1ab5..cbf48afbc 100644 --- a/src/gui/channellist.h +++ b/src/gui/channellist.h @@ -149,7 +149,8 @@ public: void SortSat(void); void SortTP(void); void ClearList(void); - bool SameTP(t_channel_id channel_id = 0); + bool SameTP(t_channel_id channel_id); + bool SameTP(CZapitChannel * channel = NULL); CLastChannel & getLastChannels() { return lastChList; } //friend class CZapitChannel; }; From ffd335adaa94b7f07718c7c0af3e38e58d37bacb Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:12:01 +0400 Subject: [PATCH 020/737] nhttpd neutrinoapi: use channel camap in place of global pmt_caids --- .../tuxboxapi/coolstream/neutrinoapi.cpp | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/nhttpd/tuxboxapi/coolstream/neutrinoapi.cpp b/src/nhttpd/tuxboxapi/coolstream/neutrinoapi.cpp index 476ffbd5d..f446127c6 100644 --- a/src/nhttpd/tuxboxapi/coolstream/neutrinoapi.cpp +++ b/src/nhttpd/tuxboxapi/coolstream/neutrinoapi.cpp @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include @@ -457,15 +457,20 @@ std::string CNeutrinoAPI::getAudioInfoAsString(void) { //------------------------------------------------------------------------- std::string CNeutrinoAPI::getCryptInfoAsString(void) { - extern int pmt_caids[4][11]; - unsigned short i,j; + unsigned short i; std::stringstream out; - std::string casys[11]={"Irdeto:","Betacrypt:","Seca:","Viaccess:","Nagra:","Conax: ","Cryptoworks:","Videoguard:","EBU:","XCrypt:","PowerVU:"}; - for(i=0;i<4;i++){ - for(j=0;j<11;j++){ - if(pmt_caids[i][j]){ - out << casys[j] << hex << pmt_caids[i][j]<< "\n"; - } + std::string casys[11]= {"Irdeto:","Betacrypt:","Seca:","Viaccess:","Nagra:","Conax: ","Cryptoworks:","Videoguard:","EBU:","XCrypt:","PowerVU:"}; + int caids[] = { 0x600, 0x1700, 0x0100, 0x0500, 0x1800, 0xB00, 0xD00, 0x900, 0x2600, 0x4a00, 0x0E00 }; + + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if(channel) { + for (i = 0; i < 11; i++) { + for(casys_map_iterator_t it = channel->camap.begin(); it != channel->camap.end(); ++it) { + int caid = (*it) & 0xFF00; + if(caid == caids[i]) + out << casys[i] << hex << (*it) << "\n"; + } + } } return out.str(); From abf326252d65b727b0108ff82506eb1c41597509 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:18:05 +0400 Subject: [PATCH 021/737] zapittypes.h: add ci_clock to zapit start arg struct; add cam_ci to zapit config struct --- src/zapit/include/zapit/client/zapittypes.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/zapit/include/zapit/client/zapittypes.h b/src/zapit/include/zapit/client/zapittypes.h index ed6fbd703..216519f69 100644 --- a/src/zapit/include/zapit/client/zapittypes.h +++ b/src/zapit/include/zapit/client/zapittypes.h @@ -149,6 +149,7 @@ typedef struct ZAPIT_start_arg int startchannelradio_nr; int uselastchannel; int video_mode; + int ci_clock; } Z_start_arg; typedef struct TP_map @@ -162,23 +163,26 @@ typedef struct TP_map #define MAX_LNB 64 typedef struct Zapit_config { - int motorRotationSpeed; int writeChannelsNames; int makeRemainingChannelsBouquet; int saveLastChannel; int rezapTimeout; - int feTimeout; int fastZap; int sortNames; - int highVoltage; int scanPids; int scanSDT; + int cam_ci; int useGotoXX; + /* FE common */ + int feTimeout; int gotoXXLaDirection; int gotoXXLoDirection; - int repeatUsals; double gotoXXLatitude; double gotoXXLongitude; + int repeatUsals; + /* FE specific */ + int highVoltage; + int motorRotationSpeed; int uni_scr; int uni_qrg; } t_zapit_config; From 2de6b90c5502fee96ec0a641da4d6dca2a6e320a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:20:24 +0400 Subject: [PATCH 022/737] zapit ci.cpp: add constructors and ca_pmt_pid member --- src/zapit/include/zapit/ci.h | 5 +++++ src/zapit/src/ci.cpp | 30 ++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/zapit/include/zapit/ci.h b/src/zapit/include/zapit/ci.h index 7fad5741b..4d66db618 100644 --- a/src/zapit/include/zapit/ci.h +++ b/src/zapit/include/zapit/ci.h @@ -81,7 +81,10 @@ class CCaPmt : public CCaTable unsigned ca_pmt_length; public: + CCaPmt(); + CCaPmt(const unsigned char * const buffer); ~CCaPmt(void); + unsigned getLength(void); unsigned writeToBuffer(unsigned char * const buffer, int demux = 1, int camask = 3); @@ -91,6 +94,8 @@ class CCaPmt : public CCaTable unsigned version_number : 5; unsigned current_next_indicator : 1; + unsigned short ca_pmt_pid; + std::vector es_info; }; diff --git a/src/zapit/src/ci.cpp b/src/zapit/src/ci.cpp index b71e1e649..677f576ba 100644 --- a/src/zapit/src/ci.cpp +++ b/src/zapit/src/ci.cpp @@ -22,7 +22,7 @@ #include #include -extern int curpmtpid; +#include /* * conditional access descriptors */ @@ -51,7 +51,6 @@ unsigned int CCaDescriptor::writeToBuffer(unsigned char * const buffer) // retur return descriptor_length + 2; } - /* * generic table containing conditional access descriptors */ @@ -89,7 +88,6 @@ CCaTable::~CCaTable(void) delete ca_descriptor[i]; } - /* * elementary stream information */ @@ -111,10 +109,30 @@ unsigned int CEsInfo::writeToBuffer(unsigned char * const buffer) // returns num //return 3 + CCaTable::writeToBuffer(&(buffer[3])); } - /* * contitional access program map table */ + +CCaPmt::CCaPmt() +{ + ca_pmt_list_management = 0; + program_number = 0; + reserved1 = 0; + version_number = 0; + current_next_indicator = 0; + ca_pmt_pid = 0; +} + +CCaPmt::CCaPmt(const unsigned char * const buffer) +{ + program_number = (buffer[3] << 8) + buffer[4]; + reserved1 = buffer[5] >> 6; + version_number = (buffer[5] >> 1) & 0x1F; + current_next_indicator = buffer[5] & 0x01; + reserved2 = buffer[10] >> 4; + ca_pmt_pid = 0; +} + CCaPmt::~CCaPmt(void) { for (unsigned int i = 0; i < es_info.size(); i++) @@ -153,8 +171,8 @@ unsigned int CCaPmt::writeToBuffer(unsigned char * const buffer, int demux, int buffer[27] = 0x84; // pmt pid buffer[28] = 0x02; - buffer[29] = (curpmtpid >> 8) & 0xFF; - buffer[30] = curpmtpid & 0xFF; // 30 + buffer[29] = (ca_pmt_pid >> 8) & 0xFF; + buffer[30] = ca_pmt_pid & 0xFF; // 30 int lenpos=10; int len=19; From 9a2c303348aa9b1365269e0e2711c45f422dcae1 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:27:58 +0400 Subject: [PATCH 023/737] neutrino scan: use CServiceManager API to get satellite name; use CServiceScan API to get frontend; set cable nid if cable; --- src/gui/scan.cpp | 76 +++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/src/gui/scan.cpp b/src/gui/scan.cpp index 505a1280c..9b9f97c6d 100644 --- a/src/gui/scan.cpp +++ b/src/gui/scan.cpp @@ -57,9 +57,10 @@ #include -#include -#include +#include +#include #include +#include #include extern cVideo * videoDecoder; @@ -83,25 +84,18 @@ CScanTs::CScanTs() } extern int scan_fta_flag;//in zapit descriptors definiert -extern int start_fast_scan(int scan_mode, int opid); -#include void CScanTs::prev_next_TP( bool up) { t_satellite_position position = 0; - for (sat_iterator_t sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { - if (!strcmp(sit->second.name.c_str(), scansettings.satNameNoDiseqc)) { - position = sit->first; - break; - } - } + position = CServiceManager::getInstance()->GetSatellitePosition(scansettings.satNameNoDiseqc); extern std::map select_transponders; transponder_list_t::iterator tI; bool next_tp = false; - if(up){ + if(up) { for (tI = select_transponders.begin(); tI != select_transponders.end(); tI++) { t_satellite_position satpos = GET_SATELLITEPOSITION_FROM_TRANSPONDER_ID(tI->first) & 0xFFF; if (GET_SATELLITEPOSITION_FROM_TRANSPONDER_ID(tI->first) & 0xF000) @@ -113,21 +107,21 @@ void CScanTs::prev_next_TP( bool up) break; } } - }else{ - for ( tI=select_transponders.end() ; tI != select_transponders.begin(); tI-- ){ + } else { + for ( tI=select_transponders.end() ; tI != select_transponders.begin(); tI-- ) { t_satellite_position satpos = GET_SATELLITEPOSITION_FROM_TRANSPONDER_ID(tI->first) & 0xFFF; if (GET_SATELLITEPOSITION_FROM_TRANSPONDER_ID(tI->first) & 0xF000) satpos = -satpos; if (satpos != position) continue; - if(tI->second.feparams.frequency < TP.feparams.frequency){ + if(tI->second.feparams.frequency < TP.feparams.frequency) { next_tp = true; break; } } } - if(next_tp){ + if(next_tp) { TP.feparams.frequency = tI->second.feparams.frequency; if(g_info.delivery_system == DVB_S) { TP.feparams.u.qpsk.symbol_rate = tI->second.feparams.u.qpsk.symbol_rate; @@ -147,21 +141,23 @@ void CScanTs::testFunc() int w = x + width - xpos2; char buffer[128]; char * f, *s, *m; - if(CFrontend::getInstance()->getInfo()->type == FE_QPSK) { - CFrontend::getInstance()->getDelSys(TP.feparams.u.qpsk.fec_inner, dvbs_get_modulation((fe_code_rate_t)TP.feparams.u.qpsk.fec_inner), f, s, m); + + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + if(frontend->getInfo()->type == FE_QPSK) { + frontend->getDelSys(TP.feparams.u.qpsk.fec_inner, dvbs_get_modulation((fe_code_rate_t)TP.feparams.u.qpsk.fec_inner), f, s, m); snprintf(buffer,sizeof(buffer), "%u %c %d %s %s %s", TP.feparams.frequency/1000, TP.polarization == 0 ? 'H' : 'V', TP.feparams.u.qpsk.symbol_rate/1000, f, s, m); - } else if(CFrontend::getInstance()->getInfo()->type == FE_QAM) { - CFrontend::getInstance()->getDelSys(scansettings.TP_fec, scansettings.TP_mod, f, s, m); + } else if(frontend->getInfo()->type == FE_QAM) { + frontend->getDelSys(scansettings.TP_fec, scansettings.TP_mod, f, s, m); snprintf(buffer,sizeof(buffer), "%u %d %s %s %s", atoi(scansettings.TP_freq)/1000, atoi(scansettings.TP_rate)/1000, f, s, m); } paintLine(xpos2, ypos_cur_satellite, w - 95, scansettings.satNameNoDiseqc); paintLine(xpos2, ypos_frequency, w, buffer); success = g_Zapit->tune_TP(TP); - } + int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) { - diseqc_t diseqcType = NO_DISEQC; + //diseqc_t diseqcType = NO_DISEQC; neutrino_msg_t msg; neutrino_msg_data_t data; //bool manual = (scansettings.scan_mode == 2); @@ -201,6 +197,7 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) CRecordManager::getInstance()->StopAutoRecord(); g_Zapit->stopPlayBack(); + frameBuffer->paintBackground(); videoDecoder->ShowPicture(DATADIR "/neutrino/icons/scan.jpg"); g_Sectionsd->setPauseScanning(true); @@ -221,6 +218,7 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) TP.feparams.u.qam.symbol_rate = atoi(scansettings.TP_rate); TP.feparams.u.qam.fec_inner = (fe_code_rate_t)scansettings.TP_fec; TP.feparams.u.qam.modulation = (fe_modulation_t) scansettings.TP_mod; + CServiceScan::getInstance()->SetCableNID(scansettings.cable_nid); } //printf("[neutrino] freq %d rate %d fec %d pol %d\n", TP.feparams.frequency, TP.feparams.u.qpsk.symbol_rate, TP.feparams.u.qpsk.fec_inner, TP.polarization); } @@ -228,16 +226,12 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) if(fast) { } else if(manual || !scan_all) { - for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { - if(!strcmp(sit->second.name.c_str(),scansettings.satNameNoDiseqc)) { - sat.position = sit->first; - strncpy(sat.satName, scansettings.satNameNoDiseqc, 50); - satList.push_back(sat); - break; - } - } + sat.position = CServiceManager::getInstance()->GetSatellitePosition(scansettings.satNameNoDiseqc); + strncpy(sat.satName, scansettings.satNameNoDiseqc, 50); + satList.push_back(sat); } else { - for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { + satellite_map_t & satmap = CServiceManager::getInstance()->SatelliteList(); + for(sit = satmap.begin(); sit != satmap.end(); sit++) { if(sit->second.use_in_scan) { sat.position = sit->first; strncpy(sat.satName, sit->second.name.c_str(), 50); @@ -252,13 +246,14 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) if (system(NEUTRINO_SCAN_START_SCRIPT) != 0) perror(NEUTRINO_SCAN_START_SCRIPT " failed"); } - +#if 0 /* send diseqc type to zapit */ diseqcType = (diseqc_t) scansettings.diseqcMode; g_Zapit->setDiseqcType(diseqcType); /* send diseqc repeat to zapit */ g_Zapit->setDiseqcRepeat( scansettings.diseqcRepeat); +#endif g_Zapit->setScanBouquetMode( (CZapitClient::bouquetMode)scansettings.bouquetMode); /* send satellite list to zapit */ @@ -268,7 +263,7 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) /* send scantype to zapit */ g_Zapit->setScanType((CZapitClient::scanType) scansettings.scanType ); - tuned = CFrontend::getInstance()->getStatus(); + tuned = -1; paint(test); /* go */ if(test) { @@ -314,7 +309,7 @@ int CScanTs::exec(CMenuTarget* /*parent*/, const std::string & actionKey) msg = handleMsg(msg, data); } while (!(msg == CRCInput::RC_timeout)); - showSNR(); // FIXME commented until scan slowdown will be solved + showSNR(); } /* to join scan thread */ g_Zapit->stopScan(); @@ -394,9 +389,9 @@ int CScanTs::handleMsg(neutrino_msg_t msg, neutrino_msg_data_t data) int fec = (data >> 8) & 0xFF; int rate = data >> 16; char * f, *s, *m; - CFrontend::getInstance()->getDelSys(fec, (fe_modulation_t)0, f, s, m); // FIXME + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + frontend->getDelSys(fec, (fe_modulation_t)0, f, s, m); // FIXME snprintf(buffer,sizeof(buffer), " %c %d %s %s %s", pol == 0 ? 'H' : 'V', rate, f, s, m); - //(pol == 0) ? sprintf(buffer, "-H") : sprintf(buffer, "-V"); paintLine(xpos2 + xpos_frequency, ypos_frequency, w - xpos_frequency - (7*fw), buffer); } break; @@ -453,8 +448,10 @@ void CScanTs::paintRadar(void) { char filename[30]; - if(tuned != CFrontend::getInstance()->getStatus()) { - tuned = CFrontend::getInstance()->getStatus(); + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + bool status = frontend->getStatus(); + if(tuned != status) { + tuned = status; frameBuffer->loadPal(tuned ? "radar.pal" : "radar_red.pal", 18, 38); } @@ -558,8 +555,9 @@ void CScanTs::showSNR () int posx, posy; int sw; - ssig = CFrontend::getInstance()->getSignalStrength(); - ssnr = CFrontend::getInstance()->getSignalNoiseRatio(); + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + ssig = frontend->getSignalStrength(); + ssnr = frontend->getSignalNoiseRatio(); snr = (ssnr & 0xFFFF) * 100 / 65535; sig = (ssig & 0xFFFF) * 100 / 65535; From 71bca85637a9598a13fe6be589f27ec6277ab83f Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:31:05 +0400 Subject: [PATCH 024/737] streaminfo2.cpp: add frontend class member; show tuner number with name; use channel ca sys map in place of global pmt_caids; simplify paintCASystem --- src/gui/streaminfo2.cpp | 282 ++++++++++++++-------------------------- src/gui/streaminfo2.h | 2 + 2 files changed, 98 insertions(+), 186 deletions(-) diff --git a/src/gui/streaminfo2.cpp b/src/gui/streaminfo2.cpp index 0515b2815..8a5951df1 100644 --- a/src/gui/streaminfo2.cpp +++ b/src/gui/streaminfo2.cpp @@ -40,17 +40,18 @@ #include #include #include -#include +#include +#include #include #include #include #include #include + extern cVideo * videoDecoder; extern cAudio * audioDecoder; extern CRemoteControl *g_RemoteControl; /* neutrino.cpp */ -extern CZapitClient::SatelliteList satList; #if 0 extern CPipSetup * g_Pip0; @@ -115,6 +116,7 @@ int CStreamInfo2::exec (CMenuTarget * parent, const std::string &) if (parent) parent->hide (); + frontend = CFEManager::getInstance()->getLiveFE(); paint (paint_mode); int res = doSignalStrengthLoop (); hide (); @@ -150,9 +152,9 @@ int CStreamInfo2::doSignalStrengthLoop () uint64_t timeoutEnd = CRCInput::calcTimeoutEnd_MS (100); g_RCInput->getMsgAbsoluteTimeout (&msg, &data, &timeoutEnd); - ssig = CFrontend::getInstance()->getSignalStrength(); - ssnr = CFrontend::getInstance()->getSignalNoiseRatio(); - ber = CFrontend::getInstance()->getBitErrorRate(); + ssig = frontend->getSignalStrength(); + ssnr = frontend->getSignalNoiseRatio(); + ber = frontend->getBitErrorRate(); signal.sig = ssig & 0xFFFF; signal.snr = ssnr & 0xFFFF; @@ -246,6 +248,10 @@ int CStreamInfo2::doSignalStrengthLoop () res = menu_return::RETURN_EXIT_ALL; break; } + else if (msg == (neutrino_msg_t) g_settings.key_screenshot) { + CNeutrinoApp::getInstance ()->handleMsg (msg, data); + continue; + } // -- any key --> abort if (msg <= CRCInput::RC_MaxRC) { @@ -285,10 +291,12 @@ void CStreamInfo2::paint_signal_fe_box(int _x, int _y, int w, int h) { int y1; int xd = w/4; - std::string tuner_name = g_Locale->getText(LOCALE_STREAMINFO_SIGNAL); - tuner_name += ": "; - tuner_name += CFrontend::getInstance()->getInfo()->name; - g_Font[font_small]->RenderString(_x, _y+iheight+15, width-10, tuner_name.c_str(), COL_INFOBAR, 0, true); + + int tuner = 1 + frontend->getNumber(); + char tname[255]; + snprintf(tname, sizeof(tname), "%s: %d: %s", g_Locale->getText(LOCALE_STREAMINFO_SIGNAL), tuner, frontend->getInfo()->name); + + g_Font[font_small]->RenderString(_x, _y+iheight+15, width-10, tname /*tuner_name.c_str()*/, COL_INFOBAR, 0, true); sigBox_x = _x; sigBox_y = _y+iheight+15; @@ -602,19 +610,20 @@ void CStreamInfo2::paint_techinfo(int xpos, int ypos) //satellite t_satellite_position satellitePosition = CNeutrinoApp::getInstance ()->channelList->getActiveSatellitePosition (); - sat_iterator_t sit = satellitePositions.find(satellitePosition); - if(sit != satellitePositions.end()) { - ypos += iheight; - if(CFrontend::getInstance()->getInfo()->type == FE_QPSK) { - sprintf ((char *) buf, "%s:",g_Locale->getText (LOCALE_SATSETUP_SATELLITE));//swiped locale - } - else if(CFrontend::getInstance()->getInfo()->type == FE_QAM) { - sprintf ((char *) buf, "%s:",g_Locale->getText (LOCALE_CHANNELLIST_PROVS)); - } - g_Font[font_info]->RenderString(xpos, ypos, box_width, buf, COL_INFOBAR, 0, true); // UTF-8 - sprintf ((char *) buf, "%s", sit->second.name.c_str()); - g_Font[font_info]->RenderString (xpos+spaceoffset, ypos, box_width, buf, COL_INFOBAR, 0, true); // UTF-8 + + ypos += iheight; + if(frontend->getInfo()->type == FE_QPSK) { + sprintf ((char *) buf, "%s:",g_Locale->getText (LOCALE_SATSETUP_SATELLITE));//swiped locale } + else if(frontend->getInfo()->type == FE_QAM) { + sprintf ((char *) buf, "%s:",g_Locale->getText (LOCALE_CHANNELLIST_PROVS)); + } + g_Font[font_info]->RenderString(xpos, ypos, box_width, buf, COL_INFOBAR, 0, true); // UTF-8 + + sprintf ((char *) buf, "%s", + CServiceManager::getInstance()->GetSatelliteName(satellitePosition).c_str()); + g_Font[font_info]->RenderString (xpos+spaceoffset, ypos, box_width, buf, COL_INFOBAR, 0, true); // UTF-8 + CChannelList *channelList = CNeutrinoApp::getInstance ()->channelList; // int curnum = channelList->getActiveChannelNumber(); // CZapitChannel * channel = channelList->getChannel(curnum); @@ -629,8 +638,8 @@ void CStreamInfo2::paint_techinfo(int xpos, int ypos) //tsfrequenz ypos += iheight; char * f=NULL, *s=NULL, *m=NULL; - if(CFrontend::getInstance()->getInfo()->type == FE_QPSK) { - CFrontend::getInstance()->getDelSys((fe_code_rate_t)si.fec, dvbs_get_modulation((fe_code_rate_t)si.fec), f, s, m); + if(frontend->getInfo()->type == FE_QPSK) { + frontend->getDelSys((fe_code_rate_t)si.fec, dvbs_get_modulation((fe_code_rate_t)si.fec), f, s, m); if (!strncmp(s,const_cast("DVB-S2"),6)){ s=const_cast("S2"); scaling = 27000; @@ -643,7 +652,7 @@ void CStreamInfo2::paint_techinfo(int xpos, int ypos) g_Font[font_info]->RenderString(xpos, ypos, box_width, "Tp. Freq.:" , COL_INFOBAR, 0, true); // UTF-8 g_Font[font_info]->RenderString(xpos+spaceoffset, ypos, box_width, buf, COL_INFOBAR, 0, true); // UTF-8 } - else if(CFrontend::getInstance()->getInfo()->type == FE_QAM) { + else if(frontend->getInfo()->type == FE_QAM) { sprintf ((char *) buf, "%s",g_Locale->getText (LOCALE_SCANTS_FREQDATA)); g_Font[font_info]->RenderString(xpos, ypos, box_width, buf , COL_INFOBAR, 0, true); // UTF-8 sprintf((char*) buf, "%d.%d MHz", si.tsfrequency/1000, si.tsfrequency%1000); @@ -728,187 +737,88 @@ void CStreamInfo2::paint_techinfo(int xpos, int ypos) paintCASystem(xpos,ypos); } +#define NUM_CAIDS 11 void CStreamInfo2::paintCASystem(int xpos, int ypos) { - extern int pmt_caids[4][11]; - unsigned short i,j, ypos1 = 0; + unsigned short i, ypos1 = 0; int box_width = width*2/3-10; if(box_h2 > 0) { frameBuffer->paintBoxRel (0, ypos+(iheight*2), box_width, box_h2, COL_MENUHEAD_PLUS_0); } - std::string casys[11]={"Irdeto:","Betacrypt:","Seca:","Viaccess:","Nagra:","Conax: ","Cryptoworks:","Videoguard:","EBU:","XCrypt:","PowerVU:"}; - bool caids[11] ={ false, false, false, false, false, false, false, false, false, false, false }; - char tmp[100] = {0}; - int array[11] = {0}; - for(i = 0; i < 11; i++){ - array[i]=0; - array[i] = g_Font[font_info]->getRenderWidth( casys[i].c_str() ); + std::string casys[NUM_CAIDS]={"Irdeto:","Betacrypt:","Seca:","Viaccess:","Nagra:","Conax: ","Cryptoworks:","Videoguard:","EBU:","XCrypt:","PowerVU:"}; + bool caids[NUM_CAIDS]; + int array[NUM_CAIDS]; + char tmp[100]; + + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if(!channel) + return; + + for(i = 0; i < NUM_CAIDS; i++) { + array[i] = g_Font[font_info]->getRenderWidth(casys[i].c_str()); + caids[i] = false; } - for(j=0;j<4;j++){ - for(i=0;i<11;i++){ - if(pmt_caids[j][i] > 1 && i == 0){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 1){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 2){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 3){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 4){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 5){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 6){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 7){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 8){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 9){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } - else if(pmt_caids[j][i] > 1 && i == 10){ - for( int k = 0; k < 4;k++){ - if(pmt_caids[j][i] == pmt_caids[k][i] && ( j != k)){ - pmt_caids[j][i]=1; - } - } - if(pmt_caids[j][i] > 1 ) - { - snprintf(tmp,sizeof(tmp)," 0x%04X",pmt_caids[j][i]); - casys[i] += tmp; - } - caids[i] = true; - } + int spaceoffset = 0; + + for(casys_map_iterator_t it = channel->camap.begin(); it != channel->camap.end(); ++it) { + int idx = -1; + switch(((*it) >> 8) & 0xFF) { + case 0x06: + idx = 0; + break; + case 0x17: + idx = 1; + break; + case 0x01: + idx = 2; + break; + case 0x05: + idx = 3; + break; + case 0x18: + idx = 4; + break; + case 0x0B: + idx = 5; + break; + case 0x0D: + idx = 6; + break; + case 0x09: + idx = 7; + break; + case 0x26: + idx = 8; + break; + case 0x4a: + idx = 9; + break; + case 0x0E: + idx = 10; + break; + default: + break; + } + if(idx >= 0) { + snprintf(tmp, sizeof(tmp)," 0x%04X", (*it)); + casys[idx] += tmp; + caids[idx] = true; + if(spaceoffset < array[idx]) + spaceoffset = array[idx]; } } - int spaceoffset = 0 ; - for(i=0 ; i<11; i++){ - if(caids[i] == true) - if(spaceoffset < array[i]) - spaceoffset = array[i]; - } spaceoffset+=4; ypos += iheight*2; bool cryptsysteme = true; - for(int ca_id = 0;ca_id < 11;ca_id++){ + for(int ca_id = 0; ca_id < NUM_CAIDS; ca_id++){ if(caids[ca_id] == true){ if(cryptsysteme){ ypos += iheight; - g_Font[font_info]->RenderString(xpos , ypos, box_width, "Cryptsysteme:" , COL_INFOBAR, 0, false); + g_Font[font_info]->RenderString(xpos , ypos, box_width, "Conditional access:" , COL_INFOBAR, 0, false); cryptsysteme = false; } ypos += sheight; diff --git a/src/gui/streaminfo2.h b/src/gui/streaminfo2.h index 5a2d19115..dd6b553d2 100644 --- a/src/gui/streaminfo2.h +++ b/src/gui/streaminfo2.h @@ -27,6 +27,7 @@ #include #include +#include class CStreamInfo2 : public CMenuTarget @@ -34,6 +35,7 @@ class CStreamInfo2 : public CMenuTarget private: CFrameBuffer *frameBuffer; + CFrontend *frontend; int x; int y; int width; From 59b74261b389c6733b04871771a49f1769b7b127 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:32:01 +0400 Subject: [PATCH 025/737] test_menu.cpp: use CFEManager API to get frontend --- src/gui/test_menu.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/test_menu.cpp b/src/gui/test_menu.cpp index 783468139..c602b448c 100644 --- a/src/gui/test_menu.cpp +++ b/src/gui/test_menu.cpp @@ -48,7 +48,7 @@ #include "gui/widget/hintbox.h" #include "gui/scan.h" #include "gui/scan_setup.h" -#include +#include extern int cs_test_card(int unit, char * str); @@ -254,7 +254,8 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) sprintf(scansettings.TP_freq, "%d", freq); #if 0 // not needed ? - switch (CFrontend::getInstance()->getInfo()->type) + CFrontend * frontend = CFEManager::getInstance()->getFE(0); + switch (frontend->getInfo()->type) { case FE_QPSK: sprintf(scansettings.TP_rate, "%d", tmpI->second.feparams.u.qpsk.symbol_rate); @@ -279,7 +280,8 @@ int CTestMenu::exec(CMenuTarget* parent, const std::string &actionKey) int freq = 12538000; sprintf(scansettings.TP_freq, "%d", freq); - switch (CFrontend::getInstance()->getInfo()->type) + CFrontend * frontend = CFEManager::getInstance()->getFE(0); + switch (frontend->getInfo()->type) { case FE_QPSK: sprintf(scansettings.TP_rate, "%d", 41250*1000); From 9b10aadb4f527ef68467b4514ae80b571fac3420 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:42:35 +0400 Subject: [PATCH 026/737] neutrino.cpp: save/load ci clock setting; pass ci_clock to zapit at start time; remove global satellitePositions usage; check for free frontend in quickZap if record running, allow quickZap if found remove code moved to scan_setup updateManualSettings; fix remove background radio picture, if mode was changed for record in standby; save neutrino.conf in signal handler; dont delete frameBuffer after stop_daemons(true) to prevent crash --- src/neutrino.cpp | 74 ++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 35c043b6d..31ccf3e98 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -140,7 +140,9 @@ static pthread_t nhttpd_thread ; //#define DISABLE_SECTIONSD extern int sectionsd_stop; +#ifndef DISABLE_SECTIONSD static pthread_t sections_thread; +#endif void * sectionsd_main_thread(void *data); extern bool timeset; // sectionsd @@ -355,6 +357,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.standby_cpufreq = configfile.getInt32("standby_cpufreq", 100); g_settings.rounded_corners = configfile.getInt32("rounded_corners", 1); g_settings.ci_standby_reset = configfile.getInt32("ci_standby_reset", 0); + g_settings.ci_clock = configfile.getInt32("ci_clock", 7); #ifndef CPU_FREQ g_settings.cpufreq = 0; @@ -801,6 +804,7 @@ void CNeutrinoApp::saveSetup(const char * fname) configfile.setInt32( "standby_cpufreq", g_settings.standby_cpufreq); configfile.setInt32("rounded_corners", g_settings.rounded_corners); configfile.setInt32("ci_standby_reset", g_settings.ci_standby_reset); + configfile.setInt32("ci_clock", g_settings.ci_clock); configfile.setInt32( "make_hd_list", g_settings.make_hd_list); //led @@ -1241,15 +1245,21 @@ void CNeutrinoApp::channelsInit(bool bOnly) /* all TV / RADIO channels per satellite */ sat_iterator_t sit; - for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { + satellite_map_t satlist = CServiceManager::getInstance()->SatelliteList(); + for(sit = satlist.begin(); sit != satlist.end(); sit++) { +#if 0 if(!sit->second.have_channels) continue; +#endif + CServiceManager::getInstance()->GetAllSatelliteChannels(zapitList, sit->first); + if(!zapitList.size()) + continue; tvi = 0, ri = 0; CBouquet* tmp1 = TVsatList->addBouquet(sit->second.name.c_str()); CBouquet* tmp2 = RADIOsatList->addBouquet(sit->second.name.c_str()); - CServiceManager::getInstance()->GetAllSatelliteChannels(zapitList, sit->first); + //CServiceManager::getInstance()->GetAllSatelliteChannels(zapitList, sit->first); for(zapit_list_it_t it = zapitList.begin(); it != zapitList.end(); it++) { if ((*it)->getServiceType() == ST_DIGITAL_TELEVISION_SERVICE) { tmp1->channelList->addChannel(*it); @@ -1638,6 +1648,7 @@ int CNeutrinoApp::run(int argc, char **argv) ZapStart_arg.startchannelradio_nr = g_settings.startchannelradio_nr; ZapStart_arg.uselastchannel = g_settings.uselastchannel; ZapStart_arg.video_mode = g_settings.video_Mode; + ZapStart_arg.ci_clock = g_settings.ci_clock; CZapit::getInstance()->Start(&ZapStart_arg); @@ -1758,10 +1769,12 @@ int CNeutrinoApp::run(int argc, char **argv) InitMenu(); /* wait for sectionsd to be able to process our registration */ +#ifndef DISABLE_SECTIONSD time_t t = time_monotonic_ms(); while (! sectionsd_isReady()) sleep(0); dprintf(DEBUG_NORMAL, "had to wait %ld ms for sectionsd to start up\n", time_monotonic_ms() - t); +#endif dprintf( DEBUG_NORMAL, "registering as event client\n"); @@ -1905,11 +1918,13 @@ void CNeutrinoApp::quickZap(int msg) int res; StopSubtitles(); -#if 1 - if(recordingstatus && !autoshift) -#else +#if 0 CRecordManager::getInstance()->StopAutoRecord(); if(CRecordManager::getInstance()->RecordingStatus()) +#else + //if(recordingstatus && !autoshift) + printf("CNeutrinoApp::quickZap haveFreeFrontend %d\n", CFEManager::getInstance()->haveFreeFrontend()); + if(!CFEManager::getInstance()->haveFreeFrontend()) #endif { res = channelList->numericZap(g_settings.key_zaphistory); @@ -1944,8 +1959,10 @@ void CNeutrinoApp::RealRun(CMenuWidget &mainMenu) if(g_settings.power_standby || init_cec_setting) standbyMode(true); - //cCA::GetInstance()->Ready(true); - +#if 0 +INFO("cCA::GetInstance()->Ready\n"); + cCA::GetInstance()->Ready(true); +#endif while( true ) { g_RCInput->getMsg(&msg, &data, 100, ((g_settings.remote_control_hardware == CKeybindSetup::REMOTECONTROL_NEO1) && (g_RemoteControl->subChannels.size() < 1)) ? true : false); // 10 secs.. @@ -2223,33 +2240,7 @@ int CNeutrinoApp::handleMsg(const neutrino_msg_t _msg, neutrino_msg_data_t data) StartSubtitles(!g_InfoViewer->is_visible); /* update scan settings for manual scan to current channel */ - CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); - if(channel) { - sat_iterator_t sit = satellitePositions.find(channel->getSatellitePosition()); - if(sit != satellitePositions.end()) - strncpy(scanSettings.satNameNoDiseqc, sit->second.name.c_str(), 50); - - transponder_list_t::iterator tI; - tI = transponders.find(channel->getTransponderId()); - if(tI != transponders.end()) { - sprintf(scanSettings.TP_freq, "%d", tI->second.feparams.frequency); - switch (CFrontend::getInstance()->getInfo()->type) { - case FE_QPSK: - sprintf(scanSettings.TP_rate, "%d", tI->second.feparams.u.qpsk.symbol_rate); - scanSettings.TP_fec = tI->second.feparams.u.qpsk.fec_inner; - scanSettings.TP_pol = tI->second.polarization; - break; - case FE_QAM: - sprintf(scanSettings.TP_rate, "%d", tI->second.feparams.u.qam.symbol_rate); - scanSettings.TP_fec = tI->second.feparams.u.qam.fec_inner; - scanSettings.TP_mod = tI->second.feparams.u.qam.modulation; - break; - case FE_OFDM: - case FE_ATSC: - break; - } - } - } + CScanSetup::getInstance()->updateManualSettings(); } if ((msg == NeutrinoMessages::EVT_TIMER)) { if(data == scrambled_timer) { @@ -2905,7 +2896,7 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) saveEpg(); } - stop_daemons(retcode);//need here for timer_is_rec before saveSetup + stop_daemons(true /*retcode*/);//need here for timer_is_rec before saveSetup g_settings.shutdown_timer_record_type = timer_is_rec; saveSetup(NEUTRINO_SETTINGS_FILE); @@ -3025,8 +3016,7 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) delete funNotifier; } //CVFD::getInstance()->ShowText(g_Locale->getText(LOCALE_MAINMENU_REBOOT)); - delete frameBuffer; - + //delete frameBuffer; #if 0 /* FIXME this next hack to test, until we find real crash on exit reason */ system("/etc/init.d/rcK"); system("/bin/sync"); @@ -3237,6 +3227,7 @@ printf("CNeutrinoApp::setVolume dx %d dy %d\n", dx, dy); void CNeutrinoApp::tvMode( bool rezap ) { + INFO("rezap %d current mode %d", rezap, mode); if(mode==mode_radio ) { if (g_settings.radiotext_enable && g_Radiotext) { delete g_Radiotext; @@ -3315,7 +3306,7 @@ void CNeutrinoApp::scartMode( bool bOnOff ) void CNeutrinoApp::standbyMode( bool bOnOff ) { static bool wasshift = false; - //printf( ( bOnOff ) ? "mode: standby on\n" : "mode: standby off\n" ); + INFO("%s", bOnOff ? "ON" : "OFF" ); if( bOnOff ) { if( mode == mode_scart ) { @@ -3419,6 +3410,8 @@ void CNeutrinoApp::standbyMode( bool bOnOff ) if( lastMode == mode_radio ) { radioMode( false ); } else { + /* for standby -> tv mode from radio mode in case of record */ + videoDecoder->StopPicture(); tvMode( false ); } t_channel_id live_channel_id = CZapit::getInstance()->GetCurrentChannelID(); @@ -3447,7 +3440,8 @@ void CNeutrinoApp::standbyMode( bool bOnOff ) void CNeutrinoApp::radioMode( bool rezap) { - printf("radioMode: rezap %s\n", rezap ? "yes" : "no"); + //printf("radioMode: rezap %s\n", rezap ? "yes" : "no"); + INFO("rezap %d current mode %d", rezap, mode); if(mode==mode_tv ) { g_RCInput->killTimer(g_InfoViewer->lcdUpdateTimer); g_InfoViewer->lcdUpdateTimer = g_RCInput->addTimer( LCD_UPDATE_TIME_RADIO_MODE, false ); @@ -3510,7 +3504,6 @@ void CNeutrinoApp::switchClockOnOff() /************************************************************************************** * CNeutrinoApp - exec, menuitem callback (shutdown) * **************************************************************************************/ -void SaveMotorPositions(); int CNeutrinoApp::exec(CMenuTarget* parent, const std::string & actionKey) { @@ -3728,6 +3721,7 @@ void sighandler (int signum) case SIGTERM: case SIGINT: delete CRecordManager::getInstance(); + CNeutrinoApp::getInstance()->saveSetup(NEUTRINO_SETTINGS_FILE); stop_daemons(); _exit(0); default: From 2c131c8117d6165ab1d8e03ff67a7ed6e7dd47d4 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:46:46 +0400 Subject: [PATCH 027/737] libconfigfile: check iterator for end before using it --- lib/libconfigfile/configfile.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/libconfigfile/configfile.cpp b/lib/libconfigfile/configfile.cpp index 8d7677456..d567fee76 100644 --- a/lib/libconfigfile/configfile.cpp +++ b/lib/libconfigfile/configfile.cpp @@ -391,6 +391,8 @@ void CConfigFile::setInt32Vector(const std::string & key, const std::vector::const_iterator it = vec.begin(); ; ) { + if (it == vec.end()) + break; s << (*it); it++; if (it == vec.end()) @@ -406,6 +408,8 @@ void CConfigFile::setStringVector(const std::string & key, const std::vector::const_iterator it = vec.begin(); ; ) { + if (it == vec.end()) + break; configData[key] += *it; it++; if (it == vec.end()) From f442ad8fbc9e5c9a50f08ac03cc0b523b1ce5c40 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:50:08 +0400 Subject: [PATCH 028/737] zapit pmt: convert pmt code to class; remove global pmt_caids; use negative filter for pmt updates --- src/zapit/include/zapit/pmt.h | 19 +- src/zapit/src/pmt.cpp | 420 +++++++++------------------------- 2 files changed, 120 insertions(+), 319 deletions(-) diff --git a/src/zapit/include/zapit/pmt.h b/src/zapit/include/zapit/pmt.h index d858a5ce3..b8db4eb5d 100644 --- a/src/zapit/include/zapit/pmt.h +++ b/src/zapit/include/zapit/pmt.h @@ -25,9 +25,24 @@ #include "channel.h" #include "ci.h" -int parse_pmt(CZapitChannel * const channel); int pmt_set_update_filter(CZapitChannel * const channel, int * fd); int pmt_stop_update_filter(int * fd); -int scan_parse_pmt(int pmtpid, int service_id ); +#define PMT_SECTION_SIZE 1024 +class CPmt +{ + private: + int dmxnum; + unsigned char buffer[PMT_SECTION_SIZE]; + + bool Read(unsigned short pid, unsigned short sid); + void MakeCAMap(casys_map_t &camap); + unsigned short ParseES(const unsigned char * const buff, CZapitChannel * const channel, CCaPmt * const caPmt); + public: + CPmt(int dnum = 0); + ~CPmt(); + + bool parse_pmt(CZapitChannel * const channel); + bool haveCaSys(int pmtpid, int service_id); +}; #endif /* __zapit_pmt_h__ */ diff --git a/src/zapit/src/pmt.cpp b/src/zapit/src/pmt.cpp index b9006374f..d47b0ba47 100644 --- a/src/zapit/src/pmt.cpp +++ b/src/zapit/src/pmt.cpp @@ -55,7 +55,16 @@ * 0xc6 User Private (Canal+) */ -unsigned short parse_ES_info(const unsigned char * const buffer, CZapitChannel * const channel, CCaPmt * const caPmt) +CPmt::CPmt(int dnum) +{ + dmxnum = dnum; +} + +CPmt::~CPmt() +{ +} + +unsigned short CPmt::ParseES(const unsigned char * const buff, CZapitChannel * const channel, CCaPmt * const caPmt) { unsigned short ES_info_length; unsigned short pos; @@ -73,73 +82,46 @@ unsigned short parse_ES_info(const unsigned char * const buffer, CZapitChannel * /* elementary stream info for ca pmt */ CEsInfo *esInfo = new CEsInfo(); - esInfo->stream_type = buffer[0]; - esInfo->reserved1 = buffer[1] >> 5; - esInfo->elementary_PID = ((buffer[1] & 0x1F) << 8) | buffer[2]; - esInfo->reserved2 = buffer[3] >> 4; + esInfo->stream_type = buff[0]; + esInfo->reserved1 = buff[1] >> 5; + esInfo->elementary_PID = ((buff[1] & 0x1F) << 8) | buff[2]; + esInfo->reserved2 = buff[3] >> 4; - ES_info_length = ((buffer[3] & 0x0F) << 8) | buffer[4]; + ES_info_length = ((buff[3] & 0x0F) << 8) | buff[4]; for (pos = 5; pos < ES_info_length + 5; pos += descriptor_length + 2) { - descriptor_tag = buffer[pos]; - descriptor_length = buffer[pos + 1]; + descriptor_tag = buff[pos]; + descriptor_length = buff[pos + 1]; unsigned char fieldCount = descriptor_length / 5; switch (descriptor_tag) { - case 0x02: - video_stream_descriptor(buffer + pos); - break; - - case 0x03: - audio_stream_descriptor(buffer + pos); - break; - case 0x05: if (descriptor_length >= 3) - if (!strncmp((const char*)&buffer[pos + 2], "DTS", 3)) + if (!strncmp((const char*)&buff[pos + 2], "DTS", 3)) isDts = true; break; case 0x09: - esInfo->addCaDescriptor(buffer + pos); + esInfo->addCaDescriptor(buff + pos); descramble = true; break; case 0x0A: /* ISO_639_language_descriptor */ #if 0 -printf("descr 0x0A: %02X %02X %02X\n", buffer[pos+2], buffer[pos+3], buffer[pos+4]); +printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); #endif /* FIXME cyfra+ radio -> 41 20 31 ?? */ - if (description != "" && buffer[pos + 3] == ' ') { - description += buffer[pos + 3]; - description += buffer[pos + 4]; + if (description != "" && buff[pos + 3] == ' ') { + description += buff[pos + 3]; + description += buff[pos + 4]; } else { for (i = 0; i < 3; i++) - description += tolower(buffer[pos + i + 2]); + description += tolower(buff[pos + i + 2]); } break; - case 0x13: /* Defined in ISO/IEC 13818-6 */ - break; - - case 0x0E: - Maximum_bitrate_descriptor(buffer + pos); - break; - - case 0x0F: - Private_data_indicator_descriptor(buffer + pos); - break; - - case 0x11: - STD_descriptor(buffer + pos); - break; - - case 0x45: - VBI_data_descriptor(buffer + pos); - break; - case 0x52: /* stream_identifier_descriptor */ - componentTag = buffer[pos + 2]; + componentTag = buff[pos + 2]; break; case 0x56: /* teletext descriptor */ @@ -147,12 +129,12 @@ printf("descr 0x0A: %02X %02X %02X\n", buffer[pos+2], buffer[pos+3], buffer[pos+ //printf("[pmt] teletext pid %x: %s\n", esInfo->elementary_PID, tmp_Lang); printf("[pmt] teletext pid %x\n", esInfo->elementary_PID); for (unsigned char fIdx = 0; fIdx < fieldCount; fIdx++) { - memmove(tmp_Lang, &buffer[pos + 5*fIdx + 2], 3); + memmove(tmp_Lang, &buff[pos + 5*fIdx + 2], 3); tmp_Lang[3] = '\0'; - unsigned char teletext_type=buffer[pos + 5*fIdx + 5]>> 3; - unsigned char teletext_magazine_number = buffer[pos + 5*fIdx + 5] & 7; - unsigned char teletext_page_number=buffer[pos + 5*fIdx + 6]; -printf("[pmt] teletext type %d mag %d page %d lang %s\n", teletext_type, teletext_magazine_number, teletext_page_number, tmp_Lang); + unsigned char teletext_type=buff[pos + 5*fIdx + 5]>> 3; + unsigned char teletext_magazine_number = buff[pos + 5*fIdx + 5] & 7; + unsigned char teletext_page_number=buff[pos + 5*fIdx + 6]; + printf("[pmt] teletext type %d mag %d page %d lang %s\n", teletext_type, teletext_magazine_number, teletext_page_number, tmp_Lang); if (teletext_type==0x01) channel->setTeletextLang(tmp_Lang); if (teletext_type==0x02){ @@ -173,36 +155,25 @@ printf("[pmt] teletext type %d mag %d page %d lang %s\n", teletext_type, teletex unsigned char fieldCount1=descriptor_length/8; for (unsigned char fIdx=0;fIdxaddDVBSubtitle(esInfo->elementary_PID,tmpLang,subtitling_type,composition_page_id,ancillary_page_id); } descramble = true;//FIXME MGM / 10E scrambling subtitles ? } - subtitling_descriptor(buffer + pos); - break; - - case 0x5F: - private_data_specifier_descriptor(buffer + pos); - break; - - case 0x66: - data_broadcast_id_descriptor(buffer + pos); + subtitling_descriptor(buff + pos); break; case 0x6A: /* AC3 descriptor */ isAc3 = true; break; - case 0x6F: /* unknown, Astra 19.2E */ - break; - case 0x7B: isDts = true; break; @@ -211,50 +182,8 @@ printf("[pmt] teletext type %d mag %d page %d lang %s\n", teletext_type, teletex isAac = true; break; - case 0x90: /* unknown, Astra 19.2E */ - break; - - case 0xB1: /* unknown, Astra 19.2E */ - break; - - case 0xC0: /* unknown, Astra 19.2E */ - break; - - case 0xC1: /* unknown, Astra 19.2E */ - break; - - case 0xC2: /* User Private descriptor - Canal+ */ -#if 0 - DBG("0xC2 dump:"); - for (i = 0; i < descriptor_length; i++) { - printf("%c", buffer[pos + 2 + i]); - if (((i+1) % 8) == 0) - printf("\n"); - } -#endif - break; - case 0xC5: /* User Private descriptor - Canal+ Radio */ - //description = convertDVBUTF8((const char*)&buffer[pos+3], 24, 2, 1); - description = convertDVBUTF8((const char*)&buffer[pos+3], 24, 2, channel->getTransportStreamId() << 16 | channel->getOriginalNetworkId()); -#if 0 -printf("descr 0xC5\n"); - for (i = 0; i < 24; i++) { -printf("%02X ", buffer[pos + i]); - //description += buffer[pos + i + 3]; - } -printf("\n"); -printf("[pmt] name %s\n", description.c_str()); -#endif - break; - - case 0xC6: /* unknown, Astra 19.2E */ - break; - - case 0xFD: /* unknown, Astra 19.2E */ - break; - - case 0xFE: /* unknown, Astra 19.2E */ + description = convertDVBUTF8((const char*)&buff[pos+3], 24, 2, channel->getTransportStreamId() << 16 | channel->getOriginalNetworkId()); break; default: @@ -291,17 +220,17 @@ printf("[pmt] name %s\n", description.c_str()); int tmp=0; // Houdini: shameless stolen from enigma dvbservices.cpp for (pos = 5; pos < ES_info_length + 5; pos += descriptor_length + 2) { - descriptor_tag = buffer[pos]; - descriptor_length = buffer[pos + 1]; + descriptor_tag = buff[pos]; + descriptor_length = buff[pos + 1]; switch (descriptor_tag) { case 0x5F: //DESCR_PRIV_DATA_SPEC: - if ( ((buffer[pos + 2]<<24) | (buffer[pos + 3]<<16) | (buffer[pos + 4]<<8) | (buffer[pos + 5])) == 190 ) + if ( ((buff[pos + 2]<<24) | (buff[pos + 3]<<16) | (buff[pos + 4]<<8) | (buff[pos + 5])) == 190 ) tmp |= 1; break; case 0x90: { - if ( descriptor_length == 4 && !buffer[pos + 2] && !buffer[pos + 3] && buffer[pos + 4] == 0xFF && buffer[pos + 5] == 0xFF ) + if ( descriptor_length == 4 && !buff[pos + 2] && !buff[pos + 3] && buff[pos + 4] == 0xFF && buff[pos + 5] == 0xFF ) tmp |= 2; } //break;?? @@ -365,26 +294,8 @@ printf("[pmt] name %s\n", description.c_str()); if(!CServiceScan::getInstance()->Scanning()) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::AAC, description, componentTag); break; - case 0x0B: - break; - - case 0x90: - break; - - case 0x93: - break; - - case 0xC0: - break; - - case 0xC1: - break; - - case 0xC6: - break; - default: - DBG("stream_type: %02x\n", esInfo->stream_type); + INFO("stream_type: %02x\n", esInfo->stream_type); break; } @@ -396,48 +307,21 @@ printf("[pmt] name %s\n", description.c_str()); return ES_info_length; } -int curpmtpid,curservice_id; -int pmt_caids[4][11] = {{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0}}; - -int parse_pmt(CZapitChannel * const channel) +bool CPmt::Read(unsigned short pid, unsigned short sid) { - int pmtlen; - int ia, dpmtlen, pos; - unsigned char descriptor_length=0; - - unsigned char buffer[PMT_SIZE]; - - /* current position in buffer */ - unsigned short i,j; - for(j=0;j<4;j++){ - for(i=0;i<11;i++) - pmt_caids[j][i] = 0; - } - /* length of elementary stream description */ - unsigned short ES_info_length; - - /* TS_program_map_section elements */ - unsigned short section_length; - unsigned short program_info_length; - + bool ret = true; unsigned char filter[DMX_FILTER_SIZE]; unsigned char mask[DMX_FILTER_SIZE]; - printf("[zapit] parsing pmt pid 0x%X\n", channel->getPmtPid()); - - if (channel->getPmtPid() == 0){ - return -1; - } - - cDemux * dmx = new cDemux(); + cDemux * dmx = new cDemux(dmxnum); dmx->Open(DMX_PSI_CHANNEL); memset(filter, 0x00, DMX_FILTER_SIZE); memset(mask, 0x00, DMX_FILTER_SIZE); filter[0] = 0x02; /* table_id */ - filter[1] = channel->getServiceId() >> 8; - filter[2] = channel->getServiceId(); + filter[1] = sid >> 8; + filter[2] = sid; filter[3] = 0x01; /* current_next_indicator */ filter[4] = 0x00; /* section_number */ mask[0] = 0xFF; @@ -445,83 +329,55 @@ int parse_pmt(CZapitChannel * const channel) mask[2] = 0xFF; mask[3] = 0x01; mask[4] = 0xFF; - - if ((dmx->sectionFilter(channel->getPmtPid(), filter, mask, 5) < 0) || (dmx->Read(buffer, PMT_SIZE) < 0)) { - delete dmx; - return -1; + if ((dmx->sectionFilter(pid, filter, mask, 5) < 0) || (dmx->Read(buffer, PMT_SIZE) < 0)) { + printf("CPmt::Read: pid %x failed\n", pid); + ret = false; } delete dmx; + return ret; +} + +void CPmt::MakeCAMap(casys_map_t &camap) +{ + int pmtlen; + int pos; + unsigned char descriptor_length=0; - curservice_id = channel->getServiceId(); - curpmtpid = channel->getPmtPid(); pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] +3; - - dpmtlen=0; pos=10; - short int ci0 = 0, ci1 = 0, ci2 = 0, ci3 = 0, ci4 = 0, ci5 = 0, ci6 = 0, ci7 = 0, ci8 = 0, ci9 = 0, ci10 = 0; - if(!CServiceScan::getInstance()->Scanning()) { - while(pos+20) { - switch(buffer[ia+2]) { - case 0x06: pmt_caids[ci0][0] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci0 < 3) ci0++; - break; - case 0x17: pmt_caids[ci1][1] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci1 < 3) ci1++; - break; - case 0x01: pmt_caids[ci2][2] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci2 < 3) ci2++; - break; - case 0x05: pmt_caids[ci3][3] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci3 < 3) ci3++; - break; - case 0x18: pmt_caids[ci4][4] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci4 < 3) ci4++; - break; - case 0x0B: pmt_caids[ci5][5] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci5 < 3) ci5++; - break; - case 0x0D: pmt_caids[ci6][6] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci6 < 3) ci6++; - break; - case 0x09: pmt_caids[ci7][7] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci7 < 3) ci7++; - break; - case 0x26: pmt_caids[ci8][8] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci8 < 3) ci8++; - break; - case 0x4a: pmt_caids[ci9][9] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci9 < 3) ci9++; - break; - case 0x0E: pmt_caids[ci10][10] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; - if(ci10 < 3) ci10++; - break; - } //switch - } // if - } // for - pos+=dpmtlen+5; - } // while -#if 0 - fout=fopen("/tmp/caids.info","w"); - if(fout) { - fprintf(fout, "%d %d %d %d %d %d %d %d %d %d\n", caids[0],caids[1],caids[2],caids[3],caids[4],caids[5], caids[6], caids[7], caids[8], caids[9]); - fclose(fout); + camap.clear(); + while(pos + 2 < pmtlen) { + int dpmtlen=((buffer[pos] & 0x0f) << 8) | buffer[pos+1]; + for (int ia = pos+2; ia < (dpmtlen+pos+2);ia += descriptor_length + 2) { + descriptor_length = buffer[ia+1]; + if (ia < pmtlen - 4) + if(buffer[ia] == 0x09 && buffer[ia + 1] > 0) { + int caid = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3];; + camap.insert(caid); + } } + pos += dpmtlen + 5; + } +} -#endif - } /* if !CServiceScan::getInstance()->Scanning() */ - CCaPmt *caPmt = new CCaPmt(); +bool CPmt::parse_pmt(CZapitChannel * const channel) +{ + unsigned short i; + + /* length of elementary stream description */ + unsigned short ES_info_length; + + printf("[zapit] parsing pmt pid 0x%X\n", channel->getPmtPid()); + + if (channel->getPmtPid() == 0) + return false; + + if(!Read(channel->getPmtPid(), channel->getServiceId())) + return false; /* ca pmt */ - caPmt->program_number = (buffer[3] << 8) + buffer[4]; - caPmt->reserved1 = buffer[5] >> 6; - caPmt->version_number = (buffer[5] >> 1) & 0x1F; - caPmt->current_next_indicator = buffer[5] & 0x01; - caPmt->reserved2 = buffer[10] >> 4; + CCaPmt *caPmt = new CCaPmt(buffer); + caPmt->ca_pmt_pid = channel->getPmtPid(); printf("[pmt] pcr pid: old 0x%x new 0x%x\n", channel->getPcrPid(), ((buffer[8] & 0x1F) << 8) + buffer[9]); @@ -530,14 +386,11 @@ int parse_pmt(CZapitChannel * const channel) channel->resetPids(); } /* pmt */ - section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; - //if(!channel->getPidsFlag()) - channel->setPcrPid(((buffer[8] & 0x1F) << 8) + buffer[9]); + channel->setPcrPid(((buffer[8] & 0x1F) << 8) + buffer[9]); - program_info_length = ((buffer[10] & 0x0F) << 8) | buffer[11]; - - if (program_info_length) + unsigned short program_info_length = ((buffer[10] & 0x0F) << 8) | buffer[11]; + if (program_info_length) { for (i = 12; i < 12 + program_info_length; i += buffer[i + 1] + 2) switch (buffer[i]) { case 0x09: @@ -547,20 +400,25 @@ int parse_pmt(CZapitChannel * const channel) DBG("decriptor_tag: %02x\n", buffer[i]); break; } + } /* pmt */ + unsigned short section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; for (i = 12 + program_info_length; i < section_length - 1; i += ES_info_length + 5) - ES_info_length = parse_ES_info(buffer + i, channel, caPmt); + ES_info_length = ParseES(buffer + i, channel, caPmt); if(CServiceScan::getInstance()->Scanning()) { channel->setCaPmt(NULL); channel->setRawPmt(NULL); delete caPmt; } else { + MakeCAMap(channel->camap); channel->setCaPmt(caPmt); + int pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] + 3; unsigned char * p = new unsigned char[pmtlen]; memmove(p, buffer, pmtlen); channel->setRawPmt(p, pmtlen); + channel->scrambled = !channel->camap.empty(); } #if 0 //Quick&Dirty Hack to support Premiere's EPG not only on the portal but on the subchannels as well @@ -573,90 +431,18 @@ int parse_pmt(CZapitChannel * const channel) #endif channel->setPidsFlag(); - return 0; + return true; } -int scan_parse_pmt(int pmtpid, int service_id ) +bool CPmt::haveCaSys(int pmtpid, int service_id ) { - if((pmtpid < 1 ) || (curpmtpid == pmtpid && service_id != curservice_id)) - return -1; - if(curpmtpid == pmtpid && service_id == curservice_id){ - for(int i=0;i<11;i++){ - if(pmt_caids[0][i] > 0) - return 1; - } - return 0; - } - - int pmtlen; - int ia, dpmtlen, pos; - unsigned char descriptor_length=0; - const short pmt_size = 1024; - - unsigned char buffer[pmt_size]; - - unsigned char filter[DMX_FILTER_SIZE]; - unsigned char mask[DMX_FILTER_SIZE]; - - cDemux * dmx = new cDemux(); - dmx->Open(DMX_PSI_CHANNEL); - - memset(filter, 0x00, DMX_FILTER_SIZE); - memset(mask, 0x00, DMX_FILTER_SIZE); - - filter[0] = 0x02; /* table_id */ - filter[1] = service_id >> 8; - filter[2] = service_id; - filter[3] = 0x01; /* current_next_indicator */ - filter[4] = 0x00; /* section_number */ - mask[0] = 0xFF; - mask[1] = 0xFF; - mask[2] = 0xFF; - mask[3] = 0x01; - mask[4] = 0xFF; - - if ((dmx->sectionFilter(pmtpid, filter, mask, 5) < 0) || (dmx->Read(buffer, pmt_size) < 0)) { - delete dmx; - return -1; - } - delete dmx; - pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] +3; - - dpmtlen=0; - pos=10; - if(service_id == ((buffer[3] << 8) | buffer[4]) ){ - while(pos+20) { - switch(buffer[ia+2]) { - case 0x06: - case 0x17: - case 0x01: - case 0x05: - case 0x18: - case 0x0B: - case 0x0D: - case 0x09: - case 0x26: - case 0x4a: - case 0x0E: - return 1; - } //switch - } // if - } // for - pos+=dpmtlen+5; - } // while - return 0; - } - return -1; + if(!Read(pmtpid, service_id)) + return false; + casys_map_t camap; + MakeCAMap(camap); + return !camap.empty(); } -#ifndef DMX_SET_NEGFILTER_MASK - #define DMX_SET_NEGFILTER_MASK _IOW('o',48,uint8_t *) -#endif cDemux * pmtDemux; @@ -689,7 +475,7 @@ int pmt_set_update_filter(CZapitChannel * const channel, int * fd) mask[4] = 0xFF; printf("[pmt] set update filter, sid 0x%x pid 0x%x version %x\n", channel->getServiceId(), channel->getPmtPid(), channel->getCaPmt()->version_number); -#if HAVE_COOL_HARDWARE +#if 0 //HAVE_COOL_HARDWARE filter[3] = (((channel->getCaPmt()->version_number + 1) & 0x01) << 1) | 0x01; mask[3] = (0x01 << 1) | 0x01; pmtDemux->sectionFilter(channel->getPmtPid(), filter, mask, 5); From 109d74c24b0eb8c6786b31000e90ded765fc8435 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 15:59:49 +0400 Subject: [PATCH 029/737] capmt: remember source demux for updates; use record demux from channel --- src/zapit/include/zapit/cam.h | 2 ++ src/zapit/src/cam.cpp | 14 +++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/zapit/include/zapit/cam.h b/src/zapit/include/zapit/cam.h index 3d8c8b735..ebfcf5d7c 100644 --- a/src/zapit/include/zapit/cam.h +++ b/src/zapit/include/zapit/cam.h @@ -46,6 +46,7 @@ class CCam : public CBasicClient virtual unsigned char getVersion(void) const; virtual const char *getSocketName(void) const; int camask, demuxes[3]; + int source_demux; public: CCam(); @@ -53,6 +54,7 @@ class CCam : public CBasicClient bool setCaPmt(CCaPmt * const caPmt, int _demux = 0, int _camask = 1, bool update = false); int getCaMask(void) { return camask; }; int makeMask(int demux, bool add); + int getSource() { return source_demux; }; }; typedef std::map cammap_t; diff --git a/src/zapit/src/cam.cpp b/src/zapit/src/cam.cpp index 99b42ee28..d66212b3b 100644 --- a/src/zapit/src/cam.cpp +++ b/src/zapit/src/cam.cpp @@ -33,6 +33,7 @@ CCam::CCam() { camask = 0; demuxes[0] = demuxes[1] = demuxes[2] = 0; + source_demux = -1; } unsigned char CCam::getVersion(void) const @@ -72,6 +73,7 @@ bool CCam::sendMessage(const char * const data, const size_t length, bool update bool CCam::setCaPmt(CCaPmt * const caPmt, int _demux, int _camask, bool update) { camask = _camask; + source_demux = _demux; printf("CCam::setCaPmt cam %x source %d camask %d update %s\n", (int) this, _demux, camask, update ? "yes" : "no" ); if(camask == 0) { @@ -140,7 +142,7 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start printf("CCamManager: channel %llx not found\n", channel_id); return false; } - +printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", force_update); mutex.lock(); if(channel->getCaPmt() == NULL) { printf("CCamManager: channel %llx dont have caPmt\n", channel_id); @@ -148,8 +150,6 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start return false; } - sat_iterator_t sit = satellitePositions.find(channel->getSatellitePosition()); - cammap_iterator_t it = channel_map.find(channel_id); if(it != channel_map.end()) { cam = it->second; @@ -167,8 +167,8 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start demux = LIVE_DEMUX; break; case RECORD: - source = DEMUX_SOURCE_0; - demux = RECORD_DEMUX;//FIXME + source = channel->getRecordDemux(); //DEMUX_SOURCE_0;//FIXME + demux = channel->getRecordDemux(); //RECORD_DEMUX;//FIXME break; case STREAM: source = DEMUX_SOURCE_0; @@ -182,6 +182,10 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start else newmask = cam->makeMask(demux, start); + if(cam->getSource() > 0) + source = cam->getSource(); + +printf("CCam::SetMode: source %d old mask %d new mask %d force update %s\n", source, oldmask, newmask, force_update ? "yes" : "no"); if((oldmask != newmask) || force_update) cam->setCaPmt(channel->getCaPmt(), source, newmask, true); From 50df9f82457403a918e6e4e7fc706914bc5902d5 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 16:01:48 +0400 Subject: [PATCH 030/737] sdt: change to use new pat/pmt classes; use new CServiceScan and CFEManager API --- src/zapit/src/sdt.cpp | 58 +++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/zapit/src/sdt.cpp b/src/zapit/src/sdt.cpp index 210bcb25d..7a55c9120 100644 --- a/src/zapit/src/sdt.cpp +++ b/src/zapit/src/sdt.cpp @@ -29,11 +29,9 @@ #include #include -#include // DEMUX_DEVICE #include -#include -#include -#include +#include +#include #include #define SDT_SIZE 1026 @@ -176,7 +174,7 @@ int parse_sdt( int flen; bool cable_hack_done = false; - bool cable = (CFrontend::getInstance()->getInfo()->type == FE_QAM); + bool cable = (CServiceScan::getInstance()->GetFrontend()->getInfo()->type == FE_QAM); #if 1 flen = 5; memset(filter, 0x00, DMX_FILTER_SIZE); @@ -257,10 +255,11 @@ _repeat: ISO_639_language_descriptor(buffer + pos2); break; - /* case 0x40: - network_name_descriptor(buffer + pos2); - break; - */ + /* + case 0x40: + network_name_descriptor(buffer + pos2); + break; + */ case 0x42: stuffing_descriptor(buffer + pos2); break; @@ -362,10 +361,11 @@ _repeat: goto _repeat; } delete dmx; - +#if 0 sat_iterator_t sit = satellitePositions.find(satellitePosition); if(sit != satellitePositions.end()) sit->second.have_channels = true; +#endif return 0; } @@ -394,7 +394,7 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const unsigned char filter[DMX_FILTER_SIZE]; unsigned char mask[DMX_FILTER_SIZE]; - transponder_id_t current_tp_id = CFrontend::getInstance()->getTsidOnid(); + transponder_id_t current_tp_id = CFEManager::getInstance()->getLiveFE()->getTsidOnid(); memset(filter, 0x00, DMX_FILTER_SIZE); filter[0] = 0x42; @@ -412,13 +412,24 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const mask[6] = 0xFF; mask[7] = 0xFF; - std::vector > sidpmt; - int pat_ok = scan_parse_pat( sidpmt ); + CPat pat; + + int pat_ok = pat.Parse(); cDemux * dmx = new cDemux(); dmx->Open(DMX_PSI_CHANNEL); int ret = -1; + t_service_id current_sid = 0; + unsigned short curent_pmt = 0; + unsigned char current_scrambled = 0; + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if(channel) { + current_sid = channel->getServiceId(); + curent_pmt = channel->getPmtPid(); + current_scrambled = channel->scrambled; + } + //printf("parse_current_sdt: *************** current sid 0x%x ***************\n", current_sid); do { if ((dmx->sectionFilter(0x11, filter, mask, 8) < 0) || (dmx->Read(buffer, SDT_SIZE) < 0)) { delete dmx; @@ -437,11 +448,22 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const EIT_present_following_flag = buffer[pos + 2] & 0x01; running_status = buffer [pos + 3] & 0xE0; - for (unsigned short i=0; i 0) && running_status != 32) { + if(service_id != current_sid) { + CPmt pmt; + tmp_free_CA_mode = pmt.haveCaSys(pmtpid, service_id); + //printf("parse_current_sdt: sid 0x%x scrambled %d\n", service_id, tmp_free_CA_mode); + } else if(pmtpid != curent_pmt) { + ret = -2; + break; + } + else { + tmp_free_CA_mode = current_scrambled; + //printf("parse_current_sdt: skip current sid 0x%x\n", current_sid); } } + if(tmp_free_CA_mode == -1){ free_CA_mode = buffer [pos + 3] & 0x10; }else{ @@ -472,14 +494,14 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const break; } #endif - if(current_tp_id != CFrontend::getInstance()->getTsidOnid()) + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) break; } } while (filter[4]++ != buffer[7]); delete dmx; - if(current_tp_id != CFrontend::getInstance()->getTsidOnid()) + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) ret = -2; return ret; From 985a14dfc0edfcee318ae4f9ab7a176434a1bc7c Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 16:05:30 +0400 Subject: [PATCH 031/737] descriptors: use new pat/pmt classes; use CServiceScan API to get frontend; --- src/zapit/src/descriptors.cpp | 38 ++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/zapit/src/descriptors.cpp b/src/zapit/src/descriptors.cpp index dc43bc83b..e198da888 100644 --- a/src/zapit/src/descriptors.cpp +++ b/src/zapit/src/descriptors.cpp @@ -251,7 +251,8 @@ int satellite_delivery_system_descriptor(const unsigned char * const buffer, t_t transponder_id_t TsidOnid; int modulationSystem, modulationType, rollOff, fec_inner; - if (CFrontend::getInstance()->getInfo()->type != FE_QPSK) + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + if (frontend->getInfo()->type != FE_QPSK) return -1; feparams.frequency = @@ -315,7 +316,8 @@ int satellite_delivery_system_descriptor(const unsigned char * const buffer, t_t int cable_delivery_system_descriptor(const unsigned char * const buffer, t_transport_stream_id transport_stream_id, t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq) { transponder_id_t TsidOnid; - if (CFrontend::getInstance()->getInfo()->type != FE_QAM) + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + if (frontend->getInfo()->type != FE_QAM) return -1; FrontendParameters feparams; @@ -442,6 +444,9 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s CZapitChannel *channel = NULL; bool tpchange = false; static transponder_id_t last_tpid = 0; + + static CPat pat; + //scrambled if(free_ca && scan_fta_flag){ return; @@ -624,7 +629,8 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s CZapitBouquet* bouquet; int bouquetId; char pname[100]; - if (CFrontend::getInstance()->getInfo()->type == FE_QPSK) + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + if (frontend->getInfo()->type == FE_QPSK) snprintf(pname, 100, "[%c%03d.%d] %s", satellitePosition > 0? 'E' : 'W', abs(satellitePosition)/10, abs(satellitePosition)%10, providerName.c_str()); else snprintf(pname, 100, "%s", providerName.c_str()); @@ -654,10 +660,14 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s break; } if(CZapit::getInstance()->scanPids()) { - if(tpchange) - parse_pat(); + if(tpchange) { + //parse_pat(); + pat.Reset(); + pat.Parse(); + } channel->resetPids(); +#if 0 if(!pat_get_pmt_pid(channel)) { if(!parse_pmt(channel)) { //if(channel->getPreAudioPid() == 0 && channel->getVideoPid() == 0) @@ -667,6 +677,15 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s } } } +#endif + if(pat.Parse(channel)) { + CPmt pmt; + if(!pmt.parse_pmt(channel)) { + if ((channel->getPreAudioPid() != 0) || (channel->getVideoPid() != 0)) { + channel->setPidsFlag(); + } + } + } } if(service_type == ST_DIGITAL_TELEVISION_SERVICE && !channel->scrambled) { CZapit::getInstance()->SetCurrentChannelID(channel->getChannelID()); @@ -851,11 +870,12 @@ void subtitling_descriptor(const unsigned char * const) /* 0x5A */ int terrestrial_delivery_system_descriptor(const unsigned char * const) { - if (CFrontend::getInstance()->getInfo()->type != FE_OFDM) - return -1; - /* TODO */ - +#if 0 + CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); + if (frontend->getInfo()->type != FE_OFDM) + return -1; +#endif return 0; } From 73a2f85e35b0b0ec66505a36f48a1d64f1b5b91a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 16:14:02 +0400 Subject: [PATCH 032/737] zapit: split audio pids saving to SaveAudioMap; remove global cam_ci; add CFEManager API to save/load per frontend settings; use new pat/pmt classes; use CFEManager API to close, open, get frontend; set CI clock at startup; cleanup unused code; --- src/zapit/include/zapit/zapit.h | 11 +- src/zapit/src/zapit.cpp | 503 ++++++++++++++++---------------- 2 files changed, 264 insertions(+), 250 deletions(-) diff --git a/src/zapit/include/zapit/zapit.h b/src/zapit/include/zapit/zapit.h index 67c1032b2..d71ba5f73 100644 --- a/src/zapit/include/zapit/zapit.h +++ b/src/zapit/include/zapit/zapit.h @@ -16,7 +16,7 @@ #include #include -#include +#include #define PAL 0 #define NTSC 1 @@ -80,6 +80,8 @@ class CZapit : public OpenThreads::Thread CZapitChannel * current_channel; t_channel_id live_channel_id; + CFrontend * live_fe; + audio_map_t audio_map; bool current_is_nvod; bool standby; @@ -89,12 +91,13 @@ class CZapit : public OpenThreads::Thread int pmt_update_fd; void LoadAudioMap(); - void SaveSettings(bool write_conf, bool write_audio); + void SaveAudioMap(); + void SaveSettings(bool write); void SaveChannelPids(CZapitChannel* channel); void RestoreChannelPids(CZapitChannel* channel); void ConfigFrontend(); - bool TuneChannel(CZapitChannel * channel, bool &transponder_change); + bool TuneChannel(CFrontend *frontend, CZapitChannel * channel, bool &transponder_change); bool ParsePatPmt(CZapitChannel * channel); bool send_data_count(int connfd, int data_count); @@ -161,5 +164,7 @@ class CZapit : public OpenThreads::Thread CZapitChannel * GetCurrentChannel() { return current_channel; }; t_channel_id GetCurrentChannelID() { return live_channel_id; }; void SetCurrentChannelID(const t_channel_id channel_id) { live_channel_id = channel_id; }; + void SetLiveFrontend(CFrontend * fe) { if(fe) live_fe = fe; } + CFrontend * GetLiveFrontend() { return live_fe; }; }; #endif /* __zapit_h__ */ diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index c2764aef5..39f4b1ffa 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -4,6 +4,7 @@ * zapit - d-box2 linux project * * (C) 2001, 2002 by Philipp Leusmann + * Copyright (C) 2011 CoolStream International Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,7 +52,7 @@ #include #include -#include +#include #include #if HAVE_COOL_HARDWARE #include @@ -70,13 +71,12 @@ #include "libtuxtxt/teletext.h" /* globals */ - int sig_delay = 2; // seconds between signal check /* the bouquet manager */ CBouquetManager *g_bouquetManager = NULL; -int cam_ci = 2; // CA_INIT_SC 0 or CA_INIT_CI 1 or CA_INIT_BOTH 2 +//int cam_ci = 2; // CA_INIT_SC 0 or CA_INIT_CI 1 or CA_INIT_BOTH 2 cCA *ca = NULL; extern cDemux * pmtDemux; extern cVideo *videoDecoder; @@ -140,12 +140,13 @@ void CZapit::SendEvent(const unsigned int eventID, const void* eventbody, const eventServer->sendEvent(eventID, CEventServer::INITID_ZAPIT, eventbody, eventbodysize); } -void CZapit::SaveSettings(bool write, bool write_a) +void CZapit::SaveSettings(bool write) { if (current_channel) { // now save the lowest channel number with the current channel_id int c = ((currentMode & RADIO_MODE) ? g_bouquetManager->radioChannelsBegin() : g_bouquetManager->tvChannelsBegin()).getLowestChannelNumberWithChannelID(current_channel->getChannelID()); //printf("LAST CHAN %d !!!!!!!!!!!\n\n\n", c); + //FIXME save last TV/RADIO channel id, always ? if (c >= 0) { if ((currentMode & RADIO_MODE)) lastChannelRadio = c; @@ -162,81 +163,88 @@ void CZapit::SaveSettings(bool write, bool write_a) configfile.setInt32("lastChannelTV", lastChannelTV); configfile.setInt64("lastChannel", live_channel_id); } - configfile.setInt32("lastSatellitePosition", CFrontend::getInstance()->getCurrentSatellitePosition()); - configfile.setInt32("diseqcRepeats", CFrontend::getInstance()->getDiseqcRepeats()); - configfile.setInt32("diseqcType", CFrontend::getInstance()->getDiseqcType()); - configfile.setInt32("motorRotationSpeed", config.motorRotationSpeed); configfile.setBool("writeChannelsNames", config.writeChannelsNames); configfile.setBool("makeRemainingChannelsBouquet", config.makeRemainingChannelsBouquet); configfile.setInt32("feTimeout", config.feTimeout); configfile.setInt32("rezapTimeout", config.rezapTimeout); configfile.setBool("scanPids", config.scanPids); - configfile.setBool("highVoltage", config.highVoltage); + configfile.setInt32("scanSDT", config.scanSDT); + configfile.setInt32("cam_ci", config.cam_ci); +#if 0 // unused + configfile.setBool("fastZap", config.fastZap); + configfile.setBool("sortNames", config.sortNames); +#endif + /* FIXME FE global */ char tempd[12]; sprintf(tempd, "%3.6f", config.gotoXXLatitude); configfile.setString("gotoXXLatitude", tempd); sprintf(tempd, "%3.6f", config.gotoXXLongitude); configfile.setString("gotoXXLongitude", tempd); + configfile.setInt32("gotoXXLaDirection", config.gotoXXLaDirection); configfile.setInt32("gotoXXLoDirection", config.gotoXXLoDirection); configfile.setInt32("repeatUsals", config.repeatUsals); - configfile.setInt32("scanSDT", config.scanSDT); +#if 1 + /* FIXME FE specific */ + configfile.setBool("highVoltage", config.highVoltage); + configfile.setInt32("lastSatellitePosition", live_fe->getCurrentSatellitePosition()); + configfile.setInt32("diseqcRepeats", live_fe->getDiseqcRepeats()); + configfile.setInt32("diseqcType", live_fe->getDiseqcType()); + configfile.setInt32("motorRotationSpeed", config.motorRotationSpeed); configfile.setInt32("uni_scr", config.uni_scr); configfile.setInt32("uni_qrg", config.uni_qrg); - - configfile.setInt32("cam_ci", cam_ci); - -#if 0 // unused - configfile.setBool("fastZap", config.fastZap); - configfile.setBool("sortNames", config.sortNames); #endif if (configfile.getModifiedFlag()) configfile.saveConfig(CONFIGFILE); - } - if (write_a) { - FILE *audio_config_file = fopen(AUDIO_CONFIG_FILE, "w"); - if (audio_config_file) { - for (audio_map_iterator_t audio_map_it = audio_map.begin(); audio_map_it != audio_map.end(); audio_map_it++) { - fprintf(audio_config_file, "%llx %d %d %d %d %d %d\n", (uint64_t) audio_map_it->first, - (int) audio_map_it->second.apid, (int) audio_map_it->second.mode, (int) audio_map_it->second.volume, - (int) audio_map_it->second.subpid, (int) audio_map_it->second.ttxpid, (int) audio_map_it->second.ttxpage); - } - fdatasync(fileno(audio_config_file)); - fclose(audio_config_file); - } else - perror(AUDIO_CONFIG_FILE); - } } void CZapit::LoadAudioMap() { FILE *audio_config_file = fopen(AUDIO_CONFIG_FILE, "r"); audio_map.clear(); - if (audio_config_file) { - t_channel_id chan; - int apid = 0, subpid = 0, ttxpid = 0, ttxpage = 0; - int mode = 0; - int volume = 0; - char s[1000]; - while (fgets(s, 1000, audio_config_file)) { - sscanf(s, "%llx %d %d %d %d %d %d", &chan, &apid, &mode, &volume, &subpid, &ttxpid, &ttxpage); - audio_map[chan].apid = apid; - audio_map[chan].subpid = subpid; - audio_map[chan].mode = mode; - audio_map[chan].volume = volume; - audio_map[chan].ttxpid = ttxpid; - audio_map[chan].ttxpage = ttxpage; - } - fclose(audio_config_file); - } else + if (!audio_config_file) { perror(AUDIO_CONFIG_FILE); + return; + } + t_channel_id chan; + int apid = 0, subpid = 0, ttxpid = 0, ttxpage = 0; + int mode = 0; + int volume = 0; + char s[1000]; + while (fgets(s, 1000, audio_config_file)) { + sscanf(s, "%llx %d %d %d %d %d %d", &chan, &apid, &mode, &volume, &subpid, &ttxpid, &ttxpage); + audio_map[chan].apid = apid; + audio_map[chan].subpid = subpid; + audio_map[chan].mode = mode; + audio_map[chan].volume = volume; + audio_map[chan].ttxpid = ttxpid; + audio_map[chan].ttxpage = ttxpage; + } + fclose(audio_config_file); } +void CZapit::SaveAudioMap() +{ + FILE *audio_config_file = fopen(AUDIO_CONFIG_FILE, "w"); + if (!audio_config_file) { + perror(AUDIO_CONFIG_FILE); + return; + } + for (audio_map_iterator_t audio_map_it = audio_map.begin(); audio_map_it != audio_map.end(); audio_map_it++) { + fprintf(audio_config_file, "%llx %d %d %d %d %d %d\n", (uint64_t) audio_map_it->first, + (int) audio_map_it->second.apid, (int) audio_map_it->second.mode, (int) audio_map_it->second.volume, + (int) audio_map_it->second.subpid, (int) audio_map_it->second.ttxpid, (int) audio_map_it->second.ttxpage); + } + fdatasync(fileno(audio_config_file)); + fclose(audio_config_file); +} + + void CZapit::LoadSettings() { if (!configfile.loadConfig(CONFIGFILE)) @@ -252,11 +260,16 @@ void CZapit::LoadSettings() voltageOff = configfile.getBool("voltageOff", 0); #endif config.saveLastChannel = configfile.getBool("saveLastChannel", true); - config.rezapTimeout = configfile.getInt32("rezapTimeout", 1); - config.feTimeout = configfile.getInt32("feTimeout", 40); + /* FIXME Channels renum should be done for all channels atm. TODO*/ + //config.makeRemainingChannelsBouquet = configfile.getBool("makeRemainingChannelsBouquet", 1); + config.makeRemainingChannelsBouquet = 1; config.scanPids = configfile.getBool("scanPids", 0); + config.scanSDT = configfile.getInt32("scanSDT", 0); + config.cam_ci = configfile.getInt32("cam_ci", 2); + config.rezapTimeout = configfile.getInt32("rezapTimeout", 1); + + config.feTimeout = configfile.getInt32("feTimeout", 40); config.highVoltage = configfile.getBool("highVoltage", 0); - config.makeRemainingChannelsBouquet = configfile.getBool("makeRemainingChannelsBouquet", 1); config.gotoXXLatitude = strtod(configfile.getString("gotoXXLatitude", "0.0").c_str(), NULL); config.gotoXXLongitude = strtod(configfile.getString("gotoXXLongitude", "0.0").c_str(), NULL); @@ -264,42 +277,42 @@ void CZapit::LoadSettings() config.gotoXXLoDirection = configfile.getInt32("gotoXXLoDirection", 0); config.repeatUsals = configfile.getInt32("repeatUsals", 0); - config.scanSDT = configfile.getInt32("scanSDT", 0); - + /* FIXME FE specific, to be removed */ + diseqcType = (diseqc_t)configfile.getInt32("diseqcType", NO_DISEQC); + config.motorRotationSpeed = configfile.getInt32("motorRotationSpeed", 18); // default: 1.8 degrees per second config.uni_scr = configfile.getInt32("uni_scr", -1); config.uni_qrg = configfile.getInt32("uni_qrg", 0); - cam_ci = configfile.getInt32("cam_ci", 2); - - diseqcType = (diseqc_t)configfile.getInt32("diseqcType", NO_DISEQC); - config.motorRotationSpeed = configfile.getInt32("motorRotationSpeed", 18); // default: 1.8 degrees per second - - CFrontend::getInstance()->setDiseqcRepeats(configfile.getInt32("diseqcRepeats", 0)); - CFrontend::getInstance()->setCurrentSatellitePosition(configfile.getInt32("lastSatellitePosition", 0)); - CFrontend::getInstance()->setDiseqcType(diseqcType); - - //FIXME globals ! -#if 0 - motorRotationSpeed = config.motorRotationSpeed; - highVoltage = config.highVoltage; - feTimeout = config.feTimeout; - gotoXXLaDirection = config.gotoXXLaDirection; - gotoXXLoDirection = config.gotoXXLoDirection; - gotoXXLatitude = config.gotoXXLatitude; - gotoXXLongitude = config.gotoXXLongitude; - repeatUsals = config.repeatUsals; -#endif printf("[zapit.cpp] diseqc type = %d\n", diseqcType); + + CFEManager::getInstance()->loadSettings(); + /**/ + LoadAudioMap(); } void CZapit::ConfigFrontend() { - CFrontend::getInstance()->setTimeout(config.feTimeout); - CFrontend::getInstance()->configUsals(config.gotoXXLatitude, config.gotoXXLongitude, - config.gotoXXLaDirection, config.gotoXXLoDirection, config.repeatUsals); - CFrontend::getInstance()->configRotor(config.motorRotationSpeed, config.highVoltage); - CFrontend::getInstance()->configUnicable(config.uni_scr, config.uni_qrg); + int count = CFEManager::getInstance()->getFrontendCount(); + for(int i = 0; i < count; i++) { + CFrontend * fe = CFEManager::getInstance()->getFE(i); + if(!fe) + continue; + + fe->setTimeout(config.feTimeout); + fe->configUsals(config.gotoXXLatitude, config.gotoXXLongitude, + config.gotoXXLaDirection, config.gotoXXLoDirection, config.repeatUsals); + + if(!CFEManager::getInstance()->configExist()) { + INFO("New frontend config not exist"); + fe->configRotor(config.motorRotationSpeed, config.highVoltage); + fe->configUnicable(config.uni_scr, config.uni_qrg); + fe->setDiseqcType(diseqcType); + fe->setDiseqcRepeats(configfile.getInt32("diseqcRepeats", 0)); + fe->setCurrentSatellitePosition(configfile.getInt32("lastSatellitePosition", 0)); + fe->setSatellites(CServiceManager::getInstance()->SatelliteList()); + } + } } void CZapit::SendPMT(bool forupdate) @@ -386,13 +399,21 @@ audio_map_set_t * CZapit::GetSavedPids(const t_channel_id channel_id) return NULL; } -bool CZapit::TuneChannel(CZapitChannel * channel, bool &transponder_change) +bool CZapit::TuneChannel(CFrontend * frontend, CZapitChannel * channel, bool &transponder_change) { + //CFrontend * frontend = CFEManager::getInstance()->allocateFE(channel); + if(frontend == NULL) { + ERROR("Cannot get frontend\n"); + return false; + } transponder_change = false; - if (!(currentMode & RECORD_MODE)) { - transponder_change = CFrontend::getInstance()->setInput(channel, current_is_nvod); +#if 0 + if (!(currentMode & RECORD_MODE)) +#endif + { + transponder_change = frontend->setInput(channel, current_is_nvod); if(transponder_change && !current_is_nvod) { - int waitForMotor = CFrontend::getInstance()->driveToSatellitePosition(channel->getSatellitePosition()); + int waitForMotor = frontend->driveToSatellitePosition(channel->getSatellitePosition()); if(waitForMotor > 0) { printf("[zapit] waiting %d seconds for motor to turn satellite dish.\n", waitForMotor); SendEvent(CZapitClient::EVT_ZAP_MOTOR, &waitForMotor, sizeof(waitForMotor)); @@ -408,40 +429,33 @@ bool CZapit::TuneChannel(CZapitChannel * channel, bool &transponder_change) /* if channel's transponder does not match frontend's tuned transponder ... */ if (transponder_change || current_is_nvod) { - if (CFrontend::getInstance()->tuneChannel(channel, current_is_nvod) == false) { + if (frontend->tuneChannel(channel, current_is_nvod) == false) { return false; } } - } else if(!SAME_TRANSPONDER(channel->getChannelID(), live_channel_id)) + } +#if 0 + else if(!SAME_TRANSPONDER(channel->getChannelID(), live_channel_id)) return false; - +#endif return true; } bool CZapit::ParsePatPmt(CZapitChannel * channel) { + CPat pat(channel->getRecordDemux()); + CPmt pmt(channel->getRecordDemux()); DBG("looking up pids for channel_id " PRINTF_CHANNEL_ID_TYPE "\n", channel->getChannelID()); - /* get program map table pid from program association table */ - if (channel->getPmtPid() == 0) { - printf("[zapit] no pmt pid, going to parse pat\n"); - if (parse_pat(channel) < 0) { - printf("[zapit] pat parsing failed\n"); - return false; - } + + if(!pat.Parse(channel)) { + printf("[zapit] pat parsing failed\n"); + return false; + } + if (!pmt.parse_pmt(channel)) { + printf("[zapit] pmt parsing failed\n"); + return false; } - /* parse program map table and store pids */ - if (parse_pmt(channel) < 0) { - printf("[zapit] pmt parsing failed\n"); - if (parse_pat(channel) < 0) { - printf("pat parsing failed\n"); - return false; - } - else if (parse_pmt(channel) < 0) { - printf("[zapit] pmt parsing failed\n"); - return false; - } - } return true; } @@ -459,6 +473,16 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay return false; } + printf("[zapit] zap to %s (%llx tp %llx)\n", newchannel->getName().c_str(), newchannel->getChannelID(), newchannel->getTransponderId()); + + CFrontend * fe = CFEManager::getInstance()->allocateFE(newchannel); + if(fe == NULL) { + ERROR("Cannot get frontend\n"); + return false; + } + live_fe = fe; + CFEManager::getInstance()->setLiveFE(live_fe); + sig_delay = 2; if (!firstzap && current_channel) SaveChannelPids(current_channel); @@ -477,30 +501,16 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay current_channel = newchannel; live_channel_id = current_channel->getChannelID(); - SaveSettings(false, false); + SaveSettings(false); - printf("[zapit] zap to %s (%llx)\n", current_channel->getName().c_str(), live_channel_id); - - if(!TuneChannel(newchannel, transponder_change)) + if(!TuneChannel(live_fe, newchannel, transponder_change)) return false; + if (current_channel->getServiceType() == ST_NVOD_REFERENCE_SERVICE) { current_is_nvod = true; return true; } -#if 0 //FIXME improve or remove ? this is to start playback before pmt - //bool we_playing = channel->getPidsFlag();//FIXME: this starts playback before pmt - bool we_playing = 0; - - if (we_playing) { - printf("[zapit] channel have pids: vpid %X apid %X pcr %X\n", current_channel->getVideoPid(), current_channel->getPreAudioPid(), current_channel->getPcrPid());fflush(stdout); - if((current_channel->getAudioChannelCount() <= 0) && current_channel->getPreAudioPid() > 0) { - std::string desc = "Preset"; - current_channel->addAudioChannel(current_channel->getPreAudioPid(), CZapitAudioChannel::MPEG, desc, 0xFF); - } - StartPlayBack(current_channel); - } -#endif failed = !ParsePatPmt(current_channel); @@ -547,7 +557,13 @@ bool CZapit::ZapForRecord(const t_channel_id channel_id) return false; } printf("%s: %s (%llx)\n", __FUNCTION__, newchannel->getName().c_str(), channel_id); - if(!TuneChannel(newchannel, transponder_change)) + + CFrontend * frontend = CFEManager::getInstance()->allocateFE(newchannel); + if(frontend == NULL) { + ERROR("Cannot get frontend\n"); + return false; + } + if(!TuneChannel(frontend, newchannel, transponder_change)) return false; if(!ParsePatPmt(newchannel)) @@ -777,7 +793,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) } case CZapitMessages::CMD_GET_CURRENT_SATELLITE_POSITION: { - int32_t currentSatellitePosition = current_channel ? current_channel->getSatellitePosition() : CFrontend::getInstance()->getCurrentSatellitePosition(); + int32_t currentSatellitePosition = current_channel ? current_channel->getSatellitePosition() : live_fe->getCurrentSatellitePosition(); CBasicServer::send_data(connfd, ¤tSatellitePosition, sizeof(currentSatellitePosition)); break; } @@ -826,16 +842,16 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) msgCurrentServiceInfo.pmtpid = current_channel->getPmtPid(); msgCurrentServiceInfo.pmt_version = (current_channel->getCaPmt() != NULL) ? current_channel->getCaPmt()->version_number : 0xff; msgCurrentServiceInfo.pcrpid = current_channel->getPcrPid(); - msgCurrentServiceInfo.tsfrequency = CFrontend::getInstance()->getFrequency(); - msgCurrentServiceInfo.rate = CFrontend::getInstance()->getRate(); - msgCurrentServiceInfo.fec = CFrontend::getInstance()->getCFEC(); + msgCurrentServiceInfo.tsfrequency = live_fe->getFrequency(); + msgCurrentServiceInfo.rate = live_fe->getRate(); + msgCurrentServiceInfo.fec = live_fe->getCFEC(); msgCurrentServiceInfo.vtype = current_channel->type; //msgCurrentServiceInfo.diseqc = current_channel->getDiSEqC(); } if(!msgCurrentServiceInfo.fec) msgCurrentServiceInfo.fec = (fe_code_rate)3; - if (CFrontend::getInstance()->getInfo()->type == FE_QPSK) - msgCurrentServiceInfo.polarisation = CFrontend::getInstance()->getPolarization(); + if (live_fe->getInfo()->type == FE_QPSK) + msgCurrentServiceInfo.polarisation = live_fe->getPolarization(); else msgCurrentServiceInfo.polarisation = 2; CBasicServer::send_data(connfd, &msgCurrentServiceInfo, sizeof(msgCurrentServiceInfo)); @@ -844,7 +860,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) case CZapitMessages::CMD_GET_DELIVERY_SYSTEM: { CZapitMessages::responseDeliverySystem _response; - switch (CFrontend::getInstance()->getInfo()->type) { + switch (live_fe->getInfo()->type) { case FE_QAM: _response.system = DVB_C; break; @@ -855,7 +871,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) _response.system = DVB_T; break; default: - WARN("Unknown type %d", CFrontend::getInstance()->getInfo()->type); + WARN("Unknown type %d", live_fe->getInfo()->type); return false; } @@ -961,7 +977,7 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) CBasicServer::send_data(connfd, &response, sizeof(response)); #endif DBG("[zapit] sending EVT_SERVICES_CHANGED\n"); - CFrontend::getInstance()->setTsidOnid(0); + live_fe->setTsidOnid(0); ZapIt(live_channel_id, current_is_nvod); SendEvent(CZapitClient::EVT_SERVICES_CHANGED); //SendEvent(CZapitClient::EVT_BOUQUETS_CHANGED); @@ -1002,23 +1018,24 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) TP.feparams.inversion = INVERSION_AUTO; const char *name = scanProviders.size() > 0 ? scanProviders.begin()->second.c_str() : "unknown"; - switch (CFrontend::getInstance()->getInfo()->type) { + switch (live_fe->getInfo()->type) { case FE_QPSK: case FE_OFDM: { + //FIXME check scanProviders.size() ! t_satellite_position satellitePosition = scanProviders.begin()->first; printf("[zapit] tune to sat %s freq %d rate %d fec %d pol %d\n", name, TP.feparams.frequency, TP.feparams.u.qpsk.symbol_rate, TP.feparams.u.qpsk.fec_inner, TP.polarization); - CFrontend::getInstance()->setInput(satellitePosition, TP.feparams.frequency, TP.polarization); - CFrontend::getInstance()->driveToSatellitePosition(satellitePosition); + live_fe->setInput(satellitePosition, TP.feparams.frequency, TP.polarization); + live_fe->driveToSatellitePosition(satellitePosition); break; } case FE_QAM: printf("[zapit] tune to cable %s freq %d rate %d fec %d\n", name, TP.feparams.frequency, TP.feparams.u.qam.symbol_rate, TP.feparams.u.qam.fec_inner); break; default: - WARN("Unknown type %d", CFrontend::getInstance()->getInfo()->type); + WARN("Unknown type %d", live_fe->getInfo()->type); return false; } - CFrontend::getInstance()->tuneFrequency(&TP.feparams, TP.polarization, true); + live_fe->tuneFrequency(&TP.feparams, TP.polarization, true); } break; case CZapitMessages::CMD_SCAN_TP: { @@ -1027,10 +1044,11 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) #if 0 printf("[zapit] TP_id %d freq %d rate %d fec %d pol %d\n", TP.TP_id, TP.feparams.frequency, TP.feparams.u.qpsk.symbol_rate, TP.feparams.u.qpsk.fec_inner, TP.polarization); #endif + //FIXME not used ? to scan current channel's TP. manual scan menu updated with current params if(!(TP.feparams.frequency > 0) && current_channel) { transponder_list_t::iterator transponder = transponders.find(current_channel->getTransponderId()); TP.feparams.frequency = transponder->second.feparams.frequency; - switch (CFrontend::getInstance()->getInfo()->type) { + switch (live_fe->getInfo()->type) { case FE_QPSK: case FE_OFDM: TP.feparams.u.qpsk.symbol_rate = transponder->second.feparams.u.qpsk.symbol_rate; @@ -1043,20 +1061,14 @@ printf("[zapit] TP_id %d freq %d rate %d fec %d pol %d\n", TP.TP_id, TP.feparams TP.feparams.u.qam.modulation = transponder->second.feparams.u.qam.modulation; break; default: - WARN("Unknown type %d", CFrontend::getInstance()->getInfo()->type); + WARN("Unknown type %d", live_fe->getInfo()->type); return false; } - if(scanProviders.size() > 0) - scanProviders.clear(); -#if 0 - std::map::iterator spos_it; - for (spos_it = satellitePositions.begin(); spos_it != satellitePositions.end(); spos_it++) - if(spos_it->second == current_channel->getSatellitePosition()) - scanProviders[transponder->second.DiSEqC] = spos_it->first.c_str(); -#endif - //FIXME not ready - //if(satellitePositions.find(current_channel->getSatellitePosition()) != satellitePositions.end()) + scanProviders.clear(); + + scanProviders[current_channel->getSatellitePosition()] = + CServiceManager::getInstance()->GetSatelliteName(current_channel->getSatellitePosition()); current_channel = 0; } PrepareScan(); @@ -1082,8 +1094,8 @@ printf("[zapit] TP_id %d freq %d rate %d fec %d pol %d\n", TP.TP_id, TP.feparams CZapitClient::responseGetSatelliteList sat; satlength = sizeof(sat); - sat_iterator_t sit; - for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) { + satellite_map_t satmap = CServiceManager::getInstance()->SatelliteList(); + for(sat_iterator_t sit = satmap.begin(); sit != satmap.end(); sit++) { strncpy(sat.satName, sit->second.name.c_str(), 50); sat.satName[49] = 0; sat.satPosition = sit->first; @@ -1097,33 +1109,45 @@ printf("[zapit] TP_id %d freq %d rate %d fec %d pol %d\n", TP.TP_id, TP.feparams } case CZapitMessages::CMD_SCANSETSCANSATLIST: { + bool setfe = true; CZapitClient::commandSetScanSatelliteList sat; scanProviders.clear(); while (CBasicServer::receive_data(connfd, &sat, sizeof(sat))) { printf("[zapit] adding to scan %s (position %d)\n", sat.satName, sat.position); scanProviders[sat.position] = sat.satName; + if(setfe) { + /* for test signal */ + CServiceScan::getInstance()->SetFrontend(sat.position); + live_fe = CServiceScan::getInstance()->GetFrontend(); + setfe = false; + } } break; } case CZapitMessages::CMD_SCANSETSCANMOTORPOSLIST: { // absolute + ERROR("CZapitMessages::CMD_SCANSETSCANMOTORPOSLIST: depreciated command\n"); break; } case CZapitMessages::CMD_SCANSETDISEQCTYPE: { - //diseqcType is global + //FIXME diseqcType is global +#if 0 CBasicServer::receive_data(connfd, &diseqcType, sizeof(diseqcType)); - CFrontend::getInstance()->setDiseqcType(diseqcType); - DBG("set diseqc type %d", diseqcType); + live_fe->setDiseqcType(diseqcType); +#endif + ERROR("CZapitMessages::CMD_SCANSETDISEQCTYPE: depreciated command\n"); break; } case CZapitMessages::CMD_SCANSETDISEQCREPEAT: { +#if 0 uint32_t repeats; CBasicServer::receive_data(connfd, &repeats, sizeof(repeats)); - CFrontend::getInstance()->setDiseqcRepeats(repeats); - DBG("set diseqc repeats to %d", repeats); + live_fe->setDiseqcRepeats(repeats); +#endif + ERROR("CZapitMessages::CMD_SCANSETDISEQCREPEAT: depreciated command\n"); break; } @@ -1422,12 +1446,11 @@ printf("[zapit] TP_id %d freq %d rate %d fec %d pol %d\n", TP.TP_id, TP.feparams case CZapitMessages::CMD_GET_FE_SIGNAL: { CZapitClient::responseFESignal response_FEsig; - - response_FEsig.sig = CFrontend::getInstance()->getSignalStrength(); - response_FEsig.snr = CFrontend::getInstance()->getSignalNoiseRatio(); - response_FEsig.ber = CFrontend::getInstance()->getBitErrorRate(); - + response_FEsig.sig = live_fe->getSignalStrength(); + response_FEsig.snr = live_fe->getSignalNoiseRatio(); + response_FEsig.ber = live_fe->getBitErrorRate(); CBasicServer::send_data(connfd, &response_FEsig, sizeof(CZapitClient::responseFESignal)); + ERROR("CZapitMessages::CMD_GET_FE_SIGNAL: depreciated command\n"); break; } @@ -1537,10 +1560,10 @@ printf("[zapit] TP_id %d freq %d rate %d fec %d pol %d\n", TP.TP_id, TP.feparams CBasicServer::receive_data(connfd, &msgMotor, sizeof(msgMotor)); printf("[zapit] received motor command: %x %x %x %x %x %x\n", msgMotor.cmdtype, msgMotor.address, msgMotor.cmd, msgMotor.num_parameters, msgMotor.param1, msgMotor.param2); if(msgMotor.cmdtype > 0x20) - CFrontend::getInstance()->sendMotorCommand(msgMotor.cmdtype, msgMotor.address, msgMotor.cmd, msgMotor.num_parameters, msgMotor.param1, msgMotor.param2); + live_fe->sendMotorCommand(msgMotor.cmdtype, msgMotor.address, msgMotor.cmd, msgMotor.num_parameters, msgMotor.param1, msgMotor.param2); // TODO !! //else if(current_channel) - // CFrontend::getInstance()->satFind(msgMotor.cmdtype, current_channel); + // live_fe->satFind(msgMotor.cmdtype, current_channel); break; } @@ -1606,22 +1629,10 @@ void CZapit::sendAPIDs(int connfd) void CZapit::internalSendChannels(int connfd, ZapitChannelList* channels, const unsigned int first_channel_nr, bool nonames) { int data_count = channels->size(); -#if RECORD_RESEND // old, before tv/radio resend - if (currentMode & RECORD_MODE) { - for (uint32_t i = 0; i < channels->size(); i++) - if ((*channels)[i]->getTransponderId() != channel->getTransponderId()) - data_count--; - } -#endif if (!send_data_count(connfd, data_count)) return; for (uint32_t i = 0; i < channels->size();i++) { -#if RECORD_RESEND // old, before tv/radio resend - if ((currentMode & RECORD_MODE) && ((*channels)[i]->getTransponderId() != CFrontend::getInstance()->getTsidOnid())) - continue; -#endif - if(nonames) { CZapitClient::responseGetBouquetNChannels response; response.nr = first_channel_nr + i; @@ -1637,14 +1648,14 @@ void CZapit::internalSendChannels(int connfd, ZapitChannelList* channels, const CZapitClient::responseGetBouquetChannels response; strncpy(response.name, ((*channels)[i]->getName()).c_str(), CHANNEL_NAME_SIZE); response.name[CHANNEL_NAME_SIZE-1] = 0; -//printf("internalSendChannels: name %s\n", response.name); + //printf("internalSendChannels: name %s\n", response.name); response.satellitePosition = (*channels)[i]->getSatellitePosition(); response.channel_id = (*channels)[i]->getChannelID(); response.nr = first_channel_nr + i; if (CBasicServer::send_data(connfd, &response, sizeof(response)) == false) { ERROR("could not send any return"); -DBG("current: %d name %s total %d\n", i, response.name, data_count); + DBG("current: %d name %s total %d\n", i, response.name, data_count); if (CBasicServer::send_data(connfd, &response, sizeof(response)) == false) { ERROR("could not send any return, stop"); return; @@ -1675,25 +1686,16 @@ void CZapit::sendBouquets(int connfd, const bool emptyBouquetsToo, CZapitClient: if (emptyBouquetsToo || (!g_bouquetManager->Bouquets[i]->bHidden && g_bouquetManager->Bouquets[i]->bUser) || ((!g_bouquetManager->Bouquets[i]->bHidden) && (((curMode & RADIO_MODE) && !g_bouquetManager->Bouquets[i]->radioChannels.empty()) || - ((curMode & TV_MODE) && !g_bouquetManager->Bouquets[i]->tvChannels.empty()))) - ) + ((curMode & TV_MODE) && !g_bouquetManager->Bouquets[i]->tvChannels.empty())))) { -// ATTENTION: in RECORD_MODE empty bouquets are not send! -#if RECORD_RESEND // old, before tv/radio resend - if ((!(currentMode & RECORD_MODE)) || ((CFrontend::getInstance() != NULL) && - (((currentMode & RADIO_MODE) && (g_bouquetManager->Bouquets[i]->recModeRadioSize(CFrontend::getInstance()->getTsidOnid()) > 0)) || - ((currentMode & TV_MODE) && (g_bouquetManager->Bouquets[i]->recModeTVSize (CFrontend::getInstance()->getTsidOnid()) > 0))))) -#endif - { - msgBouquet.bouquet_nr = i; - strncpy(msgBouquet.name, g_bouquetManager->Bouquets[i]->Name.c_str(), 30); - msgBouquet.name[29] = 0; - msgBouquet.locked = g_bouquetManager->Bouquets[i]->bLocked; - msgBouquet.hidden = g_bouquetManager->Bouquets[i]->bHidden; - if (CBasicServer::send_data(connfd, &msgBouquet, sizeof(msgBouquet)) == false) { - ERROR("could not send any return"); - return; - } + msgBouquet.bouquet_nr = i; + strncpy(msgBouquet.name, g_bouquetManager->Bouquets[i]->Name.c_str(), 30); + msgBouquet.name[29] = 0; + msgBouquet.locked = g_bouquetManager->Bouquets[i]->bLocked; + msgBouquet.hidden = g_bouquetManager->Bouquets[i]->bHidden; + if (CBasicServer::send_data(connfd, &msgBouquet, sizeof(msgBouquet)) == false) { + ERROR("could not send any return"); + return; } } } @@ -1747,17 +1749,19 @@ bool CZapit::StartPlayBack(CZapitChannel *thisChannel) bool have_video = false; bool have_teletext = false; + INFO("standby %d playing %d forced %d", standby, playing, playbackStopForced); if(!thisChannel) thisChannel = current_channel; + if ((playbackStopForced == true) || (!thisChannel) || playing) return false; - printf("[zapit] vpid %X apid %X pcr %X\n", thisChannel->getVideoPid(), thisChannel->getAudioPid(), thisChannel->getPcrPid()); if(standby) { - CFrontend::getInstance()->Open(); + CFEManager::getInstance()->Open(); return true; } + printf("[zapit] vpid %X apid %X pcr %X\n", thisChannel->getVideoPid(), thisChannel->getAudioPid(), thisChannel->getPcrPid()); if (thisChannel->getPcrPid() != 0) have_pcr = true; if (thisChannel->getAudioPid() != 0) @@ -1824,12 +1828,18 @@ bool CZapit::StartPlayBack(CZapitChannel *thisChannel) bool CZapit::StopPlayBack(bool send_pmt) { +#if 1 if(send_pmt) { CCamManager::getInstance()->Stop(live_channel_id, CCamManager::PLAY); ca->SendPMT(0, (unsigned char*) "", 0, CA_SLOT_TYPE_SMARTCARD); } - - printf("StopPlayBack: standby %d forced %d\n", standby, playbackStopForced); +#endif +#if 0 + if (send_pmt && !(currentMode & RECORD_MODE)) + ca->SendPMT(0, (unsigned char*) "", 0, CA_SLOT_TYPE_SMARTCARD); + CCamManager::getInstance()->Stop(live_channel_id, CCamManager::PLAY); +#endif + INFO("standby %d playing %d forced %d", standby, playing, playbackStopForced); if (!playing) return true; @@ -1860,34 +1870,31 @@ bool CZapit::StopPlayBack(bool send_pmt) void CZapit::enterStandby(void) { + INFO("standby %d", standby); if (standby) return; standby = true; - SaveSettings(true, true); + SaveSettings(true); + SaveAudioMap(); StopPlayBack(true); if(!(currentMode & RECORD_MODE)) { - CFrontend::getInstance()->Close(); + CFEManager::getInstance()->Close(); } } void CZapit::leaveStandby(void) { + INFO("standby %d", standby); if(!standby) return; printf("[zapit] diseqc type = %d\n", diseqcType); - CFrontend::getInstance()->setDiseqcRepeats(configfile.getInt32("diseqcRepeats", 0)); - CFrontend::getInstance()->setCurrentSatellitePosition(configfile.getInt32("lastSatellitePosition", 0)); - CFrontend::getInstance()->setDiseqcType(diseqcType); - if(!(currentMode & RECORD_MODE)) { - CFrontend::getInstance()->Open(); - CFrontend::getInstance()->setTsidOnid(0); - CFrontend::getInstance()->setDiseqcType(diseqcType); + CFEManager::getInstance()->Open(); } standby = false; if (current_channel) @@ -1959,6 +1966,8 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg) if(started) return false; + CFEManager::getInstance()->Init(); + live_fe = CFEManager::getInstance()->getFE(0); /* load configuration or set defaults if no configuration file exists */ video_mode = ZapStart_arg->video_mode; @@ -1982,11 +1991,23 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg) #endif ca = cCA::GetInstance(); - LoadSettings(); - ConfigFrontend(); + //LoadSettings(); + //LoadAudioMap(); /* create bouquet manager */ g_bouquetManager = new CBouquetManager(); + if (!PrepareChannels()) + WARN("error parsing services"); + else + INFO("channels have been loaded succesfully"); + + /* FIXME to transit from old satconfig.conf to new frontend.conf, + * ConfigFrontend called after PrepareChannels, as it copy satellitePositions to every fe */ + LoadSettings(); + ConfigFrontend(); + + if(!CFEManager::getInstance()->configExist()) + CFEManager::getInstance()->saveSettings(true); if (configfile.getInt32("lastChannelMode", 0)) SetRadioMode(); @@ -2000,7 +2021,7 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg) } /* CA_INIT_CI or CA_INIT_SC or CA_INIT_BOTH */ - switch(cam_ci){ + switch(config.cam_ci){ case 2: ca->SetInitMask(CA_INIT_BOTH); break; @@ -2014,15 +2035,13 @@ bool CZapit::Start(Z_start_arg *ZapStart_arg) ca->SetInitMask(CA_INIT_BOTH); break; } + + // set ci clock to ZapStart_arg->ci_clock + ca->SetTSClock(ZapStart_arg->ci_clock * 1000000); ca->Start(); eventServer = new CEventServer; - if (!PrepareChannels()) - WARN("error parsing services"); - else - INFO("channels have been loaded succesfully"); - current_channel = CServiceManager::getInstance()->FindChannel(live_channel_id); // some older? hw needs this sleep. e.g. my hd-1c. @@ -2072,23 +2091,24 @@ void CZapit::run() if (pmt_update_fd != -1) { unsigned char buf[4096]; int ret = pmtDemux->Read(buf, 4095, 10); - if (ret > 0) { - pmt_stop_update_filter(&pmt_update_fd); - printf("[zapit] pmt updated, sid 0x%x new version 0x%x\n", (buf[3] << 8) + buf[4], (buf[5] >> 1) & 0x1F); - if(current_channel) { - t_channel_id channel_id = current_channel->getChannelID(); - int vpid = current_channel->getVideoPid(); - parse_pmt(current_channel); - if(vpid != current_channel->getVideoPid()) { - ZapIt(current_channel->getChannelID(), true); - } else { - SendPMT(true); - pmt_set_update_filter(current_channel, &pmt_update_fd); - } - SendEvent(CZapitClient::EVT_PMT_CHANGED, &channel_id, sizeof(channel_id)); + if (ret > 0) { + pmt_stop_update_filter(&pmt_update_fd); + printf("[zapit] pmt updated, sid 0x%x new version 0x%x\n", (buf[3] << 8) + buf[4], (buf[5] >> 1) & 0x1F); + if(current_channel) { + t_channel_id channel_id = current_channel->getChannelID(); + int vpid = current_channel->getVideoPid(); + CPmt pmt; + pmt.parse_pmt(current_channel); + if(vpid != current_channel->getVideoPid()) { + ZapIt(current_channel->getChannelID(), true); + } else { + SendPMT(true); + pmt_set_update_filter(current_channel, &pmt_update_fd); } + SendEvent(CZapitClient::EVT_PMT_CHANGED, &channel_id, sizeof(channel_id)); } } + } /* yuck, don't waste that much cpu time :) */ usleep(0); #if 0 @@ -2096,11 +2116,11 @@ void CZapit::run() curtime = time(0); if(sig_delay && (curtime - stime) > sig_delay) { stime = curtime; - uint16_t sig = CFrontend::getInstance()->getSignalStrength(); + uint16_t sig = live_fe->getSignalStrength(); //if(sig < 8000) if(sig < 28000) { printf("[monitor] signal %d, trying to re-tune...\n", sig); - CFrontend::getInstance()->retuneChannel(); + live_fe->retuneChannel(); } } } @@ -2108,8 +2128,10 @@ void CZapit::run() } SaveChannelPids(current_channel); - SaveSettings(true, true); + SaveSettings(true); + SaveAudioMap(); StopPlayBack(true); + CFEManager::getInstance()->saveSettings(true); CServiceManager::getInstance()->SaveMotorPositions(); @@ -2127,10 +2149,8 @@ void CZapit::run() INFO("demuxes/decoders deleted"); - CFrontend::getInstance()->Close(); - delete CFrontend::getInstance(); - - INFO("frontend deleted"); + delete CFEManager::getInstance(); + INFO("frontend(s) deleted"); if (ca) { INFO("stopping CA"); ca->Stop(); @@ -2146,18 +2166,7 @@ void CZapit::SetConfig(Zapit_config * Cfg) config = *Cfg; - //FIXME globals! -#if 0 - motorRotationSpeed = config.motorRotationSpeed; - highVoltage = config.highVoltage; - feTimeout = config.feTimeout; - gotoXXLaDirection = config.gotoXXLaDirection; - gotoXXLoDirection = config.gotoXXLoDirection; - gotoXXLatitude = config.gotoXXLatitude; - gotoXXLongitude = config.gotoXXLongitude; - repeatUsals = config.repeatUsals; -#endif - SaveSettings(true, false); + SaveSettings(true); ConfigFrontend(); } From f9010a8bd188caf44407fee77f2858317faea87b Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 16:15:21 +0400 Subject: [PATCH 033/737] update libcs headers --- lib/libcoolstream/ca_cs.h | 38 ++++++++++++++++++++++++++++++------ lib/libcoolstream/video_cs.h | 1 + 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/lib/libcoolstream/ca_cs.h b/lib/libcoolstream/ca_cs.h index 638762b83..86fa900f4 100644 --- a/lib/libcoolstream/ca_cs.h +++ b/lib/libcoolstream/ca_cs.h @@ -5,6 +5,7 @@ /* */ /* (C) 2010 CoolStream International Ltd. */ /* */ +/* $Id:: ca_cs.h 2528 2011-12-22 13:19:41Z nightshad $ */ /*******************************************************************************/ #ifndef __CA_CS_H_ #define __CA_CS_H_ @@ -26,13 +27,13 @@ enum CA_SLOT_TYPE { enum CA_MESSAGE_FLAGS { CA_MESSAGE_EMPTY = (1 << 0), - CA_MESSAGE_HAS_PARAM1_DATA = (1 << 1), // Free after use! + CA_MESSAGE_HAS_PARAM1_DATA = (1 << 1), /// Free after use! CA_MESSAGE_HAS_PARAM1_INT = (1 << 2), CA_MESSAGE_HAS_PARAM1_PTR = (1 << 3), CA_MESSAGE_HAS_PARAM2_INT = (1 << 4), CA_MESSAGE_HAS_PARAM2_PTR = (1 << 5), CA_MESSAGE_HAS_PARAM2_DATA = (1 << 6), - CA_MESSAGE_HAS_PARAM3_DATA = (1 << 7), // Free after use! + CA_MESSAGE_HAS_PARAM3_DATA = (1 << 7), /// Free after use! CA_MESSAGE_HAS_PARAM3_INT = (1 << 8), CA_MESSAGE_HAS_PARAM3_PTR = (1 << 9), CA_MESSAGE_HAS_PARAM4_INT = (1 << 10), @@ -59,6 +60,7 @@ enum CA_MESSAGE_MSGID { CA_MESSAGE_MSG_ECM_ARRIVED, CA_MESSAGE_MSG_EMM_ARRIVED, CA_MESSAGE_MSG_CHANNEL_CHANGE, + CA_MESSAGE_MSG_GUI_READY, CA_MESSAGE_MSG_EXIT, }; @@ -84,36 +86,60 @@ typedef struct CA_MESSAGE { #define CS_CA_PDATA void #endif +/// CA module class class cCA : public OpenThreads::Thread { private: + /// Static instance of the CA module static cCA *inst; - // + /// Private constructor (singleton method) cCA(void); - // + /// Private data for the CA module CS_CA_PDATA *privateData; enum CA_INIT_MASK initMask; bool exit; bool started; bool guiReady; + /// Thread method virtual void run(void); public: + /// Returns the number of CI slots u32 GetNumberCISlots(void); - u32 GetNumberSmartCardSlots(void); // + /// Returns the number of Smartcard slots + u32 GetNumberSmartCardSlots(void); + /// Singleton static cCA *GetInstance(void); + /// Send PMT to a individual or to all available modules bool SendPMT(int Unit, unsigned char *Data, int Len, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL); + /// Sends a message to the CA thread bool SendMessage(const CA_MESSAGE *Msg); + /// Sets which modules to initialize. It is only + /// possible to change this once! void SetInitMask(enum CA_INIT_MASK InitMask); + /// Sets the frequency (in Hz) of the TS stream input (only valid for CI) + void SetTSClock(u32 Speed); + /// Start the CA module bool Start(void); + /// Stops the CA module void Stop(void); + /// Notify that the GUI is ready to receive messages + /// (CA messages coming from a module) void Ready(bool Set); + /// Resets a module (if possible) void ModuleReset(enum CA_SLOT_TYPE, u32 Slot); + /// Checks if a module is present bool ModulePresent(enum CA_SLOT_TYPE, u32 Slot); + /// Returns the module name in array Name void ModuleName(enum CA_SLOT_TYPE, u32 Slot, char *Name); + /// Notify the module we want to enter menu void MenuEnter(enum CA_SLOT_TYPE, u32 Slot); + /// Notify the module with our answer (choice nr) void MenuAnswer(enum CA_SLOT_TYPE, u32 Slot, u32 choice); + /// Notify the module with our answer (binary) void InputAnswer(enum CA_SLOT_TYPE, u32 Slot, u8 * Data, int Len); + /// Notify the module we closed the menu void MenuClose(enum CA_SLOT_TYPE, u32 Slot); + /// Virtual destructor virtual ~cCA(); }; -#endif //__CA_H_ +#endif ///__CA_H_ diff --git a/lib/libcoolstream/video_cs.h b/lib/libcoolstream/video_cs.h index 5b3ca08a5..a80d59051 100644 --- a/lib/libcoolstream/video_cs.h +++ b/lib/libcoolstream/video_cs.h @@ -230,6 +230,7 @@ public: int CloseVBI(void); int StartVBI(unsigned short pid); int StopVBI(void); + bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false); }; #endif // __VIDEO_CS_H_ From 8a778f3fd4e5fd6bba5559a8624f64149460c250 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 16:19:35 +0400 Subject: [PATCH 034/737] sectionsd: use negative filter --- src/sectionsd/sectionsd.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sectionsd/sectionsd.cpp b/src/sectionsd/sectionsd.cpp index c116d6aa0..e42327878 100644 --- a/src/sectionsd/sectionsd.cpp +++ b/src/sectionsd/sectionsd.cpp @@ -7048,9 +7048,9 @@ int eit_set_update_filter(int *fd) unsigned char cur_eit = dmxCN.get_eit_version(); xprintf("eit_set_update_filter, servicekey = 0x" - PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS - ", current version 0x%x got events %d\n", - messaging_current_servicekey, cur_eit, messaging_have_CN); + PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS + ", current version 0x%x got events %d\n", + messaging_current_servicekey, cur_eit, messaging_have_CN); if (cur_eit == 0xff) { *fd = -1; @@ -7078,7 +7078,7 @@ int eit_set_update_filter(int *fd) mask[2] = 0xFF; int timeout = 0; -#if !HAVE_COOL_HARDWARE +#if 1 //!HAVE_COOL_HARDWARE filter[3] = (cur_eit << 1) | 0x01; mask[3] = (0x1F << 1) | 0x01; mode[3] = 0x1F << 1; @@ -8384,7 +8384,7 @@ static void *cnThread(void *) removeOldEvents(oldEventsAre); // alte Events dprintf("after removeoldevents\n"); readLockEvents(); - printf("[sectionsd] Removed %d old events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); + printf("[sectionsd] Removed %d old events (%d left).\n", anzEventsAlt - mySIeventsOrderUniqueKey.size(), mySIeventsOrderUniqueKey.size()); if (mySIeventsOrderUniqueKey.size() != anzEventsAlt) { print_meminfo(); From ef39d9bd5d2de4560801fda1d1b23e6193ba265a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 16:38:03 +0400 Subject: [PATCH 035/737] screenshot: enable screenshots --- src/driver/screenshot.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/screenshot.cpp b/src/driver/screenshot.cpp index c91ddd28d..c4f8b25e6 100644 --- a/src/driver/screenshot.cpp +++ b/src/driver/screenshot.cpp @@ -79,7 +79,7 @@ bool CScreenShot::GetData() CFrameBuffer::getInstance()->setActive(false); #endif -#if 0 // to enable after libcs/drivers update +#if 1 // to enable after libcs/drivers update res = videoDecoder->GetScreenImage(pixel_data, xres, yres, get_video, get_osd, scale_to_video); #endif From 04ef64b0abc40c2edb004de3e988680f2573e931 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 13 Jan 2012 18:18:21 +0400 Subject: [PATCH 036/737] debug configure script --- cross-configure.cool.debug | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 cross-configure.cool.debug diff --git a/cross-configure.cool.debug b/cross-configure.cool.debug new file mode 100755 index 000000000..6ce9ebed1 --- /dev/null +++ b/cross-configure.cool.debug @@ -0,0 +1,31 @@ +#!/bin/sh + +PREFIX=/opt/newcross/arm-cx2450x-linux-gnueabi/arm-cx2450x-linux-gnueabi/sys-root/usr +CCPATH= +HOST=arm-cx2450x-linux-gnueabi + +export PKG_CONFIG_PATH=${PREFIX}/lib/pkgconfig +export CC=$CCPATH$HOST-gcc +export AR=$CCPATH$HOST-ar +export NM=$CCPATH$HOST-nm +export RANLIB=$CCPATH$HOST-ranlib +export OBJDUMP=$CCPATH$HOST-objdump +export STRIP=$CCPATH$HOST-strip + +export CFLAGS=" -Wall -Wextra -Wshadow -Werror -g -ggdb3 \ + -D__KERNEL_STRICT_NAMES -DUSE_NEVIS_GXA \ + -I"$PWD"/include -I"$PWD"/include/linux/dvb -I"$PREFIX"/include/freetype2" + +export CXXFLAGS=" -Wall -Wextra -Wshadow -Werror -g -ggdb3 \ + -D__KERNEL_STRICT_NAMES -DUSE_NEVIS_GXA \ + -I"$PWD"/include -I"$PWD"/include/linux/dvb -I"$PREFIX"/include/freetype2" + +export LDFLAGS="-L"$PREFIX"/lib -lcurl -lssl -lcrypto -ldl" + +export DVB_API_VERSION=3 +export FREETYPE_CONFIG=$PREFIX/bin/freetype-config +export CURL_CONFIG=$PREFIX/bin/curl-config + +./autogen.sh +./configure --prefix=${PREFIX} --build=i386-pc-linux-gnu --host=$HOST --without-driver --with-target=cdk --with-targetprefix="" "$*" + From afef2d570de001a759659dc871f497071535984f Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Tue, 17 Jan 2012 16:41:59 +0400 Subject: [PATCH 037/737] frontend: set slave in contructor; decrease tune debug lines --- src/zapit/src/frontend.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/zapit/src/frontend.cpp b/src/zapit/src/frontend.cpp index acc99e82c..9cb455fad 100644 --- a/src/zapit/src/frontend.cpp +++ b/src/zapit/src/frontend.cpp @@ -107,7 +107,7 @@ static const struct dtv_property dvbc_cmdargs[] = { struct timeval tv, tv2; \ unsigned int timer_msec = 0; -#define FE_TIMER_START() \ +#define FE_TIMER_START() \ gettimeofday(&tv, NULL); #define FE_TIMER_STOP(label) \ @@ -134,6 +134,8 @@ typedef enum dvb_fec { fNone = 15 } dvb_fec_t; +#define TIME_STEP 200 +#define TIMEOUT_MAX_MS (feTimeout*100) /*********************************************************************************************************/ // Global fe instance CFrontend *CFrontend::currentFe = NULL; @@ -153,7 +155,7 @@ CFrontend::CFrontend(int Number, int Adapter) fd = -1; fenumber = Number; adapter = Adapter; - slave = false; + slave = (Number != 0); //false; standby = true; locked = false; usecount = 0; @@ -424,8 +426,6 @@ uint32_t CFrontend::getUncorrectedBlocks(void) const return blocks; } -#define TIME_STEP 200 -#define TIMEOUT_MAX_MS (feTimeout*100) struct dvb_frontend_event CFrontend::getEvent(void) { struct dvb_frontend_event event; @@ -440,7 +440,7 @@ struct dvb_frontend_event CFrontend::getEvent(void) memset(&event, 0, sizeof(struct dvb_frontend_event)); - printf("[fe%d] getEvent: max timeout: %d\n", fenumber, TIMEOUT_MAX_MS); + //printf("[fe%d] getEvent: max timeout: %d\n", fenumber, TIMEOUT_MAX_MS); FE_TIMER_START(); //while (msec <= TIMEOUT_MAX_MS ) { @@ -770,7 +770,9 @@ int CFrontend::setFrontend(const struct dvb_frontend_parameters *feparams, bool struct dvb_frontend_event event; event = getEvent(); - FE_TIMER_STOP("tuning took"); + if(tuned) { + FE_TIMER_STOP("tuning took"); + } } return tuned; @@ -1085,7 +1087,7 @@ bool CFrontend::retuneChannel(void) int CFrontend::tuneFrequency(FrontendParameters * feparams, uint8_t polarization, bool nowait) { TP_params TP; - printf("[fe%d] tune to frequency %d pol %s srate %d\n", fenumber, feparams->frequency, polarization ? "Vertical/Right" : "Horizontal/Left", feparams->u.qpsk.symbol_rate); + //printf("[fe%d] tune to frequency %d pol %s srate %d\n", fenumber, feparams->frequency, polarization ? "Vertical/Right" : "Horizontal/Left", feparams->u.qpsk.symbol_rate); memmove(&curfe, feparams, sizeof(struct dvb_frontend_parameters)); memmove(&TP.feparams, feparams, sizeof(struct dvb_frontend_parameters)); @@ -1134,7 +1136,10 @@ int CFrontend::setParameters(TP_params *TP, bool /*nowait*/) #endif } - printf("[fe%d] tuner to frequency %d (offset %d)\n", fenumber, feparams->frequency, freq_offset); + //printf("[fe%d] tuner to frequency %d (offset %d timeout %d)\n", fenumber, feparams->frequency, freq_offset, TIMEOUT_MAX_MS); + //printf("[fe%d] tune to frequency %d (tuner %d offset %d timeout %d)\n", fenumber, freq, feparams->frequency, freq_offset, TIMEOUT_MAX_MS); + printf("[fe%d] tune to %d pol %s srate %d (tuner %d offset %d timeout %d)\n", fenumber, + freq, TP->polarization ? "V/R" : "H/L", feparams->u.qpsk.symbol_rate, feparams->frequency, freq_offset, TIMEOUT_MAX_MS); setFrontend(feparams); #if 0 @@ -1227,7 +1232,7 @@ void CFrontend::setDiseqc(int sat_no, const uint8_t pol, const uint32_t frequenc fe_sec_mini_cmd_t b = (sat_no & 1) ? SEC_MINI_B : SEC_MINI_A; int delay = 0; - INFO("[fe%d] diseqc input %d -> %d", fenumber, diseqc, sat_no); + printf("[fe%d] diseqc input %d -> %d\n", fenumber, diseqc, sat_no); if (slave) return; @@ -1365,7 +1370,7 @@ int CFrontend::driveToSatellitePosition(t_satellite_position satellitePosition, //if(config.diseqcType == DISEQC_ADVANCED) //FIXME testing { - printf("[fe%d] SatellitePosition %d -> %d\n", fenumber, currentSatellitePosition, satellitePosition); + //printf("[fe%d] SatellitePosition %d -> %d\n", fenumber, currentSatellitePosition, satellitePosition); bool moved = false; sat_iterator_t sit = satellites.find(satellitePosition); @@ -1380,7 +1385,8 @@ int CFrontend::driveToSatellitePosition(t_satellite_position satellitePosition, if (sit != satellites.end()) old_position = sit->second.motor_position; - printf("[fe%d] motorPosition %d -> %d usals %s\n", fenumber, old_position, new_position, use_usals ? "on" : "off"); + //printf("[fe%d] motorPosition %d -> %d usals %s\n", fenumber, old_position, new_position, use_usals ? "on" : "off"); + printf("[fe%d] sat pos %d -> %d motor pos %d -> %d usals %s\n", fenumber, currentSatellitePosition, satellitePosition, old_position, new_position, use_usals ? "on" : "off"); if (currentSatellitePosition == satellitePosition) return 0; From fc77e30427194035fc836d9d80955938391b0f9d Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Tue, 17 Jan 2012 19:11:43 +0400 Subject: [PATCH 038/737] convertDVBUTF8: skip characters 0x80-0x9F --- src/sectionsd/edvbstring.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sectionsd/edvbstring.cpp b/src/sectionsd/edvbstring.cpp index 62bc05b77..8226043da 100644 --- a/src/sectionsd/edvbstring.cpp +++ b/src/sectionsd/edvbstring.cpp @@ -660,7 +660,7 @@ std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid) ++i; break; } - +//printf("convertDVBUTF8: table %d new table %d\n", table, newtable); if(!table) table = newtable; if(table == 64 && (newtable !=0 )){//for ISO6937 @@ -697,6 +697,8 @@ std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid) res[t++]= 0x20; else if ((code == 0x8A)) res[t++]= '\n'; // 0x8a is vertical tab. Just use newline for now. + else if((code >= 0x80) && (code <= 0x9F)) + continue; else if (code < 0x800) // two byte mapping { res[t++]=(code>>6)|0xC0; From a64d049f241be4f68fa41063873fb0eef0289109 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 15:00:59 +0400 Subject: [PATCH 039/737] Makefile.am: add libdvbsi++ to link list --- src/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile.am b/src/Makefile.am index 3f3d13361..f90ffd92b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,6 +85,7 @@ neutrino_LDADD = \ @AVUTIL_LIBS@ \ $(FLACLIBS) \ $(VORBISLIBS) \ + -ldvbsi++ \ -lungif \ -ljpeg \ -lOpenThreads \ From 229109a8a41524d22a68ba6f2be46895bfc1c5b8 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 15:04:18 +0400 Subject: [PATCH 040/737] gitignore: add drivertool, svn_version.h, vim swap files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c341c7b38..b2acf5b02 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ INSTALL *.lo *.a *.la +.*.swp ### binaries that fall out of the build lib/sectionsdclient/sectionsdcontrol @@ -30,3 +31,5 @@ src/neutrino src/nhttpd/web/*.js.gz src/zapit/src/pzapit src/zapit/src/udpstreampes +src/drivertool +src/gui/svn_version.h From 72f566474aaaef2f1f45679a178b102a4fd39fb7 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 15:05:26 +0400 Subject: [PATCH 041/737] edvbstring: add inlined convertDVBUTF8 with std::string param --- src/sectionsd/edvbstring.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sectionsd/edvbstring.h b/src/sectionsd/edvbstring.h index a3d1aa037..a01101ab2 100644 --- a/src/sectionsd/edvbstring.h +++ b/src/sectionsd/edvbstring.h @@ -5,4 +5,10 @@ const std::string convertLatin1UTF8(const std::string &string); int isUTF8(const std::string &string); std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid = 0); int readEncodingFile(); + +inline std::string convertDVBUTF8(const std::string &string, int table=0, int tsidonid=0) +{ + return convertDVBUTF8((const char*)string.c_str(), string.length(), table, tsidonid); +} + #endif // __E_STRING__ From f044899756215653ed8a208c722482234aec99b1 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 15:19:08 +0400 Subject: [PATCH 042/737] edvbstring: change convertDVBUTF8 to stringDVBUTF8 to prevent overloading with implicit convertion from char --- src/sectionsd/edvbstring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sectionsd/edvbstring.h b/src/sectionsd/edvbstring.h index a01101ab2..0554adb9c 100644 --- a/src/sectionsd/edvbstring.h +++ b/src/sectionsd/edvbstring.h @@ -6,7 +6,7 @@ int isUTF8(const std::string &string); std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid = 0); int readEncodingFile(); -inline std::string convertDVBUTF8(const std::string &string, int table=0, int tsidonid=0) +inline std::string stringDVBUTF8(const std::string &string, int table=0, int tsidonid=0) { return convertDVBUTF8((const char*)string.c_str(), string.length(), table, tsidonid); } From 0df936543c50b0fefa99627b8a0b6b85282991ce Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 15:19:57 +0400 Subject: [PATCH 043/737] zapit Makefile.am: add scansdt.cpp for new sdt class --- src/zapit/src/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/zapit/src/Makefile.am b/src/zapit/src/Makefile.am index 813aa055e..e432b834e 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -21,7 +21,8 @@ noinst_LIBRARIES = libzapit.a libzapit_a_SOURCES = \ bouquets.cpp channel.cpp dvbstring.cpp getservices.cpp \ scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp femanager.cpp \ - descriptors.cpp nit.cpp pat.cpp pmt.cpp sdt.cpp fastscan.cpp + descriptors.cpp nit.cpp pat.cpp pmt.cpp sdt.cpp fastscan.cpp \ + scansdt.cpp bin_PROGRAMS = pzapit sbin_PROGRAMS = udpstreampes From 0465778d2df3419dfef01afafc9cc2819729ea7e Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 21:32:47 +0400 Subject: [PATCH 044/737] sdt: new code, more or less working --- src/zapit/src/scansdt.cpp | 452 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 452 insertions(+) create mode 100644 src/zapit/src/scansdt.cpp diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp new file mode 100644 index 000000000..b1bf01f55 --- /dev/null +++ b/src/zapit/src/scansdt.cpp @@ -0,0 +1,452 @@ +/* + * $Id: sdt.cpp,v 1.44 2003/03/14 08:22:04 obi Exp $ + * + * (C) 2002, 2003 by Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include + +/* zapit */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +extern CZapitClient::scanType scanType; // FIXME + +CSdt::CSdt(t_satellite_position spos, freq_id_t frq, int dnum) +{ + satellitePosition = spos; + freq_id = frq; + dmxnum = dnum; + cable = (CServiceScan::getInstance()->GetFrontend()->getInfo()->type == FE_QAM); +} + +CSdt::~CSdt() +{ + ServiceDescriptionSectionIterator sit; + for (sit = sections.begin(); sit != sections.end(); sit++) { + delete *(sit); + } +} + +bool CSdt::Read() +{ + int secdone[255]; + int sectotal = -1; + bool cable_hack_done = false; + + memset(secdone, 0, 255); + cDemux * dmx = new cDemux(dmxnum); + dmx->Open(DMX_PSI_CHANNEL); + + unsigned char buffer[SDT_SECTION_SIZE]; + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + + int flen = 1; + memset(filter, 0x00, DMX_FILTER_SIZE); + memset(mask, 0x00, DMX_FILTER_SIZE); + + filter[0] = 0x42; + mask[0] = 0xFF; + if (!dmx->sectionFilter(0x11, filter, mask, flen)) { + delete dmx; + return false; + } + do { +_repeat: + if (dmx->Read(buffer, SDT_SECTION_SIZE) < 0) { + delete dmx; + return false; + } + unsigned char secnum = buffer[6]; + if(cable_hack_done) { + if( (transport_stream_id == ((buffer[3] << 8) | buffer[4])) && + (original_network_id == ((buffer[8] << 8) | buffer[9]))) + break; + } else { + transport_stream_id = (buffer[3] << 8) | buffer[4]; + original_network_id = (buffer[8] << 8) | buffer[9]; + } + printf("[SDT] section %X last %X tsid 0x%x onid 0x%x -> %s\n", buffer[6], buffer[7], transport_stream_id, original_network_id, secdone[secnum] ? "skip" : "use"); + + if(secdone[secnum]) + continue; + secdone[secnum] = 1; + sectotal++; + + ServiceDescriptionSection * sdt = new ServiceDescriptionSection(buffer); + sections.push_back(sdt); + + } while(sectotal < buffer[7]); + if(cable && !cable_hack_done && sectotal == 0) { + cable_hack_done = true; + secdone[0] = 0; + goto _repeat; + } + delete dmx; + return true; +} + +bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid) +{ + ServiceDescriptionSectionIterator it; + + if(!Read()) + return false; + + for (it = sections.begin(); it != sections.end(); it++) { + ServiceDescriptionSection * sdt = *it; + + transport_stream_id = sdt->getTransportStreamId(); + original_network_id = sdt->getOriginalNetworkId(); + + //ServiceDescriptionSection sdt(buffer); + printf("SDT: tid %02x onid %02x\n", sdt->getTransportStreamId(), sdt->getOriginalNetworkId()); + const ServiceDescriptionList &slist = *sdt->getDescriptions(); + for (ServiceDescriptionConstIterator sit = slist.begin(); sit != slist.end(); ++sit) { + ServiceDescription * service = *sit; + //printf("SDT: sid %x \n", service->getServiceId()); + DescriptorConstIterator dit; + for (dit = service->getDescriptors()->begin(); dit != service->getDescriptors()->end(); ++dit) { + Descriptor * d = *dit; + //printf("SDT: sid %x descriptor %02x\n", service->getServiceId(), d->getTag()); + switch (d->getTag()) { + case SERVICE_DESCRIPTOR: + { + ServiceDescriptor * sd = (ServiceDescriptor *) d; + ParseServiceDescriptor(service, sd); + } + break; + case CA_IDENTIFIER_DESCRIPTOR: + { + CaIdentifierDescriptor * cad = (CaIdentifierDescriptor *) d; + const CaSystemIdList * calist = cad->getCaSystemIds(); + for(CaSystemIdConstIterator cit = calist->begin(); cit != calist->end(); ++cit) + printf("CASYS %02x\n", *cit); + } + break; + default: + printf("SDT: sid %x descriptor %02x\n", service->getServiceId(), d->getTag()); + break; + } + } + } + } + *p_tsid = transport_stream_id; + *p_onid = original_network_id; + return true; +} + +uint8_t CSdt::FixServiceType(uint8_t type) +{ + if((type == 0x9A) || (type == 0x86) || (type==0xc3) || + (type==0xc5) || (type==0xc6) || (type == 0x11) || + (type == 0x16) || (type == 0x19) || (type == 0x82) || + (type == 0x87) || (type == 0xd3)) + return 1; + return type; +} + +bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescriptor * sd) +{ + uint8_t service_type = FixServiceType(sd->getServiceType()); + uint8_t real_type = sd->getServiceType(); + t_service_id service_id = service->getServiceId(); + bool free_ca = service->getFreeCaMode(); + + int tsidonid = (transport_stream_id << 16) | original_network_id; + std::string providerName = stringDVBUTF8(sd->getServiceProviderName(), 0, tsidonid); + std::string serviceName = stringDVBUTF8(sd->getServiceName(), 0, tsidonid); + + printf("SDT: sid %04x type %x provider [%s] service [%s]\n", service_id, sd->getServiceType(), providerName.c_str(), serviceName.c_str()); + + if (!CheckScanType(service_type)) + return false; + + if(serviceName.empty() || serviceName == "."){ + char buf_tmp[64]; + snprintf(buf_tmp, sizeof(buf_tmp), "unknown (0x%04X_0x%04X)", transport_stream_id, service_id); + serviceName = buf_tmp; + } else { + FixWhiteSpaces(serviceName); + } + + if(providerName.empty()) { + providerName = "Unknown Provider"; + } else { + FixWhiteSpaces(providerName); + } + + CServiceScan::getInstance()->ChannelFound(service_type, providerName, serviceName); + + CZapitChannel *channel = CheckChannelId(service_id); + if (channel) { + channel->setName(serviceName); + channel->setServiceType(real_type); + } else { + channel = new CZapitChannel ( + serviceName, + service_id, + transport_stream_id, + original_network_id, + real_type, + satellitePosition, + freq_id + ); + CServiceManager::getInstance()->AddChannel(channel); + } + channel->scrambled = free_ca; + + AddToBouquet(providerName, channel); + + return true; +} + +CZapitChannel * CSdt::CheckChannelId(t_service_id service_id) +{ + int flist[5] = { freq_id, freq_id-1, freq_id+1, freq_id-2, freq_id+2 }; + for(int i = 0; i < 6; i++) { + freq_id_t freq = flist[i]; + t_channel_id channel_id = CREATE_CHANNEL_ID64; + CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id); + if(channel) + return channel; + freq++; + } + return NULL; +} + +void CSdt::FixWhiteSpaces(std::string &str) +{ + size_t found; + while((found = str.find(" ")) != std::string::npos) + str.replace(found, 2, " "); + + if(isspace(str[0])) + str = str.substr(1, str.length()); + if(isspace(str[str.length()-1])) + str = str.substr(0, str.length()-1); +} + +bool CSdt::CheckScanType(uint8_t service_type) +{ + switch ( scanType ) { + case CZapitClient::ST_TVRADIO: + if ( (service_type == 1 ) || (service_type == 2) ) + return true; + break; + case CZapitClient::ST_TV: + if ( service_type == 1 ) + return true; + break; + case CZapitClient::ST_RADIO: + if ( service_type == 2 ) + return true; + break; + case CZapitClient::ST_ALL: + return true; + break; + } + return false; +} + +bool CSdt::AddToBouquet(std::string &providerName, CZapitChannel *channel) +{ + switch (channel->getServiceType()) { + case ST_DIGITAL_TELEVISION_SERVICE: + case ST_DIGITAL_RADIO_SOUND_SERVICE: + case ST_NVOD_REFERENCE_SERVICE: + case ST_NVOD_TIME_SHIFTED_SERVICE: + { + char pname[100]; + if (!cable) + snprintf(pname, 100, "[%c%03d.%d] %s", satellitePosition > 0? 'E' : 'W', abs(satellitePosition)/10, abs(satellitePosition)%10, providerName.c_str()); + else + snprintf(pname, 100, "%s", providerName.c_str()); + + int bouquetId = scanBouquetManager->existsBouquet(pname); + CZapitBouquet* bouquet; + + if (bouquetId == -1) + bouquet = scanBouquetManager->addBouquet(std::string(pname), false); + else + bouquet = scanBouquetManager->Bouquets[bouquetId]; + + bouquet->addService(channel); + + return true; + } + default: + break; + } + return false; +} + +#if 0 +int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const t_original_network_id p_original_network_id, + t_satellite_position satellitePosition, freq_id_t freq) +{ + //extern bool sdt_wakeup;//zapit.cpp + unsigned char buffer[SDT_SIZE]; + + /* position in buffer */ + unsigned short pos; + unsigned short pos2; + + /* service_description_section elements */ + unsigned short section_length; + unsigned short transport_stream_id; + unsigned short original_network_id; + unsigned short service_id; + unsigned short descriptors_loop_length; + unsigned short running_status; + + bool EIT_schedule_flag; + bool EIT_present_following_flag; + bool free_CA_mode; + int tmp_free_CA_mode = -1; + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + + transponder_id_t current_tp_id = CFEManager::getInstance()->getLiveFE()->getTsidOnid(); + + memset(filter, 0x00, DMX_FILTER_SIZE); + filter[0] = 0x42; + filter[1] = (p_transport_stream_id >> 8) & 0xff; + filter[2] = p_transport_stream_id & 0xff; + filter[4] = 0x00; + filter[6] = (p_original_network_id >> 8) & 0xff; + filter[7] = p_original_network_id & 0xff; + + memset(mask, 0x00, DMX_FILTER_SIZE); + mask[0] = 0xFF; + mask[1] = 0xFF; + mask[2] = 0xFF; + mask[4] = 0xFF; + mask[6] = 0xFF; + mask[7] = 0xFF; + + CPat pat; + + int pat_ok = pat.Parse(); + + cDemux * dmx = new cDemux(); + dmx->Open(DMX_PSI_CHANNEL); + int ret = -1; + + t_service_id current_sid = 0; + unsigned short curent_pmt = 0; + unsigned char current_scrambled = 0; + CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); + if(channel) { + current_sid = channel->getServiceId(); + curent_pmt = channel->getPmtPid(); + current_scrambled = channel->scrambled; + } + //printf("parse_current_sdt: *************** current sid 0x%x ***************\n", current_sid); + do { + if ((dmx->sectionFilter(0x11, filter, mask, 8) < 0) || (dmx->Read(buffer, SDT_SIZE) < 0)) { + delete dmx; + return ret; + } + dmx->Stop(); + + section_length = ((buffer[1] & 0x0F) << 8) | buffer[2]; + transport_stream_id = (buffer[3] << 8) | buffer[4]; + original_network_id = (buffer[8] << 8) | buffer[9]; + + for (pos = 11; pos < section_length - 1; pos += descriptors_loop_length + 5) { + tmp_free_CA_mode = -1; + service_id = (buffer[pos] << 8) | buffer[pos + 1]; + EIT_schedule_flag = buffer[pos + 2] & 0x02; + EIT_present_following_flag = buffer[pos + 2] & 0x01; + running_status = buffer [pos + 3] & 0xE0; + + unsigned short pmtpid = pat.GetPmtPid(service_id); + if(pat_ok && (pmtpid > 0) && running_status != 32) { + if(service_id != current_sid) { + CPmt pmt; + tmp_free_CA_mode = pmt.haveCaSys(pmtpid, service_id); + //printf("parse_current_sdt: sid 0x%x scrambled %d\n", service_id, tmp_free_CA_mode); + } else if(pmtpid != curent_pmt) { + ret = -2; + break; + } + else { + tmp_free_CA_mode = current_scrambled; + //printf("parse_current_sdt: skip current sid 0x%x\n", current_sid); + } + } + + if(tmp_free_CA_mode == -1){ + free_CA_mode = buffer [pos + 3] & 0x10; + }else{ + free_CA_mode = tmp_free_CA_mode; + } + descriptors_loop_length = ((buffer[pos + 3] & 0x0F) << 8) | buffer[pos + 4]; + + for (pos2 = pos + 5; pos2 < pos + descriptors_loop_length + 5; pos2 += buffer[pos2 + 1] + 2) { +//printf("[sdt] descriptor %X\n", buffer[pos2]); + switch (buffer[pos2]) { + case 0x48: + current_service_descriptor(buffer + pos2, service_id, transport_stream_id, original_network_id, satellitePosition, freq, free_CA_mode); + ret = 0; + break; + + default: + /* + DBG("descriptor_tag: %02x\n", buffer[pos2]); + generic_descriptor(buffer + pos2); + */ + break; + } + } + free_CA_mode = -1; +#if 0 + if(sdt_wakeup){//break scan , transponder change + ret = -2; + break; + } +#endif + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + break; + } + } + while (filter[4]++ != buffer[7]); + delete dmx; + + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + ret = -2; + + return ret; +} +#endif From 60a0d2bb8b79efd80f1b91256ef92bcac85e8a42 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 21:38:27 +0400 Subject: [PATCH 045/737] sdt: new class --- src/zapit/include/zapit/scansdt.h | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/zapit/include/zapit/scansdt.h diff --git a/src/zapit/include/zapit/scansdt.h b/src/zapit/include/zapit/scansdt.h new file mode 100644 index 000000000..3e0a29be7 --- /dev/null +++ b/src/zapit/include/zapit/scansdt.h @@ -0,0 +1,68 @@ +/* + * Neutrino-GUI - DBoxII-Project + * + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __zapit_scan_sdt_h__ +#define __zapit_scan_sdt_h__ + +#include +#include +#include +#include + +#define SDT_SECTION_SIZE 1026 + +#if 0 +typedef std::map sidpmt_map_t; +typedef sidpmt_map_t::iterator sidpmt_map_iterator_t; +typedef std::pair sidpmt_map_pair_t; +#endif + +class CSdt +{ + private: + int dmxnum; + bool parsed; + bool cable; + + t_transport_stream_id transport_stream_id; + t_original_network_id original_network_id; + t_satellite_position satellitePosition; + freq_id_t freq_id; + + ServiceDescriptionSectionList sections; + + uint8_t FixServiceType(uint8_t type); + bool CheckScanType(uint8_t service_type); + CZapitChannel * CheckChannelId(t_service_id service_id); + void FixWhiteSpaces(std::string &str); + bool AddToBouquet(std::string &providerName, CZapitChannel *channel); + + bool Read(); + bool ParseServiceDescriptor(ServiceDescription * service, ServiceDescriptor * sd); + + public: + CSdt(t_satellite_position spos, freq_id_t frq, int dnum = 0); + ~CSdt(); + bool Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid); +}; + +#endif From a7e0aa58b2e3a6bbb0ef882f3894e2bb88a8f6f9 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 18 Jan 2012 21:38:50 +0400 Subject: [PATCH 046/737] scan: test using new sdt class --- src/zapit/src/scan.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index c987630aa..ac9899060 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #define NIT_THREAD @@ -272,12 +273,15 @@ _repeat: } #endif //INFO("parsing SDT (tsid:onid %04x:%04x)", tI->second.transport_stream_id, tI->second.original_network_id); +#if 0 int status = parse_sdt(&tI->second.transport_stream_id, &tI->second.original_network_id, satellitePosition, freq /*tI->second.feparams.frequency/1000*/); if(status < 0) { printf("[scan] SDT failed !\n"); continue; } - +#endif + CSdt sdt(satellitePosition, freq); + sdt.Parse(&tI->second.transport_stream_id, &tI->second.original_network_id); TsidOnid = CREATE_TRANSPONDER_ID_FROM_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID( freq /*tI->second.feparams.frequency/1000*/, satellitePosition, tI->second.original_network_id, tI->second.transport_stream_id); From 14493233941b9196d42036bc5fa937ec27260478 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 15:24:52 +0400 Subject: [PATCH 047/737] zapit channel: add constructor using channel_id --- src/zapit/include/zapit/channel.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/zapit/include/zapit/channel.h b/src/zapit/include/zapit/channel.h index 608424e88..46e4bd6ac 100644 --- a/src/zapit/include/zapit/channel.h +++ b/src/zapit/include/zapit/channel.h @@ -161,6 +161,7 @@ class CZapitChannel uint8_t record_demux; + void Init(); friend class CChannelList; public: @@ -179,6 +180,7 @@ class CZapitChannel /* constructor, desctructor */ CZapitChannel(const std::string & p_name, t_service_id p_sid, t_transport_stream_id p_tsid, t_original_network_id p_onid, unsigned char p_service_type, t_satellite_position p_satellite_position, freq_id_t freq); + CZapitChannel(const std::string & p_name, t_channel_id p_channel_id, unsigned char p_service_type, t_satellite_position p_satellite_position, freq_id_t p_freq); ~CZapitChannel(void); /* get methods - read only variables */ @@ -243,6 +245,11 @@ class CZapitChannel void dumpBouquetXml(FILE * fd); void setRecordDemux(int num) { record_demux = num; }; int getRecordDemux() { return record_demux; }; + static t_channel_id makeChannelId(t_satellite_position sat, freq_id_t freq, + t_transport_stream_id tsid, t_original_network_id onid, t_service_id sid) + { + return (((uint64_t)(sat+freq*4) << 48) | ((uint64_t) tsid << 32) | ((uint64_t)onid << 16) | (uint64_t)sid); + }; }; #endif /* __zapit_channel_h__ */ From 05445b01d092ebf462fc21cfe17bcb65c5487854 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 15:25:31 +0400 Subject: [PATCH 048/737] zapittypes.h: add GET_TRANSPORT_STREAM_ID_FROM_CHANNEL_ID define --- src/zapit/include/zapit/client/zapittypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zapit/include/zapit/client/zapittypes.h b/src/zapit/include/zapit/client/zapittypes.h index 216519f69..557c8df93 100644 --- a/src/zapit/include/zapit/client/zapittypes.h +++ b/src/zapit/include/zapit/client/zapittypes.h @@ -55,6 +55,7 @@ typedef uint32_t t_transponder_id; typedef uint64_t t_channel_id; #define CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID(service_id,original_network_id,transport_stream_id) ((((t_channel_id)transport_stream_id) << 32) | (((t_channel_id)original_network_id) << 16) | (t_channel_id)service_id) #define CREATE_CHANNEL_ID CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID(service_id, original_network_id, transport_stream_id) +#define GET_TRANSPORT_STREAM_ID_FROM_CHANNEL_ID(channel_id) ((t_original_network_id)((channel_id) >> 32)) #define GET_ORIGINAL_NETWORK_ID_FROM_CHANNEL_ID(channel_id) ((t_original_network_id)((channel_id) >> 16)) #define GET_SERVICE_ID_FROM_CHANNEL_ID(channel_id) ((t_service_id)(channel_id)) #define PRINTF_CHANNEL_ID_TYPE "%16llx" @@ -62,7 +63,6 @@ typedef uint64_t t_channel_id; #define SCANF_CHANNEL_ID_TYPE "%llx" #define CREATE_CHANNEL_ID64 (((uint64_t)(satellitePosition+freq*4) << 48) | ((uint64_t) transport_stream_id << 32) | ((uint64_t)original_network_id << 16) | (uint64_t)service_id) -//#define CREATE_CHANNEL_ID64 CREATE_CHANNEL_ID_FROM_64(satellitePosition, service_id, original_network_id, transport_stream_id) #define SAME_TRANSPONDER(id1, id2) ((id1 >> 16) == (id2 >> 16)) From 202ac3fa4a02301f9888e4f24055599547df5170 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 15:26:23 +0400 Subject: [PATCH 049/737] zapit channel: add constructor using channel_id --- src/zapit/src/channel.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/zapit/src/channel.cpp b/src/zapit/src/channel.cpp index 5cf65aa35..5213104f5 100644 --- a/src/zapit/src/channel.cpp +++ b/src/zapit/src/channel.cpp @@ -33,13 +33,31 @@ CZapitChannel::CZapitChannel(const std::string & p_name, t_service_id p_sid, t_t satellitePosition = p_satellite_position; freq = p_freq; channel_id = CREATE_CHANNEL_ID64; + Init(); +//printf("NEW CHANNEL %s %x\n", name.c_str(), (int) this); +} + +CZapitChannel::CZapitChannel(const std::string & p_name, t_channel_id p_channel_id, unsigned char p_service_type, t_satellite_position p_satellite_position, freq_id_t p_freq) +{ + name = p_name; + channel_id = p_channel_id; + service_id = GET_SERVICE_ID_FROM_CHANNEL_ID(channel_id); + transport_stream_id = GET_TRANSPORT_STREAM_ID_FROM_CHANNEL_ID(channel_id); + original_network_id = GET_ORIGINAL_NETWORK_ID_FROM_CHANNEL_ID(channel_id); + serviceType = p_service_type; + satellitePosition = p_satellite_position; + freq = p_freq; + Init(); +} + +void CZapitChannel::Init() +{ caPmt = NULL; rawPmt = NULL; type = 0; number = 0; scrambled = 0; pname = NULL; - //currentEvent = NULL; pmtPid = 0; resetPids(); ttx_language_code = ""; @@ -48,7 +66,6 @@ CZapitChannel::CZapitChannel(const std::string & p_name, t_service_id p_sid, t_t has_bouquet = false; record_demux = 2; polarization = 0; -//printf("NEW CHANNEL %s %x\n", name.c_str(), (int) this); } CZapitChannel::~CZapitChannel(void) @@ -58,9 +75,6 @@ CZapitChannel::~CZapitChannel(void) setCaPmt(NULL); setRawPmt(NULL); camap.clear(); - - //if(currentEvent) - // delete currentEvent; } CZapitAudioChannel *CZapitChannel::getAudioChannel(unsigned char index) From ce43e5c0b6d1d614e46f427466b83c2ae7744ffa Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 16:40:32 +0400 Subject: [PATCH 050/737] getservices.cpp: remove unused sdt.h include --- src/zapit/include/zapit/getservices.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zapit/include/zapit/getservices.h b/src/zapit/include/zapit/getservices.h index 479308fc6..530f36d12 100644 --- a/src/zapit/include/zapit/getservices.h +++ b/src/zapit/include/zapit/getservices.h @@ -28,7 +28,6 @@ #include #include -#include #include #include #include From 28c0f5419ccf927b736ea3993b2419dca8336ad4 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 16:41:22 +0400 Subject: [PATCH 051/737] pat.h: add get sid map method --- src/zapit/include/zapit/pat.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/zapit/include/zapit/pat.h b/src/zapit/include/zapit/pat.h index c5a5fb676..86309fdd9 100644 --- a/src/zapit/include/zapit/pat.h +++ b/src/zapit/include/zapit/pat.h @@ -47,6 +47,7 @@ class CPat bool Parse(); unsigned short GetPmtPid(t_service_id sid); bool Parse(CZapitChannel * const channel); + sidpmt_map_t &getSids() { return sidpmt; }; }; #endif /* __zapit_pat_h__ */ From 510f68d48aba971b8fc0121bbd4d9c1c043bf4b1 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 16:41:52 +0400 Subject: [PATCH 052/737] pat.cpp: add debug if sid not found --- src/zapit/src/pat.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/zapit/src/pat.cpp b/src/zapit/src/pat.cpp index 20f1a49aa..1c3868299 100644 --- a/src/zapit/src/pat.cpp +++ b/src/zapit/src/pat.cpp @@ -96,6 +96,8 @@ unsigned short CPat::GetPmtPid(t_service_id sid) if(it != sidpmt.end()) pid = it->second; } + if(!pid) + printf("[pat] sid %04x not found\n", sid); return pid; } From 772d8d365ff6b87c560ef3fd2c4a8164a6b072d0 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 16:48:51 +0400 Subject: [PATCH 053/737] scan: join NIT thread before continue, if sdt parse failed --- src/zapit/src/scan.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index ac9899060..ca122862e 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -281,7 +281,26 @@ _repeat: } #endif CSdt sdt(satellitePosition, freq); - sdt.Parse(&tI->second.transport_stream_id, &tI->second.original_network_id); + bool sdt_parsed = sdt.Parse(tI->second.transport_stream_id, tI->second.original_network_id); + +#ifdef NIT_THREAD + if(scan_nit && nthread) { + if(pthread_join(nthread, NULL)) + perror("pthread_join !!!!!!!!!"); + } +#else + if(scan_nit) { + printf("[scan] trying to parse NIT\n"); + int status = parse_nit(satellitePosition, freq /*tI->second.feparams.frequency/1000*/); + if(status < 0) + printf("[scan] NIT failed !\n"); + } +#endif + if(!sdt_parsed) { + printf("[scan] SDT failed !\n"); + continue; + } + TsidOnid = CREATE_TRANSPONDER_ID_FROM_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID( freq /*tI->second.feparams.frequency/1000*/, satellitePosition, tI->second.original_network_id, tI->second.transport_stream_id); @@ -304,19 +323,6 @@ _repeat: else stI->second.feparams.u.qpsk.fec_inner = tI->second.feparams.u.qpsk.fec_inner; -#ifdef NIT_THREAD - if(scan_nit && nthread) { - if(pthread_join(nthread, NULL)) - perror("pthread_join !!!!!!!!!"); - } -#else - if(scan_nit) { - printf("[scan] trying to parse NIT\n"); - int status = parse_nit(satellitePosition, freq /*tI->second.feparams.frequency/1000*/); - if(status < 0) - printf("[scan] NIT failed !\n"); - } -#endif printf("[scan] tpid ready: %llx\n", TsidOnid); } if(scan_nit) { From ff1a43aba0a1804a88fd034e58e4a090da445b30 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 16:51:36 +0400 Subject: [PATCH 054/737] scansdt: add code to scan current sdt for updates --- src/zapit/include/zapit/scansdt.h | 19 +++-- src/zapit/src/scansdt.cpp | 124 ++++++++++++++++++++++++------ 2 files changed, 109 insertions(+), 34 deletions(-) diff --git a/src/zapit/include/zapit/scansdt.h b/src/zapit/include/zapit/scansdt.h index 3e0a29be7..ac725cd08 100644 --- a/src/zapit/include/zapit/scansdt.h +++ b/src/zapit/include/zapit/scansdt.h @@ -23,32 +23,31 @@ #ifndef __zapit_scan_sdt_h__ #define __zapit_scan_sdt_h__ -#include +#include #include #include #include #define SDT_SECTION_SIZE 1026 -#if 0 -typedef std::map sidpmt_map_t; -typedef sidpmt_map_t::iterator sidpmt_map_iterator_t; -typedef std::pair sidpmt_map_pair_t; -#endif - class CSdt { private: int dmxnum; - bool parsed; bool cable; t_transport_stream_id transport_stream_id; t_original_network_id original_network_id; t_satellite_position satellitePosition; freq_id_t freq_id; + std::string lastProviderName; ServiceDescriptionSectionList sections; + CPat pat; + + /* current sdt to check updates */ + bool current; + transponder_id_t current_tp_id; uint8_t FixServiceType(uint8_t type); bool CheckScanType(uint8_t service_type); @@ -60,9 +59,9 @@ class CSdt bool ParseServiceDescriptor(ServiceDescription * service, ServiceDescriptor * sd); public: - CSdt(t_satellite_position spos, freq_id_t frq, int dnum = 0); + CSdt(t_satellite_position spos, freq_id_t frq, bool curr = false, int dnum = 0); ~CSdt(); - bool Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid); + bool Parse(t_transport_stream_id &tsid, t_original_network_id &onid); }; #endif diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp index b1bf01f55..967ba4977 100644 --- a/src/zapit/src/scansdt.cpp +++ b/src/zapit/src/scansdt.cpp @@ -1,12 +1,11 @@ /* - * $Id: sdt.cpp,v 1.44 2003/03/14 08:22:04 obi Exp $ + * Copyright (C) 2011 CoolStream International Ltd * - * (C) 2002, 2003 by Andreas Oberritter + * License: GPLv2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -40,12 +39,16 @@ #include extern CZapitClient::scanType scanType; // FIXME +extern int scan_fta_flag; // FIXME -CSdt::CSdt(t_satellite_position spos, freq_id_t frq, int dnum) +CSdt::CSdt(t_satellite_position spos, freq_id_t frq, bool curr, int dnum) { satellitePosition = spos; freq_id = frq; dmxnum = dnum; + current = curr; + transport_stream_id = 0; + original_network_id = 0; cable = (CServiceScan::getInstance()->GetFrontend()->getInfo()->type == FE_QAM); } @@ -57,6 +60,7 @@ CSdt::~CSdt() } } +/* read all sdt sections */ bool CSdt::Read() { int secdone[255]; @@ -77,12 +81,28 @@ bool CSdt::Read() filter[0] = 0x42; mask[0] = 0xFF; + + if (transport_stream_id && original_network_id) { + flen = 8; + filter[1] = (transport_stream_id >> 8) & 0xff; + filter[2] = transport_stream_id & 0xff; + filter[6] = (original_network_id >> 8) & 0xff; + filter[7] = original_network_id & 0xff; + + mask[1] = 0xFF; + mask[2] = 0xFF; + mask[6] = 0xFF; + mask[7] = 0xFF; + } if (!dmx->sectionFilter(0x11, filter, mask, flen)) { delete dmx; return false; } do { _repeat: + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + break; + if (dmx->Read(buffer, SDT_SECTION_SIZE) < 0) { delete dmx; return false; @@ -107,19 +127,29 @@ _repeat: sections.push_back(sdt); } while(sectotal < buffer[7]); + if(cable && !cable_hack_done && sectotal == 0) { cable_hack_done = true; secdone[0] = 0; goto _repeat; } delete dmx; + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + return false; return true; } -bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid) +/* parse sdt sections */ +bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) { ServiceDescriptionSectionIterator it; + if(current) { + transport_stream_id = tsid; + original_network_id = onid; + } + current_tp_id = CFEManager::getInstance()->getLiveFE()->getTsidOnid(); + if(!Read()) return false; @@ -129,7 +159,6 @@ bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid) transport_stream_id = sdt->getTransportStreamId(); original_network_id = sdt->getOriginalNetworkId(); - //ServiceDescriptionSection sdt(buffer); printf("SDT: tid %02x onid %02x\n", sdt->getTransportStreamId(), sdt->getOriginalNetworkId()); const ServiceDescriptionList &slist = *sdt->getDescriptions(); for (ServiceDescriptionConstIterator sit = slist.begin(); sit != slist.end(); ++sit) { @@ -138,7 +167,6 @@ bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid) DescriptorConstIterator dit; for (dit = service->getDescriptors()->begin(); dit != service->getDescriptors()->end(); ++dit) { Descriptor * d = *dit; - //printf("SDT: sid %x descriptor %02x\n", service->getServiceId(), d->getTag()); switch (d->getTag()) { case SERVICE_DESCRIPTOR: { @@ -150,19 +178,29 @@ bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid) { CaIdentifierDescriptor * cad = (CaIdentifierDescriptor *) d; const CaSystemIdList * calist = cad->getCaSystemIds(); + printf("CASYS: "); for(CaSystemIdConstIterator cit = calist->begin(); cit != calist->end(); ++cit) - printf("CASYS %02x\n", *cit); + printf("%02x ", *cit); + printf("\n"); } break; default: - printf("SDT: sid %x descriptor %02x\n", service->getServiceId(), d->getTag()); + { + printf("SDT: sid %x descriptor %02x: ", service->getServiceId(), d->getTag()); + uint8_t len = d->getLength(); + uint8_t buf[len]; + d->writeToBuffer(buf); + for(uint8_t i = 0; i < len; i++) + printf("%02x ", buf[i]); + printf("\n"); + } break; } } } } - *p_tsid = transport_stream_id; - *p_onid = original_network_id; + tsid = transport_stream_id; + onid = original_network_id; return true; } @@ -183,6 +221,9 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto t_service_id service_id = service->getServiceId(); bool free_ca = service->getFreeCaMode(); + if(!current && free_ca && scan_fta_flag) + return false; + int tsidonid = (transport_stream_id << 16) | original_network_id; std::string providerName = stringDVBUTF8(sd->getServiceProviderName(), 0, tsidonid); std::string serviceName = stringDVBUTF8(sd->getServiceName(), 0, tsidonid); @@ -192,7 +233,7 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto if (!CheckScanType(service_type)) return false; - if(serviceName.empty() || serviceName == "."){ + if (serviceName.empty() || serviceName == "."){ char buf_tmp[64]; snprintf(buf_tmp, sizeof(buf_tmp), "unknown (0x%04X_0x%04X)", transport_stream_id, service_id); serviceName = buf_tmp; @@ -200,10 +241,34 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto FixWhiteSpaces(serviceName); } - if(providerName.empty()) { - providerName = "Unknown Provider"; + t_channel_id channel_id = CZapitChannel::makeChannelId(satellitePosition, + freq_id, transport_stream_id, original_network_id, service_id); + if(current) { + if(CServiceManager::getInstance()->FindCurrentChannel(channel_id)) + return false; + + CZapitChannel * channel = new CZapitChannel(serviceName, channel_id, + real_type, satellitePosition, freq_id); + + CServiceManager::getInstance()->AddCurrentChannel(channel); + + channel->scrambled = free_ca; + if(pat.Parse(channel)) { + CPmt pmt; + if(pmt.haveCaSys(channel->getPmtPid(), channel->getServiceId())) + channel->scrambled = true; + } + return true; + } + + if (providerName.empty()) { + if(lastProviderName.empty()) + providerName = "Unknown Provider"; + else + providerName = lastProviderName; } else { FixWhiteSpaces(providerName); + lastProviderName = providerName; } CServiceScan::getInstance()->ChannelFound(service_type, providerName, serviceName); @@ -213,24 +278,29 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto channel->setName(serviceName); channel->setServiceType(real_type); } else { - channel = new CZapitChannel ( - serviceName, - service_id, - transport_stream_id, - original_network_id, - real_type, - satellitePosition, - freq_id - ); + channel = new CZapitChannel(serviceName, channel_id, + real_type, satellitePosition, freq_id); + CServiceManager::getInstance()->AddChannel(channel); } channel->scrambled = free_ca; AddToBouquet(providerName, channel); + if (CZapit::getInstance()->scanPids()) { + if(pat.Parse(channel)) { + CPmt pmt; + pmt.parse_pmt(channel); + } + } + if(service_type == ST_DIGITAL_TELEVISION_SERVICE && !channel->scrambled) { + CZapit::getInstance()->SetCurrentChannelID(channel->getChannelID()); + } + return true; } +/* check current freq from -2 to +2 to find if channel already exist */ CZapitChannel * CSdt::CheckChannelId(t_service_id service_id) { int flist[5] = { freq_id, freq_id-1, freq_id+1, freq_id-2, freq_id+2 }; @@ -245,6 +315,7 @@ CZapitChannel * CSdt::CheckChannelId(t_service_id service_id) return NULL; } +/* strip repeated and begin/end whitespaces */ void CSdt::FixWhiteSpaces(std::string &str) { size_t found; @@ -257,8 +328,12 @@ void CSdt::FixWhiteSpaces(std::string &str) str = str.substr(0, str.length()-1); } +/* check if service type wanted in current scan type */ bool CSdt::CheckScanType(uint8_t service_type) { + if(current) + return true; + switch ( scanType ) { case CZapitClient::ST_TVRADIO: if ( (service_type == 1 ) || (service_type == 2) ) @@ -279,6 +354,7 @@ bool CSdt::CheckScanType(uint8_t service_type) return false; } +/* create bouquet if not exist, and add channel to bouquet */ bool CSdt::AddToBouquet(std::string &providerName, CZapitChannel *channel) { switch (channel->getServiceType()) { From 91f8e44f8ea35c9f57b2a593c6d228773ce0bdb9 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 16:52:17 +0400 Subject: [PATCH 055/737] zapit: use new sdt class to scan current sdt updates --- src/zapit/src/zapit.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index 39f4b1ffa..16ae05ed4 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -2215,7 +2216,6 @@ bool CZapitSdtMonitor::Stop() void CZapitSdtMonitor::run() { time_t tstart, tcur, wtime = 0; - int ret; t_transport_stream_id transport_stream_id = 0; t_original_network_id original_network_id = 0; t_satellite_position satellitePosition = 0; @@ -2265,12 +2265,18 @@ void CZapitSdtMonitor::run() CServiceManager::getInstance()->RemoveCurrentChannels(); - ret = parse_current_sdt(transport_stream_id, original_network_id, satellitePosition, freq); +#if 0 + int ret = parse_current_sdt(transport_stream_id, original_network_id, satellitePosition, freq); if(ret) { if(ret == -1) printf("[sdt monitor] scanSDT broken ?\n"); continue; } +#endif + CSdt sdt(satellitePosition, freq, true); + if(!sdt.Parse(transport_stream_id, original_network_id)) { + continue; + } sdt_tp.insert(std::pair (tpid, time_monotonic())); bool updated = CServiceManager::getInstance()->SaveCurrentServices(tpid); From e504785ab294dae6663cd36a0c8643babf52570d Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 17:02:19 +0400 Subject: [PATCH 056/737] Reset old sdt code to master --- src/zapit/src/sdt.cpp | 58 ++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 40 deletions(-) diff --git a/src/zapit/src/sdt.cpp b/src/zapit/src/sdt.cpp index 7a55c9120..210bcb25d 100644 --- a/src/zapit/src/sdt.cpp +++ b/src/zapit/src/sdt.cpp @@ -29,9 +29,11 @@ #include #include +#include // DEMUX_DEVICE #include -#include -#include +#include +#include +#include #include #define SDT_SIZE 1026 @@ -174,7 +176,7 @@ int parse_sdt( int flen; bool cable_hack_done = false; - bool cable = (CServiceScan::getInstance()->GetFrontend()->getInfo()->type == FE_QAM); + bool cable = (CFrontend::getInstance()->getInfo()->type == FE_QAM); #if 1 flen = 5; memset(filter, 0x00, DMX_FILTER_SIZE); @@ -255,11 +257,10 @@ _repeat: ISO_639_language_descriptor(buffer + pos2); break; - /* - case 0x40: - network_name_descriptor(buffer + pos2); - break; - */ + /* case 0x40: + network_name_descriptor(buffer + pos2); + break; + */ case 0x42: stuffing_descriptor(buffer + pos2); break; @@ -361,11 +362,10 @@ _repeat: goto _repeat; } delete dmx; -#if 0 + sat_iterator_t sit = satellitePositions.find(satellitePosition); if(sit != satellitePositions.end()) sit->second.have_channels = true; -#endif return 0; } @@ -394,7 +394,7 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const unsigned char filter[DMX_FILTER_SIZE]; unsigned char mask[DMX_FILTER_SIZE]; - transponder_id_t current_tp_id = CFEManager::getInstance()->getLiveFE()->getTsidOnid(); + transponder_id_t current_tp_id = CFrontend::getInstance()->getTsidOnid(); memset(filter, 0x00, DMX_FILTER_SIZE); filter[0] = 0x42; @@ -412,24 +412,13 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const mask[6] = 0xFF; mask[7] = 0xFF; - CPat pat; - - int pat_ok = pat.Parse(); + std::vector > sidpmt; + int pat_ok = scan_parse_pat( sidpmt ); cDemux * dmx = new cDemux(); dmx->Open(DMX_PSI_CHANNEL); int ret = -1; - t_service_id current_sid = 0; - unsigned short curent_pmt = 0; - unsigned char current_scrambled = 0; - CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); - if(channel) { - current_sid = channel->getServiceId(); - curent_pmt = channel->getPmtPid(); - current_scrambled = channel->scrambled; - } - //printf("parse_current_sdt: *************** current sid 0x%x ***************\n", current_sid); do { if ((dmx->sectionFilter(0x11, filter, mask, 8) < 0) || (dmx->Read(buffer, SDT_SIZE) < 0)) { delete dmx; @@ -448,22 +437,11 @@ int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const EIT_present_following_flag = buffer[pos + 2] & 0x01; running_status = buffer [pos + 3] & 0xE0; - unsigned short pmtpid = pat.GetPmtPid(service_id); - if(pat_ok && (pmtpid > 0) && running_status != 32) { - if(service_id != current_sid) { - CPmt pmt; - tmp_free_CA_mode = pmt.haveCaSys(pmtpid, service_id); - //printf("parse_current_sdt: sid 0x%x scrambled %d\n", service_id, tmp_free_CA_mode); - } else if(pmtpid != curent_pmt) { - ret = -2; - break; - } - else { - tmp_free_CA_mode = current_scrambled; - //printf("parse_current_sdt: skip current sid 0x%x\n", current_sid); + for (unsigned short i=0; igetLiveFE()->getTsidOnid()) + if(current_tp_id != CFrontend::getInstance()->getTsidOnid()) break; } } while (filter[4]++ != buffer[7]); delete dmx; - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + if(current_tp_id != CFrontend::getInstance()->getTsidOnid()) ret = -2; return ret; From 783d34eaefefd61163cc89fbd2537525844b507a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 17:02:49 +0400 Subject: [PATCH 057/737] Remove old sdt.cpp from compile --- src/zapit/src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zapit/src/Makefile.am b/src/zapit/src/Makefile.am index e432b834e..e0b0f1885 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -21,7 +21,7 @@ noinst_LIBRARIES = libzapit.a libzapit_a_SOURCES = \ bouquets.cpp channel.cpp dvbstring.cpp getservices.cpp \ scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp femanager.cpp \ - descriptors.cpp nit.cpp pat.cpp pmt.cpp sdt.cpp fastscan.cpp \ + descriptors.cpp nit.cpp pat.cpp pmt.cpp fastscan.cpp \ scansdt.cpp bin_PROGRAMS = pzapit From a8a0d3c3b56076f2f07b843d9b38135be566909b Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 18:42:31 +0400 Subject: [PATCH 058/737] scansdt: hide debug under ifdef; indent --- src/zapit/src/scansdt.cpp | 239 +++++++++----------------------------- 1 file changed, 58 insertions(+), 181 deletions(-) diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp index 967ba4977..806dc6020 100644 --- a/src/zapit/src/scansdt.cpp +++ b/src/zapit/src/scansdt.cpp @@ -41,6 +41,8 @@ extern CZapitClient::scanType scanType; // FIXME extern int scan_fta_flag; // FIXME +#define DEBUG_SDT + CSdt::CSdt(t_satellite_position spos, freq_id_t frq, bool curr, int dnum) { satellitePosition = spos; @@ -116,8 +118,9 @@ _repeat: transport_stream_id = (buffer[3] << 8) | buffer[4]; original_network_id = (buffer[8] << 8) | buffer[9]; } +#ifdef DEBUG_SDT printf("[SDT] section %X last %X tsid 0x%x onid 0x%x -> %s\n", buffer[6], buffer[7], transport_stream_id, original_network_id, secdone[secnum] ? "skip" : "use"); - +#endif if(secdone[secnum]) continue; secdone[secnum] = 1; @@ -159,13 +162,15 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) transport_stream_id = sdt->getTransportStreamId(); original_network_id = sdt->getOriginalNetworkId(); +#ifdef DEBUG_SDT printf("SDT: tid %02x onid %02x\n", sdt->getTransportStreamId(), sdt->getOriginalNetworkId()); +#endif const ServiceDescriptionList &slist = *sdt->getDescriptions(); for (ServiceDescriptionConstIterator sit = slist.begin(); sit != slist.end(); ++sit) { ServiceDescription * service = *sit; //printf("SDT: sid %x \n", service->getServiceId()); DescriptorConstIterator dit; - for (dit = service->getDescriptors()->begin(); dit != service->getDescriptors()->end(); ++dit) { + for (dit = service->getDescriptors()->begin(); dit != service->getDescriptors()->end(); ++dit) { Descriptor * d = *dit; switch (d->getTag()) { case SERVICE_DESCRIPTOR: @@ -176,16 +181,19 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) break; case CA_IDENTIFIER_DESCRIPTOR: { +#ifdef DEBUG_SDT CaIdentifierDescriptor * cad = (CaIdentifierDescriptor *) d; const CaSystemIdList * calist = cad->getCaSystemIds(); printf("CASYS: "); for(CaSystemIdConstIterator cit = calist->begin(); cit != calist->end(); ++cit) printf("%02x ", *cit); printf("\n"); +#endif } break; default: { +#ifdef DEBUG_SDT printf("SDT: sid %x descriptor %02x: ", service->getServiceId(), d->getTag()); uint8_t len = d->getLength(); uint8_t buf[len]; @@ -193,14 +201,20 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) for(uint8_t i = 0; i < len; i++) printf("%02x ", buf[i]); printf("\n"); +#endif } break; } } + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + break; } } tsid = transport_stream_id; onid = original_network_id; + if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + return false; + return true; } @@ -228,8 +242,10 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto std::string providerName = stringDVBUTF8(sd->getServiceProviderName(), 0, tsidonid); std::string serviceName = stringDVBUTF8(sd->getServiceName(), 0, tsidonid); - printf("SDT: sid %04x type %x provider [%s] service [%s]\n", service_id, sd->getServiceType(), providerName.c_str(), serviceName.c_str()); - +#ifdef DEBUG_SDT + printf("SDT: sid %04x type %x provider [%s] service [%s]\n", service_id, sd->getServiceType(), + providerName.c_str(), serviceName.c_str()); +#endif if (!CheckScanType(service_type)) return false; @@ -335,21 +351,21 @@ bool CSdt::CheckScanType(uint8_t service_type) return true; switch ( scanType ) { - case CZapitClient::ST_TVRADIO: - if ( (service_type == 1 ) || (service_type == 2) ) - return true; - break; - case CZapitClient::ST_TV: - if ( service_type == 1 ) - return true; - break; - case CZapitClient::ST_RADIO: - if ( service_type == 2 ) - return true; - break; - case CZapitClient::ST_ALL: + case CZapitClient::ST_TVRADIO: + if ( (service_type == 1 ) || (service_type == 2) ) return true; - break; + break; + case CZapitClient::ST_TV: + if ( service_type == 1 ) + return true; + break; + case CZapitClient::ST_RADIO: + if ( service_type == 2 ) + return true; + break; + case CZapitClient::ST_ALL: + return true; + break; } return false; } @@ -357,172 +373,33 @@ bool CSdt::CheckScanType(uint8_t service_type) /* create bouquet if not exist, and add channel to bouquet */ bool CSdt::AddToBouquet(std::string &providerName, CZapitChannel *channel) { - switch (channel->getServiceType()) { - case ST_DIGITAL_TELEVISION_SERVICE: - case ST_DIGITAL_RADIO_SOUND_SERVICE: - case ST_NVOD_REFERENCE_SERVICE: - case ST_NVOD_TIME_SHIFTED_SERVICE: - { - char pname[100]; - if (!cable) - snprintf(pname, 100, "[%c%03d.%d] %s", satellitePosition > 0? 'E' : 'W', abs(satellitePosition)/10, abs(satellitePosition)%10, providerName.c_str()); - else - snprintf(pname, 100, "%s", providerName.c_str()); + switch (channel->getServiceType()) { + case ST_DIGITAL_TELEVISION_SERVICE: + case ST_DIGITAL_RADIO_SOUND_SERVICE: + case ST_NVOD_REFERENCE_SERVICE: + case ST_NVOD_TIME_SHIFTED_SERVICE: + { + char pname[100]; + if (!cable) + snprintf(pname, 100, "[%c%03d.%d] %s", satellitePosition > 0? 'E' : 'W', + abs(satellitePosition)/10, abs(satellitePosition)%10, providerName.c_str()); + else + snprintf(pname, 100, "%s", providerName.c_str()); - int bouquetId = scanBouquetManager->existsBouquet(pname); - CZapitBouquet* bouquet; + int bouquetId = scanBouquetManager->existsBouquet(pname); + CZapitBouquet* bouquet; - if (bouquetId == -1) - bouquet = scanBouquetManager->addBouquet(std::string(pname), false); - else - bouquet = scanBouquetManager->Bouquets[bouquetId]; + if (bouquetId == -1) + bouquet = scanBouquetManager->addBouquet(std::string(pname), false); + else + bouquet = scanBouquetManager->Bouquets[bouquetId]; - bouquet->addService(channel); + bouquet->addService(channel); - return true; - } - default: - break; - } + return true; + } + default: + break; + } return false; } - -#if 0 -int parse_current_sdt( const t_transport_stream_id p_transport_stream_id, const t_original_network_id p_original_network_id, - t_satellite_position satellitePosition, freq_id_t freq) -{ - //extern bool sdt_wakeup;//zapit.cpp - unsigned char buffer[SDT_SIZE]; - - /* position in buffer */ - unsigned short pos; - unsigned short pos2; - - /* service_description_section elements */ - unsigned short section_length; - unsigned short transport_stream_id; - unsigned short original_network_id; - unsigned short service_id; - unsigned short descriptors_loop_length; - unsigned short running_status; - - bool EIT_schedule_flag; - bool EIT_present_following_flag; - bool free_CA_mode; - int tmp_free_CA_mode = -1; - unsigned char filter[DMX_FILTER_SIZE]; - unsigned char mask[DMX_FILTER_SIZE]; - - transponder_id_t current_tp_id = CFEManager::getInstance()->getLiveFE()->getTsidOnid(); - - memset(filter, 0x00, DMX_FILTER_SIZE); - filter[0] = 0x42; - filter[1] = (p_transport_stream_id >> 8) & 0xff; - filter[2] = p_transport_stream_id & 0xff; - filter[4] = 0x00; - filter[6] = (p_original_network_id >> 8) & 0xff; - filter[7] = p_original_network_id & 0xff; - - memset(mask, 0x00, DMX_FILTER_SIZE); - mask[0] = 0xFF; - mask[1] = 0xFF; - mask[2] = 0xFF; - mask[4] = 0xFF; - mask[6] = 0xFF; - mask[7] = 0xFF; - - CPat pat; - - int pat_ok = pat.Parse(); - - cDemux * dmx = new cDemux(); - dmx->Open(DMX_PSI_CHANNEL); - int ret = -1; - - t_service_id current_sid = 0; - unsigned short curent_pmt = 0; - unsigned char current_scrambled = 0; - CZapitChannel * channel = CZapit::getInstance()->GetCurrentChannel(); - if(channel) { - current_sid = channel->getServiceId(); - curent_pmt = channel->getPmtPid(); - current_scrambled = channel->scrambled; - } - //printf("parse_current_sdt: *************** current sid 0x%x ***************\n", current_sid); - do { - if ((dmx->sectionFilter(0x11, filter, mask, 8) < 0) || (dmx->Read(buffer, SDT_SIZE) < 0)) { - delete dmx; - return ret; - } - dmx->Stop(); - - section_length = ((buffer[1] & 0x0F) << 8) | buffer[2]; - transport_stream_id = (buffer[3] << 8) | buffer[4]; - original_network_id = (buffer[8] << 8) | buffer[9]; - - for (pos = 11; pos < section_length - 1; pos += descriptors_loop_length + 5) { - tmp_free_CA_mode = -1; - service_id = (buffer[pos] << 8) | buffer[pos + 1]; - EIT_schedule_flag = buffer[pos + 2] & 0x02; - EIT_present_following_flag = buffer[pos + 2] & 0x01; - running_status = buffer [pos + 3] & 0xE0; - - unsigned short pmtpid = pat.GetPmtPid(service_id); - if(pat_ok && (pmtpid > 0) && running_status != 32) { - if(service_id != current_sid) { - CPmt pmt; - tmp_free_CA_mode = pmt.haveCaSys(pmtpid, service_id); - //printf("parse_current_sdt: sid 0x%x scrambled %d\n", service_id, tmp_free_CA_mode); - } else if(pmtpid != curent_pmt) { - ret = -2; - break; - } - else { - tmp_free_CA_mode = current_scrambled; - //printf("parse_current_sdt: skip current sid 0x%x\n", current_sid); - } - } - - if(tmp_free_CA_mode == -1){ - free_CA_mode = buffer [pos + 3] & 0x10; - }else{ - free_CA_mode = tmp_free_CA_mode; - } - descriptors_loop_length = ((buffer[pos + 3] & 0x0F) << 8) | buffer[pos + 4]; - - for (pos2 = pos + 5; pos2 < pos + descriptors_loop_length + 5; pos2 += buffer[pos2 + 1] + 2) { -//printf("[sdt] descriptor %X\n", buffer[pos2]); - switch (buffer[pos2]) { - case 0x48: - current_service_descriptor(buffer + pos2, service_id, transport_stream_id, original_network_id, satellitePosition, freq, free_CA_mode); - ret = 0; - break; - - default: - /* - DBG("descriptor_tag: %02x\n", buffer[pos2]); - generic_descriptor(buffer + pos2); - */ - break; - } - } - free_CA_mode = -1; -#if 0 - if(sdt_wakeup){//break scan , transponder change - ret = -2; - break; - } -#endif - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) - break; - } - } - while (filter[4]++ != buffer[7]); - delete dmx; - - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) - ret = -2; - - return ret; -} -#endif From 5914752256efce583595775af2c6cc1dccc2dcf5 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 19 Jan 2012 21:51:42 +0400 Subject: [PATCH 059/737] getservices and scan: testing provider name replace --- src/zapit/include/zapit/getservices.h | 17 +++++++ src/zapit/src/getservices.cpp | 72 +++++++++++++++++++++++++++ src/zapit/src/scansdt.cpp | 1 + 3 files changed, 90 insertions(+) diff --git a/src/zapit/include/zapit/getservices.h b/src/zapit/include/zapit/getservices.h index 530f36d12..e03451128 100644 --- a/src/zapit/include/zapit/getservices.h +++ b/src/zapit/include/zapit/getservices.h @@ -35,6 +35,7 @@ #include #include +#include #define zapped_chan_is_nvod 0x80 struct transponder @@ -83,6 +84,18 @@ typedef channel_map_t::iterator channel_map_iterator_t; typedef std::pair channel_pair_t; typedef std::pair channel_insert_res_t; +struct provider_replace +{ + t_transport_stream_id transport_stream_id; + t_original_network_id original_network_id; + int frequency; + std::string name; + std::string newname; +}; + +typedef std::list prov_replace_map_t; +typedef prov_replace_map_t::iterator prov_replace_map_iterator_t; + class CServiceManager { private: @@ -167,5 +180,9 @@ class CServiceManager } satellite_map_t & SatelliteList() { return satellitePositions; } xmlDocPtr ScanXml(); + + prov_replace_map_t replace_map; + bool LoadProviderMap(); + bool ReplaceProviderName(std::string &name, t_transport_stream_id tsid, t_original_network_id onid); }; #endif /* __getservices_h__ */ diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 3dcb612f3..526fd8cef 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -629,6 +629,7 @@ bool CServiceManager::LoadServices(bool only_current) //FIXME copy, until global satellitePositions removed //satelliteList = satellitePositions; + LoadProviderMap(); printf("[zapit] %d services loaded (%d)...\n", service_count, allchans.size()); TIMER_STOP("[zapit] service loading took"); @@ -917,3 +918,74 @@ bool CServiceManager::SaveCurrentServices(transponder_id_t tpid) return updated; } + +#define PROVIDER_MAP_XML CONFIGDIR "/zapit/providermap.xml" +bool CServiceManager::LoadProviderMap() +{ + xmlDocPtr parser; + + replace_map.clear(); + parser = parseXmlFile(PROVIDER_MAP_XML); + if (parser != NULL) { + xmlNodePtr node = xmlDocGetRootElement(parser)->xmlChildrenNode; + while ((node = xmlGetNextOccurence(node, "TS")) != NULL) { + provider_replace replace; + replace.transport_stream_id = xmlGetNumericAttribute(node, "id", 16); + replace.original_network_id = xmlGetNumericAttribute(node, "on", 16); + replace.frequency = xmlGetNumericAttribute(node, "frq", 0); + + char * n = xmlGetAttribute(node, "name"); + char * tn = xmlGetAttribute(node, "newname"); + if(n) + replace.name = n; + if(tn) + replace.newname = tn; + +printf("prov map: tsid %04x onid %04x freq %d name [%s] to [%s]\n", replace.transport_stream_id, replace.original_network_id, replace.frequency, replace.name.c_str(), replace.newname.c_str()); + replace_map.push_back(replace); + node = node->xmlNextNode; + } + xmlFreeDoc(parser); + return true; + } + return false; +} + +bool CServiceManager::ReplaceProviderName(std::string &name, t_transport_stream_id tsid, t_original_network_id onid) +{ + std::string newname; + + prov_replace_map_iterator_t it; + for (it = replace_map.begin(); it != replace_map.end(); ++it) { + provider_replace replace = *it; + /* if replace map has tsid and onid */ + if(replace.transport_stream_id && replace.original_network_id) { + /* compare tsid/onid */ + if(replace.transport_stream_id == tsid && replace.original_network_id == onid) { + /* if new name present, old name should be present */ + if(!replace.newname.empty()) { + if (name == replace.name) + newname = replace.newname; + } else { + newname = replace.name; + } + } + } else { + /* no tsid/onid, only names. if new name present, old name should be present */ + if(!replace.newname.empty()) { + if(name == replace.name) + newname = replace.newname; + } + /* no tsid/onid, no newname, only name. compare name without case */ + else if(!strcasecmp(replace.name.c_str(), name.c_str())) + newname = replace.name; + } + + } + if(!newname.empty()) { + printf("ReplaceProviderName: old [%s] new [%s]\n", name.c_str(), newname.c_str()); + name = newname; + return true; + } + return false; +} diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp index 806dc6020..9af520eb3 100644 --- a/src/zapit/src/scansdt.cpp +++ b/src/zapit/src/scansdt.cpp @@ -284,6 +284,7 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto providerName = lastProviderName; } else { FixWhiteSpaces(providerName); + CServiceManager::getInstance()->ReplaceProviderName(providerName, transport_stream_id, original_network_id); lastProviderName = providerName; } From 1a1bfb3c7f2043d2b6027bbe49b7fba6c4c90e7e Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 13:51:09 +0400 Subject: [PATCH 060/737] scansdt: fix debug descriptor len --- src/zapit/src/scansdt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp index 9af520eb3..86c391873 100644 --- a/src/zapit/src/scansdt.cpp +++ b/src/zapit/src/scansdt.cpp @@ -195,7 +195,7 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) { #ifdef DEBUG_SDT printf("SDT: sid %x descriptor %02x: ", service->getServiceId(), d->getTag()); - uint8_t len = d->getLength(); + uint8_t len = 2+d->getLength(); uint8_t buf[len]; d->writeToBuffer(buf); for(uint8_t i = 0; i < len; i++) From 78c855add3912273553f3f35a013f7987dcc5921 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 13:52:12 +0400 Subject: [PATCH 061/737] getservices: change providermap.xml location to /var/tuxbox/config --- src/zapit/src/getservices.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 526fd8cef..387ffcdf4 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -919,7 +919,7 @@ bool CServiceManager::SaveCurrentServices(transponder_id_t tpid) return updated; } -#define PROVIDER_MAP_XML CONFIGDIR "/zapit/providermap.xml" +#define PROVIDER_MAP_XML CONFIGDIR "/providermap.xml" bool CServiceManager::LoadProviderMap() { xmlDocPtr parser; @@ -934,12 +934,12 @@ bool CServiceManager::LoadProviderMap() replace.original_network_id = xmlGetNumericAttribute(node, "on", 16); replace.frequency = xmlGetNumericAttribute(node, "frq", 0); - char * n = xmlGetAttribute(node, "name"); - char * tn = xmlGetAttribute(node, "newname"); - if(n) - replace.name = n; - if(tn) - replace.newname = tn; + char * name = xmlGetAttribute(node, "name"); + char * newname = xmlGetAttribute(node, "newname"); + if(name) + replace.name = name; + if(newname) + replace.newname = newname; printf("prov map: tsid %04x onid %04x freq %d name [%s] to [%s]\n", replace.transport_stream_id, replace.original_network_id, replace.frequency, replace.name.c_str(), replace.newname.c_str()); replace_map.push_back(replace); From b95f33c56d08b032eb79be34c7e3685fcb6fc764 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 14:20:11 +0400 Subject: [PATCH 062/737] getservices: break provider replace search when first replace found --- src/zapit/src/getservices.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 387ffcdf4..9156d867b 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -980,12 +980,11 @@ bool CServiceManager::ReplaceProviderName(std::string &name, t_transport_stream_ else if(!strcasecmp(replace.name.c_str(), name.c_str())) newname = replace.name; } - - } - if(!newname.empty()) { - printf("ReplaceProviderName: old [%s] new [%s]\n", name.c_str(), newname.c_str()); - name = newname; - return true; + if(!newname.empty()) { + printf("ReplaceProviderName: old [%s] new [%s]\n", name.c_str(), newname.c_str()); + name = newname; + return true; + } } return false; } From e899d63d93b0aee1e605ca9da8c880061ca5577c Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 14:22:48 +0400 Subject: [PATCH 063/737] getservices: change printf to DBG --- src/zapit/src/getservices.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 9156d867b..7eedd6042 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -941,7 +941,9 @@ bool CServiceManager::LoadProviderMap() if(newname) replace.newname = newname; -printf("prov map: tsid %04x onid %04x freq %d name [%s] to [%s]\n", replace.transport_stream_id, replace.original_network_id, replace.frequency, replace.name.c_str(), replace.newname.c_str()); + DBR("prov map: tsid %04x onid %04x freq %d name [%s] to [%s]\n", + replace.transport_stream_id, replace.original_network_id, + replace.frequency, replace.name.c_str(), replace.newname.c_str()); replace_map.push_back(replace); node = node->xmlNextNode; } @@ -981,7 +983,7 @@ bool CServiceManager::ReplaceProviderName(std::string &name, t_transport_stream_ newname = replace.name; } if(!newname.empty()) { - printf("ReplaceProviderName: old [%s] new [%s]\n", name.c_str(), newname.c_str()); + DBG("ReplaceProviderName: old [%s] new [%s]\n", name.c_str(), newname.c_str()); name = newname; return true; } From b4ded74d83d8ab16adfe115ef2480e6a4d330c88 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 19:28:42 +0400 Subject: [PATCH 064/737] scansdt.cpp: Change iterators it++ to ++it; move scan_fta_flag from descriptors.cpp --- src/zapit/src/scansdt.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp index 86c391873..c8bf6d4e0 100644 --- a/src/zapit/src/scansdt.cpp +++ b/src/zapit/src/scansdt.cpp @@ -39,7 +39,7 @@ #include extern CZapitClient::scanType scanType; // FIXME -extern int scan_fta_flag; // FIXME +int scan_fta_flag; // FIXME #define DEBUG_SDT @@ -57,7 +57,7 @@ CSdt::CSdt(t_satellite_position spos, freq_id_t frq, bool curr, int dnum) CSdt::~CSdt() { ServiceDescriptionSectionIterator sit; - for (sit = sections.begin(); sit != sections.end(); sit++) { + for (sit = sections.begin(); sit != sections.end(); ++sit) { delete *(sit); } } @@ -156,7 +156,7 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) if(!Read()) return false; - for (it = sections.begin(); it != sections.end(); it++) { + for (it = sections.begin(); it != sections.end(); ++it) { ServiceDescriptionSection * sdt = *it; transport_stream_id = sdt->getTransportStreamId(); From 2a79d9ad41268c27fca2439b2e1b0b3017cc56a7 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 19:29:15 +0400 Subject: [PATCH 065/737] pmt.cpp: remove subtitling_descriptor call --- src/zapit/src/pmt.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zapit/src/pmt.cpp b/src/zapit/src/pmt.cpp index d47b0ba47..0a076786e 100644 --- a/src/zapit/src/pmt.cpp +++ b/src/zapit/src/pmt.cpp @@ -167,7 +167,6 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); descramble = true;//FIXME MGM / 10E scrambling subtitles ? } - subtitling_descriptor(buff + pos); break; case 0x6A: /* AC3 descriptor */ From 25ea04aeb57b67b2e1670bf3c0e2322c2ce224c7 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 19:30:12 +0400 Subject: [PATCH 066/737] getservices.cpp: fix mistake --- src/zapit/src/getservices.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index 7eedd6042..e3b3f4c0e 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -941,7 +941,7 @@ bool CServiceManager::LoadProviderMap() if(newname) replace.newname = newname; - DBR("prov map: tsid %04x onid %04x freq %d name [%s] to [%s]\n", + DBG("prov map: tsid %04x onid %04x freq %d name [%s] to [%s]\n", replace.transport_stream_id, replace.original_network_id, replace.frequency, replace.name.c_str(), replace.newname.c_str()); replace_map.push_back(replace); From 26f87c561c529200d3ca15dfefd67be80f4b0b85 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 19:31:52 +0400 Subject: [PATCH 067/737] NIT: replacement code for nit.cpp --- src/zapit/include/zapit/scannit.h | 61 +++++++ src/zapit/src/scannit.cpp | 288 ++++++++++++++++++++++++++++++ 2 files changed, 349 insertions(+) create mode 100644 src/zapit/include/zapit/scannit.h create mode 100644 src/zapit/src/scannit.cpp diff --git a/src/zapit/include/zapit/scannit.h b/src/zapit/include/zapit/scannit.h new file mode 100644 index 000000000..dc851f45f --- /dev/null +++ b/src/zapit/include/zapit/scannit.h @@ -0,0 +1,61 @@ +/* + * Neutrino-GUI - DBoxII-Project + * + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __zapit_scan_nit_h__ +#define __zapit_scan_nit_h__ + +#include +#include +#include +#include +#include +#include + +#define NIT_SECTION_SIZE 1024 + +class CNit : public OpenThreads::Thread +{ + private: + int dmxnum; + bool cable; + + t_satellite_position satellitePosition; + freq_id_t freq_id; + unsigned short nid; + + NetworkInformationSectionList sections; + + void run(); + bool Read(); + bool ParseSatelliteDescriptor(SatelliteDeliverySystemDescriptor * sd, TransportStreamInfo * ts); + bool ParseCableDescriptor(CableDeliverySystemDescriptor * sd, TransportStreamInfo * ts); + bool ParseServiceList(ServiceListDescriptor * sd, TransportStreamInfo * ts); + + public: + CNit(t_satellite_position spos, freq_id_t frq, unsigned short pnid, int dnum = 0); + ~CNit(); + bool Start(); + bool Stop(); + bool Parse(); +}; + +#endif diff --git a/src/zapit/src/scannit.cpp b/src/zapit/src/scannit.cpp new file mode 100644 index 000000000..d7ccbacd4 --- /dev/null +++ b/src/zapit/src/scannit.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2011 CoolStream International Ltd + * + * License: GPLv2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_NIT + +CNit::CNit(t_satellite_position spos, freq_id_t frq, unsigned short pnid, int dnum) +{ + satellitePosition = spos; + freq_id = frq; + nid = pnid; + dmxnum = dnum; + cable = (CServiceScan::getInstance()->GetFrontend()->getInfo()->type == FE_QAM); +} + +CNit::~CNit() +{ + NetworkInformationSectionIterator sit; + for (sit = sections.begin(); sit != sections.end(); ++sit) { + delete *(sit); + } +} + +bool CNit::Start() +{ + int ret = start(); + return (ret == 0); +} + +bool CNit::Stop() +{ + int ret = join(); + return (ret == 0); +} + +void CNit::run() +{ + if(Parse()) + printf("[scan] NIT finished.\n"); + else + printf("[scan] NIT failed !\n"); +} + +bool CNit::Read() +{ + bool ret = true; + int secdone[2][255]; + int sectotal[2] = { -1, -1 }; + int nit_index = 0; + + for(int i = 0; i < 2; i++) { + for (int j = 0; j < 255; j++) + secdone[i][j] = 0; + } + + cDemux * dmx = new cDemux(dmxnum); + dmx->Open(DMX_PSI_CHANNEL); + + unsigned char buffer[NIT_SECTION_SIZE]; + + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + + memset(filter, 0x00, DMX_FILTER_SIZE); + memset(mask, 0x00, DMX_FILTER_SIZE); + + int flen = 1; + filter[0] = 0x40; + mask[0] = (nid != 0) ? 0xFE : 0xFF; // in case we have network ID we also want the 'other' tables + + if (nid) { // filter for the network ID + filter[1] = (nid >> 8) & 0xff; + filter[2] = (nid >> 0) & 0xff; + mask[1] = 0xff; + mask[2] = 0xff; + flen = 3; + } + + if (dmx->sectionFilter(0x10, filter, mask, flen) < 0) { + delete dmx; + return false; + } + + do { + if (dmx->Read(buffer, NIT_SECTION_SIZE) < 0) { + delete dmx; + return false; + } + + if (CServiceScan::getInstance()->Aborted()) { + ret = false; + goto _return; + } + + if ((buffer[0] != 0x40) && ((nid > 0) && (buffer[0] != 0x41))) { + // NIT actual or NIT other + printf("[NIT] ******************************************* Bogus section received: 0x%x\n", buffer[0]); + ret = false; + goto _return; + } + + nit_index = buffer[0] & 1; + + unsigned char secnum = buffer[6]; +#ifdef DEBUG_NIT + printf("[NIT] section %X last %X -> %s\n", secnum, buffer[7], secdone[nit_index][secnum] ? "skip" : "use"); +#endif + if(secdone[nit_index][secnum]) // mark sec XX done + continue; + secdone[nit_index][secnum] = 1; + sectotal[nit_index]++; + + NetworkInformationSection * nit = new NetworkInformationSection(buffer); + sections.push_back(nit); + + } while(sectotal[nit_index] < buffer[7]); +_return: + dmx->Stop(); + delete dmx; + return ret; +} + +bool CNit::Parse() +{ + printf("[scan] trying to parse NIT\n"); + + if(!Read()) + return false; + + NetworkInformationSectionIterator sit; +#ifdef DEBUG_NIT + printf("NIT: %d sections\n", sections.size()); +#endif + for (sit = sections.begin(); sit != sections.end(); ++sit) { + NetworkInformationSection * nit = *sit; + const TransportStreamInfoList *tslist = nit->getTsInfo(); +#ifdef DEBUG_NIT + printf("NIT: %d TransportStreamInfos\n", tslist->size()); +#endif + if (CServiceScan::getInstance()->Aborted()) + return false; + + for(TransportStreamInfoConstIterator tit = tslist->begin(); tit != tslist->end(); ++tit) { + TransportStreamInfo * tsinfo = *tit; + const DescriptorList * dlist = tsinfo->getDescriptors(); +#if 0 //ifdef DEBUG_NIT + printf("NIT: tsid %04x onid %04x %d descriptors\n", tsinfo->getTransportStreamId(), + tsinfo->getOriginalNetworkId(), dlist->size()); +#endif + DescriptorConstIterator dit; + for (dit = dlist->begin(); dit != dlist->end(); ++dit) { + Descriptor * d = *dit; + switch(d->getTag()) { + case SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR: + ParseSatelliteDescriptor((SatelliteDeliverySystemDescriptor *)d, tsinfo); + break; + + case CABLE_DELIVERY_SYSTEM_DESCRIPTOR: + ParseCableDescriptor((CableDeliverySystemDescriptor *)d, tsinfo); + break; + + case SERVICE_LIST_DESCRIPTOR: + ParseServiceList((ServiceListDescriptor *) d, tsinfo); + break; + + default: + { +#ifdef DEBUG_NIT + printf("NIT: descriptor %02x: ", d->getTag()); + uint8_t len = 2+d->getLength(); + uint8_t buf[len]; + d->writeToBuffer(buf); + for(uint8_t i = 0; i < len; i++) + printf("%02x ", buf[i]); + printf("\n"); +#endif + } + break; + } + } + } + } + return true; +} + +bool CNit::ParseSatelliteDescriptor(SatelliteDeliverySystemDescriptor * sd, TransportStreamInfo * tsinfo) +{ + if (cable) + return false; + + t_satellite_position newSat; + newSat = ((sd->getOrbitalPosition() >> 12) & 0xF) * 1000; + newSat += ((sd->getOrbitalPosition() >> 8) & 0xF) * 100; + newSat += ((sd->getOrbitalPosition() >> 4) & 0xF) * 10; + newSat += ((sd->getOrbitalPosition()) & 0xF); + if (newSat && (!sd->getWestEastFlag())) + newSat = 3600 - newSat; + + if(satellitePosition != newSat) { + printf("NIT: different satellite position: our %d nit %d\n", + satellitePosition, sd->getOrbitalPosition()); + } + + uint8_t polarization = sd->getPolarization(); + + FrontendParameters feparams; + + feparams.inversion = INVERSION_AUTO; + feparams.frequency = sd->getFrequency() * 10; + feparams.u.qpsk.symbol_rate = sd->getSymbolRate() * 100; + + int fec_inner = CFrontend::getCodeRate(sd->getFecInner(), sd->getModulationSystem()); + if(sd->getModulation() == 2) + fec_inner += 9; + + feparams.u.qpsk.fec_inner = (fe_code_rate_t) fec_inner; + feparams.frequency = (int) 1000 * (int) round ((double) feparams.frequency / (double) 1000); + + freq_id_t freq = feparams.frequency / 1000; + transponder_id_t TsidOnid = CREATE_TRANSPONDER_ID_FROM_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID( + freq, satellitePosition, tsinfo->getTransportStreamId(), tsinfo->getOriginalNetworkId()); + + CServiceScan::getInstance()->AddTransponder(TsidOnid, &feparams, polarization, true); + + return true; +} + +bool CNit::ParseCableDescriptor(CableDeliverySystemDescriptor * sd, TransportStreamInfo * tsinfo) +{ + if (!cable) + return false; + + FrontendParameters feparams; + + feparams.inversion = INVERSION_AUTO; + feparams.frequency = sd->getFrequency() * 100; + feparams.u.qam.symbol_rate = sd->getSymbolRate() * 100; + feparams.u.qam.fec_inner = CFrontend::getCodeRate(sd->getFecInner()); + feparams.u.qam.modulation = CFrontend::getModulation(sd->getModulation()); + + if(feparams.frequency > 1000*1000) + feparams.frequency /= 1000; + + freq_id_t freq = feparams.frequency / 1000; + transponder_id_t TsidOnid = CREATE_TRANSPONDER_ID_FROM_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID( + freq, satellitePosition, tsinfo->getTransportStreamId(), tsinfo->getOriginalNetworkId()); + + CServiceScan::getInstance()->AddTransponder(TsidOnid, &feparams, 0, true); + return true; +} + +bool CNit::ParseServiceList(ServiceListDescriptor * sd, TransportStreamInfo * tsinfo) +{ + const ServiceListItemList * slist = sd->getServiceList(); + ServiceListItemConstIterator it; + for (it = slist->begin(); it != slist->end(); ++it) { + ServiceListItem * s = *it; + + t_channel_id channel_id = CZapitChannel::makeChannelId(satellitePosition, + freq_id, tsinfo->getTransportStreamId(), tsinfo->getOriginalNetworkId(), s->getServiceId()); + CServiceScan::getInstance()->AddServiceType(channel_id, s->getServiceType()); + } + return true; +} From b5831e9be13ce0e2c51b9186797ce24d79f8340c Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 19:32:07 +0400 Subject: [PATCH 068/737] zapit/src/Makefile.am: remove nit.cpp descriptors.cpp --- src/zapit/src/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/zapit/src/Makefile.am b/src/zapit/src/Makefile.am index e0b0f1885..79b68af76 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -21,8 +21,7 @@ noinst_LIBRARIES = libzapit.a libzapit_a_SOURCES = \ bouquets.cpp channel.cpp dvbstring.cpp getservices.cpp \ scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp femanager.cpp \ - descriptors.cpp nit.cpp pat.cpp pmt.cpp fastscan.cpp \ - scansdt.cpp + nit.cpp pat.cpp pmt.cpp fastscan.cpp scansdt.cpp scannit.cpp bin_PROGRAMS = pzapit sbin_PROGRAMS = udpstreampes From 59f31f3568da560e35a775372c1e3d23ad410757 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 19:33:03 +0400 Subject: [PATCH 069/737] zapit scan.cpp: replace parse_nit with new CNit class --- src/zapit/src/scan.cpp | 37 ++++++++++--------------------------- 1 file changed, 10 insertions(+), 27 deletions(-) diff --git a/src/zapit/src/scan.cpp b/src/zapit/src/scan.cpp index ca122862e..7748f53cd 100644 --- a/src/zapit/src/scan.cpp +++ b/src/zapit/src/scan.cpp @@ -26,14 +26,13 @@ #include #include -#include #include -#include #include #include #include #include #include +#include #define NIT_THREAD @@ -263,43 +262,27 @@ _repeat: else freq = tI->second.feparams.frequency/1000; + CNit nit(satellitePosition, freq, cable_nid); #ifdef NIT_THREAD - pthread_t nthread; - nit_thread_args_t threadArgs(satellitePosition, freq, cable_nid); if(scan_nit) - if(pthread_create(&nthread, 0, nit_thread, (void*)&threadArgs)) { - ERROR("pthread_create"); - nthread = 0; - } -#endif - //INFO("parsing SDT (tsid:onid %04x:%04x)", tI->second.transport_stream_id, tI->second.original_network_id); -#if 0 - int status = parse_sdt(&tI->second.transport_stream_id, &tI->second.original_network_id, satellitePosition, freq /*tI->second.feparams.frequency/1000*/); - if(status < 0) { - printf("[scan] SDT failed !\n"); - continue; - } + nit.Start(); #endif + CSdt sdt(satellitePosition, freq); bool sdt_parsed = sdt.Parse(tI->second.transport_stream_id, tI->second.original_network_id); #ifdef NIT_THREAD - if(scan_nit && nthread) { - if(pthread_join(nthread, NULL)) - perror("pthread_join !!!!!!!!!"); - } -#else - if(scan_nit) { - printf("[scan] trying to parse NIT\n"); - int status = parse_nit(satellitePosition, freq /*tI->second.feparams.frequency/1000*/); - if(status < 0) - printf("[scan] NIT failed !\n"); - } + if(scan_nit) + nit.Stop(); #endif if(!sdt_parsed) { printf("[scan] SDT failed !\n"); continue; } +#ifndef NIT_THREAD + if(scan_nit) + nit.Parse(); +#endif TsidOnid = CREATE_TRANSPONDER_ID_FROM_SATELLITEPOSITION_ORIGINALNETWORK_TRANSPORTSTREAM_ID( freq /*tI->second.feparams.frequency/1000*/, satellitePosition, tI->second.original_network_id, From bd36acf89f93ed233fe4f15abd5189a7227cc4cf Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Fri, 20 Jan 2012 20:13:02 +0400 Subject: [PATCH 070/737] descriptors.cpp restore original code from master --- src/zapit/src/descriptors.cpp | 38 +++++++++-------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/src/zapit/src/descriptors.cpp b/src/zapit/src/descriptors.cpp index e198da888..dc43bc83b 100644 --- a/src/zapit/src/descriptors.cpp +++ b/src/zapit/src/descriptors.cpp @@ -251,8 +251,7 @@ int satellite_delivery_system_descriptor(const unsigned char * const buffer, t_t transponder_id_t TsidOnid; int modulationSystem, modulationType, rollOff, fec_inner; - CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); - if (frontend->getInfo()->type != FE_QPSK) + if (CFrontend::getInstance()->getInfo()->type != FE_QPSK) return -1; feparams.frequency = @@ -316,8 +315,7 @@ int satellite_delivery_system_descriptor(const unsigned char * const buffer, t_t int cable_delivery_system_descriptor(const unsigned char * const buffer, t_transport_stream_id transport_stream_id, t_original_network_id original_network_id, t_satellite_position satellitePosition, freq_id_t freq) { transponder_id_t TsidOnid; - CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); - if (frontend->getInfo()->type != FE_QAM) + if (CFrontend::getInstance()->getInfo()->type != FE_QAM) return -1; FrontendParameters feparams; @@ -444,9 +442,6 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s CZapitChannel *channel = NULL; bool tpchange = false; static transponder_id_t last_tpid = 0; - - static CPat pat; - //scrambled if(free_ca && scan_fta_flag){ return; @@ -629,8 +624,7 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s CZapitBouquet* bouquet; int bouquetId; char pname[100]; - CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); - if (frontend->getInfo()->type == FE_QPSK) + if (CFrontend::getInstance()->getInfo()->type == FE_QPSK) snprintf(pname, 100, "[%c%03d.%d] %s", satellitePosition > 0? 'E' : 'W', abs(satellitePosition)/10, abs(satellitePosition)%10, providerName.c_str()); else snprintf(pname, 100, "%s", providerName.c_str()); @@ -660,14 +654,10 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s break; } if(CZapit::getInstance()->scanPids()) { - if(tpchange) { - //parse_pat(); - pat.Reset(); - pat.Parse(); - } + if(tpchange) + parse_pat(); channel->resetPids(); -#if 0 if(!pat_get_pmt_pid(channel)) { if(!parse_pmt(channel)) { //if(channel->getPreAudioPid() == 0 && channel->getVideoPid() == 0) @@ -677,15 +667,6 @@ void service_descriptor(const unsigned char * const buffer, const t_service_id s } } } -#endif - if(pat.Parse(channel)) { - CPmt pmt; - if(!pmt.parse_pmt(channel)) { - if ((channel->getPreAudioPid() != 0) || (channel->getVideoPid() != 0)) { - channel->setPidsFlag(); - } - } - } } if(service_type == ST_DIGITAL_TELEVISION_SERVICE && !channel->scrambled) { CZapit::getInstance()->SetCurrentChannelID(channel->getChannelID()); @@ -870,12 +851,11 @@ void subtitling_descriptor(const unsigned char * const) /* 0x5A */ int terrestrial_delivery_system_descriptor(const unsigned char * const) { - /* TODO */ -#if 0 - CFrontend * frontend = CServiceScan::getInstance()->GetFrontend(); - if (frontend->getInfo()->type != FE_OFDM) + if (CFrontend::getInstance()->getInfo()->type != FE_OFDM) return -1; -#endif + + /* TODO */ + return 0; } From 4aa1ca94d377ec6e8ceb6d6af2c627525cc6c034 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Mon, 23 Jan 2012 19:08:59 +0400 Subject: [PATCH 071/737] nit.cpp/.h: revert to old code --- src/zapit/include/zapit/nit.h | 14 +------ src/zapit/src/nit.cpp | 72 +++++++++++++---------------------- 2 files changed, 27 insertions(+), 59 deletions(-) diff --git a/src/zapit/include/zapit/nit.h b/src/zapit/include/zapit/nit.h index 6b2c0df0e..d68382cb1 100644 --- a/src/zapit/include/zapit/nit.h +++ b/src/zapit/include/zapit/nit.h @@ -22,18 +22,6 @@ #ifndef __zapit_nit_h__ #define __zapit_nit_h__ -typedef struct nit_thread_args { - t_satellite_position satellitePosition; - freq_id_t freq; - unsigned short nid; - - nit_thread_args(t_satellite_position SatellitePosition, freq_id_t Freq, unsigned short Nid = 0) { - satellitePosition = SatellitePosition; - freq = Freq; - nid = Nid; - } -} nit_thread_args_t; - -int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned short nid = 0); +int parse_nit(t_satellite_position satellitePosition, freq_id_t freq); #endif /* __zapit_nit_h__ */ diff --git a/src/zapit/src/nit.cpp b/src/zapit/src/nit.cpp index 3472b37c1..0a58e6135 100644 --- a/src/zapit/src/nit.cpp +++ b/src/zapit/src/nit.cpp @@ -35,9 +35,10 @@ extern short abort_scan; void *nit_thread(void * data) { - nit_thread_args_t *threadArgs = (nit_thread_args_t *)data; + int satellitePosition = (int) data; + printf("[scan] trying to parse NIT\n"); - int status = parse_nit(threadArgs->satellitePosition, threadArgs->freq, threadArgs->nid); + int status = parse_nit(satellitePosition, 0); if(status < 0) printf("[scan] NIT failed !\n"); else @@ -46,19 +47,16 @@ void *nit_thread(void * data) pthread_exit(NULL); } -int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned short nid) +int parse_nit(t_satellite_position satellitePosition, freq_id_t freq) { int ret = 0; - int secdone[2][255]; - int sectotal[2] = { -1, -1 }; - int nit_index = 0; + int secdone[255]; + int sectotal = -1; - for(int i = 0; i < 2; i++) { - for (int j = 0; j < 255; j++) - secdone[i][j] = 0; - } + for(int i = 0; i < 255; i++) + secdone[i] = 0; - cDemux * dmx = new cDemux(); + cDemux * dmx = new cDemux();; dmx->Open(DMX_PSI_CHANNEL); unsigned char buffer[NIT_SIZE]; @@ -84,15 +82,7 @@ int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned s filter[0] = 0x40; //filter[4] = 0x00; - mask[0] = (nid != 0) ? 0xFE : 0xFF; // in case we have network ID we also want the 'other' tables - - if (nid) { // filter for the network ID - filter[1] = (nid >> 8) & 0xff; - filter[2] = (nid >> 0) & 0xff; - mask[1] = 0xff; - mask[2] = 0xff; - } - + mask[0] = 0xFF; //mask[4] = 0xFF; //unsigned char sec = 0x00; @@ -100,44 +90,34 @@ int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned s delete dmx; return -1; } - do { if (dmx->Read(buffer, NIT_SIZE) < 0) { delete dmx; return -1; } - if (CServiceScan::getInstance()->Aborted()) { ret = -1; goto _return; } - - if ((buffer[0] != 0x40) && ((nid > 0) && (buffer[0] != 0x41))) { - // NIT actual or NIT other - printf("[NIT] ******************************************* Bogus section received: 0x%x\n", buffer[0]); - ret = -1; - goto _return; - } - - nit_index = buffer[0] & 1; +if(buffer[0] != 0x40) + printf("[NIT] ******************************************* Bogus section received: 0x%x\n", buffer[0]); section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; network_id = ((buffer[3] << 8)| buffer [4]); network_descriptors_length = ((buffer[8] & 0x0F) << 8) | buffer[9]; unsigned char secnum = buffer[6]; - printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], network_id, secdone[nit_index][secnum] ? "skip" : "use"); - if(secdone[nit_index][secnum]) // mark sec XX done +printf("[NIT] section %X last %X network_id 0x%x -> %s\n", secnum, buffer[7], network_id, secdone[secnum] ? "skip" : "use"); + if(secdone[secnum]) // mark sec XX done continue; - secdone[nit_index][secnum] = 1; - sectotal[nit_index]++; + secdone[secnum] = 1; + sectotal++; for (pos = 10; pos < network_descriptors_length + 10; pos += buffer[pos + 1] + 2) { switch (buffer[pos]) { - /* - case 0x0F: - Private_data_indicator_descriptor(buffer + pos); - break; - */ + /* case 0x0F: + Private_data_indicator_descriptor(buffer + pos); + break; + */ case 0x40: network_name_descriptor(buffer + pos); break; @@ -149,11 +129,11 @@ int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned s case 0x5B: multilingual_network_name_descriptor(buffer + pos); break; - /* - case 0x5F: - private_data_specifier_descriptor(buffer + pos); - break; - */ + + /* case 0x5F: + private_data_specifier_descriptor(buffer + pos); + break; + */ case 0x80: /* unknown, Eutelsat 13.0E */ break; @@ -234,7 +214,7 @@ int parse_nit(t_satellite_position satellitePosition, freq_id_t freq, unsigned s } } } - } while(sectotal[nit_index] < buffer[7]); + } while(sectotal < buffer[7]); //} while (filter[4]++ != buffer[7]); _return: dmx->Stop(); From 5486ed5b7a6e8477e5a4ca4be8999f065a58c0fa Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Mon, 23 Jan 2012 20:49:35 +0400 Subject: [PATCH 072/737] remove nit.cpp from build --- src/zapit/src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zapit/src/Makefile.am b/src/zapit/src/Makefile.am index 79b68af76..795a55d71 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -21,7 +21,7 @@ noinst_LIBRARIES = libzapit.a libzapit_a_SOURCES = \ bouquets.cpp channel.cpp dvbstring.cpp getservices.cpp \ scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp femanager.cpp \ - nit.cpp pat.cpp pmt.cpp fastscan.cpp scansdt.cpp scannit.cpp + pat.cpp pmt.cpp fastscan.cpp scansdt.cpp scannit.cpp bin_PROGRAMS = pzapit sbin_PROGRAMS = udpstreampes From 8a9a1554024c34e70d6c90cabece4bc824141239 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Mon, 23 Jan 2012 20:51:10 +0400 Subject: [PATCH 073/737] pmt: use camap to set scrambled flag also at scan time --- src/zapit/src/pmt.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/zapit/src/pmt.cpp b/src/zapit/src/pmt.cpp index 0a076786e..7e7d60adb 100644 --- a/src/zapit/src/pmt.cpp +++ b/src/zapit/src/pmt.cpp @@ -366,7 +366,7 @@ bool CPmt::parse_pmt(CZapitChannel * const channel) /* length of elementary stream description */ unsigned short ES_info_length; - printf("[zapit] parsing pmt pid 0x%X\n", channel->getPmtPid()); + printf("[zapit] parsing pmt pid 0x%X (%s)\n", channel->getPmtPid(), channel->getName().c_str()); if (channel->getPmtPid() == 0) return false; @@ -406,18 +406,25 @@ bool CPmt::parse_pmt(CZapitChannel * const channel) for (i = 12 + program_info_length; i < section_length - 1; i += ES_info_length + 5) ES_info_length = ParseES(buffer + i, channel, caPmt); + casys_map_t camap; + MakeCAMap(camap); + channel->scrambled = !camap.empty(); + if(CServiceScan::getInstance()->Scanning()) { channel->setCaPmt(NULL); channel->setRawPmt(NULL); delete caPmt; } else { +#if 0 MakeCAMap(channel->camap); + channel->scrambled = !channel->camap.empty(); +#endif + channel->camap = camap; channel->setCaPmt(caPmt); int pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] + 3; unsigned char * p = new unsigned char[pmtlen]; memmove(p, buffer, pmtlen); channel->setRawPmt(p, pmtlen); - channel->scrambled = !channel->camap.empty(); } #if 0 //Quick&Dirty Hack to support Premiere's EPG not only on the portal but on the subchannels as well @@ -440,6 +447,7 @@ bool CPmt::haveCaSys(int pmtpid, int service_id ) casys_map_t camap; MakeCAMap(camap); +printf("CPmt::haveCaSys: sid %04x camap.size %d\n", service_id, camap.size()); return !camap.empty(); } From 85f2f9f83c2b0a60bb30ef146cd81d1624c4bb9d Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Mon, 23 Jan 2012 20:52:11 +0400 Subject: [PATCH 074/737] nit: ifdef DEBUG_NIT_UNUSED for dumping unhandled descriptors --- src/zapit/src/scannit.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/zapit/src/scannit.cpp b/src/zapit/src/scannit.cpp index d7ccbacd4..b8162c044 100644 --- a/src/zapit/src/scannit.cpp +++ b/src/zapit/src/scannit.cpp @@ -27,6 +27,7 @@ #include #define DEBUG_NIT +//#define DEBUG_NIT_UNUSED CNit::CNit(t_satellite_position spos, freq_id_t frq, unsigned short pnid, int dnum) { @@ -189,7 +190,7 @@ bool CNit::Parse() default: { -#ifdef DEBUG_NIT +#ifdef DEBUG_NIT_UNUSED printf("NIT: descriptor %02x: ", d->getTag()); uint8_t len = 2+d->getLength(); uint8_t buf[len]; @@ -223,6 +224,7 @@ bool CNit::ParseSatelliteDescriptor(SatelliteDeliverySystemDescriptor * sd, Tran if(satellitePosition != newSat) { printf("NIT: different satellite position: our %d nit %d\n", satellitePosition, sd->getOrbitalPosition()); + return false; } uint8_t polarization = sd->getPolarization(); From 4e5fb4c1bba09b68f8a48a723d4c37cdcdf5ef8a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 25 Jan 2012 17:23:56 +0400 Subject: [PATCH 075/737] pmt: restore code from master --- src/zapit/include/zapit/pmt.h | 19 +- src/zapit/src/pmt.cpp | 427 +++++++++++++++++++++++++--------- 2 files changed, 319 insertions(+), 127 deletions(-) diff --git a/src/zapit/include/zapit/pmt.h b/src/zapit/include/zapit/pmt.h index b8db4eb5d..d858a5ce3 100644 --- a/src/zapit/include/zapit/pmt.h +++ b/src/zapit/include/zapit/pmt.h @@ -25,24 +25,9 @@ #include "channel.h" #include "ci.h" +int parse_pmt(CZapitChannel * const channel); int pmt_set_update_filter(CZapitChannel * const channel, int * fd); int pmt_stop_update_filter(int * fd); +int scan_parse_pmt(int pmtpid, int service_id ); -#define PMT_SECTION_SIZE 1024 -class CPmt -{ - private: - int dmxnum; - unsigned char buffer[PMT_SECTION_SIZE]; - - bool Read(unsigned short pid, unsigned short sid); - void MakeCAMap(casys_map_t &camap); - unsigned short ParseES(const unsigned char * const buff, CZapitChannel * const channel, CCaPmt * const caPmt); - public: - CPmt(int dnum = 0); - ~CPmt(); - - bool parse_pmt(CZapitChannel * const channel); - bool haveCaSys(int pmtpid, int service_id); -}; #endif /* __zapit_pmt_h__ */ diff --git a/src/zapit/src/pmt.cpp b/src/zapit/src/pmt.cpp index 7e7d60adb..b9006374f 100644 --- a/src/zapit/src/pmt.cpp +++ b/src/zapit/src/pmt.cpp @@ -55,16 +55,7 @@ * 0xc6 User Private (Canal+) */ -CPmt::CPmt(int dnum) -{ - dmxnum = dnum; -} - -CPmt::~CPmt() -{ -} - -unsigned short CPmt::ParseES(const unsigned char * const buff, CZapitChannel * const channel, CCaPmt * const caPmt) +unsigned short parse_ES_info(const unsigned char * const buffer, CZapitChannel * const channel, CCaPmt * const caPmt) { unsigned short ES_info_length; unsigned short pos; @@ -82,46 +73,73 @@ unsigned short CPmt::ParseES(const unsigned char * const buff, CZapitChannel * c /* elementary stream info for ca pmt */ CEsInfo *esInfo = new CEsInfo(); - esInfo->stream_type = buff[0]; - esInfo->reserved1 = buff[1] >> 5; - esInfo->elementary_PID = ((buff[1] & 0x1F) << 8) | buff[2]; - esInfo->reserved2 = buff[3] >> 4; + esInfo->stream_type = buffer[0]; + esInfo->reserved1 = buffer[1] >> 5; + esInfo->elementary_PID = ((buffer[1] & 0x1F) << 8) | buffer[2]; + esInfo->reserved2 = buffer[3] >> 4; - ES_info_length = ((buff[3] & 0x0F) << 8) | buff[4]; + ES_info_length = ((buffer[3] & 0x0F) << 8) | buffer[4]; for (pos = 5; pos < ES_info_length + 5; pos += descriptor_length + 2) { - descriptor_tag = buff[pos]; - descriptor_length = buff[pos + 1]; + descriptor_tag = buffer[pos]; + descriptor_length = buffer[pos + 1]; unsigned char fieldCount = descriptor_length / 5; switch (descriptor_tag) { + case 0x02: + video_stream_descriptor(buffer + pos); + break; + + case 0x03: + audio_stream_descriptor(buffer + pos); + break; + case 0x05: if (descriptor_length >= 3) - if (!strncmp((const char*)&buff[pos + 2], "DTS", 3)) + if (!strncmp((const char*)&buffer[pos + 2], "DTS", 3)) isDts = true; break; case 0x09: - esInfo->addCaDescriptor(buff + pos); + esInfo->addCaDescriptor(buffer + pos); descramble = true; break; case 0x0A: /* ISO_639_language_descriptor */ #if 0 -printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); +printf("descr 0x0A: %02X %02X %02X\n", buffer[pos+2], buffer[pos+3], buffer[pos+4]); #endif /* FIXME cyfra+ radio -> 41 20 31 ?? */ - if (description != "" && buff[pos + 3] == ' ') { - description += buff[pos + 3]; - description += buff[pos + 4]; + if (description != "" && buffer[pos + 3] == ' ') { + description += buffer[pos + 3]; + description += buffer[pos + 4]; } else { for (i = 0; i < 3; i++) - description += tolower(buff[pos + i + 2]); + description += tolower(buffer[pos + i + 2]); } break; + case 0x13: /* Defined in ISO/IEC 13818-6 */ + break; + + case 0x0E: + Maximum_bitrate_descriptor(buffer + pos); + break; + + case 0x0F: + Private_data_indicator_descriptor(buffer + pos); + break; + + case 0x11: + STD_descriptor(buffer + pos); + break; + + case 0x45: + VBI_data_descriptor(buffer + pos); + break; + case 0x52: /* stream_identifier_descriptor */ - componentTag = buff[pos + 2]; + componentTag = buffer[pos + 2]; break; case 0x56: /* teletext descriptor */ @@ -129,12 +147,12 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); //printf("[pmt] teletext pid %x: %s\n", esInfo->elementary_PID, tmp_Lang); printf("[pmt] teletext pid %x\n", esInfo->elementary_PID); for (unsigned char fIdx = 0; fIdx < fieldCount; fIdx++) { - memmove(tmp_Lang, &buff[pos + 5*fIdx + 2], 3); + memmove(tmp_Lang, &buffer[pos + 5*fIdx + 2], 3); tmp_Lang[3] = '\0'; - unsigned char teletext_type=buff[pos + 5*fIdx + 5]>> 3; - unsigned char teletext_magazine_number = buff[pos + 5*fIdx + 5] & 7; - unsigned char teletext_page_number=buff[pos + 5*fIdx + 6]; - printf("[pmt] teletext type %d mag %d page %d lang %s\n", teletext_type, teletext_magazine_number, teletext_page_number, tmp_Lang); + unsigned char teletext_type=buffer[pos + 5*fIdx + 5]>> 3; + unsigned char teletext_magazine_number = buffer[pos + 5*fIdx + 5] & 7; + unsigned char teletext_page_number=buffer[pos + 5*fIdx + 6]; +printf("[pmt] teletext type %d mag %d page %d lang %s\n", teletext_type, teletext_magazine_number, teletext_page_number, tmp_Lang); if (teletext_type==0x01) channel->setTeletextLang(tmp_Lang); if (teletext_type==0x02){ @@ -155,24 +173,36 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); unsigned char fieldCount1=descriptor_length/8; for (unsigned char fIdx=0;fIdxaddDVBSubtitle(esInfo->elementary_PID,tmpLang,subtitling_type,composition_page_id,ancillary_page_id); } descramble = true;//FIXME MGM / 10E scrambling subtitles ? } + subtitling_descriptor(buffer + pos); + break; + + case 0x5F: + private_data_specifier_descriptor(buffer + pos); + break; + + case 0x66: + data_broadcast_id_descriptor(buffer + pos); break; case 0x6A: /* AC3 descriptor */ isAc3 = true; break; + case 0x6F: /* unknown, Astra 19.2E */ + break; + case 0x7B: isDts = true; break; @@ -181,8 +211,50 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); isAac = true; break; + case 0x90: /* unknown, Astra 19.2E */ + break; + + case 0xB1: /* unknown, Astra 19.2E */ + break; + + case 0xC0: /* unknown, Astra 19.2E */ + break; + + case 0xC1: /* unknown, Astra 19.2E */ + break; + + case 0xC2: /* User Private descriptor - Canal+ */ +#if 0 + DBG("0xC2 dump:"); + for (i = 0; i < descriptor_length; i++) { + printf("%c", buffer[pos + 2 + i]); + if (((i+1) % 8) == 0) + printf("\n"); + } +#endif + break; + case 0xC5: /* User Private descriptor - Canal+ Radio */ - description = convertDVBUTF8((const char*)&buff[pos+3], 24, 2, channel->getTransportStreamId() << 16 | channel->getOriginalNetworkId()); + //description = convertDVBUTF8((const char*)&buffer[pos+3], 24, 2, 1); + description = convertDVBUTF8((const char*)&buffer[pos+3], 24, 2, channel->getTransportStreamId() << 16 | channel->getOriginalNetworkId()); +#if 0 +printf("descr 0xC5\n"); + for (i = 0; i < 24; i++) { +printf("%02X ", buffer[pos + i]); + //description += buffer[pos + i + 3]; + } +printf("\n"); +printf("[pmt] name %s\n", description.c_str()); +#endif + break; + + case 0xC6: /* unknown, Astra 19.2E */ + break; + + case 0xFD: /* unknown, Astra 19.2E */ + break; + + case 0xFE: /* unknown, Astra 19.2E */ break; default: @@ -219,17 +291,17 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); int tmp=0; // Houdini: shameless stolen from enigma dvbservices.cpp for (pos = 5; pos < ES_info_length + 5; pos += descriptor_length + 2) { - descriptor_tag = buff[pos]; - descriptor_length = buff[pos + 1]; + descriptor_tag = buffer[pos]; + descriptor_length = buffer[pos + 1]; switch (descriptor_tag) { case 0x5F: //DESCR_PRIV_DATA_SPEC: - if ( ((buff[pos + 2]<<24) | (buff[pos + 3]<<16) | (buff[pos + 4]<<8) | (buff[pos + 5])) == 190 ) + if ( ((buffer[pos + 2]<<24) | (buffer[pos + 3]<<16) | (buffer[pos + 4]<<8) | (buffer[pos + 5])) == 190 ) tmp |= 1; break; case 0x90: { - if ( descriptor_length == 4 && !buff[pos + 2] && !buff[pos + 3] && buff[pos + 4] == 0xFF && buff[pos + 5] == 0xFF ) + if ( descriptor_length == 4 && !buffer[pos + 2] && !buffer[pos + 3] && buffer[pos + 4] == 0xFF && buffer[pos + 5] == 0xFF ) tmp |= 2; } //break;?? @@ -293,8 +365,26 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); if(!CServiceScan::getInstance()->Scanning()) channel->addAudioChannel(esInfo->elementary_PID, CZapitAudioChannel::AAC, description, componentTag); break; + case 0x0B: + break; + + case 0x90: + break; + + case 0x93: + break; + + case 0xC0: + break; + + case 0xC1: + break; + + case 0xC6: + break; + default: - INFO("stream_type: %02x\n", esInfo->stream_type); + DBG("stream_type: %02x\n", esInfo->stream_type); break; } @@ -306,21 +396,48 @@ printf("descr 0x0A: %02X %02X %02X\n", buff[pos+2], buff[pos+3], buff[pos+4]); return ES_info_length; } -bool CPmt::Read(unsigned short pid, unsigned short sid) +int curpmtpid,curservice_id; +int pmt_caids[4][11] = {{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0}}; + +int parse_pmt(CZapitChannel * const channel) { - bool ret = true; + int pmtlen; + int ia, dpmtlen, pos; + unsigned char descriptor_length=0; + + unsigned char buffer[PMT_SIZE]; + + /* current position in buffer */ + unsigned short i,j; + for(j=0;j<4;j++){ + for(i=0;i<11;i++) + pmt_caids[j][i] = 0; + } + /* length of elementary stream description */ + unsigned short ES_info_length; + + /* TS_program_map_section elements */ + unsigned short section_length; + unsigned short program_info_length; + unsigned char filter[DMX_FILTER_SIZE]; unsigned char mask[DMX_FILTER_SIZE]; - cDemux * dmx = new cDemux(dmxnum); + printf("[zapit] parsing pmt pid 0x%X\n", channel->getPmtPid()); + + if (channel->getPmtPid() == 0){ + return -1; + } + + cDemux * dmx = new cDemux(); dmx->Open(DMX_PSI_CHANNEL); memset(filter, 0x00, DMX_FILTER_SIZE); memset(mask, 0x00, DMX_FILTER_SIZE); filter[0] = 0x02; /* table_id */ - filter[1] = sid >> 8; - filter[2] = sid; + filter[1] = channel->getServiceId() >> 8; + filter[2] = channel->getServiceId(); filter[3] = 0x01; /* current_next_indicator */ filter[4] = 0x00; /* section_number */ mask[0] = 0xFF; @@ -328,55 +445,83 @@ bool CPmt::Read(unsigned short pid, unsigned short sid) mask[2] = 0xFF; mask[3] = 0x01; mask[4] = 0xFF; - if ((dmx->sectionFilter(pid, filter, mask, 5) < 0) || (dmx->Read(buffer, PMT_SIZE) < 0)) { - printf("CPmt::Read: pid %x failed\n", pid); - ret = false; + + if ((dmx->sectionFilter(channel->getPmtPid(), filter, mask, 5) < 0) || (dmx->Read(buffer, PMT_SIZE) < 0)) { + delete dmx; + return -1; } delete dmx; - return ret; -} - -void CPmt::MakeCAMap(casys_map_t &camap) -{ - int pmtlen; - int pos; - unsigned char descriptor_length=0; + curservice_id = channel->getServiceId(); + curpmtpid = channel->getPmtPid(); pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] +3; + + dpmtlen=0; pos=10; - camap.clear(); - while(pos + 2 < pmtlen) { - int dpmtlen=((buffer[pos] & 0x0f) << 8) | buffer[pos+1]; - for (int ia = pos+2; ia < (dpmtlen+pos+2);ia += descriptor_length + 2) { - descriptor_length = buffer[ia+1]; - if (ia < pmtlen - 4) - if(buffer[ia] == 0x09 && buffer[ia + 1] > 0) { - int caid = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3];; - camap.insert(caid); - } + short int ci0 = 0, ci1 = 0, ci2 = 0, ci3 = 0, ci4 = 0, ci5 = 0, ci6 = 0, ci7 = 0, ci8 = 0, ci9 = 0, ci10 = 0; + if(!CServiceScan::getInstance()->Scanning()) { + while(pos+20) { + switch(buffer[ia+2]) { + case 0x06: pmt_caids[ci0][0] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci0 < 3) ci0++; + break; + case 0x17: pmt_caids[ci1][1] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci1 < 3) ci1++; + break; + case 0x01: pmt_caids[ci2][2] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci2 < 3) ci2++; + break; + case 0x05: pmt_caids[ci3][3] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci3 < 3) ci3++; + break; + case 0x18: pmt_caids[ci4][4] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci4 < 3) ci4++; + break; + case 0x0B: pmt_caids[ci5][5] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci5 < 3) ci5++; + break; + case 0x0D: pmt_caids[ci6][6] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci6 < 3) ci6++; + break; + case 0x09: pmt_caids[ci7][7] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci7 < 3) ci7++; + break; + case 0x26: pmt_caids[ci8][8] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci8 < 3) ci8++; + break; + case 0x4a: pmt_caids[ci9][9] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci9 < 3) ci9++; + break; + case 0x0E: pmt_caids[ci10][10] = (buffer[ia+2] & 0x1f) << 8 | buffer[ia+3]; + if(ci10 < 3) ci10++; + break; + } //switch + } // if + } // for + pos+=dpmtlen+5; + } // while +#if 0 + fout=fopen("/tmp/caids.info","w"); + if(fout) { + fprintf(fout, "%d %d %d %d %d %d %d %d %d %d\n", caids[0],caids[1],caids[2],caids[3],caids[4],caids[5], caids[6], caids[7], caids[8], caids[9]); + fclose(fout); } - pos += dpmtlen + 5; - } -} -bool CPmt::parse_pmt(CZapitChannel * const channel) -{ - unsigned short i; - - /* length of elementary stream description */ - unsigned short ES_info_length; - - printf("[zapit] parsing pmt pid 0x%X (%s)\n", channel->getPmtPid(), channel->getName().c_str()); - - if (channel->getPmtPid() == 0) - return false; - - if(!Read(channel->getPmtPid(), channel->getServiceId())) - return false; +#endif + } /* if !CServiceScan::getInstance()->Scanning() */ + CCaPmt *caPmt = new CCaPmt(); /* ca pmt */ - CCaPmt *caPmt = new CCaPmt(buffer); - caPmt->ca_pmt_pid = channel->getPmtPid(); + caPmt->program_number = (buffer[3] << 8) + buffer[4]; + caPmt->reserved1 = buffer[5] >> 6; + caPmt->version_number = (buffer[5] >> 1) & 0x1F; + caPmt->current_next_indicator = buffer[5] & 0x01; + caPmt->reserved2 = buffer[10] >> 4; printf("[pmt] pcr pid: old 0x%x new 0x%x\n", channel->getPcrPid(), ((buffer[8] & 0x1F) << 8) + buffer[9]); @@ -385,11 +530,14 @@ bool CPmt::parse_pmt(CZapitChannel * const channel) channel->resetPids(); } /* pmt */ + section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; - channel->setPcrPid(((buffer[8] & 0x1F) << 8) + buffer[9]); + //if(!channel->getPidsFlag()) + channel->setPcrPid(((buffer[8] & 0x1F) << 8) + buffer[9]); - unsigned short program_info_length = ((buffer[10] & 0x0F) << 8) | buffer[11]; - if (program_info_length) { + program_info_length = ((buffer[10] & 0x0F) << 8) | buffer[11]; + + if (program_info_length) for (i = 12; i < 12 + program_info_length; i += buffer[i + 1] + 2) switch (buffer[i]) { case 0x09: @@ -399,29 +547,17 @@ bool CPmt::parse_pmt(CZapitChannel * const channel) DBG("decriptor_tag: %02x\n", buffer[i]); break; } - } /* pmt */ - unsigned short section_length = ((buffer[1] & 0x0F) << 8) + buffer[2]; for (i = 12 + program_info_length; i < section_length - 1; i += ES_info_length + 5) - ES_info_length = ParseES(buffer + i, channel, caPmt); - - casys_map_t camap; - MakeCAMap(camap); - channel->scrambled = !camap.empty(); + ES_info_length = parse_ES_info(buffer + i, channel, caPmt); if(CServiceScan::getInstance()->Scanning()) { channel->setCaPmt(NULL); channel->setRawPmt(NULL); delete caPmt; } else { -#if 0 - MakeCAMap(channel->camap); - channel->scrambled = !channel->camap.empty(); -#endif - channel->camap = camap; channel->setCaPmt(caPmt); - int pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] + 3; unsigned char * p = new unsigned char[pmtlen]; memmove(p, buffer, pmtlen); channel->setRawPmt(p, pmtlen); @@ -437,19 +573,90 @@ bool CPmt::parse_pmt(CZapitChannel * const channel) #endif channel->setPidsFlag(); - return true; + return 0; } -bool CPmt::haveCaSys(int pmtpid, int service_id ) +int scan_parse_pmt(int pmtpid, int service_id ) { - if(!Read(pmtpid, service_id)) - return false; + if((pmtpid < 1 ) || (curpmtpid == pmtpid && service_id != curservice_id)) + return -1; + if(curpmtpid == pmtpid && service_id == curservice_id){ + for(int i=0;i<11;i++){ + if(pmt_caids[0][i] > 0) + return 1; + } + return 0; + } + + int pmtlen; + int ia, dpmtlen, pos; + unsigned char descriptor_length=0; + const short pmt_size = 1024; + + unsigned char buffer[pmt_size]; + + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + + cDemux * dmx = new cDemux(); + dmx->Open(DMX_PSI_CHANNEL); + + memset(filter, 0x00, DMX_FILTER_SIZE); + memset(mask, 0x00, DMX_FILTER_SIZE); + + filter[0] = 0x02; /* table_id */ + filter[1] = service_id >> 8; + filter[2] = service_id; + filter[3] = 0x01; /* current_next_indicator */ + filter[4] = 0x00; /* section_number */ + mask[0] = 0xFF; + mask[1] = 0xFF; + mask[2] = 0xFF; + mask[3] = 0x01; + mask[4] = 0xFF; + + if ((dmx->sectionFilter(pmtpid, filter, mask, 5) < 0) || (dmx->Read(buffer, pmt_size) < 0)) { + delete dmx; + return -1; + } + delete dmx; + pmtlen= ((buffer[1]&0xf)<<8) + buffer[2] +3; + + dpmtlen=0; + pos=10; + if(service_id == ((buffer[3] << 8) | buffer[4]) ){ + while(pos+20) { + switch(buffer[ia+2]) { + case 0x06: + case 0x17: + case 0x01: + case 0x05: + case 0x18: + case 0x0B: + case 0x0D: + case 0x09: + case 0x26: + case 0x4a: + case 0x0E: + return 1; + } //switch + } // if + } // for + pos+=dpmtlen+5; + } // while + return 0; + } + return -1; - casys_map_t camap; - MakeCAMap(camap); -printf("CPmt::haveCaSys: sid %04x camap.size %d\n", service_id, camap.size()); - return !camap.empty(); } +#ifndef DMX_SET_NEGFILTER_MASK + #define DMX_SET_NEGFILTER_MASK _IOW('o',48,uint8_t *) +#endif cDemux * pmtDemux; @@ -482,7 +689,7 @@ int pmt_set_update_filter(CZapitChannel * const channel, int * fd) mask[4] = 0xFF; printf("[pmt] set update filter, sid 0x%x pid 0x%x version %x\n", channel->getServiceId(), channel->getPmtPid(), channel->getCaPmt()->version_number); -#if 0 //HAVE_COOL_HARDWARE +#if HAVE_COOL_HARDWARE filter[3] = (((channel->getCaPmt()->version_number + 1) & 0x01) << 1) | 0x01; mask[3] = (0x01 << 1) | 0x01; pmtDemux->sectionFilter(channel->getPmtPid(), filter, mask, 5); From c9bcd79ac0fdcabacc8eb1f348c68ff9c528b029 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 25 Jan 2012 17:34:28 +0400 Subject: [PATCH 076/737] cam: restore code from master --- src/zapit/include/zapit/cam.h | 2 -- src/zapit/src/cam.cpp | 14 +++++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/zapit/include/zapit/cam.h b/src/zapit/include/zapit/cam.h index ebfcf5d7c..3d8c8b735 100644 --- a/src/zapit/include/zapit/cam.h +++ b/src/zapit/include/zapit/cam.h @@ -46,7 +46,6 @@ class CCam : public CBasicClient virtual unsigned char getVersion(void) const; virtual const char *getSocketName(void) const; int camask, demuxes[3]; - int source_demux; public: CCam(); @@ -54,7 +53,6 @@ class CCam : public CBasicClient bool setCaPmt(CCaPmt * const caPmt, int _demux = 0, int _camask = 1, bool update = false); int getCaMask(void) { return camask; }; int makeMask(int demux, bool add); - int getSource() { return source_demux; }; }; typedef std::map cammap_t; diff --git a/src/zapit/src/cam.cpp b/src/zapit/src/cam.cpp index d66212b3b..99b42ee28 100644 --- a/src/zapit/src/cam.cpp +++ b/src/zapit/src/cam.cpp @@ -33,7 +33,6 @@ CCam::CCam() { camask = 0; demuxes[0] = demuxes[1] = demuxes[2] = 0; - source_demux = -1; } unsigned char CCam::getVersion(void) const @@ -73,7 +72,6 @@ bool CCam::sendMessage(const char * const data, const size_t length, bool update bool CCam::setCaPmt(CCaPmt * const caPmt, int _demux, int _camask, bool update) { camask = _camask; - source_demux = _demux; printf("CCam::setCaPmt cam %x source %d camask %d update %s\n", (int) this, _demux, camask, update ? "yes" : "no" ); if(camask == 0) { @@ -142,7 +140,7 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start printf("CCamManager: channel %llx not found\n", channel_id); return false; } -printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", force_update); + mutex.lock(); if(channel->getCaPmt() == NULL) { printf("CCamManager: channel %llx dont have caPmt\n", channel_id); @@ -150,6 +148,8 @@ printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, ch return false; } + sat_iterator_t sit = satellitePositions.find(channel->getSatellitePosition()); + cammap_iterator_t it = channel_map.find(channel_id); if(it != channel_map.end()) { cam = it->second; @@ -167,8 +167,8 @@ printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, ch demux = LIVE_DEMUX; break; case RECORD: - source = channel->getRecordDemux(); //DEMUX_SOURCE_0;//FIXME - demux = channel->getRecordDemux(); //RECORD_DEMUX;//FIXME + source = DEMUX_SOURCE_0; + demux = RECORD_DEMUX;//FIXME break; case STREAM: source = DEMUX_SOURCE_0; @@ -182,10 +182,6 @@ printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, ch else newmask = cam->makeMask(demux, start); - if(cam->getSource() > 0) - source = cam->getSource(); - -printf("CCam::SetMode: source %d old mask %d new mask %d force update %s\n", source, oldmask, newmask, force_update ? "yes" : "no"); if((oldmask != newmask) || force_update) cam->setCaPmt(channel->getCaPmt(), source, newmask, true); From 87e06ca3fb83e56ce4efb68e5feceace7efedb67 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 25 Jan 2012 17:47:53 +0400 Subject: [PATCH 077/737] ci: restore code from master --- src/zapit/src/ci.cpp | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/zapit/src/ci.cpp b/src/zapit/src/ci.cpp index 677f576ba..b71e1e649 100644 --- a/src/zapit/src/ci.cpp +++ b/src/zapit/src/ci.cpp @@ -22,7 +22,7 @@ #include #include -#include +extern int curpmtpid; /* * conditional access descriptors */ @@ -51,6 +51,7 @@ unsigned int CCaDescriptor::writeToBuffer(unsigned char * const buffer) // retur return descriptor_length + 2; } + /* * generic table containing conditional access descriptors */ @@ -88,6 +89,7 @@ CCaTable::~CCaTable(void) delete ca_descriptor[i]; } + /* * elementary stream information */ @@ -109,30 +111,10 @@ unsigned int CEsInfo::writeToBuffer(unsigned char * const buffer) // returns num //return 3 + CCaTable::writeToBuffer(&(buffer[3])); } + /* * contitional access program map table */ - -CCaPmt::CCaPmt() -{ - ca_pmt_list_management = 0; - program_number = 0; - reserved1 = 0; - version_number = 0; - current_next_indicator = 0; - ca_pmt_pid = 0; -} - -CCaPmt::CCaPmt(const unsigned char * const buffer) -{ - program_number = (buffer[3] << 8) + buffer[4]; - reserved1 = buffer[5] >> 6; - version_number = (buffer[5] >> 1) & 0x1F; - current_next_indicator = buffer[5] & 0x01; - reserved2 = buffer[10] >> 4; - ca_pmt_pid = 0; -} - CCaPmt::~CCaPmt(void) { for (unsigned int i = 0; i < es_info.size(); i++) @@ -171,8 +153,8 @@ unsigned int CCaPmt::writeToBuffer(unsigned char * const buffer, int demux, int buffer[27] = 0x84; // pmt pid buffer[28] = 0x02; - buffer[29] = (ca_pmt_pid >> 8) & 0xFF; - buffer[30] = ca_pmt_pid & 0xFF; // 30 + buffer[29] = (curpmtpid >> 8) & 0xFF; + buffer[30] = curpmtpid & 0xFF; // 30 int lenpos=10; int len=19; From 4e97f0aa1e7443be46691dabe37ae195f83fa56a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 25 Jan 2012 17:49:23 +0400 Subject: [PATCH 078/737] channel: remove CCaPmt --- src/zapit/include/zapit/channel.h | 12 +++++++----- src/zapit/src/channel.cpp | 6 ++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/zapit/include/zapit/channel.h b/src/zapit/include/zapit/channel.h index 46e4bd6ac..4f6f0acbe 100644 --- a/src/zapit/include/zapit/channel.h +++ b/src/zapit/include/zapit/channel.h @@ -32,7 +32,6 @@ #include /* zapit */ -#include "ci.h" #include "types.h" //#include @@ -149,9 +148,10 @@ class CZapitChannel unsigned char serviceType; /* the conditional access program map table of this channel */ - CCaPmt * caPmt; + //CCaPmt * caPmt; unsigned char * rawPmt; int pmtLen; + uint8_t pmt_version; /* from neutrino CChannel class */ uint64_t last_unlocked_EPGid; @@ -206,8 +206,9 @@ class CZapitChannel unsigned short getPrivatePid(void) { return privatePid; } unsigned short getPreAudioPid(void) { return audioPid; } bool getPidsFlag(void) { return pidsFlag; } - CCaPmt * getCaPmt(void) { return caPmt; } + //CCaPmt * getCaPmt(void) { return caPmt; } unsigned char * getRawPmt(int &len) { len = pmtLen; return rawPmt; }; + uint8_t getPmtVersion(void) { return pmt_version; }; CZapitAudioChannel * getAudioChannel(unsigned char index = 0xFF); unsigned short getAudioPid(unsigned char index = 0xFF); @@ -222,12 +223,13 @@ class CZapitChannel void setPcrPid(unsigned short pPcrPid) { pcrPid = pPcrPid; } void setPmtPid(unsigned short pPmtPid) { pmtPid = pPmtPid; } void setTeletextPid(unsigned short pTeletextPid) { teletextPid = pTeletextPid; } - void setTeletextLang(char * lang) { ttx_language_code = lang; }; + void setTeletextLang(std::string lang) { ttx_language_code = lang; }; void setVideoPid(unsigned short pVideoPid) { videoPid = pVideoPid; } void setAudioPid(unsigned short pAudioPid) { audioPid = pAudioPid; } void setPrivatePid(unsigned short pPrivatePid) { privatePid = pPrivatePid; } void setPidsFlag(void) { pidsFlag = true; } - void setCaPmt(CCaPmt *pCaPmt); + //void setCaPmt(CCaPmt *pCaPmt); + void setPmtVersion(uint8_t version) { pmt_version = version; } void setRawPmt(unsigned char * pmt, int len = 0); /* cleanup methods */ void resetPids(void); diff --git a/src/zapit/src/channel.cpp b/src/zapit/src/channel.cpp index 5213104f5..96419c715 100644 --- a/src/zapit/src/channel.cpp +++ b/src/zapit/src/channel.cpp @@ -52,7 +52,7 @@ CZapitChannel::CZapitChannel(const std::string & p_name, t_channel_id p_channel_ void CZapitChannel::Init() { - caPmt = NULL; + //caPmt = NULL; rawPmt = NULL; type = 0; number = 0; @@ -72,7 +72,7 @@ CZapitChannel::~CZapitChannel(void) { //printf("DEL CHANNEL %s %x subs %d\n", name.c_str(), (int) this, getSubtitleCount()); resetPids(); - setCaPmt(NULL); + //setCaPmt(NULL); setRawPmt(NULL); camap.clear(); } @@ -280,12 +280,14 @@ int CZapitChannel::getChannelSubIndex(void) return currentSub < getSubtitleCount() ? currentSub : -1; } +#if 0 void CZapitChannel::setCaPmt(CCaPmt *pCaPmt) { if(caPmt) delete caPmt; caPmt = pCaPmt; } +#endif void CZapitChannel::setRawPmt(unsigned char * pmt, int len) { From 16f8d7d4064bb5320b3a56889c573cffa849a390 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 25 Jan 2012 17:51:19 +0400 Subject: [PATCH 079/737] zapit: remove getCaPmt usage --- src/zapit/src/zapit.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/zapit/src/zapit.cpp b/src/zapit/src/zapit.cpp index 16ae05ed4..700e24af0 100644 --- a/src/zapit/src/zapit.cpp +++ b/src/zapit/src/zapit.cpp @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include #include #include @@ -452,7 +452,7 @@ bool CZapit::ParsePatPmt(CZapitChannel * channel) printf("[zapit] pat parsing failed\n"); return false; } - if (!pmt.parse_pmt(channel)) { + if (!pmt.Parse(channel)) { printf("[zapit] pmt parsing failed\n"); return false; } @@ -528,7 +528,7 @@ bool CZapit::ZapIt(const t_channel_id channel_id, bool forupdate, bool startplay if (failed) return false; - current_channel->getCaPmt()->ca_pmt_list_management = transponder_change ? 0x03 : 0x04; + //current_channel->getCaPmt()->ca_pmt_list_management = transponder_change ? 0x03 : 0x04; RestoreChannelPids(current_channel); @@ -841,7 +841,8 @@ bool CZapit::ParseCommand(CBasicMessage::Header &rmsg, int connfd) msgCurrentServiceInfo.apid = current_channel->getAudioPid(); msgCurrentServiceInfo.vtxtpid = current_channel->getTeletextPid(); msgCurrentServiceInfo.pmtpid = current_channel->getPmtPid(); - msgCurrentServiceInfo.pmt_version = (current_channel->getCaPmt() != NULL) ? current_channel->getCaPmt()->version_number : 0xff; + //msgCurrentServiceInfo.pmt_version = (current_channel->getCaPmt() != NULL) ? current_channel->getCaPmt()->version_number : 0xff; + msgCurrentServiceInfo.pmt_version = current_channel->getPmtVersion(); msgCurrentServiceInfo.pcrpid = current_channel->getPcrPid(); msgCurrentServiceInfo.tsfrequency = live_fe->getFrequency(); msgCurrentServiceInfo.rate = live_fe->getRate(); @@ -2099,7 +2100,7 @@ void CZapit::run() t_channel_id channel_id = current_channel->getChannelID(); int vpid = current_channel->getVideoPid(); CPmt pmt; - pmt.parse_pmt(current_channel); + pmt.Parse(current_channel); if(vpid != current_channel->getVideoPid()) { ZapIt(current_channel->getChannelID(), true); } else { From b122e5ff21a8c946b811ab5c218093b18b6a9b8b Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 25 Jan 2012 17:52:11 +0400 Subject: [PATCH 080/737] CCam: new code on using libdvbsi++ --- src/zapit/include/zapit/capmt.h | 85 +++++++++++ src/zapit/src/capmt.cpp | 245 ++++++++++++++++++++++++++++++++ 2 files changed, 330 insertions(+) create mode 100644 src/zapit/include/zapit/capmt.h create mode 100644 src/zapit/src/capmt.cpp diff --git a/src/zapit/include/zapit/capmt.h b/src/zapit/include/zapit/capmt.h new file mode 100644 index 000000000..c001a8869 --- /dev/null +++ b/src/zapit/include/zapit/capmt.h @@ -0,0 +1,85 @@ +/* + * $Id: cam.h,v 1.25 2003/02/09 19:22:08 thegoodguy Exp $ + * + * (C) 2002-2003 Andreas Oberritter , + * thegoodguy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __capmt_h__ +#define __capmt_h__ + +#include +#include "types.h" +#include +#include + +#define DEMUX_DECODE_0 1 +#define DEMUX_DECODE_1 2 +#define DEMUX_DECODE_2 4 + +#define DEMUX_SOURCE_0 0 +#define DEMUX_SOURCE_1 1 +#define DEMUX_SOURCE_2 2 + +#define LIVE_DEMUX 0 +#define STREAM_DEMUX 1 +#define RECORD_DEMUX 2 + +class CCam : public CBasicClient +{ + private: + virtual unsigned char getVersion(void) const; + virtual const char *getSocketName(void) const; + int camask, demuxes[3]; + int source_demux; + + public: + CCam(); + bool sendMessage(const char * const data, const size_t length, bool update = false); + bool setCaPmt(CZapitChannel * channel, int _demux = 0, int _camask = 1, bool update = false); + int getCaMask(void) { return camask; }; + int makeMask(int demux, bool add); + int getSource() { return source_demux; }; +}; + +typedef std::map cammap_t; +typedef cammap_t::iterator cammap_iterator_t; + +class CCamManager +{ + public: + enum runmode { + PLAY, + RECORD, + STREAM + }; + private: + cammap_t channel_map; + OpenThreads::Mutex mutex; + static CCamManager * manager; + bool SetMode(t_channel_id id, enum runmode mode, bool enable, bool force_update = false); + + public: + CCamManager(); + ~CCamManager(); + static CCamManager * getInstance(void); + bool Start(t_channel_id id, enum runmode mode, bool force_update = false) { return SetMode(id, mode, true, force_update); }; + bool Stop(t_channel_id id, enum runmode mode) { return SetMode(id, mode, false); }; + +}; +#endif /* __capmt_h__ */ diff --git a/src/zapit/src/capmt.cpp b/src/zapit/src/capmt.cpp new file mode 100644 index 000000000..a994d9402 --- /dev/null +++ b/src/zapit/src/capmt.cpp @@ -0,0 +1,245 @@ +/* + * $Id: cam.cpp,v 1.33 2004/04/04 20:20:45 obi Exp $ + * + * (C) 2002 by Andreas Oberritter , + * thegoodguy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +/* zapit */ +#include +#include /* CAMD_UDS_NAME */ +#include + +#include +#include + +#define DEBUG_CAPMT + +CCam::CCam() +{ + camask = 0; + demuxes[0] = demuxes[1] = demuxes[2] = 0; + source_demux = -1; +} + +unsigned char CCam::getVersion(void) const +{ + return 0x9F; +} + +const char *CCam::getSocketName(void) const +{ + return CAMD_UDS_NAME; +} + +bool CCam::sendMessage(const char * const data, const size_t length, bool update) +{ + /* send_data return false without trying, if no opened connection */ + if(update) { + if(!send_data(data, length)) { + if (!open_connection()) + return false; + return send_data(data, length); + } + return true; + } + + close_connection(); + + if(!data || !length) { + camask = 1; + return false; + } + if (!open_connection()) + return false; + + return send_data(data, length); +} + +bool CCam::setCaPmt(CZapitChannel * channel, int _demux, int _camask, bool update) +{ + int len; + unsigned char * buffer = channel->getRawPmt(len); + + camask = _camask; + source_demux = _demux; + + printf("CCam::setCaPmt cam %x source %d camask %d update %s\n", (int) this, _demux, camask, update ? "yes" : "no" ); + + if(camask == 0) { + close_connection(); + return true; + } + if(!buffer) + return false; + + ProgramMapSection pmt(buffer); + CaProgramMapSection capmt(&pmt, 0x03, 0x01); + + uint8_t tmp[10]; + tmp[0] = 0x84; + tmp[1] = 0x02; + tmp[2] = channel->getPmtPid() >> 8; + tmp[3] = channel->getPmtPid() & 0xFF; + capmt.injectDescriptor(tmp, false); + + tmp[0] = 0x82; + tmp[1] = 0x02; + tmp[2] = camask; + tmp[3] = source_demux; + capmt.injectDescriptor(tmp, false); + + memset(tmp, 0, sizeof(tmp)); + tmp[0] = 0x81; + tmp[1] = 0x08; + tmp[2] = channel->getSatellitePosition() >> 8; + tmp[3] = channel->getSatellitePosition() & 0xFF; + tmp[4] = channel->getFreqId() >> 8; + tmp[5] = channel->getFreqId() & 0xFF; + tmp[6] = channel->getTransportStreamId() >> 8; + tmp[7] = channel->getTransportStreamId() & 0xFF; + tmp[8] = channel->getOriginalNetworkId() >> 8; + tmp[9] = channel->getOriginalNetworkId() & 0xFF; + + capmt.injectDescriptor(tmp, false); + + unsigned char cabuf[2048]; + int calen = capmt.writeToBuffer(cabuf); +#ifdef DEBUG_CAPMT + printf("CAPMT: "); + for(int i = 0; i < calen; i++) + printf("%02X ", cabuf[i]); + printf("\n"); +#endif + return sendMessage((char *)cabuf, calen, update); +} + +int CCam::makeMask(int demux, bool add) +{ + int mask = 0; + + if(add) + demuxes[demux]++; + else if(demuxes[demux] > 0) + demuxes[demux]--; + + for(int i = 0; i < 3; i++) { + if(demuxes[i] > 0) + mask |= 1 << i; + } + printf("CCam::MakeMask: demuxes %d:%d:%d old mask %d new mask %d\n", demuxes[0], demuxes[1], demuxes[2], camask, mask); + return mask; +} + +CCamManager * CCamManager::manager = NULL; + +CCamManager::CCamManager() +{ + channel_map.clear(); +} + +CCamManager::~CCamManager() +{ + for(cammap_iterator_t it = channel_map.begin(); it != channel_map.end(); it++) + delete it->second; + channel_map.clear(); +} + +CCamManager * CCamManager::getInstance(void) +{ + if(manager == NULL) + manager = new CCamManager(); + + return manager; +} + +bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start, bool force_update) +{ + CCam * cam; + int oldmask, newmask; + int demux = DEMUX_SOURCE_0; + int source = DEMUX_SOURCE_0; + + CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id); + + if(channel == NULL) { + printf("CCamManager: channel %llx not found\n", channel_id); + return false; + } +printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", force_update); + mutex.lock(); +#if 0 + if(channel->getCaPmt() == NULL) { + printf("CCamManager: channel %llx dont have caPmt\n", channel_id); + mutex.unlock(); + return false; + } +#endif + cammap_iterator_t it = channel_map.find(channel_id); + if(it != channel_map.end()) { + cam = it->second; + } else if(start) { + cam = new CCam(); + channel_map.insert(std::pair(channel_id, cam)); + } else { + mutex.unlock(); + return false; + } + + switch(mode) { + case PLAY: + source = DEMUX_SOURCE_0; + demux = LIVE_DEMUX; + break; + case RECORD: + source = channel->getRecordDemux(); //DEMUX_SOURCE_0;//FIXME + demux = channel->getRecordDemux(); //RECORD_DEMUX;//FIXME + break; + case STREAM: + source = DEMUX_SOURCE_0; + demux = STREAM_DEMUX;//FIXME + break; + } + + oldmask = cam->getCaMask(); + if(force_update) + newmask = oldmask; + else + newmask = cam->makeMask(demux, start); + + if(cam->getSource() > 0) + source = cam->getSource(); + +printf("CCam::SetMode: source %d old mask %d new mask %d force update %s\n", source, oldmask, newmask, force_update ? "yes" : "no"); + if((oldmask != newmask) || force_update) { + cam->setCaPmt(channel, source, newmask, true); + } + + if(newmask == 0) { + /* FIXME: back to live channel from playback dont parse pmt and call setCaPmt + * (see CMD_SB_LOCK / UNLOCK PLAYBACK */ + //channel->setCaPmt(NULL); + //channel->setRawPmt(NULL);//FIXME + channel_map.erase(channel_id); + delete cam; + } + mutex.unlock(); + + return true; +} From 6adf63899faff87f6e03a1bd4eb06081fd736488 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 16:02:36 +0400 Subject: [PATCH 081/737] getservices.h: remove ci.h include --- src/zapit/include/zapit/getservices.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/zapit/include/zapit/getservices.h b/src/zapit/include/zapit/getservices.h index e03451128..503d0f2d2 100644 --- a/src/zapit/include/zapit/getservices.h +++ b/src/zapit/include/zapit/getservices.h @@ -26,7 +26,6 @@ #include -#include #include #include #include From 7df6b727b1ab7981957ef8a097a3ea237408ba8a Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 16:32:32 +0400 Subject: [PATCH 082/737] pmt: new code based on libdvbsi++ --- src/zapit/include/zapit/scanpmt.h | 49 ++++ src/zapit/src/scanpmt.cpp | 395 ++++++++++++++++++++++++++++++ 2 files changed, 444 insertions(+) create mode 100644 src/zapit/include/zapit/scanpmt.h create mode 100644 src/zapit/src/scanpmt.cpp diff --git a/src/zapit/include/zapit/scanpmt.h b/src/zapit/include/zapit/scanpmt.h new file mode 100644 index 000000000..192e8a884 --- /dev/null +++ b/src/zapit/include/zapit/scanpmt.h @@ -0,0 +1,49 @@ +/* + * $Id: pmt.h,v 1.10 2003/08/15 23:34:09 obi Exp $ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __zapit_scan_pmt_h__ +#define __zapit_scan_pmt_h__ + +#include "channel.h" +#include + +int pmt_set_update_filter(CZapitChannel * const channel, int * fd); +int pmt_stop_update_filter(int * fd); + +#define PMT_SECTION_SIZE 1024 +class CPmt +{ + private: + int dmxnum; + unsigned char buffer[PMT_SECTION_SIZE]; + + bool Read(unsigned short pid, unsigned short sid); + void MakeCAMap(casys_map_t &camap); + bool ParseEsInfo(ElementaryStreamInfo *esinfo, CZapitChannel * const channel); + public: + CPmt(int dnum = 0); + ~CPmt(); + + bool Parse(CZapitChannel * const channel); + bool haveCaSys(int pmtpid, int service_id); +}; + +#endif /* __zapit_scan_pmt_h__ */ diff --git a/src/zapit/src/scanpmt.cpp b/src/zapit/src/scanpmt.cpp new file mode 100644 index 000000000..5e2185c9e --- /dev/null +++ b/src/zapit/src/scanpmt.cpp @@ -0,0 +1,395 @@ +/* + * $Id: pmt.cpp,v 1.40 2004/04/04 20:46:17 obi Exp $ + * + * (C) 2002 by Andreas Oberritter + * (C) 2002 by Frank Bormann + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include + +/* zapit */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_PMT +//#define DEBUG_PMT_UNUSED + +CPmt::CPmt(int dnum) +{ + dmxnum = dnum; +} + +CPmt::~CPmt() +{ +} + +bool CPmt::Read(unsigned short pid, unsigned short sid) +{ + bool ret = true; + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + + cDemux * dmx = new cDemux(dmxnum); + dmx->Open(DMX_PSI_CHANNEL); + + memset(filter, 0x00, DMX_FILTER_SIZE); + memset(mask, 0x00, DMX_FILTER_SIZE); + + filter[0] = 0x02; /* table_id */ + filter[1] = sid >> 8; + filter[2] = sid; + filter[3] = 0x01; /* current_next_indicator */ + filter[4] = 0x00; /* section_number */ + mask[0] = 0xFF; + mask[1] = 0xFF; + mask[2] = 0xFF; + mask[3] = 0x01; + mask[4] = 0xFF; + if ((dmx->sectionFilter(pid, filter, mask, 5) < 0) || (dmx->Read(buffer, PMT_SECTION_SIZE) < 0)) { + printf("CPmt::Read: pid %x failed\n", pid); + ret = false; + } + delete dmx; + return ret; +} + +bool CPmt::Parse(CZapitChannel * const channel) +{ + printf("[zapit] parsing pmt pid 0x%X (%s)\n", channel->getPmtPid(), channel->getName().c_str()); + + if (channel->getPmtPid() == 0) + return false; + + if(!Read(channel->getPmtPid(), channel->getServiceId())) + return false; + + ProgramMapSection pmt(buffer); + + printf("[pmt] pcr pid: old 0x%x new 0x%x\n", channel->getPcrPid(), pmt.getPcrPid()); + + channel->resetPids(); + + channel->setPmtVersion(pmt.getVersionNumber()); + channel->setPcrPid(pmt.getPcrPid()); + + const ElementaryStreamInfoList * eslist = pmt.getEsInfo(); + ElementaryStreamInfoConstIterator it; + for (it = eslist->begin(); it != eslist->end(); ++it) { + ElementaryStreamInfo *esinfo = *it; + ParseEsInfo(esinfo, channel); + } + + casys_map_t camap; + MakeCAMap(camap); + channel->scrambled = !camap.empty(); + + if(CServiceScan::getInstance()->Scanning()) { + channel->setRawPmt(NULL); + } else { + channel->camap = camap; + int pmtlen= pmt.getSectionLength() + 3; + unsigned char * p = new unsigned char[pmtlen]; + memmove(p, buffer, pmtlen); + channel->setRawPmt(p, pmtlen); + } + + channel->setPidsFlag(); + return true; +} + +bool CPmt::ParseEsInfo(ElementaryStreamInfo *esinfo, CZapitChannel * const channel) +{ + std::string description = ""; + unsigned char componentTag = 0xFF; + CZapitAudioChannel::ZapitAudioChannelType audio_type = CZapitAudioChannel::UNKNOWN; + + uint8_t stream_type = esinfo->getType(); + + bool audio = false; + + const DescriptorList * dlist = esinfo->getDescriptors(); + DescriptorConstIterator dit; + for (dit = dlist->begin(); dit != dlist->end(); ++dit) { + Descriptor * d = *dit; + switch (d->getTag()) { + case REGISTRATION_DESCRIPTOR: + { + RegistrationDescriptor *sd = (RegistrationDescriptor*) d; + switch (sd->getFormatIdentifier()) { + case 0x44545331 ... 0x44545333: + audio_type = CZapitAudioChannel::DTS; + break; + case 0x41432d33: + audio_type = CZapitAudioChannel::AC3; + break; + default: +#ifdef DEBUG_PMT + printf("PMT: REGISTRATION_DESCRIPTOR: %x\n", sd->getFormatIdentifier()); +#endif + break; + } + } + break; + case ISO_639_LANGUAGE_DESCRIPTOR: + { + Iso639LanguageDescriptor * sd = (Iso639LanguageDescriptor*) d; + const Iso639LanguageList *languages = sd->getIso639Languages(); + Iso639LanguageConstIterator it; + for (it = languages->begin(); it != languages->end(); ++it) { + description = (*it)->getIso639LanguageCode(); + break; + } + } + break; + case STREAM_IDENTIFIER_DESCRIPTOR: + { + StreamIdentifierDescriptor *sd = (StreamIdentifierDescriptor*) d; + componentTag = sd->getComponentTag(); + } + break; + case TELETEXT_DESCRIPTOR: + { + TeletextDescriptor *td = (TeletextDescriptor*)d; + const VbiTeletextList *vbilist = td->getVbiTeletexts(); + VbiTeletextConstIterator it; + printf("[pmt] teletext pid %04x\n", esinfo->getPid()); + for (it = vbilist->begin(); it != vbilist->end(); ++it) { + VbiTeletext * vbi = *it; + + std::string lang = vbi->getIso639LanguageCode(); + uint8_t page = vbi->getTeletextPageNumber(); + uint8_t magazine = vbi->getTeletextMagazineNumber(); + printf("[pmt] teletext type %d mag %d page %d lang [%s]\n", + vbi->getTeletextType(), magazine, page, lang.c_str()); + if (vbi->getTeletextType() == 0x01) + channel->setTeletextLang(lang); + else if (vbi->getTeletextType() == 0x02) + channel->addTTXSubtitle(esinfo->getPid(), lang, magazine, page); + else if (vbi->getTeletextType() == 0x05) + channel->addTTXSubtitle(esinfo->getPid(), lang, magazine, page, true); + } + channel->setTeletextPid(esinfo->getPid()); + } + break; + case SUBTITLING_DESCRIPTOR: + if(stream_type == 0x06) { + SubtitlingDescriptor *sd = (SubtitlingDescriptor*) d; + const SubtitlingList *sublist = sd->getSubtitlings(); + SubtitlingConstIterator it; + for (it = sublist->begin(); it != sublist->end(); ++it) { + Subtitling * sub = *it; + + uint16_t composition_page_id = sub->getCompositionPageId(); + uint16_t ancillary_page_id = sub->getAncillaryPageId(); + std::string lang = sub->getIso639LanguageCode(); + + channel->addDVBSubtitle(esinfo->getPid(), lang, sub->getSubtitlingType(), + composition_page_id, ancillary_page_id); + } + } + break; + case AC3_DESCRIPTOR: + audio_type = CZapitAudioChannel::AC3; + break; + case DTS_DESCRIPTOR: + audio_type = CZapitAudioChannel::DTS; + break; + case AAC_DESCRIPTOR: + audio_type = CZapitAudioChannel::AAC; + break; + case 0xC5: /* User Private descriptor - Canal+ Radio */ + if(d->getLength() >= 25) { + uint8_t buf[2 + d->getLength()]; + d->writeToBuffer(buf); + int tsidonid = channel->getTransportStreamId() << 16 | channel->getOriginalNetworkId(); + description = convertDVBUTF8((const char*)&buf[3], 24, 2, tsidonid); + } + break; + case AUDIO_STREAM_DESCRIPTOR: + break; + case VIDEO_STREAM_DESCRIPTOR: + break; + case CA_DESCRIPTOR: + break; + default: + { +#ifdef DEBUG_PMT_UNUSED + printf("PMT: descriptor %02x: ", d->getTag()); + uint8_t len = 2+d->getLength(); + uint8_t buf[len]; + d->writeToBuffer(buf); + for(uint8_t i = 0; i < len; i++) + printf("%02x ", buf[i]); + printf("\n"); +#endif + } + break; + } + } + switch (stream_type) { + case 0x01: + case 0x02: + case 0x1b: // AVC Video Stream (MPEG4 H264) + channel->setVideoPid(esinfo->getPid()); + channel->type = (stream_type == 0x1b); //FIXME + printf("[pmt] vpid %04x stream %d type %d\n", esinfo->getPid(), stream_type, channel->type); + break; + case 0x03: + case 0x04: + audio_type = CZapitAudioChannel::MPEG; + audio = true; + break; + case 0x06: + if(audio_type != CZapitAudioChannel::UNKNOWN) + audio = true; + break; + case 0x0F: // AAC ADTS + case 0x11: // AAC LATM + audio_type = CZapitAudioChannel::AAC; + audio = true; + break; + case 0x81: + audio_type = CZapitAudioChannel::AC3; + audio = true; + break; + default: +#ifdef DEBUG_PMT_UNUSED + printf("PMT: pid %04x stream_type: %02x\n", esinfo->getPid(), stream_type); +#endif + break; + } + if(audio) { + if(description.empty()) { + char str[DESC_MAX_LEN]; + snprintf(str, DESC_MAX_LEN, "Unknown 0x%04x", esinfo->getPid()); + description = str; + } + printf("[pmt] apid %04x stream %02x type %d [%s]\n", esinfo->getPid(), stream_type, + (int) audio_type, description.c_str()); + if(CServiceScan::getInstance()->Scanning()) { + if(channel->getPreAudioPid() == 0) + channel->setAudioPid(esinfo->getPid()); + } else + channel->addAudioChannel(esinfo->getPid(), audio_type, description, componentTag); + } + return true; +} + +void CPmt::MakeCAMap(casys_map_t &camap) +{ + ProgramMapSection pmt(buffer); + CaProgramMapSection capmt(&pmt, 0x03, 0x01); + DescriptorConstIterator dit; + for (dit = capmt.getDescriptors()->begin(); dit != capmt.getDescriptors()->end(); ++dit) { + if ((*dit)->getTag() == CA_DESCRIPTOR ) { + CaDescriptor * d = (CaDescriptor*) *dit; + //printf("%02X: casys %04X capid %04X, ", d->getTag(), d->getCaSystemId(), d->getCaPid()); + camap.insert(d->getCaSystemId()); + } + } +} + +bool CPmt::haveCaSys(int pmtpid, int service_id ) +{ + if(!Read(pmtpid, service_id)) + return false; + + casys_map_t camap; + MakeCAMap(camap); + return !camap.empty(); +} + +cDemux * pmtDemux; + +int pmt_set_update_filter(CZapitChannel * const channel, int * fd) +{ + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; + unsigned char mode[DMX_FILTER_SIZE]; + + if(pmtDemux == NULL) { + pmtDemux = new cDemux(0); + pmtDemux->Open(DMX_PSI_CHANNEL); + } + + if (channel->getPmtPid() == 0) + return -1; + + memset(filter, 0x00, DMX_FILTER_SIZE); + memset(mask, 0x00, DMX_FILTER_SIZE); + memset(mode, 0x00, DMX_FILTER_SIZE); + + filter[0] = 0x02; /* table_id */ + filter[1] = channel->getServiceId() >> 8; + filter[2] = channel->getServiceId(); + filter[4] = 0x00; /* section_number */ + + mask[0] = 0xFF; + mask[1] = 0xFF; + mask[2] = 0xFF; + mask[4] = 0xFF; + +#if 0 //HAVE_COOL_HARDWARE + printf("[pmt] set update filter, sid 0x%x pid 0x%x version %x\n", channel->getServiceId(), channel->getPmtPid(), channel->getCaPmt()->version_number); + filter[3] = (((channel->getCaPmt()->version_number + 1) & 0x01) << 1) | 0x01; + mask[3] = (0x01 << 1) | 0x01; + pmtDemux->sectionFilter(channel->getPmtPid(), filter, mask, 5); +#else + printf("[pmt] set update filter, sid 0x%x pid 0x%x version %x\n", channel->getServiceId(), channel->getPmtPid(), channel->getPmtVersion()); + filter[3] = (channel->getPmtVersion() << 1) | 0x01; + mask[3] = (0x1F << 1) | 0x01; + mode[3] = 0x1F << 1; + pmtDemux->sectionFilter(channel->getPmtPid(), filter, mask, 5, 0, mode); +#endif + + *fd = 1; + return 0; +} + +int pmt_stop_update_filter(int * fd) +{ + printf("[pmt] stop update filter\n"); +#if HAVE_TRIPLEDRAGON + if (pmtDemux) + delete pmtDemux; + /* apparently a close/reopen is needed on TD... */ + pmtDemux = NULL; +#else + if(pmtDemux) + pmtDemux->Stop(); +#endif + + *fd = -1; + return 0; +} From 2667223f57e348ca5e22166487ad4b8604eff8b6 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 16:34:06 +0400 Subject: [PATCH 083/737] zapit Makefile.am: remove ci.cpp, cam.cpp, pmt.cpp, add new files --- src/zapit/src/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/zapit/src/Makefile.am b/src/zapit/src/Makefile.am index 795a55d71..f20bd57d2 100644 --- a/src/zapit/src/Makefile.am +++ b/src/zapit/src/Makefile.am @@ -20,8 +20,8 @@ noinst_LIBRARIES = libzapit.a libzapit_a_SOURCES = \ bouquets.cpp channel.cpp dvbstring.cpp getservices.cpp \ - scan.cpp zapit.cpp cam.cpp ci.cpp frontend.cpp femanager.cpp \ - pat.cpp pmt.cpp fastscan.cpp scansdt.cpp scannit.cpp + scan.cpp zapit.cpp capmt.cpp frontend.cpp femanager.cpp \ + pat.cpp scanpmt.cpp fastscan.cpp scansdt.cpp scannit.cpp bin_PROGRAMS = pzapit sbin_PROGRAMS = udpstreampes From 17ec6c9bc3a51b77939852880c539fbc88155e98 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 16:34:50 +0400 Subject: [PATCH 084/737] scannit.cpp: remove extra debug --- src/zapit/src/scannit.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/zapit/src/scannit.cpp b/src/zapit/src/scannit.cpp index b8162c044..585b6c9aa 100644 --- a/src/zapit/src/scannit.cpp +++ b/src/zapit/src/scannit.cpp @@ -153,22 +153,17 @@ bool CNit::Parse() return false; NetworkInformationSectionIterator sit; -#ifdef DEBUG_NIT - printf("NIT: %d sections\n", sections.size()); -#endif for (sit = sections.begin(); sit != sections.end(); ++sit) { NetworkInformationSection * nit = *sit; const TransportStreamInfoList *tslist = nit->getTsInfo(); -#ifdef DEBUG_NIT - printf("NIT: %d TransportStreamInfos\n", tslist->size()); -#endif + if (CServiceScan::getInstance()->Aborted()) return false; for(TransportStreamInfoConstIterator tit = tslist->begin(); tit != tslist->end(); ++tit) { TransportStreamInfo * tsinfo = *tit; const DescriptorList * dlist = tsinfo->getDescriptors(); -#if 0 //ifdef DEBUG_NIT +#if 0 printf("NIT: tsid %04x onid %04x %d descriptors\n", tsinfo->getTransportStreamId(), tsinfo->getOriginalNetworkId(), dlist->size()); #endif From 8ed6a3153dc24598f15462007dba87a06a678f9f Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 17:26:55 +0400 Subject: [PATCH 085/737] Change license header --- src/zapit/include/zapit/scanpmt.h | 7 +++---- src/zapit/src/scanpmt.cpp | 8 +++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/zapit/include/zapit/scanpmt.h b/src/zapit/include/zapit/scanpmt.h index 192e8a884..42127f29d 100644 --- a/src/zapit/include/zapit/scanpmt.h +++ b/src/zapit/include/zapit/scanpmt.h @@ -1,12 +1,11 @@ /* - * $Id: pmt.h,v 1.10 2003/08/15 23:34:09 obi Exp $ + * Copyright (C) 2011 CoolStream International Ltd * - * (C) 2002-2003 Andreas Oberritter + * License: GPLv2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/src/zapit/src/scanpmt.cpp b/src/zapit/src/scanpmt.cpp index 5e2185c9e..9ca88f424 100644 --- a/src/zapit/src/scanpmt.cpp +++ b/src/zapit/src/scanpmt.cpp @@ -1,13 +1,11 @@ /* - * $Id: pmt.cpp,v 1.40 2004/04/04 20:46:17 obi Exp $ + * Copyright (C) 2011 CoolStream International Ltd * - * (C) 2002 by Andreas Oberritter - * (C) 2002 by Frank Bormann + * License: GPLv2 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of From fe518bf88317340b7e93637a02156c9b7a94041f Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 17:35:10 +0400 Subject: [PATCH 086/737] add sample providermap.xml --- data/Makefile.am | 2 +- data/providermap.xml | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 data/providermap.xml diff --git a/data/Makefile.am b/data/Makefile.am index f5f5e5cf1..7519719cd 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -5,4 +5,4 @@ SUBDIRS += lcd endif configdir = $(CONFIGDIR) -config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf +config_DATA = cables.xml satellites.xml encoding.conf tobackup.conf providermap.xml diff --git a/data/providermap.xml b/data/providermap.xml new file mode 100644 index 000000000..ebe2b57b3 --- /dev/null +++ b/data/providermap.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From 5b184dfcd91ddf64b9b60753ac020189158fb375 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 19:18:07 +0400 Subject: [PATCH 087/737] sdt: changes in debug --- src/zapit/src/scansdt.cpp | 43 ++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/zapit/src/scansdt.cpp b/src/zapit/src/scansdt.cpp index c8bf6d4e0..496ab9ef9 100644 --- a/src/zapit/src/scansdt.cpp +++ b/src/zapit/src/scansdt.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -42,6 +42,8 @@ extern CZapitClient::scanType scanType; // FIXME int scan_fta_flag; // FIXME #define DEBUG_SDT +//#define DEBUG_SDT_UNUSED +//#define DEBUG_SDT_SERVICE CSdt::CSdt(t_satellite_position spos, freq_id_t frq, bool curr, int dnum) { @@ -102,7 +104,7 @@ bool CSdt::Read() } do { _repeat: - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + if(current && current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) break; if (dmx->Read(buffer, SDT_SECTION_SIZE) < 0) { @@ -137,7 +139,7 @@ _repeat: goto _repeat; } delete dmx; - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + if(current && current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) return false; return true; } @@ -181,7 +183,7 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) break; case CA_IDENTIFIER_DESCRIPTOR: { -#ifdef DEBUG_SDT +#if 0 //ifdef DEBUG_SDT CaIdentifierDescriptor * cad = (CaIdentifierDescriptor *) d; const CaSystemIdList * calist = cad->getCaSystemIds(); printf("CASYS: "); @@ -193,7 +195,7 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) break; default: { -#ifdef DEBUG_SDT +#ifdef DEBUG_SDT_UNUSED printf("SDT: sid %x descriptor %02x: ", service->getServiceId(), d->getTag()); uint8_t len = 2+d->getLength(); uint8_t buf[len]; @@ -206,13 +208,13 @@ bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid) break; } } - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + if(current && current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) break; } } tsid = transport_stream_id; onid = original_network_id; - if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) + if(current && current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid()) return false; return true; @@ -242,9 +244,9 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto std::string providerName = stringDVBUTF8(sd->getServiceProviderName(), 0, tsidonid); std::string serviceName = stringDVBUTF8(sd->getServiceName(), 0, tsidonid); -#ifdef DEBUG_SDT - printf("SDT: sid %04x type %x provider [%s] service [%s]\n", service_id, sd->getServiceType(), - providerName.c_str(), serviceName.c_str()); +#ifdef DEBUG_SDT_SERVICE + printf("SDT: sid %04x type %x provider [%s] service [%s] scrambled %d\n", service_id, sd->getServiceType(), + providerName.c_str(), serviceName.c_str(), free_ca); #endif if (!CheckScanType(service_type)) return false; @@ -273,7 +275,20 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto CPmt pmt; if(pmt.haveCaSys(channel->getPmtPid(), channel->getServiceId())) channel->scrambled = true; + else + channel->scrambled = false; +#ifdef DEBUG_SDT_SERVICE + if(free_ca != channel->scrambled) + printf("SDT: service update: [%s] free_ca %d scrambled %d\n", + serviceName.c_str(), free_ca, channel->scrambled); +#endif } +#if 0 //FIXME updates scrambled flag without reloading, but prevent changes found if only scrambled different + bool scrambled = channel->scrambled; + channel = CServiceManager::getInstance()->FindChannel(channel_id); + if(channel) + channel->scrambled = scrambled; +#endif return true; } @@ -307,7 +322,12 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto if (CZapit::getInstance()->scanPids()) { if(pat.Parse(channel)) { CPmt pmt; - pmt.parse_pmt(channel); + pmt.Parse(channel); +#ifdef DEBUG_SDT_SERVICE + if(free_ca != channel->scrambled) + printf("SDT: provider [%s] service [%s] free_ca %d scrambled %d camap.size %d\n", providerName.c_str(), + serviceName.c_str(), free_ca, channel->scrambled, channel->camap.size()); +#endif } } if(service_type == ST_DIGITAL_TELEVISION_SERVICE && !channel->scrambled) { @@ -327,7 +347,6 @@ CZapitChannel * CSdt::CheckChannelId(t_service_id service_id) CZapitChannel * channel = CServiceManager::getInstance()->FindChannel(channel_id); if(channel) return channel; - freq++; } return NULL; } From d072a0e8b34719b53ed6f54c8f952724b00282bf Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Thu, 26 Jan 2012 19:31:43 +0400 Subject: [PATCH 088/737] capmt: little cleanup --- src/zapit/src/capmt.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/zapit/src/capmt.cpp b/src/zapit/src/capmt.cpp index a994d9402..35ad4a1a8 100644 --- a/src/zapit/src/capmt.cpp +++ b/src/zapit/src/capmt.cpp @@ -184,13 +184,7 @@ bool CCamManager::SetMode(t_channel_id channel_id, enum runmode mode, bool start } printf("CCam::SetMode: channel %llx [%s] mode %d %s update %d\n", channel_id, channel->getName().c_str(), mode, start ? "START" : "STOP", force_update); mutex.lock(); -#if 0 - if(channel->getCaPmt() == NULL) { - printf("CCamManager: channel %llx dont have caPmt\n", channel_id); - mutex.unlock(); - return false; - } -#endif + cammap_iterator_t it = channel_map.find(channel_id); if(it != channel_map.end()) { cam = it->second; @@ -234,7 +228,6 @@ printf("CCam::SetMode: source %d old mask %d new mask %d force update %s\n", so if(newmask == 0) { /* FIXME: back to live channel from playback dont parse pmt and call setCaPmt * (see CMD_SB_LOCK / UNLOCK PLAYBACK */ - //channel->setCaPmt(NULL); //channel->setRawPmt(NULL);//FIXME channel_map.erase(channel_id); delete cam; From dae48e5b9a2e77680b5f482351d35c8e99037745 Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Tue, 31 Jan 2012 17:38:25 +0400 Subject: [PATCH 089/737] sectionsd: fix broken indents --- src/sectionsd/sectionsd.cpp | 3012 +++++++++++++++++------------------ 1 file changed, 1506 insertions(+), 1506 deletions(-) diff --git a/src/sectionsd/sectionsd.cpp b/src/sectionsd/sectionsd.cpp index e42327878..e43d38360 100644 --- a/src/sectionsd/sectionsd.cpp +++ b/src/sectionsd/sectionsd.cpp @@ -7797,9 +7797,9 @@ static void *cnThread(void *) dprintf("waiting for more than %d seconds - bail out...\n", TIME_EIT_VERSION_WAIT); /* send event anyway, so that we know there is no EPG */ eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG, - CEventServer::INITID_SECTIONSD, - &messaging_current_servicekey, - sizeof(messaging_current_servicekey)); + CEventServer::INITID_SECTIONSD, + &messaging_current_servicekey, + sizeof(messaging_current_servicekey)); writeLockMessaging(); messaging_need_eit_version = false; unlockMessaging(); @@ -7827,9 +7827,9 @@ static void *cnThread(void *) unlockMessaging(); dprintf("[cnThread] got current_next (0x%x) - sending event!\n", messaging_have_CN); eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG, - CEventServer::INITID_SECTIONSD, - &messaging_current_servicekey, - sizeof(messaging_current_servicekey)); + CEventServer::INITID_SECTIONSD, + &messaging_current_servicekey, + sizeof(messaging_current_servicekey)); /* we received an event => reset timeout timer... */ eit_waiting_since = zeit; dmxCN.lastChanged = zeit; /* this is ugly - needs somehting better */ @@ -7864,8 +7864,8 @@ static void *cnThread(void *) { timeoutsDMX = 0; printf("[cnThread] timeoutsDMX for 0x" - PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS - " reset to 0 (not broadcast)\n", messaging_current_servicekey ); + PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS + " reset to 0 (not broadcast)\n", messaging_current_servicekey ); } else { @@ -7883,153 +7883,153 @@ static void *cnThread(void *) usleep(timeoutsDMX*1000); // } - if (timeoutsDMX >= CHECK_RESTART_DMX_AFTER_TIMEOUTS && scanning) - { - dprintf("timeoutsDMX (%d) >= CHECK_RESTART_DMX_AFTER_TIMEOUTS (%d) && scanning => sendtosleepnow=true\n", + if (timeoutsDMX >= CHECK_RESTART_DMX_AFTER_TIMEOUTS && scanning) + { + dprintf("timeoutsDMX (%d) >= CHECK_RESTART_DMX_AFTER_TIMEOUTS (%d) && scanning => sendtosleepnow=true\n", timeoutsDMX, CHECK_RESTART_DMX_AFTER_TIMEOUTS); - sendToSleepNow = true; - timeoutsDMX = 0; - } + sendToSleepNow = true; + timeoutsDMX = 0; + } #endif - if ((sendToSleepNow && !messaging_need_eit_version) || channel_is_blacklisted) + if ((sendToSleepNow && !messaging_need_eit_version) || channel_is_blacklisted) + { + sendToSleepNow = false; + + dmxCN.real_pause(); + dprintf("dmxCN: going to sleep...\n"); + + writeLockMessaging(); + messaging_eit_is_busy = false; + unlockMessaging(); + + /* re-fetch time if transponder changed + Why I'm doing this here and not from commandserviceChanged? + commandserviceChanged is called on zap *start*, not after zap finished + this would lead to often actually fetching the time on the transponder + you are switching away from, not the one you are switching onto. + Doing it here at least gives us a good chance to have actually tuned + to the channel we want to get the time from... + */ + if (time_trigger_last != (messaging_current_servicekey & 0xFFFFFFFF0000ULL)) { - sendToSleepNow = false; + time_trigger_last = messaging_current_servicekey & 0xFFFFFFFF0000ULL; + pthread_mutex_lock(&timeThreadSleepMutex); + pthread_cond_broadcast(&timeThreadSleepCond); + pthread_mutex_unlock(&timeThreadSleepMutex); + } - dmxCN.real_pause(); - dprintf("dmxCN: going to sleep...\n"); + int rs; + do { + pthread_mutex_lock( &dmxCN.start_stop_mutex ); + if (!channel_is_blacklisted) + eit_set_update_filter(&eit_update_fd); + rs = pthread_cond_wait(&dmxCN.change_cond, &dmxCN.start_stop_mutex); + eit_stop_update_filter(&eit_update_fd); + pthread_mutex_unlock(&dmxCN.start_stop_mutex); + } while (channel_is_blacklisted); - writeLockMessaging(); - messaging_eit_is_busy = false; - unlockMessaging(); + writeLockMessaging(); + messaging_need_eit_version = false; + messaging_eit_is_busy = true; + unlockMessaging(); - /* re-fetch time if transponder changed - Why I'm doing this here and not from commandserviceChanged? - commandserviceChanged is called on zap *start*, not after zap finished - this would lead to often actually fetching the time on the transponder - you are switching away from, not the one you are switching onto. - Doing it here at least gives us a good chance to have actually tuned - to the channel we want to get the time from... - */ - if (time_trigger_last != (messaging_current_servicekey & 0xFFFFFFFF0000ULL)) - { - time_trigger_last = messaging_current_servicekey & 0xFFFFFFFF0000ULL; - pthread_mutex_lock(&timeThreadSleepMutex); - pthread_cond_broadcast(&timeThreadSleepCond); - pthread_mutex_unlock(&timeThreadSleepMutex); - } - - int rs; - do { - pthread_mutex_lock( &dmxCN.start_stop_mutex ); - if (!channel_is_blacklisted) - eit_set_update_filter(&eit_update_fd); - rs = pthread_cond_wait(&dmxCN.change_cond, &dmxCN.start_stop_mutex); - eit_stop_update_filter(&eit_update_fd); - pthread_mutex_unlock(&dmxCN.start_stop_mutex); - } while (channel_is_blacklisted); - - writeLockMessaging(); - messaging_need_eit_version = false; - messaging_eit_is_busy = true; - unlockMessaging(); - - if (rs == 0) - { - dprintf("dmxCN: waking up again - requested from .change()\n"); - // fix EPG problems on IPBox - // http://tuxbox-forum.dreambox-fan.de/forum/viewtopic.php?p=367937#p367937 + if (rs == 0) + { + dprintf("dmxCN: waking up again - requested from .change()\n"); + // fix EPG problems on IPBox + // http://tuxbox-forum.dreambox-fan.de/forum/viewtopic.php?p=367937#p367937 #if HAVE_IPBOX_HARDWARE - dmxCN.change(0); + dmxCN.change(0); #endif - } - else - { - printf("dmxCN: waking up again - unknown reason %d\n",rs); - dmxCN.real_unpause(); - } - zeit = time_monotonic(); } - else if (zeit > dmxCN.lastChanged + TIME_EIT_VERSION_WAIT && !messaging_need_eit_version) + else { - xprintf("zeit > dmxCN.lastChanged + TIME_EIT_VERSION_WAIT\n"); - sendToSleepNow = true; - /* we can get here if we got the EIT version but no events */ - /* send a "no epg" event anyway before going to sleep */ - if (messaging_have_CN == 0x00) - eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG, - CEventServer::INITID_SECTIONSD, - &messaging_current_servicekey, - sizeof(messaging_current_servicekey)); - continue; + printf("dmxCN: waking up again - unknown reason %d\n",rs); + dmxCN.real_unpause(); } + zeit = time_monotonic(); + } + else if (zeit > dmxCN.lastChanged + TIME_EIT_VERSION_WAIT && !messaging_need_eit_version) + { + xprintf("zeit > dmxCN.lastChanged + TIME_EIT_VERSION_WAIT\n"); + sendToSleepNow = true; + /* we can get here if we got the EIT version but no events */ + /* send a "no epg" event anyway before going to sleep */ + if (messaging_have_CN == 0x00) + eventServer->sendEvent(CSectionsdClient::EVT_GOT_CN_EPG, + CEventServer::INITID_SECTIONSD, + &messaging_current_servicekey, + sizeof(messaging_current_servicekey)); + continue; + } - if (rc < 0) - continue; + if (rc < 0) + continue; - if (rc < (int)sizeof(struct SI_section_header)) + if (rc < (int)sizeof(struct SI_section_header)) + { + xprintf("%s: rc < sizeof(SI_Section_header) (%d < %d)\n", __FUNCTION__, rc, sizeof(struct SI_section_header)); + continue; + } + + header = (SI_section_header *)static_buf; + unsigned short section_length = (header->section_length_hi << 8) | header->section_length_lo; + + if (!header->current_next_indicator) + { + // Wir wollen nur aktuelle sections + //dprintf("[cnThread] skipped sections for table 0x%x\n", header->table_id); + continue; + } + + SIsectionEIT eit(section_length + 3, static_buf); + // Houdini: if section is not parsed (too short) -> no need to check events + if (!eit.is_parsed() || !eit.header()) + continue; + + // == 0 -> kein event + //dprintf("[cnThread] adding %d events [table 0x%x] (begin)\n", eit.events().size(), header->table_id); + zeit = time(NULL); + // Nicht alle Events speichern + for (SIevents::iterator e = eit.events().begin(); e != eit.events().end(); e++) + { + if (!(e->times.empty())) { - xprintf("%s: rc < sizeof(SI_Section_header) (%d < %d)\n", __FUNCTION__, rc, sizeof(struct SI_section_header)); - continue; + addEvent(*e, zeit, true); /* cn = true => fill in current / next event */ } - - header = (SI_section_header *)static_buf; - unsigned short section_length = (header->section_length_hi << 8) | header->section_length_lo; - - if (!header->current_next_indicator) - { - // Wir wollen nur aktuelle sections - //dprintf("[cnThread] skipped sections for table 0x%x\n", header->table_id); - continue; - } - - SIsectionEIT eit(section_length + 3, static_buf); - // Houdini: if section is not parsed (too short) -> no need to check events - if (!eit.is_parsed() || !eit.header()) - continue; - - // == 0 -> kein event - //dprintf("[cnThread] adding %d events [table 0x%x] (begin)\n", eit.events().size(), header->table_id); - zeit = time(NULL); - // Nicht alle Events speichern - for (SIevents::iterator e = eit.events().begin(); e != eit.events().end(); e++) - { - if (!(e->times.empty())) - { - addEvent(*e, zeit, true); /* cn = true => fill in current / next event */ - } #if 0 - /* I don't think there are NVOD events in CN tables, so we can skip that */ - else + /* I don't think there are NVOD events in CN tables, so we can skip that */ + else + { + /* this actually happens sometimes... */ + dprintf("e->times.empty in CN-THREAD!!\n"); + // pruefen ob nvod event + readLockServices(); + MySIservicesNVODorderUniqueKey::iterator si = mySIservicesNVODorderUniqueKey.find(e->get_channel_id()); + if (si != mySIservicesNVODorderUniqueKey.end()) { - /* this actually happens sometimes... */ - dprintf("e->times.empty in CN-THREAD!!\n"); - // pruefen ob nvod event - readLockServices(); - MySIservicesNVODorderUniqueKey::iterator si = mySIservicesNVODorderUniqueKey.find(e->get_channel_id()); - if (si != mySIservicesNVODorderUniqueKey.end()) - { - /* if this never happens in reality, we can remove the whole "else" clause here */ - printdate_ms(stderr); - fprintf(stderr, "NVOD-EVENT in CN-THREAD!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - // Ist ein nvod-event - writeLockEvents(); - for (SInvodReferences::iterator i = si->second->nvods.begin(); i != si->second->nvods.end(); i++) - mySIeventUniqueKeysMetaOrderServiceUniqueKey.insert(std::make_pair(i->uniqueKey(), e->uniqueKey())); - unlockEvents(); - addNVODevent(*e); - } - unlockServices(); + /* if this never happens in reality, we can remove the whole "else" clause here */ + printdate_ms(stderr); + fprintf(stderr, "NVOD-EVENT in CN-THREAD!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + // Ist ein nvod-event + writeLockEvents(); + for (SInvodReferences::iterator i = si->second->nvods.begin(); i != si->second->nvods.end(); i++) + mySIeventUniqueKeysMetaOrderServiceUniqueKey.insert(std::make_pair(i->uniqueKey(), e->uniqueKey())); + unlockEvents(); + addNVODevent(*e); } + unlockServices(); + } #endif - } // for - //dprintf("[cnThread] added %d events (end)\n", eit.events().size()); } // for - delete[] static_buf; + //dprintf("[cnThread] added %d events (end)\n", eit.events().size()); + } // for + delete[] static_buf; - printf("[sectionsd] cnThread ended\n"); + printf("[sectionsd] cnThread ended\n"); - pthread_exit(NULL); - } + pthread_exit(NULL); +} #ifdef ENABLE_PPT @@ -8038,675 +8038,675 @@ static void *cnThread(void *) // reads EPG-datas //--------------------------------------------------------------------- - static void *pptThread(void *) - { - struct SI_section_header *header; - unsigned timeoutInMSeconds = EIT_READ_TIMEOUT; - bool sendToSleepNow = false; - unsigned short start_section = 0; - unsigned short pptpid=0; - long first_content_id = 0; - long previous_content_id = 0; - long current_content_id = 0; - bool already_exists = false; +static void *pptThread(void *) +{ + struct SI_section_header *header; + unsigned timeoutInMSeconds = EIT_READ_TIMEOUT; + bool sendToSleepNow = false; + unsigned short start_section = 0; + unsigned short pptpid=0; + long first_content_id = 0; + long previous_content_id = 0; + long current_content_id = 0; + bool already_exists = false; - // dmxPPT.addfilter( 0xa0, (0xff - 0x01) ); - dmxPPT.addfilter( 0xa0, (0xff)); - dprintf("[%sThread] pid %d (%lu) start\n", "ppt", getpid(), pthread_self()); - int timeoutsDMX = 0; - char *static_buf = new char[MAX_SECTION_LENGTH]; - int rc; + // dmxPPT.addfilter( 0xa0, (0xff - 0x01) ); + dmxPPT.addfilter( 0xa0, (0xff)); + dprintf("[%sThread] pid %d (%lu) start\n", "ppt", getpid(), pthread_self()); + int timeoutsDMX = 0; + char *static_buf = new char[MAX_SECTION_LENGTH]; + int rc; - if (static_buf == NULL) - throw std::bad_alloc(); + if (static_buf == NULL) + throw std::bad_alloc(); - time_t lastRestarted = time_monotonic(); - time_t lastData = time_monotonic(); + time_t lastRestarted = time_monotonic(); + time_t lastData = time_monotonic(); - dmxPPT.start(); // -> unlock - if (!scanning) - dmxPPT.request_pause(); + dmxPPT.start(); // -> unlock + if (!scanning) + dmxPPT.request_pause(); - waitForTimeset(); - dmxPPT.lastChanged = time_monotonic(); + waitForTimeset(); + dmxPPT.lastChanged = time_monotonic(); - while (!sectionsd_stop) { - time_t zeit = time_monotonic(); + while (!sectionsd_stop) { + time_t zeit = time_monotonic(); - if (timeoutsDMX >= CHECK_RESTART_DMX_AFTER_TIMEOUTS && scanning && !channel_is_blacklisted) + if (timeoutsDMX >= CHECK_RESTART_DMX_AFTER_TIMEOUTS && scanning && !channel_is_blacklisted) + { + if (zeit > lastRestarted + 3) // last restart older than 3secs, therefore do NOT decrease cache { - if (zeit > lastRestarted + 3) // last restart older than 3secs, therefore do NOT decrease cache + dmxPPT.stop(); // -> lock + dmxPPT.start(); // -> unlock + dprintf("[pptThread] dmxPPT restarted, cache NOT decreased (dt=%ld)\n", (int)zeit - lastRestarted); + } + else + { + + // sectionsd ist zu langsam, da zu viele events -> cache kleiner machen + dmxPPT.stop(); // -> lock + /* lockEvents(); + if(secondsToCache>24*60L*60L && mySIeventsOrderUniqueKey.size()>3000) + { + // kleiner als 1 Tag machen wir den Cache nicht, + // da die timeouts ja auch von einem Sender ohne EPG kommen koennen + // Die 3000 sind ne Annahme und beruhen auf (wenigen) Erfahrungswerten + // Man koennte auch ab 3000 Events nur noch jedes 3 Event o.ae. einsortieren + dmxSDT.real_pause(); + lockServices(); + unsigned anzEventsAlt=mySIeventsOrderUniqueKey.size(); + secondsToCache-=5*60L*60L; // 5h weniger + dprintf("[eitThread] decreasing cache 5h (now %ldh)\n", secondsToCache/(60*60L)); + removeNewEvents(); + removeOldEvents(oldEventsAre); + if(anzEventsAlt>mySIeventsOrderUniqueKey.size()) + dprintf("[eitThread] Removed %u Events (%u -> %u)\n", anzEventsAlt-mySIeventsOrderUniqueKey.size(), anzEventsAlt, mySIeventsOrderUniqueKey.size()); + unlockServices(); + dmxSDT.real_unpause(); + } + unlockEvents(); + */ + dmxPPT.start(); // -> unlock + // dputs("[pptThread] dmxPPT restarted"); + + } + + lastRestarted = zeit; + timeoutsDMX = 0; + lastData = zeit; + } + + if (sendToSleepNow || !scanning || channel_is_blacklisted) + { + sendToSleepNow = false; + + dmxPPT.real_pause(); + + int rs; + do { + pthread_mutex_lock( &dmxPPT.start_stop_mutex ); + + if (0 != privatePid) { - dmxPPT.stop(); // -> lock - dmxPPT.start(); // -> unlock - dprintf("[pptThread] dmxPPT restarted, cache NOT decreased (dt=%ld)\n", (int)zeit - lastRestarted); + struct timespec abs_wait; + struct timeval now; + + gettimeofday(&now, NULL); + TIMEVAL_TO_TIMESPEC(&now, &abs_wait); + abs_wait.tv_sec += (TIME_EIT_SCHEDULED_PAUSE); + dprintf("[pptThread] going to sleep for %d seconds...\n", TIME_EIT_SCHEDULED_PAUSE); + rs = pthread_cond_timedwait(&dmxPPT.change_cond, &dmxPPT.start_stop_mutex, &abs_wait); } else { - - // sectionsd ist zu langsam, da zu viele events -> cache kleiner machen - dmxPPT.stop(); // -> lock - /* lockEvents(); - if(secondsToCache>24*60L*60L && mySIeventsOrderUniqueKey.size()>3000) - { - // kleiner als 1 Tag machen wir den Cache nicht, - // da die timeouts ja auch von einem Sender ohne EPG kommen koennen - // Die 3000 sind ne Annahme und beruhen auf (wenigen) Erfahrungswerten - // Man koennte auch ab 3000 Events nur noch jedes 3 Event o.ae. einsortieren - dmxSDT.real_pause(); - lockServices(); - unsigned anzEventsAlt=mySIeventsOrderUniqueKey.size(); - secondsToCache-=5*60L*60L; // 5h weniger - dprintf("[eitThread] decreasing cache 5h (now %ldh)\n", secondsToCache/(60*60L)); - removeNewEvents(); - removeOldEvents(oldEventsAre); - if(anzEventsAlt>mySIeventsOrderUniqueKey.size()) - dprintf("[eitThread] Removed %u Events (%u -> %u)\n", anzEventsAlt-mySIeventsOrderUniqueKey.size(), anzEventsAlt, mySIeventsOrderUniqueKey.size()); - unlockServices(); - dmxSDT.real_unpause(); - } - unlockEvents(); - */ - dmxPPT.start(); // -> unlock - // dputs("[pptThread] dmxPPT restarted"); - + dprintf("[pptThread] going to sleep until wakeup...\n"); + rs = pthread_cond_wait(&dmxPPT.change_cond, &dmxPPT.start_stop_mutex); } - lastRestarted = zeit; - timeoutsDMX = 0; - lastData = zeit; + pthread_mutex_unlock( &dmxPPT.start_stop_mutex ); + } while (channel_is_blacklisted); + + if (rs == ETIMEDOUT) + { + dprintf("dmxPPT: waking up again - looking for new events :)\n"); + if (0 != privatePid) + { + dmxPPT.change( 0 ); // -> restart + } + } + else if (rs == 0) + { + dprintf("dmxPPT: waking up again - requested from .change()\n"); + } + else + { + dprintf("dmxPPT: waking up again - unknown reason?!\n"); + dmxPPT.real_unpause(); + } + // after sleeping get current time + zeit = time_monotonic(); + start_section = 0; // fetch new? events + lastData = zeit; // restart timer + first_content_id = 0; + previous_content_id = 0; + current_content_id = 0; + } + + if (0 == privatePid) + { + sendToSleepNow = true; // if there is no valid pid -> sleep + dprintf("dmxPPT: no valid pid 0\n"); + sleep(1); + continue; + } + + if (!scanning) + continue; // go to sleep again... + + if (pptpid != privatePid) + { + pptpid = privatePid; + dprintf("Setting PrivatePid %x\n", pptpid); + dmxPPT.setPid(pptpid); + } + + rc = dmxPPT.getSection(static_buf, timeoutInMSeconds, timeoutsDMX); + + if (rc < 0) { + if (zeit > lastData + 5) + { + sendToSleepNow = true; // if there are no data for 5 seconds -> sleep + dprintf("dmxPPT: no data for 5 seconds\n"); + } + continue; + } + + if (rc < (int)sizeof(struct SI_section_header)) + { + xprintf("%s: ret < sizeof(SI_Section_header) (%d < %d)\n", __FUNCTION__, rc, sizeof(struct SI_section_header)); + continue; + } + + lastData = zeit; + + header = (SI_section_header*)static_buf; + unsigned short section_length = header->section_length_hi << 8 | header->section_length_lo; + + if (header->current_next_indicator) + { + // Wir wollen nur aktuelle sections + if (start_section == 0) + start_section = header->section_number; + else if (start_section == header->section_number) + { + sendToSleepNow = true; // no more scanning + dprintf("[pptThread] got all sections\n"); + continue; } - if (sendToSleepNow || !scanning || channel_is_blacklisted) - { - sendToSleepNow = false; + // SIsectionPPT ppt(SIsection(section_length + 3, buf)); + SIsectionPPT ppt(section_length + 3, static_buf); + if (ppt.is_parsed()) + if (ppt.header()) + { + // == 0 -> kein event + // dprintf("[pptThread] adding %d events [table 0x%x] (begin)\n", ppt.events().size(), header.table_id); + // dprintf("got %d: ", header.section_number); + zeit = time(NULL); - dmxPPT.real_pause(); - - int rs; - do { - pthread_mutex_lock( &dmxPPT.start_stop_mutex ); - - if (0 != privatePid) + // Hintereinander vorkommende sections mit gleicher contentID herausfinden + current_content_id = ppt.content_id(); + if (first_content_id == 0) { - struct timespec abs_wait; - struct timeval now; - - gettimeofday(&now, NULL); - TIMEVAL_TO_TIMESPEC(&now, &abs_wait); - abs_wait.tv_sec += (TIME_EIT_SCHEDULED_PAUSE); - dprintf("[pptThread] going to sleep for %d seconds...\n", TIME_EIT_SCHEDULED_PAUSE); - rs = pthread_cond_timedwait(&dmxPPT.change_cond, &dmxPPT.start_stop_mutex, &abs_wait); + // aktuelle section ist die erste + already_exists = false; + first_content_id = current_content_id; + } + else if ((first_content_id == current_content_id) || (previous_content_id == current_content_id)) + { + // erste und aktuelle bzw. vorherige und aktuelle section sind gleich + already_exists = true; } else { - dprintf("[pptThread] going to sleep until wakeup...\n"); - rs = pthread_cond_wait(&dmxPPT.change_cond, &dmxPPT.start_stop_mutex); + // erste und aktuelle bzw. vorherige und aktuelle section sind nicht gleich + already_exists = false; + previous_content_id = current_content_id; } - pthread_mutex_unlock( &dmxPPT.start_stop_mutex ); - } while (channel_is_blacklisted); - - if (rs == ETIMEDOUT) - { - dprintf("dmxPPT: waking up again - looking for new events :)\n"); - if (0 != privatePid) + // Nicht alle Events speichern + for (SIevents::iterator e = ppt.events().begin(); e != ppt.events().end(); e++) { - dmxPPT.change( 0 ); // -> restart - } - } - else if (rs == 0) - { - dprintf("dmxPPT: waking up again - requested from .change()\n"); - } - else - { - dprintf("dmxPPT: waking up again - unknown reason?!\n"); - dmxPPT.real_unpause(); - } - // after sleeping get current time - zeit = time_monotonic(); - start_section = 0; // fetch new? events - lastData = zeit; // restart timer - first_content_id = 0; - previous_content_id = 0; - current_content_id = 0; - } - - if (0 == privatePid) - { - sendToSleepNow = true; // if there is no valid pid -> sleep - dprintf("dmxPPT: no valid pid 0\n"); - sleep(1); - continue; - } - - if (!scanning) - continue; // go to sleep again... - - if (pptpid != privatePid) - { - pptpid = privatePid; - dprintf("Setting PrivatePid %x\n", pptpid); - dmxPPT.setPid(pptpid); - } - - rc = dmxPPT.getSection(static_buf, timeoutInMSeconds, timeoutsDMX); - - if (rc < 0) { - if (zeit > lastData + 5) - { - sendToSleepNow = true; // if there are no data for 5 seconds -> sleep - dprintf("dmxPPT: no data for 5 seconds\n"); - } - continue; - } - - if (rc < (int)sizeof(struct SI_section_header)) - { - xprintf("%s: ret < sizeof(SI_Section_header) (%d < %d)\n", __FUNCTION__, rc, sizeof(struct SI_section_header)); - continue; - } - - lastData = zeit; - - header = (SI_section_header*)static_buf; - unsigned short section_length = header->section_length_hi << 8 | header->section_length_lo; - - if (header->current_next_indicator) - { - // Wir wollen nur aktuelle sections - if (start_section == 0) - start_section = header->section_number; - else if (start_section == header->section_number) - { - sendToSleepNow = true; // no more scanning - dprintf("[pptThread] got all sections\n"); - continue; - } - - // SIsectionPPT ppt(SIsection(section_length + 3, buf)); - SIsectionPPT ppt(section_length + 3, static_buf); - if (ppt.is_parsed()) - if (ppt.header()) - { - // == 0 -> kein event - // dprintf("[pptThread] adding %d events [table 0x%x] (begin)\n", ppt.events().size(), header.table_id); - // dprintf("got %d: ", header.section_number); - zeit = time(NULL); - - // Hintereinander vorkommende sections mit gleicher contentID herausfinden - current_content_id = ppt.content_id(); - if (first_content_id == 0) + if (!(e->times.empty())) { - // aktuelle section ist die erste - already_exists = false; - first_content_id = current_content_id; - } - else if ((first_content_id == current_content_id) || (previous_content_id == current_content_id)) - { - // erste und aktuelle bzw. vorherige und aktuelle section sind gleich - already_exists = true; + for (SItimes::iterator t = e->times.begin(); t != e->times.end(); t++) { + // if ( ( e->times.begin()->startzeit < zeit + secondsToCache ) && + // ( ( e->times.begin()->startzeit + (long)e->times.begin()->dauer ) > zeit - oldEventsAre ) ) + // add the event if at least one starttime matches + if ( ( t->startzeit < zeit + secondsToCache ) && + ( ( t->startzeit + (long)t->dauer ) > zeit - oldEventsAre ) ) + { + // dprintf("chId: " PRINTF_CHANNEL_ID_TYPE " Dauer: %ld, Startzeit: %s", e->get_channel_id(), (long)e->times.begin()->dauer, ctime(&e->times.begin()->startzeit)); + // writeLockEvents(); + + if (already_exists) + { + // Zusaetzliche Zeiten in ein Event einfuegen + addEventTimes(*e); + } + else + { + // Ein Event in alle Mengen einfuegen + addEvent(*e, zeit); + } + + // unlockEvents(); + break; // only add the event once + } +#if 0 + // why is the following not compiling, fuXX STL + else { + // remove unusable times in event + SItimes::iterator kt = t; + t--; // the iterator t points to the last element + e->times.erase(kt); + } +#endif + } } else { - // erste und aktuelle bzw. vorherige und aktuelle section sind nicht gleich - already_exists = false; - previous_content_id = current_content_id; + // pruefen ob nvod event + readLockServices(); + MySIservicesNVODorderUniqueKey::iterator si = mySIservicesNVODorderUniqueKey.find(e->get_channel_id()); + + if (si != mySIservicesNVODorderUniqueKey.end()) + { + // Ist ein nvod-event + writeLockEvents(); + + for (SInvodReferences::iterator i = si->second->nvods.begin(); i != si->second->nvods.end(); i++) + mySIeventUniqueKeysMetaOrderServiceUniqueKey.insert(std::make_pair(i->uniqueKey(), e->uniqueKey())); + + addNVODevent(*e); + unlockEvents(); + } + unlockServices(); } + } // for + //dprintf("[pptThread] added %d events (end)\n", ppt.events().size()); + } // if + } // if + } // for + delete[] static_buf; - // Nicht alle Events speichern - for (SIevents::iterator e = ppt.events().begin(); e != ppt.events().end(); e++) - { - if (!(e->times.empty())) - { - for (SItimes::iterator t = e->times.begin(); t != e->times.end(); t++) { - // if ( ( e->times.begin()->startzeit < zeit + secondsToCache ) && - // ( ( e->times.begin()->startzeit + (long)e->times.begin()->dauer ) > zeit - oldEventsAre ) ) - // add the event if at least one starttime matches - if ( ( t->startzeit < zeit + secondsToCache ) && - ( ( t->startzeit + (long)t->dauer ) > zeit - oldEventsAre ) ) - { - // dprintf("chId: " PRINTF_CHANNEL_ID_TYPE " Dauer: %ld, Startzeit: %s", e->get_channel_id(), (long)e->times.begin()->dauer, ctime(&e->times.begin()->startzeit)); - // writeLockEvents(); + dputs("[pptThread] end"); - if (already_exists) - { - // Zusaetzliche Zeiten in ein Event einfuegen - addEventTimes(*e); - } - else - { - // Ein Event in alle Mengen einfuegen - addEvent(*e, zeit); - } - - // unlockEvents(); - break; // only add the event once - } -#if 0 - // why is the following not compiling, fuXX STL - else { - // remove unusable times in event - SItimes::iterator kt = t; - t--; // the iterator t points to the last element - e->times.erase(kt); - } -#endif - } - } - else - { - // pruefen ob nvod event - readLockServices(); - MySIservicesNVODorderUniqueKey::iterator si = mySIservicesNVODorderUniqueKey.find(e->get_channel_id()); - - if (si != mySIservicesNVODorderUniqueKey.end()) - { - // Ist ein nvod-event - writeLockEvents(); - - for (SInvodReferences::iterator i = si->second->nvods.begin(); i != si->second->nvods.end(); i++) - mySIeventUniqueKeysMetaOrderServiceUniqueKey.insert(std::make_pair(i->uniqueKey(), e->uniqueKey())); - - addNVODevent(*e); - unlockEvents(); - } - unlockServices(); - } - } // for - //dprintf("[pptThread] added %d events (end)\n", ppt.events().size()); - } // if - } // if - } // for - delete[] static_buf; - - dputs("[pptThread] end"); - - pthread_exit(NULL); - } + pthread_exit(NULL); +} #endif - /* helper function for the housekeeping-thread */ - static void print_meminfo(void) - { - if (!sections_debug) - return; +/* helper function for the housekeeping-thread */ +static void print_meminfo(void) +{ + if (!sections_debug) + return; - struct mallinfo meminfo = mallinfo(); - dprintf("total size of memory occupied by chunks handed out by malloc: %d\n" + struct mallinfo meminfo = mallinfo(); + dprintf("total size of memory occupied by chunks handed out by malloc: %d\n" "total bytes memory allocated with `sbrk' by malloc, in bytes: %d (%dkB)\n", meminfo.uordblks, meminfo.arena, meminfo.arena / 1024); - } +} //--------------------------------------------------------------------- // housekeeping-thread // does cleaning on fetched datas //--------------------------------------------------------------------- - static void *houseKeepingThread(void *) +static void *houseKeepingThread(void *) +{ + int count = 0; +#ifdef UPDATE_NETWORKS + char servicename[MAX_SIZE_SERVICENAME]; +#endif + dprintf("housekeeping-thread started.\n"); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); + + while (!sectionsd_stop) { - int count = 0; -#ifdef UPDATE_NETWORKS - char servicename[MAX_SIZE_SERVICENAME]; -#endif - dprintf("housekeeping-thread started.\n"); - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); + if (count == META_HOUSEKEEPING) { + dprintf("meta housekeeping - deleting all transponders, services, bouquets.\n"); + deleteSIexceptEPG(); + count = 0; + } - while (!sectionsd_stop) + int rc = HOUSEKEEPING_SLEEP; + + while (rc) + rc = sleep(rc); + + while (!scanning) { + sleep(1); // wait for streaming to end... + if(sectionsd_stop) + break; + } + + dprintf("housekeeping.\n"); + + // TODO: maybe we need to stop scanning here?... + + readLockEvents(); + + unsigned anzEventsAlt = mySIeventsOrderUniqueKey.size(); + dprintf("before removeoldevents\n"); + unlockEvents(); + removeOldEvents(oldEventsAre); // alte Events + dprintf("after removeoldevents\n"); + readLockEvents(); + printf("[sectionsd] Removed %d old events (%d left).\n", anzEventsAlt - mySIeventsOrderUniqueKey.size(), mySIeventsOrderUniqueKey.size()); + if (mySIeventsOrderUniqueKey.size() != anzEventsAlt) { - if (count == META_HOUSEKEEPING) { - dprintf("meta housekeeping - deleting all transponders, services, bouquets.\n"); - deleteSIexceptEPG(); - count = 0; - } - - int rc = HOUSEKEEPING_SLEEP; - - while (rc) - rc = sleep(rc); - - while (!scanning) { - sleep(1); // wait for streaming to end... - if(sectionsd_stop) - break; - } - - dprintf("housekeeping.\n"); - - // TODO: maybe we need to stop scanning here?... - - readLockEvents(); - - unsigned anzEventsAlt = mySIeventsOrderUniqueKey.size(); - dprintf("before removeoldevents\n"); - unlockEvents(); - removeOldEvents(oldEventsAre); // alte Events - dprintf("after removeoldevents\n"); - readLockEvents(); - printf("[sectionsd] Removed %d old events (%d left).\n", anzEventsAlt - mySIeventsOrderUniqueKey.size(), mySIeventsOrderUniqueKey.size()); - if (mySIeventsOrderUniqueKey.size() != anzEventsAlt) - { - print_meminfo(); - dprintf("Removed %d old events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); - } - anzEventsAlt = mySIeventsOrderUniqueKey.size(); - unlockEvents(); - // usleep(100); - // lockEvents(); + print_meminfo(); + dprintf("Removed %d old events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); + } + anzEventsAlt = mySIeventsOrderUniqueKey.size(); + unlockEvents(); + // usleep(100); + // lockEvents(); #ifdef REMOVE_DUPS - removeDupEvents(); - readLockEvents(); - printf("[sectionsd] Removed %d dup events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); - anzEventsAlt = mySIeventsOrderUniqueKey.size(); - unlockEvents(); + removeDupEvents(); + readLockEvents(); + printf("[sectionsd] Removed %d dup events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); + anzEventsAlt = mySIeventsOrderUniqueKey.size(); + unlockEvents(); #endif - dprintf("before removewasteepg\n"); + dprintf("before removewasteepg\n"); #ifdef UPDATE_NETWORKS - removeWasteEvents(); // Events for channels not in services.xml - dprintf("after removewasteepg\n"); + removeWasteEvents(); // Events for channels not in services.xml + dprintf("after removewasteepg\n"); #endif - readLockEvents(); - if (mySIeventsOrderUniqueKey.size() != anzEventsAlt) - { - print_meminfo(); - dprintf("Removed %d waste events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); - } + readLockEvents(); + if (mySIeventsOrderUniqueKey.size() != anzEventsAlt) + { + print_meminfo(); + dprintf("Removed %d waste events.\n", anzEventsAlt - mySIeventsOrderUniqueKey.size()); + } - dprintf("Number of sptr events (event-ID): %u\n", mySIeventsOrderUniqueKey.size()); - dprintf("Number of sptr events (service-id, start time, event-id): %u\n", mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.size()); - dprintf("Number of sptr events (end time, service-id, event-id): %u\n", mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.size()); - dprintf("Number of sptr nvod events (event-ID): %u\n", mySIeventsNVODorderUniqueKey.size()); - dprintf("Number of cached meta-services: %u\n", mySIeventUniqueKeysMetaOrderServiceUniqueKey.size()); + dprintf("Number of sptr events (event-ID): %u\n", mySIeventsOrderUniqueKey.size()); + dprintf("Number of sptr events (service-id, start time, event-id): %u\n", mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.size()); + dprintf("Number of sptr events (end time, service-id, event-id): %u\n", mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.size()); + dprintf("Number of sptr nvod events (event-ID): %u\n", mySIeventsNVODorderUniqueKey.size()); + dprintf("Number of cached meta-services: %u\n", mySIeventUniqueKeysMetaOrderServiceUniqueKey.size()); - unlockEvents(); + unlockEvents(); #ifdef UPDATE_NETWORKS - readLockServices(); - dprintf("Number of services: %u\n", mySIservicesOrderUniqueKey.size()); - //dprintf("Number of services (name): %u\n", mySIservicesOrderServiceName.size()); - dprintf("Number of cached nvod-services: %u\n", mySIservicesNVODorderUniqueKey.size()); + readLockServices(); + dprintf("Number of services: %u\n", mySIservicesOrderUniqueKey.size()); + //dprintf("Number of services (name): %u\n", mySIservicesOrderServiceName.size()); + dprintf("Number of cached nvod-services: %u\n", mySIservicesNVODorderUniqueKey.size()); - xmlDocPtr bouquet_parser = NULL; - xmlDocPtr current_parser = NULL; - for (MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.begin(); s != mySIservicesOrderUniqueKey.end(); s++) { - dprintf("ONID: %04x TSID: %04x SID: %04x Prov: %s Name: %s actual: %d\n", + xmlDocPtr bouquet_parser = NULL; + xmlDocPtr current_parser = NULL; + for (MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.begin(); s != mySIservicesOrderUniqueKey.end(); s++) { + dprintf("ONID: %04x TSID: %04x SID: %04x Prov: %s Name: %s actual: %d\n", s->second->original_network_id, s->second->transport_stream_id, s->second->service_id, s->second->providerName.c_str(), s->second->serviceName.c_str(), (int) s->second->is_actual); - readLockMessaging(); - if (((s->second->is_actual & 8) == 8) && (!messaging_zap_detected)) { - unlockMessaging(); + readLockMessaging(); + if (((s->second->is_actual & 8) == 8) && (!messaging_zap_detected)) { + unlockMessaging(); - if (!bouquet_parser) { - if (!access(CURRENTBOUQUETS_XML, R_OK)) { - if (current_parser) - xmlFreeDoc(current_parser); - current_parser = - parseXmlFile(CURRENTBOUQUETS_XML); - } - bouquet_parser = parseXmlFile(BOUQUETS_XML); + if (!bouquet_parser) { + if (!access(CURRENTBOUQUETS_XML, R_OK)) { + if (current_parser) + xmlFreeDoc(current_parser); + current_parser = + parseXmlFile(CURRENTBOUQUETS_XML); } - snprintf(servicename, MAX_SIZE_SERVICENAME, - s->second->providerName.c_str()); - if (AddServiceToAutoBouquets(&servicename[0], - s->second->original_network_id, - s->second->transport_stream_id, - s->second->service_id, - bouquet_parser, - current_parser)) { - readLockMessaging(); - if (!messaging_zap_detected) { - unlockMessaging(); - if (current_parser) - xmlFreeDoc(current_parser); - current_parser = - parseXmlFile(CURRENTBOUQUETS_XML); - } - else - unlockMessaging(); - } - unlockServices(); - writeLockServices(); - s->second->is_actual = (s->second->is_actual & 7); - unlockServices(); - readLockServices(); + bouquet_parser = parseXmlFile(BOUQUETS_XML); } - else - unlockMessaging(); - + snprintf(servicename, MAX_SIZE_SERVICENAME, + s->second->providerName.c_str()); + if (AddServiceToAutoBouquets(&servicename[0], + s->second->original_network_id, + s->second->transport_stream_id, + s->second->service_id, + bouquet_parser, + current_parser)) { + readLockMessaging(); + if (!messaging_zap_detected) { + unlockMessaging(); + if (current_parser) + xmlFreeDoc(current_parser); + current_parser = + parseXmlFile(CURRENTBOUQUETS_XML); + } + else + unlockMessaging(); + } + unlockServices(); + writeLockServices(); + s->second->is_actual = (s->second->is_actual & 7); + unlockServices(); + readLockServices(); } - unlockServices(); - if (bouquet_parser) - xmlFreeDoc(bouquet_parser); - if (current_parser) - xmlFreeDoc(current_parser); + else + unlockMessaging(); + + } + unlockServices(); + if (bouquet_parser) + xmlFreeDoc(bouquet_parser); + if (current_parser) + xmlFreeDoc(current_parser); #endif - /* - lockTransponders(); - for (MySItranspondersOrderUniqueKey::iterator s = mySItranspondersOrderUniqueKey.begin(); s != mySItranspondersOrderUniqueKey.end(); s++) - { - // tsid = s->second->transport_stream_id; - // onid = s->second->original_network_id; - const char *ddp = &s->second->delivery_descriptor[0]; + /* + lockTransponders(); + for (MySItranspondersOrderUniqueKey::iterator s = mySItranspondersOrderUniqueKey.begin(); s != mySItranspondersOrderUniqueKey.end(); s++) + { + // tsid = s->second->transport_stream_id; + // onid = s->second->original_network_id; + const char *ddp = &s->second->delivery_descriptor[0]; - //printf("Descriptor_type: %02x\n", s->second->delivery_type); + //printf("Descriptor_type: %02x\n", s->second->delivery_type); - switch (s->second->delivery_type) { - case 0x43: - struct satellite_delivery_descriptor *sdd = (struct satellite_delivery_descriptor *)ddp; - printf("Sat TP - Orbital %04x ONID: %04x TSID: %04x\n", - (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo, - s->second->original_network_id, - s->second->transport_stream_id); + switch (s->second->delivery_type) { + case 0x43: + struct satellite_delivery_descriptor *sdd = (struct satellite_delivery_descriptor *)ddp; + printf("Sat TP - Orbital %04x ONID: %04x TSID: %04x\n", + (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo, + s->second->original_network_id, + s->second->transport_stream_id); - // if (!sdd->west_east_flag) - // position = -position; - // provider = getProvbyPosition(xmlDocGetRootElement(service_parser)->xmlChildrenNode, //position); - break; - case 0x44: - //provider = xmlDocGetRootElement(service_parser)->xmlChildrenNode; - break; - default: - break; - } - } - unlockTransponders(); - */ + // if (!sdd->west_east_flag) + // position = -position; + // provider = getProvbyPosition(xmlDocGetRootElement(service_parser)->xmlChildrenNode, //position); + break; + case 0x44: + //provider = xmlDocGetRootElement(service_parser)->xmlChildrenNode; + break; + default: + break; + } + } + unlockTransponders(); + */ - print_meminfo(); + print_meminfo(); - count++; + count++; - } // for endlos - dprintf("housekeeping-thread ended.\n"); + } // for endlos + dprintf("housekeeping-thread ended.\n"); - pthread_exit(NULL); - } + pthread_exit(NULL); +} - static void readEPGFilter(void) +static void readEPGFilter(void) +{ + xmlDocPtr filter_parser = parseXmlFile(epg_filter_dir.c_str()); + + t_original_network_id onid = 0; + t_transport_stream_id tsid = 0; + t_service_id sid = 0; + + if (filter_parser != NULL) { - xmlDocPtr filter_parser = parseXmlFile(epg_filter_dir.c_str()); + dprintf("Reading EPGFilters\n"); - t_original_network_id onid = 0; - t_transport_stream_id tsid = 0; - t_service_id sid = 0; + xmlNodePtr filter = xmlDocGetRootElement(filter_parser); + if (xmlGetNumericAttribute(filter, "is_whitelist", 10) == 1) + epg_filter_is_whitelist = true; + if (xmlGetNumericAttribute(filter, "except_current_next", 10) == 1) + epg_filter_except_current_next = true; + filter = filter->xmlChildrenNode; - if (filter_parser != NULL) - { - dprintf("Reading EPGFilters\n"); + while (filter) { - xmlNodePtr filter = xmlDocGetRootElement(filter_parser); - if (xmlGetNumericAttribute(filter, "is_whitelist", 10) == 1) - epg_filter_is_whitelist = true; - if (xmlGetNumericAttribute(filter, "except_current_next", 10) == 1) - epg_filter_except_current_next = true; - filter = filter->xmlChildrenNode; + onid = xmlGetNumericAttribute(filter, "onid", 16); + tsid = xmlGetNumericAttribute(filter, "tsid", 16); + sid = xmlGetNumericAttribute(filter, "serviceID", 16); + if (xmlGetNumericAttribute(filter, "blacklist", 10) == 1) + addBlacklist(onid, tsid, sid); + else + addEPGFilter(onid, tsid, sid); - while (filter) { + filter = filter->xmlNextNode; + } + } + xmlFreeDoc(filter_parser); +} - onid = xmlGetNumericAttribute(filter, "onid", 16); - tsid = xmlGetNumericAttribute(filter, "tsid", 16); - sid = xmlGetNumericAttribute(filter, "serviceID", 16); - if (xmlGetNumericAttribute(filter, "blacklist", 10) == 1) - addBlacklist(onid, tsid, sid); - else - addEPGFilter(onid, tsid, sid); +static void readDVBTimeFilter(void) +{ + xmlDocPtr filter_parser = parseXmlFile(dvbtime_filter_dir.c_str()); - filter = filter->xmlNextNode; - } + t_original_network_id onid = 0; + t_transport_stream_id tsid = 0; + t_service_id sid = 0; + + if (filter_parser != NULL) + { + dprintf("Reading DVBTimeFilters\n"); + + xmlNodePtr filter = xmlDocGetRootElement(filter_parser); + filter = filter->xmlChildrenNode; + + while (filter) { + + onid = xmlGetNumericAttribute(filter, "onid", 16); + tsid = xmlGetNumericAttribute(filter, "tsid", 16); + sid = xmlGetNumericAttribute(filter, "serviceID", 16); + addNoDVBTimelist(onid, tsid, sid); + + filter = filter->xmlNextNode; } xmlFreeDoc(filter_parser); } - - static void readDVBTimeFilter(void) + else { - xmlDocPtr filter_parser = parseXmlFile(dvbtime_filter_dir.c_str()); - - t_original_network_id onid = 0; - t_transport_stream_id tsid = 0; - t_service_id sid = 0; - - if (filter_parser != NULL) - { - dprintf("Reading DVBTimeFilters\n"); - - xmlNodePtr filter = xmlDocGetRootElement(filter_parser); - filter = filter->xmlChildrenNode; - - while (filter) { - - onid = xmlGetNumericAttribute(filter, "onid", 16); - tsid = xmlGetNumericAttribute(filter, "tsid", 16); - sid = xmlGetNumericAttribute(filter, "serviceID", 16); - addNoDVBTimelist(onid, tsid, sid); - - filter = filter->xmlNextNode; - } - xmlFreeDoc(filter_parser); - } - else - { - dvb_time_update = true; - } + dvb_time_update = true; } +} #if 0 - static void readBouquetFilter(void) +static void readBouquetFilter(void) +{ + xmlDocPtr filter_parser = parseXmlFile("/var/tuxbox/config/mybouquets.xml"); + + t_bouquet_id bid = 0; + + if (filter_parser != NULL) { - xmlDocPtr filter_parser = parseXmlFile("/var/tuxbox/config/mybouquets.xml"); + dprintf("Reading Bouquet Filters\n"); - t_bouquet_id bid = 0; + xmlNodePtr mybouquets = xmlDocGetRootElement(filter_parser); + mybouquets = mybouquets->xmlChildrenNode; - if (filter_parser != NULL) - { - dprintf("Reading Bouquet Filters\n"); + while ((xmlGetNextOccurence(mybouquets, "filter") != NULL) || + (xmlGetNextOccurence(mybouquets, "adder") != NULL)) { + if (strcmp(xmlGetName(mybouquets), "filter") == 0) { + if (xmlGetNumericAttribute(mybouquets, "is_whitelist", 10) == 1) + bouquet_filter_is_whitelist = true; + xmlNodePtr filter = mybouquets->xmlChildrenNode; - xmlNodePtr mybouquets = xmlDocGetRootElement(filter_parser); - mybouquets = mybouquets->xmlChildrenNode; + while (filter) { - while ((xmlGetNextOccurence(mybouquets, "filter") != NULL) || - (xmlGetNextOccurence(mybouquets, "adder") != NULL)) { - if (strcmp(xmlGetName(mybouquets), "filter") == 0) { - if (xmlGetNumericAttribute(mybouquets, "is_whitelist", 10) == 1) - bouquet_filter_is_whitelist = true; - xmlNodePtr filter = mybouquets->xmlChildrenNode; + bid = xmlGetNumericAttribute(filter, "bouquet_id", 16); - while (filter) { + addBouquetFilter(bid); - bid = xmlGetNumericAttribute(filter, "bouquet_id", 16); - - addBouquetFilter(bid); - - filter = filter->xmlNextNode; - } + filter = filter->xmlNextNode; } - if (strcmp(xmlGetName(mybouquets), "adder") == 0) { - if (mybouquets->xmlChildrenNode) - { - BouquetAdder *bouquet = new BouquetAdder; - snprintf(bouquet->BouquetName, MAX_SIZE_MYBOUQUETS_STR, - xmlGetAttribute(mybouquets, "name")); - bouquet->bid = xmlGetNumericAttribute(mybouquets, "bouquet_id", 16); - bouquet->bae = NULL; - bouquet->next = CurrentBouquetAdder; - CurrentBouquetAdder = bouquet; - xmlNodePtr entry = mybouquets->xmlChildrenNode; - while (entry) { - BouquetAdderEntry *adderentry = new BouquetAdderEntry; - snprintf(adderentry->ProviderName, MAX_SIZE_MYBOUQUETS_STR, - xmlGetAttribute(entry, "provider")); - adderentry->onid = - xmlGetNumericAttribute(entry, "onid", 16); - adderentry->tsid = - xmlGetNumericAttribute(entry, "tsid", 16); - adderentry->es = NULL; - adderentry->next = bouquet->bae; - bouquet->bae = adderentry; - if (entry->xmlChildrenNode) - { - xmlNodePtr excepts = entry->xmlChildrenNode; - while (excepts) { - ExceptService *eservice = new - ExceptService; - eservice->sid = - xmlGetNumericAttribute(entry, - "service_id", 16); - eservice->next = adderentry->es; - adderentry->es = eservice; - excepts = excepts->xmlNextNode; - } - } - entry = entry->xmlNextNode; - } - } - } - mybouquets = mybouquets->xmlNextNode; } - if (CurrentBouquetAdder) { - BouquetAdder *bouquet; - bouquet = CurrentBouquetAdder; - while (bouquet) { - dprintf("New Automatic Bouquet: Name:%s BouquetID:0x%04x\n", + if (strcmp(xmlGetName(mybouquets), "adder") == 0) { + if (mybouquets->xmlChildrenNode) + { + BouquetAdder *bouquet = new BouquetAdder; + snprintf(bouquet->BouquetName, MAX_SIZE_MYBOUQUETS_STR, + xmlGetAttribute(mybouquets, "name")); + bouquet->bid = xmlGetNumericAttribute(mybouquets, "bouquet_id", 16); + bouquet->bae = NULL; + bouquet->next = CurrentBouquetAdder; + CurrentBouquetAdder = bouquet; + xmlNodePtr entry = mybouquets->xmlChildrenNode; + while (entry) { + BouquetAdderEntry *adderentry = new BouquetAdderEntry; + snprintf(adderentry->ProviderName, MAX_SIZE_MYBOUQUETS_STR, + xmlGetAttribute(entry, "provider")); + adderentry->onid = + xmlGetNumericAttribute(entry, "onid", 16); + adderentry->tsid = + xmlGetNumericAttribute(entry, "tsid", 16); + adderentry->es = NULL; + adderentry->next = bouquet->bae; + bouquet->bae = adderentry; + if (entry->xmlChildrenNode) + { + xmlNodePtr excepts = entry->xmlChildrenNode; + while (excepts) { + ExceptService *eservice = new + ExceptService; + eservice->sid = + xmlGetNumericAttribute(entry, + "service_id", 16); + eservice->next = adderentry->es; + adderentry->es = eservice; + excepts = excepts->xmlNextNode; + } + } + entry = entry->xmlNextNode; + } + } + } + mybouquets = mybouquets->xmlNextNode; + } + if (CurrentBouquetAdder) { + BouquetAdder *bouquet; + bouquet = CurrentBouquetAdder; + while (bouquet) { + dprintf("New Automatic Bouquet: Name:%s BouquetID:0x%04x\n", bouquet->BouquetName, bouquet->bid); - BouquetAdderEntry *currententry; - currententry = bouquet->bae; - while (currententry) { - dprintf("Entry found: Provider:%s ONID:0x%04x TSID:0x%04x\n", + BouquetAdderEntry *currententry; + currententry = bouquet->bae; + while (currententry) { + dprintf("Entry found: Provider:%s ONID:0x%04x TSID:0x%04x\n", currententry->ProviderName, currententry->onid, currententry->tsid); - currententry = currententry->next; - } - bouquet = bouquet->next; + currententry = currententry->next; } + bouquet = bouquet->next; } } - xmlFreeDoc(filter_parser); } + xmlFreeDoc(filter_parser); +} - static void printHelp(void) - { - printf("\nUsage: sectionsd [-d][-nu]\n\n"); - } +static void printHelp(void) +{ + printf("\nUsage: sectionsd [-d][-nu]\n\n"); +} // Just to get our listen socket closed cleanly - static void signalHandler(int signum) +static void signalHandler(int signum) +{ + switch (signum) { - switch (signum) - { case SIGHUP: break; default: exit(0); - } } +} #define GETENVI(var) \ env = getenv("SD_"#var); \ @@ -8734,767 +8734,312 @@ static void *cnThread(void *) } else fprintf(stderr, "GETENVS("#var") failed\n"); #endif //int main(int argc, char **argv) - extern cDemux * dmxUTC; +extern cDemux * dmxUTC; - void sectionsd_main_thread(void */*data*/) +void sectionsd_main_thread(void */*data*/) +{ + pthread_t threadTOT, threadEIT, threadCN, threadHouseKeeping; +#ifdef UPDATE_NETWORKS + pthread_t threadSDT, threadNIT; +#endif +#ifdef ENABLE_FREESATEPG + pthread_t threadFSEIT; +#endif +#ifdef ENABLE_PPT + pthread_t threadPPT; +#endif + int rc; + + struct sched_param parm; + + printf("$Id: sectionsd.cpp,v 1.305 2009/07/30 12:41:39 seife Exp $\n"); + /* "export NO_SLOW_ADDEVENT=true" to disable this */ + slow_addevent = (getenv("NO_SLOW_ADDEVENT") == NULL); + if (slow_addevent) + printf("====> USING SLOW ADDEVENT. export 'NO_SLOW_ADDEVENT=1' to avoid <===\n"); + + /* for debugging / benchmarking, "export STARTUP_WAIT=true" to wait with startup for + * the EPG loading to finish + * this wil fail badly if no EPG saving / loading is configured! */ + reader_ready = (getenv("STARTUP_WAIT") == NULL); + if (!reader_ready) + printf("====> sectionsd waiting with startup until saved EPG is read <===\n"); + + SIlanguage::loadLanguages(); + + tzset(); // TZ auswerten + + CBasicServer sectionsd_server; + + //NTP-Config laden + if (!ntp_config.loadConfig(CONF_FILE)) { - pthread_t threadTOT, threadEIT, threadCN, threadHouseKeeping; -#ifdef UPDATE_NETWORKS - pthread_t threadSDT, threadNIT; -#endif -#ifdef ENABLE_FREESATEPG - pthread_t threadFSEIT; -#endif -#ifdef ENABLE_PPT - pthread_t threadPPT; -#endif - int rc; + /* set defaults if no configuration file exists */ + printf("[sectionsd] %s not found\n", CONF_FILE); + } - struct sched_param parm; + ntpserver = ntp_config.getString("network_ntpserver", "de.pool.ntp.org"); + ntprefresh = atoi(ntp_config.getString("network_ntprefresh","30").c_str() ); + ntpenable = ntp_config.getBool("network_ntpenable", false); + ntp_system_cmd = ntp_system_cmd_prefix + ntpserver; - printf("$Id: sectionsd.cpp,v 1.305 2009/07/30 12:41:39 seife Exp $\n"); - /* "export NO_SLOW_ADDEVENT=true" to disable this */ - slow_addevent = (getenv("NO_SLOW_ADDEVENT") == NULL); - if (slow_addevent) - printf("====> USING SLOW ADDEVENT. export 'NO_SLOW_ADDEVENT=1' to avoid <===\n"); + //EPG Einstellungen laden + secondsToCache = (atoi(ntp_config.getString("epg_cache_time","14").c_str() ) *24*60L*60L); //Tage + secondsExtendedTextCache = (atoi(ntp_config.getString("epg_extendedcache_time","360").c_str() ) *60L*60L); //Stunden + oldEventsAre = (atoi(ntp_config.getString("epg_old_events","1").c_str() ) *60L*60L); //Stunden + max_events= atoi(ntp_config.getString("epg_max_events","50000").c_str() ); - /* for debugging / benchmarking, "export STARTUP_WAIT=true" to wait with startup for - * the EPG loading to finish - * this wil fail badly if no EPG saving / loading is configured! */ - reader_ready = (getenv("STARTUP_WAIT") == NULL); - if (!reader_ready) - printf("====> sectionsd waiting with startup until saved EPG is read <===\n"); + printf("[sectionsd] Caching max %d events\n", max_events); + printf("[sectionsd] Caching %ld days\n", secondsToCache / (24*60*60L)); + printf("[sectionsd] Caching %ld hours Extended Text\n", secondsExtendedTextCache / (60*60L)); + printf("[sectionsd] Events are old %ldmin after their end time\n", oldEventsAre / 60); - SIlanguage::loadLanguages(); - - tzset(); // TZ auswerten - - CBasicServer sectionsd_server; - - //NTP-Config laden - if (!ntp_config.loadConfig(CONF_FILE)) - { - /* set defaults if no configuration file exists */ - printf("[sectionsd] %s not found\n", CONF_FILE); - } - - ntpserver = ntp_config.getString("network_ntpserver", "de.pool.ntp.org"); - ntprefresh = atoi(ntp_config.getString("network_ntprefresh","30").c_str() ); - ntpenable = ntp_config.getBool("network_ntpenable", false); - ntp_system_cmd = ntp_system_cmd_prefix + ntpserver; - - //EPG Einstellungen laden - secondsToCache = (atoi(ntp_config.getString("epg_cache_time","14").c_str() ) *24*60L*60L); //Tage - secondsExtendedTextCache = (atoi(ntp_config.getString("epg_extendedcache_time","360").c_str() ) *60L*60L); //Stunden - oldEventsAre = (atoi(ntp_config.getString("epg_old_events","1").c_str() ) *60L*60L); //Stunden - max_events= atoi(ntp_config.getString("epg_max_events","50000").c_str() ); - - printf("[sectionsd] Caching max %d events\n", max_events); - printf("[sectionsd] Caching %ld days\n", secondsToCache / (24*60*60L)); - printf("[sectionsd] Caching %ld hours Extended Text\n", secondsExtendedTextCache / (60*60L)); - printf("[sectionsd] Events are old %ldmin after their end time\n", oldEventsAre / 60); - - readEPGFilter(); - readDVBTimeFilter(); + readEPGFilter(); + readDVBTimeFilter(); #if 0 - readBouquetFilter(); + readBouquetFilter(); #endif - readEncodingFile(); - - if (!sectionsd_server.prepare(SECTIONSD_UDS_NAME)) { - fprintf(stderr, "[sectionsd] failed to prepare basic server\n"); - return; - } - // from here on forked - //signal(SIGHUP, signalHandler); - eventServer = new CEventServer; - - // time-Thread starten - rc = pthread_create(&threadTOT, 0, timeThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create time-thread (rc=%d)\n", rc); - return; - } - - // EIT-Thread starten - rc = pthread_create(&threadEIT, 0, eitThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create eit-thread (rc=%d)\n", rc); - return; - } - - // EIT-Thread2 starten - rc = pthread_create(&threadCN, 0, cnThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create eit-thread (rc=%d)\n", rc); - return; - } - -#ifdef ENABLE_FREESATEPG - // EIT-Thread3 starten - rc = pthread_create(&threadFSEIT, 0, fseitThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create fseit-thread (rc=%d)\n", rc); - return; - } -#endif - -#ifdef ENABLE_PPT - // premiere private epg -Thread starten - rc = pthread_create(&threadPPT, 0, pptThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create ppt-thread (rc=%d)\n", rc); - return; - } -#endif -#ifdef UPDATE_NETWORKS - // NIT-Thread starten - rc = pthread_create(&threadNIT, 0, nitThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create nit-thread (rc=%d)\n", rc); - return; - } - // SDT-Thread starten - rc = pthread_create(&threadSDT, 0, sdtThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create sdt-thread (rc=%d)\n", rc); - return; - } -#endif - - // housekeeping-Thread starten - rc = pthread_create(&threadHouseKeeping, 0, houseKeepingThread, 0); - - if (rc) { - fprintf(stderr, "[sectionsd] failed to create housekeeping-thread (rc=%d)\n", rc); - return; - } - - if (sections_debug) { - int policy; - rc = pthread_getschedparam(pthread_self(), &policy, &parm); - dprintf("mainloop getschedparam %d policy %d prio %d\n", rc, policy, parm.sched_priority); - } - sectionsd_ready = true; - - while (sectionsd_server.run(sectionsd_parse_command, sectionsd::ACTVERSION, true)) { - sched_yield(); - if (eit_update_fd != -1) { - unsigned char buf[4096]; - int ret = eitDmx->Read(buf, 4095, 10); - - if (ret > 0) { - //printf("[sectionsd] EIT update: len %d, %02X %02X %02X %02X %02X %02X version %02X\n", ret, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], ((SI_section_header*)buf)->version_number); - - printdate_ms(stdout); - printf("EIT Update Filter: new version 0x%x, Activate cnThread\n", ((SI_section_header*)buf)->version_number); - writeLockMessaging(); - // messaging_skipped_sections_ID[0].clear(); - // messaging_sections_max_ID[0] = -1; - // messaging_sections_got_all[0] = false; - messaging_have_CN = 0x00; - messaging_got_CN = 0x00; - messaging_last_requested = time_monotonic(); - unlockMessaging(); - sched_yield(); - dmxCN.change(0); - sched_yield(); - } - } - if(sectionsd_stop) - break; - - sched_yield(); - /* 10 ms is the minimal timeslice anyway (HZ = 100), so let's - wait 20 ms at least to lower the CPU load */ - usleep(20000); - } - - printf("[sectionsd] stopping...\n"); - scanning = 0; - timeset = true; - printf("broadcasting...\n"); - pthread_mutex_lock(&timeIsSetMutex); - pthread_cond_broadcast(&timeIsSetCond); - pthread_mutex_unlock(&timeIsSetMutex); - pthread_mutex_lock(&timeThreadSleepMutex); - pthread_cond_broadcast(&timeThreadSleepCond); - pthread_mutex_unlock(&timeThreadSleepMutex); - pthread_mutex_lock(&dmxEIT.start_stop_mutex); - pthread_cond_broadcast(&dmxEIT.change_cond); - pthread_mutex_unlock(&dmxEIT.start_stop_mutex); - pthread_mutex_lock(&dmxCN.start_stop_mutex); - pthread_cond_broadcast(&dmxCN.change_cond); - pthread_mutex_unlock(&dmxCN.start_stop_mutex); -#ifdef ENABLE_PPT - pthread_mutex_lock(&dmxPPT.start_stop_mutex); - pthread_cond_broadcast(&dmxPPT.change_cond); - pthread_mutex_unlock(&dmxPPT.start_stop_mutex); -#endif -#ifdef UPDATE_NETWORKS - pthread_mutex_lock(&dmxSDT.start_stop_mutex); - pthread_cond_broadcast(&dmxSDT.change_cond); - pthread_mutex_unlock(&dmxSDT.start_stop_mutex); -#endif - printf("pausing...\n"); - dmxEIT.request_pause(); - dmxCN.request_pause(); -#ifdef ENABLE_PPT - dmxPPT.request_pause(); -#endif -#ifdef ENABLE_FREESATEPG - dmxFSEIT.request_pause(); -#endif -#ifdef UPDATE_NETWORKS - dmxSDT.request_pause(); - dmxNIT.request_pause(); -#endif - pthread_cancel(threadHouseKeeping); - - if(dmxUTC) dmxUTC->Stop(); - - pthread_cancel(threadTOT); - - printf("join 1\n"); - pthread_join(threadTOT, NULL); - if(dmxUTC) delete dmxUTC; - printf("join 2\n"); - pthread_join(threadEIT, NULL); - printf("join 3\n"); - pthread_join(threadCN, NULL); -#ifdef ENABLE_PPT - printf("join 3\n"); - pthread_join(threadPPT, NULL); -#endif -#ifdef UPDATE_NETWORKS - printf("join 4\n"); - pthread_join(threadSDT, NULL); -#endif - - eit_stop_update_filter(&eit_update_fd); - if(eitDmx) - delete eitDmx; - - printf("close 1\n"); - dmxEIT.close(); - printf("close 3\n"); - dmxCN.close(); -#ifdef ENABLE_FREESATEPG - dmxFSEIT.close(); -#endif -#ifdef ENABLE_PPT - dmxPPT.close(); -#endif -#ifdef UPDATE_NETWORKS - dmxSDT.close(); - dmxNIT.close(); -#endif - - printf("[sectionsd] ended\n"); + readEncodingFile(); + if (!sectionsd_server.prepare(SECTIONSD_UDS_NAME)) { + fprintf(stderr, "[sectionsd] failed to prepare basic server\n"); return; } - /* was: commandAllEventsChannelID sendAllEvents */ - void sectionsd_getEventsServiceKey(t_channel_id serviceUniqueKey, CChannelEventList &eList, char search = 0, std::string search_text = "") - { - dprintf("sendAllEvents for " PRINTF_CHANNEL_ID_TYPE "\n", serviceUniqueKey); + // from here on forked + //signal(SIGHUP, signalHandler); + eventServer = new CEventServer; - if ((serviceUniqueKey& 0xFFFFFFFFFFFFULL) != 0) { //0xFFFFFFFFFFFFULL for CREATE_CHANNEL_ID64 - // service Found - readLockEvents(); - int serviceIDfound = 0; + // time-Thread starten + rc = pthread_create(&threadTOT, 0, timeThread, 0); - if (search_text.length()) std::transform(search_text.begin(), search_text.end(), search_text.begin(), tolower); - for (MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end(); ++e) - { - if ((*e)->get_channel_id() == (serviceUniqueKey& 0xFFFFFFFFFFFFULL)) { //0xFFFFFFFFFFFFULL for CREATE_CHANNEL_ID64 - serviceIDfound = 1; - - bool copy = true; - if(search == 0); // nothing to do here - else if(search == 1) { - std::string eName = (*e)->getName(); - std::transform(eName.begin(), eName.end(), eName.begin(), tolower); - if(eName.find(search_text) == std::string::npos) - copy = false; - } - else if(search == 2) { - std::string eText = (*e)->getText(); - std::transform(eText.begin(), eText.end(), eText.begin(), tolower); - if(eText.find(search_text) == std::string::npos) - copy = false; - } - else if(search == 3) { - std::string eExtendedText = (*e)->getExtendedText(); - std::transform(eExtendedText.begin(), eExtendedText.end(), eExtendedText.begin(), tolower); - if(eExtendedText.find(search_text) == std::string::npos) - copy = false; - } - - if(copy) { - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) - { - CChannelEvent aEvent; - aEvent.eventID = (*e)->uniqueKey(); - aEvent.startTime = t->startzeit; - aEvent.duration = t->dauer; - aEvent.description = (*e)->getName(); - if (((*e)->getText()).empty()) - aEvent.text = (*e)->getExtendedText().substr(0, 120); - else - aEvent.text = (*e)->getText(); - aEvent.channelID = serviceUniqueKey; - eList.push_back(aEvent); - } - } // if = serviceID - } - else if ( serviceIDfound ) - break; // sind nach serviceID und startzeit sortiert -> nicht weiter suchen - } - - unlockEvents(); - } - } - /* was: commandCurrentNextInfoChannelID */ - void sectionsd_getCurrentNextServiceKey(t_channel_id uniqueServiceKey, CSectionsdClient::responseGetCurrentNextInfoChannelID& current_next ) - { - dprintf("[sectionsd] Request of current/next information for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); - - SIevent currentEvt; - SIevent nextEvt; - unsigned flag = 0, flag2=0; - /* ugly hack: retry fetching current/next by restarting dmxCN if this is true */ - bool change = false; - - //t_channel_id * uniqueServiceKey = (t_channel_id *)data; - - readLockEvents(); - /* if the currently running program is requested... */ - if (uniqueServiceKey == messaging_current_servicekey) { - /* ...check for myCurrentEvent and myNextEvent */ - if (!myCurrentEvent) { - dprintf("!myCurrentEvent "); - change = true; - flag |= CSectionsdClient::epgflags::not_broadcast; - } else { - currentEvt = *myCurrentEvent; - flag |= CSectionsdClient::epgflags::has_current; // aktuelles event da... - flag |= CSectionsdClient::epgflags::has_anything; - } - if (!myNextEvent) { - dprintf("!myNextEvent "); - change = true; - } else { - nextEvt = *myNextEvent; - if (flag & CSectionsdClient::epgflags::not_broadcast) { - dprintf("CSectionsdClient::epgflags::has_no_current\n"); - flag = CSectionsdClient::epgflags::has_no_current; - } - flag |= CSectionsdClient::epgflags::has_next; // aktuelles event da... - flag |= CSectionsdClient::epgflags::has_anything; - } - } - - //dprintf("flag: 0x%x, has_current: 0x%x has_next: 0x%x\n", flag, CSectionsdClient::epgflags::has_current, CSectionsdClient::epgflags::has_next); - /* if another than the currently running program is requested, then flag will still be 0 - if either the current or the next event is not found, this condition will be true, too. - */ - if ((flag & (CSectionsdClient::epgflags::has_current|CSectionsdClient::epgflags::has_next)) != - (CSectionsdClient::epgflags::has_current|CSectionsdClient::epgflags::has_next)) { - //dprintf("commandCurrentNextInfoChannelID: current or next missing!\n"); - SItime zeitEvt1(0, 0); - if (!(flag & CSectionsdClient::epgflags::has_current)) { - currentEvt = findActualSIeventForServiceUniqueKey(uniqueServiceKey, zeitEvt1, 0, &flag2); - } else { - zeitEvt1.startzeit = currentEvt.times.begin()->startzeit; - zeitEvt1.dauer = currentEvt.times.begin()->dauer; - } - SItime zeitEvt2(zeitEvt1); - - if (currentEvt.getName().empty() && flag2 != 0) - { - dprintf("commandCurrentNextInfoChannelID change1\n"); - change = true; - } - - if (currentEvt.service_id != 0) - { //Found - flag &= (CSectionsdClient::epgflags::has_no_current|CSectionsdClient::epgflags::not_broadcast)^(unsigned)-1; - flag |= CSectionsdClient::epgflags::has_current; - flag |= CSectionsdClient::epgflags::has_anything; - dprintf("[sectionsd] current EPG found. service_id: %x, flag: 0x%x\n",currentEvt.service_id, flag); - - if (!(flag & CSectionsdClient::epgflags::has_next)) { - dprintf("*nextEvt not from cur/next V1!\n"); - nextEvt = findNextSIevent(currentEvt.uniqueKey(), zeitEvt2); - } - } - else - { // no current event... - readLockServices(); - - MySIservicesOrderUniqueKey::iterator si = mySIservicesOrderUniqueKey.end(); - si = mySIservicesOrderUniqueKey.find(uniqueServiceKey); - - if (si != mySIservicesOrderUniqueKey.end()) - { - dprintf("[sectionsd] current service has%s scheduled events, and has%s present/following events\n", si->second->eitScheduleFlag() ? "" : " no", si->second->eitPresentFollowingFlag() ? "" : " no" ); - - if ( /*( !si->second->eitScheduleFlag() ) || */ - ( !si->second->eitPresentFollowingFlag() ) ) - { - flag |= CSectionsdClient::epgflags::not_broadcast; - } - } - unlockServices(); - - if ( flag2 & CSectionsdClient::epgflags::has_anything ) - { - flag |= CSectionsdClient::epgflags::has_anything; - if (!(flag & CSectionsdClient::epgflags::has_next)) { - dprintf("*nextEvt not from cur/next V2!\n"); - nextEvt = findNextSIeventForServiceUniqueKey(uniqueServiceKey, zeitEvt2); - } - - if (nextEvt.service_id != 0) - { - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueServiceKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - // this is a race condition if first entry found is == mySIeventsOrderUniqueKey.begin() - // so perform a check - if (eFirst != mySIeventsOrderUniqueKey.begin()) - --eFirst; - - if (eFirst != mySIeventsOrderUniqueKey.begin()) - { - time_t azeit = time(NULL); - - if (eFirst->second->times.begin()->startzeit < azeit && - eFirst->second->uniqueKey() == nextEvt.uniqueKey() - 1) - flag |= CSectionsdClient::epgflags::has_no_current; - } - } - } - } - } - if (nextEvt.service_id != 0) - { - flag &= CSectionsdClient::epgflags::not_broadcast^(unsigned)-1; - dprintf("[sectionsd] next EPG found. service_id: %x, flag: 0x%x\n",nextEvt.service_id, flag); - flag |= CSectionsdClient::epgflags::has_next; - } - else if (flag != 0) - { - dprintf("commandCurrentNextInfoChannelID change2 flag: 0x%02x\n", flag); - change = true; - } - } - - if (currentEvt.service_id != 0) - { - /* check for nvod linkage */ - for (unsigned int i = 0; i < currentEvt.linkage_descs.size(); i++) - if (currentEvt.linkage_descs[i].linkageType == 0xB0) - { - fprintf(stderr,"[sectionsd] linkage in current EPG found.\n"); - flag |= CSectionsdClient::epgflags::current_has_linkagedescriptors; - break; - } - } else - flag |= CSectionsdClient::epgflags::has_no_current; - - time_t now; - - dprintf("currentEvt: '%s' (%04x) nextEvt: '%s' (%04x) flag: 0x%02x\n", - currentEvt.getName().c_str(), currentEvt.eventID, - nextEvt.getName().c_str(), nextEvt.eventID, flag); - - CSectionsdClient::sectionsdTime time_cur; - CSectionsdClient::sectionsdTime time_nxt; - now = time(NULL); - time_cur.startzeit = currentEvt.times.begin()->startzeit; - time_cur.dauer = currentEvt.times.begin()->dauer; - time_nxt.startzeit = nextEvt.times.begin()->startzeit; - time_nxt.dauer = nextEvt.times.begin()->dauer; - /* for nvod events that have multiple times, find the one that matches the current time... */ - if (currentEvt.times.size() > 1) { - for (SItimes::iterator t = currentEvt.times.begin(); t != currentEvt.times.end(); ++t) { - if ((long)now < (long)(t->startzeit + t->dauer) && (long)now > (long)t->startzeit) { - time_cur.startzeit = t->startzeit; - time_cur.dauer =t->dauer; - break; - } - } - } - /* ...and the one after that. */ - if (nextEvt.times.size() > 1) { - for (SItimes::iterator t = nextEvt.times.begin(); t != nextEvt.times.end(); ++t) { - if ((long)(time_cur.startzeit + time_cur.dauer) <= (long)(t->startzeit)) { // TODO: it's not "long", it's "time_t" - time_nxt.startzeit = t->startzeit; - time_nxt.dauer =t->dauer; - break; - } - } - } - - current_next.current_uniqueKey = currentEvt.uniqueKey(); - current_next.current_zeit.startzeit = time_cur.startzeit; - current_next.current_zeit.dauer = time_cur.dauer; - current_next.current_name = currentEvt.getName(); - - current_next.next_uniqueKey = nextEvt.uniqueKey(); - current_next.next_zeit.startzeit = time_nxt.startzeit; - current_next.next_zeit.dauer = time_nxt.dauer; - current_next.next_name = nextEvt.getName(); - - current_next.flags = flag; - current_next.current_fsk = currentEvt.getFSK(); - - unlockEvents(); - - //dprintf("change: %s, messaging_eit_busy: %s, last_request: %d\n", change?"true":"false", messaging_eit_is_busy?"true":"false",(time_monotonic() - messaging_last_requested)); - if (change && !messaging_eit_is_busy && (time_monotonic() - messaging_last_requested) < 11) { - /* restart dmxCN, but only if it is not already running, and only for 10 seconds */ - dprintf("change && !messaging_eit_is_busy => dmxCN.change(0)\n"); - dmxCN.change(0); - } - } - /* commandEPGepgIDshort */ - bool sectionsd_getEPGidShort(event_id_t epgID, CShortEPGData * epgdata) - { - bool ret = false; - dprintf("Request of current EPG for 0x%llx\n", epgID); - - readLockEvents(); - - const SIevent& e = findSIeventForEventUniqueKey(epgID); - - if (e.service_id != 0) - { // Event found - dputs("EPG found."); - epgdata->title = e.getName(); - epgdata->info1 = e.getText(); - epgdata->info2 = e.getExtendedText(); - ret = true; - } else - dputs("EPG not found!"); - - unlockEvents(); - return ret; + if (rc) { + fprintf(stderr, "[sectionsd] failed to create time-thread (rc=%d)\n", rc); + return; } -#if 0 - char * parseExtendedEvents(char * dp, CEPGData * epgdata) { - char * pItemDescriptions = dp, * pItemDescriptionStart; - dp+=strlen(dp)+1; - char * pItems = dp, * pItemStart; - dp+=strlen(dp)+1; - /* Clear vector since epgdata seems to be reused */ - epgdata->itemDescriptions.clear(); - while (*pItemDescriptions) { - pItemDescriptionStart = pItemDescriptions; - while (*pItemDescriptions && '\n' != *pItemDescriptions) { - pItemDescriptions++; - } - char pp = *pItemDescriptions; - *pItemDescriptions = 0; - epgdata->itemDescriptions.push_back(pItemDescriptionStart); - /*printf("CSectionsdClient::parseExtendedEvents: desc %s\n", pItemDescriptionStart);*/ - if(!pp) - break; - pItemDescriptions++; - } - /* Clear vector since epgdata seems to be reused */ - epgdata->items.clear(); - while (*pItems) { - pItemStart = pItems; - while (*pItems && '\n' != *pItems) { - pItems++; - } - char pp = *pItemDescriptions; - *pItems = 0; - epgdata->items.push_back(pItemStart); - /*printf("CSectionsdClient::parseExtendedEvents: item %s\n", pItemStart);*/ - if(!pp) - break; - pItems++; - } - return dp; + // EIT-Thread starten + rc = pthread_create(&threadEIT, 0, eitThread, 0); + + if (rc) { + fprintf(stderr, "[sectionsd] failed to create eit-thread (rc=%d)\n", rc); + return; + } + + // EIT-Thread2 starten + rc = pthread_create(&threadCN, 0, cnThread, 0); + + if (rc) { + fprintf(stderr, "[sectionsd] failed to create eit-thread (rc=%d)\n", rc); + return; + } + +#ifdef ENABLE_FREESATEPG + // EIT-Thread3 starten + rc = pthread_create(&threadFSEIT, 0, fseitThread, 0); + + if (rc) { + fprintf(stderr, "[sectionsd] failed to create fseit-thread (rc=%d)\n", rc); + return; } #endif - /*was getEPGid commandEPGepgID(int connfd, char *data, const unsigned dataLength) */ - bool sectionsd_getEPGid(const event_id_t epgID, const time_t startzeit, CEPGData * epgdata) - { - bool ret = false; - dprintf("Request of actual EPG for 0x%llx 0x%lx\n", epgID, startzeit); +#ifdef ENABLE_PPT + // premiere private epg -Thread starten + rc = pthread_create(&threadPPT, 0, pptThread, 0); - const SIevent& evt = findSIeventForEventUniqueKey(epgID); - - epgdata->itemDescriptions.clear(); - epgdata->items.clear(); - - readLockEvents(); - if (evt.service_id != 0) { // Event found - SItimes::iterator t = evt.times.begin(); - - for (; t != evt.times.end(); ++t) - if (t->startzeit == startzeit) - break; - - if (t == evt.times.end()) { - dputs("EPG not found!"); - } else { - dputs("EPG found."); - epgdata->eventID = evt.uniqueKey(); - epgdata->title = evt.getName(); - epgdata->info1 = evt.getText(); - epgdata->info2 = evt.getExtendedText(); - /* FIXME printf("itemDescription: %s\n", evt.itemDescription.c_str()); */ - epgdata->contentClassification = std::string(evt.contentClassification.data(), evt.contentClassification.length()); - epgdata->userClassification = std::string(evt.userClassification.data(), evt.userClassification.length()); - epgdata->fsk = evt.getFSK(); - epgdata->table_id = evt.table_id; - - epgdata->epg_times.startzeit = t->startzeit; - epgdata->epg_times.dauer = t->dauer; - - ret = true; - } - } else { - dputs("EPG not found!"); - } - unlockEvents(); - return ret; + if (rc) { + fprintf(stderr, "[sectionsd] failed to create ppt-thread (rc=%d)\n", rc); + return; } - /* was commandActualEPGchannelID(int connfd, char *data, const unsigned dataLength) */ - bool sectionsd_getActualEPGServiceKey(const t_channel_id uniqueServiceKey, CEPGData * epgdata) - { - bool ret = false; - SIevent evt; - SItime zeit(0, 0); +#endif +#ifdef UPDATE_NETWORKS + // NIT-Thread starten + rc = pthread_create(&threadNIT, 0, nitThread, 0); - dprintf("[commandActualEPGchannelID] Request of current EPG for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); + if (rc) { + fprintf(stderr, "[sectionsd] failed to create nit-thread (rc=%d)\n", rc); + return; + } + // SDT-Thread starten + rc = pthread_create(&threadSDT, 0, sdtThread, 0); - readLockEvents(); - if (uniqueServiceKey == messaging_current_servicekey) { - if (myCurrentEvent) { - evt = *myCurrentEvent; - zeit.startzeit = evt.times.begin()->startzeit; - zeit.dauer = evt.times.begin()->dauer; - if (evt.times.size() > 1) { - time_t now = time(NULL); - for (SItimes::iterator t = evt.times.begin(); t != evt.times.end(); ++t) { - if ((long)now < (long)(t->startzeit + t->dauer) && (long)now > (long)t->startzeit) { - zeit.startzeit = t->startzeit; - zeit.dauer = t->dauer; - break; - } - } - } + if (rc) { + fprintf(stderr, "[sectionsd] failed to create sdt-thread (rc=%d)\n", rc); + return; + } +#endif + + // housekeeping-Thread starten + rc = pthread_create(&threadHouseKeeping, 0, houseKeepingThread, 0); + + if (rc) { + fprintf(stderr, "[sectionsd] failed to create housekeeping-thread (rc=%d)\n", rc); + return; + } + + if (sections_debug) { + int policy; + rc = pthread_getschedparam(pthread_self(), &policy, &parm); + dprintf("mainloop getschedparam %d policy %d prio %d\n", rc, policy, parm.sched_priority); + } + sectionsd_ready = true; + + while (sectionsd_server.run(sectionsd_parse_command, sectionsd::ACTVERSION, true)) { + sched_yield(); + if (eit_update_fd != -1) { + unsigned char buf[4096]; + int ret = eitDmx->Read(buf, 4095, 10); + + if (ret > 0) { + //printf("[sectionsd] EIT update: len %d, %02X %02X %02X %02X %02X %02X version %02X\n", ret, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], ((SI_section_header*)buf)->version_number); + + printdate_ms(stdout); + printf("EIT Update Filter: new version 0x%x, Activate cnThread\n", ((SI_section_header*)buf)->version_number); + writeLockMessaging(); + // messaging_skipped_sections_ID[0].clear(); + // messaging_sections_max_ID[0] = -1; + // messaging_sections_got_all[0] = false; + messaging_have_CN = 0x00; + messaging_got_CN = 0x00; + messaging_last_requested = time_monotonic(); + unlockMessaging(); + sched_yield(); + dmxCN.change(0); + sched_yield(); } } + if(sectionsd_stop) + break; - if (evt.service_id == 0) - { - dprintf("[commandActualEPGchannelID] evt.service_id == 0 ==> no myCurrentEvent!\n"); - evt = findActualSIeventForServiceUniqueKey(uniqueServiceKey, zeit); - } - - if (evt.service_id != 0) - { - dprintf("EPG found.\n"); - epgdata->eventID = evt.uniqueKey(); - epgdata->title = evt.getName(); - epgdata->info1 = evt.getText(); - epgdata->info2 = evt.getExtendedText(); - /* FIXME printf("itemDescription: %s\n", evt.itemDescription.c_str());*/ - epgdata->contentClassification = std::string(evt.contentClassification.data(), evt.contentClassification.length()); - epgdata->userClassification = std::string(evt.userClassification.data(), evt.userClassification.length()); - epgdata->fsk = evt.getFSK(); - epgdata->table_id = evt.table_id; - - epgdata->epg_times.startzeit = zeit.startzeit; - epgdata->epg_times.dauer = zeit.dauer; - - ret = true; - } else - dprintf("EPG not found!\n"); - - unlockEvents(); - return ret; + sched_yield(); + /* 10 ms is the minimal timeslice anyway (HZ = 100), so let's + wait 20 ms at least to lower the CPU load */ + usleep(20000); } - /* was static void sendEventList(int connfd, const unsigned char serviceTyp1, const unsigned char serviceTyp2 = 0, int sendServiceName = 1, t_channel_id * chidlist = NULL, int clen = 0) */ - void sectionsd_getChannelEvents(CChannelEventList &eList, const bool tv_mode = true, t_channel_id *chidlist = NULL, int clen = 0) - { - unsigned char serviceTyp1, serviceTyp2; - clen = clen / sizeof(t_channel_id); - t_channel_id uniqueNow = 0; - t_channel_id uniqueOld = 0; - bool found_already = false; - time_t azeit = time(NULL); - std::string sname; + printf("[sectionsd] stopping...\n"); + scanning = 0; + timeset = true; + printf("broadcasting...\n"); + pthread_mutex_lock(&timeIsSetMutex); + pthread_cond_broadcast(&timeIsSetCond); + pthread_mutex_unlock(&timeIsSetMutex); + pthread_mutex_lock(&timeThreadSleepMutex); + pthread_cond_broadcast(&timeThreadSleepCond); + pthread_mutex_unlock(&timeThreadSleepMutex); + pthread_mutex_lock(&dmxEIT.start_stop_mutex); + pthread_cond_broadcast(&dmxEIT.change_cond); + pthread_mutex_unlock(&dmxEIT.start_stop_mutex); + pthread_mutex_lock(&dmxCN.start_stop_mutex); + pthread_cond_broadcast(&dmxCN.change_cond); + pthread_mutex_unlock(&dmxCN.start_stop_mutex); +#ifdef ENABLE_PPT + pthread_mutex_lock(&dmxPPT.start_stop_mutex); + pthread_cond_broadcast(&dmxPPT.change_cond); + pthread_mutex_unlock(&dmxPPT.start_stop_mutex); +#endif +#ifdef UPDATE_NETWORKS + pthread_mutex_lock(&dmxSDT.start_stop_mutex); + pthread_cond_broadcast(&dmxSDT.change_cond); + pthread_mutex_unlock(&dmxSDT.start_stop_mutex); +#endif + printf("pausing...\n"); + dmxEIT.request_pause(); + dmxCN.request_pause(); +#ifdef ENABLE_PPT + dmxPPT.request_pause(); +#endif +#ifdef ENABLE_FREESATEPG + dmxFSEIT.request_pause(); +#endif +#ifdef UPDATE_NETWORKS + dmxSDT.request_pause(); + dmxNIT.request_pause(); +#endif + pthread_cancel(threadHouseKeeping); - if(tv_mode) { - serviceTyp1 = 0x01; - serviceTyp2 = 0x04; - } else { - serviceTyp1 = 0x02; - serviceTyp2 = 0x00; - } + if(dmxUTC) dmxUTC->Stop(); + pthread_cancel(threadTOT); + + printf("join 1\n"); + pthread_join(threadTOT, NULL); + if(dmxUTC) delete dmxUTC; + printf("join 2\n"); + pthread_join(threadEIT, NULL); + printf("join 3\n"); + pthread_join(threadCN, NULL); +#ifdef ENABLE_PPT + printf("join 3\n"); + pthread_join(threadPPT, NULL); +#endif +#ifdef UPDATE_NETWORKS + printf("join 4\n"); + pthread_join(threadSDT, NULL); +#endif + + eit_stop_update_filter(&eit_update_fd); + if(eitDmx) + delete eitDmx; + + printf("close 1\n"); + dmxEIT.close(); + printf("close 3\n"); + dmxCN.close(); +#ifdef ENABLE_FREESATEPG + dmxFSEIT.close(); +#endif +#ifdef ENABLE_PPT + dmxPPT.close(); +#endif +#ifdef UPDATE_NETWORKS + dmxSDT.close(); + dmxNIT.close(); +#endif + + printf("[sectionsd] ended\n"); + + return; +} +/* was: commandAllEventsChannelID sendAllEvents */ +void sectionsd_getEventsServiceKey(t_channel_id serviceUniqueKey, CChannelEventList &eList, char search = 0, std::string search_text = "") +{ + dprintf("sendAllEvents for " PRINTF_CHANNEL_ID_TYPE "\n", serviceUniqueKey); + + if ((serviceUniqueKey& 0xFFFFFFFFFFFFULL) != 0) { //0xFFFFFFFFFFFFULL for CREATE_CHANNEL_ID64 + // service Found readLockEvents(); + int serviceIDfound = 0; - /* !!! FIX ME: if the box starts on a channel where there is no EPG sent, it hangs!!! */ + if (search_text.length()) std::transform(search_text.begin(), search_text.end(), search_text.begin(), tolower); for (MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end(); ++e) { - uniqueNow = (*e)->get_channel_id(); - if (!channel_in_requested_list(chidlist, uniqueNow, clen)) continue; - if ( uniqueNow != uniqueOld ) - { - found_already = true; - readLockServices(); - // new service, check service- type - MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.find(uniqueNow); + if ((*e)->get_channel_id() == (serviceUniqueKey& 0xFFFFFFFFFFFFULL)) { //0xFFFFFFFFFFFFULL for CREATE_CHANNEL_ID64 + serviceIDfound = 1; - if (s != mySIservicesOrderUniqueKey.end()) - { - if (s->second->serviceTyp == serviceTyp1 || (serviceTyp2 && s->second->serviceTyp == serviceTyp2)) - { - sname = s->second->serviceName; - found_already = false; - } + bool copy = true; + if(search == 0); // nothing to do here + else if(search == 1) { + std::string eName = (*e)->getName(); + std::transform(eName.begin(), eName.end(), eName.begin(), tolower); + if(eName.find(search_text) == std::string::npos) + copy = false; } - else - { - // wenn noch nie hingetuned wurde, dann gibts keine Info ber den ServiceTyp... - // im Zweifel mitnehmen - found_already = false; + else if(search == 2) { + std::string eText = (*e)->getText(); + std::transform(eText.begin(), eText.end(), eText.begin(), tolower); + if(eText.find(search_text) == std::string::npos) + copy = false; + } + else if(search == 3) { + std::string eExtendedText = (*e)->getExtendedText(); + std::transform(eExtendedText.begin(), eExtendedText.end(), eExtendedText.begin(), tolower); + if(eExtendedText.find(search_text) == std::string::npos) + copy = false; } - unlockServices(); - uniqueOld = uniqueNow; - } - - if ( !found_already ) - { - std::string eName = (*e)->getName(); - std::string eText = (*e)->getText(); - std::string eExtendedText = (*e)->getExtendedText(); - - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) - { - if (t->startzeit <= azeit && azeit <= (long)(t->startzeit + t->dauer)) + if(copy) { + for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) { CChannelEvent aEvent; aEvent.eventID = (*e)->uniqueKey(); @@ -9505,135 +9050,590 @@ static void *cnThread(void *) aEvent.text = (*e)->getExtendedText().substr(0, 120); else aEvent.text = (*e)->getText(); + aEvent.channelID = serviceUniqueKey; eList.push_back(aEvent); + } + } // if = serviceID + } + else if ( serviceIDfound ) + break; // sind nach serviceID und startzeit sortiert -> nicht weiter suchen + } - found_already = true; + unlockEvents(); + } +} +/* was: commandCurrentNextInfoChannelID */ +void sectionsd_getCurrentNextServiceKey(t_channel_id uniqueServiceKey, CSectionsdClient::responseGetCurrentNextInfoChannelID& current_next ) +{ + dprintf("[sectionsd] Request of current/next information for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); + + SIevent currentEvt; + SIevent nextEvt; + unsigned flag = 0, flag2=0; + /* ugly hack: retry fetching current/next by restarting dmxCN if this is true */ + bool change = false; + + //t_channel_id * uniqueServiceKey = (t_channel_id *)data; + + readLockEvents(); + /* if the currently running program is requested... */ + if (uniqueServiceKey == messaging_current_servicekey) { + /* ...check for myCurrentEvent and myNextEvent */ + if (!myCurrentEvent) { + dprintf("!myCurrentEvent "); + change = true; + flag |= CSectionsdClient::epgflags::not_broadcast; + } else { + currentEvt = *myCurrentEvent; + flag |= CSectionsdClient::epgflags::has_current; // aktuelles event da... + flag |= CSectionsdClient::epgflags::has_anything; + } + if (!myNextEvent) { + dprintf("!myNextEvent "); + change = true; + } else { + nextEvt = *myNextEvent; + if (flag & CSectionsdClient::epgflags::not_broadcast) { + dprintf("CSectionsdClient::epgflags::has_no_current\n"); + flag = CSectionsdClient::epgflags::has_no_current; + } + flag |= CSectionsdClient::epgflags::has_next; // aktuelles event da... + flag |= CSectionsdClient::epgflags::has_anything; + } + } + + //dprintf("flag: 0x%x, has_current: 0x%x has_next: 0x%x\n", flag, CSectionsdClient::epgflags::has_current, CSectionsdClient::epgflags::has_next); + /* if another than the currently running program is requested, then flag will still be 0 + if either the current or the next event is not found, this condition will be true, too. + */ + if ((flag & (CSectionsdClient::epgflags::has_current|CSectionsdClient::epgflags::has_next)) != + (CSectionsdClient::epgflags::has_current|CSectionsdClient::epgflags::has_next)) { + //dprintf("commandCurrentNextInfoChannelID: current or next missing!\n"); + SItime zeitEvt1(0, 0); + if (!(flag & CSectionsdClient::epgflags::has_current)) { + currentEvt = findActualSIeventForServiceUniqueKey(uniqueServiceKey, zeitEvt1, 0, &flag2); + } else { + zeitEvt1.startzeit = currentEvt.times.begin()->startzeit; + zeitEvt1.dauer = currentEvt.times.begin()->dauer; + } + SItime zeitEvt2(zeitEvt1); + + if (currentEvt.getName().empty() && flag2 != 0) + { + dprintf("commandCurrentNextInfoChannelID change1\n"); + change = true; + } + + if (currentEvt.service_id != 0) + { //Found + flag &= (CSectionsdClient::epgflags::has_no_current|CSectionsdClient::epgflags::not_broadcast)^(unsigned)-1; + flag |= CSectionsdClient::epgflags::has_current; + flag |= CSectionsdClient::epgflags::has_anything; + dprintf("[sectionsd] current EPG found. service_id: %x, flag: 0x%x\n",currentEvt.service_id, flag); + + if (!(flag & CSectionsdClient::epgflags::has_next)) { + dprintf("*nextEvt not from cur/next V1!\n"); + nextEvt = findNextSIevent(currentEvt.uniqueKey(), zeitEvt2); + } + } + else + { // no current event... + readLockServices(); + + MySIservicesOrderUniqueKey::iterator si = mySIservicesOrderUniqueKey.end(); + si = mySIservicesOrderUniqueKey.find(uniqueServiceKey); + + if (si != mySIservicesOrderUniqueKey.end()) + { + dprintf("[sectionsd] current service has%s scheduled events, and has%s present/following events\n", si->second->eitScheduleFlag() ? "" : " no", si->second->eitPresentFollowingFlag() ? "" : " no" ); + + if ( /*( !si->second->eitScheduleFlag() ) || */ + ( !si->second->eitPresentFollowingFlag() ) ) + { + flag |= CSectionsdClient::epgflags::not_broadcast; + } + } + unlockServices(); + + if ( flag2 & CSectionsdClient::epgflags::has_anything ) + { + flag |= CSectionsdClient::epgflags::has_anything; + if (!(flag & CSectionsdClient::epgflags::has_next)) { + dprintf("*nextEvt not from cur/next V2!\n"); + nextEvt = findNextSIeventForServiceUniqueKey(uniqueServiceKey, zeitEvt2); + } + + if (nextEvt.service_id != 0) + { + MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueServiceKey); + + if (eFirst != mySIeventsOrderUniqueKey.end()) + { + // this is a race condition if first entry found is == mySIeventsOrderUniqueKey.begin() + // so perform a check + if (eFirst != mySIeventsOrderUniqueKey.begin()) + --eFirst; + + if (eFirst != mySIeventsOrderUniqueKey.begin()) + { + time_t azeit = time(NULL); + + if (eFirst->second->times.begin()->startzeit < azeit && + eFirst->second->uniqueKey() == nextEvt.uniqueKey() - 1) + flag |= CSectionsdClient::epgflags::has_no_current; + } + } + } + } + } + if (nextEvt.service_id != 0) + { + flag &= CSectionsdClient::epgflags::not_broadcast^(unsigned)-1; + dprintf("[sectionsd] next EPG found. service_id: %x, flag: 0x%x\n",nextEvt.service_id, flag); + flag |= CSectionsdClient::epgflags::has_next; + } + else if (flag != 0) + { + dprintf("commandCurrentNextInfoChannelID change2 flag: 0x%02x\n", flag); + change = true; + } + } + + if (currentEvt.service_id != 0) + { + /* check for nvod linkage */ + for (unsigned int i = 0; i < currentEvt.linkage_descs.size(); i++) + if (currentEvt.linkage_descs[i].linkageType == 0xB0) + { + fprintf(stderr,"[sectionsd] linkage in current EPG found.\n"); + flag |= CSectionsdClient::epgflags::current_has_linkagedescriptors; + break; + } + } else + flag |= CSectionsdClient::epgflags::has_no_current; + + time_t now; + + dprintf("currentEvt: '%s' (%04x) nextEvt: '%s' (%04x) flag: 0x%02x\n", + currentEvt.getName().c_str(), currentEvt.eventID, + nextEvt.getName().c_str(), nextEvt.eventID, flag); + + CSectionsdClient::sectionsdTime time_cur; + CSectionsdClient::sectionsdTime time_nxt; + now = time(NULL); + time_cur.startzeit = currentEvt.times.begin()->startzeit; + time_cur.dauer = currentEvt.times.begin()->dauer; + time_nxt.startzeit = nextEvt.times.begin()->startzeit; + time_nxt.dauer = nextEvt.times.begin()->dauer; + /* for nvod events that have multiple times, find the one that matches the current time... */ + if (currentEvt.times.size() > 1) { + for (SItimes::iterator t = currentEvt.times.begin(); t != currentEvt.times.end(); ++t) { + if ((long)now < (long)(t->startzeit + t->dauer) && (long)now > (long)t->startzeit) { + time_cur.startzeit = t->startzeit; + time_cur.dauer =t->dauer; + break; + } + } + } + /* ...and the one after that. */ + if (nextEvt.times.size() > 1) { + for (SItimes::iterator t = nextEvt.times.begin(); t != nextEvt.times.end(); ++t) { + if ((long)(time_cur.startzeit + time_cur.dauer) <= (long)(t->startzeit)) { // TODO: it's not "long", it's "time_t" + time_nxt.startzeit = t->startzeit; + time_nxt.dauer =t->dauer; + break; + } + } + } + + current_next.current_uniqueKey = currentEvt.uniqueKey(); + current_next.current_zeit.startzeit = time_cur.startzeit; + current_next.current_zeit.dauer = time_cur.dauer; + current_next.current_name = currentEvt.getName(); + + current_next.next_uniqueKey = nextEvt.uniqueKey(); + current_next.next_zeit.startzeit = time_nxt.startzeit; + current_next.next_zeit.dauer = time_nxt.dauer; + current_next.next_name = nextEvt.getName(); + + current_next.flags = flag; + current_next.current_fsk = currentEvt.getFSK(); + + unlockEvents(); + + //dprintf("change: %s, messaging_eit_busy: %s, last_request: %d\n", change?"true":"false", messaging_eit_is_busy?"true":"false",(time_monotonic() - messaging_last_requested)); + if (change && !messaging_eit_is_busy && (time_monotonic() - messaging_last_requested) < 11) { + /* restart dmxCN, but only if it is not already running, and only for 10 seconds */ + dprintf("change && !messaging_eit_is_busy => dmxCN.change(0)\n"); + dmxCN.change(0); + } +} +/* commandEPGepgIDshort */ +bool sectionsd_getEPGidShort(event_id_t epgID, CShortEPGData * epgdata) +{ + bool ret = false; + dprintf("Request of current EPG for 0x%llx\n", epgID); + + readLockEvents(); + + const SIevent& e = findSIeventForEventUniqueKey(epgID); + + if (e.service_id != 0) + { // Event found + dputs("EPG found."); + epgdata->title = e.getName(); + epgdata->info1 = e.getText(); + epgdata->info2 = e.getExtendedText(); + ret = true; + } else + dputs("EPG not found!"); + + unlockEvents(); + return ret; +} + +#if 0 +char * parseExtendedEvents(char * dp, CEPGData * epgdata) { + char * pItemDescriptions = dp, * pItemDescriptionStart; + dp+=strlen(dp)+1; + char * pItems = dp, * pItemStart; + dp+=strlen(dp)+1; + /* Clear vector since epgdata seems to be reused */ + epgdata->itemDescriptions.clear(); + while (*pItemDescriptions) { + pItemDescriptionStart = pItemDescriptions; + while (*pItemDescriptions && '\n' != *pItemDescriptions) { + pItemDescriptions++; + } + char pp = *pItemDescriptions; + *pItemDescriptions = 0; + epgdata->itemDescriptions.push_back(pItemDescriptionStart); + /*printf("CSectionsdClient::parseExtendedEvents: desc %s\n", pItemDescriptionStart);*/ + if(!pp) + break; + pItemDescriptions++; + } + /* Clear vector since epgdata seems to be reused */ + epgdata->items.clear(); + while (*pItems) { + pItemStart = pItems; + while (*pItems && '\n' != *pItems) { + pItems++; + } + char pp = *pItemDescriptions; + *pItems = 0; + epgdata->items.push_back(pItemStart); + /*printf("CSectionsdClient::parseExtendedEvents: item %s\n", pItemStart);*/ + if(!pp) + break; + pItems++; + } + return dp; +} +#endif + +/*was getEPGid commandEPGepgID(int connfd, char *data, const unsigned dataLength) */ +bool sectionsd_getEPGid(const event_id_t epgID, const time_t startzeit, CEPGData * epgdata) +{ + bool ret = false; + dprintf("Request of actual EPG for 0x%llx 0x%lx\n", epgID, startzeit); + + const SIevent& evt = findSIeventForEventUniqueKey(epgID); + + epgdata->itemDescriptions.clear(); + epgdata->items.clear(); + + readLockEvents(); + if (evt.service_id != 0) { // Event found + SItimes::iterator t = evt.times.begin(); + + for (; t != evt.times.end(); ++t) + if (t->startzeit == startzeit) + break; + + if (t == evt.times.end()) { + dputs("EPG not found!"); + } else { + dputs("EPG found."); + epgdata->eventID = evt.uniqueKey(); + epgdata->title = evt.getName(); + epgdata->info1 = evt.getText(); + epgdata->info2 = evt.getExtendedText(); + /* FIXME printf("itemDescription: %s\n", evt.itemDescription.c_str()); */ + epgdata->contentClassification = std::string(evt.contentClassification.data(), evt.contentClassification.length()); + epgdata->userClassification = std::string(evt.userClassification.data(), evt.userClassification.length()); + epgdata->fsk = evt.getFSK(); + epgdata->table_id = evt.table_id; + + epgdata->epg_times.startzeit = t->startzeit; + epgdata->epg_times.dauer = t->dauer; + + ret = true; + } + } else { + dputs("EPG not found!"); + } + unlockEvents(); + return ret; +} +/* was commandActualEPGchannelID(int connfd, char *data, const unsigned dataLength) */ +bool sectionsd_getActualEPGServiceKey(const t_channel_id uniqueServiceKey, CEPGData * epgdata) +{ + bool ret = false; + SIevent evt; + SItime zeit(0, 0); + + dprintf("[commandActualEPGchannelID] Request of current EPG for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); + + readLockEvents(); + if (uniqueServiceKey == messaging_current_servicekey) { + if (myCurrentEvent) { + evt = *myCurrentEvent; + zeit.startzeit = evt.times.begin()->startzeit; + zeit.dauer = evt.times.begin()->dauer; + if (evt.times.size() > 1) { + time_t now = time(NULL); + for (SItimes::iterator t = evt.times.begin(); t != evt.times.end(); ++t) { + if ((long)now < (long)(t->startzeit + t->dauer) && (long)now > (long)t->startzeit) { + zeit.startzeit = t->startzeit; + zeit.dauer = t->dauer; break; } } } } - - unlockEvents(); } - /*was static void commandComponentTagsUniqueKey(int connfd, char *data, const unsigned dataLength) */ - bool sectionsd_getComponentTagsUniqueKey(const event_id_t uniqueKey, CSectionsdClient::ComponentTagList& tags) + + if (evt.service_id == 0) { - bool ret = false; - dprintf("Request of ComponentTags for 0x%llx\n", uniqueKey); - - tags.clear(); - - readLockEvents(); - - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) { - CSectionsdClient::responseGetComponentTags response; - ret = true; - - for (SIcomponents::iterator cmp = eFirst->second->components.begin(); cmp != eFirst->second->components.end(); ++cmp) { - response.component = cmp->component; - response.componentType = cmp->componentType; - response.componentTag = cmp->componentTag; - response.streamContent = cmp->streamContent; - - tags.insert(tags.end(), response); - } - } - - unlockEvents(); - return ret; - + dprintf("[commandActualEPGchannelID] evt.service_id == 0 ==> no myCurrentEvent!\n"); + evt = findActualSIeventForServiceUniqueKey(uniqueServiceKey, zeit); } - /* was static void commandLinkageDescriptorsUniqueKey(int connfd, char *data, const unsigned dataLength) */ - bool sectionsd_getLinkageDescriptorsUniqueKey(const event_id_t uniqueKey, CSectionsdClient::LinkageDescriptorList& descriptors) + + if (evt.service_id != 0) { - bool ret = false; - dprintf("Request of LinkageDescriptors for 0x%llx\n", uniqueKey); + dprintf("EPG found.\n"); + epgdata->eventID = evt.uniqueKey(); + epgdata->title = evt.getName(); + epgdata->info1 = evt.getText(); + epgdata->info2 = evt.getExtendedText(); + /* FIXME printf("itemDescription: %s\n", evt.itemDescription.c_str());*/ + epgdata->contentClassification = std::string(evt.contentClassification.data(), evt.contentClassification.length()); + epgdata->userClassification = std::string(evt.userClassification.data(), evt.userClassification.length()); + epgdata->fsk = evt.getFSK(); + epgdata->table_id = evt.table_id; - descriptors.clear(); - readLockEvents(); + epgdata->epg_times.startzeit = zeit.startzeit; + epgdata->epg_times.dauer = zeit.dauer; - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); + ret = true; + } else + dprintf("EPG not found!\n"); - if (eFirst != mySIeventsOrderUniqueKey.end()) { - for (SIlinkage_descs::iterator linkage_desc = eFirst->second->linkage_descs.begin(); linkage_desc != eFirst->second->linkage_descs.end(); ++linkage_desc) - { - if (linkage_desc->linkageType == 0xB0) { + unlockEvents(); + return ret; +} +/* was static void sendEventList(int connfd, const unsigned char serviceTyp1, const unsigned char serviceTyp2 = 0, int sendServiceName = 1, t_channel_id * chidlist = NULL, int clen = 0) */ +void sectionsd_getChannelEvents(CChannelEventList &eList, const bool tv_mode = true, t_channel_id *chidlist = NULL, int clen = 0) +{ + unsigned char serviceTyp1, serviceTyp2; + clen = clen / sizeof(t_channel_id); - CSectionsdClient::responseGetLinkageDescriptors response; - response.name = linkage_desc->name.c_str(); - response.transportStreamId = linkage_desc->transportStreamId; - response.originalNetworkId = linkage_desc->originalNetworkId; - response.serviceId = linkage_desc->serviceId; - descriptors.insert( descriptors.end(), response); - ret = true; - } - } - } - - unlockEvents(); - return ret; + t_channel_id uniqueNow = 0; + t_channel_id uniqueOld = 0; + bool found_already = false; + time_t azeit = time(NULL); + std::string sname; + if(tv_mode) { + serviceTyp1 = 0x01; + serviceTyp2 = 0x04; + } else { + serviceTyp1 = 0x02; + serviceTyp2 = 0x00; } - /* was static void commandTimesNVODservice(int connfd, char *data, const unsigned dataLength) */ - bool sectionsd_getNVODTimesServiceKey(const t_channel_id uniqueServiceKey, CSectionsdClient::NVODTimesList& nvod_list) + + readLockEvents(); + + /* !!! FIX ME: if the box starts on a channel where there is no EPG sent, it hangs!!! */ + for (MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end(); ++e) { - bool ret = false; - dprintf("Request of NVOD times for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); - - nvod_list.clear(); - - readLockServices(); - readLockEvents(); - - MySIservicesNVODorderUniqueKey::iterator si = mySIservicesNVODorderUniqueKey.find(uniqueServiceKey); - if (si != mySIservicesNVODorderUniqueKey.end()) + uniqueNow = (*e)->get_channel_id(); + if (!channel_in_requested_list(chidlist, uniqueNow, clen)) continue; + if ( uniqueNow != uniqueOld ) { - dprintf("NVODServices: %u\n", si->second->nvods.size()); + found_already = true; + readLockServices(); + // new service, check service- type + MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.find(uniqueNow); - if (si->second->nvods.size()) { - for (SInvodReferences::iterator ni = si->second->nvods.begin(); ni != si->second->nvods.end(); ++ni) { - SItime zeitEvt1(0, 0); - findActualSIeventForServiceUniqueKey(ni->uniqueKey(), zeitEvt1, 15*60); + if (s != mySIservicesOrderUniqueKey.end()) + { + if (s->second->serviceTyp == serviceTyp1 || (serviceTyp2 && s->second->serviceTyp == serviceTyp2)) + { + sname = s->second->serviceName; + found_already = false; + } + } + else + { + // wenn noch nie hingetuned wurde, dann gibts keine Info ber den ServiceTyp... + // im Zweifel mitnehmen + found_already = false; + } + unlockServices(); - CSectionsdClient::responseGetNVODTimes response; + uniqueOld = uniqueNow; + } - response.service_id = ni->service_id; - response.original_network_id = ni->original_network_id; - response.transport_stream_id = ni->transport_stream_id; - response.zeit.startzeit = zeitEvt1.startzeit; - response.zeit.dauer = zeitEvt1.dauer; + if ( !found_already ) + { + std::string eName = (*e)->getName(); + std::string eText = (*e)->getText(); + std::string eExtendedText = (*e)->getExtendedText(); - nvod_list.insert( nvod_list.end(), response); - ret = true; + for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) + { + if (t->startzeit <= azeit && azeit <= (long)(t->startzeit + t->dauer)) + { + CChannelEvent aEvent; + aEvent.eventID = (*e)->uniqueKey(); + aEvent.startTime = t->startzeit; + aEvent.duration = t->dauer; + aEvent.description = (*e)->getName(); + if (((*e)->getText()).empty()) + aEvent.text = (*e)->getExtendedText().substr(0, 120); + else + aEvent.text = (*e)->getText(); + eList.push_back(aEvent); + + found_already = true; + break; } } } - - unlockEvents(); - unlockServices(); - return ret; } - void sectionsd_setPrivatePid(unsigned short /*pid*/) - { -#ifdef ENABLE_PPT - privatePid = pid; - if (pid != 0) { - dprintf("[sectionsd] wakeup PPT Thread, pid=%x\n", pid); - dmxPPT.change( 0 ); + unlockEvents(); +} +/*was static void commandComponentTagsUniqueKey(int connfd, char *data, const unsigned dataLength) */ +bool sectionsd_getComponentTagsUniqueKey(const event_id_t uniqueKey, CSectionsdClient::ComponentTagList& tags) +{ + bool ret = false; + dprintf("Request of ComponentTags for 0x%llx\n", uniqueKey); + + tags.clear(); + + readLockEvents(); + + MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); + + if (eFirst != mySIeventsOrderUniqueKey.end()) { + CSectionsdClient::responseGetComponentTags response; + ret = true; + + for (SIcomponents::iterator cmp = eFirst->second->components.begin(); cmp != eFirst->second->components.end(); ++cmp) { + response.component = cmp->component; + response.componentType = cmp->componentType; + response.componentTag = cmp->componentTag; + response.streamContent = cmp->streamContent; + + tags.insert(tags.end(), response); } -#endif } - void sectionsd_set_languages(const std::vector& newLanguages) - { - SIlanguage::setLanguages(newLanguages); - SIlanguage::saveLanguages(); + unlockEvents(); + return ret; + +} +/* was static void commandLinkageDescriptorsUniqueKey(int connfd, char *data, const unsigned dataLength) */ +bool sectionsd_getLinkageDescriptorsUniqueKey(const event_id_t uniqueKey, CSectionsdClient::LinkageDescriptorList& descriptors) +{ + bool ret = false; + dprintf("Request of LinkageDescriptors for 0x%llx\n", uniqueKey); + + descriptors.clear(); + readLockEvents(); + + MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); + + if (eFirst != mySIeventsOrderUniqueKey.end()) { + for (SIlinkage_descs::iterator linkage_desc = eFirst->second->linkage_descs.begin(); linkage_desc != eFirst->second->linkage_descs.end(); ++linkage_desc) + { + if (linkage_desc->linkageType == 0xB0) { + + CSectionsdClient::responseGetLinkageDescriptors response; + response.name = linkage_desc->name.c_str(); + response.transportStreamId = linkage_desc->transportStreamId; + response.originalNetworkId = linkage_desc->originalNetworkId; + response.serviceId = linkage_desc->serviceId; + descriptors.insert( descriptors.end(), response); + ret = true; + } + } } + unlockEvents(); + return ret; + +} +/* was static void commandTimesNVODservice(int connfd, char *data, const unsigned dataLength) */ +bool sectionsd_getNVODTimesServiceKey(const t_channel_id uniqueServiceKey, CSectionsdClient::NVODTimesList& nvod_list) +{ + bool ret = false; + dprintf("Request of NVOD times for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); + + nvod_list.clear(); + + readLockServices(); + readLockEvents(); + + MySIservicesNVODorderUniqueKey::iterator si = mySIservicesNVODorderUniqueKey.find(uniqueServiceKey); + if (si != mySIservicesNVODorderUniqueKey.end()) + { + dprintf("NVODServices: %u\n", si->second->nvods.size()); + + if (si->second->nvods.size()) { + for (SInvodReferences::iterator ni = si->second->nvods.begin(); ni != si->second->nvods.end(); ++ni) { + SItime zeitEvt1(0, 0); + findActualSIeventForServiceUniqueKey(ni->uniqueKey(), zeitEvt1, 15*60); + + CSectionsdClient::responseGetNVODTimes response; + + response.service_id = ni->service_id; + response.original_network_id = ni->original_network_id; + response.transport_stream_id = ni->transport_stream_id; + response.zeit.startzeit = zeitEvt1.startzeit; + response.zeit.dauer = zeitEvt1.dauer; + + nvod_list.insert( nvod_list.end(), response); + ret = true; + } + } + } + + unlockEvents(); + unlockServices(); + return ret; +} + +void sectionsd_setPrivatePid(unsigned short /*pid*/) +{ +#ifdef ENABLE_PPT + privatePid = pid; + if (pid != 0) { + dprintf("[sectionsd] wakeup PPT Thread, pid=%x\n", pid); + dmxPPT.change( 0 ); + } +#endif +} + +void sectionsd_set_languages(const std::vector& newLanguages) +{ + SIlanguage::setLanguages(newLanguages); + SIlanguage::saveLanguages(); +} + bool sectionsd_isReady(void) { return sectionsd_ready; From 3ea0c375eac6cf5415d000ecf2f218a966f99d4f Mon Sep 17 00:00:00 2001 From: "[CST] Focus" Date: Wed, 1 Feb 2012 16:09:49 +0400 Subject: [PATCH 090/737] Copy sectionsd code to new eitd directory, to cleanup and leave original code for reference --- configure.ac | 2 +- src/eitd/FreesatTables.hpp | 3052 ++++++++++++ src/eitd/Makefile.am | 20 + src/eitd/SIbouquets.hpp | 141 + src/eitd/SIevents.cpp | 593 +++ src/eitd/SIevents.hpp | 488 ++ src/eitd/SIlanguage.cpp | 220 + src/eitd/SIlanguage.hpp | 62 + src/eitd/SInetworks.hpp | 183 + src/eitd/SIsections.cpp | 1636 ++++++ src/eitd/SIsections.hpp | 984 ++++ src/eitd/SIservices.hpp | 208 + src/eitd/SIutils.cpp | 300 ++ src/eitd/SIutils.hpp | 57 + src/eitd/debug.cpp | 35 + src/eitd/dmx.cpp | 862 ++++ src/eitd/dmxapi.cpp | 208 + src/eitd/edvbstring.cpp | 886 ++++ src/eitd/sectionsd.cpp | 9640 ++++++++++++++++++++++++++++++++++++ 19 files changed, 19576 insertions(+), 1 deletion(-) create mode 100644 src/eitd/FreesatTables.hpp create mode 100644 src/eitd/Makefile.am create mode 100644 src/eitd/SIbouquets.hpp create mode 100644 src/eitd/SIevents.cpp create mode 100644 src/eitd/SIevents.hpp create mode 100644 src/eitd/SIlanguage.cpp create mode 100644 src/eitd/SIlanguage.hpp create mode 100644 src/eitd/SInetworks.hpp create mode 100644 src/eitd/SIsections.cpp create mode 100644 src/eitd/SIsections.hpp create mode 100644 src/eitd/SIservices.hpp create mode 100644 src/eitd/SIutils.cpp create mode 100644 src/eitd/SIutils.hpp create mode 100644 src/eitd/debug.cpp create mode 100644 src/eitd/dmx.cpp create mode 100644 src/eitd/dmxapi.cpp create mode 100644 src/eitd/edvbstring.cpp create mode 100644 src/eitd/sectionsd.cpp diff --git a/configure.ac b/configure.ac index bcbb18b31..a4a8af4e7 100644 --- a/configure.ac +++ b/configure.ac @@ -174,7 +174,7 @@ data/lcd/clock/Makefile data/locale/Makefile data/scripts/Makefile data/themes/Makefile -src/sectionsd/Makefile +src/eitd/Makefile src/timerd/Makefile src/zapit/Makefile src/zapit/lib/Makefile diff --git a/src/eitd/FreesatTables.hpp b/src/eitd/FreesatTables.hpp new file mode 100644 index 000000000..68a33b3ac --- /dev/null +++ b/src/eitd/FreesatTables.hpp @@ -0,0 +1,3052 @@ +/* + * This table was derived from on-air transmissions. It certainly has omissions and + * almost certainly contains errors. Use entirely at your own risk. + */ +struct hufftab { + char last; + unsigned int value; + short bits; + char next; +}; + +#define START '\0' +#define STOP '\0' +#define ESCAPE '\1' + +static struct hufftab fsat_huffman1[] = +{ + { START, 0x00000000, 2, 'T'}, + { START, 0x40000000, 3, 'B'}, + { START, 0x60000000, 5, 'L'}, + { START, 0x68000000, 7, 'K'}, + { START, 0x6a000000, 8, '6'}, + { START, 0x6c000000, 6, 'Q'}, + { START, 0x70000000, 5, 'D'}, + { START, 0x78000000, 5, 'H'}, + { START, 0x80000000, 4, 'C'}, + { START, 0x90000000, 4, 'I'}, + { START, 0xa0000000, 5, 'R'}, + { START, 0xa8000000, 5, 'N'}, + { START, 0xb0000000, 5, 'E'}, + { START, 0xb8000000, 8, 'V'}, + { START, 0xb9000000, 10, 'Z'}, + { START, 0xb9400000, 11, '1'}, + { START, 0xb9600000, 11, '3'}, + { START, 0xb9800000, 9, '2'}, + { START, 0xba000000, 7, 'U'}, + { START, 0xbc000000, 6, 'G'}, + { START, 0xc0000000, 5, 'F'}, + { START, 0xc8000000, 5, 'A'}, + { START, 0xd0000000, 4, 'S'}, + { START, 0xe0000000, 5, 'M'}, + { START, 0xe8000000, 5, 'P'}, + { START, 0xf0000000, 5, 'W'}, + { START, 0xf8000000, 6, 'J'}, + { START, 0xfc000000, 7, 'O'}, + { START, 0xfe000000, 8, 'Y'}, + { START, 0xff400000, 11, '4'}, + { START, 0xff600000, 14, '5'}, + { START, 0xff698000, 18, 't'}, + { START, 0xff800000, 9, 'X'}, + { ' ', 0x00000000, 4, 'W'}, + { ' ', 0x10000000, 7, 'f'}, + { ' ', 0x12000000, 7, 'Q'}, + { ' ', 0x14000000, 8, '-'}, + { ' ', 0x15240000, 14, '.'}, + { ' ', 0x152c0000, 14, 'l'}, + { ' ', 0x15300000, 13, 'g'}, + { ' ', 0x15400000, 10, 'r'}, + { ' ', 0x15800000, 11, 'b'}, + { ' ', 0x15a00000, 12, 'v'}, + { ' ', 0x15b00000, 12, 'd'}, + { ' ', 0x15f00000, 13, 'u'}, + { ' ', 0x16000000, 7, 'V'}, + { ' ', 0x18000000, 5, 'I'}, + { ' ', 0x20000000, 5, 'G'}, + { ' ', 0x28000000, 7, STOP}, + { ' ', 0x2a000000, 7, 'w'}, + { ' ', 0x2c000000, 6, 'U'}, + { ' ', 0x30000000, 4, 'M'}, + { ' ', 0x40000000, 4, 'C'}, + { ' ', 0x50000000, 4, 'B'}, + { ' ', 0x60000000, 5, 'H'}, + { ' ', 0x68000000, 5, 'D'}, + { ' ', 0x70000000, 4, 'P'}, + { ' ', 0x80000000, 5, 'o'}, + { ' ', 0x88000000, 5, 'A'}, + { ' ', 0x90000000, 4, 'T'}, + { ' ', 0xa0000000, 5, 't'}, + { ' ', 0xa8000000, 9, '&'}, + { ' ', 0xa8800000, 10, '5'}, + { ' ', 0xa8c00000, 10, 'Z'}, + { ' ', 0xa9000000, 8, '1'}, + { ' ', 0xaa000000, 11, '\''}, + { ' ', 0xaa200000, 11, '0'}, + { ' ', 0xaa400000, 10, '9'}, + { ' ', 0xab000000, 11, '6'}, + { ' ', 0xab200000, 12, 'n'}, + { ' ', 0xab300000, 12, '8'}, + { ' ', 0xab400000, 10, 's'}, + { ' ', 0xab800000, 10, '4'}, + { ' ', 0xabc00000, 10, '3'}, + { ' ', 0xac000000, 6, 'O'}, + { ' ', 0xb0000000, 5, 'a'}, + { ' ', 0xb8000000, 5, 'F'}, + { ' ', 0xc0000000, 4, 'N'}, + { ' ', 0xd0000000, 5, 'L'}, + { ' ', 0xd8000000, 5, 'R'}, + { ' ', 0xe0000000, 7, '2'}, + { ' ', 0xe2000000, 7, 'K'}, + { ' ', 0xe4000000, 6, 'J'}, + { ' ', 0xe8000000, 6, 'E'}, + { ' ', 0xec000000, 7, 'Y'}, + { ' ', 0xee000000, 7, 'i'}, + { ' ', 0xf0000000, 4, 'S'}, + { '!', 0x40000000, 2, ' '}, + { '!', 0x80000000, 8, STOP}, + { '&', 0x40000000, 2, 'B'}, + { '&', 0x80000000, 1, ' '}, + { '%', 0x80000000, 1, ' '}, + { ',', 0x80000000, 1, ' '}, + { '-', 0x0c000000, 7, 'L'}, + { '-', 0x1c000000, 6, 'I'}, + { '-', 0x20000000, 8, 'P'}, + { '-', 0x38000000, 10, 'E'}, + { '-', 0x40000000, 4, 'U'}, + { '-', 0x5d000000, 8, 'i'}, + { '-', 0x84000000, 7, 'D'}, + { '-', 0x96af8000, 17, 'H'}, + { '-', 0xb0000000, 4, 'S'}, + { '-', 0xc0000000, 2, ' '}, + { '.', 0x08000000, 5, 'T'}, + { '.', 0x19600000, 13, ESCAPE}, + { '.', 0x1a000000, 8, 'W'}, + { '.', 0x20000000, 4, ' '}, + { '.', 0x40000000, 2, STOP}, + { '.', 0x80000000, 1, '.'}, + { '/', 0x40000000, 3, '7'}, + { '0', 0x40000000, 2, ' '}, + { '0', 0x80000000, 3, '6'}, + { '0', 0xa0000000, 4, STOP}, + { '0', 0xb0000000, 6, '8'}, + { '0', 0xb4000000, 7, 's'}, + { '0', 0xb7000000, 9, '/'}, + { '0', 0xb7800000, 9, '%'}, + { '0', 0xb8000000, 5, '7'}, + { '0', 0xc0000000, 2, '0'}, + { '1', 0x30000000, 4, ' '}, + { '1', 0x40000000, 2, STOP}, + { '1', 0x8c000000, 6, ':'}, + { '1', 0x98000000, 6, '\''}, + { '1', 0xa0000000, 3, '0'}, + { '1', 0xc0000000, 5, '3'}, + { '1', 0xc8000000, 6, 'X'}, + { '1', 0xcc000000, 6, '9'}, + { '1', 0xe0000000, 3, '1'}, + { '2', 0x00000000, 1, '0'}, + { '2', 0x80000000, 5, ':'}, + { '2', 0x90000000, 4, ' '}, + { '2', 0xa0000000, 3, STOP}, + { '2', 0xc0000000, 2, '4'}, + { '3', 0x00000000, 1, ' '}, + { '3', 0x80000000, 8, STOP}, + { '3', 0xe0000000, 5, '0'}, + { '3', 0xe8000000, 7, ':'}, + { '4', 0x00000000, 8, STOP}, + { '4', 0x52000000, 8, 'M'}, + { '4', 0x90000000, 4, ':'}, + { '4', 0xa0000000, 3, '-'}, + { '4', 0xc0000000, 2, ' '}, + { '5', 0xa0000000, 3, '0'}, + { '5', 0xc0000000, 2, ' '}, + { '6', 0x40000000, 2, ' '}, + { '6', 0x80000000, 2, '0'}, + { '6', 0xc6000000, 7, '4'}, + { '6', 0xd8000000, 6, '8'}, + { '6', 0xe0000000, 3, ':'}, + { '7', 0x80000000, 8, STOP}, + { '8', 0x00000000, 2, '0'}, + { '8', 0x84000000, 7, ':'}, + { '8', 0x86800000, 9, STOP}, + { '8', 0x87800000, 10, '.'}, + { '8', 0x88000000, 5, ' '}, + { '9', 0x00000000, 1, '1'}, + { '9', 0x80000000, 4, '9'}, + { '9', 0x98000000, 5, '0'}, + { '9', 0xa0000000, 3, '6'}, + { '9', 0xc0000000, 3, STOP}, + { ':', 0x00000000, 2, '0'}, + { ':', 0x58000000, 8, ESCAPE}, + { ':', 0x59000000, 8, 'T'}, + { ':', 0x60000000, 3, '.'}, + { ':', 0x80000000, 1, ' '}, + { '?', 0x20000000, 3, ':'}, + { '?', 0x40000000, 2, ' '}, + { '?', 0x80000000, 2, STOP}, + { 'A', 0x00000000, 4, 'm'}, + { 'A', 0x10000000, 5, 'w'}, + { 'A', 0x18000000, 6, 'u'}, + { 'A', 0x1c000000, 6, STOP}, + { 'A', 0x20000000, 3, 'r'}, + { 'A', 0x40000000, 3, ' '}, + { 'A', 0x68000000, 5, 'c'}, + { 'A', 0x70000000, 4, 'g'}, + { 'A', 0x80000000, 3, 'l'}, + { 'A', 0xa2000000, 7, 'v'}, + { 'A', 0xa8000000, 5, 't'}, + { 'A', 0xb0000000, 5, 'f'}, + { 'A', 0xb8000000, 5, 'i'}, + { 'A', 0xc0000000, 3, 'n'}, + { 'A', 0xe0000000, 5, 's'}, + { 'A', 0xe8000000, 6, 'b'}, + { 'A', 0xec000000, 7, 'p'}, + { 'A', 0xef180000, 13, '\''}, + { 'A', 0xef400000, 12, 'y'}, + { 'A', 0xf0000000, 4, 'd'}, + { 'B', 0x00000000, 2, 'C'}, + { 'B', 0x40000000, 2, 'B'}, + { 'B', 0x80000000, 6, STOP}, + { 'B', 0x84000000, 7, 'y'}, + { 'B', 0x87a00000, 11, 'h'}, + { 'B', 0x87e00000, 11, ' '}, + { 'B', 0x88000000, 5, 'l'}, + { 'B', 0x90000000, 4, 'i'}, + { 'B', 0xa0000000, 3, 'r'}, + { 'B', 0xc0000000, 4, 'o'}, + { 'B', 0xd0000000, 4, 'u'}, + { 'B', 0xe0000000, 4, 'a'}, + { 'B', 0xf0000000, 4, 'e'}, + { 'C', 0x00000000, 2, 'o'}, + { 'C', 0x40000000, 2, ' '}, + { 'C', 0x80000000, 3, 'l'}, + { 'C', 0xa0000000, 4, 'r'}, + { 'C', 0xb0000000, 5, 'i'}, + { 'C', 0xb8000000, 5, 'e'}, + { 'C', 0xc0000000, 3, 'h'}, + { 'C', 0xe0000000, 4, 'a'}, + { 'C', 0xf0000000, 6, 'u'}, + { 'C', 0xf4000000, 6, 'B'}, + { 'C', 0xf8000000, 7, 'y'}, + { 'C', 0xfa800000, 11, '4'}, + { 'C', 0xfc000000, 7, '!'}, + { 'C', 0xfe000000, 9, STOP}, + { 'C', 0xfea00000, 11, 'D'}, + { 'C', 0xfec00000, 10, 'I'}, + { 'C', 0xff000000, 9, 'S'}, + { 'D', 0x00000000, 3, 'r'}, + { 'D', 0x28400000, 10, 'h'}, + { 'D', 0x29800000, 9, '&'}, + { 'D', 0x2a000000, 7, 'J'}, + { 'D', 0x2c000000, 6, ' '}, + { 'D', 0x30000000, 7, 'y'}, + { 'D', 0x32000000, 9, '\''}, + { 'D', 0x32a00000, 11, 'N'}, + { 'D', 0x38000000, 5, 'u'}, + { 'D', 0x40000000, 2, 'o'}, + { 'D', 0x80000000, 2, 'a'}, + { 'D', 0xc0000000, 3, 'e'}, + { 'D', 0xe0000000, 3, 'i'}, + { 'E', 0x00000000, 2, 'm'}, + { 'E', 0x40000000, 4, 'E'}, + { 'E', 0x50000000, 5, 'F'}, + { 'E', 0x58000000, 6, 'u'}, + { 'E', 0x5d000000, 9, 'g'}, + { 'E', 0x5e000000, 7, 's'}, + { 'E', 0x60000000, 3, 'v'}, + { 'E', 0x80000000, 4, STOP}, + { 'E', 0x90000000, 6, 'r'}, + { 'E', 0x96000000, 8, 'R'}, + { 'E', 0x98000000, 5, 'd'}, + { 'E', 0xa0000000, 3, 'n'}, + { 'E', 0xc6000000, 8, '\''}, + { 'E', 0xc7000000, 8, ' '}, + { 'E', 0xc8000000, 5, 'l'}, + { 'E', 0xd0000000, 4, 'x'}, + { 'E', 0xe0000000, 3, 'a'}, + { 'F', 0x00000000, 2, 'i'}, + { 'F', 0x40000000, 4, 'e'}, + { 'F', 0x50000000, 7, 'A'}, + { 'F', 0x52000000, 8, ' '}, + { 'F', 0x53000000, 9, 'h'}, + { 'F', 0x54000000, 7, 'O'}, + { 'F', 0x57200000, 11, 'I'}, + { 'F', 0x57600000, 11, '1'}, + { 'F', 0x58000000, 5, 'l'}, + { 'F', 0x60000000, 3, 'r'}, + { 'F', 0x80000000, 2, 'a'}, + { 'F', 0xc0000000, 3, 'u'}, + { 'F', 0xe0000000, 3, 'o'}, + { 'G', 0x00000000, 8, ':'}, + { 'G', 0x01300000, 13, ESCAPE}, + { 'G', 0x01400000, 11, 'A'}, + { 'G', 0x01600000, 12, 'T'}, + { 'G', 0x02000000, 7, 'y'}, + { 'G', 0x04000000, 6, 'h'}, + { 'G', 0x08000000, 5, 'u'}, + { 'G', 0x1a800000, 10, 'P'}, + { 'G', 0x1ac00000, 10, ' '}, + { 'G', 0x1b000000, 8, 'C'}, + { 'G', 0x1c000000, 6, 'l'}, + { 'G', 0x20000000, 3, 'M'}, + { 'G', 0x40000000, 3, 'a'}, + { 'G', 0x60000000, 3, 'o'}, + { 'G', 0x80000000, 2, 'r'}, + { 'G', 0xc0000000, 3, 'i'}, + { 'G', 0xe0000000, 3, 'e'}, + { 'H', 0x00000000, 1, 'o'}, + { 'H', 0x80000000, 3, 'a'}, + { 'H', 0xa0000000, 3, 'i'}, + { 'H', 0xc0000000, 3, 'e'}, + { 'H', 0xe0000000, 4, 'u'}, + { 'H', 0xf0000000, 5, 'R'}, + { 'H', 0xfe200000, 14, ESCAPE}, + { 'H', 0xfe280000, 13, 'D'}, + { 'H', 0xff000000, 9, 'S'}, + { 'I', 0x00000000, 1, 'T'}, + { 'I', 0x80000000, 3, 's'}, + { 'I', 0xa0000000, 3, 'n'}, + { 'I', 0xc0000000, 6, 'I'}, + { 'I', 0xc4000000, 6, STOP}, + { 'I', 0xc8000000, 5, ' '}, + { 'I', 0xd0000000, 4, 't'}, + { 'I', 0xe4000000, 6, 'm'}, + { 'I', 0xe8000000, 5, '\''}, + { 'I', 0xf0000000, 8, 'a'}, + { 'I', 0xf6900000, 13, ','}, + { 'I', 0xf6980000, 13, 'A'}, + { 'I', 0xf6c00000, 11, 'f'}, + { 'I', 0xf6e00000, 12, 'o'}, + { 'I', 0xf7000000, 9, 'c'}, + { 'I', 0xf7800000, 11, 'l'}, + { 'I', 0xf7a80000, 13, 'g'}, + { 'I', 0xf7d40000, 14, 'b'}, + { 'I', 0xf8000000, 5, 'r'}, + { 'J', 0x00000000, 2, 'a'}, + { 'J', 0x40000000, 2, 'u'}, + { 'J', 0x80000000, 5, ' '}, + { 'J', 0x8c800000, 9, 's'}, + { 'J', 0x8d900000, 12, 'D'}, + { 'J', 0x90000000, 4, 'i'}, + { 'J', 0xa0000000, 3, 'o'}, + { 'J', 0xc0000000, 2, 'e'}, + { 'K', 0x00000000, 4, 'a'}, + { 'K', 0x10000000, 8, STOP}, + { 'K', 0x18000000, 5, 'r'}, + { 'K', 0x20000000, 3, 'e'}, + { 'K', 0x40000000, 2, 'i'}, + { 'K', 0x80000000, 4, 'o'}, + { 'K', 0x92800000, 9, 'w'}, + { 'K', 0x93000000, 8, 'G'}, + { 'K', 0x98000000, 6, 'n'}, + { 'K', 0xa0000000, 3, ' '}, + { 'K', 0xc0000000, 2, 'y'}, + { 'L', 0x00000000, 2, 'a'}, + { 'L', 0x40000000, 3, 'e'}, + { 'L', 0x60000000, 7, 'l'}, + { 'L', 0x63000000, 8, 'y'}, + { 'L', 0x68000000, 5, 'K'}, + { 'L', 0x70000000, 4, 'u'}, + { 'L', 0x80000000, 2, 'o'}, + { 'L', 0xc0000000, 2, 'i'}, + { 'M', 0x00000000, 3, 'e'}, + { 'M', 0x20000000, 4, 'T'}, + { 'M', 0x30000000, 5, STOP}, + { 'M', 0x38200000, 11, 'h'}, + { 'M', 0x38c00000, 10, ' '}, + { 'M', 0x39000000, 8, 'r'}, + { 'M', 0x3a000000, 8, 'E'}, + { 'M', 0x3b000000, 10, '1'}, + { 'M', 0x3c000000, 6, 'c'}, + { 'M', 0x40000000, 2, 'a'}, + { 'M', 0x80000000, 2, 'o'}, + { 'M', 0xc0000000, 4, 'y'}, + { 'M', 0xd0000000, 4, 'u'}, + { 'M', 0xe0000000, 3, 'i'}, + { 'N', 0x00000000, 2, 'o'}, + { 'N', 0x45400000, 12, 'M'}, + { 'N', 0x45c00000, 11, 'A'}, + { 'N', 0x48000000, 5, 'u'}, + { 'N', 0x50000000, 4, 'a'}, + { 'N', 0x60000000, 3, 'i'}, + { 'N', 0x80000000, 1, 'e'}, + { 'O', 0x00000000, 3, '\''}, + { 'O', 0x30000000, 4, 'l'}, + { 'O', 0x40000000, 3, 'f'}, + { 'O', 0x60800000, 9, 'g'}, + { 'O', 0x62000000, 8, 'x'}, + { 'O', 0x64000000, 6, 'S'}, + { 'O', 0x68000000, 5, 'r'}, + { 'O', 0x70000000, 5, 'd'}, + { 'O', 0x7c000000, 6, 'b'}, + { 'O', 0x80000000, 5, 'p'}, + { 'O', 0x8a800000, 9, 'a'}, + { 'O', 0x8c000000, 6, 'v'}, + { 'O', 0x90000000, 4, 'm'}, + { 'O', 0xa8000000, 6, 'w'}, + { 'O', 0xac000000, 6, 'U'}, + { 'O', 0xb0000000, 5, STOP}, + { 'O', 0xbe000000, 8, 's'}, + { 'O', 0xc0000000, 3, 'u'}, + { 'O', 0xe0000000, 3, 'n'}, + { 'P', 0x00000000, 3, 'e'}, + { 'P', 0x20000000, 3, 'a'}, + { 'P', 0x40000000, 2, 'r'}, + { 'P', 0x80000000, 2, 'l'}, + { 'P', 0xc0000000, 6, 'D'}, + { 'P', 0xc4000000, 6, 'u'}, + { 'P', 0xc8000000, 8, ' '}, + { 'P', 0xc9800000, 9, 'M'}, + { 'P', 0xcb800000, 11, ':'}, + { 'P', 0xcbc60000, 15, ESCAPE}, + { 'P', 0xcbe80000, 13, 'G'}, + { 'P', 0xcc000000, 6, 'h'}, + { 'P', 0xd0000000, 4, 'i'}, + { 'P', 0xe0000000, 3, 'o'}, + { 'Q', 0x68000000, 5, 'C'}, + { 'Q', 0x80000000, 1, 'u'}, + { 'R', 0x00000000, 2, 'a'}, + { 'R', 0x40000000, 2, 'o'}, + { 'R', 0x80000000, 3, 'i'}, + { 'R', 0xa4540000, 15, ESCAPE}, + { 'R', 0xa4600000, 12, ' '}, + { 'R', 0xa4c00000, 10, 'n'}, + { 'R', 0xa6000000, 7, STOP}, + { 'R', 0xa8000000, 5, 'E'}, + { 'R', 0xb0000000, 4, 'u'}, + { 'R', 0xc0000000, 2, 'e'}, + { 'S', 0x00000000, 5, 'n'}, + { 'S', 0x0a000000, 7, 'A'}, + { 'S', 0x0c000000, 6, 'w'}, + { 'S', 0x10000000, 4, 'a'}, + { 'S', 0x20000000, 3, 'o'}, + { 'S', 0x40000000, 3, 'p'}, + { 'S', 0x60000000, 3, 'u'}, + { 'S', 0x80000000, 8, 'O'}, + { 'S', 0x81000000, 9, 'y'}, + { 'S', 0x83000000, 8, ' '}, + { 'S', 0x84000000, 7, 'l'}, + { 'S', 0x86000000, 9, 'E'}, + { 'S', 0x86800000, 11, 'g'}, + { 'S', 0x88000000, 5, 'i'}, + { 'S', 0x90000000, 4, 'e'}, + { 'S', 0xa0000000, 6, 'm'}, + { 'S', 0xa4000000, 7, 'q'}, + { 'S', 0xa8000000, 5, 'k'}, + { 'S', 0xb0000000, 4, 'c'}, + { 'S', 0xc0000000, 3, 'h'}, + { 'S', 0xe0000000, 3, 't'}, + { 'T', 0x00000000, 1, 'h'}, + { 'T', 0x80000000, 4, 'e'}, + { 'T', 0x90000000, 4, 'r'}, + { 'T', 0xa0000000, 3, 'o'}, + { 'T', 0xc0000000, 5, 'a'}, + { 'T', 0xc83e1600, 24, '-'}, + { 'T', 0xc9000000, 8, 'y'}, + { 'T', 0xcb800000, 9, '4'}, + { 'T', 0xcc000000, 6, 'i'}, + { 'T', 0xd0000000, 5, 'w'}, + { 'T', 0xd9000000, 10, ' '}, + { 'T', 0xdc000000, 8, 'u'}, + { 'T', 0xdd000000, 8, 'W'}, + { 'T', 0xde000000, 7, 'H'}, + { 'T', 0xe0000000, 3, 'V'}, + { 'U', 0x00000000, 1, 'n'}, + { 'U', 0x80000000, 2, 'p'}, + { 'U', 0xc0000000, 5, 'R'}, + { 'U', 0xc8800000, 9, 'r'}, + { 'U', 0xce000000, 8, 'E'}, + { 'U', 0xd0000000, 4, 'K'}, + { 'U', 0xe0000000, 5, 'S'}, + { 'U', 0xec000000, 6, 's'}, + { 'U', 0xf0000000, 4, 'l'}, + { 'V', 0x20000000, 4, 'e'}, + { 'V', 0x30000000, 4, 'a'}, + { 'V', 0x50000000, 7, '\''}, + { 'V', 0x52000000, 7, '4'}, + { 'V', 0x58000000, 10, 's'}, + { 'V', 0x58e00000, 14, ESCAPE}, + { 'V', 0x5a000000, 7, 'o'}, + { 'V', 0x5c000000, 8, STOP}, + { 'V', 0x60000000, 3, 'i'}, + { 'V', 0x80000000, 1, ' '}, + { 'W', 0x10000000, 5, 'O'}, + { 'W', 0x18000000, 5, 'r'}, + { 'W', 0x20000000, 3, 'h'}, + { 'W', 0x40000000, 2, 'o'}, + { 'W', 0x80000000, 3, 'a'}, + { 'W', 0xa0000000, 3, 'i'}, + { 'W', 0xc0000000, 2, 'e'}, + { 'X', 0x80000000, 2, ' '}, + { 'X', 0xc0000000, 2, 't'}, + { 'Y', 0x40000000, 2, 'e'}, + { 'Y', 0x80000000, 1, 'o'}, + { 'Z', 0x00000000, 2, 'a'}, + { 'Z', 0x70000000, 5, 'e'}, + { 'Z', 0x7e000000, 8, STOP}, + { 'Z', 0x80000000, 1, 'o'}, + { '\'', 0x00000000, 3, 'm'}, + { '\'', 0x20000000, 4, 't'}, + { '\'', 0x30000000, 4, ' '}, + { '\'', 0x40000000, 3, 'C'}, + { '\'', 0x60000000, 5, 'd'}, + { '\'', 0x68000000, 8, 'G'}, + { '\'', 0x69700000, 13, 'K'}, + { '\'', 0x6c000000, 6, 'r'}, + { '\'', 0x70000000, 5, 'v'}, + { '\'', 0x79000000, 8, 'l'}, + { '\'', 0x7a400000, 10, STOP}, + { '\'', 0x7b800000, 13, '0'}, + { '\'', 0x7b880000, 14, ESCAPE}, + { '\'', 0x80000000, 1, 's'}, + { 'a', 0x00000000, 7, 'e'}, + { 'a', 0x02000000, 7, '\''}, + { 'a', 0x04000000, 10, '!'}, + { 'a', 0x04600000, 11, 'a'}, + { 'a', 0x04800000, 9, ':'}, + { 'a', 0x05000000, 8, 'f'}, + { 'a', 0x06000000, 7, 'w'}, + { 'a', 0x08000000, 6, 'b'}, + { 'a', 0x0c000000, 8, STOP}, + { 'a', 0x10000000, 4, 'm'}, + { 'a', 0x20000000, 3, 'r'}, + { 'a', 0x40000000, 4, 'c'}, + { 'a', 0x50000000, 10, 'o'}, + { 'a', 0x50400000, 10, 'x'}, + { 'a', 0x50900000, 13, 'j'}, + { 'a', 0x50e00000, 11, ','}, + { 'a', 0x51000000, 8, 'h'}, + { 'a', 0x52000000, 7, 'u'}, + { 'a', 0x54000000, 7, 'z'}, + { 'a', 0x56000000, 7, 'v'}, + { 'a', 0x58000000, 6, 'p'}, + { 'a', 0x5c000000, 6, 'g'}, + { 'a', 0x60000000, 3, 't'}, + { 'a', 0x80000000, 3, 'l'}, + { 'a', 0xa0000000, 4, 's'}, + { 'a', 0xb0000000, 5, ' '}, + { 'a', 0xb8000000, 5, 'd'}, + { 'a', 0xb8000000, 5, 'd'}, + { 'a', 0xc0000000, 3, 'n'}, + { 'a', 0xe0000000, 4, 'y'}, + { 'a', 0xf0000000, 5, 'i'}, + { 'a', 0xf8000000, 5, 'k'}, + { 'b', 0x00000000, 3, 'r'}, + { 'b', 0x20000000, 3, 'o'}, + { 'b', 0x40000000, 3, 'e'}, + { 'b', 0x60000000, 3, 'a'}, + { 'b', 0x80000000, 3, 'i'}, + { 'b', 0xa0000000, 6, 'h'}, + { 'b', 0xa4000000, 7, ':'}, + { 'b', 0xa6400000, 10, 't'}, + { 'b', 0xa8000000, 5, 's'}, + { 'b', 0xb0000000, 4, 'u'}, + { 'b', 0xc0000000, 4, 'y'}, + { 'b', 0xd0000000, 4, 'l'}, + { 'b', 0xe0000000, 5, 'b'}, + { 'b', 0xe8000000, 5, STOP}, + { 'b', 0xf0000000, 4, ' '}, + { 'c', 0x00000000, 2, 'k'}, + { 'c', 0x40000000, 3, 'o'}, + { 'c', 0x60000000, 6, 'l'}, + { 'c', 0x64000000, 6, 'y'}, + { 'c', 0x68000000, 6, 's'}, + { 'c', 0x6c000000, 6, STOP}, + { 'c', 0x70000000, 4, 'r'}, + { 'c', 0x80000000, 3, 'h'}, + { 'c', 0xa0000000, 5, ' '}, + { 'c', 0xa8000000, 7, 'c'}, + { 'c', 0xaa000000, 8, ':'}, + { 'c', 0xac500000, 12, '\''}, + { 'c', 0xac600000, 11, 'A'}, + { 'c', 0xac800000, 9, 'D'}, + { 'c', 0xad400000, 11, 'q'}, + { 'c', 0xad680000, 13, 'I'}, + { 'c', 0xae000000, 7, 'u'}, + { 'c', 0xb0000000, 5, 'i'}, + { 'c', 0xb8000000, 5, 'a'}, + { 'c', 0xc0000000, 3, 't'}, + { 'c', 0xe0000000, 3, 'e'}, + { 'd', 0x00000000, 5, 'o'}, + { 'd', 0x08000000, 7, '\''}, + { 'd', 0x0a000000, 8, ':'}, + { 'd', 0x0b000000, 8, 'h'}, + { 'd', 0x0c000000, 6, 'u'}, + { 'd', 0x10000000, 4, 'y'}, + { 'd', 0x20000000, 3, 'e'}, + { 'd', 0x40000000, 4, 'i'}, + { 'd', 0x50000000, 5, 'd'}, + { 'd', 0x58000000, 6, 'r'}, + { 'd', 0x5c000000, 6, 'l'}, + { 'd', 0x60000000, 4, 's'}, + { 'd', 0x70000000, 8, 'c'}, + { 'd', 0x71c00000, 10, 'm'}, + { 'd', 0x72000000, 8, 'n'}, + { 'd', 0x73000000, 8, 'w'}, + { 'd', 0x74000000, 6, 'v'}, + { 'd', 0x78000000, 6, 'g'}, + { 'd', 0x7c000000, 9, '!'}, + { 'd', 0x7c800000, 9, '-'}, + { 'd', 0x7d000000, 9, 'f'}, + { 'd', 0x7d800000, 10, ','}, + { 'd', 0x7dc00000, 11, 't'}, + { 'd', 0x7de00000, 11, 'b'}, + { 'd', 0x7e000000, 7, '.'}, + { 'd', 0x80000000, 3, STOP}, + { 'd', 0xa0000000, 3, 'a'}, + { 'd', 0xc0000000, 2, ' '}, + { 'e', 0x00000000, 3, 's'}, + { 'e', 0x20000000, 4, 't'}, + { 'e', 0x30000000, 8, 'g'}, + { 'e', 0x31000000, 8, 'f'}, + { 'e', 0x32000000, 8, 'x'}, + { 'e', 0x33000000, 10, 'P'}, + { 'e', 0x33400000, 10, 'B'}, + { 'e', 0x33800000, 9, 'h'}, + { 'e', 0x34000000, 7, 'i'}, + { 'e', 0x36000000, 7, 'p'}, + { 'e', 0x38000000, 6, 'm'}, + { 'e', 0x3c000000, 7, 'b'}, + { 'e', 0x3e000000, 8, 'k'}, + { 'e', 0x3f000000, 8, ':'}, + { 'e', 0x40000000, 2, ' '}, + { 'e', 0x80000000, 5, 'l'}, + { 'e', 0x88000000, 6, 'c'}, + { 'e', 0x8c000000, 6, 'd'}, + { 'e', 0x90000000, 4, 'n'}, + { 'e', 0xa0000000, 3, 'r'}, + { 'e', 0xc0000000, 8, STOP}, + { 'e', 0xd0000000, 7, 'v'}, + { 'e', 0xd2000000, 10, ','}, + { 'e', 0xd2400000, 11, '4'}, + { 'e', 0xd2600000, 11, '?'}, + { 'e', 0xd2800000, 9, '.'}, + { 'e', 0xd3000000, 8, 'o'}, + { 'e', 0xd4000000, 8, '\''}, + { 'e', 0xd5000000, 10, 'V'}, + { 'e', 0xd5400000, 10, 'z'}, + { 'e', 0xd5820000, 15, 'G'}, + { 'e', 0xd5840000, 14, 'q'}, + { 'e', 0xd5880000, 13, '!'}, + { 'e', 0xd5900000, 12, '-'}, + { 'e', 0xd5a00000, 11, 'u'}, + { 'e', 0xd5c00000, 10, 'j'}, + { 'e', 0xd6000000, 7, 'y'}, + { 'e', 0xd8000000, 5, 'e'}, + { 'e', 0xe0000000, 4, 'a'}, + { 'e', 0xf0000000, 4, 'w'}, + { 'f', 0x00000000, 1, ' '}, + { 'f', 0x80000000, 5, '.'}, + { 'f', 0x88000000, 6, STOP}, + { 'f', 0x8cb00000, 12, 's'}, + { 'f', 0x8d000000, 8, 'y'}, + { 'f', 0x8e700000, 12, ':'}, + { 'f', 0x8f000000, 8, 'u'}, + { 'f', 0x90000000, 4, 't'}, + { 'f', 0xa0000000, 3, 'o'}, + { 'f', 0xc0000000, 4, 'a'}, + { 'f', 0xd0000000, 4, 'i'}, + { 'f', 0xe0000000, 5, 'r'}, + { 'f', 0xe8000000, 5, 'f'}, + { 'f', 0xf0000000, 4, 'e'}, + { 'g', 0x00000000, 2, 'h'}, + { 'g', 0x40000000, 8, STOP}, + { 'g', 0x60000000, 3, 'e'}, + { 'g', 0x80000000, 2, ' '}, + { 'g', 0xc0000000, 4, 'i'}, + { 'g', 0xd0000000, 6, 's'}, + { 'g', 0xd5000000, 10, '.'}, + { 'g', 0xd5800000, 10, '\''}, + { 'g', 0xd5c00000, 10, 't'}, + { 'g', 0xd6000000, 7, 'b'}, + { 'g', 0xd8000000, 7, 'g'}, + { 'g', 0xda000000, 7, 'o'}, + { 'g', 0xdc000000, 6, 'l'}, + { 'g', 0xe0000000, 5, ':'}, + { 'g', 0xe8000000, 5, 'r'}, + { 'g', 0xf1000000, 11, 'w'}, + { 'g', 0xf1300000, 12, 'm'}, + { 'g', 0xf1400000, 10, 'y'}, + { 'g', 0xf1800000, 9, 'd'}, + { 'g', 0xf2000000, 7, 'n'}, + { 'g', 0xf4000000, 6, 'u'}, + { 'g', 0xf8000000, 5, 'a'}, + { 'h', 0x00000000, 1, 'e'}, + { 'h', 0x80000000, 6, 'b'}, + { 'h', 0x84000000, 6, 'u'}, + { 'h', 0x88000000, 8, 'w'}, + { 'h', 0x89000000, 8, 'd'}, + { 'h', 0x8a000000, 8, 'n'}, + { 'h', 0x8b000000, 8, 'y'}, + { 'h', 0x8d000000, 8, 'l'}, + { 'h', 0x8e000000, 9, '\''}, + { 'h', 0x8e800000, 10, 's'}, + { 'h', 0x8ec00000, 11, 'm'}, + { 'h', 0x8ee80000, 14, 'c'}, + { 'h', 0x8eee0000, 16, 'g'}, + { 'h', 0x8eef0000, 17, '-'}, + { 'h', 0x8f000000, 8, '.'}, + { 'h', 0x90000000, 4, 'i'}, + { 'h', 0xa0000000, 3, 'o'}, + { 'h', 0xc0000000, 4, 'a'}, + { 'h', 0xd0000000, 5, 'r'}, + { 'h', 0xd8000000, 8, STOP}, + { 'h', 0xe0000000, 4, ' '}, + { 'h', 0xf0000000, 4, 't'}, + { 'i', 0x00000000, 3, 'c'}, + { 'i', 0x20000000, 6, 'p'}, + { 'i', 0x24060000, 15, 'j'}, + { 'i', 0x24200000, 11, 'h'}, + { 'i', 0x24400000, 11, ':'}, + { 'i', 0x24600000, 11, 'w'}, + { 'i', 0x26000000, 8, 'x'}, + { 'i', 0x27000000, 10, 'u'}, + { 'i', 0x28000000, 5, 'a'}, + { 'i', 0x30000000, 5, 'v'}, + { 'i', 0x38000000, 6, ' '}, + { 'i', 0x3c000000, 7, 'z'}, + { 'i', 0x3e000000, 8, STOP}, + { 'i', 0x40000000, 2, 'n'}, + { 'i', 0x80000000, 5, 'r'}, + { 'i', 0x88000000, 5, 'd'}, + { 'i', 0x90000000, 4, 'o'}, + { 'i', 0xa0000000, 4, 'l'}, + { 'i', 0xb0000000, 5, 'm'}, + { 'i', 0xb8000000, 7, 'b'}, + { 'i', 0xba000000, 7, 'k'}, + { 'i', 0xbc000000, 6, 'f'}, + { 'i', 0xc0000000, 4, 'g'}, + { 'i', 0xd0000000, 4, 's'}, + { 'i', 0xe0000000, 4, 't'}, + { 'i', 0xf0000000, 4, 'e'}, + { 'j', 0x00000000, 1, 'y'}, + { 'j', 0x84000000, 6, 'i'}, + { 'j', 0x88000000, 5, 'u'}, + { 'j', 0x90000000, 4, 'a'}, + { 'j', 0xa0000000, 3, 'e'}, + { 'k', 0x00000000, 2, ' '}, + { 'k', 0x40000000, 3, 'i'}, + { 'k', 0x60000000, 4, 'y'}, + { 'k', 0x70000000, 4, 's'}, + { 'k', 0x80000000, 2, 'e'}, + { 'k', 0xc0000000, 8, STOP}, + { 'k', 0xe0000000, 8, '\''}, + { 'k', 0xe1000000, 11, 'b'}, + { 'k', 0xe1800000, 9, 'w'}, + { 'k', 0xe2000000, 7, ':'}, + { 'k', 0xe4000000, 6, 'a'}, + { 'k', 0xe8000000, 6, 'l'}, + { 'k', 0xec000000, 7, 'k'}, + { 'k', 0xee000000, 9, 'o'}, + { 'k', 0xeea00000, 12, '?'}, + { 'k', 0xeeb80000, 13, 't'}, + { 'k', 0xeee00000, 11, 'n'}, + { 'k', 0xf0000000, 4, 'f'}, + { 'l', 0x00000000, 3, 'l'}, + { 'l', 0x20000000, 5, 'u'}, + { 'l', 0x28000000, 6, 't'}, + { 'l', 0x2c000000, 6, 'm'}, + { 'l', 0x30000000, 4, 'y'}, + { 'l', 0x40000000, 2, 'e'}, + { 'l', 0x80000000, 8, STOP}, + { 'l', 0x90000000, 4, 'd'}, + { 'l', 0xa0000000, 3, 'a'}, + { 'l', 0xc0000000, 4, 'o'}, + { 'l', 0xd0000000, 5, 's'}, + { 'l', 0xd8000000, 8, 'f'}, + { 'l', 0xd9000000, 11, 'z'}, + { 'l', 0xd9400000, 10, '.'}, + { 'l', 0xd9800000, 9, 'v'}, + { 'l', 0xda000000, 7, 'k'}, + { 'l', 0xdc000000, 8, 'b'}, + { 'l', 0xdd000000, 9, ':'}, + { 'l', 0xdd800000, 10, 'w'}, + { 'l', 0xddc00000, 13, 'g'}, + { 'l', 0xdddb0000, 16, '?'}, + { 'l', 0xde000000, 8, '\''}, + { 'l', 0xdf000000, 8, 'c'}, + { 'l', 0xe0000000, 4, 'i'}, + { 'l', 0xf0000000, 4, ' '}, + { 'm', 0x00000000, 4, 'i'}, + { 'm', 0x10000000, 8, STOP}, + { 'm', 0x20000000, 3, 'm'}, + { 'm', 0x40000000, 4, 'y'}, + { 'm', 0x50000000, 5, 'b'}, + { 'm', 0x5a000000, 8, ':'}, + { 'm', 0x5b000000, 9, 'h'}, + { 'm', 0x5b800000, 13, ESCAPE}, + { 'm', 0x5ba00000, 11, '.'}, + { 'm', 0x5bc00000, 10, '\''}, + { 'm', 0x5c000000, 7, 'f'}, + { 'm', 0x5f000000, 9, 'w'}, + { 'm', 0x5f800000, 10, 'r'}, + { 'm', 0x5fc00000, 10, 'u'}, + { 'm', 0x60000000, 3, ' '}, + { 'm', 0x80000000, 2, 'e'}, + { 'm', 0xc0000000, 5, 'o'}, + { 'm', 0xc8000000, 6, 'n'}, + { 'm', 0xcc000000, 6, 's'}, + { 'm', 0xd0000000, 4, 'p'}, + { 'm', 0xe0000000, 3, 'a'}, + { 'n', 0x00000000, 3, 'i'}, + { 'n', 0x20000000, 7, 'r'}, + { 'n', 0x22000000, 8, 'v'}, + { 'n', 0x23000000, 10, '!'}, + { 'n', 0x23600000, 12, 'B'}, + { 'n', 0x23800000, 9, ','}, + { 'n', 0x24000000, 8, '-'}, + { 'n', 0x25000000, 8, '.'}, + { 'n', 0x26000000, 7, 'f'}, + { 'n', 0x28000000, 6, 'y'}, + { 'n', 0x2c000000, 7, 'u'}, + { 'n', 0x2e000000, 7, 'j'}, + { 'n', 0x30000000, 4, 'a'}, + { 'n', 0x40000000, 4, 's'}, + { 'n', 0x50000000, 6, '\''}, + { 'n', 0x54000000, 6, 'k'}, + { 'n', 0x58000000, 8, 'l'}, + { 'n', 0x59000000, 12, 'w'}, + { 'n', 0x59140000, 14, 'p'}, + { 'n', 0x59180000, 13, 'q'}, + { 'n', 0x59400000, 11, 'h'}, + { 'n', 0x59600000, 11, 'b'}, + { 'n', 0x59800000, 9, 'm'}, + { 'n', 0x5a000000, 8, 'x'}, + { 'n', 0x5b000000, 8, ':'}, + { 'n', 0x5c000000, 6, 'o'}, + { 'n', 0x60000000, 4, 'e'}, + { 'n', 0x70000000, 5, 'c'}, + { 'n', 0x78000000, 5, 'n'}, + { 'n', 0x80000000, 3, 'g'}, + { 'n', 0xa0000000, 3, ' '}, + { 'n', 0xc0000000, 3, 'd'}, + { 'n', 0xe0000000, 8, STOP}, + { 'n', 0xf0000000, 4, 't'}, + { 'o', 0x00000000, 2, 'r'}, + { 'o', 0x40000000, 4, 'f'}, + { 'o', 0x50000000, 4, ' '}, + { 'o', 0x60000000, 4, 'w'}, + { 'o', 0x70000000, 6, 'a'}, + { 'o', 0x74000000, 6, 'b'}, + { 'o', 0x78000000, 5, 't'}, + { 'o', 0x80000000, 4, 'o'}, + { 'o', 0x90000000, 5, 'c'}, + { 'o', 0x98000000, 6, 'y'}, + { 'o', 0x9c000000, 8, STOP}, + { 'o', 0xa0000000, 5, 'p'}, + { 'o', 0xa8000000, 5, 'd'}, + { 'o', 0xb0000000, 4, 'u'}, + { 'o', 0xc0000000, 3, 'n'}, + { 'o', 0xe0000000, 5, 'm'}, + { 'o', 0xe8000000, 6, 's'}, + { 'o', 0xec000000, 6, 'k'}, + { 'o', 0xf0000000, 5, 'l'}, + { 'o', 0xf8180000, 14, ','}, + { 'o', 0xf8200000, 11, '?'}, + { 'o', 0xf8400000, 11, ':'}, + { 'o', 0xf8600000, 12, '.'}, + { 'o', 0xf8800000, 9, 'h'}, + { 'o', 0xf9000000, 9, '!'}, + { 'o', 0xf9800000, 10, '\''}, + { 'o', 0xf9c00000, 11, 'z'}, + { 'o', 0xf9e00000, 11, 'x'}, + { 'o', 0xfa000000, 7, 'v'}, + { 'o', 0xfc000000, 7, 'g'}, + { 'o', 0xfe000000, 9, 'e'}, + { 'o', 0xfe800000, 9, 'j'}, + { 'o', 0xff000000, 8, 'i'}, + { 'p', 0x00000000, 2, 'e'}, + { 'p', 0x40000000, 8, STOP}, + { 'p', 0x60000000, 4, 's'}, + { 'p', 0x70000000, 5, 'l'}, + { 'p', 0x78000000, 5, 'r'}, + { 'p', 0x80000000, 3, 'i'}, + { 'p', 0xa0000000, 4, ' '}, + { 'p', 0xb0000000, 5, 'h'}, + { 'p', 0xb8000000, 6, 't'}, + { 'p', 0xbc000000, 6, '\''}, + { 'p', 0xc0000000, 3, 'o'}, + { 'p', 0xe0000000, 4, 'p'}, + { 'p', 0xf0000000, 5, 'a'}, + { 'p', 0xf8000000, 7, 'd'}, + { 'p', 0xfa000000, 7, 'm'}, + { 'p', 0xfc000000, 7, 'y'}, + { 'p', 0xfe000000, 10, '?'}, + { 'p', 0xfe600000, 11, '.'}, + { 'p', 0xff000000, 10, 'w'}, + { 'p', 0xff400000, 10, 'u'}, + { 'p', 0xff800000, 9, '!'}, + { 'q', 0x10000000, 4, '\''}, + { 'q', 0x40000000, 8, STOP}, + { 'q', 0x80000000, 1, 'u'}, + { 'r', 0x00000000, 3, ' '}, + { 'r', 0x20000000, 7, '\''}, + { 'r', 0x22000000, 8, 'f'}, + { 'r', 0x23000000, 8, '.'}, + { 'r', 0x24000000, 6, 'k'}, + { 'r', 0x28000000, 6, 'r'}, + { 'r', 0x2c000000, 6, 'm'}, + { 'r', 0x30000000, 4, 'y'}, + { 'r', 0x40000000, 4, 'd'}, + { 'r', 0x50000000, 9, ','}, + { 'r', 0x50800000, 9, 'p'}, + { 'r', 0x51000000, 8, 'b'}, + { 'r', 0x52000000, 7, 'c'}, + { 'r', 0x54000000, 6, 'u'}, + { 'r', 0x58000000, 5, 'n'}, + { 'r', 0x60000000, 3, 'i'}, + { 'r', 0x80000000, 4, 's'}, + { 'r', 0x90000000, 4, 't'}, + { 'r', 0xa0000000, 3, 'e'}, + { 'r', 0xc0000000, 4, 'a'}, + { 'r', 0xd0000000, 4, STOP}, + { 'r', 0xe0000000, 8, 'v'}, + { 'r', 0xe1000000, 9, 'w'}, + { 'r', 0xe1800000, 11, '-'}, + { 'r', 0xe1a00000, 12, 'h'}, + { 'r', 0xe1c00000, 10, 'j'}, + { 'r', 0xe2000000, 7, ':'}, + { 'r', 0xe4000000, 6, 'g'}, + { 'r', 0xe8000000, 5, 'l'}, + { 'r', 0xf0000000, 4, 'o'}, + { 's', 0x00000000, 4, 's'}, + { 's', 0x10000000, 7, '.'}, + { 's', 0x12000000, 7, '!'}, + { 's', 0x14000000, 8, ','}, + { 's', 0x15000000, 8, 'f'}, + { 's', 0x16000000, 7, 'y'}, + { 's', 0x20000000, 4, 'i'}, + { 's', 0x30000000, 4, 'h'}, + { 's', 0x40000000, 7, 'p'}, + { 's', 0x42000000, 11, '?'}, + { 's', 0x42200000, 11, 'w'}, + { 's', 0x42400000, 10, 'm'}, + { 's', 0x42800000, 9, 'k'}, + { 's', 0x43000000, 8, '\''}, + { 's', 0x44000000, 6, 'o'}, + { 's', 0x48000000, 7, 'a'}, + { 's', 0x4a000000, 9, 'd'}, + { 's', 0x4a800000, 11, 'g'}, + { 's', 0x4aa00000, 12, 'q'}, + { 's', 0x4ac00000, 10, 'b'}, + { 's', 0x4b000000, 8, 'n'}, + { 's', 0x4c000000, 6, 'c'}, + { 's', 0x50000000, 5, 'e'}, + { 's', 0x58000000, 6, ':'}, + { 's', 0x5c000000, 8, 'l'}, + { 's', 0x5d000000, 8, 'r'}, + { 's', 0x5e000000, 7, 'u'}, + { 's', 0x60000000, 3, 't'}, + { 's', 0x80000000, 2, ' '}, + { 's', 0xc0000000, 2, STOP}, + { 't', 0x00000000, 3, 'i'}, + { 't', 0x20000000, 4, 'a'}, + { 't', 0x30000000, 7, '\''}, + { 't', 0x32000000, 8, 'w'}, + { 't', 0x33000000, 9, '?'}, + { 't', 0x33c00000, 11, '-'}, + { 't', 0x33e00000, 11, ','}, + { 't', 0x34000000, 7, ':'}, + { 't', 0x36000000, 8, '!'}, + { 't', 0x37000000, 9, 'n'}, + { 't', 0x37800000, 10, 'd'}, + { 't', 0x38000000, 5, 't'}, + { 't', 0x40000000, 4, 'r'}, + { 't', 0x50000000, 5, 'y'}, + { 't', 0x58000000, 6, 'm'}, + { 't', 0x5c000000, 8, '.'}, + { 't', 0x5d000000, 8, 'b'}, + { 't', 0x5e000000, 8, 'E'}, + { 't', 0x60000000, 8, STOP}, + { 't', 0x80000000, 3, ' '}, + { 't', 0xa0000000, 4, 's'}, + { 't', 0xb0000000, 4, 'o'}, + { 't', 0xc0000000, 5, 'u'}, + { 't', 0xc8000000, 6, 'c'}, + { 't', 0xcc000000, 6, 'l'}, + { 't', 0xd0000000, 4, 'e'}, + { 't', 0xe0000000, 3, 'h'}, + { 'u', 0x00000000, 2, 'r'}, + { 'u', 0x40000000, 4, 'e'}, + { 'u', 0x50000000, 4, 'm'}, + { 'u', 0x60000000, 5, 'c'}, + { 'u', 0x68000000, 5, 'g'}, + { 'u', 0x70000000, 5, 'b'}, + { 'u', 0x78000000, 6, STOP}, + { 'u', 0x7e800000, 10, 'f'}, + { 'u', 0x7f000000, 8, '\''}, + { 'u', 0x80000000, 3, 's'}, + { 'u', 0xa0000000, 5, 'p'}, + { 'u', 0xa8000000, 5, 'i'}, + { 'u', 0xb0000000, 5, 'l'}, + { 'u', 0xb8000000, 6, 'y'}, + { 'u', 0xbc000000, 7, ' '}, + { 'u', 0xbf000000, 10, 'w'}, + { 'u', 0xbf400000, 12, 'v'}, + { 'u', 0xbf500000, 12, 'x'}, + { 'u', 0xbf600000, 13, 'j'}, + { 'u', 0xc0000000, 4, 't'}, + { 'u', 0xd0000000, 5, 'd'}, + { 'u', 0xd8000000, 5, 'a'}, + { 'u', 0xe0000000, 3, 'n'}, + { 'v', 0x00000000, 5, '.'}, + { 'v', 0x08000000, 7, 'y'}, + { 'v', 0x0a000000, 10, ESCAPE}, + { 'v', 0x0b000000, 8, 's'}, + { 'v', 0x10000000, 4, 'o'}, + { 'v', 0x20000000, 3, 'a'}, + { 'v', 0x40000000, 2, 'i'}, + { 'v', 0x80000000, 1, 'e'}, + { 'w', 0x00000000, 1, 's'}, + { 'w', 0x80000000, 3, ' '}, + { 'w', 0xa0000000, 5, 'a'}, + { 'w', 0xa8000000, 8, 'm'}, + { 'w', 0xa9800000, 9, 'b'}, + { 'w', 0xaa000000, 9, 'k'}, + { 'w', 0xaa800000, 9, 'r'}, + { 'w', 0xab000000, 8, 'd'}, + { 'w', 0xac000000, 11, 'c'}, + { 'w', 0xac200000, 11, 'f'}, + { 'w', 0xacc00000, 10, 'h'}, + { 'w', 0xad000000, 8, 'l'}, + { 'w', 0xae000000, 7, 'y'}, + { 'w', 0xb0000000, 4, 'i'}, + { 'w', 0xc0000000, 3, STOP}, + { 'w', 0xe0000000, 4, 'o'}, + { 'w', 0xf0000000, 5, 'n'}, + { 'w', 0xf8000000, 5, 'e'}, + { 'x', 0x00000000, 2, 'p'}, + { 'x', 0x40000000, 5, 'o'}, + { 'x', 0x48000000, 6, 'e'}, + { 'x', 0x4e000000, 7, 'f'}, + { 'x', 0x50000000, 5, 'c'}, + { 'x', 0x58000000, 6, 'y'}, + { 'x', 0x5c800000, 9, 'a'}, + { 'x', 0x5d000000, 12, ESCAPE}, + { 'x', 0x5d400000, 10, '\''}, + { 'x', 0x60000000, 4, STOP}, + { 'x', 0x70000000, 5, 'i'}, + { 'x', 0x80000000, 2, ' '}, + { 'x', 0xc0000000, 2, 't'}, + { 'y', 0x00000000, 1, ' '}, + { 'y', 0x80000000, 8, 'i'}, + { 'y', 0x81800000, 9, 'f'}, + { 'y', 0x82000000, 7, 'n'}, + { 'y', 0x84000000, 7, 't'}, + { 'y', 0x86000000, 8, ','}, + { 'y', 0x87000000, 8, 'p'}, + { 'y', 0x88000000, 5, 'o'}, + { 'y', 0x90000000, 5, 's'}, + { 'y', 0x98000000, 6, 'd'}, + { 'y', 0x9c000000, 8, 'm'}, + { 'y', 0x9d000000, 9, 'r'}, + { 'y', 0x9d800000, 9, 'g'}, + { 'y', 0x9e000000, 8, 'c'}, + { 'y', 0x9f500000, 13, 'v'}, + { 'y', 0x9f5c0000, 15, 'h'}, + { 'y', 0xa0000000, 5, 'a'}, + { 'y', 0xa8000000, 7, '\''}, + { 'y', 0xaa000000, 7, 'b'}, + { 'y', 0xac000000, 8, 'w'}, + { 'y', 0xad000000, 8, 'e'}, + { 'y', 0xae000000, 7, '.'}, + { 'y', 0xb0000000, 5, 'l'}, + { 'y', 0xb8000000, 5, ':'}, + { 'y', 0xc0000000, 8, STOP}, + { 'z', 0x00000000, 2, 'z'}, + { 'z', 0x40000000, 2, STOP}, + { 'z', 0x80000000, 4, 'y'}, + { 'z', 0x90000000, 4, 'e'}, + { 'z', 0xa0000000, 3, 'i'}, + { 'z', 0xd0000000, 4, ' '}, + { 'z', 0xe0000000, 4, 'l'}, + { 'z', 0xf0000000, 5, 'a'}, + { 'z', 0xf8000000, 6, 'o'}, + { 'z', 0xfc000000, 8, 'm'} +}; + + +/* + * This table was derived from on-air transmissions. It certainly has omissions and + * almost certainly contains errors. Use entirely at your own risk. + */ + +static struct hufftab fsat_huffman2[] = +{ + { START, 0x00000000, 5, 'H'}, + { START, 0x08000000, 6, 'O'}, + { START, 0x0c000000, 7, 'K'}, + { START, 0x0e000000, 8, '2'}, + { START, 0x0f000000, 9, 'Q'}, + { START, 0x0f800000, 10, '9'}, + { START, 0x0fc00000, 10, '8'}, + { START, 0x10000000, 4, 'J'}, + { START, 0x20000000, 5, 'I'}, + { START, 0x28000000, 5, 'R'}, + { START, 0x30000000, 4, 'D'}, + { START, 0x40000000, 3, 'A'}, + { START, 0x62000000, 8, 'U'}, + { START, 0x63000000, 8, '('}, + { START, 0x64000000, 6, '['}, + { START, 0x68000000, 5, 'F'}, + { START, 0x70000000, 5, '.'}, + { START, 0x78000000, 5, 'W'}, + { START, 0x80000000, 3, 'C'}, + { START, 0xa0000000, 4, 'S'}, + { START, 0xb0000000, 8, '1'}, + { START, 0xb1000000, 9, '3'}, + { START, 0xb1800000, 10, '6'}, + { START, 0xb1c00000, 10, '5'}, + { START, 0xb2000000, 10, 'Z'}, + { START, 0xb2400000, 10, '7'}, + { START, 0xb2800000, 10, '4'}, + { START, 0xb2f00000, 12, ' '}, + { START, 0xb3000000, 8, 'V'}, + { START, 0xb4000000, 6, 'L'}, + { START, 0xb8000000, 5, 'M'}, + { START, 0xc0000000, 5, 'B'}, + { START, 0xc8000000, 5, 'P'}, + { START, 0xd0000000, 7, 'Y'}, + { START, 0xd2000000, 7, 'G'}, + { START, 0xd4000000, 6, 'E'}, + { START, 0xd8000000, 5, 'N'}, + { START, 0xe0000000, 3, 'T'}, + { ' ', 0x00000000, 6, 'A'}, + { ' ', 0x04000000, 8, 'k'}, + { ' ', 0x05000000, 8, 'O'}, + { ' ', 0x06000000, 7, 'v'}, + { ' ', 0x08000000, 7, 'G'}, + { ' ', 0x0a000000, 7, 'N'}, + { ' ', 0x0c000000, 6, 'M'}, + { ' ', 0x10000000, 4, 'o'}, + { ' ', 0x20000000, 4, 's'}, + { ' ', 0x30000000, 5, 'd'}, + { ' ', 0x38000000, 10, '3'}, + { ' ', 0x38400000, 10, '8'}, + { ' ', 0x38800000, 10, '6'}, + { ' ', 0x38c00000, 11, '0'}, + { ' ', 0x38e60000, 15, '$'}, + { ' ', 0x38f00000, 12, 'X'}, + { ' ', 0x39000000, 9, 'q'}, + { ' ', 0x39800000, 9, 'U'}, + { ' ', 0x3a000000, 7, 'y'}, + { ' ', 0x3c000000, 6, 'e'}, + { ' ', 0x40000000, 3, 'a'}, + { ' ', 0x60000000, 5, '['}, + { ' ', 0x68000000, 8, '-'}, + { ' ', 0x69000000, 9, 'V'}, + { ' ', 0x69800000, 11, '\''}, + { ' ', 0x69a00000, 11, '9'}, + { ' ', 0x69c00000, 10, '5'}, + { ' ', 0x6a000000, 7, 'H'}, + { ' ', 0x6c000000, 9, 'Y'}, + { ' ', 0x6c800000, 9, ' '}, + { ' ', 0x6d000000, 8, '1'}, + { ' ', 0x6e000000, 7, 'L'}, + { ' ', 0x70000000, 6, 'B'}, + { ' ', 0x74000000, 6, 'C'}, + { ' ', 0x78000000, 5, 'p'}, + { ' ', 0x80000000, 3, 't'}, + { ' ', 0xa0000000, 6, 'T'}, + { ' ', 0xa4000000, 7, 'J'}, + { ' ', 0xa6000000, 7, 'F'}, + { ' ', 0xa8000000, 5, 'b'}, + { ' ', 0xb0000000, 10, '('}, + { ' ', 0xb0400000, 11, 'Z'}, + { ' ', 0xb0600000, 13, ESCAPE}, + { ' ', 0xb0680000, 13, '.'}, + { ' ', 0xb0700000, 13, '&'}, + { ' ', 0xb0780000, 14, '"'}, + { ' ', 0xb07c0000, 14, 'z'}, + { ' ', 0xb0800000, 9, '2'}, + { ' ', 0xb1000000, 8, 'K'}, + { ' ', 0xb2000000, 7, 'R'}, + { ' ', 0xb4000000, 6, 'S'}, + { ' ', 0xb8000000, 6, 'g'}, + { ' ', 0xbc000000, 7, 'u'}, + { ' ', 0xbe000000, 8, 'j'}, + { ' ', 0xbf000000, 10, STOP}, + { ' ', 0xbf800000, 10, '7'}, + { ' ', 0xbfc00000, 11, '4'}, + { ' ', 0xbfe00000, 11, 'Q'}, + { ' ', 0xc0000000, 6, 'r'}, + { ' ', 0xc4000000, 7, 'D'}, + { ' ', 0xc6000000, 7, 'W'}, + { ' ', 0xc8000000, 5, 'c'}, + { ' ', 0xd0000000, 5, 'h'}, + { ' ', 0xd8000000, 6, 'n'}, + { ' ', 0xdc000000, 6, 'l'}, + { ' ', 0xe0000000, 5, 'w'}, + { ' ', 0xe8000000, 5, 'i'}, + { ' ', 0xf0000000, 8, 'I'}, + { ' ', 0xf1000000, 8, 'E'}, + { ' ', 0xf2000000, 7, 'P'}, + { ' ', 0xf4000000, 6, 'm'}, + { ' ', 0xf8000000, 5, 'f'}, + { '!', 0x00000000, 4, ':'}, + { '!', 0x11c00000, 10, '?'}, + { '!', 0x40000000, 2, STOP}, + { '!', 0x80000000, 1, ' '}, + { '"', 0x20000000, 3, '.'}, + { '"', 0x90000000, 6, 'm'}, + { '"', 0x9e000000, 8, 'P'}, + { '"', 0x9f000000, 10, ESCAPE}, + { '"', 0xac000000, 6, 'I'}, + { '"', 0xb0000000, 7, 'c'}, + { '"', 0xb4000000, 8, 'r'}, + { '"', 0xc0000000, 2, ' '}, + { '$', 0x00000000, 1, '1'}, + { '$', 0xb0000000, 4, '2'}, + { '$', 0xde000000, 9, '3'}, + { '%', 0x80000000, 1, ' '}, + { '&', 0x00000000, 4, 'E'}, + { '&', 0x16000000, 9, ESCAPE}, + { '&', 0x18000000, 6, 'A'}, + { '&', 0x20000000, 3, 'B'}, + { '&', 0x40000000, 2, 'w'}, + { '&', 0x80000000, 1, ' '}, + { '(', 0x00000000, 3, 'P'}, + { '(', 0x23000000, 8, 'E'}, + { '(', 0x24000000, 6, 'a'}, + { '(', 0x28000000, 6, 'S'}, + { '(', 0x2c000000, 7, 'D'}, + { '(', 0x2e000000, 8, 'W'}, + { '(', 0x2f000000, 10, '4'}, + { '(', 0x30000000, 6, 'R'}, + { '(', 0x34800000, 10, '3'}, + { '(', 0x35a00000, 13, ESCAPE}, + { '(', 0x35a80000, 13, 'u'}, + { '(', 0x35b00000, 12, 'O'}, + { '(', 0x36000000, 7, 'K'}, + { '(', 0x38000000, 5, 'T'}, + { '(', 0x40000000, 2, '1'}, + { '(', 0x80000000, 4, '2'}, + { '(', 0x9c000000, 6, 'e'}, + { '(', 0xa0000000, 3, 't'}, + { '(', 0xc2000000, 9, 'w'}, + { '(', 0xc2800000, 9, 'B'}, + { '(', 0xc3000000, 8, 'g'}, + { '(', 0xc4000000, 7, 'G'}, + { '(', 0xc8000000, 7, 'M'}, + { '(', 0xca000000, 7, 'H'}, + { '(', 0xcc000000, 7, 'C'}, + { '(', 0xd0000000, 4, '5'}, + { '(', 0xe0000000, 4, 'N'}, + { '(', 0xf0000000, 6, 'J'}, + { '(', 0xf4000000, 6, 'A'}, + { ')', 0x00000000, 1, ' '}, + { ')', 0x80000000, 5, ':'}, + { ')', 0x8c000000, 6, ';'}, + { ')', 0x90000000, 4, ','}, + { ')', 0xc0000000, 2, '.'}, + { '+', 0x40000000, 2, ' '}, + { ',', 0x20000000, 3, '0'}, + { ',', 0x40000000, 2, 'S'}, + { ',', 0x80000000, 1, ' '}, + { '-', 0x00000000, 2, ' '}, + { '-', 0x40000000, 4, 't'}, + { '-', 0x50000000, 4, 'b'}, + { '-', 0x60000000, 4, 'w'}, + { '-', 0x70000000, 4, 'u'}, + { '-', 0x80000000, 5, 'c'}, + { '-', 0x88000000, 6, '9'}, + { '-', 0x8c000000, 7, 'S'}, + { '-', 0x8e000000, 8, 'C'}, + { '-', 0x8f000000, 10, 'F'}, + { '-', 0x8f480000, 13, '0'}, + { '-', 0x8f600000, 11, 'K'}, + { '-', 0x8f800000, 9, 'H'}, + { '-', 0x90000000, 4, 'o'}, + { '-', 0xa0000000, 4, 's'}, + { '-', 0xb0000000, 4, 'f'}, + { '-', 0xc0000000, 6, 'h'}, + { '-', 0xc4000000, 9, 'A'}, + { '-', 0xc4800000, 10, 'j'}, + { '-', 0xc4c00000, 10, 'P'}, + { '-', 0xc5000000, 8, 'W'}, + { '-', 0xc6000000, 9, '6'}, + { '-', 0xc6800000, 9, 'B'}, + { '-', 0xc7000000, 8, 'g'}, + { '-', 0xc8000000, 6, '1'}, + { '-', 0xcc000000, 6, 'y'}, + { '-', 0xd0000000, 7, 'e'}, + { '-', 0xd2000000, 7, 'i'}, + { '-', 0xd4000000, 6, 'r'}, + { '-', 0xd8000000, 5, 'l'}, + { '-', 0xe0000000, 6, 'a'}, + { '-', 0xe4000000, 11, 'v'}, + { '-', 0xe4200000, 11, 'Z'}, + { '-', 0xe4800000, 10, '5'}, + { '-', 0xe4c00000, 10, 'T'}, + { '-', 0xe5000000, 8, 'J'}, + { '-', 0xe6000000, 8, 'D'}, + { '-', 0xe7000000, 16, '\''}, + { '-', 0xe7080000, 14, '3'}, + { '-', 0xe70c0000, 14, '8'}, + { '-', 0xe7400000, 10, 'I'}, + { '-', 0xe7800000, 9, 'M'}, + { '-', 0xe8000000, 5, 'd'}, + { '-', 0xf0000000, 6, 'm'}, + { '-', 0xf4000000, 9, 'E'}, + { '-', 0xf4800000, 9, 'L'}, + { '-', 0xf5000000, 8, '2'}, + { '-', 0xf6000000, 7, 'n'}, + { '-', 0xf8000000, 6, 'p'}, + { '-', 0xfc000000, 8, '7'}, + { '-', 0xfd000000, 9, 'U'}, + { '-', 0xfd800000, 9, 'k'}, + { '-', 0xfe000000, 8, 'G'}, + { '-', 0xff000000, 8, 'O'}, + { '.', 0x00000000, 7, 'a'}, + { '.', 0x02000000, 7, '['}, + { '.', 0x04000000, 6, 'u'}, + { '.', 0x08000000, 8, '4'}, + { '.', 0x09000000, 10, 'N'}, + { '.', 0x09400000, 12, 'E'}, + { '.', 0x09500000, 12, ':'}, + { '.', 0x09600000, 15, '?'}, + { '.', 0x09700000, 13, 'K'}, + { '.', 0x09780000, 13, 'Y'}, + { '.', 0x09800000, 10, 't'}, + { '.', 0x0a000000, 9, '5'}, + { '.', 0x0b000000, 11, 'r'}, + { '.', 0x0b300000, 14, '"'}, + { '.', 0x0b360000, 17, 'd'}, + { '.', 0x0b368000, 18, ESCAPE}, + { '.', 0x0b370000, 16, 'k'}, + { '.', 0x0b380000, 13, 'O'}, + { '.', 0x0b400000, 10, 'R'}, + { '.', 0x0c000000, 9, 'T'}, + { '.', 0x0d000000, 9, 'M'}, + { '.', 0x0dc00000, 10, 'P'}, + { '.', 0x0e000000, 8, 'H'}, + { '.', 0x0f000000, 9, 'C'}, + { '.', 0x0f800000, 9, '2'}, + { '.', 0x10000000, 5, 'i'}, + { '.', 0x18000000, 8, 'S'}, + { '.', 0x19000000, 8, 'W'}, + { '.', 0x1a000000, 7, '3'}, + { '.', 0x1c000000, 8, 'o'}, + { '.', 0x1d800000, 9, 'D'}, + { '.', 0x1e000000, 8, '1'}, + { '.', 0x1f000000, 9, 'B'}, + { '.', 0x1f800000, 12, '\''}, + { '.', 0x1f980000, 13, '('}, + { '.', 0x1fa00000, 11, 'G'}, + { '.', 0x1fc00000, 10, 'I'}, + { '.', 0x20000000, 5, '0'}, + { '.', 0x28000000, 5, 'c'}, + { '.', 0x30000000, 4, '.'}, + { '.', 0x40000000, 4, STOP}, + { '.', 0x80000000, 1, ' '}, + { '/', 0x00000000, 4, '5'}, + { '/', 0x10000000, 5, 'T'}, + { '/', 0x20000000, 4, '8'}, + { '/', 0x30000000, 5, 'B'}, + { '/', 0x38000000, 5, '2'}, + { '/', 0x45e80000, 13, 'c'}, + { '/', 0x54800000, 9, 'U'}, + { '/', 0x80000000, 7, 'F'}, + { '/', 0x82000000, 11, 'v'}, + { '/', 0x82400000, 10, 'J'}, + { '/', 0x82a00000, 12, 'l'}, + { '/', 0x82c00000, 10, '9'}, + { '/', 0x83000000, 8, 'm'}, + { '/', 0x84000000, 7, 's'}, + { '/', 0x86000000, 7, 'M'}, + { '/', 0x88000000, 5, '3'}, + { '/', 0x90000000, 5, '7'}, + { '/', 0x98000000, 7, 'H'}, + { '/', 0x9a000000, 8, 'W'}, + { '/', 0x9b000000, 9, 'L'}, + { '/', 0x9b800000, 12, 'V'}, + { '/', 0x9b900000, 14, ESCAPE}, + { '/', 0x9c000000, 7, 'D'}, + { '/', 0x9e000000, 7, 'A'}, + { '/', 0xa0000000, 5, '6'}, + { '/', 0xa8000000, 8, 'G'}, + { '/', 0xaa000000, 7, 'S'}, + { '/', 0xac000000, 8, 'd'}, + { '/', 0xae000000, 8, 'N'}, + { '/', 0xaf800000, 9, 'I'}, + { '/', 0xb0000000, 5, 'a'}, + { '/', 0xb8000000, 9, 'E'}, + { '/', 0xb8800000, 9, 'R'}, + { '/', 0xb9000000, 8, 'C'}, + { '/', 0xba000000, 9, 'K'}, + { '/', 0xbb000000, 8, 'P'}, + { '/', 0xbc000000, 6, '4'}, + { '/', 0xc0000000, 3, '1'}, + { '0', 0x00000000, 1, '0'}, + { '0', 0x80000000, 6, '4'}, + { '0', 0x84000000, 6, 't'}, + { '0', 0x88000000, 5, 's'}, + { '0', 0x90000000, 4, 'a'}, + { '0', 0xa0000000, 7, '3'}, + { '0', 0xa2000000, 7, '7'}, + { '0', 0xa4000000, 6, '5'}, + { '0', 0xa8000000, 8, ')'}, + { '0', 0xa9000000, 8, '/'}, + { '0', 0xaa000000, 7, ']'}, + { '0', 0xac000000, 7, '-'}, + { '0', 0xae000000, 7, '1'}, + { '0', 0xb0000000, 4, 'p'}, + { '0', 0xc0000000, 5, '.'}, + { '0', 0xc8000000, 5, '8'}, + { '0', 0xd0000000, 6, '6'}, + { '0', 0xd4000000, 8, STOP}, + { '0', 0xd5000000, 8, '9'}, + { '0', 0xd6000000, 9, '%'}, + { '0', 0xd6800000, 10, ':'}, + { '0', 0xd6e80000, 14, 'k'}, + { '0', 0xd6f00000, 12, 'm'}, + { '0', 0xd7000000, 8, '2'}, + { '0', 0xd8000000, 5, ','}, + { '0', 0xe0000000, 3, ' '}, + { '1', 0x00000000, 2, '9'}, + { '1', 0x40000000, 5, '6'}, + { '1', 0x48000000, 5, '8'}, + { '1', 0x50000000, 4, ' '}, + { '1', 0x60000000, 7, STOP}, + { '1', 0x62000000, 7, '-'}, + { '1', 0x64000000, 6, '7'}, + { '1', 0x68000000, 5, '/'}, + { '1', 0x70000000, 4, '2'}, + { '1', 0x80000000, 3, '1'}, + { '1', 0xa0000000, 5, ']'}, + { '1', 0xa8000000, 7, ')'}, + { '1', 0xaa000000, 8, '\''}, + { '1', 0xab000000, 9, 'X'}, + { '1', 0xabc00000, 11, 't'}, + { '1', 0xabe00000, 11, 'R'}, + { '1', 0xac000000, 7, ':'}, + { '1', 0xae000000, 7, 's'}, + { '1', 0xb0000000, 4, '.'}, + { '1', 0xc0000000, 4, '5'}, + { '1', 0xd0000000, 5, '3'}, + { '1', 0xd8000000, 6, '4'}, + { '1', 0xdc000000, 7, ','}, + { '1', 0xde000000, 7, 'x'}, + { '1', 0xe0000000, 3, '0'}, + { '2', 0x00000000, 3, ' '}, + { '2', 0x20000000, 5, ']'}, + { '2', 0x30000000, 4, '/'}, + { '2', 0x40000000, 3, '.'}, + { '2', 0x60000000, 6, '6'}, + { '2', 0x64000000, 6, '2'}, + { '2', 0x68000000, 5, '1'}, + { '2', 0x70000000, 6, ':'}, + { '2', 0x74000000, 6, '-'}, + { '2', 0x79000000, 8, '3'}, + { '2', 0x7a000000, 8, 't'}, + { '2', 0x7c000000, 6, ')'}, + { '2', 0x80000000, 3, '5'}, + { '2', 0xa2000000, 8, 'n'}, + { '2', 0xa3000000, 9, 'a'}, + { '2', 0xa3800000, 10, '\''}, + { '2', 0xa3d00000, 13, '"'}, + { '2', 0xa3de0000, 15, 'L'}, + { '2', 0xa4000000, 7, '8'}, + { '2', 0xa6000000, 7, '9'}, + { '2', 0xa8000000, 5, '4'}, + { '2', 0xb0000000, 4, ','}, + { '2', 0xc0000000, 2, '0'}, + { '3', 0x00000000, 2, ' '}, + { '3', 0x40000000, 5, '2'}, + { '3', 0x4cda0000, 15, 'm'}, + { '3', 0x50000000, 5, ')'}, + { '3', 0x58000000, 6, 'D'}, + { '3', 0x5c000000, 7, '7'}, + { '3', 0x5e000000, 7, '3'}, + { '3', 0x60000000, 5, ':'}, + { '3', 0x68000000, 6, '4'}, + { '3', 0x70000000, 5, '-'}, + { '3', 0x78980000, 14, ESCAPE}, + { '3', 0x7a000000, 7, '6'}, + { '3', 0x7c000000, 6, '5'}, + { '3', 0x80000000, 2, '0'}, + { '3', 0xc0000000, 3, '.'}, + { '3', 0xe0000000, 4, '/'}, + { '3', 0xf0000000, 6, ','}, + { '3', 0xf4000000, 8, '8'}, + { '3', 0xf5000000, 9, '9'}, + { '3', 0xf5800000, 10, 'r'}, + { '3', 0xf6000000, 7, 't'}, + { '3', 0xf8000000, 5, ']'}, + { '4', 0x00000000, 3, '4'}, + { '4', 0x20000000, 4, '/'}, + { '4', 0x30000000, 5, '1'}, + { '4', 0x38000000, 6, '2'}, + { '4', 0x3c000000, 7, ':'}, + { '4', 0x40000000, 2, ' '}, + { '4', 0x80000000, 3, '.'}, + { '4', 0xa0000000, 4, '5'}, + { '4', 0xb0000000, 4, '-'}, + { '4', 0xc0000000, 3, '0'}, + { '4', 0xe0000000, 7, 't'}, + { '4', 0xe2000000, 7, '3'}, + { '4', 0xe4000000, 6, '8'}, + { '4', 0xe8000000, 5, ']'}, + { '4', 0xf0000000, 5, ','}, + { '4', 0xf8000000, 6, ')'}, + { '4', 0xfc000000, 10, '9'}, + { '4', 0xfc800000, 10, '7'}, + { '4', 0xfce40000, 15, ESCAPE}, + { '4', 0xfd000000, 8, '6'}, + { '5', 0x00000000, 2, '0'}, + { '5', 0x40000000, 3, '.'}, + { '5', 0x60000000, 5, '/'}, + { '5', 0x68000000, 6, '3'}, + { '5', 0x6c000000, 7, ':'}, + { '5', 0x6e000000, 8, '4'}, + { '5', 0x6f200000, 11, ';'}, + { '5', 0x6f440000, 14, 'f'}, + { '5', 0x6fc00000, 10, '1'}, + { '5', 0x70000000, 4, 'p'}, + { '5', 0x80000000, 2, ' '}, + { '5', 0xc0000000, 4, '5'}, + { '5', 0xd0000000, 5, 'a'}, + { '5', 0xd8000000, 5, '-'}, + { '5', 0xe0000000, 7, ')'}, + { '5', 0xe6000000, 7, ','}, + { '5', 0xe8000000, 5, '6'}, + { '5', 0xf0000000, 6, '2'}, + { '5', 0xf4000000, 7, '7'}, + { '5', 0xf6000000, 7, '9'}, + { '5', 0xf8000000, 6, '8'}, + { '5', 0xfc000000, 6, ']'}, + { '6', 0x00000000, 2, ' '}, + { '6', 0x40000000, 7, '6'}, + { '6', 0x44000000, 6, '-'}, + { '6', 0x48000000, 5, '1'}, + { '6', 0x50000000, 4, ']'}, + { '6', 0x60000000, 5, '7'}, + { '6', 0x68000000, 6, '5'}, + { '6', 0x6c000000, 6, '4'}, + { '6', 0x70000000, 5, ')'}, + { '6', 0x78000000, 7, '3'}, + { '6', 0x7a000000, 7, '2'}, + { '6', 0x7c000000, 6, '8'}, + { '6', 0x80000000, 2, '.'}, + { '6', 0xc0000000, 5, ','}, + { '6', 0xc8000000, 5, ':'}, + { '6', 0xd0000000, 5, '/'}, + { '6', 0xd9fc0000, 15, ESCAPE}, + { '6', 0xda000000, 7, '9'}, + { '6', 0xdc000000, 6, 't'}, + { '6', 0xe0000000, 3, '0'}, + { '7', 0x00000000, 4, '8'}, + { '7', 0x10000000, 8, STOP}, + { '7', 0x11200000, 13, ESCAPE}, + { '7', 0x11d00000, 12, '?'}, + { '7', 0x12000000, 7, '3'}, + { '7', 0x14000000, 6, '6'}, + { '7', 0x18000000, 6, '2'}, + { '7', 0x1c000000, 6, '1'}, + { '7', 0x20000000, 3, ' '}, + { '7', 0x40000000, 4, '7'}, + { '7', 0x50000000, 5, '/'}, + { '7', 0x58000000, 8, ':'}, + { '7', 0x59000000, 8, 'p'}, + { '7', 0x5a000000, 7, ','}, + { '7', 0x5c000000, 6, 't'}, + { '7', 0x60000000, 3, '0'}, + { '7', 0x80000000, 6, '9'}, + { '7', 0x84000000, 7, 'a'}, + { '7', 0x86000000, 7, '4'}, + { '7', 0x88000000, 6, ')'}, + { '7', 0x90000000, 4, ']'}, + { '7', 0xa0000000, 3, '-'}, + { '7', 0xc0000000, 2, '.'}, + { '8', 0x00000000, 3, '4'}, + { '8', 0x20000000, 5, '/'}, + { '8', 0x28000000, 7, ':'}, + { '8', 0x2a000000, 7, ','}, + { '8', 0x2c000000, 8, 'p'}, + { '8', 0x2d000000, 8, '-'}, + { '8', 0x2e100000, 12, '\''}, + { '8', 0x2e800000, 9, STOP}, + { '8', 0x2f000000, 8, 'a'}, + { '8', 0x30000000, 4, '0'}, + { '8', 0x40000000, 2, ' '}, + { '8', 0x80000000, 4, '9'}, + { '8', 0x90000000, 4, '7'}, + { '8', 0xa0000000, 5, '3'}, + { '8', 0xa8000000, 6, ')'}, + { '8', 0xad000000, 8, '2'}, + { '8', 0xae000000, 7, 't'}, + { '8', 0xb0000000, 4, '8'}, + { '8', 0xc0000000, 3, '.'}, + { '8', 0xe0000000, 4, '1'}, + { '8', 0xf0000000, 5, '5'}, + { '8', 0xf8000000, 6, '6'}, + { '8', 0xfc000000, 6, ']'}, + { '9', 0x00000000, 3, '5'}, + { '9', 0x20000000, 3, ']'}, + { '9', 0x40000000, 5, '2'}, + { '9', 0x48000000, 6, '1'}, + { '9', 0x4c000000, 6, '/'}, + { '9', 0x50000000, 4, '0'}, + { '9', 0x60000000, 4, '.'}, + { '9', 0x70000000, 4, '-'}, + { '9', 0x80000000, 4, '4'}, + { '9', 0x90000000, 4, '8'}, + { '9', 0xa0000000, 5, '3'}, + { '9', 0xa8000000, 6, 't'}, + { '9', 0xac000000, 8, ':'}, + { '9', 0xad000000, 9, ','}, + { '9', 0xadd80000, 15, ESCAPE}, + { '9', 0xae000000, 7, ')'}, + { '9', 0xb0000000, 4, '6'}, + { '9', 0xc0000000, 4, ' '}, + { '9', 0xd0000000, 4, '7'}, + { '9', 0xe0000000, 3, '9'}, + { ':', 0x40000000, 2, '0'}, + { ':', 0x80000000, 1, ' '}, + { ';', 0x80000000, 1, ' '}, + { '=', 0x80000000, 1, ESCAPE}, + { '?', 0x00000000, 3, ':'}, + { '?', 0x20000000, 5, '!'}, + { '?', 0x28000000, 6, ';'}, + { '?', 0x2c000000, 7, '\''}, + { '?', 0x40000000, 2, STOP}, + { '?', 0x80000000, 1, ' '}, + { '@', 0xd0000000, 4, 'b'}, + { 'A', 0x00000000, 4, 's'}, + { 'A', 0x10000000, 4, 'm'}, + { 'A', 0x20000000, 4, 'd'}, + { 'A', 0x30000000, 5, 'c'}, + { 'A', 0x38000000, 10, 'C'}, + { 'A', 0x38400000, 11, 'P'}, + { 'A', 0x38700000, 12, 'K'}, + { 'A', 0x38800000, 10, ','}, + { 'A', 0x38c00000, 11, '-'}, + { 'A', 0x39c80000, 13, 'W'}, + { 'A', 0x39d00000, 12, 'M'}, + { 'A', 0x39ef8000, 18, ESCAPE}, + { 'A', 0x39f00000, 12, 'Y'}, + { 'A', 0x3ac00000, 11, 'A'}, + { 'A', 0x38f00000, 12, '&'}, + { 'A', 0x39000000, 9, 'h'}, + { 'A', 0x39800000, 10, 'y'}, + { 'A', 0x3a000000, 9, '.'}, + { 'A', 0x3a800000, 10, 'S'}, + { 'A', 0x3b000000, 10, 'k'}, + { 'A', 0x3b400000, 10, 'T'}, + { 'A', 0x3b800000, 9, 'B'}, + { 'A', 0x3c000000, 6, 'b'}, + { 'A', 0x40000000, 2, ' '}, + { 'A', 0x80000000, 4, 'r'}, + { 'A', 0x90000000, 5, 'u'}, + { 'A', 0x98100000, 13, '\''}, + { 'A', 0x98180000, 13, ':'}, + { 'A', 0x98800000, 10, 'F'}, + { 'A', 0x98c00000, 10, 'z'}, + { 'A', 0x99000000, 8, 'v'}, + { 'A', 0x9a000000, 9, 'q'}, + { 'A', 0x9aa00000, 11, 'x'}, + { 'A', 0x9ac00000, 10, 'a'}, + { 'A', 0x9b000000, 8, 'p'}, + { 'A', 0x9c000000, 6, 't'}, + { 'A', 0xa0000000, 5, 'g'}, + { 'A', 0xa8000000, 7, 'w'}, + { 'A', 0xaa000000, 7, 'i'}, + { 'A', 0xac000000, 6, 'f'}, + { 'A', 0xb0000000, 4, 'l'}, + { 'A', 0xc0000000, 3, 'D'}, + { 'A', 0xe0000000, 3, 'n'}, + { 'B', 0x00000000, 2, 'C'}, + { 'B', 0x40000000, 3, 'a'}, + { 'B', 0x60000000, 8, 'T'}, + { 'B', 0x61000000, 8, '.'}, + { 'B', 0x62000000, 9, 'A'}, + { 'B', 0x62800000, 10, 'O'}, + { 'B', 0x62e80000, 15, '-'}, + { 'B', 0x62f00000, 12, 'W'}, + { 'B', 0x63000000, 8, 'y'}, + { 'B', 0x64000000, 8, 'I'}, + { 'B', 0x65000000, 11, '&'}, + { 'B', 0x65600000, 11, 'M'}, + { 'B', 0x65940000, 15, 'S'}, + { 'B', 0x65960000, 15, 'F'}, + { 'B', 0x65a00000, 12, ','}, + { 'B', 0x65b00000, 12, '1'}, + { 'B', 0x65e00000, 12, ESCAPE}, + { 'B', 0x65f00000, 12, 'P'}, + { 'B', 0x66000000, 8, 'h'}, + { 'B', 0x67000000, 8, ' '}, + { 'B', 0x68000000, 5, 'l'}, + { 'B', 0x70000000, 4, 'i'}, + { 'B', 0x80000000, 4, 'u'}, + { 'B', 0x90000000, 4, 'o'}, + { 'B', 0xa0000000, 3, 'r'}, + { 'B', 0xc0000000, 3, 'e'}, + { 'B', 0xe0000000, 3, 'B'}, + { 'C', 0x00000000, 2, 'h'}, + { 'C', 0x40000000, 5, '\''}, + { 'C', 0x48000000, 9, 'A'}, + { 'C', 0x48b00000, 13, 'z'}, + { 'C', 0x48b80000, 16, ':'}, + { 'C', 0x48b90000, 17, ESCAPE}, + { 'C', 0x49000000, 8, 'I'}, + { 'C', 0x4a000000, 7, 'y'}, + { 'C', 0x4c000000, 6, 'e'}, + { 'C', 0x50000000, 4, 'r'}, + { 'C', 0x60000000, 3, 'B'}, + { 'C', 0x80000000, 3, 'a'}, + { 'C', 0xa0000000, 4, '.'}, + { 'C', 0xb0400000, 10, 'D'}, + { 'C', 0xb0920000, 15, '7'}, + { 'C', 0xb0b00000, 12, 'H'}, + { 'C', 0xb1000000, 10, 'S'}, + { 'C', 0xb1400000, 10, 'T'}, + { 'C', 0xb1900000, 14, 'P'}, + { 'C', 0xb1a00000, 11, 'J'}, + { 'C', 0xb1c00000, 10, 'G'}, + { 'C', 0xb2000000, 7, ','}, + { 'C', 0xb4000000, 6, 'u'}, + { 'C', 0xb8000000, 5, 'i'}, + { 'C', 0xc0000000, 3, 'o'}, + { 'C', 0xe0000000, 4, ' '}, + { 'C', 0xf0000000, 4, 'l'}, + { 'D', 0x00000000, 2, 'a'}, + { 'D', 0x40000000, 2, ','}, + { 'D', 0x80000000, 3, 'r'}, + { 'D', 0xa0000000, 3, 'o'}, + { 'D', 0xc0000000, 3, 'e'}, + { 'D', 0xe0000000, 4, 'i'}, + { 'D', 0xf0000000, 8, '.'}, + { 'D', 0xf2000000, 7, ' '}, + { 'D', 0xf4140000, 16, 'B'}, + { 'D', 0xf4180000, 14, '9'}, + { 'D', 0xf4200000, 11, 'M'}, + { 'D', 0xf4400000, 11, '&'}, + { 'D', 0xf4600000, 11, 'V'}, + { 'D', 0xf4800000, 10, 'h'}, + { 'D', 0xf4d00000, 12, 's'}, + { 'D', 0xf4e80000, 13, 'j'}, + { 'D', 0xf5000000, 9, 'w'}, + { 'D', 0xf5800000, 9, 'W'}, + { 'D', 0xf6000000, 7, '\''}, + { 'D', 0xf8400000, 11, '-'}, + { 'D', 0xf8600000, 11, 'G'}, + { 'D', 0xf8800000, 9, 'N'}, + { 'D', 0xf9000000, 9, 'C'}, + { 'D', 0xf9c00000, 10, 'I'}, + { 'D', 0xfa000000, 8, 'y'}, + { 'D', 0xfb000000, 12, 'v'}, + { 'D', 0xfb100000, 13, ESCAPE}, + { 'D', 0xfb400000, 10, ':'}, + { 'D', 0xfb800000, 9, 'J'}, + { 'D', 0xfc000000, 6, 'u'}, + { 'E', 0x00000000, 3, 'p'}, + { 'E', 0x20000000, 5, 's'}, + { 'E', 0x28000000, 6, '.'}, + { 'E', 0x2c000000, 6, 'i'}, + { 'E', 0x30000000, 5, 'r'}, + { 'E', 0x38000000, 5, 'u'}, + { 'E', 0x40000000, 3, 'a'}, + { 'E', 0x60000000, 3, 'n'}, + { 'E', 0x80000000, 5, 'E'}, + { 'E', 0x88000000, 5, ' '}, + { 'E', 0x90000000, 4, 'm'}, + { 'E', 0xa0000000, 4, 'x'}, + { 'E', 0xb0000000, 7, 'y'}, + { 'E', 0xb2000000, 7, 't'}, + { 'E', 0xb4000000, 6, ':'}, + { 'E', 0xb8000000, 7, 'g'}, + { 'E', 0xba040000, 14, 'S'}, + { 'E', 0xba160000, 16, ESCAPE}, + { 'E', 0xba400000, 11, 'f'}, + { 'E', 0xba600000, 11, 'o'}, + { 'E', 0xba800000, 10, 'R'}, + { 'E', 0xbac00000, 10, 'F'}, + { 'E', 0xbb000000, 9, 'w'}, + { 'E', 0xbbc00000, 10, 'C'}, + { 'E', 0xbe000000, 9, 'c'}, + { 'E', 0xbea00000, 11, 'e'}, + { 'E', 0xbef00000, 12, '\''}, + { 'E', 0xbf000000, 9, 'b'}, + { 'E', 0xbf800000, 11, 'h'}, + { 'E', 0xbfe00000, 11, 'D'}, + { 'E', 0xc0000000, 3, 'l'}, + { 'E', 0xe0000000, 4, 'v'}, + { 'E', 0xf0000000, 4, 'd'}, + { 'F', 0x00000000, 2, 'o'}, + { 'F', 0x40000000, 3, 'e'}, + { 'F', 0x60000000, 4, 'l'}, + { 'F', 0x70000000, 5, 'u'}, + { 'F', 0x78000000, 7, ' '}, + { 'F', 0x7a000000, 7, 'O'}, + { 'F', 0x7c000000, 10, '.'}, + { 'F', 0x7c900000, 13, 'y'}, + { 'F', 0x7c980000, 13, ','}, + { 'F', 0x7ca00000, 11, 'T'}, + { 'F', 0x7d000000, 8, 'A'}, + { 'F', 0x7ee80000, 14, 'I'}, + { 'F', 0x7ef00000, 12, '1'}, + { 'F', 0x7f000000, 8, 'B'}, + { 'F', 0x80000000, 2, 'r'}, + { 'F', 0xc0000000, 3, 'i'}, + { 'F', 0xe0000000, 3, 'a'}, + { 'G', 0x00000000, 2, 'r'}, + { 'G', 0x40000000, 2, 'a'}, + { 'G', 0x84800000, 11, ';'}, + { 'G', 0x84000000, 9, '-'}, + { 'G', 0x84a00000, 11, ','}, + { 'G', 0x84c00000, 11, 'A'}, + { 'G', 0x86000000, 9, 'C'}, + { 'G', 0x86d60000, 15, '\''}, + { 'G', 0x87000000, 8, 'P'}, + { 'G', 0x88000000, 5, 'n'}, + { 'G', 0x90000000, 4, 'u'}, + { 'G', 0xa0000000, 3, 'o'}, + { 'G', 0xc0000000, 3, 'e'}, + { 'G', 0xe0000000, 7, 'y'}, + { 'G', 0xe2000000, 7, ' '}, + { 'G', 0xe4000000, 10, '.'}, + { 'G', 0xe4400000, 10, 'I'}, + { 'G', 0xe5000000, 8, 'h'}, + { 'G', 0xe6000000, 7, 'w'}, + { 'G', 0xe8000000, 5, 'l'}, + { 'G', 0xf0000000, 4, 'i'}, + { 'H', 0x00000000, 2, 'e'}, + { 'H', 0x40000000, 2, 'a'}, + { 'H', 0x80000000, 2, 'o'}, + { 'H', 0xc0000000, 3, 'i'}, + { 'H', 0xe0000000, 5, 'R'}, + { 'H', 0xea000000, 10, 'S'}, + { 'H', 0xea400000, 10, '.'}, + { 'H', 0xea8c0000, 15, 'D'}, + { 'H', 0xea8e0000, 16, ESCAPE}, + { 'H', 0xeaa00000, 11, 'G'}, + { 'H', 0xeb000000, 8, 'I'}, + { 'H', 0xec000000, 7, 'y'}, + { 'H', 0xee000000, 9, 'Q'}, + { 'H', 0xee800000, 9, 'M'}, + { 'H', 0xef800000, 9, ' '}, + { 'H', 0xf0000000, 4, 'u'}, + { 'I', 0x00000000, 1, 'n'}, + { 'I', 0x80000000, 5, 'T'}, + { 'I', 0x88000000, 6, 'c'}, + { 'I', 0x8d000000, 9, 'P'}, + { 'I', 0x8da00000, 11, '5'}, + { 'I', 0x8e000000, 7, '\''}, + { 'I', 0x90000000, 4, 's'}, + { 'I', 0xa0000000, 8, 'A'}, + { 'I', 0xa1000000, 8, 'v'}, + { 'I', 0xa2000000, 9, 'w'}, + { 'I', 0xa2a00000, 11, '9'}, + { 'I', 0xa2c00000, 10, 'y'}, + { 'I', 0xa3000000, 9, ':'}, + { 'I', 0xa3d00000, 12, ')'}, + { 'I', 0xa4000000, 6, 'm'}, + { 'I', 0xa8000000, 5, 'a'}, + { 'I', 0xb4000000, 6, '.'}, + { 'I', 0xb8000000, 9, 'p'}, + { 'I', 0xb8800000, 11, 'b'}, + { 'I', 0xb8c00000, 11, '-'}, + { 'I', 0xb9000000, 8, 'V'}, + { 'I', 0xba000000, 7, 'l'}, + { 'I', 0xbc000000, 6, 'd'}, + { 'I', 0xc0000000, 3, 't'}, + { 'I', 0xe0000000, 5, ' '}, + { 'I', 0xe8800000, 9, ','}, + { 'I', 0xe9000000, 8, 'f'}, + { 'I', 0xea000000, 10, 'g'}, + { 'I', 0xea400000, 10, 'D'}, + { 'I', 0xea800000, 9, 'Y'}, + { 'I', 0xeb000000, 8, 'o'}, + { 'I', 0xec000000, 6, 'I'}, + { 'I', 0xf0000000, 4, 'r'}, + { 'J', 0x00000000, 2, 'e'}, + { 'J', 0x40000000, 5, ' '}, + { 'J', 0x48c00000, 10, ','}, + { 'J', 0x49000000, 8, 'r'}, + { 'J', 0x4a400000, 10, '-'}, + { 'J', 0x4ac00000, 11, 'n'}, + { 'J', 0x4aec0000, 15, ESCAPE}, + { 'J', 0x4af80000, 13, '\''}, + { 'J', 0x4b000000, 9, 's'}, + { 'J', 0x4b800000, 10, 'K'}, + { 'J', 0x4bc00000, 10, 'T'}, + { 'J', 0x4c000000, 7, 'D'}, + { 'J', 0x4e000000, 7, '.'}, + { 'J', 0x50000000, 4, 'i'}, + { 'J', 0x60000000, 3, 'u'}, + { 'J', 0x80000000, 2, 'a'}, + { 'J', 0xc0000000, 2, 'o'}, + { 'K', 0x00000000, 2, 'i'}, + { 'K', 0x40000000, 2, 'a'}, + { 'K', 0x80000000, 2, 'e'}, + { 'K', 0xc0000000, 5, 'n'}, + { 'K', 0xc8000000, 5, 'o'}, + { 'K', 0xd0000000, 6, '\''}, + { 'K', 0xd4e00000, 12, '-'}, + { 'K', 0xd5000000, 10, 'w'}, + { 'K', 0xd5600000, 12, ':'}, + { 'K', 0xd5800000, 9, 'G'}, + { 'K', 0xd6000000, 7, '.'}, + { 'K', 0xd8000000, 5, 'r'}, + { 'K', 0xe0000000, 6, 'u'}, + { 'K', 0xe4500000, 12, 'S'}, + { 'K', 0xe4800000, 9, ','}, + { 'K', 0xe5000000, 8, 'h'}, + { 'K', 0xe6000000, 7, 'l'}, + { 'K', 0xe8000000, 5, ' '}, + { 'K', 0xf0000000, 4, 'y'}, + { 'L', 0x00000000, 2, 'i'}, + { 'L', 0x40000000, 4, 'u'}, + { 'L', 0x50000000, 6, 'l'}, + { 'L', 0x54000000, 6, 'A'}, + { 'L', 0x58000000, 9, 'I'}, + { 'L', 0x59400000, 10, '\''}, + { 'L', 0x59a00000, 11, '.'}, + { 'L', 0x5a680000, 16, ESCAPE}, + { 'L', 0x5a700000, 12, 'S'}, + { 'L', 0x5c000000, 6, 'y'}, + { 'L', 0x60000000, 3, ']'}, + { 'L', 0x80000000, 2, 'o'}, + { 'L', 0xc0000000, 3, 'e'}, + { 'L', 0xe0000000, 3, 'a'}, + { 'M', 0x00000000, 2, 'o'}, + { 'M', 0x40000000, 9, '1'}, + { 'M', 0x40800000, 10, 'A'}, + { 'M', 0x41000000, 8, 'C'}, + { 'M', 0x42000000, 7, ' '}, + { 'M', 0x44000000, 9, 'h'}, + { 'M', 0x44800000, 10, 'z'}, + { 'M', 0x45000000, 9, 'I'}, + { 'M', 0x45800000, 12, 'R'}, + { 'M', 0x45b60000, 15, '2'}, + { 'M', 0x45b80000, 13, 'D'}, + { 'M', 0x45c00000, 11, '.'}, + { 'M', 0x45f00000, 13, 'E'}, + { 'M', 0x45fc0000, 14, 'w'}, + { 'M', 0x46000000, 8, 'F'}, + { 'M', 0x47800000, 9, 'X'}, + { 'M', 0x48000000, 5, 'y'}, + { 'M', 0x50000000, 4, 'c'}, + { 'M', 0x60000000, 3, 'e'}, + { 'M', 0x80000000, 6, 'S'}, + { 'M', 0x84000000, 6, 'P'}, + { 'M', 0x88000000, 5, 'r'}, + { 'M', 0x90000000, 4, 'u'}, + { 'M', 0xa0000000, 3, 'i'}, + { 'M', 0xc0000000, 2, 'a'}, + { 'N', 0x00000000, 2, 'a'}, + { 'N', 0x43500000, 12, 'M'}, + { 'N', 0x44000000, 7, 'y'}, + { 'N', 0x47000000, 8, ' '}, + { 'N', 0x48000000, 6, 'A'}, + { 'N', 0x4e000000, 9, 'L'}, + { 'N', 0x4f680000, 13, ESCAPE}, + { 'N', 0x50000000, 5, 'u'}, + { 'N', 0x58000000, 5, 'E'}, + { 'N', 0x60000000, 3, 'i'}, + { 'N', 0x80000000, 2, 'o'}, + { 'N', 0xc0000000, 2, 'e'}, + { 'O', 0x00000000, 4, 's'}, + { 'O', 0x20000000, 6, 'o'}, + { 'O', 0x28000000, 5, 'U'}, + { 'O', 0x40000000, 4, 'r'}, + { 'O', 0x50000000, 6, 'b'}, + { 'O', 0x54000000, 6, 'm'}, + { 'O', 0x58000000, 5, 'h'}, + { 'O', 0x60000000, 9, 'K'}, + { 'O', 0x60a00000, 12, ':'}, + { 'O', 0x61000000, 8, 't'}, + { 'O', 0x62000000, 8, 'k'}, + { 'O', 0x63200000, 11, 'L'}, + { 'O', 0x6c000000, 6, 'v'}, + { 'O', 0x70000000, 5, 'f'}, + { 'O', 0x78000000, 5, 'w'}, + { 'O', 0x80000000, 4, 'u'}, + { 'O', 0x90000000, 5, '.'}, + { 'O', 0x98000000, 8, 'g'}, + { 'O', 0x99c00000, 10, '-'}, + { 'O', 0x9a000000, 7, 'd'}, + { 'O', 0x9c000000, 6, 'c'}, + { 'O', 0xa0000000, 4, 'p'}, + { 'O', 0xb0000000, 4, 'l'}, + { 'O', 0xc0000000, 5, ' '}, + { 'O', 0xc8000000, 7, 'a'}, + { 'O', 0xcb200000, 11, 'A'}, + { 'O', 0xcb600000, 11, 'C'}, + { 'O', 0xcc000000, 6, 'x'}, + { 'O', 0xd0000000, 4, '\''}, + { 'O', 0xe0000000, 3, 'n'}, + { 'P', 0x00000000, 3, 'i'}, + { 'P', 0x20000000, 4, 'h'}, + { 'P', 0x31100000, 12, 'G'}, + { 'P', 0x31400000, 10, 'y'}, + { 'P', 0x32000000, 8, 'D'}, + { 'P', 0x33540000, 16, ESCAPE}, + { 'P', 0x33580000, 13, 'J'}, + { 'P', 0x33600000, 12, 'A'}, + { 'P', 0x33800000, 9, ','}, + { 'P', 0x34000000, 7, 'C'}, + { 'P', 0x36000000, 10, 'E'}, + { 'P', 0x36400000, 10, '\''}, + { 'P', 0x36900000, 12, 'F'}, + { 'P', 0x36a00000, 13, 'f'}, + { 'P', 0x36a80000, 13, 'R'}, + { 'P', 0x36b00000, 14, 'Y'}, + { 'P', 0x37000000, 8, 's'}, + { 'P', 0x38000000, 7, '.'}, + { 'P', 0x3a000000, 7, ' '}, + { 'P', 0x3c000000, 6, 'u'}, + { 'P', 0x40000000, 3, 'e'}, + { 'P', 0x60000000, 3, 'l'}, + { 'P', 0x80000000, 3, 'o'}, + { 'P', 0xa0000000, 3, 'r'}, + { 'P', 0xc0000000, 2, 'a'}, + { 'Q', 0x40000000, 5, 'a'}, + { 'Q', 0x4b000000, 8, '&'}, + { 'Q', 0x50000000, 4, '.'}, + { 'Q', 0x60000000, 3, ' '}, + { 'Q', 0x80000000, 1, 'u'}, + { 'R', 0x10000000, 6, ' '}, + { 'R', 0x15000000, 9, 'F'}, + { 'R', 0x16000000, 8, '.'}, + { 'R', 0x17000000, 10, 'N'}, + { 'R', 0x17c00000, 10, 'H'}, + { 'R', 0x18000000, 5, 'E'}, + { 'R', 0x20000000, 5, 'h'}, + { 'R', 0x28000000, 6, 'y'}, + { 'R', 0x2d800000, 9, 'n'}, + { 'R', 0x2e000000, 8, 'S'}, + { 'R', 0x2f800000, 9, 'A'}, + { 'R', 0x30000000, 4, 'u'}, + { 'R', 0x40000000, 2, 'a'}, + { 'R', 0x80000000, 3, 'i'}, + { 'R', 0xa0000000, 3, 'e'}, + { 'R', 0xc0000000, 2, 'o'}, + { 'S', 0x00000000, 4, 'a'}, + { 'S', 0x10000000, 5, 'p'}, + { 'S', 0x18000000, 5, ','}, + { 'S', 0x20000000, 4, 'h'}, + { 'S', 0x30000000, 5, 'L'}, + { 'S', 0x38000000, 7, 'w'}, + { 'S', 0x3a000000, 8, 'q'}, + { 'S', 0x3b000000, 9, 'P'}, + { 'S', 0x3b800000, 10, 'A'}, + { 'S', 0x3bc40000, 16, 'G'}, + { 'S', 0x3bc60000, 15, '}'}, + { 'S', 0x3be00000, 12, 'S'}, + { 'S', 0x3c000000, 6, 'k'}, + { 'S', 0x40000000, 5, 'i'}, + { 'S', 0x48000000, 5, 'u'}, + { 'S', 0x50000000, 5, 'o'}, + { 'S', 0x58000000, 5, 'c'}, + { 'S', 0x60000000, 5, 'e'}, + { 'S', 0x69000000, 8, 'n'}, + { 'S', 0x6a000000, 7, ' '}, + { 'S', 0x6c000000, 8, 'l'}, + { 'S', 0x6d100000, 14, 'O'}, + { 'S', 0x6d140000, 16, '-'}, + { 'S', 0x6d160000, 15, 'B'}, + { 'S', 0x6d180000, 13, ESCAPE}, + { 'S', 0x6d200000, 11, '.'}, + { 'S', 0x6d4c0000, 16, '3'}, + { 'S', 0x6d4e8000, 17, 's'}, + { 'S', 0x6d500000, 12, 'E'}, + { 'S', 0x6d600000, 12, 'v'}, + { 'S', 0x6d700000, 14, 'z'}, + { 'S', 0x6d740000, 15, 'H'}, + { 'S', 0x6d780000, 13, 'g'}, + { 'S', 0x6d800000, 9, 'y'}, + { 'S', 0x6e000000, 7, 'm'}, + { 'S', 0x70000000, 4, 't'}, + { 'S', 0x80000000, 1, ']'}, + { 'T', 0x00000000, 1, 'h'}, + { 'T', 0x80000000, 3, 'o'}, + { 'T', 0xa0000000, 4, 'V'}, + { 'T', 0xb0000000, 4, 'w'}, + { 'T', 0xc0000000, 4, 'r'}, + { 'T', 0xd0000000, 5, 'a'}, + { 'T', 0xd8000000, 5, 'i'}, + { 'T', 0xe0000000, 5, 'u'}, + { 'T', 0xe8000000, 7, 'H'}, + { 'T', 0xea000000, 8, ' '}, + { 'T', 0xeb000000, 8, 'y'}, + { 'T', 0xec000000, 7, 'W'}, + { 'T', 0xee000000, 10, 'S'}, + { 'T', 0xee400000, 11, 'A'}, + { 'T', 0xee680000, 13, '-'}, + { 'T', 0xee800000, 9, 'M'}, + { 'T', 0xef000000, 12, '.'}, + { 'T', 0xef140000, 14, '4'}, + { 'T', 0xef200000, 11, 's'}, + { 'T', 0xef400000, 13, 'C'}, + { 'T', 0xef480000, 14, 'O'}, + { 'T', 0xef4c0000, 15, 'E'}, + { 'T', 0xef540000, 15, '\''}, + { 'T', 0xef580000, 13, 'c'}, + { 'T', 0xef800000, 9, 'x'}, + { 'T', 0xf0000000, 4, 'e'}, + { 'U', 0x00000000, 2, 'K'}, + { 'U', 0x40000000, 6, 'g'}, + { 'U', 0x44000000, 8, 'k'}, + { 'U', 0x45000000, 8, 't'}, + { 'U', 0x46000000, 8, 'E'}, + { 'U', 0x47000000, 8, '-'}, + { 'U', 0x48000000, 8, 'F'}, + { 'U', 0x4ac00000, 11, 'b'}, + { 'U', 0x4b800000, 9, 'Z'}, + { 'U', 0x4c000000, 8, '2'}, + { 'U', 0x4d000000, 10, 'i'}, + { 'U', 0x4d800000, 10, 'a'}, + { 'U', 0x4e000000, 10, '.'}, + { 'U', 0x50000000, 5, 's'}, + { 'U', 0x58000000, 5, 'r'}, + { 'U', 0x60000000, 3, 'S'}, + { 'U', 0x80000000, 2, 'n'}, + { 'U', 0xc0000000, 3, 'p'}, + { 'U', 0xe0000000, 6, ' '}, + { 'U', 0xe4000000, 7, 'm'}, + { 'U', 0xe8000000, 5, 'R'}, + { 'U', 0xf0000000, 4, 'l'}, + { 'V', 0x00000000, 3, '.'}, + { 'V', 0x20000000, 3, 'a'}, + { 'V', 0x40000000, 2, ' '}, + { 'V', 0x81000000, 8, '1'}, + { 'V', 0x84780000, 13, '8'}, + { 'V', 0x91000000, 9, 'D'}, + { 'V', 0x91800000, 9, 'u'}, + { 'V', 0x94000000, 10, ';'}, + { 'V', 0x94400000, 11, ESCAPE}, + { 'V', 0x94780000, 13, 'W'}, + { 'V', 0x94800000, 9, ','}, + { 'V', 0x95000000, 8, '\''}, + { 'V', 0x96000000, 8, ':'}, + { 'V', 0x97000000, 8, 'l'}, + { 'V', 0x98000000, 5, 'o'}, + { 'V', 0xa0000000, 3, 'e'}, + { 'V', 0xc0000000, 2, 'i'}, + { 'W', 0x00000000, 2, 'h'}, + { 'W', 0x40000000, 4, 'r'}, + { 'W', 0x50800000, 9, '.'}, + { 'W', 0x51000000, 10, '\''}, + { 'W', 0x51800000, 11, '2'}, + { 'W', 0x51a00000, 11, ':'}, + { 'W', 0x52000000, 7, ' '}, + { 'W', 0x54000000, 7, 'y'}, + { 'W', 0x56000000, 9, 'I'}, + { 'W', 0x56b40000, 16, ESCAPE}, + { 'W', 0x56b80000, 13, 'u'}, + { 'W', 0x56c00000, 11, 'V'}, + { 'W', 0x57000000, 9, 'W'}, + { 'W', 0x58000000, 5, 'O'}, + { 'W', 0x60000000, 3, 'a'}, + { 'W', 0x80000000, 2, 'i'}, + { 'W', 0xc0000000, 3, 'o'}, + { 'W', 0xe0000000, 3, 'e'}, + { 'X', 0x00000000, 3, 'a'}, + { 'X', 0x43000000, 10, ')'}, + { 'X', 0x50000000, 5, '-'}, + { 'X', 0x6a000000, 7, '.'}, + { 'X', 0x70000000, 4, 't'}, + { 'X', 0x80000000, 1, ' '}, + { 'Y', 0x00000000, 2, 'e'}, + { 'Y', 0x40000000, 3, 'u'}, + { 'Y', 0x60000000, 5, 'a'}, + { 'Y', 0x6e000000, 13, '-'}, + { 'Y', 0x6e380000, 13, ','}, + { 'Y', 0x6f000000, 8, 'i'}, + { 'Y', 0x78000000, 5, ' '}, + { 'Y', 0x80000000, 1, 'o'}, + { 'Z', 0x08000000, 5, 'Z'}, + { 'Z', 0x10000000, 5, ' '}, + { 'Z', 0x18000000, 5, 'u'}, + { 'Z', 0x20000000, 4, 'z'}, + { 'Z', 0x30000000, 4, 'i'}, + { 'Z', 0x03400000, 10, '-'}, + { 'Z', 0x40000000, 2, 'a'}, + { 'Z', 0x80000000, 2, 'e'}, + { 'Z', 0xc0000000, 2, 'o'}, + { '[', 0x00000000, 4, '2'}, + { '[', 0x10000000, 11, 'J'}, + { '[', 0x10800000, 9, 'C'}, + { '[', 0x11000000, 9, 'f'}, + { '[', 0x14000000, 6, 'n'}, + { '[', 0x1c000000, 11, 'L'}, + { '[', 0x1c240000, 15, ESCAPE}, + { '[', 0x1c280000, 13, 'D'}, + { '[', 0x1c400000, 10, 'T'}, + { '[', 0x1c800000, 9, 'c'}, + { '[', 0x30000000, 4, '1'}, + { '[', 0x40000000, 2, 'A'}, + { '[', 0x80000000, 1, 'S'}, + { '\'', 0x00000000, 4, 'l'}, + { '\'', 0x10000000, 6, 'n'}, + { '\'', 0x14000000, 6, '.'}, + { '\'', 0x18000000, 6, 'C'}, + { '\'', 0x1c000000, 8, 'S'}, + { '\'', 0x1d000000, 9, 'f'}, + { '\'', 0x1d800000, 9, 'g'}, + { '\'', 0x1e000000, 10, 'o'}, + { '\'', 0x1e400000, 10, 'K'}, + { '\'', 0x1e840000, 14, '0'}, + { '\'', 0x1e900000, 12, 'W'}, + { '\'', 0x1ea00000, 11, '?'}, + { '\'', 0x1ec00000, 10, 'a'}, + { '\'', 0x1f000000, 8, 'p'}, + { '\'', 0x20000000, 3, 't'}, + { '\'', 0x40000000, 3, ' '}, + { '\'', 0x60000000, 6, 'B'}, + { '\'', 0x64000000, 9, 'F'}, + { '\'', 0x64800000, 9, 'h'}, + { '\'', 0x65000000, 8, 'D'}, + { '\'', 0x66000000, 11, 'E'}, + { '\'', 0x66400000, 10, 'u'}, + { '\'', 0x66800000, 9, 'H'}, + { '\'', 0x67900000, 12, ':'}, + { '\'', 0x67b40000, 16, ESCAPE}, + { '\'', 0x67b80000, 13, 'y'}, + { '\'', 0x68000000, 5, 'r'}, + { '\'', 0x70000000, 7, 'd'}, + { '\'', 0x72400000, 10, 'I'}, + { '\'', 0x72800000, 9, 'R'}, + { '\'', 0x73800000, 9, 'T'}, + { '\'', 0x74000000, 6, 'A'}, + { '\'', 0x78000000, 7, 'v'}, + { '\'', 0x7a000000, 10, 'w'}, + { '\'', 0x7a400000, 10, 'b'}, + { '\'', 0x7a800000, 9, 'G'}, + { '\'', 0x7b000000, 8, 'i'}, + { '\'', 0x7c000000, 8, 'c'}, + { '\'', 0x7d000000, 8, 'm'}, + { '\'', 0x7e000000, 13, '6'}, + { '\'', 0x7e100000, 12, 'q'}, + { '\'', 0x7e220000, 15, 'U'}, + { '\'', 0x7e300000, 12, 'M'}, + { '\'', 0x7e400000, 10, 'e'}, + { '\'', 0x7e800000, 9, 'L'}, + { '\'', 0x7f000000, 8, ','}, + { '\'', 0x80000000, 1, 's'}, + { ']', 0x04000000, 6, ','}, + { ']', 0x20000000, 3, '.'}, + { ']', 0x40000000, 2, ' '}, + { ']', 0x80000000, 1, STOP}, + { 'a', 0x00000000, 4, 'm'}, + { 'a', 0x10000000, 6, 'p'}, + { 'a', 0x14000000, 7, 'w'}, + { 'a', 0x16000000, 9, ','}, + { 'a', 0x16800000, 9, '\''}, + { 'a', 0x17000000, 8, 'z'}, + { 'a', 0x18000000, 5, 'd'}, + { 'a', 0x20000000, 3, 'r'}, + { 'a', 0x40000000, 2, 'n'}, + { 'a', 0x80000000, 5, 'i'}, + { 'a', 0x88000000, 6, 'u'}, + { 'a', 0x8c000000, 6, 'v'}, + { 'a', 0x90000000, 4, 's'}, + { 'a', 0xa0000000, 3, 't'}, + { 'a', 0xc0000000, 5, 'y'}, + { 'a', 0xc8000000, 8, '.'}, + { 'a', 0xc9000000, 11, 'a'}, + { 'a', 0xc9200000, 11, '-'}, + { 'a', 0xc9400000, 12, 'q'}, + { 'a', 0xc9500000, 14, '!'}, + { 'a', 0xc9550000, 17, 'J'}, + { 'a', 0xc9560000, 16, ';'}, + { 'a', 0xc9570000, 16, ')'}, + { 'a', 0xc9580000, 18, 'R'}, + { 'a', 0xc9590000, 16, '/'}, + { 'a', 0xc95c0000, 14, '?'}, + { 'a', 0xc9600000, 11, 'j'}, + { 'a', 0xc9800000, 9, 'e'}, + { 'a', 0xca000000, 11, ':'}, + { 'a', 0xca200000, 11, 'o'}, + { 'a', 0xca400000, 10, 'x'}, + { 'a', 0xca800000, 9, 'h'}, + { 'a', 0xcb000000, 8, 'f'}, + { 'a', 0xcc000000, 6, 'g'}, + { 'a', 0xd0000000, 5, 'c'}, + { 'a', 0xd8000000, 6, 'b'}, + { 'a', 0xdc000000, 6, 'k'}, + { 'a', 0xe0000000, 4, ' '}, + { 'a', 0xf0000000, 4, 'l'}, + { 'b', 0x00000000, 2, 'e'}, + { 'b', 0x40000000, 3, 'u'}, + { 'b', 0x60000000, 3, 'a'}, + { 'b', 0x80000000, 3, 'y'}, + { 'b', 0xa0000000, 3, 'o'}, + { 'b', 0xc0000000, 4, 'l'}, + { 'b', 0xd0000000, 6, 's'}, + { 'b', 0xd4000000, 9, 'j'}, + { 'b', 0xd4800000, 13, '?'}, + { 'b', 0xd4880000, 14, 'f'}, + { 'b', 0xd48c0000, 16, '/'}, + { 'b', 0xd4900000, 13, 'v'}, + { 'b', 0xd4984000, 19, ESCAPE}, + { 'b', 0xd4a00000, 11, ':'}, + { 'b', 0xd4c00000, 10, '\''}, + { 'b', 0xd5000000, 8, 'c'}, + { 'b', 0xd6000000, 9, ','}, + { 'b', 0xd6800000, 9, '.'}, + { 'b', 0xd7000000, 11, 'w'}, + { 'b', 0xd7200000, 11, 'd'}, + { 'b', 0xd7400000, 11, 'h'}, + { 'b', 0xd7600000, 11, '&'}, + { 'b', 0xd7800000, 12, 'm'}, + { 'b', 0xd7900000, 12, 'n'}, + { 'b', 0xd7a00000, 11, '-'}, + { 'b', 0xd7c00000, 10, 't'}, + { 'b', 0xd8000000, 6, ' '}, + { 'b', 0xdc000000, 6, 'b'}, + { 'b', 0xe0000000, 4, 'r'}, + { 'b', 0xf0000000, 4, 'i'}, + { 'c', 0x00000000, 2, 'o'}, + { 'c', 0x40000000, 4, 'i'}, + { 'c', 0x50000000, 4, 'l'}, + { 'c', 0x60000000, 3, 'a'}, + { 'c', 0x80000000, 3, 'e'}, + { 'c', 0xa0000000, 5, 'u'}, + { 'c', 0xa8000000, 5, 'r'}, + { 'c', 0xb0000000, 4, 'k'}, + { 'c', 0xc0000000, 3, 'h'}, + { 'c', 0xe0000000, 5, ' '}, + { 'c', 0xe8000000, 7, 'y'}, + { 'c', 0xea000000, 7, 'c'}, + { 'c', 0xec000000, 12, ':'}, + { 'c', 0xec100000, 15, 'b'}, + { 'c', 0xec120000, 15, ESCAPE}, + { 'c', 0xec1b0000, 16, 'V'}, + { 'c', 0xec1c0000, 14, 'E'}, + { 'c', 0xec200000, 11, 'n'}, + { 'c', 0xec400000, 10, 'G'}, + { 'c', 0xec800000, 13, 'N'}, + { 'c', 0xec900000, 12, '-'}, + { 'c', 0xeca00000, 12, 'A'}, + { 'c', 0xecb00000, 14, '?'}, + { 'c', 0xecb80000, 15, ';'}, + { 'c', 0xecba0000, 17, 'U'}, + { 'c', 0xecc00000, 11, 'D'}, + { 'c', 0xece00000, 12, 'L'}, + { 'c', 0xecf00000, 12, '\''}, + { 'c', 0xed000000, 8, 's'}, + { 'c', 0xee000000, 8, '.'}, + { 'c', 0xef000000, 11, 'K'}, + { 'c', 0xef200000, 12, 'd'}, + { 'c', 0xef300000, 14, 'M'}, + { 'c', 0xef380000, 13, 'F'}, + { 'c', 0xef400000, 12, 'q'}, + { 'c', 0xef500000, 12, 'I'}, + { 'c', 0xef600000, 11, 'C'}, + { 'c', 0xef800000, 9, ','}, + { 'c', 0xf0000000, 4, 't'}, + { 'd', 0x00000000, 1, ' '}, + { 'd', 0x80000000, 8, 'h'}, + { 'd', 0x81000000, 8, ':'}, + { 'd', 0x82000000, 8, 'm'}, + { 'd', 0x83000000, 11, '!'}, + { 'd', 0x83300000, 12, ')'}, + { 'd', 0x83400000, 12, 'k'}, + { 'd', 0x83500000, 12, ';'}, + { 'd', 0x83600000, 15, 'z'}, + { 'd', 0x83640000, 16, ESCAPE}, + { 'd', 0x83660000, 15, 'q'}, + { 'd', 0x836c0000, 14, 'j'}, + { 'd', 0x83700000, 12, '/'}, + { 'd', 0x83800000, 9, 'f'}, + { 'd', 0x84000000, 6, 'd'}, + { 'd', 0x88000000, 5, '.'}, + { 'd', 0x90000000, 8, 'w'}, + { 'd', 0x91000000, 8, 'n'}, + { 'd', 0x92000000, 7, '-'}, + { 'd', 0x94000000, 6, 'l'}, + { 'd', 0x98000000, 5, 'o'}, + { 'd', 0xa0000000, 3, 'e'}, + { 'd', 0xc0000000, 4, 'a'}, + { 'd', 0xd0000000, 6, 'u'}, + { 'd', 0xd4000000, 11, 'p'}, + { 'd', 0xd4200000, 11, 't'}, + { 'd', 0xd4400000, 10, '?'}, + { 'd', 0xd4800000, 10, 'b'}, + { 'd', 0xd4c00000, 10, 'c'}, + { 'd', 0xd5000000, 8, '\''}, + { 'd', 0xd6000000, 7, 'v'}, + { 'd', 0xd8000000, 5, 'r'}, + { 'd', 0xe0000000, 4, 'i'}, + { 'd', 0xf0000000, 7, 'g'}, + { 'd', 0xf2000000, 7, ','}, + { 'd', 0xf4000000, 6, 'y'}, + { 'd', 0xf8000000, 5, 's'}, + { 'e', 0x00000000, 4, 'd'}, + { 'e', 0x10000000, 5, 'c'}, + { 'e', 0x18000000, 6, 'x'}, + { 'e', 0x1c000000, 7, 'f'}, + { 'e', 0x1e000000, 8, '-'}, + { 'e', 0x1f000000, 8, 'h'}, + { 'e', 0x20000000, 6, 'v'}, + { 'e', 0x24000000, 6, 'i'}, + { 'e', 0x28000000, 6, 'y'}, + { 'e', 0x2c000000, 8, 'k'}, + { 'e', 0x2d000000, 10, ')'}, + { 'e', 0x2d400000, 10, 'q'}, + { 'e', 0x2d800000, 9, ':'}, + { 'e', 0x2e000000, 7, 'b'}, + { 'e', 0x30000000, 4, 'a'}, + { 'e', 0x40000000, 3, 's'}, + { 'e', 0x60000000, 5, 'e'}, + { 'e', 0x68000000, 5, 'w'}, + { 'e', 0x70000000, 6, 'm'}, + { 'e', 0x74000000, 7, ','}, + { 'e', 0x76000000, 8, '\''}, + { 'e', 0x77000000, 11, 'z'}, + { 'e', 0x77240000, 14, '4'}, + { 'e', 0x77280000, 14, 'B'}, + { 'e', 0x772c0000, 16, ESCAPE}, + { 'e', 0x772d4000, 18, 'G'}, + { 'e', 0x772f4000, 21, '2'}, + { 'e', 0x77300000, 13, '/'}, + { 'e', 0x77380000, 14, ']'}, + { 'e', 0x773c0000, 14, ';'}, + { 'e', 0x77400000, 10, '?'}, + { 'e', 0x77800000, 10, 'u'}, + { 'e', 0x77c00000, 11, '!'}, + { 'e', 0x77e00000, 12, STOP}, + { 'e', 0x77f00000, 12, 'j'}, + { 'e', 0x78000000, 5, 't'}, + { 'e', 0x80000000, 2, ' '}, + { 'e', 0xc0000000, 3, 'r'}, + { 'e', 0xe0000000, 5, 'l'}, + { 'e', 0xe8000000, 6, '.'}, + { 'e', 0xec000000, 7, 'p'}, + { 'e', 0xee000000, 8, 'g'}, + { 'e', 0xef000000, 8, 'o'}, + { 'e', 0xf0000000, 4, 'n'}, + { 'f', 0x00000000, 2, 'o'}, + { 'f', 0x40000000, 3, 'i'}, + { 'f', 0x60000000, 5, 't'}, + { 'f', 0x68000000, 8, 's'}, + { 'f', 0x69000000, 8, 'y'}, + { 'f', 0x6a000000, 10, '?'}, + { 'f', 0x6a400000, 12, 'm'}, + { 'f', 0x6a500000, 16, 'h'}, + { 'f', 0x6a560000, 16, ';'}, + { 'f', 0x6a600000, 11, ':'}, + { 'f', 0x6a800000, 11, '\''}, + { 'f', 0x6aa00000, 11, 'g'}, + { 'f', 0x6ac00000, 10, ','}, + { 'f', 0x6b000000, 9, '.'}, + { 'f', 0x6b800000, 12, ESCAPE}, + { 'f', 0x6b980000, 14, ')'}, + { 'f', 0x6b9c0000, 14, 'w'}, + { 'f', 0x6bb00000, 12, 'n'}, + { 'f', 0x6bc00000, 10, '-'}, + { 'f', 0x6c000000, 6, 'l'}, + { 'f', 0x70000000, 4, 'a'}, + { 'f', 0x80000000, 2, ' '}, + { 'f', 0xc0000000, 3, 'r'}, + { 'f', 0xe0000000, 4, 'e'}, + { 'f', 0xf0000000, 5, 'u'}, + { 'f', 0xf8000000, 5, 'f'}, + { 'g', 0x00000000, 3, 'a'}, + { 'g', 0x20000000, 9, 'd'}, + { 'g', 0x20800000, 10, '?'}, + { 'g', 0x20c00000, 10, 'm'}, + { 'g', 0x21000000, 8, '\''}, + { 'g', 0x22000000, 8, '-'}, + { 'g', 0x23000000, 8, ':'}, + { 'g', 0x24000000, 6, ','}, + { 'g', 0x28000000, 6, 'n'}, + { 'g', 0x2c000000, 7, 'y'}, + { 'g', 0x2e000000, 13, 'k'}, + { 'g', 0x2e080000, 14, ')'}, + { 'g', 0x2e0c0000, 14, '"'}, + { 'g', 0x2e100000, 12, ';'}, + { 'g', 0x2e200000, 11, '!'}, + { 'g', 0x2e400000, 13, 'p'}, + { 'g', 0x2e480000, 16, ESCAPE}, + { 'g', 0x2e4e0000, 15, '/'}, + { 'g', 0x2e600000, 11, 'f'}, + { 'g', 0x2e800000, 9, 'b'}, + { 'g', 0x2f000000, 9, 't'}, + { 'g', 0x2f800000, 9, 'w'}, + { 'g', 0x30000000, 4, 'u'}, + { 'g', 0x40000000, 3, 'h'}, + { 'g', 0x60000000, 4, 'r'}, + { 'g', 0x70000000, 5, 'l'}, + { 'g', 0x78000000, 6, 'g'}, + { 'g', 0x7c000000, 6, '.'}, + { 'g', 0x80000000, 4, 'i'}, + { 'g', 0x90000000, 5, 's'}, + { 'g', 0x98000000, 5, 'o'}, + { 'g', 0xa0000000, 3, 'e'}, + { 'g', 0xc0000000, 2, ' '}, + { 'h', 0x00000000, 1, 'e'}, + { 'h', 0x80000000, 3, 'o'}, + { 'h', 0xa0000000, 3, 'i'}, + { 'h', 0xc0000000, 3, ' '}, + { 'h', 0xe0000000, 9, 'd'}, + { 'h', 0xe0880000, 15, 'p'}, + { 'h', 0xe08a0000, 15, ';'}, + { 'h', 0xe08c0000, 15, '/'}, + { 'h', 0xe0900000, 12, 'c'}, + { 'h', 0xe0a00000, 13, 'h'}, + { 'h', 0xe0a80000, 13, 'k'}, + { 'h', 0xe0b00000, 12, '?'}, + { 'h', 0xe0c00000, 10, 'w'}, + { 'h', 0xe1000000, 8, 'y'}, + { 'h', 0xe2000000, 9, 's'}, + { 'h', 0xe2800000, 10, '\''}, + { 'h', 0xe2c00000, 10, '-'}, + { 'h', 0xe3000000, 8, 'l'}, + { 'h', 0xe4000000, 6, 'r'}, + { 'h', 0xe8000000, 8, '.'}, + { 'h', 0xe9000000, 8, 'n'}, + { 'h', 0xea000000, 9, ','}, + { 'h', 0xea800000, 12, '!'}, + { 'h', 0xea910000, 17, ESCAPE}, + { 'h', 0xea940000, 14, 'g'}, + { 'h', 0xea980000, 13, 'f'}, + { 'h', 0xeaa00000, 11, 'm'}, + { 'h', 0xeac00000, 11, ':'}, + { 'h', 0xeae00000, 11, 'b'}, + { 'h', 0xeb000000, 8, 'u'}, + { 'h', 0xec000000, 6, 't'}, + { 'h', 0xf0000000, 4, 'a'}, + { 'i', 0x00000000, 3, 't'}, + { 'i', 0x20000000, 5, 'a'}, + { 'i', 0x28000000, 6, 'p'}, + { 'i', 0x2c000000, 7, 'z'}, + { 'i', 0x2e000000, 9, '-'}, + { 'i', 0x2e800000, 9, 'x'}, + { 'i', 0x2f000000, 8, 'b'}, + { 'i', 0x30000000, 4, 'l'}, + { 'i', 0x40000000, 3, 's'}, + { 'i', 0x60000000, 5, 'm'}, + { 'i', 0x68000000, 5, 'd'}, + { 'i', 0x70000000, 5, 'v'}, + { 'i', 0x78000000, 6, 'f'}, + { 'i', 0x7c000000, 7, ' '}, + { 'i', 0x7e000000, 8, 'k'}, + { 'i', 0x7f000000, 10, 'u'}, + { 'i', 0x7f400000, 11, '.'}, + { 'i', 0x7f600000, 15, '/'}, + { 'i', 0x7f622000, 19, 'C'}, + { 'i', 0x7f624000, 19, ESCAPE}, + { 'i', 0x7f627000, 20, ';'}, + { 'i', 0x7f640000, 14, ':'}, + { 'i', 0x7f680000, 13, 'i'}, + { 'i', 0x7f700000, 12, 'w'}, + { 'i', 0x7f800000, 10, 'q'}, + { 'i', 0x7fc00000, 11, ','}, + { 'i', 0x7fe00000, 14, 'h'}, + { 'i', 0x7fe50000, 18, ')'}, + { 'i', 0x7fe80000, 13, 'j'}, + { 'i', 0x7ff00000, 12, '\''}, + { 'i', 0x80000000, 2, 'n'}, + { 'i', 0xc0000000, 4, 'o'}, + { 'i', 0xd0000000, 4, 'c'}, + { 'i', 0xe0000000, 5, 'g'}, + { 'i', 0xe8000000, 5, 'r'}, + { 'i', 0xf0000000, 4, 'e'}, + { 'j', 0x00000000, 1, 'o'}, + { 'j', 0x80000000, 5, 'i'}, + { 'j', 0x88800000, 11, 'n'}, + { 'j', 0x88a00000, 13, ESCAPE}, + { 'j', 0x8a000000, 7, ' '}, + { 'j', 0x90000000, 4, 'e'}, + { 'j', 0xa0000000, 3, 'a'}, + { 'j', 0xc0000000, 2, 'u'}, + { 'k', 0x00000000, 3, 's'}, + { 'k', 0x20000000, 4, '.'}, + { 'k', 0x30000000, 6, '\''}, + { 'k', 0x34000000, 6, 'a'}, + { 'k', 0x38000000, 6, 'p'}, + { 'k', 0x3c000000, 6, ','}, + { 'k', 0x40000000, 7, '/'}, + { 'k', 0x42000000, 10, 'r'}, + { 'k', 0x42800000, 10, '?'}, + { 'k', 0x42c00000, 11, 'j'}, + { 'k', 0x42e00000, 12, ')'}, + { 'k', 0x43000000, 10, 't'}, + { 'k', 0x43400000, 10, 'g'}, + { 'k', 0x43800000, 9, 'b'}, + { 'k', 0x44000000, 7, '-'}, + { 'k', 0x46000000, 7, 'o'}, + { 'k', 0x48000000, 5, 'y'}, + { 'k', 0x50000000, 6, 'l'}, + { 'k', 0x54000000, 6, 'f'}, + { 'k', 0x58000000, 6, 'n'}, + { 'k', 0x5c000000, 9, 'w'}, + { 'k', 0x5c800000, 9, 'm'}, + { 'k', 0x5d000000, 8, ':'}, + { 'k', 0x5e000000, 9, 'h'}, + { 'k', 0x5e800000, 12, ';'}, + { 'k', 0x5e900000, 12, 'c'}, + { 'k', 0x5eb00000, 13, '!'}, + { 'k', 0x5ec00000, 10, 'd'}, + { 'k', 0x5f000000, 9, 'u'}, + { 'k', 0x5f800000, 9, 'k'}, + { 'k', 0x60000000, 3, 'i'}, + { 'k', 0x80000000, 2, ' '}, + { 'k', 0xc0000000, 2, 'e'}, + { 'l', 0x00000000, 4, 'u'}, + { 'l', 0x10000000, 4, 'd'}, + { 'l', 0x20000000, 4, 'y'}, + { 'l', 0x30000000, 6, '.'}, + { 'l', 0x34000000, 7, 'v'}, + { 'l', 0x36000000, 10, 'r'}, + { 'l', 0x36400000, 10, 'h'}, + { 'l', 0x36800000, 9, ':'}, + { 'l', 0x37000000, 8, 'c'}, + { 'l', 0x38000000, 6, 't'}, + { 'l', 0x3c000000, 7, 'f'}, + { 'l', 0x3e000000, 8, '-'}, + { 'l', 0x3f000000, 10, 'n'}, + { 'l', 0x3f400000, 10, 'g'}, + { 'l', 0x3f800000, 9, 'b'}, + { 'l', 0x40000000, 3, 'a'}, + { 'l', 0x60000000, 3, 'i'}, + { 'l', 0x80000000, 3, 'l'}, + { 'l', 0xa0000000, 5, 's'}, + { 'l', 0xa8000000, 7, 'm'}, + { 'l', 0xaa000000, 7, 'k'}, + { 'l', 0xac000000, 7, 'p'}, + { 'l', 0xae000000, 9, '\''}, + { 'l', 0xae800000, 11, '?'}, + { 'l', 0xaea80000, 15, ';'}, + { 'l', 0xaeaa0000, 17, '@'}, + { 'l', 0xaeaa8000, 17, 'j'}, + { 'l', 0xaeab0000, 16, ESCAPE}, + { 'l', 0xaeac0000, 14, '/'}, + { 'l', 0xaeb00000, 13, 'z'}, + { 'l', 0xaeb80000, 15, 'E'}, + { 'l', 0xaebc0000, 16, ')'}, + { 'l', 0xaec00000, 10, 'w'}, + { 'l', 0xaf000000, 8, ','}, + { 'l', 0xb0000000, 4, 'o'}, + { 'l', 0xc0000000, 3, 'e'}, + { 'l', 0xe0000000, 3, ' '}, + { 'm', 0x00000000, 2, 'a'}, + { 'm', 0x40000000, 2, 'e'}, + { 'm', 0x80000000, 5, '.'}, + { 'm', 0x88000000, 5, 's'}, + { 'm', 0x90000000, 4, 'p'}, + { 'm', 0xa0000000, 7, ','}, + { 'm', 0xa3000000, 9, ':'}, + { 'm', 0xa3800000, 11, '?'}, + { 'm', 0xa3a00000, 11, '!'}, + { 'm', 0xa3c00000, 10, 'r'}, + { 'm', 0xa4000000, 6, 'y'}, + { 'm', 0xa8000000, 7, '/'}, + { 'm', 0xaa000000, 9, '\''}, + { 'm', 0xaa800200, 23, STOP}, + { 'm', 0xaaa00000, 11, 'w'}, + { 'm', 0xaac00000, 10, 'f'}, + { 'm', 0xab000000, 10, 'l'}, + { 'm', 0xab400000, 14, ')'}, + { 'm', 0xab440000, 14, ESCAPE}, + { 'm', 0xab490000, 17, 'k'}, + { 'm', 0xab498000, 17, 'z'}, + { 'm', 0xab4c0000, 14, 'd'}, + { 'm', 0xab500000, 13, 't'}, + { 'm', 0xab600000, 11, 'h'}, + { 'm', 0xab800000, 10, 'n'}, + { 'm', 0xabc00000, 11, '-'}, + { 'm', 0xabf00000, 13, ';'}, + { 'm', 0xabf80000, 13, 'c'}, + { 'm', 0xac000000, 6, 'b'}, + { 'm', 0xb0000000, 4, 'o'}, + { 'm', 0xc0000000, 4, 'i'}, + { 'm', 0xd0000000, 5, 'u'}, + { 'm', 0xd8000000, 5, 'm'}, + { 'm', 0xe0000000, 3, ' '}, + { 'n', 0x00000000, 4, 's'}, + { 'n', 0x10000000, 8, 'm'}, + { 'n', 0x11000000, 11, 'p'}, + { 'n', 0x11200000, 13, '/'}, + { 'n', 0x11300000, 12, ';'}, + { 'n', 0x11400000, 10, 'z'}, + { 'n', 0x11800000, 9, 'w'}, + { 'n', 0x12000000, 7, 'u'}, + { 'n', 0x14000000, 8, 'l'}, + { 'n', 0x15000000, 8, '-'}, + { 'n', 0x16000000, 7, 'v'}, + { 'n', 0x18000000, 7, 'f'}, + { 'n', 0x1a000000, 10, 'h'}, + { 'n', 0x1a400000, 13, ESCAPE}, + { 'n', 0x1a480000, 14, 'B'}, + { 'n', 0x1a500000, 12, ')'}, + { 'n', 0x1a600000, 11, 'x'}, + { 'n', 0x1a800000, 9, ':'}, + { 'n', 0x1b000000, 10, 'b'}, + { 'n', 0x1b400000, 10, 'j'}, + { 'n', 0x1b800000, 10, 'r'}, + { 'n', 0x1bc00000, 12, '!'}, + { 'n', 0x1bd00000, 12, 'q'}, + { 'n', 0x1be00000, 11, '?'}, + { 'n', 0x1c000000, 6, '.'}, + { 'n', 0x20000000, 3, 't'}, + { 'n', 0x40000000, 2, ' '}, + { 'n', 0x80000000, 3, 'g'}, + { 'n', 0xa0000000, 4, 'a'}, + { 'n', 0xb0000000, 5, 'c'}, + { 'n', 0xb8000000, 7, 'k'}, + { 'n', 0xba000000, 7, '\''}, + { 'n', 0xbc000000, 6, 'n'}, + { 'n', 0xc0000000, 5, 'i'}, + { 'n', 0xc8000000, 7, 'y'}, + { 'n', 0xca000000, 7, ','}, + { 'n', 0xcc000000, 6, 'o'}, + { 'n', 0xd0000000, 4, 'e'}, + { 'n', 0xe0000000, 3, 'd'}, + { 'o', 0x00000000, 4, 'l'}, + { 'o', 0x10000000, 5, 'v'}, + { 'o', 0x18000000, 6, 'k'}, + { 'o', 0x1c000000, 6, 'i'}, + { 'o', 0x20000000, 3, 'u'}, + { 'o', 0x40000000, 5, 's'}, + { 'o', 0x48000000, 5, 'p'}, + { 'o', 0x50000000, 6, 'g'}, + { 'o', 0x54000000, 9, '-'}, + { 'o', 0x54800000, 9, ','}, + { 'o', 0x55000000, 8, 'h'}, + { 'o', 0x56000000, 7, 'e'}, + { 'o', 0x58000000, 7, 'y'}, + { 'o', 0x5a000000, 7, 'a'}, + { 'o', 0x5c000000, 6, 'c'}, + { 'o', 0x60000000, 3, ' '}, + { 'o', 0x80000000, 3, 'r'}, + { 'o', 0xa0000000, 5, 't'}, + { 'o', 0xa8000000, 5, 'o'}, + { 'o', 0xb0000000, 8, '.'}, + { 'o', 0xb1000000, 13, '!'}, + { 'o', 0xb10d0000, 16, ';'}, + { 'o', 0xb10e0000, 16, 'G'}, + { 'o', 0xb10ff000, 20, 'C'}, + { 'o', 0xb1100000, 12, '?'}, + { 'o', 0xb1200000, 11, ':'}, + { 'o', 0xb1400000, 10, '\''}, + { 'o', 0xb1800000, 14, '/'}, + { 'o', 0xb1840000, 14, ')'}, + { 'o', 0xb1880000, 13, 'q'}, + { 'o', 0xb1900000, 12, 'j'}, + { 'o', 0xb1a00000, 11, 'z'}, + { 'o', 0xb1c00000, 10, 'x'}, + { 'o', 0xb2000000, 7, 'b'}, + { 'o', 0xb4000000, 6, 'd'}, + { 'o', 0xb8000000, 5, 'w'}, + { 'o', 0xc0000000, 4, 'm'}, + { 'o', 0xd0000000, 4, 'f'}, + { 'o', 0xe0000000, 3, 'n'}, + { 'p', 0x00000000, 4, 'p'}, + { 'p', 0x10000000, 8, '-'}, + { 'p', 0x11200000, 11, 'f'}, + { 'p', 0x11400000, 11, 'k'}, + { 'p', 0x11600000, 11, '!'}, + { 'p', 0x11800000, 9, '?'}, + { 'p', 0x12000000, 7, 'd'}, + { 'p', 0x14000000, 6, 'm'}, + { 'p', 0x18000000, 5, 't'}, + { 'p', 0x20000000, 3, 'l'}, + { 'p', 0x40000000, 3, ' '}, + { 'p', 0x60000000, 3, 'o'}, + { 'p', 0x80000000, 5, 'u'}, + { 'p', 0x88000000, 5, 'h'}, + { 'p', 0x90000000, 5, 's'}, + { 'p', 0x98000000, 17, ESCAPE}, + { 'p', 0x98080000, 13, 'g'}, + { 'p', 0x98100000, 12, '/'}, + { 'p', 0x98200000, 11, 'c'}, + { 'p', 0x98400000, 11, 'n'}, + { 'p', 0x98600000, 11, 'w'}, + { 'p', 0x98800000, 9, ':'}, + { 'p', 0x99000000, 10, '\''}, + { 'p', 0x99c00000, 10, 'b'}, + { 'p', 0x9a000000, 7, 'y'}, + { 'p', 0x9c000000, 7, '.'}, + { 'p', 0x9e000000, 7, ','}, + { 'p', 0xa0000000, 3, 'r'}, + { 'p', 0xc0000000, 4, 'a'}, + { 'p', 0xd0000000, 4, 'i'}, + { 'p', 0xe0000000, 3, 'e'}, + { 'q', 0x00000000, 3, ','}, + { 'q', 0x20000000, 3, '.'}, + { 'q', 0x44000000, 6, 'a'}, + { 'q', 0x60000000, 3, ' '}, + { 'q', 0x80000000, 1, 'u'}, + { 'r', 0x00000000, 3, 'a'}, + { 'r', 0x20000000, 3, 'o'}, + { 'r', 0x40000000, 4, 's'}, + { 'r', 0x50000000, 4, 't'}, + { 'r', 0x60000000, 7, 'f'}, + { 'r', 0x62018000, 17, 'Z'}, + { 'r', 0x62040000, 16, 'x'}, + { 'r', 0x62050000, 16, ESCAPE}, + { 'r', 0x62080000, 13, ';'}, + { 'r', 0x62100000, 12, 'q'}, + { 'r', 0x62200000, 12, 'j'}, + { 'r', 0x62400000, 11, '!'}, + { 'r', 0x62600000, 12, '/'}, + { 'r', 0x62740000, 14, 'z'}, + { 'r', 0x62780000, 13, ')'}, + { 'r', 0x62800000, 9, ':'}, + { 'r', 0x63000000, 8, '\''}, + { 'r', 0x64000000, 7, ','}, + { 'r', 0x66000000, 7, 'v'}, + { 'r', 0x68000000, 6, 'u'}, + { 'r', 0x6c000000, 6, 'm'}, + { 'r', 0x70000000, 5, 'd'}, + { 'r', 0x78000000, 8, '-'}, + { 'r', 0x79000000, 8, 'b'}, + { 'r', 0x7a000000, 9, 'w'}, + { 'r', 0x7a800000, 10, '?'}, + { 'r', 0x7ac00000, 10, 'h'}, + { 'r', 0x7b000000, 8, 'p'}, + { 'r', 0x7c000000, 6, 'k'}, + { 'r', 0x80000000, 3, 'i'}, + { 'r', 0xa0000000, 5, 'n'}, + { 'r', 0xa8000000, 5, 'y'}, + { 'r', 0xb0000000, 7, 'c'}, + { 'r', 0xb2000000, 7, 'g'}, + { 'r', 0xb4000000, 6, 'l'}, + { 'r', 0xb8000000, 6, '.'}, + { 'r', 0xbc000000, 6, 'r'}, + { 'r', 0xc0000000, 3, ' '}, + { 'r', 0xe0000000, 3, 'e'}, + { 's', 0x00000000, 1, ' '}, + { 's', 0x80000000, 4, '.'}, + { 's', 0x90000000, 10, '!'}, + { 's', 0x90400000, 10, 'g'}, + { 's', 0x90800000, 9, 'b'}, + { 's', 0x91000000, 8, 'n'}, + { 's', 0x92000000, 9, 'f'}, + { 's', 0x92800000, 10, 'r'}, + { 's', 0x92c00000, 12, '/'}, + { 's', 0x92d00000, 12, ')'}, + { 's', 0x92e20000, 15, '"'}, + { 's', 0x92e58000, 17, '@'}, + { 's', 0x92e60000, 15, 'z'}, + { 's', 0x92e80000, 13, 'v'}, + { 's', 0x92f00000, 12, STOP}, + { 's', 0x93000000, 8, 'm'}, + { 's', 0x94000000, 6, 'c'}, + { 's', 0x98000000, 5, ','}, + { 's', 0xa0000000, 3, 't'}, + { 's', 0xc0000000, 5, 'o'}, + { 's', 0xc8000000, 5, 's'}, + { 's', 0xd0000000, 6, 'u'}, + { 's', 0xd4000000, 8, 'y'}, + { 's', 0xd5000000, 9, 'w'}, + { 's', 0xd5800000, 10, '?'}, + { 's', 0xd5c00000, 10, '-'}, + { 's', 0xd6000000, 8, ':'}, + { 's', 0xd7000000, 12, ']'}, + { 's', 0xd7100000, 12, ';'}, + { 's', 0xd7200000, 11, 'd'}, + { 's', 0xd7400000, 10, 'q'}, + { 's', 0xd7800000, 9, '\''}, + { 's', 0xd8000000, 6, 'p'}, + { 's', 0xdc000000, 8, 'l'}, + { 's', 0xdd000000, 8, 'k'}, + { 's', 0xde000000, 7, 'a'}, + { 's', 0xe0000000, 4, 'e'}, + { 's', 0xf0000000, 5, 'h'}, + { 's', 0xf8000000, 5, 'i'}, + { 't', 0x00000000, 3, 'i'}, + { 't', 0x20000000, 4, 'a'}, + { 't', 0x30000000, 5, 'u'}, + { 't', 0x38000000, 9, 'n'}, + { 't', 0x38800000, 11, '!'}, + { 't', 0x38a00000, 13, 'g'}, + { 't', 0x38a80000, 13, ';'}, + { 't', 0x38b94000, 19, 'j'}, + { 't', 0x38ba0000, 16, 'E'}, + { 't', 0x38bc0000, 14, ')'}, + { 't', 0x38c00000, 10, '?'}, + { 't', 0x39000000, 8, '-'}, + { 't', 0x3a000000, 7, 'c'}, + { 't', 0x3c000000, 6, '.'}, + { 't', 0x40000000, 3, 'o'}, + { 't', 0x60000000, 3, 'e'}, + { 't', 0x80000000, 2, 'h'}, + { 't', 0xc0000000, 8, 'v'}, + { 't', 0xc1000000, 8, 'm'}, + { 't', 0xc2000000, 7, 'l'}, + { 't', 0xc4000000, 6, 't'}, + { 't', 0xc8000000, 5, 'r'}, + { 't', 0xd0000000, 6, 'y'}, + { 't', 0xd4000000, 11, 'z'}, + { 't', 0xd4300000, 13, 'p'}, + { 't', 0xd4380000, 14, '/'}, + { 't', 0xd43c0000, 14, 'k'}, + { 't', 0xd4400000, 10, 'b'}, + { 't', 0xd4800000, 10, ':'}, + { 't', 0xd4c00000, 11, 'd'}, + { 't', 0xd4e00000, 11, 'f'}, + { 't', 0xd5000000, 8, 'w'}, + { 't', 0xd6000000, 8, ','}, + { 't', 0xd7000000, 8, '\''}, + { 't', 0xd8000000, 5, 's'}, + { 't', 0xe0000000, 3, ' '}, + { 'u', 0x00000000, 5, 'b'}, + { 'u', 0x08000000, 5, ' '}, + { 'u', 0x10000000, 4, 'd'}, + { 'u', 0x20000000, 4, 'e'}, + { 'u', 0x30000000, 5, 'i'}, + { 'u', 0x38000000, 7, 'y'}, + { 'u', 0x3a000000, 8, 'z'}, + { 'u', 0x3b000000, 11, 'w'}, + { 'u', 0x3b200000, 12, 'q'}, + { 'u', 0x3b300000, 13, 'j'}, + { 'u', 0x3b380000, 15, 'u'}, + { 'u', 0x3b3a0000, 15, '?'}, + { 'u', 0x3b400000, 10, '-'}, + { 'u', 0x3b800000, 10, 'o'}, + { 'u', 0x3bc00000, 11, ':'}, + { 'u', 0x3be00000, 12, 'h'}, + { 'u', 0x3bf00000, 12, 'v'}, + { 'u', 0x3c000000, 8, '\''}, + { 'u', 0x3d000000, 9, ','}, + { 'u', 0x3d800000, 10, '.'}, + { 'u', 0x3dc00000, 10, 'x'}, + { 'u', 0x3e000000, 8, 'f'}, + { 'u', 0x3f000000, 8, 'k'}, + { 'u', 0x40000000, 5, 'a'}, + { 'u', 0x48000000, 5, 'g'}, + { 'u', 0x50000000, 4, 'l'}, + { 'u', 0x60000000, 3, 't'}, + { 'u', 0x80000000, 4, 'p'}, + { 'u', 0x90000000, 5, 'c'}, + { 'u', 0x98000000, 5, 'm'}, + { 'u', 0xa0000000, 3, 'n'}, + { 'u', 0xc0000000, 3, 's'}, + { 'u', 0xe0000000, 3, 'r'}, + { 'v', 0x00000000, 3, 'a'}, + { 'v', 0x20000000, 9, 'u'}, + { 'v', 0x20b00000, 12, 'v'}, + { 'v', 0x20c00000, 11, ','}, + { 'v', 0x20e40000, 15, 't'}, + { 'v', 0x20e78000, 18, ESCAPE}, + { 'v', 0x20f00000, 12, 'l'}, + { 'v', 0x21000000, 8, '\''}, + { 'v', 0x22000000, 9, 's'}, + { 'v', 0x22800000, 10, 'r'}, + { 'v', 0x22c00000, 11, 'n'}, + { 'v', 0x22e00000, 12, '@'}, + { 'v', 0x22f00000, 12, ':'}, + { 'v', 0x23000000, 8, 'y'}, + { 'v', 0x24000000, 6, ' '}, + { 'v', 0x28000000, 5, '.'}, + { 'v', 0x30000000, 4, 'o'}, + { 'v', 0x40000000, 2, 'i'}, + { 'v', 0x80000000, 1, 'e'}, + { 'w', 0x00000000, 2, 'i'}, + { 'w', 0x40000000, 5, '.'}, + { 'w', 0x50000000, 4, 'a'}, + { 'w', 0x60000000, 3, 'e'}, + { 'w', 0x80000000, 3, ' '}, + { 'w', 0xa0000000, 3, 's'}, + { 'w', 0xc0000000, 3, 'h'}, + { 'w', 0xe0000000, 5, 'n'}, + { 'w', 0xe8000000, 11, 'f'}, + { 'w', 0xe8200000, 11, ']'}, + { 'w', 0xe8400000, 11, '!'}, + { 'w', 0xe8680000, 13, 'u'}, + { 'w', 0xe8700000, 12, 'g'}, + { 'w', 0xe8800000, 10, ':'}, + { 'w', 0xe8c00000, 12, '?'}, + { 'w', 0xe8d00000, 12, 't'}, + { 'w', 0xe8e00000, 11, 'k'}, + { 'w', 0xe9000000, 9, 'c'}, + { 'w', 0xe9800000, 10, 'm'}, + { 'w', 0xe9c00000, 10, '\''}, + { 'w', 0xea000000, 8, ','}, + { 'w', 0xeb000000, 8, 'l'}, + { 'w', 0xec000000, 7, 'r'}, + { 'w', 0xee000000, 10, 'd'}, + { 'w', 0xee400000, 11, '-'}, + { 'w', 0xee640000, 14, 'j'}, + { 'w', 0xee800000, 9, 'b'}, + { 'w', 0xef000000, 8, 'y'}, + { 'w', 0xf0000000, 4, 'o'}, + { 'x', 0x00000000, 4, 'i'}, + { 'x', 0x10000000, 5, 'u'}, + { 'x', 0x18000000, 6, 'f'}, + { 'x', 0x1c000000, 7, ','}, + { 'x', 0x1e000000, 7, 'm'}, + { 'x', 0x20000000, 4, 'a'}, + { 'x', 0x30b00000, 12, '/'}, + { 'x', 0x30c00000, 10, '?'}, + { 'x', 0x32000000, 7, 'y'}, + { 'x', 0x34000000, 6, 'o'}, + { 'x', 0x38000000, 5, 'e'}, + { 'x', 0x40000000, 2, 'p'}, + { 'x', 0x80000000, 4, 'c'}, + { 'x', 0x90000000, 6, '.'}, + { 'x', 0x94000000, 9, ':'}, + { 'x', 0x94800000, 10, 'l'}, + { 'x', 0x94e00000, 11, 'b'}, + { 'x', 0x95000000, 8, '\''}, + { 'x', 0x97000000, 9, 'h'}, + { 'x', 0x97800000, 10, 'w'}, + { 'x', 0x97d80000, 13, ';'}, + { 'x', 0x97e00000, 11, ')'}, + { 'x', 0x98000000, 5, '-'}, + { 'x', 0xa0000000, 3, ' '}, + { 'x', 0xc0000000, 2, 't'}, + { 'y', 0x00000000, 3, 'o'}, + { 'y', 0x20000000, 7, 'w'}, + { 'y', 0x22000000, 11, ')'}, + { 'y', 0x222a0000, 15, 'x'}, + { 'y', 0x22300000, 12, 'k'}, + { 'y', 0x22400000, 10, ';'}, + { 'y', 0x22c00000, 12, ESCAPE}, + { 'y', 0x22e00000, 11, '/'}, + { 'y', 0x23000000, 8, 'b'}, + { 'y', 0x24000000, 6, 'a'}, + { 'y', 0x28000000, 6, 'i'}, + { 'y', 0x2c000000, 6, 'd'}, + { 'y', 0x30000000, 4, 's'}, + { 'y', 0x40000000, 8, '?'}, + { 'y', 0x41000000, 8, 'r'}, + { 'y', 0x42000000, 8, 'p'}, + { 'y', 0x43000000, 8, 'f'}, + { 'y', 0x44000000, 6, 'n'}, + { 'y', 0x48000000, 5, ','}, + { 'y', 0x50000000, 4, '.'}, + { 'y', 0x60000000, 5, 'e'}, + { 'y', 0x68000000, 7, 't'}, + { 'y', 0x6a000000, 7, 'm'}, + { 'y', 0x6c000000, 6, ':'}, + { 'y', 0x70000000, 5, '\''}, + { 'y', 0x78000000, 10, 'h'}, + { 'y', 0x78400000, 10, '!'}, + { 'y', 0x78810000, 16, 'T'}, + { 'y', 0x78830000, 16, 'P'}, + { 'y', 0x78880000, 13, '"'}, + { 'y', 0x78900000, 12, STOP}, + { 'y', 0x78a00000, 11, ']'}, + { 'y', 0x78c00000, 10, 'g'}, + { 'y', 0x79000000, 8, 'c'}, + { 'y', 0x7a000000, 7, '-'}, + { 'y', 0x7c000000, 6, 'l'}, + { 'y', 0x80000000, 1, ' '}, + { 'z', 0x04000000, 7, '\''}, + { 'z', 0x07000000, 8, 't'}, + { 'z', 0x08000000, 6, ','}, + { 'z', 0x0c000000, 6, '.'}, + { 'z', 0x10000000, 4, 'l'}, + { 'z', 0x20000000, 3, 'a'}, + { 'z', 0x40000000, 4, 'y'}, + { 'z', 0x50000000, 5, 'o'}, + { 'z', 0x5c800000, 11, 's'}, + { 'z', 0x5cc00000, 12, 'h'}, + { 'z', 0x5d000000, 8, 'm'}, + { 'z', 0x5e000000, 9, '-'}, + { 'z', 0x5e800000, 9, 'u'}, + { 'z', 0x5f100000, 14, 'q'}, + { 'z', 0x5f140000, 14, 'n'}, + { 'z', 0x5f180000, 13, 'v'}, + { 'z', 0x5f800000, 9, 'b'}, + { 'z', 0x60000000, 3, 'z'}, + { 'z', 0x80000000, 2, 'e'}, + { 'z', 0xc0000000, 3, ' '}, + { 'z', 0xe0000000, 3, 'i'}, + { '}', 0x0819c000, 18, STOP} +}; diff --git a/src/eitd/Makefile.am b/src/eitd/Makefile.am new file mode 100644 index 000000000..200019dbe --- /dev/null +++ b/src/eitd/Makefile.am @@ -0,0 +1,20 @@ +INCLUDES = \ + -I$(top_srcdir)/src \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src/zapit/include \ + -I$(top_srcdir)/lib/libconfigfile \ + -I$(top_srcdir)/lib/connection \ + -I$(top_srcdir)/lib/libeventserver \ + -I$(top_srcdir)/lib/xmltree + +if BOXTYPE_COOL +INCLUDES += -I$(top_srcdir)/lib/libcoolstream +endif +if BOXTYPE_TRIPLE +INCLUDES += -I$(top_srcdir)/lib/libtriple +endif + +AM_CPPFLAGS = -D DO_NOT_INCLUDE_STUFF_NOT_NEEDED_FOR_SECTIONSD + +noinst_LIBRARIES = libsectionsd.a +libsectionsd_a_SOURCES = sectionsd.cpp dmxapi.cpp debug.cpp dmx.cpp SIsections.cpp SIevents.cpp SIutils.cpp SIlanguage.cpp edvbstring.cpp diff --git a/src/eitd/SIbouquets.hpp b/src/eitd/SIbouquets.hpp new file mode 100644 index 000000000..42b8414c0 --- /dev/null +++ b/src/eitd/SIbouquets.hpp @@ -0,0 +1,141 @@ +#ifndef SIBOUQUETS_HPP +#define SIBOUQUETS_HPP +// +// $Id: SIbouquets.hpp,v 1.2 2006/02/08 21:15:50 houdini Exp $ +// +// classes SIservices and SIservices (dbox-II-project) +// +// Homepage: http://dbox2.elxsi.de +// +// Copyright (C) 2001 fnbrd (fnbrd@gmx.de), +// 2002 thegoodguy (thegoodguy@berlios.de) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + + +#include +#include + +#include + +// forward references +class SIservice; +class SIevent; +class SIbouquet; + +struct loop_len { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned reserved_future_use : 4; + unsigned descriptors_loop_length_hi : 4; +#else + unsigned descriptors_loop_length_hi : 4; + unsigned reserved_future_use : 4; +#endif + unsigned descriptors_loop_length_lo : 8; +} __attribute__ ((packed)) ; // 2 Bytes + +struct bat_service { + + unsigned transport_stream_id_hi : 8; + unsigned transport_stream_id_lo : 8; + unsigned original_network_id_hi : 8; + unsigned original_network_id_lo : 8; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned reserved_future_use : 4; + unsigned descriptors_loop_length_hi : 4; +#else + unsigned descriptors_loop_length_hi : 4; + unsigned reserved_future_use : 4; +#endif + unsigned descriptors_loop_length_lo : 8; + +} __attribute__ ((packed)) ; // 6 Bytes + + + +class SIbouquet { +public: + SIbouquet(const t_bouquet_id _bouquet_id) { + + bouquet_id = _bouquet_id; + transport_stream_id = 0; + original_network_id = 0; + service_id = 0; + serviceTyp = 0; +// position = 0; + bouquetName = ""; + } + + // Um einen service zum Suchen zu erstellen + SIbouquet(const t_bouquet_id _bouquet_id, const t_service_id _service_id, const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id) + { + service_id = _service_id; + original_network_id = _original_network_id; + transport_stream_id = _transport_stream_id; + serviceTyp = 0; +// position = 0; + } + // Std-Copy + SIbouquet(const SIbouquet &s) { + + service_id = s.service_id; + original_network_id = s.original_network_id; + transport_stream_id = s.transport_stream_id; + bouquet_id = s.bouquet_id; + bouquetName = s.bouquetName; + serviceTyp = s.serviceTyp; + position = s.position; + } + + t_bouquet_id bouquet_id; // This is because of wrong design of sectionsd. Normally we would parse only tables instead of sections... + std::string bouquetName; // This is because of wrong design of sectionsd. Normally we would parse only tables instead of sections... + t_original_network_id original_network_id; + t_transport_stream_id transport_stream_id; + t_service_id service_id; + uint16_t position; + unsigned char serviceTyp; + bool operator < (const SIbouquet& s) const { + return uniqueKey() < s.uniqueKey(); + } + + t_bouquetentry_id uniqueKey(void) const { + return CREATE_BOUQUETENTRY_ID(bouquet_id, (uint16_t) serviceTyp, position, service_id); + } + + void dump(void) const { + + printf("Bouquet-ID: %hu\n", bouquet_id); + printf("Original-Network-ID: %hu\n", original_network_id); + printf("Transport-Stream-ID: %hu\n", transport_stream_id); + printf("Service-ID: %hu\n", service_id); + printf("Service-Typ: %hhu\n", serviceTyp); + if(bouquetName.length()) + printf("Bouquet-Name: %s\n", bouquetName.c_str()); + } +}; + +// Fuer for_each +struct printSIbouquet : public std::unary_function +{ + void operator() (const SIbouquet &s) { s.dump();} +}; + +// Als Klasse, da ich nicht weiss, wie man eine Forward-Referenz auf ein typedef macht +class SIbouquets : public std::set > +{ +}; + +#endif // SIBOUQUETS_HPP diff --git a/src/eitd/SIevents.cpp b/src/eitd/SIevents.cpp new file mode 100644 index 000000000..bc18c0ada --- /dev/null +++ b/src/eitd/SIevents.cpp @@ -0,0 +1,593 @@ +// +// $Id: SIevents.cpp,v 1.35 2008/08/16 19:23:18 seife Exp $ +// +// classes SIevent and SIevents (dbox-II-project) +// +// Homepage: http://dbox2.elxsi.de +// +// Copyright (C) 2001 fnbrd (fnbrd@gmx.de) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// +// + +#include +#include +#include + +#include +#include +#include +#include // fuer poll() + +#include +#include +#include + +#include "SIlanguage.hpp" +#include "SIutils.hpp" +#include "SIservices.hpp" +#include "SIevents.hpp" +#ifdef UPDATE_NETWORKS +#include "SIbouquets.hpp" +#include "SInetworks.hpp" +#endif +#include "SIsections.hpp" +#include + +const std::string languangeOFF = "OFF"; + +SIevent::SIevent(const struct eit_event *e) +{ + eventID = (e->event_id_hi << 8) | e->event_id_lo; + time_t start_time = changeUTCtoCtime(((const unsigned char *)e) + 2); + unsigned long duration = 0; + + if (!((e->duration_hi == 0xff) && (e->duration_mid == 0xff) && (e->duration_lo == 0xff))) + duration = ((e->duration_hi)>>4)*10*3600L + ((e->duration_hi)&0x0f)*3600L + + ((e->duration_mid)>>4)*10*60L + ((e->duration_mid)&0x0f)*60L + + ((e->duration_lo)>>4)*10 + ((e->duration_lo)&0x0f); + + if (start_time && duration) + times.insert(SItime(start_time, duration)); + + running = (int)e->running_status; + + table_id = 0xFF; /* not set */ + version = 0xFF; + service_id = 0; + original_network_id = 0; + transport_stream_id = 0; +} + +SIevent::SIevent(const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id, const t_service_id _service_id, + const unsigned short _event_id) +{ + original_network_id = _original_network_id; + transport_stream_id = _transport_stream_id; + service_id = _service_id; + eventID = _event_id; + table_id = 0xFF; /* not set */ + version = 0xFF; + /* contentClassification = ""; + userClassification = ""; + itemDescription = ""; + item = ""; + extendedText = "";*/ +} + +// Std-Copy +SIevent::SIevent(const SIevent &e) +{ + eventID=e.eventID; + langName=e.langName; + langText=e.langText; +// startzeit=e.startzeit; +// dauer=e.dauer; + times=e.times; + service_id = e.service_id; + original_network_id = e.original_network_id; + transport_stream_id = e.transport_stream_id; + itemDescription=e.itemDescription; + item=e.item; + langExtendedText=e.langExtendedText; + contentClassification=e.contentClassification; + userClassification=e.userClassification; + components=e.components; + ratings=e.ratings; + linkage_descs=e.linkage_descs; + running=e.running; + vps = e.vps; + table_id = e.table_id; + version = e.version; +} + +int SIevent::saveXML(FILE *file, const char *serviceName) const +{ + if(saveXML0(file)) + return 1; + if(serviceName) { + if(fprintf(file, " ")<0) + return 2; + saveStringToXMLfile(file, serviceName); + if(fprintf(file, "\n")<0) + return 3; + } + return saveXML2(file); +} + +char SIevent::getFSK() const +{ + for (SIparentalRatings::iterator it = ratings.begin(); it != ratings.end(); ++it) + { + if (it->countryCode == "DEU") + { + if ((it->rating >= 0x01) && (it->rating <= 0x0F)) + return (it->rating + 3); // 0x01 to 0x0F minimum age = rating + 3 years + else + return (it->rating == 0 ? 0 : 18); // return FSK 18 for : 0x10 to 0xFF defined by the broadcaster + } + } + if (!ratings.empty()) + { + if ((ratings.begin()->rating >= 0x01) && (ratings.begin()->rating <= 0x0F)) + return (ratings.begin()->rating + 3); + else + return (ratings.begin()->rating == 0 ? 0 : 18); + } + + return 0x00; // 0x00 undefined +} + +int SIevent::saveXML0(FILE *file) const +{ + if(fprintf(file, "\t\t\n", eventID)<0) + return 1; + return 0; +} + +int SIevent::saveXML2(FILE *file) const +{ + for (std::map::const_iterator + i = langName.begin() ; + i != langName.end() ; + i++) { + if (i->second.length()) { + fprintf(file, "\t\t\tfirst.c_str()); + saveStringToXMLfile(file, i->second.c_str()); + fprintf(file, "\"/>\n"); + } + } + for (std::map::const_iterator + i = langText.begin() ; + i != langText.end() ; + i++) { + if (i->second.length()) { + fprintf(file, "\t\t\tfirst.c_str()); + saveStringToXMLfile(file, i->second.c_str()); + fprintf(file, "\"/>\n"); + } + } + if(item.length()) { + fprintf(file, "\t\t\t\n"); + } + if(itemDescription.length()) { + fprintf(file, "\t\t\t\n"); + } + for (std::map::const_iterator + i = langExtendedText.begin() ; + i != langExtendedText.end() ; + i++) { + if (i->second.length()) { + fprintf(file, "\t\t\tfirst.c_str()); + saveStringToXMLfile(file, i->second.c_str()); + fprintf(file, "\"/>\n"); + } + } + for_each(times.begin(), times.end(), saveSItimeXML(file)); + for(unsigned i=0; i\n", contentClassification[i], userClassification[i]); + for_each(components.begin(), components.end(), saveSIcomponentXML(file)); + for_each(ratings.begin(), ratings.end(), saveSIparentalRatingXML(file)); + for_each(linkage_descs.begin(), linkage_descs.end(), saveSIlinkageXML(file)); + fprintf(file, "\t\t\n"); + return 0; +} + +std::string SIevent::getName() const +{ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + std::map::const_iterator it = langName.begin() ; + if (it != langName.end()) return it->second; + else return(""); + } else { + std::string retval; + SIlanguage::filter(langName, 1, retval); + return retval; + } +} + +void SIevent::setName(const std::string &lang, const std::string &name) +{ + std::string tmp = name; + std::replace(tmp.begin(), tmp.end(), '\n', ' '); +//printf("setName: lang %s text %s\n", lang.c_str(), name.c_str()); + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + langName[languangeOFF] = tmp; //name; + } else { + langName[lang] = tmp; //name; + } +} + +std::string SIevent::getText() const +{ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + std::map::const_iterator it = langText.begin() ; + if (it != langText.end()) return it->second; + else return(""); + } else { + std::string retval; + SIlanguage::filter(langText, 0, retval); + return retval; + } +} + +void SIevent::setText(const std::string &lang, const std::string &text) +{ +//printf("setText: lang %s text %s\n", lang.c_str(), text.c_str()); + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + langText[languangeOFF] = text; + } else { + langText[lang] = text; + } +} + +std::string SIevent::getExtendedText() const +{ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + std::map::const_iterator it = langExtendedText.begin() ; + if (it != langExtendedText.end()) return it->second; + else return(""); + } else { + std::string retval; + SIlanguage::filter(langExtendedText, 0, retval); + return retval; + } +} + +void SIevent::appendExtendedText(const std::string &lang, const std::string &text) +{ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + langExtendedText[languangeOFF] += text; + } else { + langExtendedText[lang] += text; + } +} + +void SIevent::setExtendedText(const std::string &lang, const std::string &text) +{ +//printf("setExtendedText: lang %s text %s\n", lang.c_str(), text.c_str()); + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { + langExtendedText[languangeOFF] = text; + } else { + langExtendedText[lang] = text; + } +} + +void SIevent::dump(void) const +{ + printf("Unique key: %llx\n", uniqueKey()); + if(original_network_id) + printf("Original-Network-ID: %hu\n", original_network_id); + if (service_id) + printf("Service-ID: %hu\n", service_id); + printf("Event-ID: %hu\n", eventID); + if(item.length()) + printf("Item: %s\n", item.c_str()); + if(itemDescription.length()) + printf("Item-Description: %s\n", itemDescription.c_str()); + + for (std::map::const_iterator it = langName.begin() ; + it != langName.end() ; ++it) + printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str()); + for (std::map::const_iterator it = langText.begin() ; + it != langText.end() ; ++it) + printf("Text (%s): %s\n", it->first.c_str(), it->second.c_str()); + for (std::map::const_iterator it = langExtendedText.begin() ; + it != langExtendedText.end() ; ++it) + printf("Extended-Text (%s): %s\n", it->first.c_str(), it->second.c_str()); + + if(contentClassification.length()) { + printf("Content classification:"); + for(unsigned i=0; i::const_iterator it = langName.begin() ; + it != langName.end() ; ++it) + printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str()); + for (std::map::const_iterator it = langText.begin() ; + it != langText.end() ; ++it) + printf("Text (%s): %s\n", it->first.c_str(), it->second.c_str()); + for (std::map::const_iterator it = langExtendedText.begin() ; + it != langExtendedText.end() ; ++it) + printf("Extended-Text (%s): %s\n", it->first.c_str(), it->second.c_str()); + /* + if(startzeit) + printf("Startzeit: %s", ctime(&startzeit)); + if(dauer) + printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer); + */ + for_each(times.begin(), times.end(), printSItime()); + for_each(ratings.begin(), ratings.end(), printSIparentalRating()); + for_each(linkage_descs.begin(), linkage_descs.end(), printSIlinkage()); +} +/* +// Liest n Bytes aus einem Socket per read +inline int readNbytes(int fd, char *buf, int n) +{ +int j; +for(j=0; jservice_id == serviceID) + for (SItimes::iterator t = k->times.begin(); t != k->times.end(); ++t) + if ((t->startzeit <= zeit) && (zeit <= (long)(t->startzeit+t->dauer))) { + close(fd); + return SIevent(*k); + } + } + + else { + delete[] buf; + } + + } while (time(NULL) < szeit + (long)timeoutInSeconds); + + close(fd); + return evt; +} + +void SIevents::removeOldEvents(long seconds) +{ + time_t current_time = time(NULL); + + for(SIevents::iterator it = begin(); it != end(); ) + { + // "it->times.erase(kt);": + // passing `const SItimes' as `this' argument of `void set,allocator >::erase(_Rb_tree_iterator)' discards qualifiers + + // hence we have to modify a copy + + SIevent copy_of_event(*it); + bool copy_has_changed = false; + + for (SItimes::iterator jt = copy_of_event.times.begin(); jt != copy_of_event.times.end(); ) + { + if ((jt->startzeit) + (int)(jt->dauer) < current_time - seconds) + { + copy_of_event.times.erase(jt++); + copy_has_changed = true; + } + else + ++jt; + } + if (copy_has_changed) + { + erase(it++); + + // Set has the important property that inserting a new element into a set does not + // invalidate iterators that point to existing elements. + if (copy_of_event.times.size() != 0) +#ifdef DEBUG + assert((++insert(it, copy_of_event)) == it); +#else + insert(it, copy_of_event); // it is the hint where to insert (I hope that doesn't invalidate it) +// insert(copy_of_event); // alternative method without hint +#endif + + } + else + ++it; + } +} + +// Entfernt anhand der Services alle time shifted events (ohne Text, +// mit service-id welcher im nvod steht) +// und sortiert deren Zeiten in die Events mit dem Text ein. +void SIevents::mergeAndRemoveTimeShiftedEvents(const SIservices &services) +{ + // Wir gehen alle services durch, suchen uns die services mit nvods raus + // und fuegen dann die Zeiten der Events mit der service-id eines nvods + // in das entsprechende Event mit der service-id das die nvods hat ein. + // die 'nvod-events' werden auch geloescht + +// SIevents eventsToDelete; // Hier rein kommen Events die geloescht werden sollen + for(SIservices::iterator k=services.begin(); k!=services.end(); ++k) + if(k->nvods.size()) { + // NVOD-Referenzen gefunden + // Zuerst mal das Event mit dem Text holen + iterator e; + for(e=begin(); e!=end(); ++e) + if(e->service_id == k->service_id) + break; + if(e!=end()) { + // *e == event mit dem Text + SIevent newEvent(*e); // Kopie des Events + // Jetzt die nvods druchgehen und deren Uhrzeiten in obiges Event einfuegen + for(SInvodReferences::iterator n=k->nvods.begin(); n!=k->nvods.end(); ++n) { + // Alle druchgehen und deren Events suchen + for(iterator en=begin(); en!=end(); en++) { + if(en->service_id==n->getServiceID()) { + newEvent.times.insert(en->times.begin(), en->times.end()); +// newEvent.times.insert(SItime(en->startzeit, en->dauer)); +// eventsToDelete.insert(SIevent(*en)); + } + } + } + erase(e); // Altes Event loeschen -> iterator (e) ungültig + insert(newEvent); // und das erweiterte Event wieder einfuegen + } + } + + // + // delete all events with serviceID that have a service type 0 + // + for (iterator it = begin(); it != end(); ) + { + SIservices::iterator s = services.find(SIservice(it->service_id, it->original_network_id, it->transport_stream_id)); + if ((s != services.end()) && (s->serviceTyp == 0)) + { + // Set is a Sorted Associative Container + // Erasing an element from a set also does not invalidate any iterators, + // except, of course, for iterators that actually point to the element + // that is being erased. + erase(it++); + } + else + ++it; + } +} +#endif diff --git a/src/eitd/SIevents.hpp b/src/eitd/SIevents.hpp new file mode 100644 index 000000000..679fe881f --- /dev/null +++ b/src/eitd/SIevents.hpp @@ -0,0 +1,488 @@ +#ifndef SIEVENTS_HPP +#define SIEVENTS_HPP +// +// $Id: SIevents.hpp,v 1.29 2008/08/16 19:23:18 seife Exp $ +// +// classes SIevent and SIevents (dbox-II-project) +// +// Homepage: http://dbox2.elxsi.de +// +// Copyright (C) 2001 fnbrd (fnbrd@gmx.de) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +// + +#include +#include +#include + +#include +#include "edvbstring.h" +//#include "SIutils.hpp" + +// forward references +class SIservice; +class SIservices; +class SIbouquets; + +struct eit_event { + unsigned event_id_hi : 8; + unsigned event_id_lo : 8; + unsigned start_time_hi : 8; + unsigned start_time_hi2 : 8; + unsigned start_time_mid : 8; + unsigned start_time_lo2 : 8; + unsigned start_time_lo : 8; + unsigned duration_hi : 8; + unsigned duration_mid : 8; + unsigned duration_lo : 8; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned running_status : 3; + unsigned free_CA_mode : 1; + unsigned descriptors_loop_length_hi : 4; +#else + unsigned descriptors_loop_length_hi : 4; + unsigned free_CA_mode : 1; + unsigned running_status : 3; +#endif + unsigned descriptors_loop_length_lo : 8; +} __attribute__ ((packed)) ; + + +struct descr_component_header { + unsigned descriptor_tag : 8; + unsigned descriptor_length : 8; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned reserved_future_use : 4; + unsigned stream_content : 4; +#else + unsigned stream_content : 4; + unsigned reserved_future_use : 4; +#endif + unsigned component_type : 8; + unsigned component_tag : 8; + unsigned iso_639_2_language_code_hi : 8; + unsigned iso_639_2_language_code_mid : 8; + unsigned iso_639_2_language_code_lo : 8; +} __attribute__ ((packed)) ; + +struct descr_linkage_header { + unsigned descriptor_tag : 8; + unsigned descriptor_length : 8; + unsigned transport_stream_id_hi : 8; + unsigned transport_stream_id_lo : 8; + unsigned original_network_id_hi : 8; + unsigned original_network_id_lo : 8; + unsigned service_id_hi : 8; + unsigned service_id_lo : 8; + unsigned linkage_type : 8; +} __attribute__ ((packed)) ; + +struct descr_pdc_header { + unsigned descriptor_tag : 8; + unsigned descriptor_length : 8; + unsigned pil0 : 8; + unsigned pil1 : 8; + unsigned pil2 : 8; +} __attribute__ ((packed)) ; + +class SIlinkage { +public: + SIlinkage(const struct descr_linkage_header *link) { + linkageType = link->linkage_type; + transportStreamId = (link->transport_stream_id_hi << 8) | link->transport_stream_id_lo; + originalNetworkId = (link->original_network_id_hi << 8) | link->original_network_id_lo; + serviceId = (link->service_id_hi << 8) | link->service_id_lo; + if (link->descriptor_length > sizeof(struct descr_linkage_header) - 2) + //name = std::string(((const char *)link) + sizeof(struct descr_linkage_header), link->descriptor_length - (sizeof(struct descr_linkage_header) - 2)); + name = convertDVBUTF8(((const char *)link)+sizeof(struct descr_linkage_header), link->descriptor_length-(sizeof(struct descr_linkage_header)-2), 0, 0); + } + + // Std-copy + SIlinkage(const SIlinkage &l) { + linkageType = l.linkageType; + transportStreamId = l.transportStreamId; + originalNetworkId = l.originalNetworkId; + serviceId = l.serviceId; + name = l.name; + } + + // default + SIlinkage(void) { + linkageType = 0; + transportStreamId = 0; + originalNetworkId = 0; + serviceId = 0; +// name = ; + } + + // Der Operator zum sortieren + bool operator < (const SIlinkage& l) const { + return name < l.name; + } + + void dump(void) const { + printf("Linakge Type: 0x%02hhx\n", linkageType); + if (name.length()) + printf("Name: %s\n", name.c_str()); + printf("Transport Stream Id: 0x%04hhx\n", transportStreamId); + printf("Original Network Id: 0x%04hhx\n", originalNetworkId); + printf("Service Id: 0x%04hhx\n", serviceId); + } + + int saveXML(FILE *file) const { + fprintf(file, "\t\t\t\n", transportStreamId, originalNetworkId, serviceId); +// %s, , name.c_str())<0) +// return 1; + return 0; + } + + unsigned char linkageType; // Linkage Descriptor + std::string name; // Text aus dem Linkage Descriptor + t_transport_stream_id transportStreamId; // Linkage Descriptor + t_original_network_id originalNetworkId; // Linkage Descriptor + t_service_id serviceId; // Linkage Descriptor +}; + +// Fuer for_each +struct printSIlinkage : public std::unary_function +{ + void operator() (const SIlinkage &l) { l.dump();} +}; + +// Fuer for_each +struct saveSIlinkageXML : public std::unary_function +{ + FILE *f; + saveSIlinkageXML(FILE *fi) { f=fi;} + void operator() (const SIlinkage &l) { l.saveXML(f);} +}; + +//typedef std::multiset > SIlinkage_descs; +typedef std::vector SIlinkage_descs; + +class SIcomponent { + public: + SIcomponent(const struct descr_component_header *comp) { + streamContent=comp->stream_content; + componentType=comp->component_type; + componentTag=comp->component_tag; + if(comp->descriptor_length>sizeof(struct descr_component_header)-2) + //component=std::string(((const char *)comp)+sizeof(struct descr_component_header), comp->descriptor_length-(sizeof(struct descr_component_header)-2)); + component=convertDVBUTF8(((const char *)comp)+sizeof(struct descr_component_header), comp->descriptor_length-(sizeof(struct descr_component_header)-2), 0, 0); + } + // Std-copy + SIcomponent(const SIcomponent &c) { + streamContent=c.streamContent; + componentType=c.componentType; + componentTag=c.componentTag; + component=c.component; + } + + SIcomponent(void) { + streamContent=0; + componentType=0; + componentTag=0; + } + // Der Operator zum sortieren + bool operator < (const SIcomponent& c) const { + return streamContent < c.streamContent; +// return component < c.component; + } + void dump(void) const { + if(component.length()) + printf("Component: %s\n", component.c_str()); + printf("Stream Content: 0x%02hhx\n", streamContent); + printf("Component type: 0x%02hhx\n", componentType); + printf("Component tag: 0x%02hhx\n", componentTag); + } + int saveXML(FILE *file) const { + fprintf(file, "\t\t\t\n"); +// %s +// return 1; +// saveStringToXMLfile(file, component.c_str()); +// fprintf(file, "\"/>\n"); + return 0; + } + std::string component; // Text aus dem Component Descriptor + unsigned char componentType; // Component Descriptor + unsigned char componentTag; // Component Descriptor + unsigned char streamContent; // Component Descriptor +}; + +// Fuer for_each +struct printSIcomponent : public std::unary_function +{ + void operator() (const SIcomponent &c) { c.dump();} +}; + +// Fuer for_each +struct saveSIcomponentXML : public std::unary_function +{ + FILE *f; + saveSIcomponentXML(FILE *fi) { f=fi;} + void operator() (const SIcomponent &c) { c.saveXML(f);} +}; + +typedef std::multiset > SIcomponents; + +class SIparentalRating { + public: + SIparentalRating(const std::string &cc, unsigned char rate) { + rating=rate; + countryCode=cc; + } + // Std-Copy + SIparentalRating(const SIparentalRating &r) { + rating=r.rating; + countryCode=r.countryCode; + } + // Der Operator zum sortieren + bool operator < (const SIparentalRating& c) const { + return countryCode < c.countryCode; + } + void dump(void) const { + printf("Rating: %s %hhu (+3)\n", countryCode.c_str(), rating); + } + int saveXML(FILE *file) const { + if(fprintf(file, "\t\t\t\n", countryCode.c_str(), rating)<0) + return 1; + return 0; + } + std::string countryCode; + unsigned char rating; // Bei 1-16 -> Minumim Alter = rating +3 +}; + +// Fuer for_each +struct printSIparentalRating : public std::unary_function +{ + void operator() (const SIparentalRating &r) { r.dump();} +}; + +// Fuer for_each +struct saveSIparentalRatingXML : public std::unary_function +{ + FILE *f; + saveSIparentalRatingXML(FILE *fi) { f=fi;} + void operator() (const SIparentalRating &r) { r.saveXML(f);} +}; + +typedef std::set > SIparentalRatings; + +class SItime { + public: + SItime(time_t s, unsigned d) { + startzeit=s; + dauer=d; // in Sekunden, 0 -> time shifted (cinedoms) + } + // Std-Copy + SItime(const SItime &t) { + startzeit=t.startzeit; + dauer=t.dauer; + } + // Der Operator zum sortieren + bool operator < (const SItime& t) const { + return startzeit < t.startzeit; + } + void dump(void) const { + printf("Startzeit: %s", ctime(&startzeit)); + printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer); + } + int saveXML(FILE *file) const { // saves the time + // Ist so noch nicht in Ordnung, das sollte untergliedert werden, + // da sonst evtl. time,date,duration,time,date,... auftritt + // und eine rein sequentielle Ordnung finde ich nicht ok. + /* + struct tm *zeit=localtime(&startzeit); + fprintf(file, "\t\t\t\t\t\n", zeit->tm_hour, zeit->tm_min, zeit->tm_sec); + fprintf(file, "\t\t\t\t\t%02d.%02d.%04d\n", zeit->tm_mday, zeit->tm_mon+1, zeit->tm_year+1900); + fprintf(file, "\t\t\t\t\t%u\n", dauer); + */ + fprintf(file, "\t\t\t\n") == 0) + writeTransponderFromDescriptor(dst, onid, tsid, ddp, is_sat); + } + if (strcmp(buffer, "\n") == 0) + write_xml_provend(dst, is_sat); + + while (!feof(src)) + { + fprintf(dst, buffer); + fgets(buffer, 255, src); + } + } + + fclose(src); + } + fclose(dst); + + rename(CURRENTSERVICES_TMP, CURRENTSERVICES_XML); + + return; +} + +static bool updateNetwork() +{ + t_transport_stream_id tsid; + t_original_network_id onid; + t_network_id network_id; + + int position = 0; + struct satellite_delivery_descriptor *sdd; + const char *ddp; + std::string frontendType; + + bool need_update = false; + bool needs_fix = false; + + xmlNodePtr provider; + xmlNodePtr tp; + + FILE * tmp; + + xmlDocPtr service_parser = parseXmlFile(SERVICES_XML); + + if (service_parser == NULL) + return false; + + xmlDocPtr current_parser = NULL; + xmlNodePtr current_tp = NULL; + xmlNodePtr current_provider = NULL; + + tmp = fopen(CURRENTSERVICES_XML, "r"); + if (tmp) { + fclose(tmp); + current_parser= parseXmlFile(CURRENTSERVICES_XML); + } + + int i = 0; + readLockMessaging(); + while ((i < MAX_NIDs) && (messaging_nit_nid[i] != 0) && (!messaging_zap_detected)) { + unlockMessaging(); + + network_id = messaging_nit_nid[i]; + + // go through all transpopnders currently cached by neutrino - I won't need them after this loop. They COULD be cleared. + for (MySItranspondersOrderUniqueKey::iterator s = mySItranspondersOrderUniqueKey.begin(); s != + mySItranspondersOrderUniqueKey.end(); s++) + { + readLockMessaging(); + if (messaging_zap_detected) { + unlockMessaging(); + break; + } + unlockMessaging(); + if (s->second->network_id == network_id) { + needs_fix = false; + tsid = s->second->transport_stream_id; + onid = s->second->original_network_id; + ddp = &s->second->delivery_descriptor[0]; + + //printf("Descriptor_type: %02x\n", s->second->delivery_type); + frontendType = xmlGetName(xmlDocGetRootElement(service_parser)->xmlChildrenNode); + switch (s->second->delivery_type) { + case 0x43: + if (!strcmp(frontendType.c_str(), "sat")) { + sdd = (struct satellite_delivery_descriptor *)ddp; + position = (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo; + if (!sdd->west_east_flag) + position = -position; + provider = getProvbyPosition(xmlDocGetRootElement(service_parser)->xmlChildrenNode, position); + } + else { + provider = NULL; + position = 1000; + } + break; + case 0x44: + if (!strcmp(frontendType.c_str(), "cable")) { + provider = xmlDocGetRootElement(service_parser)->xmlChildrenNode; + position = 0; + } + else { + position = 1000; + provider = NULL; + } + break; + default: + position = 1000; + provider = NULL; + break; + } + + //provider with satellite position does not exist in services.xml + if ((!provider) && (position != 1000)) { + provider = getProviderFromSatellitesXML(xmlDocGetRootElement(service_parser)->xmlChildrenNode, position); + if (provider) + needs_fix = true; //backward compatibility - add position node + } + //provider also not found in satellites.xml... + if ((!provider) && (position != 1000)) { + if (current_parser != NULL) { + provider = getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, position); + } + } + //and finally provider not found in currentservices.xml - we give up + if (!provider) { + dprintf("[sectionsd::updateNetwork] Provider not found for Transponder ONID: %04x TSID: %04x.\n", onid, + tsid); + } + else { + //we found a valid provider node + tp = findTransponderFromProv(provider->xmlChildrenNode, onid, tsid); + if (!tp) { + dprintf("[sectionsd::updateNetwork] Transponder ONID: %04x TSID: %04x not found.\n", onid, tsid); + if (current_parser != NULL) { + + switch (s->second->delivery_type) { + case 0x43: //satellite descriptor + current_provider = + getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, + position); + break; + case 0x44: //cable + current_provider = xmlDocGetRootElement(current_parser)->xmlChildrenNode; + break; + default: + break; + } + if (current_provider) + current_tp = findTransponderFromProv(current_provider->xmlChildrenNode, onid, + tsid); + } + //write the new transponder to currentservices.xml + if (!current_tp) { + updateXMLnet(provider, onid, tsid, ddp, position); + xmlFreeDoc(current_parser); + current_parser= parseXmlFile(CURRENTSERVICES_XML); + } + + } else { + dprintf("[sectionsd::updateNetwork] Transponder ONID: %04x TSID: %04x found.\n", onid, tsid); + if ( (s->second->is_actual & 7) && (needs_fix) ) { + //if(!(tmp = fopen(CURRENTSERVICES_XML, "r"))) + if (current_parser == NULL) { + dprintf("[sectionsd::updateNetwork] services.xml provider needs update\n"); + updateXMLnet(provider, onid, tsid, NULL, position); + current_parser= parseXmlFile(CURRENTSERVICES_XML); + } + else { + current_provider = + getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, + position); + if (!current_provider) { + updateXMLnet(provider, onid, tsid, NULL, position); + xmlFreeDoc(current_parser); + current_parser= parseXmlFile(CURRENTSERVICES_XML); + } + } + } + } + } + } + //sleep(10); + } + i++; + readLockMessaging(); + } + unlockMessaging(); + if (current_parser != NULL) + xmlFreeDoc(current_parser); + xmlFreeDoc(service_parser); + + return need_update; +} + +xmlNodePtr findBouquet(xmlDocPtr parser,t_bouquet_id bouquet_id) +{ + xmlNodePtr bouquet = xmlDocGetRootElement(parser)->xmlChildrenNode; + while (xmlGetNextOccurence(bouquet, "Bouquet") != NULL) { + //printf("Checking: %04x\n", xmlGetNumericAttribute(bouquet, "bouquet_id", 16)); + if (xmlGetNumericAttribute(bouquet, "bouquet_id", 16) == bouquet_id) + return bouquet; + bouquet = bouquet->xmlNextNode; + } + return NULL; +} + +static bool compareBouquet(xmlNodePtr channel, t_bouquet_id bouquet_id) +{ + MySIbouquetsOrderUniqueKey::iterator s = mySIbouquetsOrderUniqueKey.begin(); + while (s != mySIbouquetsOrderUniqueKey.end()) { + if (s->second->bouquet_id == bouquet_id) { + if (channel) { + if ( (xmlGetNumericAttribute(channel, "serviceID", 16) != s->second->service_id) || + (xmlGetNumericAttribute(channel, "tsid", 16) != s->second->transport_stream_id) || + (xmlGetNumericAttribute(channel, "onid", 16) != s->second->original_network_id) ) { + //printf("Service: %04x\n",s->second->service_id); + return true; + } + channel = channel->xmlNextNode; + } else + return true; + } + s++; + } + if ((!channel) && (s == mySIbouquetsOrderUniqueKey.end())) + return false; + else + return true; +} + +static void write_bouquet_xml_node(FILE *fd, t_bouquet_id bouquet_id) +{ + bool found = false; + + MySIbouquetsOrderUniqueKey::iterator s = mySIbouquetsOrderUniqueKey.begin(); + while ((!found) && (s != mySIbouquetsOrderUniqueKey.end())) { + if ((s->second->bouquet_id == bouquet_id) && (s->second->bouquetName.length() != 0)) + found = true; + else + s++; + } + if (found) + fprintf(fd, "\t\n") != 0) && (strcmp(buffer, prov_str_neu) != 0) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - if (strcmp(buffer, prov_str_neu) != 0) - fprintf(dst, prov_str_neu); - if (ddp != NULL) { - while( (!feof(src)) && (strcmp(buffer, "\n") != 0) && - (strcmp(buffer, "\t\n") != 0) && (strcmp(buffer, "\t\n")) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - //if (strcmp(buffer, "\n") == 0) - writeTransponderFromDescriptor(dst, onid, tsid, ddp, is_sat); - } - if (strcmp(buffer, "\n") == 0) - write_xml_provend(dst, is_sat); - - while (!feof(src)) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - } - - fclose(src); - } - fclose(dst); - - rename(CURRENTSERVICES_TMP, CURRENTSERVICES_XML); - - return; -} - -static bool updateNetwork() -{ - t_transport_stream_id tsid; - t_original_network_id onid; - t_network_id network_id; - - int position = 0; - struct satellite_delivery_descriptor *sdd; - const char *ddp; - std::string frontendType; - - bool need_update = false; - bool needs_fix = false; - - xmlNodePtr provider; - xmlNodePtr tp; - - FILE * tmp; - - xmlDocPtr service_parser = parseXmlFile(SERVICES_XML); - - if (service_parser == NULL) - return false; - - xmlDocPtr current_parser = NULL; - xmlNodePtr current_tp = NULL; - xmlNodePtr current_provider = NULL; - - tmp = fopen(CURRENTSERVICES_XML, "r"); - if (tmp) { - fclose(tmp); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - - int i = 0; - readLockMessaging(); - while ((i < MAX_NIDs) && (messaging_nit_nid[i] != 0) && (!messaging_zap_detected)) { - unlockMessaging(); - - network_id = messaging_nit_nid[i]; - - // go through all transpopnders currently cached by neutrino - I won't need them after this loop. They COULD be cleared. - for (MySItranspondersOrderUniqueKey::iterator s = mySItranspondersOrderUniqueKey.begin(); s != - mySItranspondersOrderUniqueKey.end(); s++) - { - readLockMessaging(); - if (messaging_zap_detected) { - unlockMessaging(); - break; - } - unlockMessaging(); - if (s->second->network_id == network_id) { - needs_fix = false; - tsid = s->second->transport_stream_id; - onid = s->second->original_network_id; - ddp = &s->second->delivery_descriptor[0]; - - //printf("Descriptor_type: %02x\n", s->second->delivery_type); - frontendType = xmlGetName(xmlDocGetRootElement(service_parser)->xmlChildrenNode); - switch (s->second->delivery_type) { - case 0x43: - if (!strcmp(frontendType.c_str(), "sat")) { - sdd = (struct satellite_delivery_descriptor *)ddp; - position = (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo; - if (!sdd->west_east_flag) - position = -position; - provider = getProvbyPosition(xmlDocGetRootElement(service_parser)->xmlChildrenNode, position); - } - else { - provider = NULL; - position = 1000; - } - break; - case 0x44: - if (!strcmp(frontendType.c_str(), "cable")) { - provider = xmlDocGetRootElement(service_parser)->xmlChildrenNode; - position = 0; - } - else { - position = 1000; - provider = NULL; - } - break; - default: - position = 1000; - provider = NULL; - break; - } - - //provider with satellite position does not exist in services.xml - if ((!provider) && (position != 1000)) { - provider = getProviderFromSatellitesXML(xmlDocGetRootElement(service_parser)->xmlChildrenNode, position); - if (provider) - needs_fix = true; //backward compatibility - add position node - } - //provider also not found in satellites.xml... - if ((!provider) && (position != 1000)) { - if (current_parser != NULL) { - provider = getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, position); - } - } - //and finally provider not found in currentservices.xml - we give up - if (!provider) { - dprintf("[sectionsd::updateNetwork] Provider not found for Transponder ONID: %04x TSID: %04x.\n", onid, - tsid); - } - else { - //we found a valid provider node - tp = findTransponderFromProv(provider->xmlChildrenNode, onid, tsid); - if (!tp) { - dprintf("[sectionsd::updateNetwork] Transponder ONID: %04x TSID: %04x not found.\n", onid, tsid); - if (current_parser != NULL) { - - switch (s->second->delivery_type) { - case 0x43: //satellite descriptor - current_provider = - getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, - position); - break; - case 0x44: //cable - current_provider = xmlDocGetRootElement(current_parser)->xmlChildrenNode; - break; - default: - break; - } - if (current_provider) - current_tp = findTransponderFromProv(current_provider->xmlChildrenNode, onid, - tsid); - } - //write the new transponder to currentservices.xml - if (!current_tp) { - updateXMLnet(provider, onid, tsid, ddp, position); - xmlFreeDoc(current_parser); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - - } else { - dprintf("[sectionsd::updateNetwork] Transponder ONID: %04x TSID: %04x found.\n", onid, tsid); - if ( (s->second->is_actual & 7) && (needs_fix) ) { - //if(!(tmp = fopen(CURRENTSERVICES_XML, "r"))) - if (current_parser == NULL) { - dprintf("[sectionsd::updateNetwork] services.xml provider needs update\n"); - updateXMLnet(provider, onid, tsid, NULL, position); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - else { - current_provider = - getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, - position); - if (!current_provider) { - updateXMLnet(provider, onid, tsid, NULL, position); - xmlFreeDoc(current_parser); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - } - } - } - } - } - //sleep(10); - } - i++; - readLockMessaging(); - } - unlockMessaging(); - if (current_parser != NULL) - xmlFreeDoc(current_parser); - xmlFreeDoc(service_parser); - - return need_update; -} - -xmlNodePtr findBouquet(xmlDocPtr parser,t_bouquet_id bouquet_id) -{ - xmlNodePtr bouquet = xmlDocGetRootElement(parser)->xmlChildrenNode; - while (xmlGetNextOccurence(bouquet, "Bouquet") != NULL) { - //printf("Checking: %04x\n", xmlGetNumericAttribute(bouquet, "bouquet_id", 16)); - if (xmlGetNumericAttribute(bouquet, "bouquet_id", 16) == bouquet_id) - return bouquet; - bouquet = bouquet->xmlNextNode; - } - return NULL; -} - -static bool compareBouquet(xmlNodePtr channel, t_bouquet_id bouquet_id) -{ - MySIbouquetsOrderUniqueKey::iterator s = mySIbouquetsOrderUniqueKey.begin(); - while (s != mySIbouquetsOrderUniqueKey.end()) { - if (s->second->bouquet_id == bouquet_id) { - if (channel) { - if ( (xmlGetNumericAttribute(channel, "serviceID", 16) != s->second->service_id) || - (xmlGetNumericAttribute(channel, "tsid", 16) != s->second->transport_stream_id) || - (xmlGetNumericAttribute(channel, "onid", 16) != s->second->original_network_id) ) { - //printf("Service: %04x\n",s->second->service_id); - return true; - } - channel = channel->xmlNextNode; - } else - return true; - } - s++; - } - if ((!channel) && (s == mySIbouquetsOrderUniqueKey.end())) - return false; - else - return true; -} - -static void write_bouquet_xml_node(FILE *fd, t_bouquet_id bouquet_id) -{ - bool found = false; - - MySIbouquetsOrderUniqueKey::iterator s = mySIbouquetsOrderUniqueKey.begin(); - while ((!found) && (s != mySIbouquetsOrderUniqueKey.end())) { - if ((s->second->bouquet_id == bouquet_id) && (s->second->bouquetName.length() != 0)) - found = true; - else - s++; - } - if (found) - fprintf(fd, "\t