Logo Search packages:      
Sourcecode: kaffeine version File versions

dvbpanel.cpp

/***************************************************************************
                          dvbpanel.cpp  -  description
                             -------------------
    begin                : Mon Jan 19 2004
    copyright            : (C) 2004-2005 by Christophe Thommeret
    email                : hftom@free.fr
    last modified        : $Date: 2005/02/02 10:08:24 $ by $Author: juergenk $
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 <qlayout.h>
#include <qfile.h>
#include <qdir.h>
#include <qstringlist.h>
#include <qlabel.h>
#include <qpixmap.h>
#include <qaccel.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qapp.h>

#include <kiconloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include "dvbpanel.h"
#include "channeldesc.h"
#include "dvbstream.h"
#include "dvbevents.h"
#include "kevents.h"



DvbPanel::DvbPanel( QWidget *accel, QWidget *parent, const char *name ) : QWidget(parent,name)
{
      timeShiftFileName = "";
      timersDialog = 0;
      currentChannelNumber = 0;
      
      channels.setAutoDelete( true );
      timers.setAutoDelete( true );
      
      setSizePolicy( QSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred) );
      
      QVBoxLayout *vb = new QVBoxLayout( this, 6, 6 );

      channelsBtn = new QToolButton( this );
      QToolTip::add( channelsBtn, i18n("Channels"));
      dateBtn = new QToolButton( this );
      QToolTip::add( dateBtn, i18n("Timers"));
      infoBtn = new QToolButton( this );
      QToolTip::add( infoBtn, i18n("Electronic Program Guide"));
      configBtn = new QToolButton( this );
      QToolTip::add( configBtn, i18n("DVB settings"));
      QHBoxLayout *h1 = new QHBoxLayout();
      h1->addWidget( channelsBtn );
      h1->addItem( new QSpacerItem( 1, 1, QSizePolicy::Preferred, QSizePolicy::Minimum ) );
      h1->addWidget( dateBtn );
      h1->addItem( new QSpacerItem( 1, 1, QSizePolicy::Preferred, QSizePolicy::Minimum ) );
      h1->addWidget( infoBtn );
      h1->addItem( new QSpacerItem( 1, 1, QSizePolicy::Preferred, QSizePolicy::Minimum ) );
      h1->addWidget( configBtn );
      vb->addLayout( h1 );
      
      channelsCb = new QListBox( this );
      channelsCb->setBottomScrollBar( false );
      channelsCb->setSizePolicy( QSizePolicy (QSizePolicy::Preferred, QSizePolicy::MinimumExpanding) );
      channelsCb->setEnabled( false );
      vb->addWidget( channelsCb );
      shiftLed = new KLed( this );
      shiftLed->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
      //shiftLed->setColor( QColor( 255,255,0 ) );
      shiftLed->setDarkFactor( 500 );
      shiftLed->off();
      h1 = new QHBoxLayout();
      h1->addWidget( shiftLed );
      h1->addWidget( new QLabel( i18n("Time shifting"), this ) );
      h1->addItem( new QSpacerItem( 20, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ) );
      h1->addWidget( new QLabel( i18n("Audio :"), this ) );
      audioComb = new QComboBox( this );
      audioComb->setSizePolicy( QSizePolicy (QSizePolicy::Preferred, QSizePolicy::Fixed) );
      audioComb->setEnabled( false );
      h1->addWidget( audioComb );
      h1->addItem( new QSpacerItem( 20, 20, QSizePolicy::MinimumExpanding, QSizePolicy::Minimum ) );
      recordLed = new KLed( this );
      recordLed->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) );
      recordLed->setColor( QColor( 255,0,0 ) );
      recordLed->setDarkFactor( 500 );
      recordLed->off();
      h1->addWidget( recordLed );
      recordBtn = new KPushButton( this );
      h1->addWidget( recordBtn );
      vb->addLayout( h1 );
      broadcastBtn = new KPushButton( this );
      broadcastBtn->setToggleButton( true );
      broadcastBtn->setEnabled(false);
      broadcastBtn->hide();
      vb->addWidget( broadcastBtn );

      KIconLoader *icon = new KIconLoader();
      tvPix = icon->loadIcon( "kdvbtv", KIcon::Small );
      tvcPix = icon->loadIcon( "kdvbtvc", KIcon::Small );
      raPix = icon->loadIcon( "kdvbra", KIcon::Small );
      racPix = icon->loadIcon( "kdvbrac", KIcon::Small );
      broadcastBtn->setGuiItem( KGuiItem(i18n("Broadcast"), icon->loadIconSet("network_local", KIcon::Small) ) );
      recordBtn->setGuiItem( KGuiItem(i18n("Instant record"), icon->loadIconSet("filesave", KIcon::Small) ) );
      dateBtn->setIconSet( icon->loadIconSet("date", KIcon::Small) );
      infoBtn->setIconSet( icon->loadIconSet("view_text", KIcon::Small) );
      channelsBtn->setIconSet( icon->loadIconSet("kdvbtv", KIcon::Small) );
      configBtn->setIconSet( icon->loadIconSet("configure", KIcon::Small) );

      connect( channelsCb, SIGNAL(selected(const QString &)), this, SLOT(channelSelected(const QString &)) );
      connect( audioComb, SIGNAL(activated(int)), this, SLOT(audioSelected(int)) );
      connect( this, SIGNAL(zap(ChannelDesc*)), SLOT(dvbZap(ChannelDesc*)) );
      connect( configBtn, SIGNAL(clicked()), this, SLOT(showConfigDialog()));

      QAccel *acn = new QAccel( accel );
      acn->insertItem( Key_0, 10 );
      acn->insertItem( Key_1, 11 );
      acn->insertItem( Key_2, 12 );
      acn->insertItem( Key_3, 13 );
      acn->insertItem( Key_4, 14 );
      acn->insertItem( Key_5, 15 );
      acn->insertItem( Key_6, 16 );
      acn->insertItem( Key_7, 17 );
      acn->insertItem( Key_8, 18 );
      acn->insertItem( Key_9, 19 );
      connect( acn, SIGNAL(activated(int)), this, SLOT(numKeyInput(int)) );
      connect( recordBtn, SIGNAL(clicked()), this, SLOT(setRecord()) );
      connect( infoBtn, SIGNAL(clicked()), this, SLOT(showEvents()) );
      connect( channelsBtn, SIGNAL(clicked()), this, SLOT(scanner()) );
      connect( dateBtn, SIGNAL(clicked()), this, SLOT(showTimers()) );

      numKey = 0;
      connect( &numKeyHideTimer, SIGNAL(timeout()), this, SLOT(hideNumKey()) );

      connect( &timersTimer, SIGNAL(timeout()), this, SLOT(checkTimers()) );
      
      setConfig();
      
      updown = 1;
      autocount = 0;
}



void DvbPanel::dumpEvents()
{
      fprintf(stderr,"Dumping events :\n");
      dvb->dvbEvents->dumpEvents();
}



void DvbPanel::dvbOSD()
{
      QStringList list;
      DVBevents *events = dvb->dvbEvents;
      EventDesc *desc;
      QString s;
      int i, j;
      ChannelDesc liveChannel = dvb->getLiveChannel();
      if ( liveChannel.name=="" ) return;

      if ( dvb->liveIsRecording() ) list.append( "R" );
      if ( dvb->timeShiftMode() ) list.append( "T" );
      
      i = 0;
      for ( j=0; j<(int)events->events.count(); j++ ) {
            desc = events->events.at(j);
            if ( desc->tid>0x4f ) continue;
            if ( desc->sid!=liveChannel.sid || desc->tsid!=liveChannel.tp.tsid ) continue;
            if ( desc->running!=4 && desc->running!=1 ) continue;
            s = desc->startDateTime.toString( "hh:mm" );
            s = s+" - ";
            if ( desc->title!="" ) {
                  s = s+desc->title;
                  list.append( s );
                  i++;
            }
            if ( i>1 ) break;
      }
      emit showDvbOSD( list );
}



void DvbPanel::enableLiveDvb( bool on )
{
      channelsCb->setEnabled( on );
}



void DvbPanel::checkFirstRun()
{
      if ( dvbConfig->firstRun() ) showConfigDialog();
}



void DvbPanel::setConfig()
{
      QString s = locateLocal("appdata", "");
      
      conf = new KConfig( s+"dvbrc" );
      dvbConfig = new DVBconfig( conf, s );
      
      //for ( i=0; i<(int)dvbConfig->devList.count(); i++ ) {
            //dvb.append( new DvbStream( dvbConfig->devList.at(i)->adapter, dvbConfig->devList.at(i)->source ) );
            dvb = new DvbStream( dvbConfig->devList.at(0)->adapter, dvbConfig->devList.at(0)->type, dvbConfig->devList.at(0)->source );
            connect( dvb, SIGNAL(shifting(bool)), this, SLOT(setShiftLed(bool)) );
            connect( dvb, SIGNAL(timerEnded(RecTimer*)), this, SLOT(killTimer(RecTimer*)) );
            connect( dvb, SIGNAL(isRecording(bool)), this, SLOT(setRecordLed(bool)) );
            connect( dvb, SIGNAL(playDvb()), this, SIGNAL(playDvb()) );
      //}
      fifoName = QDir::homeDirPath()+"/.kaxtv.ts";
      QFile f( fifoName );
      if ( f.exists() ) f.remove();
      if ( (mkfifo( fifoName, 0644 ))<0 ) {
            perror( fifoName.latin1() );
            fifoName = "";
      }
      getTimerList();
      timersTimer.start( 1000 );
      getChannelList();
}



void DvbPanel::showConfigDialog()
{
      int ret;
      
loop:
      if ( !dvbConfig->haveData() ) {
            ret = KMessageBox::questionYesNo( this, i18n("<qt>Can't get DVB data from http://hftom.free.fr/kaxtv/dvbdata.tar.gz !<br>\
                  Check your internet connection, and say Yes to try again.<br>\
                  Or say No to cancel.<br>\
                  If you already have this archive, copy it to ~/.kde/share/apps/kaffeine/dvbdata.tar.gz and say Yes.<br><br>Should I try again ?</qt>") );
            if ( ret==KMessageBox::Yes ) goto loop;
            return;
      }
      
      DvbConfigDialog dlg( dvbConfig, this );
      ret = dlg.exec();
      if ( ret==DvbConfigDialog::Rejected ) return;
      /*for ( i=0; i<(int)dvbConfig->devList.count(); i++ ) {
            dvb.at(i)->setSources( dvbConfig->devList.at(i)->source );
      }*/
      dvb->setSources( dvbConfig->devList.at(0)->source );
}



