|
|
|
/*
|
|
|
|
* dvbpanel.cpp
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2007 Christophe Thommeret <hftom@free.fr>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/statvfs.h>
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqwhatsthis.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqpopupmenu.h>
|
|
|
|
#include <tqmap.h>
|
|
|
|
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <kinputdialog.h>
|
|
|
|
#include <kicondialog.h>
|
|
|
|
#include <tdeaction.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <tdefiledialog.h>
|
|
|
|
#include <ktrader.h>
|
|
|
|
#include <kxmlguifactory.h>
|
|
|
|
#include <tdeparts/componentfactory.h>
|
|
|
|
|
|
|
|
#include "kaffeinedvbplugin.h"
|
|
|
|
#include "dvbpanel.h"
|
|
|
|
#include "channeldesc.h"
|
|
|
|
#include "dvbstream.h"
|
|
|
|
#include "kevents.h"
|
|
|
|
#include "broadcasteditor.h"
|
|
|
|
#include "channeleditor.h"
|
|
|
|
|
|
|
|
#define CHANICONSIZE 28
|
|
|
|
|
|
|
|
#define MODE_FREE 0
|
|
|
|
#define MODE_LIVE 100
|
|
|
|
#define MODE_BROADCAST 200
|
|
|
|
#define MODE_RECORD 300
|
|
|
|
#define MODE_CANTDO 400
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DIconViewItem::DIconViewItem( DvbPanel *pan, TQIconView *parent, const TQString &text, const TQPixmap &icon )
|
|
|
|
: KIconViewItem( parent, text, icon )
|
|
|
|
{
|
|
|
|
panel = pan;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DIconViewItem::dropped( TQDropEvent *e, const TQValueList<TQIconDragItem> & )
|
|
|
|
{
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
if ( !dropEnabled() )
|
|
|
|
return;
|
|
|
|
if ( TQTextDrag::decode( e, s ) )
|
|
|
|
panel->moveChannel( text(), s );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DListView::DListView( TQWidget *parent ) : TDEListView( parent )
|
|
|
|
{
|
|
|
|
visibleItems = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQDragObject* DListView::dragObject()
|
|
|
|
{
|
|
|
|
if ( currentItem() )
|
|
|
|
return new TQTextDrag( currentItem()->text(1), this );
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DvbPanel::DvbPanel( TQWidget *parent, TQObject *objParent, const char *name ) : KaffeineInput(objParent,name)
|
|
|
|
{
|
|
|
|
browseDvbStream = -1;
|
|
|
|
plug = NULL;
|
|
|
|
|
|
|
|
isTuning = false;
|
|
|
|
timeShiftFileName = "";
|
|
|
|
timersDialog = 0;
|
|
|
|
currentCategory = "All";
|
|
|
|
channels.setAutoDelete( true );
|
|
|
|
timers.setAutoDelete( true );
|
|
|
|
dvb.setAutoDelete( true );
|
|
|
|
|
|
|
|
mainWidget = new TQVBox( parent );
|
|
|
|
mainWidget->setSizePolicy( TQSizePolicy (TQSizePolicy::Preferred, TQSizePolicy::Preferred) );
|
|
|
|
split = new TQSplitter( mainWidget );
|
|
|
|
split->setOpaqueResize( true );
|
|
|
|
pbox = new TQVBox( split );
|
|
|
|
iconView = new KIconView( pbox );
|
|
|
|
iconView->setVScrollBarMode( TQScrollView::AlwaysOff );
|
|
|
|
iconView->setHScrollBarMode( TQScrollView::AlwaysOff );
|
|
|
|
iconView->horizontalScrollBar()->setFixedHeight( 0 );
|
|
|
|
connect( iconView, TQT_SIGNAL(rightButtonPressed(TQIconViewItem*,const TQPoint&)), this, TQT_SLOT(catContextMenu(TQIconViewItem*,const TQPoint&)) );
|
|
|
|
connect( iconView, TQT_SIGNAL(clicked(TQIconViewItem*)), this, TQT_SLOT(catSelected(TQIconViewItem*)) );
|
|
|
|
iconView->setArrangement(TQIconView::TopToBottom);
|
|
|
|
iconView->setMargin(0);
|
|
|
|
iconView->setSpacing(0);
|
|
|
|
iconView->setItemsMovable(false);
|
|
|
|
iconView->setResizeMode(TQIconView::Adjust);
|
|
|
|
iconView->setSizePolicy( TQSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
playerBox = new TQVBox( pbox );
|
|
|
|
playerBox->setMinimumWidth( 200 );
|
|
|
|
panel = new TQFrame( split );
|
|
|
|
panel->setLineWidth(1);
|
|
|
|
panel->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
|
|
|
|
split->moveToFirst( panel );
|
|
|
|
split->setResizeMode( panel, TQSplitter::KeepSize );
|
|
|
|
|
|
|
|
TQVBoxLayout *vb = new TQVBoxLayout( panel, 3, 3 );
|
|
|
|
channelsBtn = new TQToolButton( panel );
|
|
|
|
channelsBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( channelsBtn, i18n("Channels"));
|
|
|
|
dateBtn = new TQToolButton( panel );
|
|
|
|
dateBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( dateBtn, i18n("Timers"));
|
|
|
|
infoBtn = new TQToolButton( panel );
|
|
|
|
infoBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( infoBtn, i18n("Electronic Program Guide"));
|
|
|
|
osdBtn = new TQToolButton( panel );
|
|
|
|
osdBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( osdBtn, i18n("OSD"));
|
|
|
|
configBtn = new TQToolButton( panel );
|
|
|
|
configBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( configBtn, i18n("DVB settings"));
|
|
|
|
recallBtn = new TQToolButton( panel );
|
|
|
|
recallBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( recallBtn, i18n("Recall"));
|
|
|
|
TQHBoxLayout *h1 = new TQHBoxLayout();
|
|
|
|
h1->addItem( new TQSpacerItem( 1, 1, TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
h1->addWidget( channelsBtn );
|
|
|
|
h1->addWidget( dateBtn );
|
|
|
|
h1->addWidget( infoBtn );
|
|
|
|
h1->addWidget( osdBtn );
|
|
|
|
h1->addWidget( configBtn );
|
|
|
|
h1->addWidget( recallBtn );
|
|
|
|
h1->addItem( new TQSpacerItem( 1, 1, TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
vb->addLayout( h1 );
|
|
|
|
|
|
|
|
h1 = new TQHBoxLayout();
|
|
|
|
searchBtn = new TQToolButton( panel );
|
|
|
|
searchBtn->setAutoRaise( true );
|
|
|
|
TQToolTip::add( searchBtn, i18n("Search channel(s)"));
|
|
|
|
TQLabel* filterLabel = new TQLabel( i18n("Filter") + ":", panel );
|
|
|
|
searchLE = new KLineEdit( panel );
|
|
|
|
searchLE->setFocusPolicy( TQ_ClickFocus );
|
|
|
|
h1->addWidget( searchBtn );
|
|
|
|
h1->addWidget( filterLabel );
|
|
|
|
h1->addWidget( searchLE );
|
|
|
|
vb->addLayout( h1 );
|
|
|
|
|
|
|
|
channelsCb = new DListView( panel );
|
|
|
|
channelsCb->setHScrollBarMode( TQListView::AlwaysOff );
|
|
|
|
//channelsCb->setPaletteBackgroundColor( TQColor(255,255,200) );
|
|
|
|
connect( channelsCb, TQT_SIGNAL(itemRenamed(TQListViewItem*)), this, TQT_SLOT(channelNumberChanged(TQListViewItem*)) );
|
|
|
|
connect( channelsCb, TQT_SIGNAL(doubleClicked(TQListViewItem*)), this, TQT_SLOT(channelSelected(TQListViewItem*)) );
|
|
|
|
connect( channelsCb, TQT_SIGNAL(clicked(TQListViewItem*)), this, TQT_SLOT(channelClicked(TQListViewItem*)) );
|
|
|
|
connect( channelsCb, TQT_SIGNAL(contextMenuRequested(TQListViewItem*,const TQPoint&,int)), this, TQT_SLOT(channelPopup(TQListViewItem*,const TQPoint&,int)) );
|
|
|
|
channelsCb->setItemsRenameable( true );
|
|
|
|
channelsCb->addColumn( i18n("Number") );
|
|
|
|
channelsCb->addColumn( i18n("Name") );
|
|
|
|
channelsCb->addColumn( i18n("Source") );
|
|
|
|
channelsCb->setAllColumnsShowFocus( true );
|
|
|
|
channelsCb->setSizePolicy( TQSizePolicy (TQSizePolicy::Preferred, TQSizePolicy::MinimumExpanding) );
|
|
|
|
//channelsCb->setEnabled( false );
|
|
|
|
vb->addWidget( channelsCb );
|
|
|
|
|
|
|
|
h1 = new TQHBoxLayout();
|
|
|
|
recordBtn = new TQToolButton( panel );
|
|
|
|
TQToolTip::add( recordBtn, i18n("Instant Record") );
|
|
|
|
recordBtn->setToggleButton( true );
|
|
|
|
h1->addWidget( recordBtn );
|
|
|
|
broadcastBtn = new TQToolButton( panel );
|
|
|
|
TQToolTip::add( broadcastBtn, i18n("Broadcast") );
|
|
|
|
h1->addWidget( broadcastBtn );
|
|
|
|
vb->addLayout( h1 );
|
|
|
|
|
|
|
|
h1 = new TQHBoxLayout();
|
|
|
|
h1->addItem( new TQSpacerItem( 1, 1, TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
shiftLed = new KLed( panel );
|
|
|
|
shiftLed->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
|
|
|
|
shiftLed->setDarkFactor( 500 );
|
|
|
|
shiftLed->off();
|
|
|
|
TQToolTip::add( shiftLed, i18n("Time shifting") );
|
|
|
|
h1->addWidget( shiftLed );
|
|
|
|
h1->addItem( new TQSpacerItem( 1, 1, TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
recordLed = new KLed( panel );
|
|
|
|
recordLed->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
|
|
|
|
recordLed->setColor( TQColor( 255,0,0 ) );
|
|
|
|
recordLed->setDarkFactor( 500 );
|
|
|
|
recordLed->off();
|
|
|
|
TQToolTip::add( recordLed, i18n("Recording") );
|
|
|
|
h1->addWidget( recordLed );
|
|
|
|
h1->addItem( new TQSpacerItem( 1, 1, TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
broadcastLed = new KLed( panel );
|
|
|
|
broadcastLed->setSizePolicy( TQSizePolicy( TQSizePolicy::Fixed, TQSizePolicy::Fixed ) );
|
|
|
|
broadcastLed->setColor( TQColor( 255,128,0 ) );
|
|
|
|
broadcastLed->setDarkFactor( 500 );
|
|
|
|
broadcastLed->off();
|
|
|
|
TQToolTip::add( broadcastLed, i18n("Broadcasting") );
|
|
|
|
h1->addWidget( broadcastLed );
|
|
|
|
h1->addItem( new TQSpacerItem( 1, 1, TQSizePolicy::Preferred, TQSizePolicy::Minimum ) );
|
|
|
|
vb->addLayout( h1 );
|
|
|
|
|
|
|
|
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 );
|
|
|
|
TQIconSet iconset;
|
|
|
|
iconset.setPixmap( icon->loadIcon( "filesave", KIcon::Small ), TQIconSet::Small );
|
|
|
|
iconset.setPixmap( icon->loadIcon( "player_record", KIcon::Small), TQIconSet::Small, TQIconSet::Normal, TQIconSet::On );
|
|
|
|
recordBtn->setIconSet( iconset );
|
|
|
|
broadcastBtn->setIconSet( icon->loadIconSet("network_local", KIcon::Small) );
|
|
|
|
dateBtn->setIconSet( icon->loadIconSet("date", KIcon::Small) );
|
|
|
|
infoBtn->setIconSet( icon->loadIconSet("view_text", KIcon::Small) );
|
|
|
|
osdBtn->setIconSet( icon->loadIconSet("info", KIcon::Small) );
|
|
|
|
channelsBtn->setIconSet( icon->loadIconSet("kdvbtv", KIcon::Small) );
|
|
|
|
configBtn->setIconSet( icon->loadIconSet("configure", KIcon::Small) );
|
|
|
|
recallBtn->setIconSet( icon->loadIconSet("reload", KIcon::Small) );
|
|
|
|
searchBtn->setIconSet( icon->loadIconSet("locationbar_erase", KIcon::Small) );
|
|
|
|
|
|
|
|
setXMLFile("kaffeinedvb.rc");
|
|
|
|
setupActions();
|
|
|
|
|
|
|
|
connect( this, TQT_SIGNAL(zap(ChannelDesc*)), TQT_SLOT(dvbZap(ChannelDesc*)) );
|
|
|
|
connect( configBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(showConfigDialog()));
|
|
|
|
connect( recallBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(recallZap()));
|
|
|
|
|
|
|
|
connect( recordBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(setRecord()) );
|
|
|
|
connect( broadcastBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(setBroadcast()) );
|
|
|
|
connect( infoBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(showEvents()) );
|
|
|
|
connect( channelsBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(scanner()) );
|
|
|
|
connect( dateBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(showTimers()) );
|
|
|
|
connect( osdBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(dvbOSD()));
|
|
|
|
connect( searchBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(resetSearch()) );
|
|
|
|
connect(searchLE, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(searchChannel(const TQString&)));
|
|
|
|
|
|
|
|
connect( &timersTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(checkTimers()) );
|
|
|
|
connect( &osdTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(resetOSD()) );
|
|
|
|
connect( &showOsdTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(dvbOSD()) );
|
|
|
|
connect( &tuningTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(setTuning()) );
|
|
|
|
connect( &stopTuningTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(setTuning()) );
|
|
|
|
connect( &diskTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(diskStatus()) );
|
|
|
|
|
|
|
|
setConfig();
|
|
|
|
|
|
|
|
updown = 1;
|
|
|
|
autocount = 0;
|
|
|
|
delete icon;
|
|
|
|
|
|
|
|
events.loadEpg();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::togglePanel()
|
|
|
|
{
|
|
|
|
if ( panel->isHidden() )
|
|
|
|
panel->show();
|
|
|
|
else
|
|
|
|
panel->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::diskStatus()
|
|
|
|
{
|
|
|
|
double freemb;
|
|
|
|
struct statvfs buf;
|
|
|
|
|
|
|
|
if ( statvfs( dvbConfig->shiftDir.local8Bit(), &buf ) ) {
|
|
|
|
fprintf(stderr,"Couldn't get file system statistics\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
freemb = (double)(((double)(buf.f_bavail)*(double)(buf.f_bsize))/(1024.0*1024.0));
|
|
|
|
if ( freemb<300 )
|
|
|
|
emit showOSD( i18n("Warning: low disc space")+TQString(" (%1").arg((int)freemb)+i18n("MB")+")", 5000, 3 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::channelPopup( TQListViewItem *it, const TQPoint &pos, int col )
|
|
|
|
{
|
|
|
|
TQPoint p=pos;
|
|
|
|
|
|
|
|
if ( !it )
|
|
|
|
return;
|
|
|
|
|
|
|
|
int i=col, j;
|
|
|
|
TQImage img;
|
|
|
|
TQPixmap pix;
|
|
|
|
TQString name = it->text(1);
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
TQPopupMenu *pop = new TQPopupMenu();
|
|
|
|
pop->insertItem( i18n("Select icon..."), 1 );
|
|
|
|
pop->insertItem( i18n("Edit..."), 2 );
|
|
|
|
i = 0;
|
|
|
|
i = pop->exec( TQCursor::pos() );
|
|
|
|
switch ( i ) {
|
|
|
|
case 0 :
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
|
|
s = KFileDialog::getOpenFileName( TQString(), "image/png image/jpeg image/gif image/x-bmp image/x-xpm", 0, i18n("Choose channel icon"));
|
|
|
|
if ( s.isEmpty() )
|
|
|
|
break;
|
|
|
|
img = TQImage( s );
|
|
|
|
if ( img.isNull() )
|
|
|
|
break;
|
|
|
|
if ( img.width()>img.height() )
|
|
|
|
img = img.smoothScale( CHANICONSIZE, img.height()*CHANICONSIZE/img.width() );
|
|
|
|
else
|
|
|
|
img = img.smoothScale( img.width()*CHANICONSIZE/img.height(), CHANICONSIZE );
|
|
|
|
pix.convertFromImage( img );
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
if ( channels.at(j)->name==name ) {
|
|
|
|
channels.at(j)->pix = pix;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pix.save( dvbConfig->dvbConfigIconsDir+name, "PNG" );
|
|
|
|
fillChannelList();
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
editChannel( name );
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
delete pop;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool DvbPanel::editChannel( TQString &name )
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
ChannelDesc *chan=0;
|
|
|
|
TQStringList list;
|
|
|
|
TQPixmap pix;
|
|
|
|
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
chan = channels.at(j);
|
|
|
|
if ( chan->name==name ) {
|
|
|
|
j = -1;
|
|
|
|
list.append( chan->tp.source );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( j==-1 ) {
|
|
|
|
ChannelEditor dlg( list, false, chan, &channels, mainWidget );
|
|
|
|
int ret = dlg.exec();
|
|
|
|
if ( ret==ChannelEditor::Accepted ) {
|
|
|
|
pix.load( dvbConfig->dvbConfigIconsDir+chan->name );
|
|
|
|
if ( !pix.isNull() )
|
|
|
|
chan->pix = pix;
|
|
|
|
else {
|
|
|
|
if ( chan->type==1 ) {
|
|
|
|
if ( chan->fta )
|
|
|
|
pix = tvcPix;
|
|
|
|
else
|
|
|
|
pix = tvPix;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( chan->fta )
|
|
|
|
pix = racPix;
|
|
|
|
else
|
|
|
|
pix = raPix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fillChannelList( chan );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::getTargets( TQStringList &uiNames, TQStringList &iconNames, TQStringList &targetNames )
|
|
|
|
{
|
|
|
|
uiNames.append( i18n("Digital TV") );
|
|
|
|
iconNames.append( "tv" );
|
|
|
|
targetNames.append( "DVB" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::execTarget( const TQString &target )
|
|
|
|
{
|
|
|
|
if ( target=="DVB" ) {
|
|
|
|
if ( !channelsCb->isEnabled() ) {
|
|
|
|
KMessageBox::information( mainWidget, i18n("Live digital TV only works with the xine engine.") );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
emit showMe( this );
|
|
|
|
TQTimer::singleShot( 100, this, TQT_SLOT(playLastChannel()) );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setupActions()
|
|
|
|
{
|
|
|
|
new TDEAction(i18n("OSD Next Channel"), "next", CTRL+SHIFT+Key_W, this, TQT_SLOT(dvbOSDNext()), actionCollection(), "dvb_browse_next");
|
|
|
|
new TDEAction(i18n("OSD Previous Channel"), "previous", CTRL+SHIFT+Key_Q, this, TQT_SLOT(dvbOSDPrev()), actionCollection(),"dvb_browse_prev");
|
|
|
|
new TDEAction(i18n("OSD Zap"), "ok", CTRL+SHIFT+Key_E, this, TQT_SLOT(dvbOSDZap()), actionCollection(), "dvb_browse_zap");
|
|
|
|
new TDEAction(i18n("OSD Next Event"), "down", CTRL+SHIFT+Key_S, this, TQT_SLOT(dvbOSDAdvance()), actionCollection(), "dvb_browse_advance");
|
|
|
|
new TDEAction(i18n("OSD Previous Event"), "up", CTRL+SHIFT+Key_A, this, TQT_SLOT(dvbOSDRetreat()), actionCollection(), "dvb_browse_retreat");
|
|
|
|
new TDEAction(i18n("Instant Record"), "filesave", 0, this, TQT_SLOT(setRecord()), actionCollection(), "dvb_instant_record");
|
|
|
|
new TDEAction(i18n("Recall"), "reload", CTRL+SHIFT+Key_Z, this, TQT_SLOT(recallZap()), actionCollection(), "dvb_recall");
|
|
|
|
new TDEAction(i18n("Show OSD"), "info", Key_O, this, TQT_SLOT(dvbOSD()), actionCollection(), "dvb_show_osd");
|
|
|
|
new TDEAction(i18n("EPG..."), "view_text", Key_G, this, TQT_SLOT(showEvents()), actionCollection(), "dvb_show_epg");
|
|
|
|
new TDEAction(i18n("Timers..."), "date", Key_T, this, TQT_SLOT(showTimers()), actionCollection(), "dvb_show_timers");
|
|
|
|
new TDEAction(i18n("Broadcasting..."), "network_local", Key_B, this, TQT_SLOT(setBroadcast()), actionCollection(), "dvb_show_broadcast");
|
|
|
|
new TDEAction(i18n("Channels..."), "kdvbtv", Key_C, this, TQT_SLOT(scanner()), actionCollection(), "dvb_channels");
|
|
|
|
new TDEAction(i18n("Configure DVB..."), "configure", CTRL|Key_C, this, TQT_SLOT(showConfigDialog()), actionCollection(), "dvb_config");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQWidget *DvbPanel::wantPlayerWindow()
|
|
|
|
{
|
|
|
|
return playerBox;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQWidget *DvbPanel::inputMainWidget()
|
|
|
|
{
|
|
|
|
return mainWidget;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::searchChannel( const TQString &text )
|
|
|
|
{
|
|
|
|
int i, c=-1;
|
|
|
|
TQListViewItemIterator it( channelsCb );
|
|
|
|
if ( !it.current() )
|
|
|
|
return;
|
|
|
|
for ( i=0; i<channelsCb->columns(); i++ ) {
|
|
|
|
if ( channelsCb->columnText(i)==i18n("Name") ) {
|
|
|
|
c = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( c==-1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
channelsCb->visibleItems = 0;
|
|
|
|
|
|
|
|
while ( it.current() ) {
|
|
|
|
if ( text.isEmpty() || it.current()->text( c ).contains( text, false ) ) {
|
|
|
|
it.current()->setVisible(true);
|
|
|
|
++channelsCb->visibleItems;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
it.current()->setVisible(false);
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::resetSearch()
|
|
|
|
{
|
|
|
|
searchLE->clear();
|
|
|
|
searchChannel( "" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::channelNumberChanged( TQListViewItem *it )
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
bool ok;
|
|
|
|
unsigned int oldNum=0;
|
|
|
|
unsigned int num = it->text(0).toUInt( &ok, 10 );
|
|
|
|
|
|
|
|
for ( i=0; i<(int)channels.count(); i++ ) {
|
|
|
|
if ( channels.at(i)->name==it->text(1) ) {
|
|
|
|
oldNum = channels.at(i)->num;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( num && oldNum ) {
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
if ( channels.at(j)->num==num ) {
|
|
|
|
channels.at(j)->num = oldNum;
|
|
|
|
channels.at(i)->num = num;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((int)num > maxChannelNumber)
|
|
|
|
maxChannelNumber = num;
|
|
|
|
if ((int)num < minChannelNumber)
|
|
|
|
minChannelNumber = num;
|
|
|
|
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::catSelected( TQIconViewItem *it )
|
|
|
|
{
|
|
|
|
if ( !it ) return;
|
|
|
|
|
|
|
|
if ( it->text()==i18n("All") )
|
|
|
|
currentCategory = "All";
|
|
|
|
else if ( it->text()==i18n("TV") )
|
|
|
|
currentCategory = "TV";
|
|
|
|
else if ( it->text()==i18n("Radio") )
|
|
|
|
currentCategory = "Radio";
|
|
|
|
else
|
|
|
|
currentCategory = it->text();
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::catContextMenu( TQIconViewItem *it, const TQPoint &p )
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
TQString name, icon;
|
|
|
|
int i=0, ret;
|
|
|
|
|
|
|
|
TQPopupMenu *pop = new TQPopupMenu();
|
|
|
|
if ( !it ) {
|
|
|
|
pop->insertItem( i18n("New Category..."), 0 );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pop->insertItem( i18n("Change Icon..."), 1 );
|
|
|
|
if ( it->text()!=i18n("All") && it->text()!=i18n("Radio") && it->text()!=i18n("TV") )
|
|
|
|
pop->insertItem( i18n("Delete Category..."), 2 );
|
|
|
|
}
|
|
|
|
i = pop->exec( p );
|
|
|
|
switch ( i ) {
|
|
|
|
case 0 :
|
|
|
|
name = KInputDialog::getText( i18n("New Category"), i18n("Enter a name for this category:"), TQString(), &ok);
|
|
|
|
for ( TQIconViewItem *qitem = iconView->firstItem(); qitem; qitem = qitem->nextItem() ) {
|
|
|
|
if ( qitem->text()==name )
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
if ( ok ) {
|
|
|
|
KIconViewItem* item = new DIconViewItem(this, iconView, name, TDEGlobal::iconLoader()->loadIcon("kaffeine", KIcon::NoGroup, KIcon::SizeSmallMedium));
|
|
|
|
item->setDropEnabled( true );
|
|
|
|
dvbConfig->addCategory( name, "kaffeine" );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
|
|
icon = KIconDialog::getIcon();
|
|
|
|
if ( !icon.isEmpty() ) {
|
|
|
|
it->setPixmap( TDEGlobal::iconLoader()->loadIcon(icon, KIcon::NoGroup, KIcon::SizeSmallMedium) );
|
|
|
|
dvbConfig->changeIconCategory( it->text(), icon );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2 :
|
|
|
|
ret = KMessageBox::questionYesNo( mainWidget, i18n("Do you really want to delete this category?") );
|
|
|
|
if ( ret==KMessageBox::Yes ) {
|
|
|
|
dvbConfig->removeCategory( it->text() );
|
|
|
|
delete it;
|
|
|
|
currentCategory = "All";
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
delete pop;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::moveChannel( const TQString &cat, const TQString &name )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ChannelDesc *chan;
|
|
|
|
TQListViewItem *it;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)channels.count(); i++ ) {
|
|
|
|
chan = channels.at(i);
|
|
|
|
if ( chan->name==name ) {
|
|
|
|
if ( cat==i18n("All") )
|
|
|
|
chan->category = "";
|
|
|
|
else
|
|
|
|
chan->category = cat;
|
|
|
|
it = channelsCb->currentItem();
|
|
|
|
if ( it && currentCategory!="All" && currentCategory!="TV" && currentCategory!="Radio" )
|
|
|
|
delete it;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dumpEvents()
|
|
|
|
{
|
|
|
|
EventSource *esrc;
|
|
|
|
EventTsid *et;
|
|
|
|
EventSid *es;
|
|
|
|
TQPtrList<EventDesc> *esEvents;
|
|
|
|
EventDesc *desc;
|
|
|
|
int i, k, j, m, n;
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
TQFile f( TQDir::homeDirPath()+"/kaffeine_dvb_events.txt" );
|
|
|
|
if ( f.open(IO_WriteOnly|IO_Truncate) ) {
|
|
|
|
fprintf( stderr, "Creating events file.\n");
|
|
|
|
TQTextStream tt( &f );
|
|
|
|
tt << "Saved: "+TQDateTime::currentDateTime().toString( "dd-MM-yyyy hh:mm:ss" )+"\n";
|
|
|
|
k= 0;
|
|
|
|
for( i=0; i<events.getNSource(); i++ ) {
|
|
|
|
if ( !(esrc=events.getNEventSource( i )) )
|
|
|
|
continue;
|
|
|
|
tt << esrc->getSource()+TQString(" : %1 TS with events.\n").arg( esrc->getNTsid() );
|
|
|
|
for ( m=0; m<esrc->getNTsid(); m++ ) {
|
|
|
|
if ( !(et=esrc->getNEventTsid( m )) )
|
|
|
|
continue;
|
|
|
|
tt << TQString("TSID %1 : %2 services with events\n").arg( et->getTsid() ).arg( et->getNSid() );
|
|
|
|
for ( n=0; n<et->getNSid(); n++ ) {
|
|
|
|
if ( !(es=et->getNEventSid( n )) )
|
|
|
|
continue;
|
|
|
|
tt << TQString(" SID %1 : %2 events\n").arg( es->getSid() ).arg( es->getNDesc() );
|
|
|
|
k+= es->getNDesc();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tt << "Number of events : "+s.setNum( k )+"\n";
|
|
|
|
fprintf( stderr, "Number of events : %d\n", k );
|
|
|
|
tt << "-------------------------\n";
|
|
|
|
tt << "\n";
|
|
|
|
for( i=0; i<events.getNSource(); i++ ) {
|
|
|
|
if ( !(esrc=events.getNEventSource( i )) )
|
|
|
|
continue;
|
|
|
|
for ( m=0; m<esrc->getNTsid(); m++ ) {
|
|
|
|
if ( !(et=esrc->getNEventTsid( m )) )
|
|
|
|
continue;
|
|
|
|
for ( n=0; n<et->getNSid(); n++ ) {
|
|
|
|
if ( !(es=et->getNEventSid( n )) )
|
|
|
|
continue;
|
|
|
|
esEvents = es->getEvents();
|
|
|
|
es->lock();
|
|
|
|
for ( j=0; j<(int)esEvents->count(); j++ ) {
|
|
|
|
if ( !(desc=esEvents->at( j )) )
|
|
|
|
continue;
|
|
|
|
tt << "Source: "+desc->source+"\n";
|
|
|
|
tt << TQString("Network ID: %1\n").arg(desc->nid);
|
|
|
|
tt << TQString("Transport Stream ID: %1\n").arg(desc->tsid);
|
|
|
|
tt << TQString("Service ID: %1\n").arg(desc->sid);
|
|
|
|
tt << TQString("Event ID: %1\n").arg(desc->eid);
|
|
|
|
tt << "Title: "+desc->title+"\n";
|
|
|
|
tt << "Subtitle: "+desc->subtitle+"\n";
|
|
|
|
tt << desc->startDateTime.toString( "dd-MM-yyyy hh:mm:ss" )+"\n";
|
|
|
|
tt << desc->duration.toString( "hh:mm:ss" )+"\n";
|
|
|
|
s = "";
|
|
|
|
for ( k=0; k<(int)desc->shortEvents.count(); k++ ) {
|
|
|
|
s = s + desc->shortEvents.at(k)->name;
|
|
|
|
if (!desc->shortEvents.at(k)->name.isEmpty() && !desc->shortEvents.at(k)->text.isEmpty()) {
|
|
|
|
s = s + " : ";
|
|
|
|
s = s + desc->shortEvents.at(k)->text;
|
|
|
|
s = s+". ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for ( k=0; k<(int)desc->extEvents.count(); k++ )
|
|
|
|
s = s+ *desc->extEvents.at(k);
|
|
|
|
tt << s+"\n";
|
|
|
|
tt << "\n";
|
|
|
|
}
|
|
|
|
es->unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
else fprintf( stderr, "Can't create events file!\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::channelClicked( TQListViewItem *it )
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ChannelDesc> iter( channels );
|
|
|
|
ChannelDesc *itdesc, *desc=0;
|
|
|
|
DvbStream *d = 0;
|
|
|
|
|
|
|
|
if ( !it )
|
|
|
|
return;
|
|
|
|
|
|
|
|
iter.toFirst();
|
|
|
|
while ( (itdesc=iter.current())!=0 ) {
|
|
|
|
if ( itdesc->name==it->text(1) ) {
|
|
|
|
desc = itdesc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !desc )
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int j = 0; j < (int)dvb.count(); j ++) {
|
|
|
|
if (dvb.at(j)->canSource(desc)) {
|
|
|
|
d = dvb.at(j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
osdMode = 0;
|
|
|
|
dvbOSD( *desc, d );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::resetOSD()
|
|
|
|
{
|
|
|
|
osdMode = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSD()
|
|
|
|
{
|
|
|
|
DvbStream *d = 0;
|
|
|
|
|
|
|
|
if (browseDvbStream != -1 && osdMode != 0) {
|
|
|
|
dvbOSDSkip(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasLive() ) {
|
|
|
|
d = dvb.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( d )
|
|
|
|
dvbOSD( d->getLiveChannel(), d );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDZap()
|
|
|
|
{
|
|
|
|
ChannelDesc *chan = 0;
|
|
|
|
|
|
|
|
if (browseDvbStream == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
osdMode = 0;
|
|
|
|
|
|
|
|
for (int i=0; i<(int)channels.count(); i++) {
|
|
|
|
if ((int) channels.at(i)->num == browseDvbStream) {
|
|
|
|
chan = channels.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!chan)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dvbZap(chan);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDNext()
|
|
|
|
{
|
|
|
|
browseDvbTimeShift = -1;
|
|
|
|
osdMode = 0;
|
|
|
|
|
|
|
|
dvbOSDSkip(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDSkip(int skip, int timeShift /* = 0 */)
|
|
|
|
{
|
|
|
|
DvbStream *d = 0;
|
|
|
|
ChannelDesc *chan = 0;
|
|
|
|
|
|
|
|
int mychan = -1;
|
|
|
|
|
|
|
|
if (browseDvbStream == -1)
|
|
|
|
mychan = dvbConfig->lastChannel;
|
|
|
|
else
|
|
|
|
mychan = browseDvbStream + skip;
|
|
|
|
|
|
|
|
if (mychan < minChannelNumber)
|
|
|
|
mychan = maxChannelNumber;
|
|
|
|
else if (mychan > maxChannelNumber)
|
|
|
|
mychan = minChannelNumber;
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)channels.count(); i ++) {
|
|
|
|
if ((int) channels.at(i)->num == mychan) {
|
|
|
|
chan = channels.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!chan)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int j = 0; j < (int)dvb.count(); j ++) {
|
|
|
|
if (dvb.at(j)->canSource(chan)) {
|
|
|
|
d = dvb.at(j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!d)
|
|
|
|
return;
|
|
|
|
|
|
|
|
browseDvbStream = chan->num;
|
|
|
|
|
|
|
|
dvbOSD(*chan, d, timeShift);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDPrev()
|
|
|
|
{
|
|
|
|
browseDvbTimeShift = -1;
|
|
|
|
osdMode = 0;
|
|
|
|
|
|
|
|
dvbOSDSkip(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDHide()
|
|
|
|
{
|
|
|
|
browseDvbStream = -1;
|
|
|
|
browseDvbTimeShift = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDAdvance()
|
|
|
|
{
|
|
|
|
osdMode = 0;
|
|
|
|
|
|
|
|
dvbOSDSkip(0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSDRetreat()
|
|
|
|
{
|
|
|
|
osdMode = 0;
|
|
|
|
|
|
|
|
dvbOSDSkip(0, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbOSD(ChannelDesc liveChannel, DvbStream *d, int timeShift /* = 0 */)
|
|
|
|
{
|
|
|
|
TQStringList list;
|
|
|
|
EventSource *esrc;
|
|
|
|
EventSid *es;
|
|
|
|
TQPtrList<EventDesc> *esEvents;
|
|
|
|
EventDesc *desc;
|
|
|
|
TQString s;
|
|
|
|
int i, j, k;
|
|
|
|
int first=0;
|
|
|
|
|
|
|
|
if ( !d || liveChannel.name.isEmpty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( osdMode==2 ) {
|
|
|
|
osdTimer.stop();
|
|
|
|
osdMode = 0;
|
|
|
|
list.append( "STOP" );
|
|
|
|
emit showDvbOSD( s.setNum( liveChannel.num )+" - "+liveChannel.name, list );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( osdMode==1 )
|
|
|
|
osdTimer.stop();
|
|
|
|
|
|
|
|
if ( osdMode==0 ) {
|
|
|
|
if ( d->liveIsRecording() )
|
|
|
|
list.append( "R" );
|
|
|
|
if ( d->timeShiftMode() )
|
|
|
|
list.append( "T" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
list.append( "E" );
|
|
|
|
|
|
|
|
int myshift = 0;
|
|
|
|
|
|
|
|
if (browseDvbTimeShift == -1)
|
|
|
|
myshift = 0;
|
|
|
|
else
|
|
|
|
myshift = browseDvbTimeShift + timeShift;
|
|
|
|
|
|
|
|
if (myshift < 0)
|
|
|
|
myshift = 0;
|
|
|
|
|
|
|
|
browseDvbTimeShift = myshift;
|
|
|
|
|
|
|
|
k = 0;
|
|
|
|
|
|
|
|
esrc = events.getEventSource( liveChannel.tp.source );
|
|
|
|
es = esrc->getEventSid( liveChannel.tp.nid, liveChannel.tp.tsid, liveChannel.sid );
|
|
|
|
if ( !es )
|
|
|
|
goto end;
|
|
|
|
es->lock();
|
|
|
|
esEvents = es->getEvents();
|
|
|
|
|
|
|
|
for ( j=myshift; j<(myshift+2); j++ ) {
|
|
|
|
desc = esEvents->at( j );
|
|
|
|
if ( !desc )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ( !desc->title.isEmpty() ) {
|
|
|
|
s = desc->startDateTime.toString( "hh:mm" );
|
|
|
|
s = s+" - ";
|
|
|
|
s = s+desc->title;
|
|
|
|
if ( !osdMode && !first && !myshift ) {
|
|
|
|
TQDateTime dt = TQDateTime::currentDateTime();
|
|
|
|
int secs = desc->startDateTime.secsTo( dt );
|
|
|
|
i = TQTime().secsTo( desc->duration );
|
|
|
|
if ( i!=0 )
|
|
|
|
i = secs*100/i;
|
|
|
|
if ( i>100 )
|
|
|
|
i = 100;
|
|
|
|
list.append( TQString("BAR")+TQString().setNum( i ) );
|
|
|
|
++first;
|
|
|
|
}
|
|
|
|
list.append( s );
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
else if ( osdMode )
|
|
|
|
list.append( "" );
|
|
|
|
if ( osdMode==0 ) {
|
|
|
|
if ( k>1 )
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
list.append( desc->subtitle );
|
|
|
|
s = "";
|
|
|
|
for ( i=0; i<(int)desc->shortEvents.count(); i++ ) {
|
|
|
|
s = s + desc->shortEvents.at(i)->name;
|
|
|
|
if (!desc->shortEvents.at(i)->name.isEmpty() && !desc->shortEvents.at(i)->text.isEmpty()) {
|
|
|
|
s+= " : ";
|
|
|
|
s+= desc->shortEvents.at(i)->text;
|
|
|
|
s+= ". ";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for ( i=0; i<(int)desc->extEvents.count(); i++ )
|
|
|
|
s+= *desc->extEvents.at(i);
|
|
|
|
list.append( s );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
es->unlock();
|
|
|
|
|
|
|
|
end:
|
|
|
|
if ( osdMode==0 )
|
|
|
|
osdTimer.start( 5000, true );
|
|
|
|
osdMode++;
|
|
|
|
emit showDvbOSD( s.setNum( liveChannel.num )+" - "+liveChannel.name, list );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::enableLiveDvb( bool on )
|
|
|
|
{
|
|
|
|
channelsCb->setEnabled( on );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::checkFirstRun()
|
|
|
|
{
|
|
|
|
if ( dvbConfig->firstRun() )
|
|
|
|
showConfigDialog();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setConfig()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int error = 0;
|
|
|
|
KIconViewItem* item = NULL;
|
|
|
|
DvbStream *d;
|
|
|
|
|
|
|
|
TQString s = locateLocal("appdata", "");
|
|
|
|
dvbConfig = new DVBconfig( s );
|
|
|
|
item = new DIconViewItem(this, iconView, i18n("All"), TDEGlobal::iconLoader()->loadIcon(dvbConfig->allIcon, KIcon::NoGroup, KIcon::SizeSmallMedium));
|
|
|
|
iconView->setFixedHeight( item->height()+iconView->horizontalScrollBar()->height() );
|
|
|
|
item->setDropEnabled( true );
|
|
|
|
item = new DIconViewItem(this, iconView, i18n("Radio"), TDEGlobal::iconLoader()->loadIcon(dvbConfig->radioIcon, KIcon::NoGroup, KIcon::SizeSmallMedium));
|
|
|
|
item->setDropEnabled( false );
|
|
|
|
item = new DIconViewItem(this, iconView, i18n("TV"), TDEGlobal::iconLoader()->loadIcon(dvbConfig->tvIcon, KIcon::NoGroup, KIcon::SizeSmallMedium));
|
|
|
|
item->setDropEnabled( false );
|
|
|
|
|
|
|
|
TDETrader::OfferList offers = TDETrader::self()->query("KaffeineDvbPlugin");
|
|
|
|
TDETrader::OfferList::Iterator it = offers.begin();
|
|
|
|
if ( it!=offers.end() ) {
|
|
|
|
KService::Ptr ptr = (*it);
|
|
|
|
plugName = ptr->desktopEntryName();
|
|
|
|
plug = KParts::ComponentFactory::createPartInstanceFromService<KaffeineDvbPlugin>(ptr, 0, ptr->name().ascii(), 0, 0, 0, &error);
|
|
|
|
if (error > 0) {
|
|
|
|
fprintf( stderr, "Loading of DVB plugin failed: %s\n", KLibLoader::self()->lastErrorMessage().ascii() );
|
|
|
|
plug = NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf( stderr, "DVB plugin loaded\n.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvbConfig->categories.count(); i++ ) {
|
|
|
|
item = new DIconViewItem(this, iconView, dvbConfig->categories.at(i)->name, TDEGlobal::iconLoader()->loadIcon(dvbConfig->categories.at(i)->icon, KIcon::NoGroup, KIcon::SizeSmallMedium));
|
|
|
|
item->setDropEnabled( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvbConfig->devList.count(); i++ ) {
|
|
|
|
d = new DvbStream( dvbConfig->devList.at(i), dvbConfig->defaultCharset, &events );
|
|
|
|
d->setPlug( plug );
|
|
|
|
dvb.append( d );
|
|
|
|
connect( d, TQT_SIGNAL(shifting(bool)), this, TQT_SLOT(setShiftLed(bool)) );
|
|
|
|
connect( d, TQT_SIGNAL(isBroadcasting(bool)), this, TQT_SLOT(setBroadcastLed(bool)) );
|
|
|
|
connect( d, TQT_SIGNAL(timerEnded(RecTimer*)), this, TQT_SLOT(killTimer(RecTimer*)) );
|
|
|
|
connect( d, TQT_SIGNAL(isRecording(bool)), this, TQT_SLOT(setRecordLed(bool)) );
|
|
|
|
connect( d, TQT_SIGNAL(playDvb()), this, TQT_SLOT(pipeOpened()) );
|
|
|
|
}
|
|
|
|
fifoName = TDEGlobal::dirs()->saveLocation("tmp")+".kaxtv.ts";
|
|
|
|
TQFile f( fifoName );
|
|
|
|
if ( f.exists() )
|
|
|
|
f.remove();
|
|
|
|
if ( (mkfifo( fifoName.ascii(), 0644 ))<0 ) {
|
|
|
|
perror( fifoName.latin1() );
|
|
|
|
fifoName = "";
|
|
|
|
}
|
|
|
|
fifoName1 = TDEGlobal::dirs()->saveLocation("tmp")+".kaxtv1.ts";
|
|
|
|
TQFile f1( fifoName1 );
|
|
|
|
if ( f1.exists() )
|
|
|
|
f1.remove();
|
|
|
|
if ( (mkfifo( fifoName1.ascii(), 0644 ))<0 ) {
|
|
|
|
perror( fifoName1.latin1() );
|
|
|
|
fifoName1 = "";
|
|
|
|
}
|
|
|
|
currentFifo = fifoName;
|
|
|
|
getTimerList();
|
|
|
|
timersTimer.start( 5000 );
|
|
|
|
getChannelList();
|
|
|
|
rtp = new Ts2Rtp();
|
|
|
|
rtp->setSocket( dvbConfig->broadcastAddress, dvbConfig->broadcastPort, dvbConfig->senderPort );
|
|
|
|
cleaner = new Cleaner( dvbConfig->shiftDir, dvbConfig->recordDir );
|
|
|
|
split->setSizes( dvbConfig->splitSizes );
|
|
|
|
recallChannel = dvbConfig->lastChannel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::showConfigDialog()
|
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if ( !dvbConfig->haveData() ) {
|
|
|
|
ret = KMessageBox::questionYesNo( mainWidget, 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 ~/.trinity/share/apps/kaffeine/dvbdata.tar.gz and say Yes.<br><br>Should I try again?</qt>") );
|
|
|
|
if ( ret==KMessageBox::Yes )
|
|
|
|
goto loop;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ )
|
|
|
|
dvb.at(i)->probeCam();
|
|
|
|
DvbConfigDialog dlg( this, dvbConfig, mainWidget, plug );
|
|
|
|
connect( dlg.dumpBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(dumpEvents()) );
|
|
|
|
ret = dlg.exec();
|
|
|
|
disconnect( dlg.dumpBtn, TQT_SIGNAL(clicked()), this, TQT_SLOT(dumpEvents()) );
|
|
|
|
if ( ret==DvbConfigDialog::Rejected )
|
|
|
|
return;
|
|
|
|
rtp->setSocket( dvbConfig->broadcastAddress, dvbConfig->broadcastPort, dvbConfig->senderPort );
|
|
|
|
cleaner->setPaths( dvbConfig->shiftDir, dvbConfig->recordDir );
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::camClicked( int devNum )
|
|
|
|
{
|
|
|
|
dvb.at(devNum)->showCamDialog();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQPtrList<Transponder> DvbPanel::getSourcesStatus()
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
TQStringList list;
|
|
|
|
TQPtrList<Transponder> ss;
|
|
|
|
Transponder t;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( !dvb.at(i)->getPriority() ) // priority==0==don't use
|
|
|
|
continue;
|
|
|
|
list = dvb.at(i)->getSources();
|
|
|
|
for ( j=0; j<(int)list.count(); j++ ) {
|
|
|
|
if ( dvb.at(i)->hasRec() || dvb.at(i)->hasBroadcast() )
|
|
|
|
t = dvb.at(i)->getCurrentTransponder();
|
|
|
|
else {
|
|
|
|
t = Transponder();
|
|
|
|
t.source = list[j];
|
|
|
|
}
|
|
|
|
ss.append( new Transponder( t ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ss;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::fillChannelList( ChannelDesc *ch )
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
ChannelDesc *chan;
|
|
|
|
TDEListViewItem *it, *visible=0;
|
|
|
|
bool cont=false;
|
|
|
|
TQPtrList<Transponder> trans = getSourcesStatus();
|
|
|
|
trans.setAutoDelete( true );
|
|
|
|
|
|
|
|
searchLE->clear();
|
|
|
|
channelsCb->clear();
|
|
|
|
for ( i=0; i<(int)channels.count(); i++ ) {
|
|
|
|
chan = channels.at(i);
|
|
|
|
for ( j=0; j<(int)trans.count(); j++ ) {
|
|
|
|
cont = false;
|
|
|
|
if ( trans.at(j)->source==chan->tp.source ) {
|
|
|
|
if ( trans.at(j)->freq ) {
|
|
|
|
if ( chan->tp==*trans.at(j) ) break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cont = true;
|
|
|
|
}
|
|
|
|
if ( cont )
|
|
|
|
continue;
|
|
|
|
if ( currentCategory=="TV" ) {
|
|
|
|
if ( chan->type!=1 )
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( currentCategory=="Radio" ) {
|
|
|
|
if ( chan->type!=2 )
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if ( currentCategory!="All" && chan->category!=currentCategory )
|
|
|
|
continue;
|
|
|
|
it = new TDEListViewItem( channelsCb, TQString().sprintf("%05d", chan->num), chan->name, chan->tp.source );
|
|
|
|
if ( ch && ch==chan )
|
|
|
|
visible = it;
|
|
|
|
it->setDragEnabled( true );
|
|
|
|
chan->pix.load( dvbConfig->dvbConfigIconsDir+chan->name );
|
|
|
|
if ( !chan->pix.isNull() )
|
|
|
|
it->setPixmap( 1, chan->pix );
|
|
|
|
else {
|
|
|
|
if ( chan->type==1 ) {
|
|
|
|
if ( chan->fta )
|
|
|
|
it->setPixmap( 1, tvcPix );
|
|
|
|
else
|
|
|
|
it->setPixmap( 1, tvPix );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( chan->fta )
|
|
|
|
it->setPixmap( 1, racPix );
|
|
|
|
else
|
|
|
|
it->setPixmap( 1, raPix );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
channelsCb->visibleItems = channelsCb->childCount();
|
|
|
|
trans.clear();
|
|
|
|
if ( visible ) {
|
|
|
|
channelsCb->ensureItemVisible( visible );
|
|
|
|
channelsCb->setSelected( visible, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DvbStream* DvbPanel::getWorkingDvb( int mode, ChannelDesc *chan )
|
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
TQValueList<int> working; // free=0, hasLive=100, hasBroadcast=200, hasRec=300, can'tDoChannel=400
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ )
|
|
|
|
working.append( 100-dvb.at(i)->getPriority() );
|
|
|
|
|
|
|
|
// fill in working status
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( !dvb.at(i)->canSource( chan ) || working[i]==100 ) {
|
|
|
|
working[i] = MODE_CANTDO;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( dvb.at(i)->isTuned() ) {
|
|
|
|
if ( dvb.at(i)->getCurrentTransponder()==chan->tp ) {
|
|
|
|
return dvb.at(i); // use that one since it's already tuned on the good mplex
|
|
|
|
}
|
|
|
|
else if ( dvb.at(i)->hasRec() )
|
|
|
|
working[i] += MODE_RECORD;
|
|
|
|
else if ( dvb.at(i)->hasBroadcast() )
|
|
|
|
working[i] += MODE_BROADCAST;
|
|
|
|
else {
|
|
|
|
if ( mode==MODE_LIVE )
|
|
|
|
working[i] += MODE_FREE;
|
|
|
|
else
|
|
|
|
working[i] += MODE_LIVE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
working[i] += MODE_FREE;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
// search for least working card
|
|
|
|
for ( i=1; i<(int)working.count(); i++ ) {
|
|
|
|
if ( working[i]<working[0] ) {
|
|
|
|
working[0] = working[i];
|
|
|
|
ret = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( working[0]<mode )
|
|
|
|
return dvb.at(ret);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setBroadcast()
|
|
|
|
{
|
|
|
|
int ret, i;
|
|
|
|
TQPtrList<ChannelDesc> list;
|
|
|
|
bool live=false;
|
|
|
|
DvbStream *d;
|
|
|
|
|
|
|
|
BroadcastEditor dlg( mainWidget, &channels, &list );
|
|
|
|
ret = dlg.exec();
|
|
|
|
if ( ret==BroadcastEditor::Rejected )
|
|
|
|
return;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasBroadcast() )
|
|
|
|
dvb.at(i)->stopBroadcast();
|
|
|
|
}
|
|
|
|
if ( ! list.count() ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d = getWorkingDvb( MODE_BROADCAST, list.at(0) );
|
|
|
|
|
|
|
|
if ( d )
|
|
|
|
ret = d->canStartBroadcast( live, list.at(0) );
|
|
|
|
else
|
|
|
|
ret = -1;
|
|
|
|
if ( ret==0 ) {
|
|
|
|
if ( live ) {
|
|
|
|
stopLive();
|
|
|
|
emit dvbStop();
|
|
|
|
}
|
|
|
|
if ( !d->startBroadcast( &list, rtp ) ) {
|
|
|
|
KMessageBox::information( mainWidget, i18n("Broadcasting failed.") );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
KMessageBox::information( mainWidget, i18n("Can't start broadcasting.") );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::checkTimers()
|
|
|
|
{
|
|
|
|
int i, j, ret;
|
|
|
|
bool live=false;
|
|
|
|
RecTimer *t;
|
|
|
|
ChannelDesc *chan;
|
|
|
|
TQDateTime cur=TQDateTime::currentDateTime();
|
|
|
|
DvbStream *d;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)timers.count(); i++ ) {
|
|
|
|
t = timers.at(i);
|
|
|
|
if ( t->running )
|
|
|
|
continue;
|
|
|
|
if ( t->begin<=cur && cur<t->begin.addSecs(TQTime().secsTo(t->duration)) ) {
|
|
|
|
chan = 0;
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
if ( channels.at(j)->name==t->channel ) {
|
|
|
|
chan = channels.at(j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !chan )
|
|
|
|
continue;
|
|
|
|
d = getWorkingDvb( MODE_RECORD, chan );
|
|
|
|
live = false;
|
|
|
|
if ( d )
|
|
|
|
ret = d->canStartTimer( live, chan );
|
|
|
|
else
|
|
|
|
ret = -1;
|
|
|
|
if ( ret==0 ) {
|
|
|
|
if ( live ) {
|
|
|
|
stopLive();
|
|
|
|
emit dvbStop();
|
|
|
|
}
|
|
|
|
if ( d->startTimer( chan, dvbConfig->recordDir, dvbConfig->sizeFile, t, dvbConfig->filenameFormat ) ) {
|
|
|
|
TDEProcess proc;
|
|
|
|
proc << TQDir::homeDirPath()+"/bin/kaffeine_recording";
|
|
|
|
proc << "On";
|
|
|
|
proc.start( TDEProcess::DontCare );
|
|
|
|
t->running = 1;
|
|
|
|
if ( timersDialog )
|
|
|
|
emit timersChanged();
|
|
|
|
saveTimerList();
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fprintf( stderr, "start timer failed!!!\n" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fprintf( stderr, "Cant start timer !!!\n" );
|
|
|
|
}
|
|
|
|
else if ( t->mode ) {
|
|
|
|
if (t->begin.addSecs(t->duration.hour()*3600+t->duration.minute()*60+60)<cur) {
|
|
|
|
updateModeTimer( t );
|
|
|
|
if ( timersDialog )
|
|
|
|
emit timersChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setRecord()
|
|
|
|
{
|
|
|
|
ChannelDesc curchan;
|
|
|
|
TQString s="";
|
|
|
|
int ret, i, r=0;
|
|
|
|
bool live=false;
|
|
|
|
RecTimer *t, *rt;
|
|
|
|
EventDesc *desc;
|
|
|
|
DvbStream *d=0;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasLive() ) {
|
|
|
|
d = dvb.at(i);
|
|
|
|
curchan = d->getLiveChannel();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !d ) {
|
|
|
|
recordBtn->setOn( false );
|
|
|
|
showTimers();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
desc = events.getEventDesc( curchan.tp.source, curchan.tp.nid, curchan.tp.tsid, curchan.sid, 0 );
|
|
|
|
|
|
|
|
if ( desc )
|
|
|
|
s = desc->title;
|
|
|
|
|
|
|
|
if ( s.isEmpty() ) {
|
|
|
|
if ( !dvbConfig->filenameFormat.contains("%chan") )
|
|
|
|
s = curchan.name;
|
|
|
|
if ( !dvbConfig->filenameFormat.contains("%date") )
|
|
|
|
s+="_"+TQDateTime::currentDateTime().toString( "yyyyMMdd-hhmmss" );
|
|
|
|
}
|
|
|
|
|
|
|
|
rt = new RecTimer();
|
|
|
|
rt->name = s;
|
|
|
|
rt->channel = curchan.name;
|
|
|
|
rt->begin = TQDateTime::currentDateTime();
|
|
|
|
rt->duration = TQTime( 0,0,0).addSecs( dvbConfig->instantDuration*60 ) ;
|
|
|
|
rt->running = 1;
|
|
|
|
rt->mode = 0;
|
|
|
|
|
|
|
|
ret = d->canStartTimer( live, &curchan );
|
|
|
|
if ( ret==0 ) {
|
|
|
|
if ( d->startTimer( &curchan, dvbConfig->recordDir, dvbConfig->sizeFile, rt, dvbConfig->filenameFormat ) ) {
|
|
|
|
TDEProcess proc;
|
|
|
|
proc << TQDir::homeDirPath()+"/bin/kaffeine_recording";
|
|
|
|
proc << "On";
|
|
|
|
proc.start( TDEProcess::DontCare );
|
|
|
|
|
|
|
|
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();
|
|
|
|
emit showOSD( i18n("Instant Record successfully started"), 5000, 3 );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
KMessageBox::information( mainWidget, i18n("Instant Recording failed to start.") );
|
|
|
|
fprintf( stderr, "DvbPanel::setRecord:start timer failed!\n" );
|
|
|
|
delete rt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
delete rt;
|
|
|
|
for ( i=0; i<(int)timers.count(); i++ ) {
|
|
|
|
t = timers.at(i);
|
|
|
|
if ( d->liveIsRecording() && t->running && curchan.name == t->channel ) {
|
|
|
|
d->updateTimer( t, 0 );
|
|
|
|
emit showOSD( i18n("Recording successfully stopped"), 5000, 3 );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
showTimers();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setRecordLed( bool on )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
bool rec=false;
|
|
|
|
|
|
|
|
if ( on ) {
|
|
|
|
recordLed->on();
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasRec() ) {
|
|
|
|
rec = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !rec )
|
|
|
|
recordLed->off();
|
|
|
|
else
|
|
|
|
recordLed->on();
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->liveIsRecording() ) {
|
|
|
|
recordBtn->setOn( true );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
recordBtn->setOn( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setBroadcastLed( bool on )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
bool broad=false;
|
|
|
|
|
|
|
|
if ( on ) {
|
|
|
|
broadcastLed->on();
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasBroadcast() ) {
|
|
|
|
broad = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !broad )
|
|
|
|
broadcastLed->off();
|
|
|
|
else
|
|
|
|
broadcastLed->on();
|
|
|
|
fillChannelList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::killTimer( RecTimer *t )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)timers.count(); i++ ) {
|
|
|
|
if ( timers.at(i)==t ) {
|
|
|
|
TDEProcess proc;
|
|
|
|
proc << TQDir::homeDirPath()+"/bin/kaffeine_recording";
|
|
|
|
if ( recordLed->state()==KLed::On )
|
|
|
|
proc << "On";
|
|
|
|
else
|
|
|
|
proc << "Off";
|
|
|
|
proc << TDEProcess::quote( t->fullPath );
|
|
|
|
proc.start( TDEProcess::DontCare );
|
|
|
|
|
|
|
|
if ( t->mode )
|
|
|
|
updateModeTimer( t );
|
|
|
|
else
|
|
|
|
timers.remove( t );
|
|
|
|
if ( timersDialog )
|
|
|
|
emit timersChanged();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::updateModeTimer( RecTimer *t )
|
|
|
|
{
|
|
|
|
int stop=0, r=0, i;
|
|
|
|
|
|
|
|
if ( t->mode==CronTimer::Daily )
|
|
|
|
t->begin = t->begin.addDays(1);
|
|
|
|
else if ( t->mode==CronTimer::Weekly )
|
|
|
|
t->begin = t->begin.addDays(7);
|
|
|
|
else if ( t->mode==CronTimer::Monthly )
|
|
|
|
t->begin = t->begin.addMonths(1);
|
|
|
|
else while ( !stop ) {
|
|
|
|
t->begin = t->begin.addDays(1);
|
|
|
|
if ( (t->begin.date().dayOfWeek()==1) && (t->mode&CronTimer::Monday) ) stop++;
|
|
|
|
else if ( (t->begin.date().dayOfWeek()==2) && (t->mode&CronTimer::Tuesday) ) stop++;
|
|
|
|
else if ( (t->begin.date().dayOfWeek()==3) && (t->mode&CronTimer::Wednesday) ) stop++;
|
|
|
|
else if ( (t->begin.date().dayOfWeek()==4) && (t->mode&CronTimer::Thursday) ) stop++;
|
|
|
|
else if ( (t->begin.date().dayOfWeek()==5) && (t->mode&CronTimer::Friday) ) stop++;
|
|
|
|
else if ( (t->begin.date().dayOfWeek()==6) && (t->mode&CronTimer::Saturday) ) stop++;
|
|
|
|
else if ( (t->begin.date().dayOfWeek()==7) && (t->mode&CronTimer::Sunday) ) stop++;
|
|
|
|
}
|
|
|
|
|
|
|
|
RecTimer *nt = new RecTimer();
|
|
|
|
nt->name = t->name;
|
|
|
|
nt->channel = t->channel;
|
|
|
|
nt->begin = t->begin;
|
|
|
|
nt->duration = t->duration;
|
|
|
|
nt->running = 0;
|
|
|
|
nt->mode = t->mode;
|
|
|
|
timers.remove( t );
|
|
|
|
for ( i=0; i<(int)timers.count(); i++ ) {
|
|
|
|
t = timers.at(i);
|
|
|
|
if ( nt->begin>t->begin )
|
|
|
|
r=i+1;
|
|
|
|
}
|
|
|
|
timers.insert( r, nt );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::showTimers()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
TQStringList list;
|
|
|
|
TQMap<TQString,TQString> map;
|
|
|
|
|
|
|
|
if ( channels.count()==0 ) {
|
|
|
|
KMessageBox::sorry( 0, i18n("You may want to define some channel first!") );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for ( TQPtrListIterator<ChannelDesc> it(channels); it.current(); ++it )
|
|
|
|
map[it.current()->name] = it.current()->name;
|
|
|
|
TQMap<TQString,TQString>::Iterator it;
|
|
|
|
TQMap<TQString,TQString>::Iterator end(map.end());
|
|
|
|
for ( it = map.begin(); it != end; ++it )
|
|
|
|
list.append( it.data() );
|
|
|
|
|
|
|
|
timersDialog = new KRecord( list, &timers, mainWidget, dvbConfig->timerSize );
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
connect( timersDialog, TQT_SIGNAL(updateTimer(RecTimer*,int)), dvb.at(i), TQT_SLOT(updateTimer(RecTimer*,int)) );
|
|
|
|
}
|
|
|
|
connect( this, TQT_SIGNAL(timersChanged()), timersDialog, TQT_SLOT(refresh()) );
|
|
|
|
timersDialog->exec();
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
disconnect( timersDialog, TQT_SIGNAL(updateTimer(RecTimer*,int)), dvb.at(i), TQT_SLOT(updateTimer(RecTimer*,int)) );
|
|
|
|
}
|
|
|
|
disconnect( this, TQT_SIGNAL(timersChanged()), timersDialog, TQT_SLOT(refresh()) );
|
|
|
|
dvbConfig->timerSize = timersDialog->size();
|
|
|
|
delete timersDialog;
|
|
|
|
timersDialog = 0;
|
|
|
|
saveTimerList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int DvbPanel::getSNR( int device )
|
|
|
|
{
|
|
|
|
if ( device<0 || device>=(int)dvb.count() )
|
|
|
|
return -1;
|
|
|
|
return dvb.at(device)->getSNR();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbNewTimer( TQString name, TQString channel, TQString datetime, TQString duration )
|
|
|
|
{
|
|
|
|
newTimer( channel, name, TQDateTime::fromString( datetime, Qt::ISODate ), TQTime::fromString( duration ), false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::newTimer( TQString channel, TQString name, TQDateTime begin, TQTime duration, bool warn )
|
|
|
|
{
|
|
|
|
int i, r=0;
|
|
|
|
RecTimer *t;
|
|
|
|
RecTimer *rt = new RecTimer();
|
|
|
|
|
|
|
|
rt->name = name.replace("/","_").replace(">","_").replace("<","_").replace(":","_").replace('"',"_").replace("\\","_").replace("|","_");
|
|
|
|
rt->channel = channel;
|
|
|
|
rt->begin = begin.addSecs( -(dvbConfig->beginMargin*60) );
|
|
|
|
rt->duration = duration.addSecs( (dvbConfig->beginMargin+dvbConfig->endMargin)*60 ) ;
|
|
|
|
rt->running = 0;
|
|
|
|
rt->mode = 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 );
|
|
|
|
if ( warn )
|
|
|
|
KMessageBox::information( 0, i18n("Timer successfully created.") );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::scanner()
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
loop:
|
|
|
|
if ( !dvbConfig->haveData() ) {
|
|
|
|
ret = KMessageBox::questionYesNo( mainWidget, 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 ~/.trinity/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, dvbConfig->defaultCharset );
|
|
|
|
dlg.exec();
|
|
|
|
dvbConfig->scanSize = dlg.size();
|
|
|
|
fillChannelList();
|
|
|
|
saveChannelList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::showEvents()
|
|
|
|
{
|
|
|
|
events.doClean( false );
|
|
|
|
KEvents dlg( &channels, &dvb, &events, mainWidget, dvbConfig->epgSize );
|
|
|
|
connect( &dlg, TQT_SIGNAL(addTimer(TQString,TQString,TQDateTime,TQTime)), this, TQT_SLOT(newTimer(TQString,TQString,TQDateTime,TQTime)) );
|
|
|
|
connect( &dlg, TQT_SIGNAL(zapTo(const TQString &)), this, TQT_SLOT(channelSelected(const TQString &)) );
|
|
|
|
dlg.exec();
|
|
|
|
dvbConfig->epgSize = dlg.size();
|
|
|
|
disconnect( &dlg, TQT_SIGNAL(addTimer(TQString,TQString,TQDateTime,TQTime)), this, TQT_SLOT(newTimer(TQString,TQString,TQDateTime,TQTime)) );
|
|
|
|
disconnect( &dlg, TQT_SIGNAL(zapTo(const TQString &)), this, TQT_SLOT(channelSelected(const TQString &)) );
|
|
|
|
events.doClean( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setShiftLed( bool on )
|
|
|
|
{
|
|
|
|
if ( on ) {
|
|
|
|
shiftLed->on();
|
|
|
|
diskTimer.start( 300000 );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
shiftLed->off();
|
|
|
|
diskTimer.stop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::channelSelected( const TQString &name )
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ChannelDesc> iter( channels );
|
|
|
|
ChannelDesc *itdesc;
|
|
|
|
|
|
|
|
iter.toFirst();
|
|
|
|
while ( (itdesc=iter.current())!=0 ) {
|
|
|
|
if ( itdesc->name==name ) {
|
|
|
|
dvbZap( itdesc );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::channelSelected( TQListViewItem *it )
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ChannelDesc> iter( channels );
|
|
|
|
ChannelDesc *itdesc;
|
|
|
|
|
|
|
|
if ( !it )
|
|
|
|
return;
|
|
|
|
|
|
|
|
iter.toFirst();
|
|
|
|
while ( (itdesc=iter.current())!=0 ) {
|
|
|
|
if ( itdesc->name==it->text(1) ) {
|
|
|
|
dvbZap( itdesc );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::nextTrack( MRL& )
|
|
|
|
{
|
|
|
|
next();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::previousTrack( MRL& )
|
|
|
|
{
|
|
|
|
previous();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::currentTrack( MRL& )
|
|
|
|
{
|
|
|
|
playLastChannel();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::trackNumber( int num, MRL& )
|
|
|
|
{
|
|
|
|
playNumChannel( num );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::recallZap()
|
|
|
|
{
|
|
|
|
emit showMe( this );
|
|
|
|
playNumChannel( recallChannel );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::playNumChannel( int num )
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
bool ok=false;
|
|
|
|
|
|
|
|
if ( !channelsCb->isEnabled() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
if ( (int)channels.at(j)->num==num ) {
|
|
|
|
ok = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ok )
|
|
|
|
dvbZap( channels.at( j ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::playbackFinished( MRL& )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::playLastChannel()
|
|
|
|
{
|
|
|
|
/*int ret, i, j;
|
|
|
|
TQPtrList<ChannelDesc> list;
|
|
|
|
bool live=false, ok=false;
|
|
|
|
DvbStream *d;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasBroadcast() )
|
|
|
|
dvb.at(i)->stopBroadcast();
|
|
|
|
}
|
|
|
|
++dvbConfig->lastChannel;
|
|
|
|
if ( dvbConfig->lastChannel>channels.count() )
|
|
|
|
dvbConfig->lastChannel = 1;
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
if ( (int)channels.at(j)->num==dvbConfig->lastChannel ) {
|
|
|
|
ok = true;
|
|
|
|
list.append( channels.at(j) );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( ! list.count() ) {
|
|
|
|
TQTimer::singleShot( 2000, this, TQT_SLOT(playLastChannel()) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
d = getWorkingDvb( MODE_BROADCAST, list.at(0) );
|
|
|
|
if ( d )
|
|
|
|
ret = d->canStartBroadcast( live, list.at(0) );
|
|
|
|
else
|
|
|
|
ret = -1;
|
|
|
|
if ( ret==0 ) {
|
|
|
|
if ( live ) {
|
|
|
|
stopLive();
|
|
|
|
emit dvbStop();
|
|
|
|
}
|
|
|
|
if ( !d->startBroadcast( &list, rtp ) ) {
|
|
|
|
fprintf( stderr, "Broadcasting failed.\n" );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf( stderr, "Tuning to: %s / autocount: %lu\n", channels.at(j)->name.ascii(), autocount );
|
|
|
|
++autocount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fprintf( stderr, "Can't start broadcasting.\n");
|
|
|
|
|
|
|
|
TQTimer::singleShot( 2000, this, TQT_SLOT(playLastChannel()) );
|
|
|
|
return;*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int j;
|
|
|
|
bool ok=false;
|
|
|
|
|
|
|
|
if ( !channelsCb->isEnabled() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
for ( j=0; j<(int)channels.count(); j++ ) {
|
|
|
|
if ( (int)channels.at(j)->num==dvbConfig->lastChannel ) {
|
|
|
|
ok = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !ok )
|
|
|
|
return;
|
|
|
|
|
|
|
|
dvbZap( channels.at(j) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::next()
|
|
|
|
{
|
|
|
|
if ( !channelsCb->isEnabled() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQListViewItem* nextItem;
|
|
|
|
|
|
|
|
TQListViewItem* playingItem = channelsCb->findItem( TQString().sprintf("%05d", dvbConfig->lastChannel), 0 );
|
|
|
|
|
|
|
|
if ( !playingItem == 0 ) // yes, it's in the current category
|
|
|
|
{
|
|
|
|
if ( playingItem == channelsCb->lastItem() )
|
|
|
|
nextItem = channelsCb->firstChild(); // wrap around
|
|
|
|
else
|
|
|
|
nextItem = playingItem->itemBelow();
|
|
|
|
}
|
|
|
|
else // not in current category, user has switched category, use first in current cat
|
|
|
|
nextItem = channelsCb->firstChild();
|
|
|
|
|
|
|
|
channelsCb->setSelected( nextItem, true );
|
|
|
|
channelSelected( nextItem );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::previous()
|
|
|
|
{
|
|
|
|
if ( !channelsCb->isEnabled() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
TQListViewItem* prevItem;
|
|
|
|
|
|
|
|
TQListViewItem* playingItem = channelsCb->findItem( TQString().sprintf("%05d", dvbConfig->lastChannel), 0 );
|
|
|
|
|
|
|
|
if ( !playingItem == 0 ) // yes, it's in the current category
|
|
|
|
{
|
|
|
|
if ( playingItem == channelsCb->firstChild() )
|
|
|
|
prevItem = channelsCb->lastItem(); // wrap around
|
|
|
|
else
|
|
|
|
prevItem = playingItem->itemAbove();
|
|
|
|
}
|
|
|
|
else // not in current category, user has switched category, use first in current cat
|
|
|
|
prevItem = channelsCb->firstChild();
|
|
|
|
|
|
|
|
channelsCb->setSelected( prevItem, true );
|
|
|
|
channelSelected( prevItem );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::dvbZap( ChannelDesc *chan )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
DvbStream *d;
|
|
|
|
|
|
|
|
if ( currentFifo.isEmpty() || isTuning )
|
|
|
|
return;
|
|
|
|
|
|
|
|
isTuning = true;
|
|
|
|
emit setTimeShiftFilename( "" );
|
|
|
|
d = getWorkingDvb( MODE_LIVE, chan );
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasLive() ) {
|
|
|
|
dvb.at(i)->preStopLive();
|
|
|
|
emit dvbPause( false );
|
|
|
|
dvb.at(i)->stopLive( chan );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finalZap( d, chan );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::pipeOpened()
|
|
|
|
{
|
|
|
|
tuningTimer.start( 1000, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::setTuning()
|
|
|
|
{
|
|
|
|
tuningTimer.stop();
|
|
|
|
stopTuningTimer.stop();
|
|
|
|
isTuning = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::finalZap( DvbStream *d, ChannelDesc *chan )
|
|
|
|
{
|
|
|
|
TQString s, t;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
emit setCurrentPlugin( this );
|
|
|
|
|
|
|
|
fprintf( stderr, "Tuning to: %s / autocount: %lu\n", chan->name.latin1(), autocount );
|
|
|
|
TQTime tm;
|
|
|
|
tm.start();
|
|
|
|
|
|
|
|
if ( !d ) {
|
|
|
|
emit dvbStop();
|
|
|
|
isTuning = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret = d->goLive( chan, currentFifo, dvbConfig->ringBufSize );
|
|
|
|
|
|
|
|
switch ( ret ) {
|
|
|
|
case DvbStream::ErrIsRecording :
|
|
|
|
emit showOSD( i18n("Still recording."), 5000, 3 );
|
|
|
|
break;
|
|
|
|
case DvbStream::ErrIsBroadcasting :
|
|
|
|
emit showOSD( i18n("Still broadcasting."), 5000, 3 );
|
|
|
|
break;
|
|
|
|
case DvbStream::ErrCantTune :
|
|
|
|
emit showOSD( i18n("Can't tune dvb!"), 5000, 3 );
|
|
|
|
break;
|
|
|
|
case DvbStream::ErrCantSetPids :
|
|
|
|
emit showOSD( i18n("Can't set pid(s)"), 5000, 3 );
|
|
|
|
break;
|
|
|
|
case DvbStream::ErrCamUsed :
|
|
|
|
emit showOSD( i18n("No CAM free"), 5000, 3 );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf( stderr, "Tuning delay: %d ms\n", tm.elapsed() );
|
|
|
|
osdMode = 0;
|
|
|
|
if ( ret<1 ) {
|
|
|
|
emit dvbOpen( currentFifo, s.setNum( chan->num)+" - "+chan->name, chan->vpid );
|
|
|
|
showOsdTimer.start( 2000, true );
|
|
|
|
++autocount;
|
|
|
|
stopTuningTimer.start( 5000, true );
|
|
|
|
if ( currentFifo==fifoName ) {
|
|
|
|
if ( !fifoName1.isEmpty() )
|
|
|
|
currentFifo = fifoName1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( !fifoName.isEmpty() )
|
|
|
|
currentFifo = fifoName;
|
|
|
|
}
|
|
|
|
if ( channelsCb->visibleItems<5 ) {
|
|
|
|
resetSearch();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( d->liveIsRecording() )
|
|
|
|
recordBtn->setOn( true );
|
|
|
|
else
|
|
|
|
recordBtn->setOn( false );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
recordBtn->setOn( false );
|
|
|
|
isTuning = false;
|
|
|
|
emit dvbStop();
|
|
|
|
}
|
|
|
|
if ( dvbConfig->lastChannel!=(int)chan->num ) {
|
|
|
|
recallChannel = dvbConfig->lastChannel;
|
|
|
|
dvbConfig->lastChannel = chan->num;
|
|
|
|
}
|
|
|
|
//TQTimer::singleShot( 3000, this, TQT_SLOT(playLastChannel()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::pauseLiveTV()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
DvbStream *d=0;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasLive() ) {
|
|
|
|
d = dvb.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !d )
|
|
|
|
return;
|
|
|
|
|
|
|
|
timeShiftFileName = dvbConfig->shiftDir+"DVBLive-"+TQDateTime::currentDateTime().toString("yyyyMMddThhmmss")+".m2t";
|
|
|
|
if ( d->doPause( timeShiftFileName ) )
|
|
|
|
emit setTimeShiftFilename( timeShiftFileName );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::timeShiftMode()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasLive() ) {
|
|
|
|
return dvb.at(i)->timeShiftMode();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::stopLive()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ChannelDesc chan;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasLive() ) {
|
|
|
|
recallChannel = dvb.at(i)->getLiveChannel().num;
|
|
|
|
dvb.at(i)->preStopLive();
|
|
|
|
dvb.at(i)->stopLive( &chan );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
recordBtn->setOn( false );
|
|
|
|
emit setTimeShiftFilename( "" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// TV | vpid(stream_type) | apid1(lang)(ac3),apid2, | ttpid | sid | tsid | type(S,C,T)source | freq | sr | pol | fecH | inv | mod | fecL | bw | trans | guard | hier | number / subpid1(type)(pageid)(ancid)(lang),subpid2..., | category | nid |
|
|
|
|
bool DvbPanel::getChannelList()
|
|
|
|
{
|
|
|
|
bool ret=false;
|
|
|
|
TQString s, c, t, u, type;
|
|
|
|
int pos, tpos;
|
|
|
|
ChannelDesc *chan;
|
|
|
|
TQString src="";
|
|
|
|
int ns;
|
|
|
|
TDEListViewItem *it;
|
|
|
|
TQPixmap pix;
|
|
|
|
|
|
|
|
maxChannelNumber = 0;
|
|
|
|
minChannelNumber = -1;
|
|
|
|
|
|
|
|
int sort = dvbConfig->readDvbChanOrder();
|
|
|
|
if ( sort ) {
|
|
|
|
int column = sort&1;
|
|
|
|
int order = sort>>1;
|
|
|
|
switch (order){
|
|
|
|
case 1:
|
|
|
|
channelsCb->setSorting ( column, FALSE );
|
|
|
|
break;
|
|
|
|
case 0:
|
|
|
|
channelsCb->setSorting ( column, TRUE );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFile f( locateLocal("appdata", "channels.dvb" ) );
|
|
|
|
if ( f.open(IO_ReadOnly) ) {
|
|
|
|
TQTextStream 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("|");
|
|
|
|
c = s.left( pos );
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
tpos = c.find("(");
|
|
|
|
if ( tpos>0 )
|
|
|
|
chan->vpid = c.left(tpos).toUShort();
|
|
|
|
else
|
|
|
|
chan->vpid = c.toUShort();
|
|
|
|
if( tpos>0 ) {
|
|
|
|
t = c.right( c.length()-tpos-1);
|
|
|
|
t.remove(")");
|
|
|
|
chan->vType = t.toUShort();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
chan->vType = 2;
|
|
|
|
if ( !chan->vpid )
|
|
|
|
chan->vType = 0;
|
|
|
|
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;
|
|
|
|
chan->tp.source = "Terrestrial";
|
|
|
|
}
|
|
|
|
else if ( c.startsWith("C") ) {
|
|
|
|
chan->tp.type=FE_QAM;
|
|
|
|
chan->tp.source = "Cable";
|
|
|
|
}
|
|
|
|
else if ( c.startsWith("S") ) {
|
|
|
|
chan->tp.type=FE_QPSK;
|
|
|
|
c.remove( 0, 1 );
|
|
|
|
chan->tp.source = c;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
chan->tp.type=FE_ATSC;
|
|
|
|
chan->tp.source = "Atsc";
|
|
|
|
}
|
|
|
|
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 35 : chan->tp.coderateH = FEC_3_5; break;
|
|
|
|
case 910 : chan->tp.coderateH = FEC_9_10; 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 108 : chan->tp.modulation = VSB_8; break;
|
|
|
|
case 116 : chan->tp.modulation = VSB_16; break;
|
|
|
|
case 1000 : chan->tp.modulation = PSK_8; break;
|
|
|
|
case 1001 : chan->tp.modulation = APSK_16; break;
|
|
|
|
case 1003 : chan->tp.modulation = DQPSK; 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 35 : chan->tp.coderateH = FEC_3_5; break;
|
|
|
|
case 910 : chan->tp.coderateH = FEC_9_10; 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();
|
|
|
|
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);
|
|
|
|
tpos=t.find("(");
|
|
|
|
ns = (int)chan->nsubpid;
|
|
|
|
chan->subpid[ns].pid = t.left(tpos).toUShort();
|
|
|
|
t = t.right( t.length()-tpos-1 );
|
|
|
|
tpos=t.find(")");
|
|
|
|
chan->subpid[ns].type = t.left(tpos).toUShort();
|
|
|
|
t = t.right( t.length()-tpos-2 );
|
|
|
|
tpos=t.find(")");
|
|
|
|
chan->subpid[ns].page = t.left(tpos).toUShort();
|
|
|
|
t = t.right( t.length()-tpos-2 );
|
|
|
|
tpos=t.find(")");
|
|
|
|
chan->subpid[ns].id = t.left(tpos).toUShort();
|
|
|
|
t = t.right( t.length()-tpos-2 );
|
|
|
|
tpos=t.find(")");
|
|
|
|
chan->subpid[ns].lang = t.left(tpos);
|
|
|
|
c = c.right( c.length()-pos-1 );
|
|
|
|
chan->nsubpid++;
|
|
|
|
}
|
|
|
|
pos = s.find("|");
|
|
|
|
chan->category = s.left( pos );
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
pos = s.find("|");
|
|
|
|
chan->tp.nid = s.left(pos).toUShort();
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
pos = s.find("|");
|
|
|
|
switch ( s.left(pos).toInt() ) {
|
|
|
|
case 20 : chan->tp.rolloff = ROLLOFF_20; break;
|
|
|
|
case 25 : chan->tp.rolloff = ROLLOFF_25; break;
|
|
|
|
case 35 : chan->tp.rolloff = ROLLOFF_35; break;
|
|
|
|
case -1 : chan->tp.rolloff = ROLLOFF_AUTO;
|
|
|
|
}
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
pos = s.find("|");
|
|
|
|
chan->tp.S2 = s.left(pos).toInt();
|
|
|
|
|
|
|
|
if ( chan->tp.source.isEmpty() ) {
|
|
|
|
delete chan;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
chan->pix.load( dvbConfig->dvbConfigIconsDir+chan->name );
|
|
|
|
it = new TDEListViewItem( channelsCb, TQString().sprintf("%05d", chan->num), chan->name, chan->tp.source );
|
|
|
|
it->setDragEnabled( true );
|
|
|
|
if ( !chan->pix.isNull() )
|
|
|
|
it->setPixmap( 1, chan->pix );
|
|
|
|
else {
|
|
|
|
if ( chan->type==1 ) {
|
|
|
|
if ( chan->fta )
|
|
|
|
it->setPixmap( 1, tvcPix );
|
|
|
|
else
|
|
|
|
it->setPixmap( 1, tvPix );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ( chan->fta )
|
|
|
|
it->setPixmap( 1, racPix );
|
|
|
|
else
|
|
|
|
it->setPixmap( 1, raPix );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
channels.append( chan );
|
|
|
|
if ( chan->num<=0 )
|
|
|
|
chan->num = channels.count();
|
|
|
|
|
|
|
|
if ( (int)chan->num > maxChannelNumber )
|
|
|
|
maxChannelNumber = chan->num;
|
|
|
|
if ( minChannelNumber == -1 || (int)chan->num < minChannelNumber )
|
|
|
|
minChannelNumber = chan->num;
|
|
|
|
|
|
|
|
}
|
|
|
|
ret = true;
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::saveChannelList()
|
|
|
|
{
|
|
|
|
bool ret=false;
|
|
|
|
int i, k;
|
|
|
|
TQString s;
|
|
|
|
ChannelDesc *chan=0;
|
|
|
|
|
|
|
|
TQFile f( locateLocal("appdata", "channels.dvb" ) );
|
|
|
|
if ( f.open(IO_WriteOnly|IO_Truncate) ) {
|
|
|
|
TQTextStream tt( &f );
|
|
|
|
tt<<"#Generated by Kaffeine 0.5\n";
|
|
|
|
for( i=0; i<(int)channels.count(); i++ ) {
|
|
|
|
chan = channels.at(i);
|
|
|
|
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);
|
|
|
|
if ( chan->vType ) {
|
|
|
|
tt<< "(";
|
|
|
|
tt<< s.setNum(chan->vType);
|
|
|
|
tt<< ")";
|
|
|
|
}
|
|
|
|
tt<< "|";
|
|
|
|
for ( k=0; k<chan->napid; k++ ) {
|
|
|
|
tt<< s.setNum(chan->apid[k].pid);
|
|
|
|
if ( !chan->apid[k].lang.isEmpty() )
|
|
|
|
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"; tt<< chan->tp.source; break;
|
|
|
|
case FE_QAM : tt<< "Cable"; break;
|
|
|
|
case FE_OFDM : tt<< "Terrestrial"; break;
|
|
|
|
case FE_ATSC : tt<< "Atsc"; break;
|
|
|
|
}
|
|
|
|
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_3_5 : tt<< "35|"; break;
|
|
|
|
case FEC_9_10 : tt<< "910|"; 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 VSB_8 : tt<< "108|"; break;
|
|
|
|
case VSB_16 : tt<< "116|"; break;
|
|
|
|
case PSK_8 : tt<< "1000|"; break;
|
|
|
|
case APSK_16 : tt<< "1001|"; break;
|
|
|
|
case DQPSK : tt<< "1003|"; 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_3_5 : tt<< "35|"; break;
|
|
|
|
case FEC_9_10 : tt<< "910|"; 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)+"|";
|
|
|
|
for ( k=0; k<chan->nsubpid; k++ ) {
|
|
|
|
tt<< s.setNum(chan->subpid[k].pid);
|
|
|
|
tt<< "("+s.setNum(chan->subpid[k].type)+")";
|
|
|
|
tt<< "("+s.setNum(chan->subpid[k].page)+")";
|
|
|
|
tt<< "("+s.setNum(chan->subpid[k].id)+")";
|
|
|
|
tt<< "("+chan->subpid[k].lang+")";
|
|
|
|
tt<< ",";
|
|
|
|
}
|
|
|
|
tt<< "|";
|
|
|
|
tt<< chan->category+"|";
|
|
|
|
tt<< s.setNum(chan->tp.nid)+"|";
|
|
|
|
switch ( chan->tp.rolloff ) {
|
|
|
|
case ROLLOFF_20 : tt<< "20|"; break;
|
|
|
|
case ROLLOFF_25 : tt<< "25|"; break;
|
|
|
|
case ROLLOFF_35 : tt<< "35|"; break;
|
|
|
|
case ROLLOFF_AUTO : tt<< "-1|";
|
|
|
|
}
|
|
|
|
tt<< s.setNum(chan->tp.S2)+"|";
|
|
|
|
tt<< "\n";
|
|
|
|
}
|
|
|
|
ret = true;
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::getTimerList()
|
|
|
|
{
|
|
|
|
bool ret=false;
|
|
|
|
TQString s;
|
|
|
|
int pos;
|
|
|
|
RecTimer *t;
|
|
|
|
|
|
|
|
TQFile f( locateLocal("appdata", "timers.dvb" ) );
|
|
|
|
if ( f.open(IO_ReadOnly) ) {
|
|
|
|
TQTextStream 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 = TQDateTime::fromString( s.left( pos ), Qt::ISODate );
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
pos = s.find("|");
|
|
|
|
t->duration = TQTime::fromString( s.left( pos ) );
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
pos = s.find("|");
|
|
|
|
//t->filetype = s.left( pos ).toInt();
|
|
|
|
t->mode = 0;
|
|
|
|
s = s.right( s.length()-pos-1 );
|
|
|
|
pos = s.find("|");
|
|
|
|
t->mode = s.left( pos ).toInt();
|
|
|
|
t->running = 0;
|
|
|
|
timers.append( t );
|
|
|
|
}
|
|
|
|
ret = true;
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::saveTimerList()
|
|
|
|
{
|
|
|
|
bool ret=false;
|
|
|
|
int i;
|
|
|
|
TQString s;
|
|
|
|
RecTimer *t;
|
|
|
|
|
|
|
|
TQFile f( locateLocal("appdata", "timers.dvb" ) );
|
|
|
|
if ( f.open(IO_WriteOnly|IO_Truncate) ) {
|
|
|
|
TQTextStream tt( &f );
|
|
|
|
tt<<"#Generated by Kaffeine 0.5\n";
|
|
|
|
for( i=0; i<(int)timers.count(); i++ ) {
|
|
|
|
t = timers.at(i);
|
|
|
|
if ( t->running && !t->mode )
|
|
|
|
continue;
|
|
|
|
tt<< t->name+"|";
|
|
|
|
tt<< t->channel+"|";
|
|
|
|
tt<< t->begin.toString("yyyy-MM-ddThh:mm:ss")+"|";
|
|
|
|
tt<< t->duration.toString()+"|";
|
|
|
|
tt<< s.setNum(0/*t->filetype*/)+"|";
|
|
|
|
tt<< s.setNum(t->mode)+"|";
|
|
|
|
tt<< "\n";
|
|
|
|
}
|
|
|
|
ret = true;
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool DvbPanel::close()
|
|
|
|
{
|
|
|
|
int ret=0, i;
|
|
|
|
bool rec = false;
|
|
|
|
|
|
|
|
for ( i=0; i<(int)dvb.count(); i++ ) {
|
|
|
|
if ( dvb.at(i)->hasRec() ) {
|
|
|
|
rec = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( rec ) {
|
|
|
|
ret = KMessageBox::questionYesNo( 0, i18n("Kaffeine is still recording. Do you really want to quit?") );
|
|
|
|
if ( ret!=KMessageBox::Yes )
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else if ( timers.count() ) {
|
|
|
|
ret = KMessageBox::questionYesNo( 0, i18n("Kaffeine has queued timers. Do you really want to quit?") );
|
|
|
|
if ( ret!=KMessageBox::Yes )
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
emit dvbStop();
|
|
|
|
stopLive();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void DvbPanel::saveConfig()
|
|
|
|
{
|
|
|
|
saveTimerList();
|
|
|
|
saveChannelList();
|
|
|
|
dvbConfig->splitSizes = split->sizes();
|
|
|
|
dvbConfig->saveDvbChanOrder( channelsCb->sortOrder(), channelsCb->sortColumn() );
|
|
|
|
dvbConfig->saveConfig();
|
|
|
|
//delete dvbConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DvbPanel::~DvbPanel()
|
|
|
|
{
|
|
|
|
dvb.clear();
|
|
|
|
delete rtp;
|
|
|
|
delete cleaner;
|
|
|
|
if ( plug ) {
|
|
|
|
KService::Ptr service = KService::serviceByDesktopName( plugName );
|
|
|
|
KLibLoader::self()->unloadLibrary( service->library().ascii() );
|
|
|
|
}
|
|
|
|
events.saveEpg();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "dvbpanel.moc"
|