Logo Search packages:      
Sourcecode: kaffeine version File versions

dvbstream.cpp

/***************************************************************************
                          dvbstream.cpp  -  description
                             -------------------
    begin                : Mon Jan 20 2003
    copyright            : (C) 2003-2005 by Christophe Thommeret
    email                : hftom@free.fr
    last modified        : $Date: 2005/02/15 08:18:35 $ by $Author: hftom $

    some code from :
            dvbstream (GPL), Copyright (C) Dave Chapman 2001,2002
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <resolv.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <values.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>

#include <linux/dvb/dmx.h>

#include <qdir.h>

#include <klocale.h>
#include <kapplication.h>

#include "dvbstream.h"
#include "dvbevents.h"
#include "gdvb.h"

#define slof (11700*1000UL)
#define lof1 (9750*1000UL)
#define lof2 (10600*1000UL)



DvbStream::DvbStream( int card, fe_type_t type, QString src )
{
      isRunning = false;
      timeShifting = false;
      waitPause = 0;
      dvbCard = card;
      setSources( src );
      fdFrontend = fdDvr = 0;
      ndmx = 0;
      currentTransponder = Transponder();
      frontendName = QString("/dev/dvb/adapter%1/frontend0").arg( dvbCard );
      dvrName = QString("/dev/dvb/adapter%1/dvr0").arg( dvbCard );
      demuxName = QString("/dev/dvb/adapter%1/demux0").arg( dvbCard );
      dvbType = type;

      out.setAutoDelete( true );

      bool bok;
      dvbEvents = new DVBevents( &bok, dvbCard );

      connect( &statusTimer, SIGNAL(timeout()), this, SLOT(checkStatus()) );
}



void DvbStream::setSources( QString src )
{
      QString s;
      int pos, i;

      s = src;
      source.clear();
      pos = s.find("|");
      s = s.right( s.length()-pos-1 );
      for ( i=0; i<src.contains("|"); i++ ) {
            pos = s.find("|");
            source.append( s.left(pos) );
            s = s.right( s.length()-pos-1 );
      }
}



QStringList DvbStream::getSources()
{
      return source;
}



bool DvbStream::canSource( ChannelDesc *chan )
{
      if ( chan->tp.type!=dvbType ) return false;
      int i = getSatPos( chan->tp.source );
      if ( i!=-1 ) return true;
      else return false;
}



int DvbStream::getSatPos( QString src )
{
      int i;

      for ( i=0; i<(int)source.count(); i++ ) if ( source[i]==src ) return i;
      return -1;
}



bool DvbStream::openFe()
{
      if ( fdFrontend ) {
            fprintf(stderr,"openFe : fdFrontend != 0\n");
            return false;
      }
      fdFrontend = open( frontendName, O_RDWR );
      if ( fdFrontend<0 ) {
            perror("openFe :");
            fdFrontend = 0;
            return false;
      }
      return true;
}



bool DvbStream::closeFe()
{
      if ( !fdFrontend ) return true;
      if ( close( fdFrontend )<0 ) {
            perror("closeFe : ");
            return false;
      }
      fdFrontend = 0;
      currentTransponder = Transponder();
      return true;
}



void DvbStream::connectStatus( bool con )
{
      if ( con ) statusTimer.start( 1000 );
      else statusTimer.stop();
}



ChannelDesc DvbStream::getLiveChannel()
{
      int i;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( out.at(i)->hasLive() ) return out.at(i)->channel;
      }
      return ChannelDesc();
}



bool DvbStream::hasRec()
{
      int i;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( out.at(i)->hasRec() ) return true;
      }
      return false;
}



bool DvbStream::liveIsRecording()
{
      int i;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( out.at(i)->hasLive() ) {
                  if ( out.at(i)->hasRec() ) return true;
                  else return false;
            }
      }
      return false;
}



Transponder DvbStream::getCurrentTransponder()
{
      return currentTransponder;
}



bool DvbStream::isTuned()
{
      if ( fdFrontend ) return true;
      else return false;
}



bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
{
      int tone=-1, status, res;
      struct dvb_frontend_parameters feparams;
      struct dvb_frontend_event event;
      struct dvb_frontend_info fe_info;
      struct pollfd pf[1];
      unsigned long freq=chan->tp.freq;
      unsigned long srate=chan->tp.sr;

      closeFe();
      if ( !openFe() ) return false;

      if ( (res = ioctl( fdFrontend, FE_GET_INFO, &fe_info ) < 0) ) {
            perror("FE_GET_INFO: ");
            return false;
      }

      fprintf(stderr, "Using DVB card \"%s\"\n", fe_info.name);

      freq*=1000;
      srate*=1000;

      switch( fe_info.type ) {
            case FE_OFDM : {
                  if (freq < 1000000) freq*=1000UL;
                  feparams.frequency=freq;
                  feparams.u.ofdm.bandwidth=chan->tp.bandwidth;
                  feparams.u.ofdm.code_rate_HP=chan->tp.coderateH;
                  feparams.u.ofdm.code_rate_LP=chan->tp.coderateL;
                  feparams.u.ofdm.constellation=chan->tp.modulation;
                  feparams.u.ofdm.transmission_mode=chan->tp.transmission;
                  feparams.u.ofdm.guard_interval=chan->tp.guard;
                  feparams.u.ofdm.hierarchy_information=chan->tp.hierarchy;
                  fprintf(stderr,"tuning DVB-T to %lu Hz\n", freq);
                  fprintf(stderr,"inv:%d bw:%d fecH:%d fecL:%d mod:%d tm:%d gi:%d hier:%d\n", chan->tp.inversion,
                        chan->tp.bandwidth, chan->tp.coderateH, chan->tp.coderateL, chan->tp.modulation,
                        chan->tp.transmission, chan->tp.guard, chan->tp.hierarchy );
                  break;
            }
            case FE_QAM : {
                  fprintf(stderr,"tuning DVB-C to %lu\n", freq);
                  feparams.frequency=freq;
                  feparams.u.qam.symbol_rate = srate;
                  feparams.u.qam.fec_inner = chan->tp.coderateH;
                  feparams.u.qam.modulation = chan->tp.modulation;
                  fprintf(stderr,"inv:%d sr:%d fecH:%d mod:%d\n", chan->tp.inversion,
                        srate, chan->tp.coderateH, chan->tp.modulation );
                  break;
            }
            case FE_QPSK : {
                  fprintf(stderr,"tuning DVB-S to %lu %c %lu\n", freq, chan->tp.pol, srate);
                  if (freq > 2200000) {
                        if (freq < slof) {
                              feparams.frequency=(freq-lof1);
                              tone = SEC_TONE_OFF;
                        }
                        else {
                              feparams.frequency=(freq-lof2);
                              tone = SEC_TONE_ON;
                        }
                  }
                  else feparams.frequency=freq;

                  feparams.u.qpsk.symbol_rate=srate;
                  feparams.u.qpsk.fec_inner=chan->tp.coderateH;
                  fprintf(stderr,"inv:%d fecH:%d\n", chan->tp.inversion, chan->tp.coderateH );
                  if ( setupSwitch( getSatPos( chan->tp.source ), (chan->tp.pol=='h') || (chan->tp.pol=='H'), freq > slof )!=0 ) {
                        closeFe();
                        return false;
                  }
                  break;
            }
      }
      if ( chan->tp.inversion==INVERSION_AUTO ) {
            if ( fe_info.caps & FE_CAN_INVERSION_AUTO ) feparams.inversion=chan->tp.inversion;
            else {
                  fprintf(stderr,"Can NOT inversion_auto\n");
                  feparams.inversion=INVERSION_OFF;
            }
      }
      else feparams.inversion=chan->tp.inversion;

      //usleep(100000);

      if (ioctl(fdFrontend,FE_SET_FRONTEND,&feparams) < 0) {
            perror("ERROR tuning \n");
            closeFe();
            return false;
      }

      pf[0].fd = fdFrontend;
      pf[0].events = POLLIN;

      memset( &event.status, 0, sizeof(event.status) );
      int eventCount = 0;
      int polling = 0;
      while (((event.status & FE_TIMEDOUT)==0) && ((event.status & FE_HAS_LOCK)==0)) {
            if ( ++polling>10 ) {
                  closeFe();
                  return false;
            }
            fprintf(stderr,"polling....\n");
            if (poll(pf,1,10000)){
                  if (pf[0].revents & POLLIN){
                        fprintf(stderr,"Getting frontend event\n");
                        if (++eventCount > 7) { // 7 is just a working guess...
                              closeFe();
                              return false;
                        }
                        if ((status = ioctl(fdFrontend, FE_GET_EVENT, &event)) < 0){
                              if (status != -EOVERFLOW) {
                                    perror("FE_GET_EVENT");
                                    closeFe();
                                    return false;
                              }
                        }
                  }
            }
      }

      if (event.status & FE_HAS_LOCK) {
            switch(fe_info.type) {
                  case FE_OFDM:
                        fprintf(stderr,"Event:  Frequency: %d\n",event.parameters.frequency);
                        break;
                  case FE_QPSK:
                        fprintf(stderr,"Event:  Frequency: %d\n",(unsigned int)((event.parameters.frequency)+(tone==SEC_TONE_OFF ? lof1 : lof2)));
                        fprintf(stderr,"        SymbolRate: %d\n",event.parameters.u.qpsk.symbol_rate);
                        fprintf(stderr,"        FEC_inner:  %d\n",event.parameters.u.qpsk.fec_inner);
                        fprintf(stderr,"\n");
                        break;
                  case FE_QAM:
                        fprintf(stderr,"Event:  Frequency: %d\n",event.parameters.frequency);
                        fprintf(stderr,"        SymbolRate: %d\n",event.parameters.u.qpsk.symbol_rate);
                        fprintf(stderr,"        FEC_inner:  %d\n",event.parameters.u.qpsk.fec_inner);
                        break;
            }
      }
      else {
            fprintf(stderr,"Not able to lock to the signal on the given frequency\n");
            closeFe();
            return false;
      }

      if ( !dvr ) return true;

      if ( ( fdDvr = open( dvrName, O_RDONLY|O_NONBLOCK)) < 0 ) {
            perror("DVR DEVICE: ");
            closeFe();
            fdDvr = 0;
            return false;
      }
      pfd.fd=fdDvr;
      pfd.events=POLLIN|POLLPRI;

      currentTransponder = chan->tp;
      return true;
}



int DvbStream::setupSwitch( int switchPos, int voltage18, int hiband )
{
      struct diseqc_cmd switch_cmds[] = {
            { { { 0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf2, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf1, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf3, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf4, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf6, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf5, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf7, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf8, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xfa, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xf9, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xfb, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xfc, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xfe, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xfd, 0x00, 0x00 }, 4 }, 0 },
            { { { 0xe0, 0x10, 0x38, 0xff, 0x00, 0x00 }, 4 }, 0 }
      };
      struct diseqc_cmd *cmd[2] = { NULL, NULL };
      int i = 4 * switchPos + 2 * hiband + (voltage18 ? 1 : 0);

      fprintf( stderr, "DiSEqC: switch pos %i, %sV, %sband (index %d)\n", switchPos, voltage18 ? "18" : "13", hiband ? "hi" : "lo", i );
      if ( i < 0 || i >= (int)(sizeof(switch_cmds)/sizeof(struct diseqc_cmd)) ) return -EINVAL;
      cmd[0] = &switch_cmds[i];
      return diseqc( i % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13, cmd,
            (i/2) % 2 ? SEC_TONE_ON : SEC_TONE_OFF, (i/4) % 2 ? SEC_MINI_B : SEC_MINI_A );
}



int DvbStream::diseqc( fe_sec_voltage_t v, struct diseqc_cmd **cmd, fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
{
      int err;

      if ((err = ioctl(fdFrontend, FE_SET_TONE, SEC_TONE_OFF))) {
            perror("FE_SET_TONE failed");
            //return err;
      }
      if ((err = ioctl(fdFrontend, FE_SET_VOLTAGE, v))) {
            perror("FE_SET_VOLTAGE failed");
            //return err;
      }
      usleep(15*1000);
      while (*cmd) {
            fprintf( stderr, "DiSEqC: %02x %02x %02x %02x %02x %02x\n", (*cmd)->cmd.msg[0], (*cmd)->cmd.msg[1],
                  (*cmd)->cmd.msg[2], (*cmd)->cmd.msg[3], (*cmd)->cmd.msg[4], (*cmd)->cmd.msg[5]);
            if ((err = ioctl(fdFrontend, FE_DISEQC_SEND_MASTER_CMD, &(*cmd)->cmd))) {
                  perror("FE_DISEQC_SEND_MASTER_CMD failed");
                  //return err;
            }
            usleep( (*cmd)->wait*1000 );
            cmd++;
      }
      usleep(15*1000);
      if ((err = ioctl(fdFrontend, FE_DISEQC_SEND_BURST, b))) {
            perror("FE_DISEQC_SEND_BURST failed");
            //return err;
      }
      usleep(15*1000);
      if ((err = ioctl(fdFrontend, FE_SET_TONE, t))) {
            perror("FE_SET_TONE failed");
            //return err;
      };
      return 0;
}



bool DvbStream::setPids( DVBout *o, int napid )
{
      int i, dmx;
      struct dmx_pes_filter_params pesFilterParams;
      dmx_pes_type_t pestype = DMX_PES_OTHER;
      QValueList<int> pidList;

      if ( o->channel.vpid!=0 ) pidList.append( o->channel.vpid );
      pidList.append( o->channel.apid[napid].pid );
      if ( o->channel.subpid.pid!=0 ) pidList.append( o->channel.subpid.pid );

      //if ( (ndmx+pidList.count())>MAX_CHANNELS ) return false;

      for ( i=0; i<(int)pidList.count(); i++ ) {
            if ( ( dmx = open( demuxName, O_RDWR)) < 0 ) {
                  fprintf(stderr,"FD %i: ",i);
                  perror("DEMUX DEVICE: ");
                  return false;
            }
            else o->dmx.append(dmx);
      }

      for ( i=0; i<(int)pidList.count(); i++ ) {
            pesFilterParams.pid = pidList[i];
            pesFilterParams.input = DMX_IN_FRONTEND;
            pesFilterParams.output = DMX_OUT_TS_TAP;
            pesFilterParams.pes_type = pestype;
            pesFilterParams.flags = DMX_IMMEDIATE_START;
            if ( ioctl( o->dmx[i], DMX_SET_PES_FILTER, &pesFilterParams) < 0)  {
                  fprintf( stderr, "FILTER %i: ", pidList[i] );
                  perror("DMX SET PES FILTER");
            }
      }

      ndmx +=pidList.count();

      return true;
}



void DvbStream::removePids( DVBout *o )
{
      int i;

      for ( i=0; i<(int)o->dmx.count(); i++ ) close( o->dmx[i] );
      ndmx -=o->dmx.count();
}



void DvbStream::removeOut( DVBout *o )
{
      disconnect( o, SIGNAL(endRecord(DVBout*,RecTimer*,bool)), this, SLOT(recordEnded(DVBout*,RecTimer*,bool)) );
      disconnect( o, SIGNAL(playDvb()), this, SLOT(receivePlayDvb()) );
      disconnect( o, SIGNAL(shifting(bool)), this, SLOT(receiveShifting(bool)) );
      out.remove( o );
}



bool DvbStream::checkStatus()
{
      int32_t strength;
      fe_status_t festatus;
      bool ret=true;

       strength=0;
      ioctl(fdFrontend,FE_READ_SIGNAL_STRENGTH,&strength);
      emit signalStatus(strength*100/65535);

      strength=0;
      ioctl(fdFrontend,FE_READ_SNR,&strength);
      emit snrStatus(strength*100/65535);

      memset( &festatus, 0, sizeof(festatus) );
      ioctl(fdFrontend,FE_READ_STATUS,&festatus);

      if (festatus & FE_HAS_LOCK) emit lockStatus( true );
      else {
            emit lockStatus( false );
            ret = false;
      }

      return ret;
}



bool DvbStream::hasVideo()
{
      if ( getLiveChannel().vpid ) return true;
      else return false;
}



void DvbStream::run()
{
      unsigned char buf[188];
      int n, i, thWrite=0;
      int WSIZE=188*8;
      DVBout *o=0;

      dvbEvents->go( true );

      while ( isRunning ) {
            poll( &pfd, 1, 500 );
            n = read( fdDvr, buf, 188 );
            if ( n==188 ) {
                  memcpy( thBuf+thWrite, buf, n );
                  thWrite+=n;
                  if ( waitPause>0 ) {
                        o = 0;
                        for ( i=0; i<(int)out.count(); i++ ) if ( out.at(i)->hasLive() ) o = out.at(i);
                        if ( o ) {
                              if ( o->doPause( timeShiftFileName ) ) waitPause = 0;
                              else waitPause = -1;
                        }
                        else waitPause = -1;
                  }
                  if ( thWrite==WSIZE ) {
                        for ( i=0; i<(int)out.count(); i++ ) out.at(i)->process( thBuf, WSIZE );
                        thWrite = 0;
                  }
            }
            else usleep(1000);
      }

      fprintf(stderr,"dvbstream::run() end\n");
}



bool DvbStream::doPause( QString name )
{
      //if ( !hasVideo() ) return false;

      if ( !timeShifting ) {
            timeShiftFileName = name;
            waitPause = 1;
            while ( waitPause>0 ) usleep(100);
            if ( waitPause<0 ) return false;
            else receiveShifting( true );
            return true;
      }
      return false;
}



bool DvbStream::timeShiftMode()
{
      return timeShifting;
}



void DvbStream::receiveShifting( bool b )
{
      timeShifting = b;
      emit shifting( b );
}



bool DvbStream::running()
{
      return isRunning;
}



void DvbStream::receivePlayDvb()
{
      //KApplication::kApplication()->postEvent( videoWin, new QTimerEvent( 500 ) );
}



void DvbStream::recordEnded( DVBout *o, RecTimer* t, bool kill )
{
      if ( t ) emit timerEnded( t );
      if ( kill ) {
            removePids( o );
            removeOut( o );
            if ( out.count()==0 ) stop();
      }
      recordingState();
}



void DvbStream::recordingState()
{
      int i;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( out.at(i)->hasRec() ) {
                  emit isRecording( true );
                  return;
            }
      }
      emit isRecording( false );
}



void DvbStream::updateTimer( RecTimer *t, int ms )
{
      int i;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( out.at(i)->recTimer==t ) {
                  if ( ms ) out.at(i)->changeTimer( ms );
                  else out.at(i)->stopRec();
                  return;
            }
      }
      if ( !ms ) emit timerEnded( t ); // not running
}



int DvbStream::canStartTimer( bool &live, ChannelDesc *chan )
{
      int i, ret=0;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( (chan->tp!=out.at(i)->channel.tp) && out.at(i)->hasRec() ) return ErrIsRecording;
            if ( (out.at(i)->channel.name==chan->name) && out.at(i)->hasRec() ) return ErrIsRecording;
            if ( out.at(i)->hasLive() ) {
                  if ( chan->tp!=out.at(i)->channel.tp ) live = true;
                  else if ( (out.at(i)->channel.name==chan->name) && (out.at(i)->currentAudioPid()!=0) ) live = true;
            }
      }
      return ret;
}



bool DvbStream::startTimer( ChannelDesc *chan, QString path, RecTimer *t )
{
      int i;
      bool stop=false, newout=false;
      DVBout *o=0;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( out.at(i)->channel.name==chan->name ) o = out.at(i);
      }

      if ( !isTuned() ) {
            for ( i=0; i<3; i++ ) {
                  if ( tuneDvb( chan ) ) {
                        i = -1;
                        break;
                  }
                  else usleep(100000);
            }
            if ( i<0 ) stop = true;
            else return false;
      }

      if ( !o ) {
            o = new DVBout( *chan, dvbCard );
            connect( o, SIGNAL(endRecord(DVBout*,RecTimer*,bool)), this, SLOT(recordEnded(DVBout*,RecTimer*,bool)) );
            connect( o, SIGNAL(playDvb()), this, SLOT(receivePlayDvb()) );
            connect( o, SIGNAL(shifting(bool)), this, SLOT(receiveShifting(bool)) );
            out.append( o );
            if ( !setPids( o, 0 ) ) {
                  if ( stop ) stopFrontend();
                  removePids( o );
                  removeOut( o );
                  return false;
            }
            newout = true;
      }

      if ( !o->goRec( t->filetype, path+t->name, t ) ) {
            if ( stop ) stopFrontend();
            if ( newout ) {
                  removePids( o );
                  removeOut( o );
            }
            return false;
      }

      fprintf(stderr,"NOUT : %d\n", out.count() );

      if ( !isRunning ) {
            isRunning = true;
            start();
      }
      recordingState();
      return true;
}



int DvbStream::goLive( ChannelDesc *chan, QString pipeName, int &napid )
{
      int i;
      bool stop=false;
      DVBout *o=0;

      for ( i=0; i<(int)out.count(); i++ ) {
            if ( (chan->tp!=out.at(i)->channel.tp) && out.at(i)->hasRec() ) return ErrIsRecording;
            if ( out.at(i)->channel.name==chan->name ) o = out.at(i);
      }

      if ( !isTuned() ) {
            for ( i=0; i<3; i++ ) {
                  if ( tuneDvb( chan ) ) {
                        i = -1;
                        break;
                  }
                  else usleep(100000);
            }
            if ( i<0 ) stop = true;
            else return ErrCantTune;
      }

      if ( !o ) {
            o = new DVBout( *chan, dvbCard );
            connect( o, SIGNAL(endRecord(DVBout*,RecTimer*,bool)), this, SLOT(recordEnded(DVBout*,RecTimer*,bool)) );
            connect( o, SIGNAL(playDvb()), this, SLOT(receivePlayDvb()) );
            connect( o, SIGNAL(shifting(bool)), this, SLOT(receiveShifting(bool)) );
            out.append( o );
            if ( !setPids( o, napid ) ) {
                  if ( stop ) stopFrontend();
                  removePids( o );
                  removeOut( o );
                  return ErrCantSetPids;
            }
      }

      if ( o->hasRec() ) {
            napid = o->currentAudioPid();
            i = ErrDontSwitchAudio;
      }
      else i = 0;

      o->goLive( pipeName, napid );
      fprintf(stderr,"NOUT : %d\n", out.count() );

      if ( !isRunning ) {
            isRunning = true;
            start();
      }
      return i;
}



void DvbStream::stopLive( ChannelDesc *chan )
{
      int i;
      DVBout *o;

      fprintf(stderr,"Asked to stop\n");
      for ( i=0; i<(int)out.count(); i++ ) {
            o = out.at(i);
            if ( o->hasLive() ) {
                  o->stopLive();
                  if ( !o->hasRec() ) {
                        removePids( o );
                        removeOut( o );
                  }
                  break;
            }
      }
      fprintf(stderr,"Live stopped\n");
      if ( out.count()==0 && chan->tp!=currentTransponder ) stop();
}



void DvbStream::stop()
{
      isRunning = false;
      if ( !wait(100) ) {
            terminate();
            wait();
            fprintf(stderr,"dvbstream::run() terminated\n");
      }
      dvbEvents->stop();
      stopFrontend();
}



void DvbStream::stopFrontend()
{
      if ( fdDvr ) {
            close( fdDvr );
            fprintf(stderr,"fdDvr closed\n");
            fdDvr = 0;
      }
      if ( fdFrontend ) closeFe();
      fprintf(stderr,"Frontend closed\n");
}



void DvbStream::setScanning( bool b )
{
      connectStatus( b );
}



void DvbStream::stopScan()
{
      if ( fdFrontend ) closeFe();
}



DvbStream::~DvbStream()
{
      delete dvbEvents;
      disconnect( &statusTimer, SIGNAL(timeout()), this, SLOT(checkStatus()) );
}

Generated by  Doxygen 1.6.0   Back to index