wrong paremeter in DVBDemuxHandles::setSectionFiltler iocall
[senf.git] / Socket / Protocols / DVB / DVBSocketController.cc
1 #include "../../../Utils/Exception.hh"
2 #include "../../../Utils/Logger/Logger.hh"
3 #include <../../../Utils/membind.hh>
4
5 #include "DVBSocketController.hh"
6 #include <sstream>
7 using namespace std;
8 #define prefix_
9
10
11
12 senf::DVBSocketController::DVBSocketController(DVBFrontendHandle frontendHandle_, DVBDemuxSectionHandle sectionHandle_ , const Callback & cb_) :
13     dir( this ),
14     frontendHandle( frontendHandle_ ),
15     sectionHandle( sectionHandle_ ),
16     type( frontendHandle.protocol().getInfo().type ),
17     parser( type ),
18     cb( cb_ ),
19     event( "senf::DVBSocketController::readEvent", senf::membind(&DVBSocketController::readEvent, this), frontendHandle, senf::scheduler::FdEvent::EV_PRIO, false )
20 {
21     initConsole();
22 }
23
24 prefix_ senf::DVBSocketController::~DVBSocketController()
25 {
26 }
27 prefix_ string senf::DVBSocketController::tuneToCMD(const string & configLine, const string & mode){
28     struct dvb_frontend_parameters frontend;
29     
30   
31     // no valid configline, so it will be treaten like a channel name
32     if (configLine.find(":")==string::npos){
33         if (mode.c_str()[0]=='a'){
34             tuneTo(configLine);
35             return "async readConfFile";
36         }
37         else{
38             tuneTo_sync(configLine);
39             return "sync readConfFile";
40         }
41         
42     }
43     // add psydo name to complete configline syntax
44     frontend = parser.getFrontendParam("foo:"+configLine);
45     
46     if (mode.c_str()[0]=='a'){
47         switch (type) {
48             case FE_QPSK:
49                 tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
50                 break;
51             case FE_QAM:
52                 tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
53                 break;
54             case FE_OFDM:
55                 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);
56                 break;
57             default:
58                 SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
59         }
60         return "async get directly";
61     }
62     else {
63         switch (type) {
64             case FE_QPSK: if (mode.c_str()[0]=='a')
65                 tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
66                 break;
67             case FE_QAM:
68                 tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
69                 break;
70             case FE_OFDM:
71                 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);
72                 break;
73             default:
74                 SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
75         }
76         return "sync get directly";
77     }
78 }
79
80 prefix_ void senf::DVBSocketController::tuneTo(const string & channel)
81 {
82     struct dvb_frontend_parameters frontend;
83    
84     string configLine = parser.getConfigLine(channel);
85     
86     frontend = parser.getFrontendParam(configLine);
87     switch (type) {
88         case FE_QPSK:
89             tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
90             break;
91         case FE_QAM:
92             tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
93             break;
94         case FE_OFDM:
95             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);
96             break;
97         default:
98             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
99     }    
100 }
101
102 prefix_ void senf::DVBSocketController::tuneDVB_T(unsigned int frequency, 
103                 fe_spectral_inversion_t inversion,
104                 fe_bandwidth_t bandwidth, 
105                 fe_code_rate_t code_rate_HP, /* high priority stream code rate */
106                 fe_code_rate_t code_rate_LP, /* low priority stream code rate */
107                 fe_modulation_t constellation, /* modulation type (see above) */
108                 fe_transmit_mode_t transmission_mode, 
109                 fe_guard_interval_t guard_interval,
110                 fe_hierarchy_t hierarchy_information
111                 )
112 {
113     if(type != FE_OFDM)
114         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-T Card!";
115     event.enable();
116     frontendHandle.protocol().setNonBlock();
117     frontendHandle.protocol().tuneDVB_T(frequency, 
118                 inversion, 
119                 bandwidth, 
120                 code_rate_HP, 
121                 code_rate_LP, 
122                 constellation, 
123                 transmission_mode, 
124                 guard_interval, 
125                 hierarchy_information);
126 }
127
128 prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency, fe_spectral_inversion_t inversion, unsigned int symbole_rate, fe_code_rate_t code_rate){
129     if(type != FE_QPSK)
130         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-S Card!";
131     event.enable();
132     frontendHandle.protocol().setNonBlock();
133     frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
134 }
135
136 prefix_ void senf::DVBSocketController::tuneDVB_C(unsigned int frequency, 
137                 fe_spectral_inversion_t inversion,
138                 unsigned int symbol_rate,
139                 fe_code_rate_t fec_inner,
140                 fe_modulation_t modulation
141                 )
142 {   
143     if(type != FE_QAM)
144         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-C Card!";
145     
146     event.enable();
147     frontendHandle.protocol().setNonBlock();
148     
149     frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
150 }
151
152 prefix_ dvb_frontend_event senf::DVBSocketController::tuneTo_sync(const string & channel)
153 {
154     struct dvb_frontend_parameters frontend;
155     dvb_frontend_event ev;
156     string configLine = parser.getConfigLine(channel);
157     
158     frontend = parser.getFrontendParam(configLine);
159     switch (type) {
160         case FE_QPSK:
161             ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
162             break;
163         case FE_QAM:
164             ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate, frontend.u.qam.fec_inner, frontend.u.qam.modulation);
165             break;
166         case FE_OFDM:
167             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);
168             break;
169         default:
170             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
171     }
172     return ev;
173 }
174
175 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_T_sync(unsigned int frequency, 
176                 fe_spectral_inversion_t inversion,
177                 fe_bandwidth_t bandwidth, 
178                 fe_code_rate_t code_rate_HP, /* high priority stream code rate */
179                 fe_code_rate_t code_rate_LP, /* low priority stream code rate */
180                 fe_modulation_t constellation, /* modulation type (see above) */
181                 fe_transmit_mode_t transmission_mode, 
182                 fe_guard_interval_t guard_interval,
183                 fe_hierarchy_t hierarchy_information
184                 )
185 {
186     if(type != FE_OFDM)
187         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-T Card!";
188     event.disable();
189     frontendHandle.protocol().setNonBlock(false);
190     
191     frontendHandle.protocol().tuneDVB_T(frequency, 
192             inversion, 
193             bandwidth, 
194             code_rate_HP, 
195             code_rate_LP, 
196             constellation, 
197             transmission_mode, 
198             guard_interval, 
199             hierarchy_information);
200     
201     if(!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
202         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
203     
204     return frontendHandle.protocol().getEvent();
205 }
206
207 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){
208     if(type != FE_QPSK)
209         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-S Card!";
210     event.disable();
211     frontendHandle.protocol().setNonBlock(false);
212     frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
213     
214     if(!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
215         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
216     return frontendHandle.protocol().getEvent();
217 }
218
219 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_C_sync(unsigned int frequency, 
220                 fe_spectral_inversion_t inversion,
221                 unsigned int symbol_rate,
222                 fe_code_rate_t fec_inner,
223                 fe_modulation_t modulation
224                 )
225 {   
226     if(type != FE_QAM)
227         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ") << getTypeString() << " for this operation you need a DVB-C Card!";
228     
229     event.disable();
230     frontendHandle.protocol().setNonBlock(false);
231     frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
232     if(!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
233         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
234
235     return frontendHandle.protocol().getEvent();
236 }
237
238
239 prefix_ string senf::DVBSocketController::getTypeString(){
240     switch (type) {
241         case FE_QPSK:
242             return "DVB-S";
243         case FE_QAM:
244             return "DVB-C";
245         case FE_OFDM:
246             return "DVB-T";
247         default:
248             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
249     }
250     
251 }
252 prefix_ unsigned int senf::DVBSocketController::bitErrorRate(){ 
253     return frontendHandle.protocol().bitErrorRate();
254 }
255
256 prefix_ unsigned int senf::DVBSocketController::signalToNoiseRatio(){ 
257     return frontendHandle.protocol().signalNoiseRatio();
258 }
259
260 prefix_ unsigned int senf::DVBSocketController::signalStrength(){ 
261     return frontendHandle.protocol().signalStrength();
262 }
263
264 prefix_ string senf::DVBSocketController::getTuneInfo(const string & conf){
265     const char* cConf = conf.c_str();
266     stringstream info;
267     
268     fe_status_t status;
269     uint16_t snr, signal;
270     uint32_t ber, uncorrected_blocks;
271     status = frontendHandle.protocol().status();
272     snr = frontendHandle.protocol().signalNoiseRatio();
273     signal = frontendHandle.protocol().signalStrength();
274     ber = frontendHandle.protocol().bitErrorRate();
275     uncorrected_blocks = frontendHandle.protocol().uncorrectedBlocks();
276     
277     info << hex;
278     
279     for(unsigned int i = 0; i < conf.size(); ++i){
280         switch(cConf[i]){
281             case 'S' :
282                 info << " | signal " << signal;
283                 break;
284             case 's' : 
285                 info << " | snr " << snr;
286                 break;
287             case 'b' :
288                 info << " | ber " << ber;
289                 break;
290             case 'u' :
291                 info << " | unc " << uncorrected_blocks;
292                 break;
293             case 'f' :
294                 info << " | status: " << status2String(status);
295                 break;
296             default:
297                 break;
298         }
299     }
300     return info.str();
301 }
302 prefix_ string senf::DVBSocketController::status2String(fe_status_t status){
303    string s("");
304     if (status & FE_HAS_LOCK)
305         return s += "|HAS LOCK"; 
306     if (status & FE_HAS_CARRIER)
307         s += "|HAS CARRIER";
308     if (status & FE_HAS_VITERBI)
309         s += "|HAS VITERBI";
310     if (status & FE_HAS_SYNC)
311         s += "|HAS SYNC";
312     if (status & FE_HAS_SIGNAL)
313         s += "|HAS SIGNAL";
314     if (status & FE_TIMEDOUT)
315         s += "|TIMED OUT";
316     if (status & FE_REINIT)
317         s += "|REINIT";
318
319     return s;
320 }
321
322 prefix_ void senf::DVBSocketController::setSectionFilter(unsigned short int pid, 
323         unsigned char filter,
324         unsigned int flags, 
325         unsigned char mask, 
326         unsigned char mode,
327         unsigned int timeout)
328 {
329     sectionHandle.protocol().setSectionFilter(pid, timeout, flags, filter, mask, mode);
330     
331 }
332
333 prefix_ void senf::DVBSocketController::setBufferSize(unsigned long size)
334 {
335     sectionHandle.protocol().setBufferSize(size);
336 }
337
338 prefix_ void senf::DVBSocketController::startFiltering()
339 {
340     sectionHandle.protocol().startFiltering();
341 }
342
343 prefix_ void senf::DVBSocketController::stopFiltering()
344 {
345     sectionHandle.protocol().stopFiltering();
346 }
347
348
349 prefix_ fe_type_t senf::DVBSocketController::getType(){
350     return type;
351 }
352
353 prefix_ void senf::DVBSocketController::readEvent(int event){
354     cb(frontendHandle.protocol().getEvent());
355 }
356
357 prefix_ void senf::DVBSocketController::initConsole(){
358     // binding functions to console
359     namespace kw = senf::console::kw;
360     dir.doc("DVB Controller");
361     
362     dir.add("type", &DVBSocketController::getTypeString)
363     .doc("Shows actual type of card DVB-{T, S, C}");
364     
365     dir.add("info", &DVBSocketController::getTuneInfo)
366     .doc("Returns a string which shows actual tuning status.\n\
367             \"S\" prints signal strength (in hex)\n\
368             \"s\" prints singal to noise ration (in hex)\n\
369             \"b\" prints bit error rate (in hex)\n\
370             \"u\" prints uncorrected blocks (in hex)\n\
371             \"f\" prints readable overal status e.g. \"Has Lock\"\n\n\
372             These characters can be used to form the output. Be aware, some\n\
373             features may not be supported be your current driver implementation\n\
374             and could end in throwing an exception!")
375     .arg("conf", "Ssbuf", kw::default_value = "Ssbuf");
376     
377     dir.add("tuneTo", &DVBSocketController::tuneToCMD)
378         .doc("tunes to channel listet in the configfile.")
379         .arg("channel", "channel to tune")
380         .arg("mode", "mode \"sync\" or \"async\"", kw::default_value = "async");
381     
382     dir.add("buffersize", &DVBSocketController::setBufferSize)
383         .doc("Set the size of the circular buffer used for filtered data.")
384         .arg("size", "in byte");
385     
386     dir.add("start", &DVBSocketController::startFiltering)
387         .doc("Starts filtering");
388         
389     dir.add("stop", &DVBSocketController::setBufferSize)
390         .doc("Stops filtering");
391     
392     dir.add("filter", &DVBSocketController::setSectionFilter)
393         .arg("pid", "pid to filter")
394         .arg("filter", "filter", kw::default_value = 62)
395         .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)
396         .arg("mask", "mask", kw::default_value = 0xff)
397         .arg("mode", "mode", kw::default_value = 0)
398         .arg("timeout", "timeout", kw::default_value = 0)
399         .doc("Sets parameters for section filter.");
400        
401     dir.add("stop", &DVBSocketController::setBufferSize)
402             .doc("Stops filtering");
403 }