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 ([EMAIL PROTECTED])
* 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
[email protected]
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb