/************************************************************************* * Copyright 2009 Ralph Spitzner (rasp@spitzner.org) * * This file is part of Yahdr. * * Yahdr is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Yahdr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Yahdr. If not, see . **************************************************************************/ #include "dvbtcontrol.h" /* - 0x11 - MPEG2 HD Television Service - 0x16 - Advanced Codec SD Television service - 0x19 - Advanced Codec HD Television service */ #warning respect the above somewhere/how extern sql::mysql::MySQL_Driver *driver; extern sql::Connection *con; extern sql::Statement *stmt; DVBtcontrol::DVBtcontrol() { frontend_fd = demux_fd = dvr_fd = video_fd = audio_fd = nit_fd = 0; first_sdt = sdp = 0; intchan = 1; //ctor } DVBtcontrol::CH DVBtcontrol::channels_ger[] = { /// germany {50500000,7}, {57500000,7}, {64500000,7}, {71500000,7}, {177500000,7}, {184500000,7}, {191500000,7}, {198500000,7}, {205500000,7}, {212500000,7}, {219500000,7}, {226500000,7}, {233500000,7}, /* hyperband ?? */ {306000000,8}, {314000000,8}, {322000000,8}, {330000000,8}, {338000000,8}, {346000000,8}, {354000000,8}, {362000000,8}, {370000000,8}, {378000000,8}, {386000000,8}, {394000000,8}, {402000000,8}, {410000000,8}, {418000000,8}, {426000000,8}, {434000000,8}, {442000000,8}, {450000000,8}, {458000000,8}, {466000000,8}, /* UHF */ {474000000,8}, {482000000,8}, {490000000,8}, {498000000,8}, {506000000,8}, {514000000,8}, {522000000,8}, {530000000,8}, {538000000,8}, {546000000,8}, {554000000,8}, {562000000,8}, {570000000,8}, {578000000,8}, {586000000,8}, {594000000,8}, {602000000,8}, {610000000,8}, {618000000,8}, {626000000,8}, {634000000,8}, {642000000,8}, {650000000,8}, {658000000,8}, {666000000,8}, {674000000,8}, {682000000,8}, {690000000,8}, {698000000,8}, {706000000,8}, {714000000,8}, {722000000,8}, {730000000,8}, {738000000,8}, {746000000,8}, {754000000,8}, {762000000,8}, {770000000,8}, {778000000,8}, {786000000,8}, {794000000,8}, {802000000,8}, {810000000,8}, {818000000,8}, {826000000,8}, {834000000,8}, {842000000,8}, {850000000,8}, {858000000,8}, {0,0} }; int DVBtcontrol::input_timeout (int filedes, unsigned int seconds) { fd_set set; struct timeval timeout; /* Initialize the file descriptor set. */ FD_ZERO (&set); FD_SET (filedes, &set); /* Initialize the timeout data structure. */ timeout.tv_sec = seconds; timeout.tv_usec = 0; /* select returns 0 if timeout, 1 if input available, -1 if error. */ return TEMP_FAILURE_RETRY (select (FD_SETSIZE, &set, NULL, NULL, &timeout)); } bool DVBtcontrol::init(uint16_t adapter,uint16_t device,char *ch_fname) { char buffer[256]; intchan = 1; ch_dbname = ch_fname; adapnum = adapter; devnum = device; memset(&frontend_param, 0, sizeof(struct dvb_frontend_parameters)); frontend_param.frequency = 177500000;//50500000; frontend_param.inversion = INVERSION_AUTO; frontend_param.u.ofdm.bandwidth = BANDWIDTH_7_MHZ; frontend_param.u.ofdm.code_rate_HP =FEC_3_4; frontend_param.u.ofdm.code_rate_LP = FEC_AUTO; frontend_param.u.ofdm.constellation = QAM_16; // ?? frontend_param.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;//8K; frontend_param.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;//1_8; //frontend_param.u.ofdm.hierarchy_information = HIERARCHY_NONE; #warning put device # in config sprintf(buffer,"/dev/dvb/adapter%d/frontend%d",adapter,0); printf("DVBinit device %s\n",buffer); if ((frontend_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } sprintf(buffer,"/dev/dvb/adapter%d/demux%d",adapter,0); if ((demux_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } if ((video_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } if ((audio_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } if (setup_frontend (frontend_fd, &frontend_param) < 0) return false; return true; } /// remove control chars char *clean(char *str) { char *ret,*rets; if (!(ret = (char *)malloc(strlen(str)+1))) { printf("Aieeeh, out of mem in clean()\n"); exit(666); } memset(ret,0,strlen(str)+1); rets = ret; while (*(str)) { switch (*(str)) { case 0 ... 0x09: str++; break; case 0x10: str += 3; break; case 0x86 ... 0x87: str++; break; default: *(ret++) = *(str++); break; } } return rets; } bool DVBtcontrol::read_tpinfo(CH *chp,uint16_t tpnum) { typedef struct netw { uint16_t pnum; uint16_t ppid; struct netw *next; } NW; typedef struct pid { uint8_t type; uint8_t langcode[4]; /// padded zero uint16_t pid; uint16_t pnum; struct pid *next; } PID; typedef struct program { uint16_t pid; uint16_t service_id; uint8_t service_type; uint8_t eit_sched; uint8_t eit_pf; uint8_t free_ca; PID *pids; string provider_n; string service_n; struct program *next; } PROGRAM; uint8_t secnum,lsec; int seclen; uint8_t buffer[4096],*bp,*dp; uint16_t nbytes,ts_id,ilen,i,lb,x,slen,infolen; struct dmx_sct_filter_params sctFilterParams; int wantnew; SDTSEC *sect; NW *nwp,*fnw,*tnw; PID *pidp,*fpid,*tpid; SDATA *tsdp; nwp = NULL; pidp = fpid = tpid = NULL; memset(&sctFilterParams, 0, sizeof(sctFilterParams)); sctFilterParams.pid = 0x0; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START; sctFilterParams.filter.filter[0] = 0x0; // 0x4e --> now/next sctFilterParams.filter.mask[0] = 0xff; if (ioctl(demux_fd, DMX_SET_FILTER, &sctFilterParams) < 0) { cout << "DMX filter set failed in read_nit ! (fd = " << demux_fd << ")" << endl; return false; } while (1) { if ((nbytes = read(demux_fd,buffer,4096)) == -1) { cout << "failed to read from demux" << endl; return false; } cout << "read " << nbytes << " bytes for table " ; printf("0x%x\n",buffer[0]); if (buffer[0] == 0) /// PAT table, just in case they also send other stuff break; } bp = (uint8_t*)&buffer; bp++; bp++; seclen = *(bp++); seclen -= 8; /// crc discount ts_id = *(bp++); ts_id <<= 8; ts_id |= *(bp++) ; bp++; secnum = *(bp++); lsec = *(bp++); nwp = fnw = new NW; i = 0; #warning WERK !!! bigfatwarning: deal with sections !! do { nwp->pnum = *(bp++); nwp->pnum <<= 8; nwp->pnum |= *(bp++); nwp->ppid = *(bp++) & 0x1f; /// upper three bit are reserved nwp->ppid <<= 8; nwp->ppid |= *(bp++); i ++; printf("PID: %d, Program: %d\n",nwp->ppid,nwp->pnum); if ( i < (seclen/4)) { nwp->next = new NW; nwp = nwp->next; nwp->next = NULL; } } while (i < (seclen/4)); nwp = fnw; do { if (nwp->pnum != 0) { //printf("Program: %d\nPID: %d\n",nwp->pnum,nwp->ppid); memset(&sctFilterParams, 0, sizeof(sctFilterParams)); sctFilterParams.pid = nwp->ppid; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START; sctFilterParams.filter.filter[0] = 0x2; sctFilterParams.filter.mask[0] = 0xff; if (ioctl(demux_fd, DMX_SET_FILTER, &sctFilterParams) < 0) { cout << "DMX filter set failed in read_info !" << endl; return false; } while (1) { if ( 0 == input_timeout(demux_fd, 20)) /// wait 30 secs { cout << "Timeout on PID #" << nwp->ppid << endl; return false; //break; } if ((nbytes = read(demux_fd,buffer,4096)) <= 0) { cout << "failed to read from demux" ; printf("for table 0x%x\n",buffer[0]); return false; } cout << "read " << nbytes << " bytes for table " ; printf("0x%x\n",buffer[0]); if (buffer[0] == 0x2) /// PMT table, just in case they also send other stuff break; } /// PMT start if (pidp == NULL) { pidp = fpid = new PID; memset(pidp,0,sizeof(PID)); pidp->next = NULL; } else { pidp->next = new PID; pidp = pidp->next; memset(pidp,0,sizeof(PID)); pidp->next = NULL; } printf("|"); fflush(stdout); bp = (uint8_t *)&buffer; ///tableid -> 2 bp++; seclen = *(bp++); seclen <<= 8; seclen |= *(bp++); seclen &= 0xfff; /// upper 4 bits are section syntax,lit 0,reserved bp++; bp++; /// already know program number bp++; /// reserved,version,current/next bp++; /// section number bp++; /// last section bp++; bp++; /// 3 bits reserved, PCR PID infolen = (*(bp++) << 8) & 0xfff; infolen |= *(bp++); /// reserved, program info len (lower 12) dp = bp; bp += infolen; seclen -= infolen + 9 + 4; wantnew = 0; while (seclen > 0) { //fprintf(stderr,"_%d_",seclen); if (wantnew == 1) { pidp->next = new PID; pidp = pidp->next; memset(pidp,0,sizeof(PID)); } pidp->next = NULL; printf("."); fflush(stdout); switch (*bp) { case 17: case 3 ... 5: dp = bp; wantnew = 1; pidp->pnum = nwp->pnum; pidp->type = *(bp++); pidp->pid = *(bp++); pidp->pid <<= 8; pidp->pid |= *(bp++); pidp->pid &= 0x1fff; ilen = *(bp++); ilen <<= 8; ilen |= *(bp++); ilen &= 0xfff; /// upper 4 reserved while (ilen != 0) { switch (*(bp)) { case 0x0a: pidp->langcode[0] = '\0'; pidp->langcode[1] = '\0'; pidp->langcode[2] = '\0'; pidp->langcode[3] = '\0'; pidp->langcode[0] = *(bp+2); pidp->langcode[1] = *(bp+3); pidp->langcode[2] = *(bp+4); bp++; ilen -= 2; ilen -= *(bp); bp += *(bp); bp++; break; default: bp++; ilen -= 2; ilen -= *(bp); bp += *(bp) ; bp ++; break; } } break; case 27: case 16: case 2: //video case 6: dp = bp; pidp->pnum = nwp->pnum; pidp->type = *(bp++); pidp->pid = *(bp++); pidp->pid <<= 8; pidp->pid |= *(bp++); pidp->pid &= 0x1fff; ilen = *(bp++); ilen <<= 8; ilen |= *(bp++); ilen &= 0xfff; /// upper 4 reserved bp += ilen; /// loose viedo info wantnew = 1; break; default: // dontcare wantnew = 0;//1; dp = bp; pidp->pnum = 0; //nwp->pnum; pidp->type = *(bp++); pidp->pid = *(bp++); pidp->pid <<= 8; pidp->pid |= *(bp++); pidp->pid &= 0x1fff; ilen = *(bp++); ilen <<= 8; ilen |= *(bp++); ilen &= 0xfff; /// upper 4 reserved bp += ilen; /// loose viedo info break; } int lendiff = (bp -dp); seclen -= lendiff; } } } while ((nwp = nwp->next)); /// read SDT and fill program struct memset(&sctFilterParams, 0, sizeof(sctFilterParams)); sctFilterParams.pid = 0x11; sctFilterParams.timeout = 0; sctFilterParams.flags = DMX_IMMEDIATE_START; sctFilterParams.filter.filter[0] = 0x42; sctFilterParams.filter.mask[0] = 0xff; if (ioctl(demux_fd, DMX_SET_FILTER, &sctFilterParams) < 0) { perror("DMX_SET_FILTER sdt"); return false; } if ( 0 == input_timeout(demux_fd, 60)) /// wait 30 secs { cout << "Timeout reding demux" << endl; return false; //break; } if ((nbytes = read(demux_fd,buffer,4096)) == -1) { cout << "failed to read from demux" << endl; return false; } bp = (uint8_t *) &buffer; SDTHEAD *head = fill_sdthead((uint8_t *) bp); bp = bp + SDTHEAD_SIZ + 1; sect = fill_sdtsec((uint8_t *) bp ); bp = bp + SDTSEC_SIZ ; printf("\nRead SDT\n"); wantnew = 0; dp = bp; while ((bp - dp) < head->section_length) { if (sdp == NULL) { sdp = new SDATA; sdp->next = NULL; } else if (wantnew == 1) { sdp->next = new SDATA; sdp = sdp->next; sdp->next = NULL; } if (sdp == NULL) { cout << "failed to get SDATA mem" << endl; return false; } if (first_sdt == NULL) first_sdt = sdp; sdp->tsid = head->transport_stream_id; sdp->service_id = sect->service_id; // printf("SERVICEID = %d\n",sdp->service_id); sdp->epg = sect->EIT_schedule_flag; sdp->pf = sect->EIT_present_follow; sdp->CA = sect->freeCA; sdp->run = sect->runningstatus; switch (*bp) { case 0x48: /// service desc bp++; slen = *(bp++); /// length sdp->type = *(bp++); lb = *(bp++); slen -= lb + 2; for (x = 0; x != lb; x++) { sdp->provider[x] = *(bp++); } sdp->provider[x] = '\0'; lb = *(bp++); slen -= lb + 1 ; for (x = 0; x != lb; x++) { sdp->name[x] = *(bp++); } // printf("############# sdp->name = %s sdp->service_id %d\n",sdp->name,sdp->service_id); sdp->name[x] = '\0'; //i += SDTSEC_SIZ + sizeof(DESCRIPTOR) + 1 + 1 + desc->descriptor_length; wantnew = 1; break; case 0x42 ... 0x47: case 0x49 ... 0x4c: case 0x51: case 0x53: case 0x57: case 0x5d: case 0x5f: case 0x64: // case 0x6e: case 0x71 ... 0x72: bp ++; bp += *(bp) + 1 ; sect = fill_sdtsec(bp); bp += SDTSEC_SIZ; wantnew = 0; break; default: sect = fill_sdtsec(bp); bp += SDTSEC_SIZ; wantnew = 0; break; } } delete sect; delete head; nwp = fnw; string *prov,*pname; sql::ResultSet *res; //intchan = time(0); do { if (nwp->pnum != 0) { sdp = find_sdata(nwp->pnum); if(sdp == NULL) printf("Aieeh,SDP = NULL\n"); if (sdp != NULL) /// oberGAU nothing we can do here, there are 'stray' PID's e.g. /// receiver update with no service info to it.... { intchan ++; prov = specialchars((unsigned char *)&sdp->provider); pname = specialchars((unsigned char *)&sdp->name); sprintf((char *)buffer,"select name from channels where name=\"%s\"",pname->data()); try { res = stmt->executeQuery((char *)buffer); } catch (sql::SQLException &e) { cout << __FUNCTION__ ; cout << "########## ERR: " << e.what(); cout << " (MySQL error code: " << e.getErrorCode(); cout << ", SQLState: " << e.getSQLState() << " )" << endl; cout << "not ok 1" << endl; } if(res->next()) { cout << "Already have " << pname->data() << endl; } else { sprintf((char *)buffer,"insert into channels values(%d,%d, %d, %d, %d, %d, %d, %d, %d,%d,%d,\"%s\",\"%s\");", tpnum,chp->freq,chp->bw,ts_id,qam,intchan,nwp->pnum,nwp->ppid,sdp->type , sdp->epg,sdp->pf,prov->data(),pname->data()); stmt->execute((char *)buffer); printf("found %s - %s TYPE=%d chan ##%d\n",clean(sdp->provider),clean(sdp->name),sdp->type,intchan); delete prov; delete pname; pidp = fpid; do { if (pidp->pnum == nwp->pnum ) { /// basically one entry too many.... switch (pidp->type) { /*case 27 : case 2 : sprintf((char *)buffer,"insert into pids values (%d,%d,%d,%d,'%s');", intchan,0,pidp->pid,0,strlen((char *)pidp->langcode) > 0 ? (char*)pidp->langcode : "NON"); stmt->execute((char *)buffer); break; case 3 ... 4: sprintf((char *)buffer,"insert into pids values (%d,%d,%d,%d,'%s');", intchan,pidp->pid,0,0,strlen((char *)pidp->langcode) > 0 ? (char*)pidp->langcode : "var"); stmt->execute((char *)buffer); break;*/ /*case 27: //case 6: //teletext case 26: case 2: case 3 ... 4: case 6:*/ default: sprintf((char *)buffer,"insert into pids values (%d,%d,%d,%d);", intchan,pidp->pid,pidp->type,pidp->pnum); stmt->execute((char *)buffer); break; /* default: printf("junking pid %d TYPE=%d (data or unknown)\n",pidp->pid,pidp->type); break;*/ } } } while ((pidp = pidp->next)); } } } } while ((nwp = nwp->next)); //fprintf(ch_filep,"}\n"); printf("\n"); nwp = fnw; do { tnw = nwp; nwp = nwp->next; delete tnw; } while (nwp); pidp = fpid; do { tpid = pidp; if(tpid != NULL) { pidp = pidp->next; delete tpid; } } while (pidp); sdp = first_sdt; do { tsdp = sdp; sdp = sdp->next; delete tsdp; } while (sdp); first_sdt = NULL; return true; } DVBtcontrol::SDATA *DVBtcontrol::find_sdata(uint16_t pgnum) { SDATA *p; p = first_sdt; do { //printf("comp %d,%d\n",pgnum,p->service_id); if (p->service_id == pgnum) return p; } while ((p = p->next)); return (SDATA *) NULL; } DVBtcontrol::SDTSEC *DVBtcontrol::fill_sdtsec(uint8_t *data) { SDTSEC *sec; uint16_t buf; if (!(sec = new SDTSEC)) return (SDTSEC *)NULL; buf = *(data++) << 8; buf |= *(data++); sec->service_id = buf; sec->reserved = (*data & 0xfc) >> 2; sec->EIT_schedule_flag = (*data & 2) >> 1; sec->EIT_present_follow = *data & 1; data++; buf = *data << 8; data ++; buf |= *data; sec->runningstatus = (buf & 0xe000) >> 13; sec->freeCA = (buf & 0x1000) >> 12; sec->descriptors_loop_length = buf & 0xfff; return sec; } DVBtcontrol::SDTHEAD *DVBtcontrol::fill_sdthead(uint8_t *data) { uint16_t buf; SDTHEAD *head; if (!(head = new SDTHEAD)) return (SDTHEAD *)NULL; head->table_id = *(data++); //tid head->section_syntax_indicator = (*(data) & 128) >> 7; head->reserved1 = (*(data) & 64) >> 6; head->reserved2 = (*(data) & ( 32 | 16)) >> 4; buf = (*(data) & (8 | 4 | 2 | 1)) << 8; data ++; buf |= *(data); head->section_length = buf; // printf("sectionlen = %d\n",buf); data ++; buf = *(data) << 8; data ++; buf |= *(data); head->transport_stream_id = buf; data ++; head->reserved3 = (*(data) & (128 | 64)) >> 6; head->version_number = (*(data) & ( 32 | 16 | 8 | 4 | 2)) >> 1; head->current_next_indicator = *(data) & 1; data ++; head->section_number = *(data); // printf("XXX Secnum %d ",head->section_number); data ++; head->last_section_number = *(data); //printf("XXX Last Secnum %d ",head->last_section_number); data ++; buf = *(data) << 8; data ++; buf |= *(data); head->original_network_id = buf; data ++; head->reserved_fut_use = *data; return head; } bool DVBtcontrol::scan() { CH *chp; int tpnum; char buffer[256]; chp = channels_ger; intchan = 0; tpnum = 1; if (frontend_fd == 0) { sprintf(buffer,"/dev/dvb/adapter%d/frontend%d",adapter,0); if ((frontend_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } } if (demux_fd == 0) { sprintf(buffer,"/dev/dvb/adapter%d/demux%d",adapter,0); if ((demux_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } } memset(&frontend_param, 0, sizeof(struct dvb_frontend_parameters)); frontend_param.inversion = INVERSION_AUTO; frontend_param.u.ofdm.code_rate_HP =FEC_3_4; frontend_param.u.ofdm.code_rate_LP = FEC_AUTO; frontend_param.u.ofdm.constellation = QAM_16; // ?? frontend_param.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;//8K; frontend_param.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;//1_8; while (chp->freq != 0) { frontend_param.frequency = chp->freq; frontend_param.u.ofdm.bandwidth = chp->bw == 7 ? BANDWIDTH_7_MHZ : BANDWIDTH_8_MHZ; if (setup_frontend (frontend_fd, &frontend_param) < 0) return false; if (check_frontend (frontend_fd)) { printf("##### LOCK on freq %d\n",chp->freq); read_tpinfo(chp,tpnum++); /// read info and put into db } else printf("!!!! no LOCK on freq %d\n",chp->freq); chp++; } return true; } void DVBtcontrol::clearfds() { int i=0; do { if(pidfds[i] > 0) { close(pidfds[i]); pidfds[i] = 0; } else break; }while(i++ < 255); } //bool DVBtcontrol::tuneto(uint32_t freq,uint8_t bw,uint16_t vpid, uint16_t apid, uint16_t textpid,fe_modulation_t QAM) bool DVBtcontrol::tuneto(uint32_t freq,uint8_t bw,CPIDS *pids, fe_modulation_t QAM) { char buffer[256]; int i = 0; if (frontend_fd == 0) { sprintf(buffer,"/dev/dvb/adapter%d/frontend%d",adapter,0); if ((frontend_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening '%s'", buffer); return false; } } sprintf(buffer,"/dev/dvb/adapter%d/demux%d",adapter,0); clearfds(); if (video_fd == 0) { if ((video_fd = open(buffer, O_RDWR)) < 0) { printf ("failed opening (video_fd)'%s'", buffer); return false; } } // cout << "tune" << freq << " a " << apid << " v " << vpid; if (oldfreq != freq) { memset(&frontend_param, 0, sizeof(struct dvb_frontend_parameters)); frontend_param.frequency = freq; frontend_param.inversion = INVERSION_AUTO; frontend_param.u.ofdm.bandwidth = bw == 7 ? BANDWIDTH_7_MHZ : BANDWIDTH_8_MHZ; frontend_param.u.ofdm.code_rate_HP =FEC_3_4; frontend_param.u.ofdm.code_rate_LP = FEC_AUTO; frontend_param.u.ofdm.constellation = QAM_16; // ?? frontend_param.u.ofdm.transmission_mode = TRANSMISSION_MODE_AUTO;//8K; frontend_param.u.ofdm.guard_interval = GUARD_INTERVAL_AUTO;//1_8; //frontend_param.u.ofdm.hierarchy_information = HIERARCHY_NONE; if (setup_frontend (frontend_fd, &frontend_param) < 0) return false; } if(pids != NULL) do { if ((pidfds[i] = open(buffer, O_RDWR)) < 0) { printf ("failed opening (fd #%d)\n", i); return false; } pesfilter.pid = pids->pid; //vpid; pesfilter.input = DMX_IN_FRONTEND; pesfilter.output = DMX_OUT_TS_TAP;// : */DMX_OUT_DECODER; pesfilter.flags = DMX_IMMEDIATE_START; printf("pid %d -- type %d\n",pids->pid,pids->type); pesfilter.pes_type = DMX_PES_OTHER; if (ioctl(pidfds[i], DMX_SET_PES_FILTER, &pesfilter) < 0) { printf("ioctl(DMX_SET_PES_FILTER) for PID #%d failed\n",i); //return false; } i++; } while(pids = pids->next); return true; } bool DVBtcontrol::setup_frontend (int fe_fd, struct dvb_frontend_parameters *frontend) { struct dvb_frontend_info fe_info; if (ioctl(fe_fd, FE_GET_INFO, &fe_info) < 0) { printf("ioctl FE_GET_INFO failed\n"); return false; } if (fe_info.type != FE_OFDM) { printf("frontend device is not a OFDM (DVB-T) device\n"); return false; } printf ("tuning to %i Hz\n", frontend->frequency); if (ioctl(fe_fd, FE_SET_FRONTEND, frontend) < 0) { printf("ioctl FE_SET_FRONTEND failed\n"); return false; } return true; } bool DVBtcontrol::check_frontend (int fe_fd) { fe_status_t status; uint16_t snr, signal; uint32_t ber, uncorrected_blocks; uint16_t tries; tries = 0; do { ioctl(fe_fd, FE_READ_STATUS, &status); ioctl(fe_fd, FE_READ_SIGNAL_STRENGTH, &signal); ioctl(fe_fd, FE_READ_SNR, &snr); ioctl(fe_fd, FE_READ_BER, &ber); ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks); printf ("."); fflush(stdout); if (status & FE_HAS_LOCK) { return 1; } else tries ++; if (tries == 5) { return 0; } usleep(1000000); } while (1); return 0; } DVBtcontrol::~DVBtcontrol() { //dtor }