void DvbPanel::fillChannelList( ChannelDesc curchan, bool all )
{
      int i;
      bool stop=false;
      ChannelDesc *chan;
      
      channelsCb->clear();
      for ( i=0; i<(int)channels.count(); i++ ) {
            chan = channels.at(i);
            if ( !all ) if ( chan->tp!=curchan.tp ) continue;
            if ( chan->type==1 ) {
                  if ( chan->fta==0 ) channelsCb->insertItem( tvPix, chan->name );
                  else channelsCb->insertItem( tvcPix, chan->name );
            }
            else {
                  if ( chan->fta==0 ) channelsCb->insertItem( raPix, chan->name );
                  else channelsCb->insertItem( racPix, chan->name );
            }
      }
      channelsCb->sort();
      if ( curchan.name=="" ) return;
      for ( i=0; i<(int)channelsCb->count(); i++ ) {
            if ( channelsCb->text(i)==curchan.name ) {
                  stop = true;
                  break;
            }
      }
      if ( stop ) {
            channelsCb->setCurrentItem( i );
            channelsCb->ensureCurrentVisible();
      }
}



void DvbPanel::setRecord()
{
      ChannelDesc curchan = dvb->getLiveChannel();
      QString s="";
      int ret, i, j, r=0;
      bool live=false;
      RecTimer *t, *rt;
      EventDesc *desc;

      if ( curchan.name=="" ) return;
      
      for ( j=0; j<(int)dvb->dvbEvents->events.count(); j++ ) {
            desc = dvb->dvbEvents->events.at(j);
            if ( desc->sid!=curchan.sid || desc->tsid!=curchan.tp.tsid ) continue;
            if ( desc->running!=4 ) continue;
            s = desc->title;
            break;
      }

      if ( s=="" ) s = curchan.name+"-"+QDateTime::currentDateTime().toString("yy.MM.dd-hh:mm:ss");
      fprintf(stderr,"Name : %s\n",s.latin1());

      rt = new RecTimer();
      rt->name = s.replace( "/", "_" ).replace( ">", "_" );
      fprintf(stderr,"Name cleaned: %s\n", rt->name.latin1());
      rt->channel = curchan.name;
      rt->begin = QDateTime::currentDateTime();
      rt->duration = QTime( 0,0,0).addSecs( dvbConfig->instantDuration*60 ) ;
      rt->filetype = dvbConfig->format;
      rt->running = 1;

      ret = dvb->canStartTimer( live, &curchan );
      if ( ret==0 ) {
            if ( dvb->startTimer( &curchan, dvbConfig->recordDir, rt ) ) {
                  for ( i=0; i<(int)timers.count(); i++ ) {
                        t = timers.at(i);
                        if ( rt->begin>t->begin ) r=i+1;
                  }
                  timers.insert( r, rt );
                  if ( timersDialog ) emit timersChanged();
                  saveTimerList();
                  audioComb->setEnabled( false );
                  KMessageBox::information( this, i18n("Timer successfully created and started.") );
            }
            else {
                  fprintf( stderr, "start timer failed !\n" );
                  delete rt;
            }
      }
      else {
            fprintf( stderr, "Cant start timer !\n" );
            delete rt;
      }
}



void DvbPanel::setRecordLed( bool on )
{
      ChannelDesc curchan;

      curchan = dvb->getLiveChannel();
      if ( curchan.name=="" ) curchan.tp = dvb->getCurrentTransponder();

      if ( on ) {
            recordLed->on();
            fillChannelList( curchan, false );
      }
      else {
            recordLed->off();
            fillChannelList( curchan, true );
      }
}



void DvbPanel::hideNumKey()
{
      int j;
      bool ok=false;
      
      for ( j=0; j<(int)channels.count(); j++ ) {
            if ( (int)channels.at(j)->num==numKey ) {
                  ok = true;
                  break;
            }
      }
      if ( !ok ) return;
      
      broadcastBtn->setOn( false );
      dvbZap( channels.at( j ) );
      //channelsCb->setCurrentItem( numKey-1 );
      //channelsCb->ensureCurrentVisible();
      numKey = 0;
}



void DvbPanel::numKeyInput( int n )
{
      QString s;
      
      if ( numKeyHideTimer.isActive() ) {
            numKeyHideTimer.stop();
            numKey*=10;
            numKey+=(n-10);
      }
      else {
            if ( n==10 ) return;
            numKey = n-10;
      }
      s = s.setNum( numKey )+"_";
      emit showOSD( s, 1000, 3 );
      numKeyHideTimer.start( 1000, true );
}



void DvbPanel::checkTimers()
{
      int i, j, ret;
      bool live=false;
      RecTimer *t;
      ChannelDesc *chan=0;
      QDateTime cur=QDateTime::currentDateTime();
      ChannelDesc curchan;

      for ( i=0; i<(int)timers.count(); i++ ) {
            t = timers.at(i);
            if ( t->running ) continue;
            if ( t->begin.date()==cur.date() && t->begin.time().hour()==cur.time().hour() && t->begin.time().minute()==cur.time().minute() ) {
                  for ( j=0; j<(int)channels.count(); j++ ) {
                        if ( channels.at(j)->name==t->channel ) {
                              chan = channels.at(j);
                              break;
                        }
                  }
                  if ( !chan ) continue;
                  ret = dvb->canStartTimer( live, chan );
                  if ( ret==0 ) {
                        if ( live ) {
                              stopLive();
                              emit dvbStop();
                        }
                        if ( dvb->startTimer( chan, dvbConfig->recordDir, t ) ) {
                              t->running = 1;
                              if ( timersDialog ) emit timersChanged();
                              saveTimerList();
                              audioComb->setEnabled( false );
                              i--;
                        }
                        else fprintf( stderr, "start timer failed!!!\n" );    
                  }
                  else fprintf( stderr, "Cant start timer !!!\n" );     
            }
      }
}



void DvbPanel::killTimer( RecTimer *t )
{
      int i;

      for ( i=0; i<(int)timers.count(); i++ ) {
            if ( timers.at(i)==t ) {
                  timers.remove( t );
                  if ( timersDialog ) emit timersChanged();
                  return;
            }
      }
}



void DvbPanel::showTimers()
{
      int i;
      QStringList list;

      if ( channels.count()==0 ) {
            KMessageBox::sorry( 0, i18n("You may want to define some channel first !") );
            return;
      }
      for ( i=0; i<(int)channels.count(); i++ ) list.append( channels.at(i)->name );
      timersDialog = new KRecord( list, &timers, this, dvbConfig->timerSize, dvbConfig->format );
      connect( timersDialog, SIGNAL(updateTimer(RecTimer*,int)), dvb, SLOT(updateTimer(RecTimer*,int)) );
      connect( this, SIGNAL(timersChanged()), timersDialog, SLOT(refresh()) );
      timersDialog->exec();
      disconnect( timersDialog, SIGNAL(updateTimer(RecTimer*,int)), dvb, SLOT(updateTimer(RecTimer*,int)) );
      disconnect( this, SIGNAL(timersChanged()), timersDialog, SLOT(refresh()) );
      dvbConfig->timerSize = timersDialog->size();
      delete timersDialog;
      timersDialog = 0;
      saveTimerList();
}



void DvbPanel::newTimer( QString channel, QString name, QDateTime begin, QTime duration)
{
      int i, r=0;
      RecTimer *t;
      RecTimer *rt = new RecTimer();
      
      rt->name = name.replace( "/", "_" ).replace( ">", "_" );
      rt->channel = channel;
      rt->begin = begin.addSecs( -(dvbConfig->beginMargin*60) );
      rt->duration = duration.addSecs( (dvbConfig->beginMargin+dvbConfig->endMargin)*60 ) ;
      rt->filetype = dvbConfig->format;
      rt->running = 0;

      for ( i=0; i<(int)timers.count(); i++ ) {
            t = timers.at(i);
            if ( rt->begin>t->begin ) r=i+1;
      }
      timers.insert( r, rt );
      KMessageBox::information( 0, i18n("Timer successfully created.") );
}



void DvbPanel::scanner()
{
      ChannelDesc curchan;
      int ret;
      
loop:
      if ( !dvbConfig->haveData() ) {
            ret = KMessageBox::questionYesNo( this, i18n("<qt>Can't get DVB data from http://hftom.free.fr/kaxtv/dvbdata.tar.gz !<br>\
                  Check your internet connection, and say Yes to try again.<br>\
                  Or say No to cancel.<br>\
                  If you already have this archive, copy it to ~/.kde/share/apps/kaffeine/dvbdata.tar.gz and say Yes.<br><br>Should I try again ?</qt>") );
            if ( ret==KMessageBox::Yes ) goto loop;
            return;
      }

      if ( !dvbConfig->haveData() ) return;
      ScanDialog dlg( dvb, &channels, dvbConfig->scanSize, dvbConfig->dvbConfigDir );
      dlg.exec();
      dvbConfig->scanSize = dlg.size();
      curchan = dvb->getLiveChannel();
      fillChannelList( curchan );
      saveChannelList();
      if ( dvb->hasRec() ) {
            if ( curchan.name=="" ) curchan.tp = dvb->getCurrentTransponder();
            fillChannelList( curchan, false );
      }
      else fillChannelList( curchan );
}



void DvbPanel::showEvents()
{
      dvb->dvbEvents->doClean( false );
      KEvents dlg( &channels, dvb->dvbEvents, this, dvbConfig->epgSize );
      connect( &dlg, SIGNAL(addTimer(QString,QString,QDateTime,QTime)), this, SLOT(newTimer(QString,QString,QDateTime,QTime)) );
      dlg.exec();
      dvbConfig->epgSize = dlg.size();
      disconnect( &dlg, SIGNAL(addTimer(QString,QString,QDateTime,QTime)), this, SLOT(newTimer(QString,QString,QDateTime,QTime)) );
      dvb->dvbEvents->doClean( true );
}



void DvbPanel::setShiftLed( bool on )
{
      if ( on ) {
            shiftLed->on();
            audioComb->setEnabled( false );
      }
      else shiftLed->off();
}



void DvbPanel::channelSelected( const QString &cname )
{
      QPtrListIterator<ChannelDesc> iter( channels );
      ChannelDesc *itdesc;

      iter.toFirst();
      while ( (itdesc=iter.current())!=0 ) {
            if ( itdesc->name==cname ) {
                  broadcastBtn->setOn( false );
                  dvbZap( itdesc );
                  break;
            }
            ++iter;
      }
}



void DvbPanel::audioSelected( int n )
{
      if ( !dvb->running() ) return;

      ChannelDesc chan=dvb->getLiveChannel();

      emit setTimeShiftFilename( "" );
      emit dvbPause( false );
      dvb->stopLive( &chan );
      finalZap( &chan, false, n );
}



void DvbPanel::playChannel()
{
      if ( !channelsCb->isEnabled() ) return;
      broadcastBtn->setOn( false );
      dvbZap( channels.at(0) );
      channelsCb->setCurrentItem( 0 );
      channelsCb->ensureCurrentVisible();
}



void DvbPanel::next()
{
      int j;
      bool ok=false;

      if ( currentChannelNumber>((int)channels.count()-1) ) return;
      
      for ( j=0; j<(int)channels.count(); j++ ) {
            if ( (int)channels.at(j)->num==(currentChannelNumber+1) ) {
                  ok = true;
                  break;
            }
      }
      if ( !ok ) return;
      
      broadcastBtn->setOn( false );
      dvbZap( channels.at(j) );
}



void DvbPanel::previous()
{
      int j;
      bool ok=false;

      if ( currentChannelNumber<2 ) return;
      
      for ( j=0; j<(int)channels.count(); j++ ) {
            if ( (int)channels.at(j)->num==(currentChannelNumber-1) ) {
                  ok = true;
                  break;
            }
      }
      if ( !ok ) return;
      
      broadcastBtn->setOn( false );
      dvbZap( channels.at(j) );
}
      
      


void DvbPanel::dvbZap( ChannelDesc *chan )
{     
      if ( fifoName=="" ) return;

      audioComb->setEnabled( false );
      emit setTimeShiftFilename( "" );
      if ( dvb->getLiveChannel().tp.freq ) emit dvbPause( false );
      dvb->stopLive( chan );
      finalZap( chan, true );
}



void DvbPanel::finalZap( ChannelDesc *chan, bool setAudio, int napid )
{
      QString s, t;
      int apidn=napid;
      int i;
      
      fprintf( stderr, "Tuning to : %s / autocount : %d\n", chan->name.latin1(), autocount );
      QTime tm;
      tm.start();
      int ret = dvb->goLive( chan, fifoName, apidn );
      
      switch ( ret ) {
            case DvbStream::ErrIsRecording :
                  //KMessageBox::sorry( this, i18n("Still recording. Can't switch !") );
                  emit showOSD( i18n("Still recording. Can't switch !"), 5000, 3 );
                  break;
            case DvbStream::ErrCantTune :
                  //KMessageBox::sorry( this, i18n("Can't tune dvb !") );
                  emit showOSD( i18n("Can't tune dvb !"), 5000, 3 );
                  break;
            case DvbStream::ErrCantSetPids :
                  //KMessageBox::sorry( this, i18n("Can't set pid(s) !") );
                  emit showOSD( i18n("Can't set pid(s)"), 5000, 3 );
                  break;
      }

      if ( setAudio ) {
            audioComb->clear();
            for ( i=0; i<chan->napid; i++ ) {
                  s = t.setNum( chan->apid[i].pid );
                  if ( chan->apid[i].lang!="" ) s = s+"("+chan->apid[i].lang+")";
                  if ( chan->apid[i].ac3 ) s = s+"(ac3)";
                  audioComb->insertItem( s );
            }
            audioComb->setCurrentItem( apidn );
            if ( chan->napid>1 && ret==0 ) audioComb->setEnabled( true );
      }

      fprintf( stderr, "Tuning delay : %d ms\n", tm.elapsed() );
      if ( ret<1 ) {
            currentChannelNumber = chan->num;
            emit dvbOpen( fifoName, s.setNum( chan->num)+" - "+chan->name, chan->vpid );
            QTimer::singleShot(300, this, SIGNAL(showPlayer()));
            QTimer::singleShot(2000, this, SLOT(dvbOSD()));
      }
      else emit dvbStop();
}



