From: atx23 Date: Wed, 17 Dec 2008 14:08:35 +0000 (+0000) Subject: Changed API of DVBDemuxSectionHandle ! X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=34199e3d9e56891d51d497fc2367d14258fa0c37;p=senf.git Changed API of DVBDemuxSectionHandle ! Changed API of DVBFrontendHandle ! Added DVBSocketController git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1020 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Socket/Protocols/DVB/DVBConfigParser.cc b/Socket/Protocols/DVB/DVBConfigParser.cc new file mode 100644 index 0000000..aa45acb --- /dev/null +++ b/Socket/Protocols/DVB/DVBConfigParser.cc @@ -0,0 +1,257 @@ +#include "DVBConfigParser.hh" +#include +#include "../../../Utils/Exception.hh" + +using namespace std; +#define prefix_ + +senf::DVBConfigParser::DVBParams const senf::DVBConfigParser::params; + +prefix_ senf::DVBConfigParser::DVBParams::DVBParams() +{ + + boost::assign::insert(inversion) + ( "INVERSION_OFF", INVERSION_OFF ) + ( "INVERSION_ON", INVERSION_ON ) + ( "INVERSION_AUTO", INVERSION_AUTO ); + boost::assign::insert(bandwidth) + ( "BANDWIDTH_6_MHZ", BANDWIDTH_6_MHZ) + ( "BANDWIDTH_7_MHZ", BANDWIDTH_7_MHZ) + ( "BANDWIDTH_8_MHZ", BANDWIDTH_8_MHZ); + boost::assign::insert(code_rate) + ( "FEC_1_2", FEC_1_2) + ( "FEC_2_3", FEC_2_3) + ( "FEC_3_4", FEC_3_4) + ( "FEC_4_5", FEC_4_5) + ( "FEC_5_6", FEC_5_6) + ( "FEC_6_7", FEC_6_7) + ( "FEC_7_8", FEC_7_8) + ( "FEC_8_9", FEC_8_9) + ( "FEC_AUTO", FEC_AUTO) + ( "FEC_NONE", FEC_NONE); + boost::assign::insert(guard_interval) + ( "GUARD_INTERVAL_1_16", GUARD_INTERVAL_1_16) + ( "GUARD_INTERVAL_1_32", GUARD_INTERVAL_1_32) + ( "GUARD_INTERVAL_1_4", GUARD_INTERVAL_1_4) + ( "GUARD_INTERVAL_1_8", GUARD_INTERVAL_1_8); + boost::assign::insert(hierarchy) + ( "HIERARCHY_1", HIERARCHY_1) + ( "HIERARCHY_2", HIERARCHY_2) + ( "HIERARCHY_4", HIERARCHY_4) + ( "HIERARCHY_NONE", HIERARCHY_NONE); + boost::assign::insert(modulation) + ( "QPSK", QPSK) + ( "QAM_128", QAM_128) + ( "QAM_16", QAM_16) + ( "QAM_256", QAM_256) + ( "QAM_32", QAM_32) + ( "QAM_64", QAM_64); + boost::assign::insert(transmit_mode) + ( "TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K) + ( "TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K); +} + +senf::DVBConfigParser::DVBConfigParser(fe_type_t type_, const string & configFilePath_) : + type(type_), + configFile() +{ + initConfigFile(configFilePath_); +} + +senf::DVBConfigParser::~DVBConfigParser() +{ + configFile.close(); +} +prefix_ void senf::DVBConfigParser::initConfigFile(string configFilePath_){ + if (configFilePath_.size() == 0) { + if ( !(::getenv ("HOME")) ) + SENF_THROW_SYSTEM_EXCEPTION("$HOME not set! You need it to use default configfile."); + string configPath(::getenv ("HOME")); + switch(type) { + case FE_QPSK : + configPath += string("/.szap/channels.conf"); + break; + case FE_QAM : + configPath += string("/.czap/channels.conf"); + break; + case FE_OFDM : + configPath += string("/.tzap/channels.conf"); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } + configFilePath_ = configPath; + } + configFile.open( configFilePath_.c_str(), ios_base::in); + if(configFile.bad()) + SENF_THROW_SYSTEM_EXCEPTION("Could not read configfile: ") << configFilePath_ << "."; +} +prefix_ string senf::DVBConfigParser::getConfigLine(string channel) +{ + string configLine; + size_t pos; + transform(channel.begin(), channel.end(), channel.begin(), ::toupper); + if(configFile.bad()) + SENF_THROW_SYSTEM_EXCEPTION("Could not read file."); + while (configFile.good()){ + getline( configFile, configLine ); + transform(configLine.begin(), configLine.end(), configLine.begin(), ::toupper); + pos = configLine.find(channel); + + if(pos != string::npos && pos == 0){ // only first matching number should be interpreted as channel number + configFile.seekg(0); + return configLine; // Line found! + } + } + SENF_THROW_SYSTEM_EXCEPTION("Channel \"")<< channel << "\" not found!"; + return channel; +} + +prefix_ dvb_frontend_parameters senf::DVBConfigParser::getFrontendParam(string configLine){ + struct dvb_frontend_parameters frontend; + transform(configLine.begin(), configLine.end(), configLine.begin(), ::toupper); + boost::char_separator sep(":"); + tokenizer tokens(configLine, sep); + switch (type) { + case FE_QPSK: + frontend = getFrontendParamDVB_S(tokens); + break; + case FE_QAM: + frontend = getFrontendParamDVB_C(tokens); + break; + case FE_OFDM: + frontend = getFrontendParamDVB_T(tokens); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } + return frontend; +} + +prefix_ dvb_frontend_parameters senf::DVBConfigParser::getFrontendParamDVB_T( const tokenizer & tokens){ + + struct dvb_frontend_parameters frontend; + istringstream isst; + int number; + enum { p_Frequency=1, p_Inversion, p_Bandwidth, p_hp_code_rate, p_lp_code_rate, p_Mudualtion, p_Transmission, p_guard, p_hierarchy}; + vector words( tokens.begin(), tokens.end() ); + + ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters)); + + /*if(words.size() < 10) + SENF_THROW_SYSTEM_EXCEPTION("Too few arguments! There must be at least 10, but there are only: ") << words.size();*/ + + isst.str(words[p_Frequency]); + isst >> number; + if(isst.fail()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse frequency"); + frontend.frequency = number; + + if( params.inversion.find(words[p_Inversion]) == params.inversion.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse inversion"); + frontend.inversion = params.inversion.find(words[p_Inversion])->second; + + if( params.bandwidth.find(words[p_Bandwidth]) == params.bandwidth.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse bandwidth"); + frontend.u.ofdm.bandwidth = params.bandwidth.find(words[p_Bandwidth])->second; + + if( params.code_rate.find(words[p_hp_code_rate]) == params.code_rate.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse high priority stream code rate"); + frontend.u.ofdm.code_rate_HP = params.code_rate.find(words[p_hp_code_rate])->second; + + if( params.code_rate.find(words[p_lp_code_rate]) == params.code_rate.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse low priority stream code rate"); + frontend.u.ofdm.code_rate_LP = params.code_rate.find(words[p_lp_code_rate])->second; + + if( params.modulation.find(words[p_Mudualtion]) == params.modulation.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse modulation"); + frontend.u.ofdm.constellation = params.modulation.find(words[p_Mudualtion])->second; + + if( params.transmit_mode.find(words[p_Transmission]) == params.transmit_mode.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse transmission mode"); + frontend.u.ofdm.transmission_mode = params.transmit_mode.find(words[p_Transmission])->second; + + if( params.guard_interval.find(words[p_guard]) == params.guard_interval.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse guard interval"); + frontend.u.ofdm.guard_interval = params.guard_interval.find(words[p_guard])->second; + + if( params.hierarchy.find(words[p_hierarchy]) == params.hierarchy.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse hierarchy"); + frontend.u.ofdm.hierarchy_information = params.hierarchy.find(words[p_hierarchy])->second; + + return frontend; +} + +prefix_ dvb_frontend_parameters senf::DVBConfigParser::getFrontendParamDVB_S( const tokenizer & tokens){ + struct dvb_frontend_parameters frontend; + istringstream isst; + int number; + enum { p_Frequency=1, p_Inversion, p_Symbole, p_code_rate}; + vector words( tokens.begin(), tokens.end() ) ; + + ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters)); + + if(words.size() < 5) + SENF_THROW_SYSTEM_EXCEPTION("Too few arguments! There must be at least 5, but there are only: ") << words.size(); + + isst.str(words[p_Frequency]); + isst >> number; + if (isst.fail()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse frequency"); + frontend.frequency = number; + + if (params.inversion.find(words[p_Inversion]) == params.inversion.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse inversion"); + frontend.inversion = params.inversion.find(words[p_Inversion])->second; + + isst.str(words[p_Symbole]); + isst >> number; + if (isst.fail()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse symbole rate"); + frontend.u.qpsk.symbol_rate = number; + + if (params.code_rate.find(words[p_code_rate]) == params.code_rate.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse code rate"); + frontend.u.qpsk.fec_inner = params.code_rate.find(words[p_code_rate])->second; + + return frontend; +} + +prefix_ dvb_frontend_parameters senf::DVBConfigParser::getFrontendParamDVB_C( const tokenizer & tokens){ + struct dvb_frontend_parameters frontend; + istringstream isst; + int number; + enum { p_Frequency=1, p_Inversion, p_Symbole, p_code_rate, p_modulation}; + vector words( ++tokens.begin(), tokens.end() ) ; + + ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters)); + + if(words.size() < 6) + SENF_THROW_SYSTEM_EXCEPTION("Too few arguments! There must be at least 6, but there are only: ") << words.size(); + + isst.str(words[p_Frequency]); + isst >> number; + if (isst.fail()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse frequency"); + frontend.frequency = number; + + if (params.inversion.find(words[p_Inversion]) == params.inversion.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse inversion"); + frontend.inversion = params.inversion.find(words[p_Inversion])->second; + + isst.str(words[p_Symbole]); + isst >> number; + if (isst.fail()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse symbole rate"); + frontend.u.qam.symbol_rate = number; + + if (params.code_rate.find(words[p_code_rate]) == params.code_rate.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse code rate"); + frontend.u.qam.fec_inner = params.code_rate.find(words[p_code_rate])->second; + + if (params.modulation.find(words[p_modulation]) == params.modulation.end()) + SENF_THROW_SYSTEM_EXCEPTION("Cant parse modulation"); + frontend.u.qam.modulation = params.modulation.find(words[p_modulation])->second; + + return frontend; +} diff --git a/Socket/Protocols/DVB/DVBConfigParser.hh b/Socket/Protocols/DVB/DVBConfigParser.hh new file mode 100644 index 0000000..1fa99f6 --- /dev/null +++ b/Socket/Protocols/DVB/DVBConfigParser.hh @@ -0,0 +1,73 @@ +// $Id: DVBConfigParser.hh 965 2008-11-18 16:04:20Z g0dil $ +// +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Anton Gillert +// +// 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., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief DVBDemuxHandles public header */ + +#ifndef DVBCONFIGPARSER_HH_ +#define DVBCONFIGPARSER_HH_ + +#include +#include +#include +#include +#include +#include +#include +#include +namespace senf { +class DVBConfigParser +{ + struct DVBParams { + std::map inversion; + std::map bandwidth; + std::map code_rate; + std::map guard_interval; + std::map hierarchy; + std::map modulation; + std::map transmit_mode; + DVBParams(); }; + static const DVBParams params; + typedef boost::tokenizer > tokenizer; + +public: + DVBConfigParser(fe_type_t type_, const std::string & configFilePath = ""); + ~DVBConfigParser(); + + std::string getConfigLine(std::string channel); + + dvb_frontend_parameters parseCMDInput(std::string input); + dvb_frontend_parameters getFrontendParam(std::string configLine); + +private: + + fe_type_t type; + std::ifstream configFile; + void initConfigFile(std::string _configFilePath); + + dvb_frontend_parameters getFrontendParamDVB_T( const tokenizer & tokens); + dvb_frontend_parameters getFrontendParamDVB_C( const tokenizer & tokens); + dvb_frontend_parameters getFrontendParamDVB_S( const tokenizer & tokens); + +}; +} +#endif /*DVBCONFIGPARSER_H_*/ diff --git a/Socket/Protocols/DVB/DVBDemuxHandles.cc b/Socket/Protocols/DVB/DVBDemuxHandles.cc index d5343e3..3a66a06 100644 --- a/Socket/Protocols/DVB/DVBDemuxHandles.cc +++ b/Socket/Protocols/DVB/DVBDemuxHandles.cc @@ -58,11 +58,20 @@ prefix_ unsigned senf::DVBDemuxSectionSocketProtocol::available() return 4096; } -prefix_ void senf::DVBDemuxSectionSocketProtocol::setSectionFilter(struct dmx_sct_filter_params *filter) +prefix_ void senf::DVBDemuxSectionSocketProtocol::setSectionFilter(unsigned short int pid, unsigned int timeout, unsigned int flags, unsigned char filter, unsigned char mask, unsigned char mode) const { - if (::ioctl(fd(), DMX_SET_FILTER, filter) < 0) - SENF_THROW_SYSTEM_EXCEPTION("Could not set section filter of DVB adapter."); + struct dmx_sct_filter_params sec_filter; + ::memset(&sec_filter, 0, sizeof(struct dmx_sct_filter_params)); + + sec_filter.pid = pid; + sec_filter.filter.filter[0] = filter; + sec_filter.filter.mask[0] = mask; + sec_filter.filter.mode[0] = mode; + sec_filter.flags = flags; + + if (::ioctl(fd(), DMX_SET_FILTER, filter) < 0) + SENF_THROW_SYSTEM_EXCEPTION("Could not set section filter of DVB adapter."); } // ---------------------------------------------------------------- diff --git a/Socket/Protocols/DVB/DVBDemuxHandles.hh b/Socket/Protocols/DVB/DVBDemuxHandles.hh index d146830..dd24d7b 100644 --- a/Socket/Protocols/DVB/DVBDemuxHandles.hh +++ b/Socket/Protocols/DVB/DVBDemuxHandles.hh @@ -75,7 +75,12 @@ namespace senf { ///@} - void setSectionFilter(struct dmx_sct_filter_params *filter) const; + void setSectionFilter(unsigned short int pid, + unsigned int timeout, + unsigned int flags, + unsigned char filter, + unsigned char mask, + unsigned char mode) const; }; typedef ProtocolClientSocketHandle DVBDemuxSectionHandle; diff --git a/Socket/Protocols/DVB/DVBFrontendHandle.cc b/Socket/Protocols/DVB/DVBFrontendHandle.cc index 20c8caa..3b01f22 100644 --- a/Socket/Protocols/DVB/DVBFrontendHandle.cc +++ b/Socket/Protocols/DVB/DVBFrontendHandle.cc @@ -29,12 +29,8 @@ // Custom includes #include #include -#include -#include #include "../../../Utils/Exception.hh" -#include -#include -#include +#include //#include "DVBFrontendHandle.mpp" @@ -45,20 +41,14 @@ // senf::DVBFrontendHandle using namespace std; -prefix_ void senf::DVBFrontendSocketProtocol::init_client(unsigned const short adapter,unsigned const short device) +prefix_ void senf::DVBFrontendSocketProtocol::init_client(unsigned short adapter, unsigned short device, int flags) + const { string devFrontend = str( boost::format("/dev/dvb/adapter%d/frontend%d") % adapter % device); - int f = open(devFrontend.c_str(), O_RDONLY | O_NONBLOCK); + int f = open(devFrontend.c_str(), flags); if (f < 0) SENF_THROW_SYSTEM_EXCEPTION("")<< "Could not open frontend device of DVB adapter " << devFrontend << "."; fd(f); - - // later there will be a decision between waitTune and asyncTune - cb2_X_Tune = boost::bind(&senf::DVBFrontendSocketProtocol::waitTune, this, _1); - - struct dvb_frontend_info info; - ioctl(fd(), FE_GET_INFO, &info); - } prefix_ unsigned senf::DVBFrontendSocketProtocol::available() @@ -73,28 +63,12 @@ prefix_ bool senf::DVBFrontendSocketProtocol::eof() return false; } -prefix_ struct dvb_frontend_event senf::DVBFrontendSocketProtocol::tune(const struct dvb_frontend_parameters & frontend){ - return cb2_X_Tune(frontend); -} -prefix_ struct dvb_frontend_event senf::DVBFrontendSocketProtocol::waitTune(const struct dvb_frontend_parameters & frontend) { - // tuning - if ( ::ioctl(fd(), FE_SET_FRONTEND, &frontend) ) - SENF_THROW_SYSTEM_EXCEPTION("") << "Could not write on frontend device. Socket should initialized with write permissions."; - // getting event - struct dvb_frontend_event ev; - ::ioctl(fd(), FE_GET_EVENT, &ev); - - return ev; -} - -prefix_ struct dvb_frontend_event senf::DVBFrontendSocketProtocol::asyncTune(const struct dvb_frontend_parameters & frontend){ +prefix_ void senf::DVBFrontendSocketProtocol::tune(const struct dvb_frontend_parameters & frontend) + const +{ // tuning - if ( ::ioctl(fd(), FE_SET_FRONTEND, &frontend) ) - SENF_THROW_SYSTEM_EXCEPTION("") << "Could not write on frontend device. Socket should initialized with write permissions."; - - // do something async here - struct dvb_frontend_event ev; - return ev; + if (::ioctl(fd(), FE_SET_FRONTEND, &frontend) ) + SENF_THROW_SYSTEM_EXCEPTION("") << "ioctl FE_SET_FRONTEND failed. Socket should initialized with r/w permissions.";; } prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_T(unsigned int frequency, @@ -107,10 +81,14 @@ prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_T(unsigned int frequency, fe_guard_interval_t guard_interval, fe_hierarchy_t hierarchy_information ) + const { struct dvb_ofdm_parameters ofdm; /* DVB-T Parameters */ struct dvb_frontend_parameters frontend; + ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters)); + ::memset(&ofdm, 0, sizeof(struct dvb_ofdm_parameters)); + ofdm.bandwidth = bandwidth; ofdm.code_rate_HP = code_rate_HP; ofdm.code_rate_LP = code_rate_LP; @@ -128,11 +106,16 @@ prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_T(unsigned int frequency, prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, /* symbol rate in Symbols per second */ - fe_code_rate_t fec_inner) /* forward error correction (see above) */ + fe_code_rate_t fec_inner /* forward error correction (see above) */ + ) + const { struct dvb_qpsk_parameters qpsk; /* DVB-S Parameters*/ struct dvb_frontend_parameters frontend; + ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters)); + ::memset(&qpsk, 0, sizeof(struct dvb_qpsk_parameters)); + qpsk.symbol_rate = symbole_rate; qpsk.fec_inner = fec_inner; @@ -147,11 +130,16 @@ prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_C(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbol_rate, fe_code_rate_t fec_inner, - fe_modulation_t modulation) + fe_modulation_t modulation + ) +const { struct dvb_qam_parameters qam; /* DVB-C Parameters*/ struct dvb_frontend_parameters frontend; + ::memset(&frontend, 0, sizeof(struct dvb_frontend_parameters)); + ::memset(&qam, 0, sizeof(struct dvb_qam_parameters)); + qam.symbol_rate = symbol_rate; qam.fec_inner = fec_inner; qam.modulation = modulation; @@ -163,152 +151,66 @@ prefix_ void senf::DVBFrontendSocketProtocol::tuneDVB_C(unsigned int frequency, tune(frontend); } -prefix_ struct dvb_frontend_info senf::DVBFrontendSocketProtocol::getInfo() +prefix_ void senf::DVBFrontendSocketProtocol::setNonBlock(bool on) const{ + if(on) + ::fcntl(fd(), F_SETFL, ::fcntl(fd(), F_GETFL) | O_NONBLOCK); + else + ::fcntl(fd(), F_SETFL, ::fcntl(fd(), F_GETFL) & ~O_NONBLOCK); + +} +prefix_ dvb_frontend_info senf::DVBFrontendSocketProtocol::getInfo() const { struct dvb_frontend_info info; + ::memset(&info, 0, sizeof(struct dvb_frontend_info)); + if( ::ioctl(fd(), FE_GET_INFO, &info) ) { SENF_THROW_SYSTEM_EXCEPTION("") << "Could not read on fildescriptor."; } return info; } -prefix_ struct dvb_frontend_parameters senf::DVBFrontendSocketProtocol::getFrontendParam() const { - struct dvb_frontend_parameters frontend; - - if ( ::ioctl(fd(), FE_GET_FRONTEND, &frontend) ) - SENF_THROW_SYSTEM_EXCEPTION("") << "Could not read from frontend device, read-only access to the device is sufficient."; - return frontend; -} - -prefix_ void senf::DVBFrontendSocketProtocol::setFrequency(unsigned int frequency){ - - struct dvb_frontend_parameters frontend = getFrontendParam(); - - frontend.frequency = frequency; - - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setInversion(fe_spectral_inversion_t inversion){ - - struct dvb_frontend_parameters frontend = getFrontendParam(); - - frontend.inversion = inversion; - - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setCodeRate(fe_code_rate_t fec_inner){ - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - if( type == FE_QPSK ){ /* DVB-S */ - frontend.u.qpsk.fec_inner = fec_inner; - } - if( type == FE_QAM ){ /* DVB-C */ - frontend.u.qam.fec_inner = fec_inner; - } - if( type == FE_OFDM ){ /* DVB-T ATTENTION sets high and low priority code rate!*/ - frontend.u.ofdm.code_rate_HP = fec_inner; - frontend.u.ofdm.code_rate_LP = fec_inner; +prefix_ dvb_frontend_parameters senf::DVBFrontendSocketProtocol::getFrontendParam() const { + struct dvb_frontend_parameters frontend_; + + ::memset(&frontend_, 0, sizeof(struct dvb_frontend_parameters)); + + if(::ioctl(fd(), FE_GET_FRONTEND, &frontend_)) { + switch(errno) { + case EBADF: + SENF_THROW_SYSTEM_EXCEPTION("fd is not a valid open file descriptor."); + break; + case EFAULT: + SENF_THROW_SYSTEM_EXCEPTION( "frontend_ points to invalid address." ); + break; + case EINVAL: + SENF_THROW_SYSTEM_EXCEPTION( "Maximum supported symbol rate reached. This call may not be implemented by kernel driver!" ); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Errno: ") << errno; + } } - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setSymbolRate(unsigned int symbol_rate){ - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (! ( type == FE_QPSK || type == FE_QAM ) ) - SENF_THROW_SYSTEM_EXCEPTION("Symbole rate can only be set for DVB-S or DVB-C devices."); - if( type == FE_QPSK ) /* DVB-S */ - frontend.u.qpsk.symbol_rate = symbol_rate; - - if( type == FE_QAM ) /* DVB-C */ - frontend.u.qam.symbol_rate = symbol_rate; - - tune(frontend); -} -prefix_ void senf::DVBFrontendSocketProtocol::setModulation(fe_modulation_t modulation){ - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (! ( type == FE_OFDM || type == FE_QAM ) ) - SENF_THROW_SYSTEM_EXCEPTION("Symbole rate can only be set for DVB-T or DVB-C devices."); - if( type == FE_QAM ) /* DVB-C */ - frontend.u.qam.modulation = modulation; - if( type == FE_OFDM ) /* DVB-T */ - frontend.u.ofdm.constellation = modulation; - - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setBandwidth(fe_bandwidth_t bandwidth) { - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (type != FE_OFDM) - SENF_THROW_SYSTEM_EXCEPTION("") << "Bandwidth can only be set for DVB-T devices."; - - frontend.u.ofdm.bandwidth = bandwidth; - - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setHighPriorityCodeRate(fe_code_rate_t code_rate_HP) { - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (type != FE_OFDM) - SENF_THROW_SYSTEM_EXCEPTION("") << "High priority bandwidth can only be set for DVB-T devices."; - - frontend.u.ofdm.code_rate_HP = code_rate_HP; - - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setLowPriorityCodeRate(fe_code_rate_t code_rate_LP) { - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (type != FE_OFDM) - SENF_THROW_SYSTEM_EXCEPTION("") << "Low priority bandwidth can only be set for DVB-T devices."; - - frontend.u.ofdm.code_rate_LP = code_rate_LP; - - tune(frontend); + return frontend_; } -prefix_ void senf::DVBFrontendSocketProtocol::setGuardInterval(fe_guard_interval_t guard_interval) { - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (type != FE_OFDM) - SENF_THROW_SYSTEM_EXCEPTION("") << "Guard interval can only be set for DVB-T devices."; - - frontend.u.ofdm.guard_interval = guard_interval; - - tune(frontend); -} - -prefix_ void senf::DVBFrontendSocketProtocol::setHierarchyInformation(fe_hierarchy_t hierarchy_information) { - - fe_type_t type = getInfo().type; - struct dvb_frontend_parameters frontend = getFrontendParam(); - - if (type != FE_OFDM) - SENF_THROW_SYSTEM_EXCEPTION("") << "Hierachy information can only be set for DVB-T devices."; - - frontend.u.ofdm.hierarchy_information = hierarchy_information; - - tune(frontend); +prefix_ dvb_frontend_event senf::DVBFrontendSocketProtocol::getEvent() const{ + struct dvb_frontend_event ev ; + + ::memset(&ev, 0, sizeof(struct dvb_frontend_event)); + + if(::ioctl(fd(), FE_GET_EVENT, &ev)) { + switch(errno) { + case EBADF: + SENF_THROW_SYSTEM_EXCEPTION("Could not read from frontend device, read-only access to the device is sufficient."); + break; + case EWOULDBLOCK: + SENF_THROW_SYSTEM_EXCEPTION( "No event pending and device is in nonblocking mode." ); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Errno: ") << errno; + } + } + return ev; } prefix_ int16_t senf::DVBFrontendSocketProtocol::signalStrength() @@ -338,6 +240,26 @@ prefix_ uint32_t senf::DVBFrontendSocketProtocol::bitErrorRate() return ber; } +prefix_ uint32_t senf::DVBFrontendSocketProtocol::uncorrectedBlocks() + const +{ + uint32_t uncorrected_blocks; + if (::ioctl(fd(), FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) < 0) + SENF_THROW_SYSTEM_EXCEPTION("Could not get bit error rate of DVB adapter."); + return uncorrected_blocks; +} + + +prefix_ fe_status_t senf::DVBFrontendSocketProtocol::status() + const +{ + fe_status_t status; + if (::ioctl(fd(), FE_READ_STATUS, &status) < 0) + SENF_THROW_SYSTEM_EXCEPTION("Could not get bit error rate of DVB adapter."); + return status; +} + + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ //#include "DVBFrontendHandle.mpp" diff --git a/Socket/Protocols/DVB/DVBFrontendHandle.hh b/Socket/Protocols/DVB/DVBFrontendHandle.hh index 74c58d5..f128f64 100644 --- a/Socket/Protocols/DVB/DVBFrontendHandle.hh +++ b/Socket/Protocols/DVB/DVBFrontendHandle.hh @@ -36,11 +36,7 @@ #include "../../../Socket/ReadWritePolicy.hh" #include "../../../Socket/ProtocolClientSocketHandle.hh" #include "../../../Socket/SocketProtocol.hh" -#include -#include - - - +#include //#include "DVBFrontendHandle.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -61,33 +57,39 @@ namespace senf { /** \brief SocketProtocol for the dvb frontend device The DVB frontend device controls the tuner and DVB demodulator hardware. + ATTENTION! + Some calls are not supported by real life drivers, known issues: + + Cinergy T² getParameter is not supported + Cinergy T² in getEvent fe_status_t will be set but dvb_frontend_parameters will be stay untouched + Cinergy DT XS bitErrorRate is not supported + + This dues to the lack of driver implementation. There could be restrictions also for other DVB devices! */ class DVBFrontendSocketProtocol : public ConcreteSocketProtocol { private: - dvb_frontend_event tune(const struct dvb_frontend_parameters & frontend); - struct dvb_frontend_event waitTune(const struct dvb_frontend_parameters & frontend); - struct dvb_frontend_event asyncTune(const struct dvb_frontend_parameters & frontend); - boost::function cb2_X_Tune; + void tune(const struct dvb_frontend_parameters & frontend) const; public: /////////////////////////////////////////////////////////////////////////// // internal interface ///\name Constructors ///@{ - void init_client(unsigned const short adapter = 0, unsigned const short device = 0); + void init_client(unsigned short adapter = 0, unsigned short device = 0, int flags = (O_RDWR | O_NONBLOCK) ) const; ///< Opens the specified frontend device in read-only mode. /**< \note This member is implicitly called from the ProtocolClientSocketHandle::ProtocolClientSocketHandle() constructor */ ///@} - - void tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate); - ///< Tunes a DVB-C device - /**< Tunes a DVB-C device. Needs full configuration */ + void setNonBlock(bool on = true) const; + + void tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate) const; + ///< Tunes a DVB-S device + /**< Tunes a DVB-S device. Needs full configuration */ void tuneDVB_T(unsigned int frequency, fe_spectral_inversion_t inversion, fe_bandwidth_t bandwidth, @@ -97,54 +99,27 @@ namespace senf { fe_transmit_mode_t transmission_mode, fe_guard_interval_t guard_interval, fe_hierarchy_t hierarchy_information - ); ///< Tunes a DVB-T device + ) const; ///< Tunes a DVB-T device /**< Tunes a DVB-T device. Needs full configuration */ void tuneDVB_C(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbol_rate, fe_code_rate_t fec_inner, - fe_modulation_t modulation); + fe_modulation_t modulation + ) const; ///< Tunes a DVB-C device /**< Tunes a DVB-C device. Needs full configuration */ - struct dvb_frontend_info getInfo() const; ///< Returns information struct. + dvb_frontend_info getInfo() const; ///< Returns information struct. /**< Returns information struct, which contains information about the device which is associated with the current frontend.*/ struct dvb_frontend_parameters getFrontendParam() const; ///< Returns dvb_frontend_parameters struct. /**< Returns dvb_frontend_parameters struct, which contains the actual configuration of the device.*/ - void setFrequency(unsigned int frequency); ///< Sets frequency - /**< Sets frequency. This can be done for all device types.*/ - void setInversion(fe_spectral_inversion_t inversion); ///< Sets inversion - /**< Sets inversion. This can be done for all device types.*/ - void setCodeRate(fe_code_rate_t fec_inner); ///< Sets code rate - /**< Sets code rate. This can be done for all device types. Attention - for DVB-T devices the high and low priority stream code rate will be set to - the given value.*/ - void setSymbolRate(unsigned int symbol_rate); ///< Sets symbol rate - /**< Sets symbol rate. This can only be done for DVB-S or DVB-C devices. - Other attempts will throw an exception.*/ - void setModulation(fe_modulation_t modulation); ///< Sets modulation - /**< Sets modulation. This can only be done for DVB-T or DVB-C devices. - Other attempts will throw an exception.*/ - void setBandwidth(fe_bandwidth_t bandwidth); ///< Sets bandwidth - /**< Sets bandwidth. This can only be done for DVB-T devices. - Other attempts will throw an exception.*/ - void setHighPriorityCodeRate(fe_code_rate_t code_rate_HP); ///< Sets high priority stream code rate - /**< Sets high priority stream code rate. This can only be done for DVB-T devices. - Other attempts will throw an exception.*/ - void setLowPriorityCodeRate(fe_code_rate_t code_rate_LP); ///< Sets low priority stream code rate - /**< Sets low priority stream code rate. This can only be done for DVB-T devices. - Other attempts will throw an exception.*/ - void setGuardInterval(fe_guard_interval_t guard_interval); ///< Sets guard interval - /**< Sets guard interval. This can only be done for DVB-T devices. - Other attempts will throw an exception.*/ - void setHierarchyInformation(fe_hierarchy_t hierarchy_information); ///< Sets hierarchy information - /**< Sets hierarchy information. This can only be done for DVB-T devices. - Other attempts will throw an exception.*/ - - ///\name Abstract Interface Implementation ///@{ + + dvb_frontend_event getEvent() const; + unsigned available() const; ///< Returns always 0 /**< Returns always 0, since the DVB frontend @@ -170,6 +145,20 @@ namespace senf { /**< Returns the bit error rate for the signal currently received/demodulated by the front-end. For this method, read-only access to the device is sufficient. */ + uint32_t uncorrectedBlocks() const; ///< Returns the number of uncorrected blocks + /**< Returns the number of uncorrected blocks + * detected by the device driver during its lifetime. + * For meaningful measurements, the increment in block + * count during a specific time interval should be calculated. + * For this command, read-only access to the device is sufficient. + * Note that the counter will wrap to zero after its maximum count + * has been reached.*/ + + fe_status_t status() const; ///< This ioctl call returns status information about the front-end. + /**< This ioctl call returns status information about the + * front-end. This call only requires read-only access + * to the device.*/ + }; typedef ProtocolClientSocketHandle DVBFrontendHandle; diff --git a/Socket/Protocols/DVB/DVBSocketController.cc b/Socket/Protocols/DVB/DVBSocketController.cc new file mode 100644 index 0000000..1242ff2 --- /dev/null +++ b/Socket/Protocols/DVB/DVBSocketController.cc @@ -0,0 +1,405 @@ +#include "../../../Utils/Exception.hh" +#include "../../../Utils/Logger/Logger.hh" +#include <../../../Utils/membind.hh> + +#include "DVBSocketController.hh" +#include +using namespace std; +#define prefix_ + + + +senf::DVBSocketController::DVBSocketController(DVBFrontendHandle frontendHandle_, DVBDemuxSectionHandle sectionHandle_ , const Callback & cb_) : + dir( this ), + frontendHandle( frontendHandle_ ), + sectionHandle( sectionHandle_ ), + type( frontendHandle.protocol().getInfo().type ), + parser( type ), + cb( cb_ ), + event( "senf::DVBSocketController::readEvent", senf::membind(&DVBSocketController::readEvent, this), frontendHandle, senf::scheduler::FdEvent::EV_PRIO, false ) +{ + initConsole(); +} + +prefix_ senf::DVBSocketController::~DVBSocketController() +{ +} +prefix_ string senf::DVBSocketController::tuneToCMD(const string & configLine, const string & mode){ + struct dvb_frontend_parameters frontend; + + + // no valid configline, so it will be treaten like a channel name + if (configLine.find(":")==string::npos){ + if (mode.c_str()[0]=='a'){ + tuneTo(configLine); + return "async readConfFile"; + } + else{ + tuneTo_sync(configLine); + return "sync readConfFile"; + } + + } + // add psydo name to complete configline syntax + frontend = parser.getFrontendParam("foo:"+configLine); + + if (mode.c_str()[0]=='a'){ + switch (type) { + case FE_QPSK: + tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner); + break; + case FE_QAM: + tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation); + break; + case FE_OFDM: + tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } + return "async get directly"; + } + else { + switch (type) { + case FE_QPSK: if (mode.c_str()[0]=='a') + tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner); + break; + case FE_QAM: + tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation); + break; + case FE_OFDM: + tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } + return "sync get directly"; + } +} + +prefix_ void senf::DVBSocketController::tuneTo(const string & channel) +{ + struct dvb_frontend_parameters frontend; + + string configLine = parser.getConfigLine(channel); + + SENF_LOG((senf::log::MESSAGE) ("async: configline found: " << channel) ); + frontend = parser.getFrontendParam(configLine); + switch (type) { + case FE_QPSK: + tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner); + break; + case FE_QAM: + tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation); + break; + case FE_OFDM: + tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } +} + +prefix_ void senf::DVBSocketController::tuneDVB_T(unsigned int frequency, + fe_spectral_inversion_t inversion, + fe_bandwidth_t bandwidth, + fe_code_rate_t code_rate_HP, /* high priority stream code rate */ + fe_code_rate_t code_rate_LP, /* low priority stream code rate */ + fe_modulation_t constellation, /* modulation type (see above) */ + fe_transmit_mode_t transmission_mode, + fe_guard_interval_t guard_interval, + fe_hierarchy_t hierarchy_information + ) +{ + if(type != FE_OFDM) + SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-T Card!"; + event.enable(); + frontendHandle.protocol().setNonBlock(); + frontendHandle.protocol().tuneDVB_T(frequency, + inversion, + bandwidth, + code_rate_HP, + code_rate_LP, + constellation, + transmission_mode, + guard_interval, + hierarchy_information); +} + +prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate){ + if(type != FE_QPSK) + SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-S Card!"; + event.enable(); + frontendHandle.protocol().setNonBlock(); + frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate); +} + +prefix_ void senf::DVBSocketController::tuneDVB_C(unsigned int frequency, + fe_spectral_inversion_t inversion, + unsigned int symbol_rate, + fe_code_rate_t fec_inner, + fe_modulation_t modulation + ) +{ + if(type != FE_QAM) + SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-C Card!"; + + event.enable(); + frontendHandle.protocol().setNonBlock(); + + frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation); +} + +prefix_ dvb_frontend_event senf::DVBSocketController::tuneTo_sync(const string & channel) +{ + struct dvb_frontend_parameters frontend; + dvb_frontend_event ev; + string configLine = parser.getConfigLine(channel); + + SENF_LOG((senf::log::MESSAGE) ("sync: configline found: " << channel) ); + frontend = parser.getFrontendParam(configLine); + switch (type) { + case FE_QPSK: + ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner); + break; + case FE_QAM: + ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation); + break; + case FE_OFDM: + ev = tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth, frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP, frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode, frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information); + break; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } + return ev; +} + +prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_T_sync(unsigned int frequency, + fe_spectral_inversion_t inversion, + fe_bandwidth_t bandwidth, + fe_code_rate_t code_rate_HP, /* high priority stream code rate */ + fe_code_rate_t code_rate_LP, /* low priority stream code rate */ + fe_modulation_t constellation, /* modulation type (see above) */ + fe_transmit_mode_t transmission_mode, + fe_guard_interval_t guard_interval, + fe_hierarchy_t hierarchy_information + ) +{ + if(type != FE_OFDM) + SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-T Card!"; + event.disable(); + frontendHandle.protocol().setNonBlock(false); + + frontendHandle.protocol().tuneDVB_T(frequency, + inversion, + bandwidth, + code_rate_HP, + code_rate_LP, + constellation, + transmission_mode, + guard_interval, + hierarchy_information); + + if(!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2))) + SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!"); + + return frontendHandle.protocol().getEvent(); +} + +prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_S_sync(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate){ + if(type != FE_QPSK) + SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-S Card!"; + event.disable(); + frontendHandle.protocol().setNonBlock(false); + frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate); + + if(!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2))) + SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!"); + return frontendHandle.protocol().getEvent(); +} + +prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_C_sync(unsigned int frequency, + fe_spectral_inversion_t inversion, + unsigned int symbol_rate, + fe_code_rate_t fec_inner, + fe_modulation_t modulation + ) +{ + if(type != FE_QAM) + SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-C Card!"; + + event.disable(); + frontendHandle.protocol().setNonBlock(false); + frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation); + if(!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2))) + SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!"); + + return frontendHandle.protocol().getEvent(); +} + + +prefix_ string senf::DVBSocketController::getTypeString(){ + switch (type) { + case FE_QPSK: + return "DVB-S"; + case FE_QAM: + return "DVB-C"; + case FE_OFDM: + return "DVB-T"; + default: + SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card."); + } + +} +prefix_ unsigned int senf::DVBSocketController::bitErrorRate(){ + return frontendHandle.protocol().bitErrorRate(); +} + +prefix_ unsigned int senf::DVBSocketController::signalToNoiseRatio(){ + return frontendHandle.protocol().signalNoiseRatio(); +} + +prefix_ unsigned int senf::DVBSocketController::signalStrength(){ + return frontendHandle.protocol().signalStrength(); +} + +prefix_ string senf::DVBSocketController::getTuneInfo(const string & conf){ + const char* cConf = conf.c_str(); + stringstream info; + + fe_status_t status; + uint16_t snr, signal; + uint32_t ber, uncorrected_blocks; + status = frontendHandle.protocol().status(); + snr = frontendHandle.protocol().signalNoiseRatio(); + signal = frontendHandle.protocol().signalStrength(); + ber = frontendHandle.protocol().bitErrorRate(); + uncorrected_blocks = frontendHandle.protocol().uncorrectedBlocks(); + + info << hex; + + for(unsigned int i = 0; i < conf.size(); ++i){ + switch(cConf[i]){ + case 'S' : + info << " | signal " << signal; + break; + case 's' : + info << " | snr " << snr; + break; + case 'b' : + info << " | ber " << ber; + break; + case 'u' : + info << " | unc " << uncorrected_blocks; + break; + case 'f' : + info << " | status: " << status2String(status); + break; + default: + break; + } + } + return info.str(); +} +prefix_ string senf::DVBSocketController::status2String(fe_status_t status){ + string s(""); + if (status & FE_HAS_LOCK) + return s += "|HAS LOCK"; + if (status & FE_HAS_CARRIER) + s += "|HAS CARRIER"; + if (status & FE_HAS_VITERBI) + s += "|HAS VITERBI"; + if (status & FE_HAS_SYNC) + s += "|HAS SYNC"; + if (status & FE_HAS_SIGNAL) + s += "|HAS SIGNAL"; + if (status & FE_TIMEDOUT) + s += "|TIMED OUT"; + if (status & FE_REINIT) + s += "|REINIT"; + + return s; +} + +prefix_ void senf::DVBSocketController::setSectionFilter(unsigned short int pid, + unsigned char filter, + unsigned int flags, + unsigned char mask, + unsigned char mode, + unsigned int timeout) +{ + sectionHandle.protocol().setSectionFilter(pid, timeout, flags, filter, mask, mode); + +} + +prefix_ void senf::DVBSocketController::setBufferSize(unsigned long size) +{ + sectionHandle.protocol().setBufferSize(size); +} + +prefix_ void senf::DVBSocketController::startFiltering() +{ + sectionHandle.protocol().startFiltering(); +} + +prefix_ void senf::DVBSocketController::stopFiltering() +{ + sectionHandle.protocol().stopFiltering(); +} + + +prefix_ fe_type_t senf::DVBSocketController::getType(){ + return type; +} + +prefix_ void senf::DVBSocketController::readEvent(int event){ + cb(frontendHandle.protocol().getEvent()); +} + +prefix_ void senf::DVBSocketController::initConsole(){ + // binding functions to console + namespace kw = senf::console::kw; + dir.doc("DVB Controller"); + + dir.add("type", &DVBSocketController::getTypeString) + .doc("Shows actual type of card DVB-{T, S, C}"); + + dir.add("info", &DVBSocketController::getTuneInfo) + .doc("Returns a string which shows actual tuning status.\n\ + \"S\" prints signal strength (in hex)\n\ + \"s\" prints singal to noise ration (in hex)\n\ + \"b\" prints bit error rate (in hex)\n\ + \"u\" prints uncorrected blocks (in hex)\n\ + \"f\" prints readable overal status e.g. \"Has Lock\"\n\n\ + These characters can be used to form the output. Be aware, some\n\ + features may not be supported be your current driver implementation\n\ + and could end in throwing an exception!") + .arg("conf", "Ssbuf", kw::default_value = "Ssbuf"); + + dir.add("tuneTo", &DVBSocketController::tuneToCMD) + .doc("tunes to channel listet in the configfile.") + .arg("channel", "channel to tune") + .arg("mode", "mode \"sync\" or \"async\"", kw::default_value = "async"); + + dir.add("buffersize", &DVBSocketController::setBufferSize) + .doc("Set the size of the circular buffer used for filtered data.") + .arg("size", "in byte"); + + dir.add("start", &DVBSocketController::startFiltering) + .doc("Starts filtering"); + + dir.add("stop", &DVBSocketController::setBufferSize) + .doc("Stops filtering"); + + dir.add("filter", &DVBSocketController::setSectionFilter) + .arg("pid", "pid to filter") + .arg("filter", "filter", kw::default_value = 62) + .arg("flags", "or-able: DMX_CHECK_CRC(0x01), DMX_ONESHOT(0x02), DMX_IMMEDIATE_START(0x04), DMX_KERNEL_CLIENT(0x8000)", kw::default_value = DMX_IMMEDIATE_START | DMX_CHECK_CRC) + .arg("mask", "mask", kw::default_value = 0xff) + .arg("mode", "mode", kw::default_value = 0) + .arg("timeout", "timeout", kw::default_value = 0) + .doc("Sets parameters for section filter."); + + dir.add("stop", &DVBSocketController::setBufferSize) + .doc("Stops filtering"); +} diff --git a/Socket/Protocols/DVB/DVBSocketController.hh b/Socket/Protocols/DVB/DVBSocketController.hh new file mode 100644 index 0000000..12e018a --- /dev/null +++ b/Socket/Protocols/DVB/DVBSocketController.hh @@ -0,0 +1,112 @@ +#ifndef DVBSOCKETCONTROLLER_HH_ +#define DVBSOCKETCONTROLLER_HH_ + +#include "DVBFrontendHandle.hh" +#include "DVBDemuxHandles.hh" +// Custom includes +#include +#include +#include +#include "DVBConfigParser.hh" +#include +namespace senf { + std::string status2String(fe_status_t status); +class DVBSocketController : boost::noncopyable +{ +public: + senf::console::ScopedDirectory dir; + + typedef boost::function Callback; + + DVBSocketController(DVBFrontendHandle frontendHandle_ = DVBFrontendHandle(0,0), DVBDemuxSectionHandle sectionHandle_ = DVBDemuxSectionHandle(0,0), const Callback & cb = NULL); + ~DVBSocketController(); + + std::string tuneToCMD( const std::string & channel, const std::string & mode = "async"); + + void tuneTo(const std::string & channel); + + void tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate); + ///< Tunes a DVB-S device + /**< Tunes a DVB-S device. Needs full configuration */ + void tuneDVB_T(unsigned int frequency, + fe_spectral_inversion_t inversion, fe_bandwidth_t bandwidth, + fe_code_rate_t code_rate_HP, /* high priority stream code rate */ + fe_code_rate_t code_rate_LP, /* low priority stream code rate */ + fe_modulation_t constellation, /* modulation type (see above) */ + fe_transmit_mode_t transmission_mode, + fe_guard_interval_t guard_interval, + fe_hierarchy_t hierarchy_information); ///< Tunes a DVB-T device + /**< Tunes a DVB-T device. Needs full configuration */ + void tuneDVB_C(unsigned int frequency, + fe_spectral_inversion_t inversion, unsigned int symbol_rate, + fe_code_rate_t fec_inner, fe_modulation_t modulation); + + dvb_frontend_event tuneTo_sync( const std::string & channel ); + + dvb_frontend_event tuneDVB_S_sync(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate); + ///< Tunes a DVB-S device + /**< Tunes a DVB-S device. Needs full configuration */ + dvb_frontend_event tuneDVB_T_sync(unsigned int frequency, + fe_spectral_inversion_t inversion, fe_bandwidth_t bandwidth, + fe_code_rate_t code_rate_HP, /* high priority stream code rate */ + fe_code_rate_t code_rate_LP, /* low priority stream code rate */ + fe_modulation_t constellation, /* modulation type (see above) */ + fe_transmit_mode_t transmission_mode, + fe_guard_interval_t guard_interval, + fe_hierarchy_t hierarsourcechy_information); ///< Tunes a DVB-T device + /**< Tunes a DVB-T device. Needs full configuration */ + dvb_frontend_event tuneDVB_C_sync(unsigned int frequency, + fe_spectral_inversion_t inversion, unsigned int symbol_rate, + fe_code_rate_t fec_inner, fe_modulation_t modulation); + + fe_type_t getType(); + + std::string getTypeString(); + + std::string status2String(fe_status_t status); + unsigned int bitErrorRate(); + unsigned int signalToNoiseRatio(); + unsigned int signalStrength(); + + void setSectionFilter(unsigned short int pid, + unsigned char filter = 62, + unsigned int flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC, + unsigned char mask = 0xff, + unsigned char mode = 0, + unsigned int timeout = 0); + + void setBufferSize(unsigned long size); + ///< set the size of the circular buffer used for filtered data. + /**< The default size is two maximum sized sections, i.e. if this + function is not called a buffer size of 2 * 4096 bytes will + be used. + \param[in] size Size of circular buffer. */ + + void startFiltering(); + + void stopFiltering(); + + std::string getTuneInfo(const std::string & conf ="Ssbuf"); ///< Returns a string which shows actual tuning status + /**< Returns a string which shows actual tuning status. + "S" prints signal strength (in hex) + "s" prints singal to noise ration (in hex) + "b" prints bit error rate (in hex) + "u" prints uncorrected blocks (in hex) + "f" prints readable overal status e.g. "Has Lock" + These characters can be used to form the output. Be aware, some + features may not be supported be your current driver implementation and + could end in throwing an exception!*/ +private: + DVBFrontendHandle frontendHandle; + senf::DVBDemuxSectionHandle sectionHandle; + fe_type_t type; + DVBConfigParser parser; + Callback cb; + senf::scheduler::FdEvent event; + + void readEvent(int i); + void initConsole(); +}; + +} +#endif /*DVBSOCKETCONTROLLER_HH_*/