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