I'm trying to write a DVB recording application in Java. I chose JNI and a small native C/C++ function for tuning. However, I can't get tuning to work - I get no tuning lock and nothing on dvr either. As a test, I also copied the szap code verbatim into my file and just called zap_to() instead of my code, and it did not work either. Plain szap on commandline works. This suggests JVM/JNI as culprit, but dvbcentral also uses JNI and it seems to work (at least for its author, haven't tried myself). Does anybody have an idea what's going on? I suspect I'm just doing *something* wrong, but I have no idea what, and no targetted way (like error messages) to find out. Source attached. Hints appreciated. Thanks! Ben
/** * DVB card access on the OS level (system function ioctl()), to tune. * * This needs to happen in C/C++, because ioctl() is not accessible from Java. * This implements the JNI library libzeipisdvbtune.so, a native C++ library * accessible from Java. It implements the |native| methods from the * org.bucksch.zeipis.recorder.DVBTunerNativeJNILinux Java class. * We do as little as possible in C++. */ #include "DVBTunerNativeJNILinux.h" #include <sys/ioctl.h> #include <linux/dvb/frontend.h> #include <linux/dvb/dmx.h> #include <fcntl.h> #include <iostream> void throwEx(JNIEnv* env, const char* message) { jclass eClass = env->FindClass("org/bucksch/zeipis/recorder/CantUseTVCard"); if (eClass == 0) // can't find exception class; unexpected return; env->ThrowNew(eClass, message); } #define CHECK_RV(message) \ if (rv < 0) \ { \ throwEx(env, message); \ close(frontendFD); \ return -1; \ } /** * Called with e.g. "/dev/dvb/adapter0/frontend0", false, 12187000, false, 27500000 (=VOX in Germany) */ JNIEXPORT jint JNICALL Java_org_bucksch_zeipis_recorder_DVBTunerNativeJNILinux_tuneToNative (JNIEnv* env, jobject self, jstring frontendFilename, jboolean dvbs2, jint frequency, jboolean polv, jint symbolrate) { // Open frontend device const char* frontendFilenameC = env->GetStringUTFChars(frontendFilename, 0); int frontendFD = open(frontendFilenameC, O_RDWR | O_NONBLOCK); env->ReleaseStringUTFChars(frontendFilename, frontendFilenameC); if (frontendFD < 0) { throwEx(env, "Can't get info from device"); return -1; } /* from szap // Remove stale events struct dvb_frontend_event ev; while (ioctl(frontendFD, FE_GET_EVENT, &ev) >= 0) ; */ // Get info from device int rv; dvb_frontend_info info; rv = ioctl(frontendFD, FE_GET_INFO, &info); CHECK_RV("Can't get info from device"); #ifdef FE_GET_EXTENDED_INFO dvb_fe_caps_extended info2; if (dvbs2 && info.caps & FE_HAS_EXTENDED_INFO) // TODO { rv = ioctl(frontendFD, FE_GET_EXTENDED_INFO, &info2); CHECK_RV("Can't get extended info from device"); if (info2.modulations & MOD_8PSK) { // set card to DVB-S2 mode rv = ioctl(frontendFD, FE_SET_STANDARD, FE_DVB_S2) CHECK_RV("Failed to set card to DVB-S2 mode"); // get new info rv = ioctl(frontendFD, FE_GET_INFO, &info); CHECK_RV("Can't get info from device after setting to DVB-S2 mode"); } } #endif // Disecq int sat_no = 0; bool hiband = false; // LNB config from szap // Universal LNB const int lnb_low_val = 9750; const int lnb_high_val = 10600; const int lnb_switch_val = 11700; if (lnb_switch_val && lnb_high_val && frequency >= lnb_switch_val) hiband = true; if (hiband) frequency = frequency - lnb_high_val; else { if (frequency < lnb_low_val) frequency = lnb_low_val - frequency; else frequency = frequency - lnb_low_val; } rv = ioctl(frontendFD, FE_SET_TONE, SEC_TONE_OFF); CHECK_RV("Cound not turn disecq tone"); rv = ioctl(frontendFD, FE_SET_VOLTAGE, polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18); CHECK_RV("Could not set disecq voltage for polarity"); usleep(15 * 1000); rv = ioctl(frontendFD, FE_SET_TONE, SEC_TONE_OFF); CHECK_RV("Cound not turn off disecq tone"); usleep(15 * 1000); struct dvb_diseqc_master_cmd disecq_cmd = {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}; disecq_cmd.msg[3] = 0xf0 | (((sat_no * 4) & 0x0f) | (hiband ? 1 : 0) | (polv ? 0 : 2)); rv = ioctl(frontendFD, FE_DISEQC_SEND_MASTER_CMD, &disecq_cmd); CHECK_RV("Cound send disecq master command"); usleep(15 * 1000); rv = ioctl(frontendFD, FE_DISEQC_SEND_BURST, (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A); CHECK_RV("Cound set satellite on disecq"); usleep(15 * 1000); rv = ioctl(frontendFD, FE_SET_TONE, hiband ? SEC_TONE_ON : SEC_TONE_OFF); CHECK_RV("Cound set disecq tone"); // TODO diseqc power on? // TODO more diseqc? // CAM start // TODO // Put tuning data into struct #ifdef FE_GET_EXTENDED_INFO #define dvb_fe_params dvb_frontend_parameters_new #else #define dvb_fe_params dvb_frontend_parameters #endif dvb_fe_params p; // DVB-S p.frequency = frequency; p.u.qpsk.symbol_rate = symbolrate / 1000; // TODO inversion p.inversion = INVERSION_AUTO; if (info.caps & FE_CAN_FEC_AUTO) p.u.qpsk.fec_inner = FEC_AUTO; else { rv = -1; CHECK_RV("Card needs to support FEC INNER AUTO (TODO support setting it)"); } // TODO DVB-T // TODO DVB-C // Tuning #ifdef FE_GET_EXTENDED_INFO if (dvbs2) rv = ioctl(frontendFD, FE_SET_FRONTEND2, &p); else #endif rv = ioctl(frontendFD, FE_SET_FRONTEND, &p); CHECK_RV("Setting tuning params failed"); // Wait for lock bool haveLock = false; int loops = 0; while (!haveLock && loops++ < 50) // 5s { fe_status_t status; rv = ioctl(frontendFD, FE_READ_STATUS, &status); CHECK_RV("Reading status failed after setting tuning param"); haveLock = status & FE_HAS_LOCK; usleep(100000); // 0.1s } if (!haveLock) { uint16_t snr, sig; rv = ioctl(frontendFD, FE_READ_SIGNAL_STRENGTH, &sig); rv = ioctl(frontendFD, FE_READ_SNR, &snr); std::cout << "Tuning failed. Signal strength " << sig << ", Signal/noise ratio " << snr << "%" << std::endl; // TODO rv = -1; CHECK_RV("Tuning failed"); } return frontendFD; } JNIEXPORT jint JNICALL Java_org_bucksch_zeipis_recorder_DVBTunerNativeJNILinux_openDemuxNative (JNIEnv* env, jobject self, jstring demuxFilename, jint pid) { // Open demux device const char* demuxFilenameC = env->GetStringUTFChars(demuxFilename, 0); int demuxFD = open(demuxFilenameC, O_RDWR); env->ReleaseStringUTFChars(demuxFilename, demuxFilenameC); if (demuxFD < 0) { throwEx(env, "Could not open de-multiplexer device"); return -1; } // Buffer size From szap TODO needed? int rv = ioctl(demuxFD, DMX_SET_BUFFER_SIZE, 64 * 1024); if (rv < 0) { throwEx(env, "Setting buffer size for PID filter failed"); close(demuxFD); return -1; } // Set PID struct dmx_pes_filter_params pesfilter; pesfilter.pid = pid; pesfilter.input = DMX_IN_FRONTEND; pesfilter.output = DMX_OUT_TS_TAP; pesfilter.pes_type = DMX_PES_OTHER; // TODO DMX_PES_VIDEO, DMX_PES_AUDIO? pesfilter.flags = DMX_IMMEDIATE_START; rv = ioctl(demuxFD, DMX_SET_PES_FILTER, &pesfilter); if (rv < 0) { throwEx(env, "Could not set PID"); close(demuxFD); return -1; } return demuxFD; } JNIEXPORT void JNICALL Java_org_bucksch_zeipis_recorder_DVBTunerNativeJNILinux_closeNative (JNIEnv* env, jobject self, jint fd) { close(fd); }
/** * DVB card access on the OS level (system function ioctl()), to tune. * * This needs to happen in C/C++, because ioctl() is not accessible from Java. * This implements the JNI library libzeipisdvbtune.so, a native C++ library * accessible from Java. It implements the |native| methods from the * org.bucksch.zeipis.recorder.DVBTunerNativeJNILinux Java class. * We do as little as possible in C++. */ #include "DVBTunerNativeJNILinux.h" #include <sys/ioctl.h> #include <linux/dvb/frontend.h> #include <linux/dvb/dmx.h> #include <fcntl.h> #include <iostream> void throwEx(JNIEnv* env, const char* message) { jclass eClass = env->FindClass("org/bucksch/zeipis/recorder/CantUseTVCard"); if (eClass == 0) // can't find exception class; unexpected return; env->ThrowNew(eClass, message); } #define CHECK_RV(message) \ if (rv < 0) \ { \ throwEx(env, message); \ close(frontendFD); \ return -1; \ } static int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux, unsigned int sat_no, unsigned int freq, unsigned int pol, unsigned int sr, unsigned int vpid, unsigned int apid, int sid, int dvr, int rec_psi, int bypass); /** * Called with e.g. "/dev/dvb/adapter0/frontend0", false, 12187000, false, 27500000 (=VOX in Germany) */ JNIEXPORT jint JNICALL Java_org_bucksch_zeipis_recorder_DVBTunerNativeJNILinux_tuneToNative (JNIEnv* env, jobject self, jstring frontendFilename, jboolean dvbs2, jint frequency, jboolean polv, jint symbolrate) { printf("sat %u, frequency = %u MHz %c, symbolrate %u, " "vpid = 0x%04x, apid = 0x%04x sid = 0x%04x\n", 0, frequency / 1000, polv ? 'V' : 'H', symbolrate, 0x00a7, 0x0088, 0x2f1c); zap_to(0, 0, 0, 0, frequency, polv ? 1 : 0, symbolrate, 0x00a7, 0x0088, 0x2f1c, 1, 0, 0); return -1; } JNIEXPORT jint JNICALL Java_org_bucksch_zeipis_recorder_DVBTunerNativeJNILinux_openDemuxNative (JNIEnv* env, jobject self, jstring demuxFilename, jint pid) { return -1; } JNIEXPORT void JNICALL Java_org_bucksch_zeipis_recorder_DVBTunerNativeJNILinux_closeNative (JNIEnv* env, jobject self, jint fd) { if (fd < 0) return; close(fd); } /* szap -- simple zapping tool for the Linux DVB API * * szap operates on VDR (http://www.cadsoft.de/people/kls/vdr/index.htm) * satellite channel lists (e.g. from http://www.dxandy.de/cgi-bin/dvbchan.pl). * szap assumes you have a "Universal LNB" (i.e. with LOFs 9750/10600 MHz). * * Compilation: `gcc -Wall -I../../ost/include -O2 szap.c -o szap` * or, if your DVB driver is in the kernel source tree: * `gcc -Wall -DDVB_IN_KERNEL -O2 szap.c -o szap` * * Copyright (C) 2001 Johannes Stezenbach (js@xxxxxxxxxxxxxx) * for convergence integrated media * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ struct lnb_types_st { char *name; char **desc; unsigned long low_val; unsigned long high_val; /* zero indicates no hiband */ unsigned long switch_val; /* zero indicates no hiband */ }; /* Enumerate through standard types of LNB's until NULL returned. * Increment curno each time */ struct lnb_types_st * lnb_enum(int curno); /* Decode an lnb type, for example given on a command line * If alpha and standard type, e.g. "Universal" then match that * otherwise low[,high[,switch]] */ int lnb_decode(char *str, struct lnb_types_st *lnbp); #include <stdlib.h> #include <string.h> #include <ctype.h> static char *univ_desc[] = { "Europe", "10800 to 11800 MHz and 11600 to 12700 Mhz", "Dual LO, loband 9750, hiband 10600 MHz", (char *)NULL }; static char *dbs_desc[] = { "Expressvu, North America", "12200 to 12700 MHz", "Single LO, 11250 MHz", (char *)NULL }; static char *standard_desc[] = { "10945 to 11450 Mhz", "Single LO, 10000 Mhz", (char *)NULL }; static char *enhan_desc[] = { "Astra", "10700 to 11700 MHz", "Single LO, 9750 MHz", (char *)NULL }; static char *cband_desc[] = { "Big Dish", "3700 to 4200 MHz", "Single LO, 5150 Mhz", (char *)NULL }; static struct lnb_types_st lnbs[] = { {"UNIVERSAL", univ_desc, 9750, 10600, 11700 }, {"DBS", dbs_desc, 11250, 0, 0 }, {"STANDARD", standard_desc, 10000, 0, 0 }, {"ENHANCED", enhan_desc, 9750, 0, 0 }, {"C-BAND", cband_desc, 5150, 0, 0 } }; /* Enumerate through standard types of LNB's until NULL returned. * Increment curno each time */ struct lnb_types_st * lnb_enum(int curno) { if (curno >= (int) (sizeof(lnbs) / sizeof(lnbs[0]))) return (struct lnb_types_st *)NULL; return &lnbs[curno]; } /* Decode an lnb type, for example given on a command line * If alpha and standard type, e.g. "Universal" then match that * otherwise low[,high[,switch]] */ int lnb_decode(char *str, struct lnb_types_st *lnbp) { int i; char *cp, *np; memset(lnbp, 0, sizeof(*lnbp)); cp = str; while(*cp && isspace(*cp)) cp++; if (isalpha(*cp)) { for (i = 0; i < (int)(sizeof(lnbs) / sizeof(lnbs[0])); i++) { if (!strcasecmp(lnbs[i].name, cp)) { *lnbp = lnbs[i]; return 1; } } return -1; } if (*cp == '\0' || !isdigit(*cp)) return -1; lnbp->low_val = strtoul(cp, &np, 0); if (lnbp->low_val == 0) return -1; cp = np; while(*cp && (isspace(*cp) || *cp == ',')) cp++; if (*cp == '\0') return 1; if (!isdigit(*cp)) return -1; lnbp->high_val = strtoul(cp, &np, 0); cp = np; while(*cp && (isspace(*cp) || *cp == ',')) cp++; if (*cp == '\0') return 1; if (!isdigit(*cp)) return -1; lnbp->switch_val = strtoul(cp, NULL, 0); return 1; } #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <string.h> #include <errno.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/poll.h> #include <sys/param.h> #include <fcntl.h> #include <time.h> #include <unistd.h> #include <stdint.h> #include <sys/time.h> #include <linux/dvb/frontend.h> #include <linux/dvb/dmx.h> #include <linux/dvb/audio.h> #ifndef TRUE #define TRUE (1==1) #endif #ifndef FALSE #define FALSE (1==0) #endif /* location of channel list file */ #define CHANNEL_FILE "channels.conf" /* one line of the VDR channel file has the following format: * ^name:frequency_MHz:polarization:sat_no:symbolrate:vpid:apid:?:service_id$ */ #define FRONTENDDEVICE "/dev/dvb/adapter%d/frontend%d" #define DEMUXDEVICE "/dev/dvb/adapter%d/demux%d" #define AUDIODEVICE "/dev/dvb/adapter%d/audio%d" static struct lnb_types_st lnb_type; static int exit_after_tuning; static int interactive; static int set_demux(int dmxfd, int pid, dmx_pes_type_t pes_type, int dvr) { struct dmx_pes_filter_params pesfilter; if (pid < 0 || pid >= 0x1fff) /* ignore this pid to allow radio services */ return TRUE; if (dvr) { int buffersize = 64 * 1024; if (ioctl(dmxfd, DMX_SET_BUFFER_SIZE, buffersize) == -1) perror("DMX_SET_BUFFER_SIZE failed"); } pesfilter.pid = pid; pesfilter.input = DMX_IN_FRONTEND; pesfilter.output = dvr ? DMX_OUT_TS_TAP : DMX_OUT_DECODER; pesfilter.pes_type = pes_type; pesfilter.flags = DMX_IMMEDIATE_START; if (ioctl(dmxfd, DMX_SET_PES_FILTER, &pesfilter) == -1) { fprintf(stderr, "DMX_SET_PES_FILTER failed " "(PID = 0x%04x): %d %m\n", pid, errno); return FALSE; } return TRUE; } int get_pmt_pid(char *dmxdev, int sid) { int patfd, count; int pmt_pid = 0; int patread = 0; int section_length; unsigned char buft[4096]; unsigned char *buf = buft; struct dmx_sct_filter_params f; memset(&f, 0, sizeof(f)); f.pid = 0; f.filter.filter[0] = 0x00; f.filter.mask[0] = 0xff; f.timeout = 0; f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC; if ((patfd = open(dmxdev, O_RDWR)) < 0) { perror("openening pat demux failed"); return -1; } if (ioctl(patfd, DMX_SET_FILTER, &f) == -1) { perror("ioctl DMX_SET_FILTER failed"); close(patfd); return -1; } while (!patread){ if (((count = read(patfd, buf, sizeof(buft))) < 0) && errno == EOVERFLOW) count = read(patfd, buf, sizeof(buft)); if (count < 0) { perror("read_sections: read error"); close(patfd); return -1; } section_length = ((buf[1] & 0x0f) << 8) | buf[2]; if (count != section_length + 3) continue; buf += 8; section_length -= 8; patread = 1; /* assumes one section contains the whole pat */ while (section_length > 0) { int service_id = (buf[0] << 8) | buf[1]; if (service_id == sid) { pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3]; section_length = 0; } buf += 4; section_length -= 4; } } close(patfd); return pmt_pid; } struct diseqc_cmd { struct dvb_diseqc_master_cmd cmd; uint32_t wait; }; void diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd *cmd, fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b) { if (ioctl(fd, FE_SET_TONE, SEC_TONE_OFF) == -1) perror("FE_SET_TONE failed"); if (ioctl(fd, FE_SET_VOLTAGE, v) == -1) perror("FE_SET_VOLTAGE failed"); usleep(15 * 1000); if (ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &cmd->cmd) == -1) perror("FE_DISEQC_SEND_MASTER_CMD failed"); usleep(cmd->wait * 1000); usleep(15 * 1000); if (ioctl(fd, FE_DISEQC_SEND_BURST, b) == -1) perror("FE_DISEQC_SEND_BURST failed"); usleep(15 * 1000); if (ioctl(fd, FE_SET_TONE, t) == -1) perror("FE_SET_TONE failed"); } /* digital satellite equipment control, * specification is available from http://www.eutelsat.com/ */ static int diseqc(int secfd, int sat_no, int pol_vert, int hi_band) { struct diseqc_cmd cmd = { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 }; /* param: high nibble: reset bits, low nibble set bits, * bits are: option, position, polarizaion, band */ cmd.cmd.msg[3] = 0xf0 | (((sat_no * 4) & 0x0f) | (hi_band ? 1 : 0) | (pol_vert ? 0 : 2)); diseqc_send_msg(secfd, pol_vert ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18, &cmd, hi_band ? SEC_TONE_ON : SEC_TONE_OFF, (sat_no / 4) % 2 ? SEC_MINI_B : SEC_MINI_A); return TRUE; } static int do_tune(int fefd, unsigned int ifreq, unsigned int sr) { struct dvb_frontend_parameters tuneto; struct dvb_frontend_event ev; /* discard stale QPSK events */ while (1) { if (ioctl(fefd, FE_GET_EVENT, &ev) == -1) break; } tuneto.frequency = ifreq; tuneto.inversion = INVERSION_AUTO; tuneto.u.qpsk.symbol_rate = sr; tuneto.u.qpsk.fec_inner = FEC_AUTO; if (ioctl(fefd, FE_SET_FRONTEND, &tuneto) == -1) { perror("FE_SET_FRONTEND failed"); return FALSE; } return TRUE; } static int check_frontend (int fe_fd, int dvr) { (void)dvr; fe_status_t status; uint16_t snr, signal; uint32_t ber, uncorrected_blocks; int timeout = 0; do { if (ioctl(fe_fd, FE_READ_STATUS, &status) == -1) perror("FE_READ_STATUS failed"); /* some frontends might not support all these ioctls, thus we * avoid printing errors */ if (ioctl(fe_fd, FE_READ_SIGNAL_STRENGTH, &signal) == -1) signal = -2; if (ioctl(fe_fd, FE_READ_SNR, &snr) == -1) snr = -2; if (ioctl(fe_fd, FE_READ_BER, &ber) == -1) ber = -2; if (ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) == -1) uncorrected_blocks = -2; printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ", status, signal, snr, ber, uncorrected_blocks); if (status & FE_HAS_LOCK) printf("FE_HAS_LOCK"); printf("\n"); if (exit_after_tuning && ((status & FE_HAS_LOCK) || (++timeout >= 10))) break; usleep(1000000); } while (1); return 0; } static int zap_to(unsigned int adapter, unsigned int frontend, unsigned int demux, unsigned int sat_no, unsigned int freq, unsigned int pol, unsigned int sr, unsigned int vpid, unsigned int apid, int sid, int dvr, int rec_psi, int bypass) { char fedev[128], dmxdev[128], auddev[128]; static int fefd, dmxfda, dmxfdv, audiofd = -1, patfd, pmtfd; int pmtpid; uint32_t ifreq; int hiband, result; static struct dvb_frontend_info fe_info; if (!fefd) { snprintf(fedev, sizeof(fedev), FRONTENDDEVICE, adapter, frontend); snprintf(dmxdev, sizeof(dmxdev), DEMUXDEVICE, adapter, demux); snprintf(auddev, sizeof(auddev), AUDIODEVICE, adapter, demux); printf("using '%s' and '%s'\n", fedev, dmxdev); if ((fefd = open(fedev, O_RDWR | O_NONBLOCK)) < 0) { perror("opening frontend failed"); return FALSE; } result = ioctl(fefd, FE_GET_INFO, &fe_info); if (result < 0) { perror("ioctl FE_GET_INFO failed"); close(fefd); return FALSE; } if (fe_info.type != FE_QPSK) { fprintf(stderr, "frontend device is not a QPSK (DVB-S) device!\n"); close(fefd); return FALSE; } if ((dmxfdv = open(dmxdev, O_RDWR)) < 0) { perror("opening video demux failed"); close(fefd); return FALSE; } if ((dmxfda = open(dmxdev, O_RDWR)) < 0) { perror("opening audio demux failed"); close(fefd); return FALSE; } if (dvr == 0) /* DMX_OUT_DECODER */ audiofd = open(auddev, O_RDWR); if (rec_psi){ if ((patfd = open(dmxdev, O_RDWR)) < 0) { perror("opening pat demux failed"); close(audiofd); close(dmxfda); close(dmxfdv); close(fefd); return FALSE; } if ((pmtfd = open(dmxdev, O_RDWR)) < 0) { perror("opening pmt demux failed"); close(patfd); close(audiofd); close(dmxfda); close(dmxfdv); close(fefd); return FALSE; } } } hiband = 0; if (lnb_type.switch_val && lnb_type.high_val && freq >= lnb_type.switch_val) hiband = 1; if (hiband) ifreq = freq - lnb_type.high_val; else { if (freq < lnb_type.low_val) ifreq = lnb_type.low_val - freq; else ifreq = freq - lnb_type.low_val; } result = FALSE; if (diseqc(fefd, sat_no, pol, hiband)) if (do_tune(fefd, ifreq, sr)) if (set_demux(dmxfdv, vpid, DMX_PES_VIDEO, dvr)) if (audiofd >= 0) (void)ioctl(audiofd, AUDIO_SET_BYPASS_MODE, bypass); if (set_demux(dmxfda, apid, DMX_PES_AUDIO, dvr)) { if (rec_psi) { pmtpid = get_pmt_pid(dmxdev, sid); if (pmtpid < 0) { result = FALSE; } if (pmtpid == 0) { fprintf(stderr,"couldn't find pmt-pid for sid %04x\n",sid); result = FALSE; } if (set_demux(patfd, 0, DMX_PES_OTHER, dvr)) if (set_demux(pmtfd, pmtpid, DMX_PES_OTHER, dvr)) result = TRUE; } else { result = TRUE; } } check_frontend (fefd, dvr); if (!interactive) { close(patfd); close(pmtfd); if (audiofd >= 0) close(audiofd); close(dmxfda); close(dmxfdv); close(fefd); } return result; }
_______________________________________________ linux-dvb mailing list linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb