mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
The actual tuning is now done in a separate thread
This commit is contained in:
parent
2d2369fca0
commit
b9422baff2
@ -441,6 +441,7 @@ Oliver Endriss <o.endriss@gmx.de>
|
||||
|
||||
Reinhard Walter Buchner <rw.buchner@freenet.de>
|
||||
for adding some satellites to 'sources.conf'
|
||||
for his help in testing tuning with "Motor-DiSEqC"
|
||||
|
||||
Lauri Tischler <lauri.tischler@efore.fi>
|
||||
for helping to test and debug the new channel source and DiSEqC handling
|
||||
|
6
HISTORY
6
HISTORY
@ -1845,3 +1845,9 @@ Video Disk Recorder Revision History
|
||||
- Improved handling of repeated remote keys.
|
||||
- The RCU now only sets the channel number display when there are no incoming remote
|
||||
control keys, which improves reaction on repeated keys.
|
||||
- The actual tuning is now done in a separate thread, which makes zapping through the
|
||||
channels a lot faster and no longer gets stuck on channels that don't broadcast.
|
||||
This also makes "Motor-DiSEqC" work (thanks to Reinhard Walter Buchner for his help
|
||||
in testing this). Since switching channels now no longer explicitly waits for a
|
||||
channel lock in the foreground thread, the "panic level" mechanism is no longer
|
||||
used (maybe we don't need it nay more, anyway).
|
||||
|
25
diseqc.c
25
diseqc.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: diseqc.c 1.1 2002/10/05 13:54:32 kls Exp $
|
||||
* $Id: diseqc.c 1.2 2002/12/07 13:44:56 kls Exp $
|
||||
*/
|
||||
|
||||
#include "diseqc.h"
|
||||
@ -16,7 +16,6 @@
|
||||
cDiseqc::cDiseqc(void)
|
||||
{
|
||||
commands = NULL;
|
||||
currentAction = NULL;;
|
||||
parsing = false;
|
||||
numCodes = 0;
|
||||
}
|
||||
@ -39,11 +38,11 @@ bool cDiseqc::Parse(const char *s)
|
||||
polarization = toupper(polarization);
|
||||
if (polarization == 'V' || polarization == 'H') {
|
||||
parsing = true;
|
||||
bool Start = true;
|
||||
while (Execute(Start) != daNone)
|
||||
Start = false;
|
||||
char *CurrentAction = NULL;
|
||||
while (Execute(&CurrentAction) != daNone)
|
||||
;
|
||||
parsing = false;
|
||||
result = !commands || currentAction && !*currentAction;
|
||||
result = !commands || !*CurrentAction;
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: unknown polarization '%c'", polarization);
|
||||
@ -101,12 +100,12 @@ char *cDiseqc::Codes(char *s)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cDiseqc::eDiseqcActions cDiseqc::Execute(bool Start)
|
||||
cDiseqc::eDiseqcActions cDiseqc::Execute(char **CurrentAction)
|
||||
{
|
||||
if (Start)
|
||||
currentAction = commands;
|
||||
while (currentAction && *currentAction) {
|
||||
switch (*currentAction++) {
|
||||
if (!*CurrentAction)
|
||||
*CurrentAction = commands;
|
||||
while (*CurrentAction && **CurrentAction) {
|
||||
switch (*(*CurrentAction)++) {
|
||||
case ' ': break;
|
||||
case 't': return daToneOff;
|
||||
case 'T': return daToneOn;
|
||||
@ -114,8 +113,8 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(bool Start)
|
||||
case 'V': return daVoltage18;
|
||||
case 'A': return daMiniA;
|
||||
case 'B': return daMiniB;
|
||||
case 'W': currentAction = Wait(currentAction); break;
|
||||
case '[': currentAction = Codes(currentAction); return currentAction ? daCodes : daNone;
|
||||
case 'W': *CurrentAction = Wait(*CurrentAction); break;
|
||||
case '[': *CurrentAction = Codes(*CurrentAction); return *CurrentAction ? daCodes : daNone;
|
||||
default: return daNone;
|
||||
}
|
||||
}
|
||||
|
12
diseqc.h
12
diseqc.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: diseqc.h 1.1 2002/10/05 13:02:52 kls Exp $
|
||||
* $Id: diseqc.h 1.2 2002/12/07 13:54:02 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DISEQC_H
|
||||
@ -31,7 +31,6 @@ private:
|
||||
char polarization;
|
||||
int lof;
|
||||
char *commands;
|
||||
char *currentAction;
|
||||
bool parsing;
|
||||
uchar codes[MaxDiseqcCodes];
|
||||
int numCodes;
|
||||
@ -41,7 +40,14 @@ public:
|
||||
cDiseqc(void);
|
||||
~cDiseqc();
|
||||
bool Parse(const char *s);
|
||||
eDiseqcActions Execute(bool Start = false);
|
||||
eDiseqcActions Execute(char **CurrentAction);
|
||||
// Parses the DiSEqC commands and returns the appropriate action code
|
||||
// with every call. CurrentAction must be the address of a character pointer,
|
||||
// which is initialized to NULL. This pointer is used internally while parsing
|
||||
// the commands and shall not be modified once Execute() has been called with
|
||||
// it. Call Execute() repeatedly (always providing the same CurrentAction pointer)
|
||||
// until it returns daNone. After a successful execution of all commands
|
||||
// *CurrentAction points to the value 0x00.
|
||||
int Source(void) const { return source; }
|
||||
int Slof(void) const { return slof; }
|
||||
char Polarization(void) const { return polarization; }
|
||||
|
355
dvbdevice.c
355
dvbdevice.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 1.37 2002/11/16 12:36:50 kls Exp $
|
||||
* $Id: dvbdevice.c 1.38 2002/12/07 14:50:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -60,8 +60,207 @@ static int DvbOpen(const char *Name, int n, int Mode, bool ReportError = false)
|
||||
return fd;
|
||||
}
|
||||
|
||||
// --- cDvbTuner -------------------------------------------------------------
|
||||
|
||||
class cDvbTuner : public cThread {
|
||||
private:
|
||||
enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked };
|
||||
int fd_frontend;
|
||||
int cardIndex;
|
||||
fe_type_t frontendType;
|
||||
cChannel channel;
|
||||
const char *diseqcCommands;
|
||||
bool active;
|
||||
eTunerStatus tunerStatus;
|
||||
cMutex mutex;
|
||||
cCondVar newSet;
|
||||
bool SetFrontend(void);
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType);
|
||||
virtual ~cDvbTuner();
|
||||
bool IsTunedTo(const cChannel *Channel) const;
|
||||
void Set(const cChannel *Channel);
|
||||
bool Locked(void) { return tunerStatus == tsLocked; }
|
||||
};
|
||||
|
||||
cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType)
|
||||
{
|
||||
fd_frontend = Fd_Frontend;
|
||||
cardIndex = CardIndex;
|
||||
frontendType = FrontendType;
|
||||
diseqcCommands = NULL;
|
||||
active = false;
|
||||
tunerStatus = tsIdle;
|
||||
Start();
|
||||
}
|
||||
|
||||
cDvbTuner::~cDvbTuner()
|
||||
{
|
||||
active = false;
|
||||
tunerStatus = tsIdle;
|
||||
newSet.Broadcast();
|
||||
Cancel(3);
|
||||
}
|
||||
|
||||
bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
|
||||
{
|
||||
return tunerStatus != tsIdle && channel.Source() == Channel->Source() && channel.Frequency() == Channel->Frequency();
|
||||
}
|
||||
|
||||
void cDvbTuner::Set(const cChannel *Channel)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
channel = *Channel;
|
||||
tunerStatus = tsSet;
|
||||
newSet.Broadcast();
|
||||
}
|
||||
|
||||
static unsigned int FrequencyToHz(unsigned int f)
|
||||
{
|
||||
while (f && f < 1000000)
|
||||
f *= 1000;
|
||||
return f;
|
||||
}
|
||||
|
||||
bool cDvbTuner::SetFrontend(void)
|
||||
{
|
||||
dvb_frontend_parameters Frontend;
|
||||
|
||||
memset(&Frontend, 0, sizeof(Frontend));
|
||||
|
||||
switch (frontendType) {
|
||||
case FE_QPSK: { // DVB-S
|
||||
|
||||
unsigned int frequency = channel.Frequency();
|
||||
|
||||
if (Setup.DiSEqC) {
|
||||
cDiseqc *diseqc = Diseqcs.Get(channel.Source(), channel.Frequency(), channel.Polarization());
|
||||
if (diseqc) {
|
||||
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
|
||||
cDiseqc::eDiseqcActions da;
|
||||
for (char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
|
||||
switch (da) {
|
||||
case cDiseqc::daNone: break;
|
||||
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
|
||||
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
|
||||
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
|
||||
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
|
||||
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
|
||||
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
|
||||
case cDiseqc::daCodes: {
|
||||
int n = 0;
|
||||
uchar *codes = diseqc->Codes(n);
|
||||
if (codes) {
|
||||
struct dvb_diseqc_master_cmd cmd;
|
||||
memcpy(cmd.msg, codes, min(n, int(sizeof(cmd.msg))));
|
||||
cmd.msg_len = n;
|
||||
CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
diseqcCommands = diseqc->Commands();
|
||||
}
|
||||
frequency -= diseqc->Lof();
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int tone = SEC_TONE_OFF;
|
||||
|
||||
if (frequency < (unsigned int)Setup.LnbSLOF) {
|
||||
frequency -= Setup.LnbFrequLo;
|
||||
tone = SEC_TONE_OFF;
|
||||
}
|
||||
else {
|
||||
frequency -= Setup.LnbFrequHi;
|
||||
tone = SEC_TONE_ON;
|
||||
}
|
||||
int volt = (channel.Polarization() == 'v' || channel.Polarization() == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
|
||||
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
|
||||
CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
|
||||
}
|
||||
|
||||
Frontend.frequency = frequency * 1000UL;
|
||||
Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
|
||||
Frontend.u.qpsk.symbol_rate = channel.Srate() * 1000UL;
|
||||
Frontend.u.qpsk.fec_inner = fe_code_rate_t(channel.CoderateH());
|
||||
}
|
||||
break;
|
||||
case FE_QAM: { // DVB-C
|
||||
|
||||
// Frequency and symbol rate:
|
||||
|
||||
Frontend.frequency = FrequencyToHz(channel.Frequency());
|
||||
Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
|
||||
Frontend.u.qam.symbol_rate = channel.Srate() * 1000UL;
|
||||
Frontend.u.qam.fec_inner = fe_code_rate_t(channel.CoderateH());
|
||||
Frontend.u.qam.modulation = fe_modulation_t(channel.Modulation());
|
||||
}
|
||||
break;
|
||||
case FE_OFDM: { // DVB-T
|
||||
|
||||
// Frequency and OFDM paramaters:
|
||||
|
||||
Frontend.frequency = FrequencyToHz(channel.Frequency());
|
||||
Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
|
||||
Frontend.u.ofdm.bandwidth = fe_bandwidth_t(channel.Bandwidth());
|
||||
Frontend.u.ofdm.code_rate_HP = fe_code_rate_t(channel.CoderateH());
|
||||
Frontend.u.ofdm.code_rate_LP = fe_code_rate_t(channel.CoderateL());
|
||||
Frontend.u.ofdm.constellation = fe_modulation_t(channel.Modulation());
|
||||
Frontend.u.ofdm.transmission_mode = fe_transmit_mode_t(channel.Transmission());
|
||||
Frontend.u.ofdm.guard_interval = fe_guard_interval_t(channel.Guard());
|
||||
Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(channel.Hierarchy());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
|
||||
return false;
|
||||
}
|
||||
if (ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend) < 0) {
|
||||
esyslog("ERROR: frontend %d: %m", cardIndex);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void cDvbTuner::Action(void)
|
||||
{
|
||||
dsyslog("tuner thread started on device %d (pid=%d)", cardIndex + 1, getpid());
|
||||
active = true;
|
||||
while (active) {
|
||||
cMutexLock MutexLock(&mutex);
|
||||
if (tunerStatus == tsSet)
|
||||
tunerStatus = SetFrontend() ? tsTuned : tsIdle;
|
||||
if (tunerStatus == tsTuned) {
|
||||
fe_status_t status = fe_status_t(0);
|
||||
CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status));
|
||||
if (status & FE_HAS_LOCK)
|
||||
tunerStatus = tsLocked;
|
||||
}
|
||||
dvb_frontend_event event;
|
||||
if (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0) {
|
||||
if (tunerStatus != tsIdle && event.status & FE_REINIT) {
|
||||
tunerStatus = tsSet;
|
||||
esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
newSet.TimedWait(mutex, 1000);
|
||||
}
|
||||
dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
|
||||
}
|
||||
|
||||
// --- cDvbDevice ------------------------------------------------------------
|
||||
|
||||
cDvbDevice::cDvbDevice(int n)
|
||||
{
|
||||
dvbTuner = NULL;
|
||||
frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
|
||||
siProcessor = NULL;
|
||||
spuDecoder = NULL;
|
||||
@ -69,7 +268,7 @@ cDvbDevice::cDvbDevice(int n)
|
||||
|
||||
// Devices that are present on all card types:
|
||||
|
||||
fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
|
||||
int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
|
||||
|
||||
// Devices that are only present on cards with decoders:
|
||||
|
||||
@ -90,8 +289,10 @@ cDvbDevice::cDvbDevice(int n)
|
||||
if (fd_frontend >= 0) {
|
||||
dvb_frontend_info feinfo;
|
||||
siProcessor = new cSIProcessor(DvbName(DEV_DVB_DEMUX, n));
|
||||
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0)
|
||||
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
|
||||
frontendType = feinfo.type;
|
||||
dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
|
||||
}
|
||||
else
|
||||
LOG_ERROR;
|
||||
}
|
||||
@ -99,16 +300,13 @@ cDvbDevice::cDvbDevice(int n)
|
||||
esyslog("ERROR: can't open DVB device %d", n);
|
||||
|
||||
aPid1 = aPid2 = 0;
|
||||
|
||||
source = -1;
|
||||
frequency = -1;
|
||||
diseqcCommands = NULL;
|
||||
}
|
||||
|
||||
cDvbDevice::~cDvbDevice()
|
||||
{
|
||||
delete spuDecoder;
|
||||
delete siProcessor;
|
||||
delete dvbTuner;
|
||||
// We're not explicitly closing any device files here, since this sometimes
|
||||
// caused segfaults. Besides, the program is about to terminate anyway...
|
||||
}
|
||||
@ -322,11 +520,6 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDvbDevice::IsTunedTo(const cChannel *Channel) const
|
||||
{
|
||||
return source == Channel->Source() && frequency == Channel->Frequency();
|
||||
}
|
||||
|
||||
bool cDvbDevice::ProvidesSource(int Source) const
|
||||
{
|
||||
int type = Source & cSource::st_Mask;
|
||||
@ -346,7 +539,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
|
||||
if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel->Ca())) {
|
||||
#ifdef DO_MULTIPLE_RECORDINGS
|
||||
if (Receiving()) {
|
||||
if (IsTunedTo(Channel)) {
|
||||
if (dvbTuner->IsTunedTo(Channel)) {
|
||||
needsDetachReceivers = false;
|
||||
if (!HasPid(Channel->Vpid())) {
|
||||
if (Channel->Ca() > CACONFBASE) {
|
||||
@ -375,18 +568,11 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
|
||||
return result;
|
||||
}
|
||||
|
||||
static unsigned int FrequencyToHz(unsigned int f)
|
||||
{
|
||||
while (f && f < 1000000)
|
||||
f *= 1000;
|
||||
return f;
|
||||
}
|
||||
|
||||
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
{
|
||||
bool IsEncrypted = Channel->Ca() > CACONFBASE;
|
||||
|
||||
bool DoTune = !IsTunedTo(Channel);
|
||||
bool DoTune = !dvbTuner->IsTunedTo(Channel);
|
||||
|
||||
bool TurnOffLivePIDs = HasDecoder()
|
||||
&& (DoTune
|
||||
@ -436,136 +622,15 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
}
|
||||
|
||||
if (DoTune) {
|
||||
|
||||
dvb_frontend_parameters Frontend;
|
||||
|
||||
memset(&Frontend, 0, sizeof(Frontend));
|
||||
|
||||
switch (frontendType) {
|
||||
case FE_QPSK: { // DVB-S
|
||||
|
||||
unsigned int frequency = Channel->Frequency();
|
||||
|
||||
if (Setup.DiSEqC) {
|
||||
cDiseqc *diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
|
||||
if (diseqc) {
|
||||
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
|
||||
cDiseqc::eDiseqcActions da;
|
||||
for (bool Start = true; (da = diseqc->Execute(Start)) != cDiseqc::daNone; Start = false) {
|
||||
switch (da) {
|
||||
case cDiseqc::daNone: break;
|
||||
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
|
||||
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
|
||||
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
|
||||
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
|
||||
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
|
||||
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
|
||||
case cDiseqc::daCodes: {
|
||||
int n = 0;
|
||||
uchar *codes = diseqc->Codes(n);
|
||||
if (codes) {
|
||||
struct dvb_diseqc_master_cmd cmd;
|
||||
memcpy(cmd.msg, codes, min(n, int(sizeof(cmd.msg))));
|
||||
cmd.msg_len = n;
|
||||
CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
diseqcCommands = diseqc->Commands();
|
||||
}
|
||||
frequency -= diseqc->Lof();
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: no DiSEqC parameters found for channel %d", Channel->Number());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int tone = SEC_TONE_OFF;
|
||||
|
||||
if (frequency < (unsigned int)Setup.LnbSLOF) {
|
||||
frequency -= Setup.LnbFrequLo;
|
||||
tone = SEC_TONE_OFF;
|
||||
}
|
||||
else {
|
||||
frequency -= Setup.LnbFrequHi;
|
||||
tone = SEC_TONE_ON;
|
||||
}
|
||||
int volt = (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
|
||||
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
|
||||
CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
|
||||
}
|
||||
|
||||
Frontend.frequency = frequency * 1000UL;
|
||||
Frontend.inversion = fe_spectral_inversion_t(Channel->Inversion());
|
||||
Frontend.u.qpsk.symbol_rate = Channel->Srate() * 1000UL;
|
||||
Frontend.u.qpsk.fec_inner = fe_code_rate_t(Channel->CoderateH());
|
||||
}
|
||||
break;
|
||||
case FE_QAM: { // DVB-C
|
||||
|
||||
// Frequency and symbol rate:
|
||||
|
||||
Frontend.frequency = FrequencyToHz(Channel->Frequency());
|
||||
Frontend.inversion = fe_spectral_inversion_t(Channel->Inversion());
|
||||
Frontend.u.qam.symbol_rate = Channel->Srate() * 1000UL;
|
||||
Frontend.u.qam.fec_inner = fe_code_rate_t(Channel->CoderateH());
|
||||
Frontend.u.qam.modulation = fe_modulation_t(Channel->Modulation());
|
||||
}
|
||||
break;
|
||||
case FE_OFDM: { // DVB-T
|
||||
|
||||
// Frequency and OFDM paramaters:
|
||||
|
||||
Frontend.frequency = FrequencyToHz(Channel->Frequency());
|
||||
Frontend.inversion = fe_spectral_inversion_t(Channel->Inversion());
|
||||
Frontend.u.ofdm.bandwidth = fe_bandwidth_t(Channel->Bandwidth());
|
||||
Frontend.u.ofdm.code_rate_HP = fe_code_rate_t(Channel->CoderateH());
|
||||
Frontend.u.ofdm.code_rate_LP = fe_code_rate_t(Channel->CoderateL());
|
||||
Frontend.u.ofdm.constellation = fe_modulation_t(Channel->Modulation());
|
||||
Frontend.u.ofdm.transmission_mode = fe_transmit_mode_t(Channel->Transmission());
|
||||
Frontend.u.ofdm.guard_interval = fe_guard_interval_t(Channel->Guard());
|
||||
Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(Channel->Hierarchy());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Discard stale events:
|
||||
|
||||
for (;;) {
|
||||
dvb_frontend_event event;
|
||||
if (ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Tuning:
|
||||
|
||||
CHECK(ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend));
|
||||
|
||||
// Wait for channel lock:
|
||||
|
||||
fe_status_t status = fe_status_t(0);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status));
|
||||
if (status & FE_HAS_LOCK)
|
||||
break;
|
||||
usleep(10 * 1000);
|
||||
}
|
||||
dvbTuner->Set(Channel);
|
||||
/*XXX do we still need this???
|
||||
if (!(status & FE_HAS_LOCK)) {
|
||||
esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->Number(), CardIndex() + 1);
|
||||
if (LiveView && IsPrimaryDevice())
|
||||
cThread::RaisePanic();
|
||||
return false;
|
||||
}
|
||||
|
||||
source = Channel->Source();
|
||||
frequency = Channel->Frequency();
|
||||
|
||||
XXX*/
|
||||
}
|
||||
|
||||
// PID settings:
|
||||
|
11
dvbdevice.h
11
dvbdevice.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.h 1.18 2002/11/03 12:31:15 kls Exp $
|
||||
* $Id: dvbdevice.h 1.19 2002/12/07 14:44:29 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBDEVICE_H
|
||||
@ -22,6 +22,8 @@
|
||||
|
||||
#define MAXDVBDEVICES 4
|
||||
|
||||
class cDvbTuner;
|
||||
|
||||
class cDvbDevice : public cDevice {
|
||||
friend class cDvbOsd;
|
||||
private:
|
||||
@ -33,7 +35,7 @@ public:
|
||||
// Must be called before accessing any DVB functions.
|
||||
private:
|
||||
fe_type_t frontendType;
|
||||
int fd_osd, fd_frontend, fd_audio, fd_video, fd_dvr;
|
||||
int fd_osd, fd_audio, fd_video, fd_dvr;
|
||||
int OsdDeviceHandle(void) const { return fd_osd; }
|
||||
protected:
|
||||
virtual void MakePrimaryDevice(bool On);
|
||||
@ -53,10 +55,7 @@ public:
|
||||
// Channel facilities
|
||||
|
||||
private:
|
||||
int source;
|
||||
int frequency;
|
||||
const char *diseqcCommands;
|
||||
bool IsTunedTo(const cChannel *Channel) const;
|
||||
cDvbTuner *dvbTuner;
|
||||
public:
|
||||
virtual bool ProvidesSource(int Source) const;
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||
|
Loading…
Reference in New Issue
Block a user