1<title>Examples</title> 2<para>In this section we would like to present some examples for using the DVB API. 3</para> 4<para>NOTE: This section is out of date, and the code below won't even 5 compile. Please refer to the 6 <ulink url="http://linuxtv.org/docs/libdvbv5/index.html">libdvbv5</ulink> 7 for updated/recommended examples. 8</para> 9 10<section id="tuning"> 11<title>Tuning</title> 12<para>We will start with a generic tuning subroutine that uses the frontend and SEC, as well as 13the demux devices. The example is given for QPSK tuners, but can easily be adjusted for 14QAM. 15</para> 16<programlisting> 17 #include <sys/ioctl.h> 18 #include <stdio.h> 19 #include <stdint.h> 20 #include <sys/types.h> 21 #include <sys/stat.h> 22 #include <fcntl.h> 23 #include <time.h> 24 #include <unistd.h> 25 26 #include <linux/dvb/dmx.h> 27 #include <linux/dvb/frontend.h> 28 #include <linux/dvb/sec.h> 29 #include <sys/poll.h> 30 31 #define DMX "/dev/dvb/adapter0/demux1" 32 #define FRONT "/dev/dvb/adapter0/frontend1" 33 #define SEC "/dev/dvb/adapter0/sec1" 34 35 /⋆ routine for checking if we have a signal and other status information⋆/ 36 int FEReadStatus(int fd, fe_status_t ⋆stat) 37 { 38 int ans; 39 40 if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){ 41 perror("FE READ STATUS: "); 42 return -1; 43 } 44 45 if (⋆stat & FE_HAS_POWER) 46 printf("FE HAS POWER\n"); 47 48 if (⋆stat & FE_HAS_SIGNAL) 49 printf("FE HAS SIGNAL\n"); 50 51 if (⋆stat & FE_SPECTRUM_INV) 52 printf("SPEKTRUM INV\n"); 53 54 return 0; 55 } 56 57 58 /⋆ tune qpsk ⋆/ 59 /⋆ freq: frequency of transponder ⋆/ 60 /⋆ vpid, apid, tpid: PIDs of video, audio and teletext TS packets ⋆/ 61 /⋆ diseqc: DiSEqC address of the used LNB ⋆/ 62 /⋆ pol: Polarisation ⋆/ 63 /⋆ srate: Symbol Rate ⋆/ 64 /⋆ fec. FEC ⋆/ 65 /⋆ lnb_lof1: local frequency of lower LNB band ⋆/ 66 /⋆ lnb_lof2: local frequency of upper LNB band ⋆/ 67 /⋆ lnb_slof: switch frequency of LNB ⋆/ 68 69 int set_qpsk_channel(int freq, int vpid, int apid, int tpid, 70 int diseqc, int pol, int srate, int fec, int lnb_lof1, 71 int lnb_lof2, int lnb_slof) 72 { 73 struct secCommand scmd; 74 struct secCmdSequence scmds; 75 struct dmx_pes_filter_params pesFilterParams; 76 FrontendParameters frp; 77 struct pollfd pfd[1]; 78 FrontendEvent event; 79 int demux1, demux2, demux3, front; 80 81 frequency = (uint32_t) freq; 82 symbolrate = (uint32_t) srate; 83 84 if((front = open(FRONT,O_RDWR)) < 0){ 85 perror("FRONTEND DEVICE: "); 86 return -1; 87 } 88 89 if((sec = open(SEC,O_RDWR)) < 0){ 90 perror("SEC DEVICE: "); 91 return -1; 92 } 93 94 if (demux1 < 0){ 95 if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) 96 < 0){ 97 perror("DEMUX DEVICE: "); 98 return -1; 99 } 100 } 101 102 if (demux2 < 0){ 103 if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) 104 < 0){ 105 perror("DEMUX DEVICE: "); 106 return -1; 107 } 108 } 109 110 if (demux3 < 0){ 111 if ((demux3=open(DMX, O_RDWR|O_NONBLOCK)) 112 < 0){ 113 perror("DEMUX DEVICE: "); 114 return -1; 115 } 116 } 117 118 if (freq < lnb_slof) { 119 frp.Frequency = (freq - lnb_lof1); 120 scmds.continuousTone = SEC_TONE_OFF; 121 } else { 122 frp.Frequency = (freq - lnb_lof2); 123 scmds.continuousTone = SEC_TONE_ON; 124 } 125 frp.Inversion = INVERSION_AUTO; 126 if (pol) scmds.voltage = SEC_VOLTAGE_18; 127 else scmds.voltage = SEC_VOLTAGE_13; 128 129 scmd.type=0; 130 scmd.u.diseqc.addr=0x10; 131 scmd.u.diseqc.cmd=0x38; 132 scmd.u.diseqc.numParams=1; 133 scmd.u.diseqc.params[0] = 0xF0 | ((diseqc ⋆ 4) & 0x0F) | 134 (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) | 135 (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0); 136 137 scmds.miniCommand=SEC_MINI_NONE; 138 scmds.numCommands=1; 139 scmds.commands=&scmd; 140 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ 141 perror("SEC SEND: "); 142 return -1; 143 } 144 145 if (ioctl(sec, SEC_SEND_SEQUENCE, &scmds) < 0){ 146 perror("SEC SEND: "); 147 return -1; 148 } 149 150 frp.u.qpsk.SymbolRate = srate; 151 frp.u.qpsk.FEC_inner = fec; 152 153 if (ioctl(front, FE_SET_FRONTEND, &frp) < 0){ 154 perror("QPSK TUNE: "); 155 return -1; 156 } 157 158 pfd[0].fd = front; 159 pfd[0].events = POLLIN; 160 161 if (poll(pfd,1,3000)){ 162 if (pfd[0].revents & POLLIN){ 163 printf("Getting QPSK event\n"); 164 if ( ioctl(front, FE_GET_EVENT, &event) 165 166 == -EOVERFLOW){ 167 perror("qpsk get event"); 168 return -1; 169 } 170 printf("Received "); 171 switch(event.type){ 172 case FE_UNEXPECTED_EV: 173 printf("unexpected event\n"); 174 return -1; 175 case FE_FAILURE_EV: 176 printf("failure event\n"); 177 return -1; 178 179 case FE_COMPLETION_EV: 180 printf("completion event\n"); 181 } 182 } 183 } 184 185 186 pesFilterParams.pid = vpid; 187 pesFilterParams.input = DMX_IN_FRONTEND; 188 pesFilterParams.output = DMX_OUT_DECODER; 189 pesFilterParams.pes_type = DMX_PES_VIDEO; 190 pesFilterParams.flags = DMX_IMMEDIATE_START; 191 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ 192 perror("set_vpid"); 193 return -1; 194 } 195 196 pesFilterParams.pid = apid; 197 pesFilterParams.input = DMX_IN_FRONTEND; 198 pesFilterParams.output = DMX_OUT_DECODER; 199 pesFilterParams.pes_type = DMX_PES_AUDIO; 200 pesFilterParams.flags = DMX_IMMEDIATE_START; 201 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ 202 perror("set_apid"); 203 return -1; 204 } 205 206 pesFilterParams.pid = tpid; 207 pesFilterParams.input = DMX_IN_FRONTEND; 208 pesFilterParams.output = DMX_OUT_DECODER; 209 pesFilterParams.pes_type = DMX_PES_TELETEXT; 210 pesFilterParams.flags = DMX_IMMEDIATE_START; 211 if (ioctl(demux3, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ 212 perror("set_tpid"); 213 return -1; 214 } 215 216 return has_signal(fds); 217 } 218 219</programlisting> 220<para>The program assumes that you are using a universal LNB and a standard DiSEqC 221switch with up to 4 addresses. Of course, you could build in some more checking if 222tuning was successful and maybe try to repeat the tuning process. Depending on the 223external hardware, i.e. LNB and DiSEqC switch, and weather conditions this may be 224necessary. 225</para> 226</section> 227 228<section id="the_dvr_device"> 229<title>The DVR device</title> 230<para>The following program code shows how to use the DVR device for recording. 231</para> 232<programlisting> 233 #include <sys/ioctl.h> 234 #include <stdio.h> 235 #include <stdint.h> 236 #include <sys/types.h> 237 #include <sys/stat.h> 238 #include <fcntl.h> 239 #include <time.h> 240 #include <unistd.h> 241 242 #include <linux/dvb/dmx.h> 243 #include <linux/dvb/video.h> 244 #include <sys/poll.h> 245 #define DVR "/dev/dvb/adapter0/dvr1" 246 #define AUDIO "/dev/dvb/adapter0/audio1" 247 #define VIDEO "/dev/dvb/adapter0/video1" 248 249 #define BUFFY (188⋆20) 250 #define MAX_LENGTH (1024⋆1024⋆5) /⋆ record 5MB ⋆/ 251 252 253 /⋆ switch the demuxes to recording, assuming the transponder is tuned ⋆/ 254 255 /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ 256 /⋆ vpid, apid: PIDs of video and audio channels ⋆/ 257 258 int switch_to_record(int demux1, int demux2, uint16_t vpid, uint16_t apid) 259 { 260 struct dmx_pes_filter_params pesFilterParams; 261 262 if (demux1 < 0){ 263 if ((demux1=open(DMX, O_RDWR|O_NONBLOCK)) 264 < 0){ 265 perror("DEMUX DEVICE: "); 266 return -1; 267 } 268 } 269 270 if (demux2 < 0){ 271 if ((demux2=open(DMX, O_RDWR|O_NONBLOCK)) 272 < 0){ 273 perror("DEMUX DEVICE: "); 274 return -1; 275 } 276 } 277 278 pesFilterParams.pid = vpid; 279 pesFilterParams.input = DMX_IN_FRONTEND; 280 pesFilterParams.output = DMX_OUT_TS_TAP; 281 pesFilterParams.pes_type = DMX_PES_VIDEO; 282 pesFilterParams.flags = DMX_IMMEDIATE_START; 283 if (ioctl(demux1, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ 284 perror("DEMUX DEVICE"); 285 return -1; 286 } 287 pesFilterParams.pid = apid; 288 pesFilterParams.input = DMX_IN_FRONTEND; 289 pesFilterParams.output = DMX_OUT_TS_TAP; 290 pesFilterParams.pes_type = DMX_PES_AUDIO; 291 pesFilterParams.flags = DMX_IMMEDIATE_START; 292 if (ioctl(demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0){ 293 perror("DEMUX DEVICE"); 294 return -1; 295 } 296 return 0; 297 } 298 299 /⋆ start recording MAX_LENGTH , assuming the transponder is tuned ⋆/ 300 301 /⋆ demux1, demux2: file descriptor of video and audio filters ⋆/ 302 /⋆ vpid, apid: PIDs of video and audio channels ⋆/ 303 int record_dvr(int demux1, int demux2, uint16_t vpid, uint16_t apid) 304 { 305 int i; 306 int len; 307 int written; 308 uint8_t buf[BUFFY]; 309 uint64_t length; 310 struct pollfd pfd[1]; 311 int dvr, dvr_out; 312 313 /⋆ open dvr device ⋆/ 314 if ((dvr = open(DVR, O_RDONLY|O_NONBLOCK)) < 0){ 315 perror("DVR DEVICE"); 316 return -1; 317 } 318 319 /⋆ switch video and audio demuxes to dvr ⋆/ 320 printf ("Switching dvr on\n"); 321 i = switch_to_record(demux1, demux2, vpid, apid); 322 printf("finished: "); 323 324 printf("Recording %2.0f MB of test file in TS format\n", 325 MAX_LENGTH/(1024.0⋆1024.0)); 326 length = 0; 327 328 /⋆ open output file ⋆/ 329 if ((dvr_out = open(DVR_FILE,O_WRONLY|O_CREAT 330 |O_TRUNC, S_IRUSR|S_IWUSR 331 |S_IRGRP|S_IWGRP|S_IROTH| 332 S_IWOTH)) < 0){ 333 perror("Can't open file for dvr test"); 334 return -1; 335 } 336 337 pfd[0].fd = dvr; 338 pfd[0].events = POLLIN; 339 340 /⋆ poll for dvr data and write to file ⋆/ 341 while (length < MAX_LENGTH ) { 342 if (poll(pfd,1,1)){ 343 if (pfd[0].revents & POLLIN){ 344 len = read(dvr, buf, BUFFY); 345 if (len < 0){ 346 perror("recording"); 347 return -1; 348 } 349 if (len > 0){ 350 written = 0; 351 while (written < len) 352 written += 353 write (dvr_out, 354 buf, len); 355 length += len; 356 printf("written %2.0f MB\r", 357 length/1024./1024.); 358 } 359 } 360 } 361 } 362 return 0; 363 } 364 365</programlisting> 366 367</section> 368