Fix documentation build under maverick (doxygen 1.7.1)
[senf.git] / senf / 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 DVBSocketControlle-r 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 #include <senf/Utils/Console/ParsedCommand.hh>
34 #include <boost/shared_ptr.hpp>
35 #include "DVBProtocolWrapper.hh"
36
37 #define prefix_
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39
40 unsigned int senf::DVBSocketController::controllerNr(0);
41
42 senf::DVBSocketController::DVBSocketController(DVBFrontendHandle frontendHandle_,
43                                                const Callback & cb_)
44     : dir( this ),
45       frontendHandle( frontendHandle_ ),
46       type( frontendHandle.protocol().getInfo().type ),
47       parser( type ),
48       cb( cb_ ),
49       sectionNr(1),
50       pesNr(1),
51       event( "senf::DVBSocketController::readEvent",
52              senf::membind(&DVBSocketController::readEvent, this), frontendHandle,
53              senf::scheduler::FdEvent::EV_PRIO, false )
54 {
55     initConsole();
56 }
57
58 prefix_ senf::DVBSocketController::~DVBSocketController()
59 {}
60
61 prefix_ senf::DVBDemuxSectionHandle
62 senf::DVBSocketController::createDVBDemuxSectionHandle(int adapternumber, int demuxnumber,
63                                                        bool addToConsole)
64 {
65     DVBDemuxSectionHandle sectionHandle(adapternumber, demuxnumber);
66     if (addToConsole)
67         this->addToConsole(sectionHandle);
68     return sectionHandle;
69
70 }
71
72 prefix_ senf::DVBDemuxPESHandle
73 senf::DVBSocketController::createDVBDemuxPESHandle(int adapternumber, int demuxnumber,
74                                                    bool addToConsole)
75 {
76     DVBDemuxPESHandle pesHandle(adapternumber, demuxnumber);
77     if (addToConsole)
78         this->addToConsole(pesHandle);
79     return pesHandle;
80
81 }
82
83 prefix_ void senf::DVBSocketController::addToConsole(senf::DVBDemuxSectionHandle sh)
84 {
85     boost::shared_ptr<DVBSectionProtocolWrapper> wrap(new DVBSectionProtocolWrapper(sh));
86     sh.protocol().addWrapper(wrap);
87     dir.node().add("section" + senf::str(sectionNr), wrap->dir);
88     sectionNr++;
89 }
90
91 prefix_ void senf::DVBSocketController::addToConsole(senf::DVBDemuxPESHandle sh)
92 {
93     boost::shared_ptr<DVBPESProtocolWrapper> wrap(new DVBPESProtocolWrapper(sh));
94     sh.protocol().addWrapper(wrap);
95     dir.node().add("pes"+ senf::str(pesNr), wrap->dir);
96     pesNr++;
97 }
98
99 prefix_ void senf::DVBSocketController::tuneToCMD(std::string const & input, std::string const & mode)
100 {
101     struct dvb_frontend_parameters frontend;
102
103     // no valid configline, so it will be treaten like a channel name
104     if (input.find(":") == std::string::npos)
105     {
106         if (mode.c_str()[0]=='a')
107             tuneTo(input);
108         else
109             tuneTo_sync(input);
110         return;
111     }
112     // add psydo name "foo" to complete configline syntax
113     frontend = parser.getFrontendParam("foo:"+input);
114
115     if (mode.c_str()[0]=='a') {
116         switch (type) {
117             case FE_QPSK:
118                 tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
119                           frontend.u.qpsk.fec_inner);
120                 break;
121             case FE_QAM:
122                 tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
123                           frontend.u.qam.fec_inner, frontend.u.qam.modulation);
124                 break;
125             case FE_OFDM:
126                 tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
127                           frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
128                           frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
129                           frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
130                 break;
131             default:
132                 SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
133         }
134     }
135     else {
136         switch (type) {
137             case FE_QPSK:
138                 tuneDVB_S_sync(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
139                                frontend.u.qpsk.fec_inner);
140                 break;
141             case FE_QAM:
142                 tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
143                                frontend.u.qam.fec_inner, frontend.u.qam.modulation);
144                 break;
145             case FE_OFDM:
146                 tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
147                                frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
148                                frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
149                                frontend.u.ofdm.guard_interval,
150                                frontend.u.ofdm.hierarchy_information);
151                 break;
152             default:
153                 SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
154         }
155     }
156 }
157
158 prefix_ void senf::DVBSocketController::tuneTo(std::string const & channel)
159 {
160     struct dvb_frontend_parameters frontend;
161
162     std::string configLine = parser.getConfigLine(channel);
163
164     frontend = parser.getFrontendParam(configLine);
165     switch (type) {
166         case FE_QPSK:
167             tuneDVB_S(frontend.frequency, frontend.inversion, frontend.u.qpsk.symbol_rate,
168                       frontend.u.qpsk.fec_inner);
169             break;
170         case FE_QAM:
171             tuneDVB_C(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
172                       frontend.u.qam.fec_inner, frontend.u.qam.modulation);
173             break;
174         case FE_OFDM:
175             tuneDVB_T(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
176                       frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
177                       frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
178                       frontend.u.ofdm.guard_interval, frontend.u.ofdm.hierarchy_information);
179             break;
180         default:
181             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
182     }
183 }
184
185 prefix_ void senf::DVBSocketController::tuneDVB_T(unsigned int frequency,
186                 fe_spectral_inversion_t inversion,
187                 fe_bandwidth_t bandwidth,
188                 fe_code_rate_t code_rate_HP, /* high priority stream code rate */
189                 fe_code_rate_t code_rate_LP, /* low priority stream code rate */
190                 fe_modulation_t constellation, /* modulation type (see above) */
191                 fe_transmit_mode_t transmission_mode,
192                 fe_guard_interval_t guard_interval,
193                 fe_hierarchy_t hierarchy_information
194                 )
195 {
196     if (type != FE_OFDM)
197         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
198             << getTypeString() << " for this operation you need a DVB-T Card!";
199
200     event.enable();
201
202     frontendHandle.protocol().setNonBlock();
203     frontendHandle.protocol().tuneDVB_T(frequency,
204                 inversion,
205                 bandwidth,
206                 code_rate_HP,
207                 code_rate_LP,
208                 constellation,
209                 transmission_mode,
210                 guard_interval,
211                 hierarchy_information);
212 }
213
214 prefix_ void senf::DVBSocketController::tuneDVB_S(unsigned int frequency,
215                                                   fe_spectral_inversion_t inversion,
216                                                   unsigned int symbole_rate,
217                                                   fe_code_rate_t code_rate)
218 {
219     if (type != FE_QPSK)
220         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
221             << getTypeString() << " for this operation you need a DVB-S Card!";
222
223     event.enable();
224
225     frontendHandle.protocol().setNonBlock();
226     frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
227 }
228
229 prefix_ void senf::DVBSocketController::tuneDVB_C(unsigned int frequency,
230                 fe_spectral_inversion_t inversion,
231                 unsigned int symbol_rate,
232                 fe_code_rate_t fec_inner,
233                 fe_modulation_t modulation
234                 )
235 {
236     if (type != FE_QAM)
237         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
238             << getTypeString() << " for this operation you need a DVB-C Card!";
239
240     event.enable();
241
242     frontendHandle.protocol().setNonBlock();
243
244     frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
245 }
246
247 prefix_ dvb_frontend_event senf::DVBSocketController::tuneTo_sync(std::string const & channel)
248 {
249     struct dvb_frontend_parameters frontend;
250     dvb_frontend_event ev;
251     std::string configLine = parser.getConfigLine(channel);
252
253     frontend = parser.getFrontendParam(configLine);
254     switch (type) {
255         case FE_QPSK:
256             ev = tuneDVB_S_sync(frontend.frequency, frontend.inversion,
257                                 frontend.u.qpsk.symbol_rate, frontend.u.qpsk.fec_inner);
258             break;
259         case FE_QAM:
260             ev = tuneDVB_C_sync(frontend.frequency, frontend.inversion, frontend.u.qam.symbol_rate,
261                                 frontend.u.qam.fec_inner, frontend.u.qam.modulation);
262             break;
263         case FE_OFDM:
264             ev = tuneDVB_T_sync(frontend.frequency, frontend.inversion, frontend.u.ofdm.bandwidth,
265                                 frontend.u.ofdm.code_rate_HP, frontend.u.ofdm.code_rate_LP,
266                                 frontend.u.ofdm.constellation, frontend.u.ofdm.transmission_mode,
267                                 frontend.u.ofdm.guard_interval,
268                                 frontend.u.ofdm.hierarchy_information);
269             break;
270         default:
271             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
272     }
273     return ev;
274 }
275
276 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_T_sync(unsigned int frequency,
277                 fe_spectral_inversion_t inversion,
278                 fe_bandwidth_t bandwidth,
279                 fe_code_rate_t code_rate_HP, /* high priority stream code rate */
280                 fe_code_rate_t code_rate_LP, /* low priority stream code rate */
281                 fe_modulation_t constellation, /* modulation type (see above) */
282                 fe_transmit_mode_t transmission_mode,
283                 fe_guard_interval_t guard_interval,
284                 fe_hierarchy_t hierarchy_information
285                 )
286 {
287     if (type != FE_OFDM)
288         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
289             << getTypeString() << " for this operation you need a DVB-T Card!";
290
291     event.disable();
292
293     frontendHandle.protocol().setNonBlock(false);
294
295     frontendHandle.protocol().tuneDVB_T(frequency,
296             inversion,
297             bandwidth,
298             code_rate_HP,
299             code_rate_LP,
300             constellation,
301             transmission_mode,
302             guard_interval,
303             hierarchy_information);
304
305     if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
306         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
307
308     return frontendHandle.protocol().getEvent();
309 }
310
311 prefix_ dvb_frontend_event
312 senf::DVBSocketController::tuneDVB_S_sync(unsigned int frequency,
313                                           fe_spectral_inversion_t inversion,
314                                           unsigned int symbole_rate, fe_code_rate_t code_rate)
315 {
316     if (type != FE_QPSK)
317         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
318             << getTypeString() << " for this operation you need a DVB-S Card!";
319
320     event.disable();
321
322     frontendHandle.protocol().setNonBlock(false);
323
324     frontendHandle.protocol().tuneDVB_S(frequency, inversion, symbole_rate, code_rate);
325
326     if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
327         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
328     return frontendHandle.protocol().getEvent();
329 }
330
331 prefix_ dvb_frontend_event senf::DVBSocketController::tuneDVB_C_sync(unsigned int frequency,
332                 fe_spectral_inversion_t inversion,
333                 unsigned int symbol_rate,
334                 fe_code_rate_t fec_inner,
335                 fe_modulation_t modulation
336                 )
337 {
338     if (type != FE_QAM)
339         SENF_THROW_SYSTEM_EXCEPTION("Type of card is: ")
340             << getTypeString() << " for this operation you need a DVB-C Card!";
341
342     event.disable();
343
344     frontendHandle.protocol().setNonBlock(false);
345
346     frontendHandle.protocol().tuneDVB_C(frequency, inversion, symbol_rate, fec_inner, modulation);
347     if (!frontendHandle.waitOOBReadable(senf::ClockService::seconds(2)))
348         SENF_THROW_SYSTEM_EXCEPTION("Could not tune to channel!");
349
350     return frontendHandle.protocol().getEvent();
351 }
352
353
354 prefix_ std::string senf::DVBSocketController::getTypeString()
355 {
356     switch (type) {
357         case FE_QPSK:
358             return "DVB-S";
359         case FE_QAM:
360             return "DVB-C";
361         case FE_OFDM:
362             return "DVB-T";
363         default:
364             SENF_THROW_SYSTEM_EXCEPTION("Could not determine type of card.");
365     }
366 }
367
368 prefix_ unsigned int senf::DVBSocketController::bitErrorRate()
369 {
370     return frontendHandle.protocol().bitErrorRate();
371 }
372
373 prefix_ unsigned int senf::DVBSocketController::signalToNoiseRatio()
374 {
375     return frontendHandle.protocol().signalNoiseRatio();
376 }
377
378 prefix_ unsigned int senf::DVBSocketController::signalStrength()
379 {
380     return frontendHandle.protocol().signalStrength();
381 }
382
383 prefix_ std::string senf::DVBSocketController::getTuneInfo(std::string const & conf)
384 {
385     const char* cConf = conf.c_str();
386     std::stringstream info;
387
388     fe_status_t status;
389     frontendHandle.protocol().setNonBlock(false);
390     uint16_t snr, signal;
391     uint32_t ber, uncorrected_blocks;
392     status = frontendHandle.protocol().status();
393     snr = frontendHandle.protocol().signalNoiseRatio();
394     signal = frontendHandle.protocol().signalStrength();
395     ber = frontendHandle.protocol().bitErrorRate();
396     uncorrected_blocks = frontendHandle.protocol().uncorrectedBlocks();
397
398     info << std::hex;
399
400     for (unsigned int i = 0; i < conf.size(); ++i) {
401         if (i>0)
402             info << " | ";
403         switch (cConf[i]) {
404             case 'S' :
405                 info << "signal " << signal;
406                 break;
407             case 's' :
408                 info << "snr " << snr;
409                 break;
410             case 'b' :
411                 info << "ber " << ber;
412                 break;
413             case 'u' :
414                 info << "unc " << uncorrected_blocks;
415                 break;
416             case 'f' :
417                 info << "status: " << status2String(status);
418                 break;
419             default:
420                 break;
421         }
422     }
423     return info.str();
424 }
425
426 prefix_ std::string senf::DVBSocketController::status2String(fe_status_t status)
427 {
428     std::string s("");
429     if (status & FE_HAS_LOCK)
430         return s += "HAS LOCK";
431     if (status & FE_HAS_CARRIER)
432         s += "HAS CARRIER ";
433     if (status & FE_HAS_VITERBI)
434         s += "HAS VITERBI ";
435     if (status & FE_HAS_SYNC)
436         s += "HAS SYNC ";
437     if (status & FE_HAS_SIGNAL)
438         s += "HAS SIGNAL ";
439     if (status & FE_TIMEDOUT)
440         s += "TIMED OUT ";
441     if (status & FE_REINIT)
442         s += "REINIT ";
443
444     return s;
445 }
446
447 prefix_ fe_type_t senf::DVBSocketController::getType()
448 {
449     return type;
450 }
451
452 prefix_ void senf::DVBSocketController::readEvent(int event)
453 {
454     if (cb)
455         cb(frontendHandle.protocol().getEvent());
456 }
457
458 prefix_ void senf::DVBSocketController::initConsole()
459 {
460     namespace fty = senf::console::factory;
461     namespace kw = senf::console::kw;
462
463     dir.doc("DVB Controller " + controllerNr);
464     ++controllerNr;
465
466     dir.add("type", fty::Command(&DVBSocketController::getTypeString, this)
467             .doc("Shows actual type of card DVB-{T, S, C}") );
468
469     dir.add("info", fty::Command(&DVBSocketController::getTuneInfo, this)
470             .doc("Returns a string which shows actual tuning status.\n"
471                  "'S' prints signal strength (in hex)\n"
472                  "'s' prints singal to noise ration (in hex)\n"
473                  "'b' prints bit error rate (in hex)\n"
474                  "'u' prints uncorrected blocks (in hex)\n"
475                  "'f' prints readable overal status e.g. 'Has Lock'\n\n"
476                  "These characters can be used to form the output. Be aware, some\n"
477                  "features may not be supported be your current driver implementation\n"
478                  "and could end in throwing an exception!")
479             .arg("conf", "Ssbuf", kw::default_value = "Ssbuf") );
480
481     dir.add("tune", fty::Command(&DVBSocketController::tuneToCMD, this)
482             .doc("tunes to channel listet in the configfile.")
483             .arg("channel", "channel to tune")
484             .arg("mode", "mode 'sync' or 'async'", kw::default_value = "async") );
485 }
486
487 //-/////////////////////////////////////////////////////////////////////////////////////////////////
488 #undef prefix_
489
490 \f
491 // Local Variables:
492 // mode: c++
493 // fill-column: 100
494 // c-file-style: "senf"
495 // indent-tabs-mode: nil
496 // ispell-local-dictionary: "american"
497 // compile-command: "scons -u test"
498 // comment-column: 40
499 // End: