|
|
|
/*
|
|
|
|
* kaffeinedvbevents.cpp
|
|
|
|
*
|
|
|
|
* Copyright (C) 2003-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 <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
|
|
|
|
#include "kaffeinedvbevents.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ShortEvent::ShortEvent()
|
|
|
|
{
|
|
|
|
name=text="";
|
|
|
|
}
|
|
|
|
|
|
|
|
ShortEvent::~ShortEvent()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
EventDesc::EventDesc()
|
|
|
|
{
|
|
|
|
loop = 0;
|
|
|
|
nid=sid=tsid=eid=0;
|
|
|
|
tid=sn=lsn=running=0;
|
|
|
|
title=subtitle="";
|
|
|
|
source="";
|
|
|
|
shortEvents.setAutoDelete( true );
|
|
|
|
extEvents.setAutoDelete( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventDesc::~EventDesc()
|
|
|
|
{
|
|
|
|
shortEvents.clear();
|
|
|
|
extEvents.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EventSid::EventSid( int s )
|
|
|
|
{
|
|
|
|
sid = s;
|
|
|
|
events.setAutoDelete( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSid::~EventSid()
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
events.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventSid::remove( EventDesc *d )
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
events.remove( d );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventDesc *EventSid::getEventDesc( int n )
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
return events.at(n);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EventTsid::EventTsid( int n, int t )
|
|
|
|
{
|
|
|
|
tsid = t;
|
|
|
|
nid = n;
|
|
|
|
sidList.setAutoDelete( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventTsid::~EventTsid()
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
sidList.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSid *EventTsid::getNEventSid( int n )
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
return sidList.at( n );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSid *EventTsid::getEventSid( int sid )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
for ( i=0; i<(int)sidList.count(); i++ ) {
|
|
|
|
if ( sidList.at(i)->getSid()==sid )
|
|
|
|
return sidList.at(i);
|
|
|
|
}
|
|
|
|
EventSid *es = new EventSid( sid );
|
|
|
|
sidList.append( es );
|
|
|
|
return es;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventDesc *EventTsid::getEventDesc( int sid, int n )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
EventSid *es=0;
|
|
|
|
|
|
|
|
mutex.lock();
|
|
|
|
for ( i=0; i<(int)sidList.count(); i++ ) {
|
|
|
|
if ( sidList.at(i)->getSid()==sid ) {
|
|
|
|
es = sidList.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex.unlock();
|
|
|
|
if ( !es )
|
|
|
|
return 0;
|
|
|
|
return es->getEventDesc( n );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EventSource::EventSource( TQString src )
|
|
|
|
{
|
|
|
|
source = src;
|
|
|
|
tsidList.setAutoDelete( true );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSource::~EventSource()
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
tsidList.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
EventTsid *EventSource::getNEventTsid( int n )
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
return tsidList.at( n );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSid *EventSource::getEventSid( int nid, int tsid, int sid )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
EventTsid *et=0;
|
|
|
|
|
|
|
|
mutex.lock();
|
|
|
|
for ( i=0; i<(int)tsidList.count(); i++ ) {
|
|
|
|
if ( tsidList.at(i)->getTsid()==tsid && (nid==0 || tsidList.at(i)->getNid()==nid) ) {
|
|
|
|
et = tsidList.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( !et ) {
|
|
|
|
if ( nid==0) {
|
|
|
|
mutex.unlock();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
et = new EventTsid( nid, tsid );
|
|
|
|
tsidList.append( et );
|
|
|
|
}
|
|
|
|
mutex.unlock();
|
|
|
|
return et->getEventSid( sid );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventDesc *EventSource::getEventDesc( int nid, int tsid, int sid, int n )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
EventTsid *et=0;
|
|
|
|
|
|
|
|
mutex.lock();
|
|
|
|
for ( i=0; i<(int)tsidList.count(); i++ ) {
|
|
|
|
if ( tsidList.at(i)->getTsid()==tsid && (nid==0 || tsidList.at(i)->getNid()==nid) ) {
|
|
|
|
et = tsidList.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex.unlock();
|
|
|
|
if ( !et )
|
|
|
|
return 0;
|
|
|
|
return et->getEventDesc( sid, n );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EventTable::EventTable()
|
|
|
|
{
|
|
|
|
srcList.setAutoDelete( true );
|
|
|
|
connect ( &cleanTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(setClean()) );
|
|
|
|
cleanTimer.start( 10000 );
|
|
|
|
epgLoaded = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventTable::~EventTable()
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
srcList.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventTable::saveEpg()
|
|
|
|
{
|
|
|
|
EventSource *esrc;
|
|
|
|
EventTsid *et;
|
|
|
|
EventSid *es;
|
|
|
|
TQPtrList<EventDesc> *esEvents;
|
|
|
|
EventDesc *desc;
|
|
|
|
int i, k, j, m, n;
|
|
|
|
TQCString c;
|
|
|
|
int count=0;
|
|
|
|
unsigned char sync=0xff;
|
|
|
|
TQTime t1=TQTime::currentTime();
|
|
|
|
|
|
|
|
TQFile f( locateLocal("appdata", "dvbepg.data" ) );
|
|
|
|
if ( f.open(IO_WriteOnly|IO_Truncate) ) {
|
|
|
|
TQDataStream dt( &f );
|
|
|
|
for( i=0; i<getNSource(); i++ ) {
|
|
|
|
if ( !(esrc=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;
|
|
|
|
dt << sync; // sync byte
|
|
|
|
c = desc->source.utf8();
|
|
|
|
dt << c.data();
|
|
|
|
dt << desc->tid;
|
|
|
|
dt << desc->sid;
|
|
|
|
dt << desc->tsid;
|
|
|
|
dt << desc->nid;
|
|
|
|
dt << desc->sn;
|
|
|
|
dt << desc->lsn;
|
|
|
|
dt << desc->eid;
|
|
|
|
dt << desc->running;
|
|
|
|
dt << desc->startDateTime.toTime_t();
|
|
|
|
dt << (uint)((desc->duration.hour()*3600)+(desc->duration.minute()*60)+desc->duration.second());
|
|
|
|
dt << desc->shortEvents.count();
|
|
|
|
for ( k=0; k<(int)desc->shortEvents.count(); k++ ) {
|
|
|
|
c = desc->shortEvents.at(k)->name.utf8();
|
|
|
|
dt << c.data();
|
|
|
|
c = desc->shortEvents.at(k)->text.utf8();
|
|
|
|
dt << c.data();
|
|
|
|
}
|
|
|
|
dt << (uint)desc->extEvents.count();
|
|
|
|
for ( k=0; k<(int)desc->extEvents.count(); k++ ) {
|
|
|
|
c = desc->extEvents.at(k)->utf8();
|
|
|
|
dt << c.data();
|
|
|
|
}
|
|
|
|
c = desc->title.utf8();
|
|
|
|
dt << c.data();
|
|
|
|
c = desc->subtitle.utf8();
|
|
|
|
dt << c.data();
|
|
|
|
++count;
|
|
|
|
}
|
|
|
|
es->unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.close();
|
|
|
|
fprintf( stderr, "Saved epg data : %d events (%d msecs)\n", count, t1.msecsTo(TQTime::currentTime()) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventTable::loadEpg()
|
|
|
|
{
|
|
|
|
EventDesc *desc;
|
|
|
|
ShortEvent *sev;
|
|
|
|
EventSid *slist;
|
|
|
|
uint count, tmp, i;
|
|
|
|
#define EPGBUFSIZE 500
|
|
|
|
char buf[EPGBUFSIZE];
|
|
|
|
int num=0;
|
|
|
|
unsigned char sync;
|
|
|
|
TQDateTime cur=TQDateTime::currentDateTime();
|
|
|
|
TQTime t1=TQTime::currentTime();
|
|
|
|
|
|
|
|
if ( epgLoaded )
|
|
|
|
return;
|
|
|
|
|
|
|
|
epgLoaded = true;
|
|
|
|
TQFile f( locateLocal("appdata", "dvbepg.data" ) );
|
|
|
|
if ( f.open(IO_ReadOnly) ) {
|
|
|
|
TQDataStream dt( &f );
|
|
|
|
while (!dt.eof() ) {
|
|
|
|
dt >> sync;
|
|
|
|
if ( sync!=0xff ) {
|
|
|
|
f.close();
|
|
|
|
fprintf( stderr, "Sync error while loading epg data : %d events loaded\n", num );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
desc = new EventDesc();
|
|
|
|
dt >> tmp;
|
|
|
|
if ( !validString( f, desc, tmp, EPGBUFSIZE, num ) ) return;
|
|
|
|
dt.readRawBytes( buf, tmp );
|
|
|
|
desc->source = TQString::fromUtf8( buf );
|
|
|
|
dt >> desc->tid;
|
|
|
|
dt >> desc->sid;
|
|
|
|
dt >> desc->tsid;
|
|
|
|
dt >> desc->nid;
|
|
|
|
dt >> desc->sn;
|
|
|
|
dt >> desc->lsn;
|
|
|
|
dt >> desc->eid;
|
|
|
|
dt >> desc->running;
|
|
|
|
dt >> tmp;
|
|
|
|
desc->startDateTime.setTime_t( tmp );
|
|
|
|
dt >> tmp;
|
|
|
|
desc->duration = TQTime().addSecs( tmp );
|
|
|
|
dt >> count;
|
|
|
|
for ( i=0; i<count; i++ ) {
|
|
|
|
sev = new ShortEvent();
|
|
|
|
dt >> tmp;
|
|
|
|
if ( !validString( f, desc, tmp, EPGBUFSIZE, num ) ) return;
|
|
|
|
dt.readRawBytes( buf, tmp );
|
|
|
|
sev->name = TQString::fromUtf8( buf );
|
|
|
|
dt >> tmp;
|
|
|
|
if ( !validString( f, desc, tmp, EPGBUFSIZE, num ) ) return;
|
|
|
|
dt.readRawBytes( buf, tmp );
|
|
|
|
sev->text = TQString::fromUtf8( buf );
|
|
|
|
desc->shortEvents.append( sev );
|
|
|
|
}
|
|
|
|
dt >> count;
|
|
|
|
for ( i=0; i<count; i++ ) {
|
|
|
|
dt >> tmp;
|
|
|
|
if ( !validString( f, desc, tmp, EPGBUFSIZE, num ) ) return;
|
|
|
|
dt.readRawBytes( buf, tmp );
|
|
|
|
desc->extEvents.append( new TQString( TQString::fromUtf8( buf ) ) );
|
|
|
|
}
|
|
|
|
dt >> tmp;
|
|
|
|
if ( !validString( f, desc, tmp, EPGBUFSIZE, num ) ) return;
|
|
|
|
dt.readRawBytes( buf, tmp );
|
|
|
|
desc->title = TQString::fromUtf8( buf );
|
|
|
|
dt >> tmp;
|
|
|
|
if ( !validString( f, desc, tmp, EPGBUFSIZE, num ) ) return;
|
|
|
|
dt.readRawBytes( buf, tmp );
|
|
|
|
desc->subtitle = TQString::fromUtf8( buf );
|
|
|
|
if ( desc->startDateTime.addSecs( (desc->duration.hour()*3600)+(desc->duration.minute()*60)+desc->duration.second() )<cur )
|
|
|
|
delete desc;
|
|
|
|
else {
|
|
|
|
slist = getEventSource( desc->source )->getEventSid( desc->nid, desc->tsid, desc->sid );
|
|
|
|
if ( !slist )
|
|
|
|
continue;
|
|
|
|
slist->lock();
|
|
|
|
slist->getEvents()->append( desc );
|
|
|
|
slist->unlock();
|
|
|
|
++num;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
f.close();
|
|
|
|
fprintf( stderr, "Loaded epg data : %d events (%d msecs)\n", num, t1.msecsTo(TQTime::currentTime()) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool EventTable::validString( TQFile &f, EventDesc *d, int len, int buflen, int nev )
|
|
|
|
{
|
|
|
|
if ( len<1 || len>buflen ) {
|
|
|
|
f.close();
|
|
|
|
fprintf( stderr, "Error while loading epg data : %d events loaded\n", nev );
|
|
|
|
delete d;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventTable::setClean()
|
|
|
|
{
|
|
|
|
start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventTable::doClean( bool b )
|
|
|
|
{
|
|
|
|
if ( b ) {
|
|
|
|
if ( cleanTimer.isActive() )
|
|
|
|
return;
|
|
|
|
cleanTimer.start( 10000 );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cleanTimer.stop();
|
|
|
|
wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EventTable::run()
|
|
|
|
{
|
|
|
|
int k, m, n, sec;
|
|
|
|
EventSource *esrc;
|
|
|
|
EventTsid *et;
|
|
|
|
EventSid *es;
|
|
|
|
EventDesc *desc;
|
|
|
|
TQDateTime dt, cur;
|
|
|
|
|
|
|
|
setpriority(PRIO_PROCESS, 0, 19);
|
|
|
|
|
|
|
|
cur = TQDateTime::currentDateTime();
|
|
|
|
for( k=0; k<getNSource(); k++ ) {
|
|
|
|
if ( !(esrc=getNEventSource( k )) )
|
|
|
|
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;
|
|
|
|
if ( !(desc=es->getEventDesc( 0 )) )
|
|
|
|
continue;
|
|
|
|
dt = desc->startDateTime;
|
|
|
|
sec = desc->duration.hour()*3600+desc->duration.minute()*60+desc->duration.second();
|
|
|
|
if ( dt.addSecs( sec )<cur )
|
|
|
|
es->remove( desc );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSource *EventTable::getNEventSource( int n )
|
|
|
|
{
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
return srcList.at( n );
|
|
|
|
}
|
|
|
|
|
|
|
|
EventSource *EventTable::getEventSource( TQString src )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
TQMutexLocker locker( &mutex );
|
|
|
|
for ( i=0; i<(int)srcList.count(); i++ ) {
|
|
|
|
if ( srcList.at(i)->getSource()==src )
|
|
|
|
return srcList.at(i);
|
|
|
|
}
|
|
|
|
EventSource *es = new EventSource( src );
|
|
|
|
srcList.append( es );
|
|
|
|
return es;
|
|
|
|
}
|
|
|
|
|
|
|
|
EventDesc *EventTable::getEventDesc( TQString src, int nid, int tsid, int sid, int n )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
EventSource *es=0;
|
|
|
|
|
|
|
|
mutex.lock();
|
|
|
|
for ( i=0; i<(int)srcList.count(); i++ ) {
|
|
|
|
if ( srcList.at(i)->getSource()==src ) {
|
|
|
|
es = srcList.at(i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mutex.unlock();
|
|
|
|
if ( !es )
|
|
|
|
return 0;
|
|
|
|
return es->getEventDesc( nid, tsid, sid, n );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KaffeineEpgPlugin::KaffeineEpgPlugin( TQObject* parent, const char* name ) : KParts::Part( parent, name )
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
KaffeineEpgPlugin::~KaffeineEpgPlugin()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KaffeineEpgPlugin::safeLen( unsigned char* buf )
|
|
|
|
{
|
|
|
|
if ( buf<(secbuf+readSize) )
|
|
|
|
return true;
|
|
|
|
fprintf( stderr, "EIT (%d:%d) : buffer overflow! Rejected\n", adapter, tuner );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kaffeinedvbevents.moc"
|