DVB-Epg
view release on metacpan or search on metacpan
lib/DVB/Epg.pm view on Meta::CPAN
List eit generator rules.
Return reference to an array of arrays of rules.
=cut
sub listEit {
my $self = shift;
my $dbh = $self->{dbh};
return $dbh->selectall_arrayref( "SELECT * FROM eit ORDER BY pid, uid");
}
=head3 listPid( )
List all destination pid defined in eit generator rules.
Return array of pids.
=cut
sub listPid {
my $self = shift;
my $dbh = $self->{dbh};
my $ref = $dbh->selectcol_arrayref( "SELECT DISTINCT pid FROM eit ORDER BY pid");
return ( defined ($ref) ? @{$ref} : () );
}
=head3 deleteEit( $pid, $service_id, $original_network_id, $transport_stream_id)
Delete eit generator rule.
Parameters are optional.
Return number of deleted rules.
=cut
sub deleteEit {
my $self = shift;
my ( $pid, $service_id, $original_network_id, $transport_stream_id) = @_;
my $dbh = $self->{dbh};
return $dbh->do( "DELETE FROM eit WHERE 1"
. ( defined $pid ? " AND pid=$pid" : "" )
. ( defined $service_id ? " AND service_id=$service_id" : "" )
. ( defined $original_network_id ? " AND original_network_id=$original_network_id" : "" )
. ( defined $transport_stream_id ? " AND transport_stream_id=$transport_stream_id" : "" ) );
}
=head3 updateEit( $pid )
Use eit rules for updateing Eit sections of given $pid in database.
Return 1 on success.
Return 0 if sections are already uptodate.
Return undef on error;
=cut
sub updateEit {
my $self = shift;
my $pid = shift;
my $dbh = $self->{dbh};
my $updated = 0;
if ( !defined $pid) {
return;
}
my $sel = $dbh->prepare("SELECT * FROM eit WHERE pid=$pid");
$sel->execute();
my $ret;
my $rule;
while ( $rule = $sel->fetchrow_hashref ) {
# first calculate present/following
$ret = $self->updateEitPresent($rule);
if( ! defined $ret) {
return;
};
$updated |= $ret;
# and then calculate schedule
if ( $rule->{maxsegments} > 0 ) {
$ret = $self->updateEitSchedule($rule);
if( ! defined $ret) {
return;
};
$updated |= $ret;
}
}
return $updated;
}
=head3 updateEitPresent( $rule, $forced)
Update eit sections for given $rule.
$rule is reference to hash containing keys:
pid, service_id, original_network_id, transport_stream_id, service_id, maxsegments, actual
Update sections only if there are changes in event table of schedule since last update or
the $forced flag is set to 1.
Return undef if failed.
Return 0 if sections are already uptodate.
Return 1 after updating sections.
=cut
sub updateEitPresent {
my $self = shift;
my $rule = shift;
my $forced = shift // 0;
my $dbh = $self->{dbh};
# extend the $rule information
$rule->{table_id} = $rule->{actual} == 1 ? 0x4e : 0x4f;
my $present_following = new DVB::EventInformationTable($rule);
# lookup version_number used at last generation of eit and timestamp
my $select = $dbh->prepare( "SELECT version_number, strftime('%s',timestamp) FROM eit_version "
." WHERE pid=$rule->{pid} AND table_id=$rule->{table_id} AND service_id=$rule->{service_id}" );
$select->execute();
my ( $last_version_number, $last_update_timestamp ) = $select->fetchrow_array();
if( $forced) {
$last_update_timestamp = 0;
}
# if lookup wasn't succesfull we need to update the eit anyway
if ( !defined $last_version_number ) {
$last_update_timestamp = 0;
$last_version_number = 0;
}
# always use this time in queries
my $current_time = time();
# find last started event
$select = $dbh->prepare( "SELECT event_id, strftime('%s',start) AS start, strftime('%s',stop) AS stop, "
. " info, strftime('%s',timestamp) AS timestamp FROM event "
. " WHERE uid=$rule->{uid} AND start <= datetime( $current_time,'unixepoch') ORDER BY start DESC LIMIT 1" );
$select->execute();
my $last_started_event = $select->fetchrow_hashref;
# find following event
$select = $dbh->prepare( "SELECT event_id, strftime('%s',start) AS start, strftime('%s',stop) AS stop, "
. " info, strftime('%s',timestamp) AS timestamp FROM event "
. " WHERE uid=$rule->{uid} AND start > datetime( $current_time,'unixepoch') ORDER BY start LIMIT 1" );
$select->execute();
my $following_event = $select->fetchrow_hashref;
my $buildEit = 0;
# check if we need an update
# is the last started event still lasting
if ( defined $last_started_event && $last_started_event->{stop} > $current_time ) {
# was the start already published or is there a change in the event data
if (
$last_started_event->{start} > $last_update_timestamp
|| # present event started after last update of eit
$last_started_event->{timestamp} > $last_update_timestamp
|| # present event was modified since last update of eit
defined $following_event
lib/DVB/Epg.pm view on Meta::CPAN
if ( defined $last_started_event && $last_started_event->{stop} > $last_update_timestamp
|| # end of last started event was not pulished
defined $following_event && $following_event->{timestamp} > $last_update_timestamp
) # followig event was modified
{
$buildEit = 1;
}
}
return 0 if !$buildEit;
my $pevent;
# if there is a current event add it to table
# or add an empty section
if ( defined $last_started_event && $last_started_event->{stop} > $current_time ) {
$pevent = _unfreezeEvent( $last_started_event );
$pevent->{running_status} = 4;
}
$present_following->add2Section( 0, $pevent );
# if there is a following event add it to table
my $fevent;
if ( defined $following_event ) {
$fevent = _unfreezeEvent( $following_event );
$fevent->{running_status} = ( $following_event->{start} - $current_time ) < 20 ? 2 : 1;
}
$present_following->add2Section( 1, $fevent );
#
# Add this to playout and update version
++$last_version_number;
# Remove all section of this table
return
if !$dbh->do( "DELETE FROM section WHERE pid=$rule->{pid} AND service_id=$rule->{service_id} AND table_id=$rule->{table_id}" );
my $insert = $dbh->prepare( "INSERT INTO section VALUES ( $rule->{pid}, $rule->{table_id}, $rule->{service_id}, ?, ?)");
return if !$insert;
my $sections = $present_following->getSections($last_version_number);
foreach my $section_number ( keys %$sections ) {
$insert->bind_param( 1, $section_number );
$insert->bind_param( 2, $sections->{$section_number}, SQL_BLOB );
$insert->execute();
}
return $dbh->do( "INSERT OR REPLACE INTO eit_version VALUES ($rule->{pid}, $rule->{service_id}, "
. "$rule->{table_id}, $last_version_number, datetime( $current_time,'unixepoch'))"
);
}
=head3 updateEitSchedule( $rule)
Update eit playout packet for given $rule.
$rule is reference to hash containing keys:
pid, service_id, original_network_id, transport_stream_id, service_id, maxsegments, actual
=cut
sub updateEitSchedule {
my $self = shift;
my $rule = shift;
my $dbh = $self->{dbh};
my $num_subtable = int( ( $rule->{maxsegments} - 1 ) / 32 );
# always use this time in queries
my $current_time = time();
my $last_midnight = int( $current_time / ( 24 * 60 * 60 ) ) * 24 * 60 * 60;
# iterate over all subtables
my $subtable_count = 0;
while ( $subtable_count <= $num_subtable ) {
# extend the $rule information
$rule->{table_id} =
( $rule->{actual} == 1 ? 0x50 : 0x60 ) + $subtable_count;
my $schedule = new DVB::EventInformationTable($rule);
# lookup version_number used at last generation of eit and timestamp
my $select = $dbh->prepare(
"SELECT version_number, strftime('%s',timestamp) FROM eit_version
WHERE pid=$rule->{pid} AND table_id=$rule->{table_id} AND service_id=$rule->{service_id}"
);
$select->execute();
my ( $last_version_number, $last_update_timestamp ) =
$select->fetchrow_array();
# if lookup wasn't succesfull we need to update the eit anyway
if ( !defined $last_version_number ) {
$last_update_timestamp = 0;
$last_version_number = 0;
}
# first segment number in this subtable
my $first_segment = $subtable_count * 32;
# start of subtable interval
my $subtable_start = $last_midnight + $first_segment * 3 * 60 * 60;
# last segment in this subtable (actually it is the next of the last)
my $last_segment =
$rule->{maxsegments} >= $first_segment + 32
? $first_segment + 32
: $rule->{maxsegments};
# end of subtable interval and maxsegments
my $subtable_stop = $last_midnight + $last_segment * 3 * 60 * 60;
# find last modification time of events in this subtable
$select = $dbh->prepare( "SELECT strftime('%s',timestamp) AS timestamp FROM event "
. "WHERE uid=$rule->{uid} "
. "AND start >= datetime( $subtable_start,'unixepoch') "
. "AND start < datetime( $subtable_stop,'unixepoch') "
. "ORDER BY timestamp DESC LIMIT 1" );
$select->execute();
my ($last_event_modification) = $select->fetchrow_array() || 0;
( run in 2.454 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )