All pastes #764405 Raw Edit

DVB tuning

public cpp v1 · immutable
·published 2007-11-07 04:49 UTC
rendered paste body
/** * 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;  }  // 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  rv = ioctl(frontendFD, FE_SET_VOLTAGE, polv ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);  CHECK_RV("Could not set disecq voltage for polarity");  // 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 fec inner  }  // 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 | O_NONBLOCK);  env->ReleaseStringUTFChars(demuxFilename, demuxFilenameC);  if (demuxFD < 0)  {    throwEx(env, "Could not open de-multiplexer device");    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;  int 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);}