void DvbPanel::pauseLiveTV()
{
      if ( dvb->getLiveChannel().tp.freq ) {
            timeShiftFileName = dvbConfig->shiftDir+"DVBLive-"+QDateTime::currentDateTime().toString( Qt::ISODate )+".ts";
            if ( dvb->doPause( timeShiftFileName ) ) emit setTimeShiftFilename( timeShiftFileName );
      }
}



bool DvbPanel::timeShiftMode()
{
      return dvb->timeShiftMode();
}



void DvbPanel::stopLive()
{
      ChannelDesc chan;

      dvb->stopLive( &chan );
      emit setTimeShiftFilename( "" );
      audioComb->clear();
      audioComb->setEnabled( false );
}


//   TV | vpid | apid1(lang)(ac3),apid2, | ttpid | sid | tsid | type(S,C,T)source | freq | sr | pol | fecH | inv | mod | fecL | bw | trans | guard | hier | number /
bool DvbPanel::getChannelList()
{
      bool ret=false;
      QString s, c, t, type;
      int pos, tpos;
      ChannelDesc *chan;
      QString src="";
      
      if ( dvb->getSources().count() ) src = dvb->getSources()[0];

      QFile f( locateLocal("appdata", "channels.dvb" ) );
      if ( f.open(IO_ReadOnly) ) {
            QTextStream tt( &f );
            while ( !tt.eof() ) {
                  s = tt.readLine();
                  if ( s.startsWith("#") ) {
                        if ( s.contains("KaxTV") ) break;
                        continue;
                  }
                  chan = new ChannelDesc();
                  pos = s.find("|");
                  c = s.left( pos );
                  if ( c=="TV" || c=="TVC" ) chan->type=1;
                  else chan->type=2;
                  if ( c=="TVC" || c=="RAC" ) chan->fta=1;
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  chan->name = s.left( pos );
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  chan->vpid = s.left(pos).toUShort();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  c = s.left( pos );
                  s = s.right( s.length()-pos-1 );
                  while ( (pos=c.find(","))!=-1 ) {
                        t = c.left(pos);
                        chan->napid++;
                        if ( t.contains("(ac3)") ) {
                              chan->apid[chan->napid-1].ac3=1;
                              t.remove("(ac3)");
                        }
                        if( (tpos=t.find("("))!=-1 ) {
                              t.remove(")");
                              chan->apid[chan->napid-1].lang=t.right( t.length()-tpos-1 );
                              t = t.left( tpos );
                        }
                        chan->apid[chan->napid-1].pid=t.toUShort();
                        c = c.right( c.length()-pos-1 );
                  }
                  pos = s.find("|");
                  chan->ttpid = s.left(pos).toUShort();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  chan->sid = s.left(pos).toUShort();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  chan->tp.tsid = s.left(pos).toUShort();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  c = s.left(pos);
                  if ( c.startsWith("T") ) chan->tp.type=FE_OFDM;
                  else if ( c.startsWith("C") ) chan->tp.type=FE_QAM;
                  else chan->tp.type=FE_QPSK;
                  c.remove( 0, 1 );
                  if ( c.length() ) chan->tp.source = c;
                  else chan->tp.source = src;
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");                  
                  chan->tp.freq = s.left(pos).toULong();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  chan->tp.sr = s.left(pos).toULong();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  c = s.left( pos );
                  chan->tp.pol = c[0].latin1();
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 0 : chan->tp.coderateH = FEC_NONE; break;
                        case 12 : chan->tp.coderateH = FEC_1_2; break;
                        case 23 : chan->tp.coderateH = FEC_2_3; break;
                        case 34 : chan->tp.coderateH = FEC_3_4; break;
                        case 45 : chan->tp.coderateH = FEC_4_5; break;
                        case 56 : chan->tp.coderateH = FEC_5_6; break;
                        case 67 : chan->tp.coderateH = FEC_6_7; break;
                        case 78 : chan->tp.coderateH = FEC_7_8; break;
                        case 89 : chan->tp.coderateH = FEC_8_9; break;
                        case -1 : chan->tp.coderateH = FEC_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 0 : chan->tp.inversion = INVERSION_OFF; break;
                        case 1 : chan->tp.inversion = INVERSION_ON; break;
                        case -1 : chan->tp.inversion = INVERSION_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 8 : chan->tp.modulation = QPSK; break;
                        case 16 : chan->tp.modulation = QAM_16; break;
                        case 32 : chan->tp.modulation = QAM_32; break;
                        case 64 : chan->tp.modulation = QAM_64; break;
                        case 128 : chan->tp.modulation = QAM_128; break;
                        case 256 : chan->tp.modulation = QAM_256; break;
                        case -1 : chan->tp.modulation = QAM_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 0 : chan->tp.coderateL = FEC_NONE; break;
                        case 12 : chan->tp.coderateL = FEC_1_2; break;
                        case 23 : chan->tp.coderateL = FEC_2_3; break;
                        case 34 : chan->tp.coderateL = FEC_3_4; break;
                        case 45 : chan->tp.coderateL = FEC_4_5; break;
                        case 56 : chan->tp.coderateL = FEC_5_6; break;
                        case 67 : chan->tp.coderateL = FEC_6_7; break;
                        case 78 : chan->tp.coderateL = FEC_7_8; break;
                        case 89 : chan->tp.coderateL = FEC_8_9; break;
                        case -1 : chan->tp.coderateL = FEC_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 8 : chan->tp.bandwidth = BANDWIDTH_8_MHZ; break;
                        case 7 : chan->tp.bandwidth = BANDWIDTH_7_MHZ; break;
                        case 6 : chan->tp.bandwidth = BANDWIDTH_6_MHZ; break;
                        case -1 : chan->tp.bandwidth = BANDWIDTH_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 2 : chan->tp.transmission = TRANSMISSION_MODE_2K; break;
                        case 8 : chan->tp.transmission = TRANSMISSION_MODE_8K; break;
                        case -1 : chan->tp.transmission = TRANSMISSION_MODE_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 32 : chan->tp.guard = GUARD_INTERVAL_1_32; break;
                        case 16 : chan->tp.guard = GUARD_INTERVAL_1_16; break;
                        case 8 : chan->tp.guard = GUARD_INTERVAL_1_8; break;
                        case 4 : chan->tp.guard = GUARD_INTERVAL_1_4; break;
                        case -1 : chan->tp.guard = GUARD_INTERVAL_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  switch ( s.left(pos).toInt() ) {
                        case 0 : chan->tp.hierarchy = HIERARCHY_NONE; break;
                        case 1 : chan->tp.hierarchy = HIERARCHY_1; break;
                        case 2 : chan->tp.hierarchy = HIERARCHY_2; break;
                        case 4 : chan->tp.hierarchy = HIERARCHY_4; break;
                        case -1 : chan->tp.hierarchy = HIERARCHY_AUTO;
                  }
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  chan->num = s.left(pos).toUInt();
                  if ( chan->type==1 ) {
                        if ( chan->fta==0 ) channelsCb->insertItem( tvPix, chan->name );
                        else channelsCb->insertItem( tvcPix, chan->name );
                  }
                  else {
                        if ( chan->fta==0 ) channelsCb->insertItem( raPix, chan->name );
                        else channelsCb->insertItem( racPix, chan->name );
                  }
                  channels.append( chan );
                  if ( chan->num<=0 ) chan->num = channels.count();
                  
            }
            ret = true;
            f.close();
      }
      return ret;
}



