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