bool DvbPanel::saveChannelList()
{
      bool ret=false;
      int i, j, k;
      QString s;
      ChannelDesc *chan=0;

      QFile f( locateLocal("appdata", "channels.dvb" ) );
      if ( f.open(IO_WriteOnly|IO_Truncate) ) {
            QTextStream tt( &f );
            tt<<"#Generated by Kaffeine 0.5\n";
            for( i=0; i<(int)channelsCb->count(); i++ ) {
                  for ( j=0; j<(int)channels.count(); j++ ) {
                        chan = channels.at(j);
                        if ( chan->name==channelsCb->text(i) ) {
                              j = -1;
                              break;
                        }
                  }
                  if ( j!=-1 ) continue;
                  if ( chan->type==1 ) {
                        if ( chan->fta ) tt<<"TVC|";
                        else tt<<"TV|";
                  }
                  else {
                        if ( chan->fta ) tt<<"RAC|";
                        else tt<<"RA|";
                  }
                  tt<< chan->name+"|";
                  tt<< s.setNum(chan->vpid)+"|";
                  for ( k=0; k<chan->napid; k++ ) {
                        tt<< s.setNum(chan->apid[k].pid);
                        if ( chan->apid[k].lang!="" ) tt<< "("+chan->apid[k].lang+")";
                        if ( chan->apid[k].ac3 ) tt<< "(ac3)";
                        tt<< ",";
                  }
                  tt<< "|";
                  tt<< s.setNum(chan->ttpid)+"|";
                  tt<< s.setNum(chan->sid)+"|";
                  tt<< s.setNum(chan->tp.tsid)+"|";
                  switch ( chan->tp.type ) {
                        case FE_QPSK : tt<< "S"; break;
                        case FE_QAM : tt<< "C"; break;
                        case FE_OFDM : tt<< "T";
                  }
                  tt<< chan->tp.source;
                  tt<< "|";
                  tt<< s.setNum(chan->tp.freq)+"|";
                  tt<< s.setNum(chan->tp.sr)+"|";
                  if ( chan->tp.pol=='h'  ) tt<< "h|";
                  else tt<< "v|";
                  switch ( chan->tp.coderateH ) {
                        case FEC_NONE : tt<< "0|"; break;
                        case FEC_1_2 : tt<< "12|"; break;
                        case FEC_2_3 : tt<< "23|"; break;
                        case FEC_3_4 : tt<< "34|"; break;
                        case FEC_4_5 : tt<< "45|"; break;
                        case FEC_5_6 : tt<< "56|"; break;
                        case FEC_6_7 : tt<< "67|"; break;
                        case FEC_7_8 : tt<< "78|"; break;
                        case FEC_8_9 : tt<< "89|"; break;
                        case FEC_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.inversion ) {
                        case INVERSION_OFF : tt<< "0|"; break;
                        case INVERSION_ON : tt<< "1|"; break;
                        case INVERSION_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.modulation ) {
                        case QPSK : tt<< "8|"; break;
                        case QAM_16 : tt<< "16|"; break;
                        case QAM_32 : tt<< "32|"; break;
                        case QAM_64 : tt<< "64|"; break;
                        case QAM_128 : tt<< "128|"; break;
                        case QAM_256 : tt<< "256|"; break;
                        case QAM_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.coderateL ) {
                        case FEC_NONE : tt<< "0|"; break;
                        case FEC_1_2 : tt<< "12|"; break;
                        case FEC_2_3 : tt<< "23|"; break;
                        case FEC_3_4 : tt<< "34|"; break;
                        case FEC_4_5 : tt<< "45|"; break;
                        case FEC_5_6 : tt<< "56|"; break;
                        case FEC_6_7 : tt<< "67|"; break;
                        case FEC_7_8 : tt<< "78|"; break;
                        case FEC_8_9 : tt<< "89|"; break;
                        case FEC_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.bandwidth ) {
                        case BANDWIDTH_8_MHZ : tt<< "8|"; break;
                        case BANDWIDTH_7_MHZ : tt<< "7|"; break;
                        case BANDWIDTH_6_MHZ : tt<< "6|"; break;
                        case BANDWIDTH_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.transmission ) {
                        case TRANSMISSION_MODE_8K : tt<< "8|"; break;
                        case TRANSMISSION_MODE_2K : tt<< "2|"; break;
                        case TRANSMISSION_MODE_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.guard ) {
                        case GUARD_INTERVAL_1_32 : tt<< "32|"; break;
                        case GUARD_INTERVAL_1_16 : tt<< "16|"; break;
                        case GUARD_INTERVAL_1_8 : tt<< "8|"; break;
                        case GUARD_INTERVAL_1_4 : tt<< "4|"; break;
                        case GUARD_INTERVAL_AUTO : tt<< "-1|";
                  }
                  switch ( chan->tp.hierarchy ) {
                        case HIERARCHY_NONE : tt<< "0|"; break;
                        case HIERARCHY_1 : tt<< "1|"; break;
                        case HIERARCHY_2 : tt<< "2|"; break;
                        case HIERARCHY_4 : tt<< "4|"; break;
                        case HIERARCHY_AUTO : tt<< "-1|";
                  }
                  tt<< s.setNum(chan->num)+"|";
                  tt<< "\n";
            }
            ret = true;
            f.close();
      }
      return ret;
}



bool DvbPanel::getTimerList()
{
      bool ret=false;
      QString s;
      int pos;
      RecTimer *t;

      QFile f( locateLocal("appdata", "timers.dvb" ) );
      if ( f.open(IO_ReadOnly) ) {
            QTextStream tt( &f );
            while ( !tt.eof() ) {
                  s = tt.readLine();
                  if ( s.startsWith("#") ) continue;
                  t = new RecTimer();
                  pos = s.find("|");
                  t->name = s.left( pos );
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  t->channel = s.left( pos );
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  t->begin = QDateTime::fromString( s.left( pos ), Qt::ISODate );
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  t->duration = QTime::fromString( s.left( pos ) );
                  s = s.right( s.length()-pos-1 );
                  pos = s.find("|");
                  t->filetype = s.left( pos ).toInt();
                  t->running = 0;
                  timers.append( t );
            }
            ret = true;
            f.close();
      }
      return ret;
}



bool DvbPanel::saveTimerList()
{
      bool ret=false;
      int i;
      QString s;
      RecTimer *t;

      QFile f( locateLocal("appdata", "timers.dvb" ) );
      if ( f.open(IO_WriteOnly|IO_Truncate) ) {
            QTextStream tt( &f );
            tt<<"#Generated by Kaffeine 0.5\n";
            for( i=0; i<(int)timers.count(); i++ ) {
                  t = timers.at(i);
                  if ( t->running ) continue;
                  tt<< t->name+"|";
                  tt<< t->channel+"|";
                  tt<< t->begin.toString("yyyy-MM-ddThh:mm:ss")+"|";
                  tt<< t->duration.toString()+"|";
                  tt<< s.setNum(t->filetype)+"|";
                  tt<< "\n";
            }
            ret = true;
            f.close();
      }
      return ret;
}



bool DvbPanel::close()
{
      int ret=0;
      
      if ( dvb->hasRec() ) {
            ret = KMessageBox::questionYesNo( 0, i18n("Kaffeine is still recording. Do you really want to quit ?") );
            if ( ret==KMessageBox::Yes ) {
                  stopLive();
                  return true;
            }
            else return false;
      }
      if ( timers.count() ) {
            ret = KMessageBox::questionYesNo( 0, i18n("Kaffeine has queued timers. Do you really want to quit ?") );
            if ( ret==KMessageBox::Yes ) {
                  stopLive();
                  return true;
            }
            else return false;
      }
      stopLive();
      return true;
}


            
DvbPanel::~DvbPanel()
{
      saveTimerList();
      dvbConfig->saveConfig();
      if ( dvb ) delete dvb;
}

Generated by  Doxygen 1.6.0   Back to index