diff options
| author | Andreas Brachold <vdr07@deltab.de> | 2008-07-27 15:17:25 +0000 |
|---|---|---|
| committer | Andreas Brachold <vdr07@deltab.de> | 2008-07-27 15:17:25 +0000 |
| commit | ac6b1338382543613e1a7d319aeecb4451a7de9e (patch) | |
| tree | f8dbd70be0d8961e43054df86a188a68afc2f675 /lib | |
| parent | 180fcff6fe93d51e6ac68fc43e6fb186dcee80d8 (diff) | |
| download | xxv-ac6b1338382543613e1a7d319aeecb4451a7de9e.tar.gz xxv-ac6b1338382543613e1a7d319aeecb4451a7de9e.tar.bz2 | |
* Redesign SVDRP Communation to support more as one video disk recorder (Change database schema to version 30)
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/XXV/MODULES/AUTOTIMER.pm | 31 | ||||
| -rw-r--r-- | lib/XXV/MODULES/CHANNELS.pm | 907 | ||||
| -rw-r--r-- | lib/XXV/MODULES/CONFIG.pm | 18 | ||||
| -rw-r--r-- | lib/XXV/MODULES/EPG.pm | 556 | ||||
| -rw-r--r-- | lib/XXV/MODULES/GRAB.pm | 78 | ||||
| -rw-r--r-- | lib/XXV/MODULES/KEYWORDS.pm | 34 | ||||
| -rw-r--r-- | lib/XXV/MODULES/MOVETIMER.pm | 103 | ||||
| -rw-r--r-- | lib/XXV/MODULES/RECORDS.pm | 517 | ||||
| -rw-r--r-- | lib/XXV/MODULES/REMOTE.pm | 108 | ||||
| -rw-r--r-- | lib/XXV/MODULES/STREAM.pm | 63 | ||||
| -rw-r--r-- | lib/XXV/MODULES/SVDRP.pm | 479 | ||||
| -rw-r--r-- | lib/XXV/MODULES/TIMERS.pm | 681 | ||||
| -rw-r--r-- | lib/XXV/MODULES/XMLTV.pm | 7 | ||||
| -rw-r--r-- | lib/XXV/OUTPUT/Html.pm | 8 |
14 files changed, 2178 insertions, 1412 deletions
diff --git a/lib/XXV/MODULES/AUTOTIMER.pm b/lib/XXV/MODULES/AUTOTIMER.pm index 31418e0..26bab5e 100644 --- a/lib/XXV/MODULES/AUTOTIMER.pm +++ b/lib/XXV/MODULES/AUTOTIMER.pm @@ -418,14 +418,14 @@ sub _autotimerLookup { # Exclude unwanted channels if($obj->{exclude}) { - $sql .= sprintf(' AND ( e.channel_id = c.Id ) AND NOT (c.%s)', + $sql .= sprintf(' AND ( e.channel_id = c.id AND e.vid = c.vid ) AND NOT (c.%s)', $obj->{exclude}); } my $sth = $obj->{dbh}->prepare($sql) or return error sprintf("Couldn't prepare query: %s.",$sql); $sth->execute($addtime) - or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + or return error sprintf("Couldn't execute query: %s\r\n%s.",$sth->errstr,$sql); } my $now = time; @@ -477,7 +477,7 @@ sub _autotimerLookup { foreach my $eventid (sort keys %$events) { my $event = $events->{$eventid}; - $event->{activ} = 'y'; + $event->{active} = 'y'; $event->{priority} = $a->{Priority}; $event->{lifetime} = $a->{Lifetime}; @@ -545,7 +545,7 @@ sub _autotimerLookup { my $error = 0; if($timerID) { - $event->{pos} = $modT->getPos($timerID); + ($event->{vid},$event->{pos}) = $modT->getPos($timerID); } my $erg = $modT->saveTimer($event); foreach my $zeile (@$erg) { @@ -643,7 +643,7 @@ sub autotimerEdit { # Channels Ids in Namen umwandeln if($epg->{Channels}) { - my @channels = map { $_ = $modC->ChannelToPos($_) } split(/[\s|,]+/, $epg->{Channels}); + my @channels = split(/[\s|,]+/, $epg->{Channels}); $epg->{Channels} = \@channels; } @@ -741,14 +741,14 @@ You can also fine tune your search : 'Channels' => { typ => 'list', def => $epg->{Channels}, - choices => $modC->ChannelWithGroup('Name,POS', sprintf(' NOT (%s)', $obj->{exclude})), + choices => $modC->ChannelWithGroup('c.name,c.id', sprintf(' NOT (c.%s)', $obj->{exclude})), options => 'multi', msg => gettext('Limit search to these channels'), check => sub{ my $value = shift || return; my @vals; foreach my $chname ((ref $value eq 'ARRAY' ? @$value : split(/\s*,\s*/, $value))) { - if( my $chid = $modC->PosToChannel($chname) || $modC->NameToChannel($chname)) { + if( my $chid = $modC->ToCID($chname)) { push(@vals, $chid); } else { return undef, sprintf(gettext("The channel '%s' does not exist!"),$chname); @@ -946,8 +946,7 @@ You can also fine tune your search : 'Dir' => { typ => 'string', msg => gettext('Group all recordings into one directory'), - def => $epg->{Dir}, - # choices => $modT->getRootDirs, + def => $epg->{Dir} }, 'startdate' => { typ => 'string', @@ -1169,7 +1168,7 @@ sub list { my %f = ( 'Id' => gettext('Service'), - 'Activ' => gettext('Activ'), + 'Active' => gettext('Active'), 'Search' => gettext('Search'), 'Channels' => gettext('Channels'), 'Start' => gettext('Start time'), @@ -1181,7 +1180,7 @@ sub list { my $sql = qq| SELECT SQL_CACHE Id as \'$f{'Id'}\', - Activ as \'$f{'Activ'}\', + Activ as \'$f{'Active'}\', Search as \'$f{'Search'}\', Channels as \'$f{'Channels'}\', Dir as \'$f{'Dir'}\', @@ -1244,13 +1243,13 @@ sub list { if($obj->{exclude}) { $sql .= sprintf('NOT (%s)', $obj->{exclude}); } - my $channels = main::getModule('CHANNELS')->ChannelHash('Id',$exclude); + my $channels = main::getModule('CHANNELS')->ChannelHash('id',$exclude); map { if($_->[3]) { my @ch; foreach my $c (split(',',$_->[3])) { - my $name = $channels->{$c} ? $channels->{$c}->{'Name'} : undef; + my $name = $channels->{$c} ? $channels->{$c}->{'name'} : undef; unless($name) { $name = sprintf(gettext('Unknown channel : %s'),$c); } @@ -1373,6 +1372,7 @@ sub _eventsearch { my $sql = qq| SELECT SQL_CACHE e.eventid as eventid, + e.vid, e.channel_id as channel, c.Name as channelname, e.title as title, @@ -1387,7 +1387,10 @@ FROM CHANNELS as c WHERE ( $search ) - AND ( e.channel_id = c.Id ) + AND ( e.channel_id = c.id ) + AND ( e.vid = c.vid ) +GROUP BY + c.id , e.eventid ORDER BY e.starttime |; diff --git a/lib/XXV/MODULES/CHANNELS.pm b/lib/XXV/MODULES/CHANNELS.pm index 3a88a76..5da2811 100644 --- a/lib/XXV/MODULES/CHANNELS.pm +++ b/lib/XXV/MODULES/CHANNELS.pm @@ -8,7 +8,7 @@ use Tools; # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'CHANNELS', Prereq => { @@ -19,7 +19,7 @@ sub module { Date => (split(/ /, '$Date$'))[1], Author => 'xpix', LastAuthor => (split(/ /, '$Author$'))[1], - Status => sub{ $obj->status(@_) }, + Status => sub{ $self->status(@_) }, Preferences => { interval => { description => gettext('How often channels are to be updated (in seconds)'), @@ -40,7 +40,7 @@ sub module { default => '', choices => sub{ my $knownCA; - foreach my $CA (@{$obj->{knownCA}}) { + foreach my $CA (@{$self->{knownCA}}) { my $desc; if($CA eq '0') { $desc = gettext("Free-to-air"); } elsif($CA eq '1' @@ -76,34 +76,34 @@ sub module { cupdate => { description => gettext('Read channels and write them to the database'), short => 'cu', - callback => sub{ $obj->readData(@_) }, + callback => sub{ $self->readData(@_) }, DenyClass => 'cedit', Level => 'user', }, clist => { description => gettext("List channels from database 'cname'"), short => 'cl', - callback => sub{ $obj->list(@_) }, + callback => sub{ $self->list(@_) }, Level => 'user', }, cnew => { description => gettext("Create new channel"), short => 'cne', - callback => sub{ $obj->newChannel(@_) }, + callback => sub{ $self->newChannel(@_) }, Level => 'user', DenyClass => 'cedit', }, cedit => { description => gettext("Edits a channel 'cid'"), short => 'ced', - callback => sub{ $obj->editChannel(@_) }, + callback => sub{ $self->editChannel(@_) }, Level => 'user', DenyClass => 'cedit', }, cdelete => { description => gettext("Deletes one or more channels 'pos'"), short => 'cdl', - callback => sub{ $obj->deleteChannel(@_) }, + callback => sub{ $self->deleteChannel(@_) }, Level => 'user', DenyClass => 'cedit', }, @@ -115,16 +115,16 @@ sub module { # ------------------ sub status { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $lastReportTime = shift || 0; my $sql = "SELECT SQL_CACHE count(*) from CHANNELS"; - my $gesamt = $obj->{dbh}->selectrow_arrayref($sql)->[0]; + my $gesamt = $self->{dbh}->selectrow_arrayref($sql)->[0]; $sql = "SELECT SQL_CACHE count(*) from CHANNELGROUPS"; - my $groups = $obj->{dbh}->selectrow_arrayref($sql)->[0]; + my $groups = $self->{dbh}->selectrow_arrayref($sql)->[0]; return { message => sprintf(gettext('The system has saved %d channels from %d groups'), $gesamt, $groups), @@ -179,7 +179,7 @@ sub new { prio => 6, # -1 very hard ... 6 very low cb => sub{ lg 'Start the interval reading channels to DB!'; - $self->readData(); + $self->_readData(); }, ); @@ -189,62 +189,66 @@ sub new { # ------------------ sub _init { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); - unless($obj->{dbh}) { + unless($self->{dbh}) { panic("Session to database is'nt connected"); return 0; } - my $version = 27; # Must be increment if rows of table changed + my $version = 30; # Must be increment if rows of table changed # this tables hasen't handmade user data, # therefore old table could dropped if updated rows - if(!tableUpdated($obj->{dbh},'CHANNELS',$version,1)) { + if(!tableUpdated($self->{dbh},'CHANNELS',$version,1)) { return 0; } - if(!tableUpdated($obj->{dbh},'CHANNELGROUPS',$version,1)) { + if(!tableUpdated($self->{dbh},'CHANNELGROUPS',$version,1)) { return 0; } # Look for table or create this table - $obj->{dbh}->do(qq| + $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS CHANNELS ( - Id varchar(100) NOT NULL, - Name varchar(100) NOT NULL default '', - Frequency int(11) NOT NULL default '0', - Parameters varchar(100) default '', - Source varchar(100), - Srate int(11) default 0, + id varchar(32) NOT NULL, + vid int unsigned NOT NULL, + name varchar(100) NOT NULL default '', + frequency int unsigned NOT NULL default '0', + parameters varchar(100) default '', + source varchar(8), + symbols int unsigned default 0, VPID varchar(100) default '', APID varchar(100) default '', TPID varchar(100) default '', CA varchar(100) default '', - SID int(11) default 0, - NID int(11) default 0, - TID int(11) default 0, - RID int(11) default 0, - GRP int(11) default 0, - POS int(11) NOT NULL, - PRIMARY KEY (Id) + SID int unsigned default 0, + NID int unsigned default 0, + TID int unsigned default 0, + RID int unsigned default 0, + grp int unsigned default 0, + pos int unsigned NOT NULL, + hash varchar(32) NOT NULL, + PRIMARY KEY (hash) ) COMMENT = '$version' |); - $obj->{dbh}->do(qq| + $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS CHANNELGROUPS ( - Id int(11) not NULL, - Name varchar(100) default 'unknown', - PRIMARY KEY (Id) + id int unsigned not NULL, + pos int unsigned NOT NULL, + vid int unsigned NOT NULL, + name varchar(100) default 'unknown', + PRIMARY KEY (id) ) COMMENT = '$version' |); main::after(sub{ - $obj->{svdrp} = main::getModule('SVDRP'); - unless($obj->{svdrp}) { + $self->{svdrp} = main::getModule('SVDRP'); + unless($self->{svdrp}) { panic ("Couldn't get modul SVDRP"); return 0; } - return $obj->readData(); + return $self->_readData(); }, "CHANNELS: Read and register channels ...", 5); return 1; } @@ -252,26 +256,27 @@ sub _init { # ------------------ sub _prepare { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $data = shift || return; my $pos = shift || return; my $grp = shift || 0; + my $vid = shift; foreach my $CA (split(',', $data->[8])) { - push(@{$obj->{knownCA}},$CA); + push(@{$self->{knownCA}},$CA); } - return if($obj->{empty} eq 'n' and not (($data->[6] ne "0" || $data->[7] ne "0"))); # Ignore Channels with APID = 0/TPID = 0 from PID Scan - if($obj->{filterCA} ne "") { - my $filter = $obj->{filterCA}; + return if($self->{empty} eq 'n' and not (($data->[6] ne "0" || $data->[7] ne "0"))); # Ignore Channels with APID = 0/TPID = 0 from PID Scan + if($self->{filterCA} ne "") { + my $filter = $self->{filterCA}; $filter =~ s/\,/|/g; # Transform 0,2,400 => 0|2|400 return 0 if(not ($data->[8] =~ /(^|\,)($filter)(\,|$)/s)); # check (^|,)(0|2|400)(,|$) } # Strip short and providername from channelname e.g ch - if($obj->{stripCH}) { + if($self->{stripCH}) { my $ch = $data->[0]; - my $filter = $obj->{stripCH}; + my $filter = $self->{stripCH}; my @p = split(';',$filter); if(scalar @p == 2) { if(($p[0] =~ /provider/i)) { # format "provider;name" @@ -316,12 +321,12 @@ sub _prepare { } my $attr = { - Id => $id, - Name => $data->[0], - Frequency => $data->[1], - Parameters => $data->[2], - Source => $data->[3], - Srate => $data->[4], + id => $id, + name => $data->[0], + frequency => $data->[1], + parameters => $data->[2], + source => $data->[3], + symbols => $data->[4], VPID => $data->[5], APID => $data->[6], TPID => $data->[7], @@ -330,8 +335,9 @@ sub _prepare { NID => $data->[10], TID => $data->[11], RID => $data->[12], - GRP => $grp, - POS => $pos + grp => $grp, + pos => $pos, + vid => $vid }; return $attr; } @@ -339,17 +345,20 @@ sub _prepare { # ------------------ sub _replace { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $attr = shift || return error('No data defined!'); - my $sth = $obj->{dbh}->prepare('REPLACE INTO CHANNELS(Id,Name,Frequency,Parameters,Source,Srate,VPID,APID,TPID,CA,SID,NID,TID,RID,GRP,POS) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'); + my $sth = $self->{dbh}->prepare('REPLACE INTO CHANNELS(id,vid,hash,name,frequency,parameters,source,symbols,VPID,APID,TPID,CA,SID,NID,TID,RID,grp,pos) VALUES (?,?,md5(concat(?,?)),?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'); return $sth->execute( - $attr->{Id}, - $attr->{Name}, - $attr->{Frequency}, - $attr->{Parameters}, - $attr->{Source}, - $attr->{Srate}, + $attr->{id}, + $attr->{vid}, + $attr->{id}, + $attr->{vid}, + $attr->{name}, + $attr->{frequency}, + $attr->{parameters}, + $attr->{source}, + $attr->{symbols}, $attr->{VPID}, $attr->{APID}, $attr->{TPID}, @@ -358,21 +367,23 @@ sub _replace { $attr->{NID}, $attr->{TID}, $attr->{RID}, - $attr->{GRP}, - $attr->{POS} + $attr->{grp}, + $attr->{pos} ); } # ------------------ -sub insertGrp { +sub _insertGrp { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); + my $id = shift || return; my $pos = shift || return; my $name = shift || 0; + my $vid = shift; lg sprintf('Update group of channels "%s" (%d).', $name, $pos); - my $sth = $obj->{dbh}->prepare('REPLACE INTO CHANNELGROUPS SET Name=?, Id=?'); - $sth->execute($name, $pos) + my $sth = $self->{dbh}->prepare('REPLACE INTO CHANNELGROUPS SET name=?, id=?, pos=?, vid=?'); + $sth->execute($name, $id, $pos, $vid) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); return $pos; } @@ -380,158 +391,181 @@ sub insertGrp { # ------------------ sub readData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; - # Read channels over SVDRP - my $lstc = $obj->{svdrp}->command('lstc :groups'); - my $vdrData = [ grep(/^250/, @$lstc) ]; - - unless(scalar @$vdrData) { - # Delete old Records - $obj->{dbh}->do('DELETE FROM CHANNELS'); - $obj->{dbh}->do('DELETE FROM CHANNELGROUPS'); - - my $msg = gettext('No channels available!'); - con_err($console,$msg); - return; + if($self->_readData($watcher,$console)) { + $console->redirect({url => '?cmd=clist', wait => 1}) + if($console->typ eq 'HTML'); } +} +# ------------------ +sub _readData { +# ------------------ + my $self = shift || return error('No object defined!'); + my $watcher = shift; + my $console = shift; - my $nPos = 1; - my $grp = 0; - my $channelText; - my $grpText; - my $newChannels; - my $changedData = 0; - my $updatedData = 0; my $deleteData = 0; + my $updatedData = 0; + my $changedData = 0; + my $newChannels; + my $channelText; + my $nGrpCnt = 0; + # Read channels over SVDRP + my $hostlist = $self->{svdrp}->list_hosts(); + # read from svdrp + foreach my $vid (@$hostlist) { + my $lstc = $self->{svdrp}->command('lstc :groups',$vid); + my $vdrData = [ grep(/^250/, @$lstc) ]; + + my $grpText; + + unless(scalar @$vdrData) { + # Delete any channels from this video disk recorder + my $csth = $self->{dbh}->prepare('DELETE FROM CHANNELS where vid = ?'); + $csth->execute($vid) + or return error sprintf("Couldn't execute query: %s.",$csth->errstr); + + my $dsth = $self->{dbh}->prepare('DELETE FROM CHANNELGROUPS where vid = ?'); + $dsth->execute($vid) + or return error sprintf("Couldn't execute query: %s.",$dsth->errstr); + + my $msg = gettext(sprintf("No channels on '%s' available!",$self->{svdrp}->hostname($vid))); + con_err($console,$msg); + next; + } - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE * from CHANNELS'); - $sth->execute() - or return error sprintf("Couldn't execute query: %s.",$sth->errstr); - my $db_data = $sth->fetchall_hashref('Id'); + my $nPos = 1; + my $grp = 0; - my $gsth = $obj->{dbh}->prepare('SELECT SQL_CACHE * from CHANNELGROUPS'); - $gsth->execute() - or return error sprintf("Couldn't execute query: %s.",$gsth->errstr); - my $grp_data = $gsth->fetchall_hashref('Id'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE * from CHANNELS where vid = ?'); + $sth->execute($vid) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $db_data = $sth->fetchall_hashref('id'); - lg sprintf("Compare channels database with data from vdr : %d / %d", (scalar keys %$db_data) + (scalar keys %$grp_data) ,scalar @$vdrData); - - foreach my $line (@{$vdrData}) { + my $gsth = $self->{dbh}->prepare('SELECT SQL_CACHE * from CHANNELGROUPS where vid = ?'); + $gsth->execute($vid) + or return error sprintf("Couldn't execute query: %s.",$gsth->errstr); + my $grp_data = $gsth->fetchall_hashref('id'); - next if($line eq ""); + lg sprintf("Compare channels database with data from %s : %d / %d", $self->{svdrp}->hostname($vid), (scalar keys %$db_data) + (scalar keys %$grp_data) ,scalar @$vdrData); + + foreach my $line (@{$vdrData}) { - # 250-0 ... it's a group delimiter - if($line =~ /^250[\-|\s]0\s/) { - if($line =~ /^250[\-|\s]0\s\:\@\d+/) { # Entry to specify the number of the next channel - ($nPos, $grpText) = $line =~ /^250[\-|\s]0\s\:\@(\d+)\s(.+)/si; - } else { # Entry without specify the number of the next channel - ($grpText) = $line =~ /^250[\-|\s]0\s\:(.+)/si; - } + next if($line eq ""); - next unless($grpText); #ignore empty group delimiter like :@500 + # 250-0 ... it's a group delimiter + if($line =~ /^250[\-|\s]0\s/) { + if($line =~ /^250[\-|\s]0\s\:\@\d+/) { # Entry to specify the number of the next channel + ($nPos, $grpText) = $line =~ /^250[\-|\s]0\s\:\@(\d+)\s(.+)/si; + } else { # Entry without specify the number of the next channel + ($grpText) = $line =~ /^250[\-|\s]0\s\:(.+)/si; + } - if(exists $grp_data->{$nPos}) { - if($grp_data->{$nPos}->{Name} ne $grpText) { - $grp = $obj->insertGrp($nPos, $grpText); + next unless($grpText); #ignore empty group delimiter like :@500 + $nGrpCnt++; + if(exists $grp_data->{$nGrpCnt}) { + if($grp_data->{$nGrpCnt}->{name} ne $grpText) { + $grp = $self->_insertGrp($nGrpCnt, $nPos, $grpText, $vid); + } else { + $grp = $nPos; + } + delete $grp_data->{$nGrpCnt}; } else { - $grp = $nPos; + $grp = $self->_insertGrp($nGrpCnt, $nPos, $grpText, $vid); } - delete $grp_data->{$nPos}; + # 250-x ... it's channel x } else { - $grp = $obj->insertGrp($nPos, $grpText); - } - # 250-x ... it's channel x - } else { - unless($grp) { # Insert a default group delimiter - $grp = 1; - if(exists $grp_data->{$grp}) { - $grpText = gettext("Channels"); - if($grp_data->{$nPos}->{Name} ne $grpText) { - $obj->insertGrp($grp, $grpText); + unless($grp) { # Insert a default group delimiter + $nGrpCnt++; + $grp = 1; + if(exists $grp_data->{$nGrpCnt}) { + $grpText = gettext("Channels"); + if($grp_data->{$nPos}->{name} ne $grpText) { + $self->_insertGrp($nGrpCnt, $grp, $grpText, $vid); + } + delete $grp_data->{$nGrpCnt}; + } else { + $self->_insertGrp($nGrpCnt, $grp, $grpText, $vid); } - delete $grp_data->{$nPos}; - } else { - $obj->insertGrp($grp, $grpText); } - } - # parse channel line - ($nPos, $channelText) = $line =~ /^250[\-|\s](\d+)\s(.+)/si; - - my @data = split(':', $channelText, 13); - $data[-1] = (split(':', $data[-1]))[0]; - - if(scalar @data > 4) { - my $row = $obj->_prepare(\@data, $nPos++, $grp); - next unless($row); - - my $id = $row->{Id}; - - # Exists in DB .. update - if(exists $db_data->{$id}) { - # Compare fields - foreach my $field (qw/Name Frequency Parameters Source Srate VPID APID TPID CA SID NID TID RID GRP POS/) { - next if(not exists $row->{$field} or not $row->{$field}); - if((not exists $db_data->{$id}->{$field}) - or (not $db_data->{$id}->{$field}) - or ($db_data->{$id}->{$field} ne $row->{$field})) { - lg sprintf('Update channel "%s" - %s.', $row->{Name}, $id); - $obj->_replace($row); - $updatedData++; - last; + # parse channel line + ($nPos, $channelText) = $line =~ /^250[\-|\s](\d+)\s(.+)/si; + + my @data = split(':', $channelText, 13); + $data[-1] = (split(':', $data[-1]))[0]; + + if(scalar @data > 4) { + my $row = $self->_prepare(\@data, $nPos++, $nGrpCnt, $vid); + next unless($row); + + my $id = $row->{id}; + + # Exists in DB .. update + if(exists $db_data->{$id}) { + # Compare fields + foreach my $field (qw/name frequency parameters source symbols VPID APID TPID CA SID NID TID RID grp pos/) { + next if(not exists $row->{$field} or not $row->{$field}); + if((not exists $db_data->{$id}->{$field}) + or (not $db_data->{$id}->{$field}) + or ($db_data->{$id}->{$field} ne $row->{$field})) { + lg sprintf('Update channel "%s" - %s.', $row->{name}, $id); + $self->_replace($row); + $updatedData++; + last; + } } - } - # delete updated rows from hash - delete $db_data->{$id}; + # delete updated rows from hash + delete $db_data->{$id}; - } else { - # Not exists in DB .. insert - lg sprintf('Add new channel "%s" - %s.', $row->{Name}, $id); - $obj->_replace($row); - $changedData++; - # Remember new channels - $newChannels->{$id} = $row; + } else { + # Not exists in DB .. insert + lg sprintf('Add new channel "%s" - %s.', $row->{name}, $id); + $self->_replace($row); + $changedData++; + # Remember new channels + $newChannels->{$id} = $row; + } } - } + } } - } - # Delete unused entrys in DB - if(scalar keys %$db_data > 0) { - my @todel = keys(%$db_data); - my $sql = sprintf('DELETE FROM CHANNELS WHERE Id IN (%s)', join(',' => ('?') x @todel)); - my $sth = $obj->{dbh}->prepare($sql); - if(!$sth->execute(@todel)) { - error sprintf("Couldn't execute query: %s.",$sth->errstr); + # Delete unused entrys in DB + if(scalar keys %$db_data > 0) { + my @todel = keys(%$db_data); + my $sql = sprintf('DELETE FROM CHANNELS WHERE vid = ? AND id IN (%s)', join(',' => ('?') x @todel)); + my $sth = $self->{dbh}->prepare($sql); + if(!$sth->execute($vid, @todel)) { + error sprintf("Couldn't execute query: %s.",$sth->errstr); + } + $deleteData += scalar @todel; } - $deleteData += scalar @todel; - } - # Delete unused entrys in DB - if(scalar keys %$grp_data > 0) { - my @todel = keys(%$grp_data); - my $sql = sprintf('DELETE FROM CHANNELGROUPS WHERE Id IN (%s)', join(',' => ('?') x @todel)); - my $sth = $obj->{dbh}->prepare($sql); - if(!$sth->execute(@todel)) { - error sprintf("Couldn't execute query: %s.",$sth->errstr); + # Delete unused entrys in DB + if(scalar keys %$grp_data > 0) { + my @todel = keys(%$grp_data); + my $sql = sprintf('DELETE FROM CHANNELGROUPS WHERE vid = ? AND id IN (%s)', join(',' => ('?') x @todel)); + my $sth = $self->{dbh}->prepare($sql); + if(!$sth->execute($vid, @todel)) { + error sprintf("Couldn't execute query: %s.",$sth->errstr); + } + #$deleteData += scalar @todel; } - #$deleteData += scalar @todel; } - # sort list with CA numerical my %CA; - @CA{@{$obj->{knownCA}}} = (); - @{$obj->{knownCA}} = sort { if(is_numeric($a) && is_numeric($b)) { + @CA{@{$self->{knownCA}}} = (); + @{$self->{knownCA}} = sort { if(is_numeric($a) && is_numeric($b)) { $a <=> $b } else { $a cmp $b } } keys %CA; - $obj->_brandNewChannels($newChannels) if($newChannels); + $self->_brandNewChannels($newChannels) if($newChannels); con_msg($console, sprintf(gettext("There are %d channels inserted, %d channels updated, %d channels deleted into database."), $changedData, $updatedData, $deleteData)); @@ -559,19 +593,19 @@ sub is_numeric { defined getnum($_[0]) } # ------------------ sub list { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $id = shift || ''; my $params = shift; my %f = ( - 'Id' => gettext('Service'), - 'Name' => gettext('Name'), - 'Frequency' => gettext('Transponder frequency'), - 'Parameters' => gettext('Parameters'), - 'Source' => gettext('Signal source'), - 'Srate' => gettext('Symbol rate'), + 'id' => gettext('Service'), + 'name' => gettext('Name'), + 'frequency' => gettext('Transponder frequency'), + 'parameters' => gettext('Parameters'), + 'source' => gettext('Signal source'), + 'symbols' => gettext('Symbol rate'), 'VPID' => gettext('Video PID'), 'APID' => gettext('Audio PID'), 'TPID' => gettext('Teletext PID'), @@ -580,18 +614,18 @@ sub list { 'TID' => gettext('TID'), 'NID' => gettext('NID'), 'RID' => gettext('RID'), - 'GRP' => gettext('Channel group'), - 'POS' => gettext('Position'), + 'grp' => gettext('Channel group'), + 'pos' => gettext('Position'), ); my $sql = qq| SELECT SQL_CACHE - c.Id as \'$f{'Id'}\', - c.Name as \'$f{'Name'}\', - c.Frequency as \'$f{'Frequency'}\', - c.Parameters as \'$f{'Parameters'}\', - c.Source as \'$f{'Source'}\', - c.Srate as \'$f{'Srate'}\', + c.hash as \'$f{'id'}\', + c.name as \'$f{'name'}\', + c.frequency as \'$f{'frequency'}\', + c.parameters as \'$f{'parameters'}\', + c.source as \'$f{'source'}\', + c.symbols as \'$f{'symbols'}\', c.VPID as \'$f{'VPID'}\', c.APID as \'$f{'APID'}\', c.TPID as \'$f{'TPID'}\', @@ -600,19 +634,26 @@ SELECT SQL_CACHE c.NID as \'$f{'NID'}\', c.TID as \'$f{'TID'}\', c.RID as \'$f{'RID'}\', - c.GRP as \'$f{'GRP'}\', - c.POS as \'$f{'POS'}\', - cg.Name as __GrpName + c.grp as \'$f{'grp'}\', + c.pos as \'$f{'pos'}\', + cg.name as __GrpName, + ( SELECT + r.host + FROM RECORDER as r + WHERE r.id = c.vid + LIMIT 1) as __host from CHANNELS as c, CHANNELGROUPS as cg WHERE - c.Name LIKE ? - AND c.GRP = cg.Id + c.name LIKE ? + AND c.grp = cg.id + AND c.vid = cg.vid ORDER BY + c.vid, |; - my $sortby = "POS"; + my $sortby = "c.pos"; if(exists $params->{sortby}) { while(my($k, $v) = each(%f)) { if($params->{sortby} eq $k or $params->{sortby} eq $v) { @@ -629,7 +670,7 @@ ORDER BY my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute('%'.$id.'%') or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -643,7 +684,7 @@ ORDER BY } } - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute('%'.$id.'%') or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); $rows = $sth->rows unless($rows); @@ -664,157 +705,308 @@ ORDER BY # ------------------ sub NameToChannel { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $name = shift || return undef; + my $vid = shift; + if($vid) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE id from CHANNELS where vid = ? AND UPPER(name) = UPPER( ? )'); + $sth->execute($vid, $name) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{id} : undef; + } else { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE id from CHANNELS where UPPER(name) = UPPER( ? )'); + $sth->execute($name) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{id} : undef; + } +} - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE Id from CHANNELS where UPPER(Name) = UPPER( ? )'); - $sth->execute($name) +# ------------------ +sub GetChannel { +# ------------------ + my $self = shift || return error('No object defined!'); + my $hash = shift || return undef; + + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE * from CHANNELS where hash = ?'); + $sth->execute($hash) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchrow_hashref(); - return $erg ? $erg->{Id} : undef; + return $erg; } # ------------------ sub PosToName { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $pos = shift || return undef; - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE Name from CHANNELS where POS = ?'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE name from CHANNELS where pos = ?'); $sth->execute($pos) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchrow_hashref(); - return $erg ? $erg->{Name} : undef; + return $erg ? $erg->{name} : undef; } # ------------------ sub PosToChannel { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $pos = shift || return undef; - - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE Id from CHANNELS where POS = ?'); - $sth->execute($pos) + my $vid = shift; + if($vid) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE id from CHANNELS where vid = ? AND pos = ?'); + $sth->execute($vid,$pos) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); - my $erg = $sth->fetchrow_hashref(); - return $erg ? $erg->{Id} : undef; + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{id} : undef; + } else { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE id from CHANNELS where pos = ?'); + $sth->execute($pos) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{id} : undef; + } } # ------------------ sub ChannelGroupsArray { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $field = shift || return undef; my $where = shift || ''; $where = sprintf('WHERE %s', $where) if($where); - my $sql = sprintf('SELECT SQL_CACHE %s, Id from CHANNELGROUPS %s order by Id', $field, $where); - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sql = sprintf('SELECT SQL_CACHE %s, min(id) as id from CHANNELGROUPS %s GROUP BY name ORDER BY id, vid', $field, $where); + my $erg = $self->{dbh}->selectall_arrayref($sql); return $erg; } # ------------------ sub ChannelArray { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $field = shift || return undef; my $where = shift || ''; $where = sprintf('WHERE %s', $where) if($where); - my $sql = sprintf('SELECT SQL_CACHE %s, POS from CHANNELS %s order by POS', $field, $where); - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sql = sprintf('SELECT SQL_CACHE %s, pos from CHANNELS %s order by pos', $field, $where); + my $erg = $self->{dbh}->selectall_arrayref($sql); + return $erg; +} + +################################################################################ +# Get id of any group with same group name +sub GroupsByName { + my $self = shift || return error('No object defined!'); + my $name = shift || return undef; + + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE id from CHANNELGROUPS where name = ? order by vid, pos'); + $sth->execute($name) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchall_arrayref(); return $erg; } # ------------------ sub ChannelWithGroup { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $field = shift || return undef; my $where = shift || ''; $where = sprintf('WHERE %s', $where) if($where); - my $sql = sprintf(q|SELECT SQL_CACHE %s, ( SELECT - g.Name FROM CHANNELGROUPS as g WHERE c.GRP = g.Id - LIMIT 1) as GRP from CHANNELS as c %s order by c.POS|, $field, $where); - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sql = sprintf(q| +SELECT SQL_CACHE %s, ( SELECT g.name FROM CHANNELGROUPS as g WHERE c.grp = g.id AND c.vid = g.vid LIMIT 1) as grp + from CHANNELS as c,CHANNELGROUPS as g %s GROUP BY c.id order by c.vid, c.pos +|, $field, $where); + +# my $sql = sprintf(q|SELECT SQL_CACHE %s, ( SELECT +# g.name FROM CHANNELGROUPS as g WHERE c.grp = g.id AND c.vid = g.vid +# LIMIT 1) as grp from CHANNELS as c %s order by c.vid, c.pos|, $field, $where); + my $erg = $self->{dbh}->selectall_arrayref($sql); return $erg; } # ------------------ sub ChannelIDArray { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $field = shift || return undef; my $where = shift || ''; $where = sprintf('WHERE %s', $where) if($where); - my $sql = sprintf('SELECT SQL_CACHE %s, Id from CHANNELS %s order by POS', $field, $where); - my $erg = $obj->{dbh}->selectall_arrayref($sql); + my $sql = sprintf('SELECT SQL_CACHE %s, id from CHANNELS %s order by pos', $field, $where); + my $erg = $self->{dbh}->selectall_arrayref($sql); return $erg; } # ------------------ sub ChannelHash { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $field = shift || return undef; my $where = shift || ''; $where = sprintf('WHERE %s', $where) if($where); my $sql = sprintf('SELECT SQL_CACHE * from CHANNELS %s', $where); - my $erg = $obj->{dbh}->selectall_hashref($sql, $field); + my $erg = $self->{dbh}->selectall_hashref($sql, $field); return $erg; } -# ------------------ +################################################################################ +# Try to find channel name by given channel id +# optionally selected by id of video disk recorder sub ChannelToName { -# ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return undef; - - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE Name from CHANNELS where Id = ?'); - $sth->execute($id) - or return error sprintf("Couldn't execute query: %s.",$sth->errstr); - my $erg = $sth->fetchrow_hashref(); - return $erg ? $erg->{Name} : undef; + my $vid = shift; + + if($vid) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE name from CHANNELS where vid = ? AND id = ?'); + $sth->execute($vid, $id) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{name} : undef; + } else { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE name from CHANNELS where id = ?'); + $sth->execute($id) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{name} : undef; + } } -# ------------------ +################################################################################ +# Try to find channel position by given channel id sub ChannelToPos { -# ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return undef; - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE POS from CHANNELS where Id = ?'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE pos from CHANNELS where id = ?'); $sth->execute($id) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchrow_hashref(); - return $erg ? $erg->{POS} : undef; + return $erg ? $erg->{pos} : undef; } -# ------------------ +################################################################################ +# Try to find channel id by given position, name or channel id +# optionally selected by id of video disk recorder sub ToCID { -# ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $text = shift || return undef; + my $vid = shift; - if($text =~ /^\d+$/ and (my $pch = $obj->PosToChannel($text) )) { + if($text =~ /^\d+$/ and (my $pch = $self->PosToChannel($text,$vid) )) { return $pch; - } elsif((my $nch = $obj->NameToChannel($text) )) { + } elsif((my $nch = $self->NameToChannel($text,$vid) )) { return $nch; - } elsif(my $name = $obj->ChannelToName($text)) { + } elsif(my $name = $self->ChannelToName($text,$vid)) { return $text; } return undef; } + +################################################################################ +# Try to find channel hash by given channel position +# optionally selected by id of video disk recorder +sub PosToHash { + my $self = shift || return error('No object defined!'); + my $pos = shift || return undef; + my $vid = shift; + + if($vid) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE hash as id from CHANNELS where vid = ? AND pos = ?'); + $sth->execute($vid,$pos) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{hash} : undef; + } else { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE hash from CHANNELS where pos = ? ORDER BY vid'); + $sth->execute($pos) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{hash} : undef; + } +} + + +################################################################################ +# Try to find channel hash by given channel id +# optionally selected by id of video disk recorder +sub CIDToHash { + my $self = shift || return error('No object defined!'); + my $cid = shift || return undef; + my $vid = shift; + + if($vid) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE hash from CHANNELS where vid = ? AND id = ?'); + $sth->execute($vid,$cid) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{hash} : undef; + } else { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE hash from CHANNELS where id = ? ORDER BY vid'); + $sth->execute($cid) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{hash} : undef; + } +} + +################################################################################ +# Try to find channel hash by given channel name +# optionally selected by id of video disk recorder +sub NameToHash { + my $self = shift || return error('No object defined!'); + my $cid = shift || return undef; + my $vid = shift; + + if($vid) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE hash from CHANNELS where vid = ? AND UPPER(name) = UPPER( ? )'); + $sth->execute($vid,$cid) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{hash} : undef; + } else { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE hash from CHANNELS where UPPER(name) = UPPER( ? ) ORDER BY vid'); + $sth->execute($cid) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $erg = $sth->fetchrow_hashref(); + return $erg ? $erg->{hash} : undef; + } +} + +################################################################################ +# Try to find channel hash by given position, name or channel id +# optionally selected by id of video disk recorder +sub ToHash { + my $self = shift || return error('No object defined!'); + my $query = shift || return undef; + my $vid = shift; + + if($query and $query =~ /^[0-9a-f]{32}$/i) { + return ($query); + } + if($query =~ /^\d+$/ and (my $pch = $self->PosToHash($query,$vid) )) { + return $pch; + } + if(index($query, '-') != -1) { + my $hash = $self->CIDToHash($query,$vid); + return $hash if($hash); + } + return $self->NameToHash($query,$vid); +} + # ------------------ sub getChannelType { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return undef; - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE VPID,APID from CHANNELS where Id = ?'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE VPID,APID from CHANNELS where id = ?'); $sth->execute($id) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchrow_hashref(); @@ -832,13 +1024,13 @@ sub getChannelType { # ------------------ sub newChannel { # ------------------ - my $self = shift || return error('No object defined!'); - my $watcher = shift || return error('No watcher defined!'); - my $console = shift || return error('No console defined!'); - my $id = shift || 0; - my $defaultData = shift || 0; + my $self = shift || return error('No object defined!'); + my $watcher = shift || return error('No watcher defined!'); + my $console = shift || return error('No console defined!'); + my $id = shift || 0; + my $default = shift || 0; - $self->editChannel($watcher, $console, 0, $defaultData); + $self->editChannel($watcher, $console, 0, $default); } # ------------------ @@ -850,31 +1042,43 @@ sub editChannel { my $cid = shift || 0; # If channelid then edit channel my $data = shift || 0; # Data for defaults - my $defaultData; + my $default; if($cid and not ref $data) { - $cid = $self->PosToChannel($cid) - unless(index($cid, '-') > -1); + my $hash = $self->ToHash($cid); + if($hash) { + $cid = $hash; + } else { + return con_err($console, sprintf(gettext("Channel '%s' does not exist in the database!"),$cid)); + } - my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE POS, Name, Frequency, Parameters, Source, Srate, VPID, APID, TPID, CA, SID, NID, TID, RID from CHANNELS where Id = ?'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE pos, vid, name, frequency, parameters, source, symbols, VPID, APID, TPID, CA, SID, NID, TID, RID from CHANNELS where hash = ?'); $sth->execute($cid) or return con_err($console, sprintf(gettext("Channel '%s' does not exist in the database!"),$cid)); - $defaultData = $sth->fetchrow_hashref(); + $default = $sth->fetchrow_hashref(); } elsif (ref $data eq 'HASH') { - $defaultData = $data; + $default = $data; } + my $vlist = $self->{svdrp}->enum_onlinehosts(); my $questions = [ - 'POS' => { + 'pos' => { typ => 'hidden', - def => $defaultData->{POS} || 0, - } ]; + def => $default->{pos} || 0, + }, + 'vid' => { + typ => scalar @$vlist > 1 ? 'list' : 'hidden', + def => $default->{vid} || $self->{svdrp}->primary_hosts(), + choices => $vlist, + msg => gettext('Which video disk recorder should used'), + } + ]; my $newpos = [ 'NEWPOS' => { typ => 'integer', msg => gettext('Position'), - def => int($defaultData->{POS}), + def => int($default->{pos}), check => sub{ my $value = shift; if(int($value) > 0) { @@ -889,9 +1093,9 @@ sub editChannel { if($cid); my $more = [ - 'Name' => { + 'name' => { typ => 'string', - def => $defaultData->{Name} || gettext('New channel'), + def => $default->{name} || gettext('New channel'), msg => gettext("Name"), check => sub{ my $value = shift || return; @@ -902,10 +1106,10 @@ sub editChannel { } }, }, - 'Frequency' => { + 'frequency' => { typ => 'integer', msg => gettext('Transponder frequency'), - def => int($defaultData->{Frequency}) || 0, + def => int($default->{frequency}) || 0, check => sub{ my $value = shift; if(int($value) > 0) { @@ -915,9 +1119,9 @@ sub editChannel { } }, }, - 'Source' => { + 'source' => { typ => 'string', - def => $defaultData->{Source} || "", + def => $default->{source} || "", msg => gettext("Signal source"), check => sub{ my $value = shift || return; @@ -928,9 +1132,9 @@ sub editChannel { } }, }, - 'Parameters' => { + 'parameters' => { typ => 'string', - def => $defaultData->{Parameters} || "", + def => $default->{parameters} || "", msg => gettext("Various parameters, depending on signal source"), check => sub{ my $value = shift || return; @@ -941,10 +1145,10 @@ sub editChannel { } }, }, - 'Srate' => { + 'symbols' => { typ => 'integer', msg => gettext('Symbol rate'), - def => int($defaultData->{Srate}) || 27500, + def => int($default->{symbols}) || 27500, check => sub{ my $value = shift; if(int($value) > 0) { @@ -957,7 +1161,7 @@ sub editChannel { 'VPID' => { typ => 'integer', msg => gettext('Video PID (VPID)'), - def => int($defaultData->{VPID}) || 0, + def => int($default->{VPID}) || 0, check => sub{ my $value = shift; if(int($value) >= 0) { @@ -969,7 +1173,7 @@ sub editChannel { }, 'APID' => { typ => 'string', - def => $defaultData->{APID} || 0, + def => $default->{APID} || 0, msg => gettext("Audio PID (APID)"), check => sub{ my $value = shift || return; @@ -983,7 +1187,7 @@ sub editChannel { 'TPID' => { typ => 'integer', msg => gettext('Teletext PID (TPID)'), - def => int($defaultData->{TPID}) || 0, + def => int($default->{TPID}) || 0, check => sub{ my $value = shift; if(int($value) >= 0) { @@ -995,7 +1199,7 @@ sub editChannel { }, 'CA' => { typ => 'string', - def => $defaultData->{CA} || 0, + def => $default->{CA} || 0, msg => gettext("Conditional access (CA)"), check => sub{ my $value = shift || return; @@ -1009,7 +1213,7 @@ sub editChannel { 'SID' => { typ => 'integer', msg => gettext('Service ID (SID)'), - def => int($defaultData->{SID}) || 0, + def => int($default->{SID}) || 0, check => sub{ my $value = shift; if(int($value) >= 0) { @@ -1022,7 +1226,7 @@ sub editChannel { 'NID' => { typ => 'integer', msg => gettext('Network ID (NID)'), - def => int($defaultData->{NID}) || 0, + def => int($default->{NID}) || 0, check => sub{ my $value = shift; if(int($value) >= 0) { @@ -1035,7 +1239,7 @@ sub editChannel { 'TID' => { typ => 'integer', msg => gettext('Transport stream ID (TID)'), - def => int($defaultData->{TID}) || 0, + def => int($default->{TID}) || 0, check => sub{ my $value = shift; if(int($value) >= 0) { @@ -1048,7 +1252,7 @@ sub editChannel { 'RID' => { typ => 'integer', msg => gettext('Radio ID (RID)'), - def => int($defaultData->{RID}) || 0, + def => int($default->{RID}) || 0, check => sub{ my $value = shift; if(int($value) >= 0) { @@ -1066,7 +1270,7 @@ sub editChannel { : gettext('New channel')), $questions, $data); if(ref $datasave eq 'HASH') { - my $erg = $self->saveChannel($datasave, $datasave->{POS}); + my $erg = $self->saveChannel($datasave, $datasave->{pos}); my $error; foreach my $zeile (@$erg) { @@ -1077,7 +1281,7 @@ sub editChannel { unless($error) { debug sprintf('%s channel with name "%s" is saved%s', ($cid ? 'Changed' : 'New'), - $data->{Name}, + $data->{name}, ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); $console->message($erg); @@ -1090,7 +1294,7 @@ sub editChannel { con_err($console, $erg); } sleep(1); - $self->readData($watcher,$console); + $self->_readData($watcher,$console); $console->redirect({url => '?cmd=clist', wait => 1}) if($console->typ eq 'HTML'); @@ -1121,11 +1325,11 @@ sub saveChannel { $erg = $self->{svdrp}->command( sprintf("%s %s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s", $pos ? "modc $pos" : "newc", - $data->{Name}, - int($data->{Frequency}), - $data->{Parameters}, - $data->{Source}, - int($data->{Srate}), + $data->{name}, + int($data->{frequency}), + $data->{parameters}, + $data->{source}, + int($data->{symbols}), int($data->{VPID}), $data->{APID}, int($data->{TPID}), @@ -1148,38 +1352,63 @@ sub deleteChannel { my $channelid = shift || return con_err($console, gettext("No channel defined for deletion! Please use cdelete 'pos'!")); my $answer = shift || 0; - my @channels = reverse sort{ $a <=> $b } split(/[^0-9]/, $channelid); + my @ch = split(/[^0-9a-f]/, $channelid); + map { + my $hash = $self->ToHash($_); + $_ = $hash if($hash); + } @ch; - my $sql = sprintf('SELECT SQL_CACHE Id,POS,Name from CHANNELS where POS in (%s)', join(',' => ('?') x @channels)); + my $sql = sprintf('SELECT SQL_CACHE vid,pos,name,hash from CHANNELS where hash in (%s) ORDER BY pos desc', join(',' => ('?') x @ch)); my $sth = $self->{dbh}->prepare($sql); - $sth->execute(@channels) + $sth->execute(@ch) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); - my $data = $sth->fetchall_hashref('POS'); - - foreach my $pos (@channels) { - unless(exists $data->{$pos}) { - con_err($console, sprintf(gettext("Channel '%s' does not exist in the database!"), $pos)); - next; - } - - if(ref $console and $console->{TYP} ne 'HTML') { - $console->table($data->{$pos}); + my $data = $sth->fetchall_arrayref(); + + foreach my $d (@$data) { + my $c = { + vid => $d->[0], + pos => $d->[1], + name => $d->[2], + hash => $d->[3] + }; + + if(ref $console and $console->{TYP} eq 'CONSOLE') { + $console->table({ + gettext('Position') => $c->{pos}, + gettext('Name') => $c->{name}, + gettext('Video disk recorder') => $c->{vid}, + }); my $confirm = $console->confirm({ typ => 'confirm', def => 'y', msg => gettext('Would you like to delete this channel?'), }, $answer); - next if(! $answer eq 'y'); + next if(!$answer eq 'y'); } - debug sprintf('Channel with name "%s" is deleted%s', - $data->{$pos}->{Name}, + debug sprintf('Delete channel with name "%s"%s', + $c->{name}, ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - $self->{svdrp}->queue_cmds("delc $pos"); # Sammeln der Kommandos + $self->{svdrp}->queue_cmds(sprintf("delc %d", $c->{pos}), $c->{vid}); + + # remove channel from request, if found inside database + my $i = 0; + for my $x (@ch) { + if ( $x eq $c->{hash} ) { # Remove known MD5 from user request + splice @ch, $i, 1; + } else { + $i++; + } + } } + con_err($console, + sprintf(gettext("Channel '%s' does not exist in the database!"), + join('\',\'',@ch))) + if(scalar @ch); + if($self->{svdrp}->queue_cmds('COUNT')) { my $erg = $self->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos $console->msg($erg, $self->{svdrp}->err) @@ -1187,12 +1416,12 @@ sub deleteChannel { sleep(1); - $self->readData($watcher,$console); - - $console->redirect({url => '?cmd=clist', wait => 1}) - if(ref $console and $console->typ eq 'HTML' and !$self->{svdrp}->err); + if($self->_readData($watcher,$console)) { + $console->redirect({url => '?cmd=clist', wait => 1}) + if(ref $console and $console->typ eq 'HTML'); + } } else { - con_err($console, gettext("No channel defined for deletion!")); + $console->err(gettext("Found no channel to delete!")); } return 1; @@ -1201,7 +1430,7 @@ sub deleteChannel { # ------------------ sub _brandNewChannels { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $attr = shift || return; my @lines; @@ -1211,8 +1440,8 @@ sub _brandNewChannels { ($c->{VPID} ? gettext('TV') : gettext('Radio')), - $c->{Name}, - $c->{POS}, + $c->{name}, + $c->{pos}, (($c->{CA} && (!is_numeric($c->{CA}) || $c->{CA} > 16)) ? gettext('(encrypted)') : ''), )); last if(25 < scalar @lines ); @@ -1229,5 +1458,35 @@ sub _brandNewChannels { return 1; } +# ------------------ +sub buildSourceList { +# ------------------ + my $self = shift || return error('No object defined!'); + my $vid = shift || return undef; + + my @DVBCardsTyp; + + my $sql = qq| +select + Source from CHANNELS +where + vid = ? +group by + Source +ORDER BY + Source asc +|; + my $sth = $self->{dbh}->prepare($sql); + $sth->execute($vid) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + + my $result = $sth->fetchall_arrayref(); + foreach my $source (@$result ) { + push(@DVBCardsTyp,$source->[0]); + } + my $cards = join(',',@DVBCardsTyp); + lg sprintf("Founded sources of channels %s", $cards); + return $cards; +} 1; diff --git a/lib/XXV/MODULES/CONFIG.pm b/lib/XXV/MODULES/CONFIG.pm index 8ff319e..ff9de48 100644 --- a/lib/XXV/MODULES/CONFIG.pm +++ b/lib/XXV/MODULES/CONFIG.pm @@ -56,9 +56,19 @@ sub module { short => 'rel', callback => sub{ my ($w, $c, $l) = @_; - $Module::Reload::Debug = 2; - Module::Reload->check; - $c->message(gettext("Modules loaded.")); + $Module::Reload::Debug = CORE::int(($Tools::VERBOSE+.5)/2); +# my %Status = %Module::Reload->Stat; + my $cnt = Module::Reload->check(); +# my $files; +# foreach my $file (keys %Module::Reload::Stat) { +# push(@$files, $file) +# if($Module::Reload::Stat{$file} ne $Status{$file}); +# } + if($cnt) { + $c->message(sprintf(gettext("Reload %d modules."),$cnt)); + } else { + $c->message(gettext("There none module reloaded.")); + } }, Level => 'admin' }, @@ -351,7 +361,7 @@ sub usage { }; if($console->typ eq 'HTML') { $info->{periods} = $mods->{'XXV::MODULES::EPG'}->{periods}; - $info->{CHANNELS} = $mods->{'XXV::MODULES::CHANNELS'}->ChannelArray('Name'); + $info->{CHANNELS} = $mods->{'XXV::MODULES::CHANNELS'}->ChannelWithGroup('c.name,c.hash'); $info->{CONFIGS} = [ sort @realModName ]; } $console->table( $ret, $info ); diff --git a/lib/XXV/MODULES/EPG.pm b/lib/XXV/MODULES/EPG.pm index 7e49470..aeade79 100644 --- a/lib/XXV/MODULES/EPG.pm +++ b/lib/XXV/MODULES/EPG.pm @@ -7,7 +7,7 @@ use Tools; # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'EPG', Prereq => { @@ -19,7 +19,7 @@ sub module { Date => (split(/ /, '$Date$'))[1], Author => 'xpix', LastAuthor => (split(/ /, '$Author$'))[1], - Status => sub{ $obj->status(@_) }, + Status => sub{ $self->status(@_) }, Preferences => { epgimages => { description => gettext('Location of additional EPG images.'), @@ -49,32 +49,32 @@ sub module { search => { description => gettext('Search within EPG data'), short => 's', - callback => sub{ $obj->search(@_) }, + callback => sub{ $self->search(@_) }, }, program => { description => gettext("List program for channel 'channel name'"), short => 'p', - callback => sub{ $obj->program(@_) }, + callback => sub{ $self->program(@_) }, }, display => { description => gettext("Show program 'eventid'"), short => 'd', - callback => sub{ $obj->display(@_) }, + callback => sub{ $self->display(@_) }, }, now => { description => gettext('Display events currently showing.'), short => 'n', - callback => sub{ $obj->runningNow(@_) }, + callback => sub{ $self->runningNow(@_) }, }, next => { description => gettext('Display events showing next.'), short => 'nx', - callback => sub{ $obj->runningNext(@_) }, + callback => sub{ $self->runningNext(@_) }, }, schema => { description => gettext('Display events in a schematic way'), short => 'sch', - callback => sub{ $obj->schema(@_) }, + callback => sub{ $self->schema(@_) }, }, erestart => { description => gettext('Update EPG data.'), @@ -87,29 +87,29 @@ sub module { ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - $obj->startReadEpgData($watcher,$console); + $self->startReadEpgData($watcher,$console); }, Level => 'admin', }, erun => { description => gettext('Display the current program running in the VDR'), short => 'en', - callback => sub{ $obj->NowOnChannel(@_) }, + callback => sub{ $self->NowOnChannel(@_) }, Level => 'user', DenyClass => 'remote', }, conflict => { hidden => 'yes', - callback => sub{ $obj->checkOnTimer(@_) }, + callback => sub{ $self->checkOnTimer(@_) }, }, edescription => { hidden => 'yes', short => 'ed', - callback => sub { $obj->getDescription(@_) }, + callback => sub { $self->getDescription(@_) }, }, esuggest => { hidden => 'yes', - callback => sub{ $obj->suggest(@_) }, + callback => sub{ $self->suggest(@_) }, }, }, }; @@ -119,7 +119,7 @@ sub module { # ------------------ sub status { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $lastReportTime = shift || 0; @@ -128,7 +128,7 @@ sub status { my $newEntrys = 0; { - my $sth = $obj->{dbh}->prepare("SELECT SQL_CACHE count(*) as count from EPG"); + my $sth = $self->{dbh}->prepare("SELECT SQL_CACHE count(*) as count from EPG"); if(!$sth->execute()) { error sprintf("Couldn't execute query: %s.",$sth->errstr); @@ -139,7 +139,7 @@ sub status { } { - my $sth = $obj->{dbh}->prepare("SELECT SQL_CACHE count(*) as count from EPG where UNIX_TIMESTAMP(addtime) > ?"); + my $sth = $self->{dbh}->prepare("SELECT SQL_CACHE count(*) as count from EPG where UNIX_TIMESTAMP(addtime) > ?"); if(!$sth->execute($lastReportTime)) { error sprintf("Couldn't execute query: %s.",$sth->errstr); @@ -200,14 +200,14 @@ sub new { # ------------------ sub _init { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); - unless($obj->{dbh}) { + unless($self->{dbh}) { panic("Session to database is'nt connected"); return 0; } - my $version = 27; # Must be increment if rows of table changed + my $version = 30; # Must be increment if rows of table changed # this tables hasen't handmade user data, # therefore old table could dropped if updated rows @@ -215,53 +215,54 @@ sub _init { foreach my $table (qw/EPG OLDEPG TEMPEPG/) { # remove old table, if updated version - if(!tableUpdated($obj->{dbh},$table,$version,1)) { + if(!tableUpdated($self->{dbh},$table,$version,1)) { return 0; } - $obj->{dbh}->do(qq| + $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS $table ( eventid int unsigned NOT NULL default '0', + vid int unsigned NOT NULL, title text NOT NULL default '', subtitle text default '', description text, - channel_id varchar(100) NOT NULL default '', + channel_id varchar(32) NOT NULL default '', starttime datetime NOT NULL default '0000-00-00 00:00:00', - duration int(11) NOT NULL default '0', + duration int NOT NULL default '0', tableid tinyint(4) default 0, image text default '', - version tinyint(3) default 0, + version tinyint default 0, video varchar(100) default '', audio varchar(255) default '', addtime datetime NOT NULL default '0000-00-00 00:00:00', vpstime datetime default '0000-00-00 00:00:00', - PRIMARY KEY (eventid), + PRIMARY KEY (vid,eventid,channel_id), INDEX (starttime), INDEX (channel_id) ) COMMENT = '$version' |); } - $obj->{before_updated} = []; - $obj->{after_updated} = []; + $self->{before_updated} = []; + $self->{after_updated} = []; # Repair later Data ... main::after(sub{ - $obj->{svdrp} = main::getModule('SVDRP'); - unless($obj->{svdrp}) { + $self->{svdrp} = main::getModule('SVDRP'); + unless($self->{svdrp}) { panic ("Couldn't get modul SVDRP"); return 0; } - $obj->startReadEpgData(); + $self->startReadEpgData(); # Restart watcher every x hours Event->timer( - interval => $obj->{interval}, + interval => $self->{interval}, prio => 6, # -1 very hard ... 6 very low cb => sub{ lg sprintf('The read on epg data is restarted!'); - $obj->startReadEpgData(); + $self->startReadEpgData(); }, ); return 1; @@ -273,7 +274,7 @@ sub _init { # ------------------ sub startReadEpgData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; @@ -283,29 +284,32 @@ sub startReadEpgData { if(ref $console && $console->typ eq 'HTML') { $waiter = $console->wait(gettext("Read EPG data ..."),0,1000,'no'); } - - $obj->_before_updated($watcher,$console,$waiter); + my $updated = 0; + $self->_before_updated($watcher,$console,$waiter); + + $self->moveOldEPGEntrys(); # Read data over SVDRP - my $vdata = $obj->{svdrp}->command('LSTE'); - map { - $_ =~ s/^\d{3}.//; - $_ =~ s/[\r|\n]$//; - } @$vdata; - - - # Adjust waiter max value now. - $waiter->max(scalar @$vdata) - if(ref $console && ref $waiter); - - $obj->moveOldEPGEntrys(); - - # Read file row by row - my $updated = $obj->compareEpgData($vdata,$watcher,$console,$waiter); - - $obj->deleteDoubleEPGEntrys(); + my $hostlist = $self->{svdrp}->list_hosts(); + # read from svdrp + foreach my $vid (@$hostlist) { + my $vdata = $self->{svdrp}->command('LSTE',$vid); + map { + $_ =~ s/^\d{3}.//; + # $_ =~ s/[\r|\n]$//; + } @$vdata; + + + # Adjust waiter max value now. + $waiter->max(scalar @$vdata) + if(ref $console && ref $waiter); + + # Read file row by row + $updated |= $self->compareEpgData($vdata,$vid,$watcher,$console,$waiter); + } + $self->deleteDoubleEPGEntrys(); - $obj->_updated($watcher,$console,$waiter) if($updated); + $self->_updated($watcher,$console,$waiter) if($updated); # last call of waiter $waiter->end() if(ref $waiter); @@ -324,23 +328,23 @@ sub startReadEpgData { # ------------------ sub before_updated { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $cb = shift || return error('No callback defined!'); my $log = shift || 0; - push(@{$obj->{before_updated}}, [$cb, $log]); + push(@{$self->{before_updated}}, [$cb, $log]); } # Ausführen der Registrierten Callbacks vor dem Aktualisieren der EPG Daten # ------------------ sub _before_updated { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $waiter = shift; - foreach my $CB (@{$obj->{before_updated}}) { + foreach my $CB (@{$self->{before_updated}}) { next unless(ref $CB eq 'ARRAY'); lg $CB->[1] if($CB->[1]); @@ -354,23 +358,23 @@ sub _before_updated { # ------------------ sub updated { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $cb = shift || return error('No callback defined!'); my $log = shift || 0; - push(@{$obj->{after_updated}}, [$cb, $log]); + push(@{$self->{after_updated}}, [$cb, $log]); } # Ausführen der Registrierten Callbacks nach dem Aktualisieren der EPG Daten # ------------------ sub _updated { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $waiter = shift; - foreach my $CB (@{$obj->{after_updated}}) { + foreach my $CB (@{$self->{after_updated}}) { next unless(ref $CB eq 'ARRAY'); lg $CB->[1] if($CB->[1]); @@ -383,8 +387,9 @@ sub _updated { # ------------------ sub compareEpgData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $vdata = shift || return error('No data defined!'); + my $vid = shift; my $watcher = shift; my $console = shift; my $waiter = shift; @@ -399,21 +404,23 @@ sub compareEpgData { my $vdrData; my $channel; my $channelname; + my $hostname = $self->{svdrp}->hostname($vid); + while($count < scalar $vdata) { - ($vdrData,$channel,$channelname,$count) = $obj->readEpgData($vdata,$count); + ($vdrData,$channel,$channelname,$count) = $self->readEpgData($vid,$vdata,$count); last if(not $channel); $waiter->next($count,undef, sprintf(gettext("Analyze channel '%s'"), $channelname)) if(ref $waiter); # First - read database - my $sql = qq|SELECT SQL_CACHE eventid, title, subtitle, length(description) as ldescription, duration, UNIX_TIMESTAMP(starttime) as starttime, UNIX_TIMESTAMP(vpstime) as vpstime, video, audio from EPG where channel_id = ? |; - my $sth = $obj->{dbh}->prepare($sql); - $sth->execute($channel) + my $sql = qq|SELECT SQL_CACHE eventid, title, subtitle, length(description) as ldescription, duration, UNIX_TIMESTAMP(starttime) as starttime, UNIX_TIMESTAMP(vpstime) as vpstime, video, audio from EPG where vid = ? and channel_id = ? |; + my $sth = $self->{dbh}->prepare($sql); + $sth->execute($vid, $channel) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $db_data = $sth->fetchall_hashref('eventid'); - lg sprintf("Compare EPG Database with data from vdr : %d / %d for channel '%s' - %s", scalar keys %$db_data,scalar keys %$vdrData, $channelname, $channel); + lg sprintf("Compare EPG Database with data from %s : %d / %d for channel '%s' - %s", $hostname, scalar keys %$db_data,scalar keys %$vdrData, $channelname, $channel); # Compare this Hashes foreach my $eid (keys %{$vdrData}) { my $row = $vdrData->{$eid}; @@ -426,7 +433,7 @@ sub compareEpgData { if((not exists $db_data->{$eid}->{$field}) or (not $db_data->{$eid}->{$field}) or ($db_data->{$eid}->{$field} ne $row->{$field})) { - $obj->replace($eid, $row); + $self->replace($eid, $vid, $row); $updatedData++; last; } @@ -437,7 +444,7 @@ sub compareEpgData { } else { # Not exists in DB .. insert - $obj->replace($eid, $row); + $self->replace($eid, $vid, $row); $changedData++; } } @@ -445,9 +452,9 @@ sub compareEpgData { # Delete unused EpgEntrys in DB if(scalar keys %$db_data > 0) { my @todel = keys(%$db_data); - my $sql = sprintf('DELETE FROM EPG WHERE eventid IN (%s)', join(',' => ('?') x @todel)); - my $sth = $obj->{dbh}->prepare($sql); - if(!$sth->execute(@todel)) { + my $sql = sprintf('DELETE FROM EPG WHERE vid = ? and eventid IN (%s)', join(',' => ('?') x @todel)); + my $sth = $self->{dbh}->prepare($sql); + if(!$sth->execute($vid, @todel)) { error sprintf("Couldn't execute query: %s.",$sth->errstr); } $deleteData += scalar @todel; @@ -461,23 +468,23 @@ sub compareEpgData { # ------------------ sub moveOldEPGEntrys { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); # Copy and delete old EPG Entrys - $obj->{dbh}->do('REPLACE INTO OLDEPG SELECT * FROM EPG WHERE (UNIX_TIMESTAMP(EPG.starttime) + EPG.duration) < UNIX_TIMESTAMP()'); - $obj->{dbh}->do('DELETE FROM EPG WHERE (UNIX_TIMESTAMP(EPG.starttime) + EPG.duration) < UNIX_TIMESTAMP()'); + $self->{dbh}->do('REPLACE INTO OLDEPG SELECT * FROM EPG WHERE (UNIX_TIMESTAMP(EPG.starttime) + EPG.duration) < UNIX_TIMESTAMP()'); + $self->{dbh}->do('DELETE FROM EPG WHERE (UNIX_TIMESTAMP(EPG.starttime) + EPG.duration) < UNIX_TIMESTAMP()'); } # ------------------ sub deleteDoubleEPGEntrys { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); # Delete double EPG Entrys - my $erg = $obj->{dbh}->selectall_arrayref('SELECT SQL_CACHE eventid FROM EPG GROUP BY starttime, channel_id having count(*) > 1'); + my $erg = $self->{dbh}->selectall_arrayref('SELECT SQL_CACHE eventid FROM EPG GROUP BY starttime, vid, channel_id having count(*) > 1'); if(scalar @$erg > 0) { lg sprintf('Repair data found %d wrong events!', scalar @$erg); - my $sth = $obj->{dbh}->prepare('DELETE FROM EPG WHERE eventid = ?'); + my $sth = $self->{dbh}->prepare('DELETE FROM EPG WHERE eventid = ?'); foreach my $row (@$erg) { $sth->execute($row->[0]); } @@ -487,13 +494,15 @@ sub deleteDoubleEPGEntrys { # ------------------ sub replace { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $eventid = shift || return error('No eventid defined!'); + my $vid = shift || return error('No vid defined!'); my $attr = shift || return error('No data defined!'); - my $sth = $obj->{dbh}->prepare('REPLACE INTO EPG(eventid, title, subtitle, description, channel_id, duration, tableid, image, version, video, audio, starttime, vpstime, addtime) VALUES (?,?,?,?,?,?,?,?,?,?,?,FROM_UNIXTIME(?),FROM_UNIXTIME(?),NOW())'); + my $sth = $self->{dbh}->prepare('REPLACE INTO EPG(eventid, vid, title, subtitle, description, channel_id, duration, tableid, image, version, video, audio, starttime, vpstime, addtime) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,FROM_UNIXTIME(?),FROM_UNIXTIME(?),NOW())'); $sth->execute( $eventid, + $vid, $attr->{title}, $attr->{subtitle}, $attr->{description}, @@ -512,7 +521,8 @@ sub replace { # ------------------ sub encodeEpgId { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); + my $vid = shift || return error('No data defined!'); my $epgid = shift || return error('No event defined!'); my $channel = shift || return error('No channel defined!'); @@ -520,7 +530,7 @@ sub encodeEpgId { my @id = split('-', $channel); # Make a fix format 0xCCCCEEEE : C-Channelid (high-word), E-Eventid(low-word) => real-eventid = uniqueid & FFFF - my $eventid = ((($id[-3] + $id[-2] + $id[-1]) & 0x3FFF) << 16) | ($epgid & 0xFFFF); + my $eventid = (($vid & 0xFF) << 24) | ((($id[-3] + $id[-2] + $id[-1]) & 0x3FFF) << 16) | ($epgid & 0xFFFF); return $eventid; } @@ -528,13 +538,14 @@ sub encodeEpgId { # ------------------ sub readEpgData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); + my $vid = shift || return error('No data defined!'); my $vdata = shift || return error('No data defined!'); my $count = shift || 0; my $dataHash = {}; my $cmod = main::getModule ('CHANNELS'); - my $channels = $cmod->ChannelArray ('Id,Name'); + my $channels = $cmod->ChannelArray ('id,name',sprintf(" vid = '%d'", $vid)); my $channel; my $channelname; my $event; @@ -544,17 +555,17 @@ sub readEpgData { # Ok, Datarow complete... if($line eq 'e' and $event->{eventid} and $event->{channel}) { - if(-e sprintf('%s/%d.png', $obj->{epgimages}, $event->{eventid})) { + if(-e sprintf('%s/%d.png', $self->{epgimages}, $event->{eventid})) { my $firstimage = sprintf('%d.png',$event->{eventid}); $event->{image} = $firstimage."\n"; - my $imgpath = sprintf('%s/%d_?.png',$obj->{epgimages},$event->{eventid}); + my $imgpath = sprintf('%s/%d_?.png',$self->{epgimages},$event->{eventid}); foreach my $img (glob($imgpath)) { $event->{image} .= sprintf("%s.png\n", basename($img, '.png')); } } $channel = $event->{channel}; - my $eventid = $obj->encodeEpgId($event->{eventid}, $channel); + my $eventid = $self->encodeEpgId($vid, $event->{eventid}, $channel); $event->{title} = gettext("No title") unless($event->{title}); @@ -625,7 +636,7 @@ sub readEpgData { # ------------------ sub search { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $data = shift; @@ -645,13 +656,14 @@ sub search { my $erg = []; my $rows = 0; + my $cmod = main::getModule('CHANNELS'); if($search) { # Channelsearch if($params->{channel}) { - $search->{query} .= ' AND c.POS = ?'; - push(@{$search->{term}},$params->{channel}); + $search->{query} .= ' AND c.hash = ?'; + push(@{$search->{term}}, $cmod->ToHash($params->{channel})); } # Videoformat search @@ -686,8 +698,8 @@ sub search { e.eventid as \'$f{'id'}\', e.title as \'$f{'title'}\', e.subtitle as __Subtitle, - c.Name as \'$f{'channel'}\', - c.POS as __Pos, + c.name as \'$f{'channel'}\', + c.hash as __position, DATE_FORMAT(e.starttime, '%H:%i') as \'$f{'start'}\', DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(e.starttime) + e.duration), '%H:%i') as \'$f{'stop'}\', UNIX_TIMESTAMP(e.starttime) as \'$f{'day'}\', @@ -714,9 +726,12 @@ sub search { EPG as e, CHANNELS as c where - e.channel_id = c.Id + e.channel_id = c.id + AND e.vid = c.vid AND ( $search->{query} ) AND ((UNIX_TIMESTAMP(e.starttime) + e.duration) > UNIX_TIMESTAMP()) + group by + c.id , e.eventid order by starttime |; @@ -725,7 +740,7 @@ sub search { my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute(@{$search->{term}}) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -743,7 +758,7 @@ sub search { } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); + $sth = $self->{dbh}->prepare($sql); $sth->execute(@{$search->{term}}) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); @@ -764,7 +779,7 @@ sub search { rows => $rows }; if($console->typ eq 'HTML') { - $info->{channels} = main::getModule('CHANNELS')->ChannelWithGroup('Name,POS'); + $info->{channels} = $cmod->ChannelWithGroup('c.name,c.hash'); } $console->table($erg, $info ); } @@ -772,12 +787,12 @@ sub search { # ------------------ sub program { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $channel = shift || $obj->{dbh}->selectrow_arrayref("SELECT SQL_CACHE POS from CHANNELS limit 1")->[0]; + my $cid = shift || $self->{dbh}->selectrow_arrayref("SELECT SQL_CACHE hash from CHANNELS order by vid, pos limit 1")->[0]; - my $mod = main::getModule('CHANNELS'); + my $cmod = main::getModule('CHANNELS'); my $search; if($console->{cgi}->param('filter')) { @@ -785,23 +800,13 @@ sub program { $search->{query} .= ' AND '; } - my $cid; - $search->{query} .= ' e.channel_id = ?'; - if($channel =~ /^\d+$/sig) { - $cid = $mod->PosToChannel($channel) - or return con_err($console, sprintf(gettext("This channel '%s' does not exist in the database!"),$channel)); - } else { - $cid = $mod->NameToChannel($channel) - or return con_err($console, sprintf(gettext("This channel '%s' does not exist in the database!"),$channel)); - } + $search->{query} .= ' c.hash = ?'; + $cid = $cmod->ToHash($cid); push(@{$search->{term}},$cid); - - my %f = ( 'id' => gettext('Service'), 'title' => gettext('Title'), - 'channel' => gettext('Channel'), 'start' => gettext('Start'), 'stop' => gettext('Stop'), 'day' => gettext('Day') @@ -837,7 +842,8 @@ SELECT SQL_CACHE from EPG as e, CHANNELS as c where - e.channel_id = c.Id + e.channel_id = c.id + AND e.vid = c.vid AND ( $search->{query} ) AND ((UNIX_TIMESTAMP(e.starttime) + e.duration) > UNIX_TIMESTAMP()) order by @@ -849,7 +855,7 @@ order by my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute(@{$search->{term}}) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -867,7 +873,7 @@ order by } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); + $sth = $self->{dbh}->prepare($sql); $sth->execute(@{$search->{term}}) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); @@ -888,8 +894,8 @@ order by rows => $rows }; if($console->typ eq 'HTML') { - $info->{channels} = $mod->ChannelWithGroup('Name,POS'); - $info->{current} = $mod->ChannelToPos($cid); + $info->{channels} = $cmod->ChannelWithGroup('c.name,c.hash'); + $info->{current} = $cid; } $console->table($erg, $info ); } @@ -897,7 +903,7 @@ order by # ------------------ sub display { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $eventid = shift; @@ -929,7 +935,7 @@ SELECT SQL_CACHE e.subtitle as \'$f{'Subtitle'}\', UNIX_TIMESTAMP(e.starttime) as \'$f{'Start'}\', UNIX_TIMESTAMP(e.starttime) + e.duration as \'$f{'Stop'}\', - c.Name as \'$f{'Channel'}\', + c.name as \'$f{'Channel'}\', e.description as \'$f{'Description'}\', e.video as __Video, e.audio as __Audio, @@ -955,10 +961,11 @@ SELECT SQL_CACHE from $table as e,CHANNELS as c where - e.channel_id = c.Id + e.channel_id = c.id + AND e.vid = c.vid and eventid = ? |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($eventid) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); $fields = $sth->{'NAME'}; @@ -987,52 +994,70 @@ where # ------------------ sub runningNext { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $data = shift; my $param = shift || {}; - my $cgroups = main::getModule('CHANNELS')->ChannelGroupsArray('Name'); - my $cgrp = $param->{cgrp} || $cgroups->[0][1]; # Erster GroupEintrag # Create temporary table - $obj->{dbh}->do(qq| + $self->{dbh}->do(qq| CREATE TEMPORARY TABLE IF NOT EXISTS NEXTEPG ( channel_id varchar(100) NOT NULL default '', nexttime datetime NOT NULL default '0000-00-00 00:00:00' ) |); # Remove old data - $obj->{dbh}->do('delete from NEXTEPG'); + $self->{dbh}->do('delete from NEXTEPG'); # Get channelid and starttime of next broadcasting my $sqltemp = qq| INSERT INTO NEXTEPG select - c.Id as channel_id, + c.id as channel_id, MIN(e.starttime) as nexttime - FROM EPG as e, CHANNELS as c - WHERE e.channel_id = c.Id + FROM EPG as e, CHANNELS as c, CHANNELGROUPS as g + WHERE e.channel_id = c.id + AND e.vid = c.vid + AND c.grp = g.id + AND c.vid = g.vid AND e.starttime > NOW() |; -if($cgrp ne 'all') { - $sqltemp .= qq| - AND c.GRP = ? -|; } + my $term; + my $grpsql = ''; + my $cmod = main::getModule('CHANNELS'); + my $cgroups = $cmod->ChannelGroupsArray('name'); + my $cgrp = $param->{cgrp} || $cgroups->[0][1]; # First id of groups; + if($cgrp ne 'all') { + my $cgrps; + # Find any groups by same group name + foreach my $g (@$cgroups) { + if($g->[1] == $cgrp) { + $cgrps = $cmod->GroupsByName($g->[0]); + last; + } + } + # build query + if($cgrps) { + $grpsql = sprintf(" AND g.id in (%s) ",join(',' => ('?') x @$cgrps)); + foreach my $c (@$cgrps) { + push(@{$term},$c->[0]); + } + } else { # group id + $grpsql = " AND g.id = ? "; + push(@{$term},$cgrp); + } + } + $sqltemp .= $grpsql; $sqltemp .= qq| -GROUP BY c.Id +GROUP BY c.id +ORDER BY c.vid, c.pos |; - - my $sthtemp = $obj->{dbh}->prepare($sqltemp); - if($cgrp ne 'all') { - $sthtemp->execute($cgrp) - or return con_err($console, sprintf("Couldn't execute query: %s.",$sthtemp->errstr)); - } else { - $sthtemp->execute() - or return con_err($console, sprintf("Couldn't execute query: %s.",$sthtemp->errstr)); - } + my $sthtemp = $self->{dbh}->prepare($sqltemp); + $sthtemp->execute(ref $term eq 'ARRAY' ? @$term : $term) + or return con_err($console, sprintf("Couldn't execute query: %s.",$sthtemp->errstr)); my %f = ( 'Service' => gettext('Service'), @@ -1047,9 +1072,9 @@ SELECT SQL_CACHE e.eventid as \'$f{'Service'}\', e.title as \'$f{'Title'}\', e.subtitle as __Subtitle, - c.Name as \'$f{'Channel'}\', - c.POS as __POS, - g.Name as __Channelgroup, + c.name as \'$f{'Channel'}\', + c.hash as __position, + g.name as __Channelgroup, DATE_FORMAT(e.starttime, "%H:%i") as \'$f{'Start'}\', DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as \'$f{'Stop'}\', e.description as __Description, @@ -1073,19 +1098,18 @@ SELECT SQL_CACHE FROM EPG as e, CHANNELS as c, NEXTEPG as n, CHANNELGROUPS as g WHERE - e.channel_id = c.Id - AND n.channel_id = c.Id - AND c.GRP = g.Id + e.channel_id = c.id + AND n.channel_id = c.id + AND c.grp = g.id + AND c.vid = g.vid AND e.starttime = n.nexttime |; -if($cgrp ne 'all') { - $sql .= qq| - AND c.GRP = ? -|; } + $sql .= $grpsql; $sql .= qq| -ORDER BY c.POS +GROUP BY c.id +ORDER BY c.vid, c.pos |; my $rows; @@ -1093,14 +1117,9 @@ ORDER BY c.POS my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); - if($cgrp ne 'all') { - $rsth->execute($cgrp) - or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); - } else { - $rsth->execute() + my $rsth = $self->{dbh}->prepare($sql); + $rsth->execute(ref $term eq 'ARRAY' ? @$term : $term) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); - } $rows = $rsth->rows; if($rows <= $limit) { $sth = $rsth; @@ -1116,8 +1135,8 @@ ORDER BY c.POS } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); - $sth->execute(($cgrp ne 'all') ? $cgrp : undef) + $sth = $self->{dbh}->prepare($sql); + $sth->execute(ref $term eq 'ARRAY' ? @$term : $term) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); } @@ -1134,7 +1153,7 @@ ORDER BY c.POS $console->table($erg, { - periods => $obj->{periods}, + periods => $self->{periods}, cgroups => $cgroups, channelgroup => $cgrp, rows => $rows @@ -1145,13 +1164,11 @@ ORDER BY c.POS # ------------------ sub runningNow { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $zeit = shift || time; my $param = shift || {}; - my $cgroups = main::getModule('CHANNELS')->ChannelGroupsArray('Name'); - my $cgrp = $param->{cgrp} || $cgroups->[0][1]; # Erster GroupEintrag # i.e.: 635 --> 06:35 $zeit = fmttime($zeit) @@ -1179,9 +1196,9 @@ SELECT SQL_CACHE e.eventid as \'$f{'Service'}\', e.title as \'$f{'Title'}\', e.subtitle as __Subtitle, - c.Name as \'$f{'Channel'}\', - c.POS as __POS, - g.Name as __Channelgroup, + c.name as \'$f{'Channel'}\', + c.hash as __position, + g.name as __Channelgroup, DATE_FORMAT(e.starttime, "%H:%i") as \'$f{'Start'}\', DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as \'$f{'Stop'}\', e.description as __Description, @@ -1205,24 +1222,44 @@ SELECT SQL_CACHE FROM EPG as e, CHANNELS as c, CHANNELGROUPS as g WHERE - e.channel_id = c.Id - AND c.GRP = g.Id + e.channel_id = c.id + AND c.grp = g.id + AND e.vid = c.vid + AND c.vid = g.vid AND ? BETWEEN UNIX_TIMESTAMP(e.starttime) AND (UNIX_TIMESTAMP(e.starttime) + e.duration) |; + my $cmod = main::getModule('CHANNELS'); + my $cgroups = $cmod->ChannelGroupsArray('name'); + my $cgrp = $param->{cgrp} || $cgroups->[0][1]; # First id of groups; + my $term; push(@{$term},$zeit); if($cgrp ne 'all') { - push(@{$term},$cgrp); - - $sql .= qq| - AND c.GRP = ? - |; + my $cgrps; + # Find any groups by same group name + foreach my $g (@$cgroups) { + if($g->[1] == $cgrp) { + $cgrps = $cmod->GroupsByName($g->[0]); + last; + } + } + # build query + if($cgrps) { + $sql .= sprintf(" AND g.id in (%s) ",join(',' => ('?') x @$cgrps)); + foreach my $c (@$cgrps) { + push(@{$term},$c->[0]); + } + } else { # group id + $sql .= " AND g.id = ? "; + push(@{$term},$cgrp); + } } $sql .= qq| -ORDER BY c.POS +GROUP BY c.id +ORDER BY c.vid, c.pos |; my $rows; @@ -1230,7 +1267,7 @@ ORDER BY c.POS my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -1248,7 +1285,7 @@ ORDER BY c.POS } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); + $sth = $self->{dbh}->prepare($sql); $sth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); @@ -1266,7 +1303,7 @@ ORDER BY c.POS $console->table($erg, { zeit => $zeit, - periods => $obj->{periods}, + periods => $self->{periods}, cgroups => $cgroups, channelgroup => $cgrp, rows => $rows @@ -1277,10 +1314,15 @@ ORDER BY c.POS # ------------------ sub NowOnChannel { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; - my $channel = shift || $obj->_actualChannel || return con_err($console, gettext('No channel defined!')); + my $channel = shift; + my $vid = shift || $self->{svdrp}->primary_hosts(); + + $channel = $self->_actualChannel($vid) unless($channel); + return con_err($console, gettext('No channel defined!')) unless($channel); + my $zeit = time; my $sql = @@ -1289,8 +1331,8 @@ SELECT SQL_CACHE e.eventid as Service, e.title as Title, e.subtitle as Subtitle, - c.Name as Channel, - c.POS as POS, + c.name as Channel, + c.pos as POS, e.video as __video, e.audio as __audio, DATE_FORMAT(e.starttime, "%a %d.%m") as StartDay, @@ -1316,16 +1358,18 @@ SELECT SQL_CACHE FROM EPG as e, CHANNELS as c WHERE - e.channel_id = c.Id + e.channel_id = c.id + AND e.vid = c.vid AND ? BETWEEN UNIX_TIMESTAMP(e.starttime) AND (UNIX_TIMESTAMP(e.starttime) + e.duration) - AND c.POS = ? + AND c.vid = ? + AND c.pos = ? ORDER BY starttime LIMIT 1 |; - my $sth = $obj->{dbh}->prepare($sql); - $sth->execute($zeit, $channel) + my $sth = $self->{dbh}->prepare($sql); + $sth->execute($zeit, $vid, $channel) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); my $erg = $sth->fetchrow_hashref(); @@ -1339,9 +1383,10 @@ LIMIT 1 # ------------------ sub _actualChannel { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); + my $vid = shift; - my $erg = $obj->{svdrp}->command('chan'); + my $erg = $self->{svdrp}->command('chan', $vid); my ($chanpos, $channame) = $erg->[1] =~ /^250\s+(\d+)\s+(\S+)/sig; return $chanpos; } @@ -1349,12 +1394,13 @@ sub _actualChannel { # ------------------ sub schema { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $zeit = shift || time; my $param = shift || {}; + my $term; # i.e.: 635 --> 06:35 $zeit = fmttime($zeit) @@ -1365,13 +1411,18 @@ sub schema { $zeit = UnixDate(ParseDate($zeit),"%s") || time; } - $zeit += 86400 if($zeit < time - ($obj->{timeframe} * 3600)); + $zeit += 86400 if($zeit < time - ($self->{timeframe} * 3600)); $zeit++; - my $zeitvon = $obj->toFullHour($zeit); - my $zeitbis = $zeitvon + ($obj->{timeframe}*3600); - my $cgroups = main::getModule('CHANNELS')->ChannelGroupsArray('Name'); - my $cgrp = $param->{cgrp} || $cgroups->[0][1]; # Erster GroupEintrag + my $zeitvon = $self->toFullHour($zeit); + my $zeitbis = $zeitvon + ($self->{timeframe}*3600); + + push(@$term, $zeitvon); + push(@$term, $zeitbis); + push(@$term, $zeitvon); + push(@$term, $zeitbis); + push(@$term, $zeitvon); + push(@$term, $zeitbis); my $sql = qq| @@ -1379,8 +1430,8 @@ SELECT SQL_CACHE e.eventid as Service, e.title as Title, e.subtitle as __Subtitle, - c.Name as Channel, - c.POS as __POS, + c.name as Channel, + c.hash as __channelid, DATE_FORMAT(e.starttime, "%H:%i") as Start, DATE_FORMAT(FROM_UNIXTIME(UNIX_TIMESTAMP(starttime) + e.duration), "%H:%i") as Stop, (unix_timestamp(e.starttime) + e.duration - unix_timestamp())/e.duration*100 as Percent, @@ -1389,7 +1440,7 @@ SELECT SQL_CACHE UNIX_TIMESTAMP(starttime) + e.duration as second_stop, e.video as __video, e.audio as __audio, - e.image as __image, + e.image as __image, ( SELECT t.id FROM TIMERS as t @@ -1404,44 +1455,71 @@ SELECT SQL_CACHE NOW() between t.starttime and t.stoptime AND (t.flags & 1) FROM TIMERS as t WHERE t.eventid = e.eventid - LIMIT 1) as __running + LIMIT 1) as __running, + c.vid as __vid, + c.pos as __position FROM - EPG as e, CHANNELS as c + EPG as e, CHANNELS as c, CHANNELGROUPS as g WHERE - e.channel_id = c.Id + e.channel_id = c.id + AND c.grp = g.id AND ( - ( UNIX_TIMESTAMP(e.starttime) >= ? AND UNIX_TIMESTAMP(e.starttime) <= ? ) + ( UNIX_TIMESTAMP(e.starttime) BETWEEN ? AND ? ) OR - ( UNIX_TIMESTAMP(e.starttime) + e.duration >= ? AND UNIX_TIMESTAMP(e.starttime) + e.duration <= ? ) + ( UNIX_TIMESTAMP(e.starttime) + e.duration BETWEEN ? AND ? ) OR - ( UNIX_TIMESTAMP(e.starttime) <= ? AND UNIX_TIMESTAMP(e.starttime) + e.duration >= ? ) - ) - AND - c.GRP = ? -ORDER BY - c.POS,e.starttime + ( ? BETWEEN UNIX_TIMESTAMP(e.starttime) AND (UNIX_TIMESTAMP(e.starttime) + e.duration) ) + OR + ( ? BETWEEN UNIX_TIMESTAMP(e.starttime) AND (UNIX_TIMESTAMP(e.starttime) + e.duration) ) + )|; + + my $cmod = main::getModule('CHANNELS'); + my $cgroups = $cmod->ChannelGroupsArray('name'); + my $cgrp = $param->{cgrp} || $cgroups->[0][1]; # First id of groups; + + if($cgrp ne 'all') { + my $cgrps; + # Find any groups by same group name + foreach my $g (@$cgroups) { + if($g->[1] == $cgrp) { + $cgrps = $cmod->GroupsByName($g->[0]); + last; + } + } + # build query + if($cgrps) { + $sql .= sprintf(" AND g.id in (%s) ",join(',' => ('?') x @$cgrps)); + foreach my $c (@$cgrps) { + push(@{$term},$c->[0]); + } + } else { # group id + $sql .= " AND g.id = ? "; + push(@{$term},$cgrp); + } + } + $sql .= qq| + GROUP BY c.id,e.starttime + ORDER BY c.vid, c.pos,e.starttime |; - my $sth = $obj->{dbh}->prepare($sql); - $sth->execute($zeitvon,$zeitbis,$zeitvon,$zeitbis,$zeitvon,$zeitbis,$cgrp) + my $sth = $self->{dbh}->prepare($sql); + $sth->execute(@$term) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); - my $fields = $sth->{'NAME'}; my $erg = $sth->fetchall_arrayref(); my $data = {}; foreach my $c (@$erg) { - push(@{$data->{$c->[4]}}, $c); + push(@{$data->{($c->[17]*100000) + $c->[18]}}, $c); } $console->table($data, { zeitvon => $zeitvon, zeitbis => $zeitbis, - periods => $obj->{periods}, + periods => $self->{periods}, cgroups => $cgroups, - channelgroup => $cgrp, - HouresProSite => $obj->{timeframe} + channelgroup => $cgrp } ); } @@ -1449,32 +1527,34 @@ ORDER BY # ------------------ sub checkOnTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $eid = shift || return con_err($console, gettext('No event id defined!')); - my $tim = main::getModule('TIMERS'); my $sql = qq| SELECT SQL_CACHE - e.starttime as starttime, + e.starttime, ADDDATE(e.starttime, INTERVAL e.duration SECOND) as stoptime, LEFT(c.Source,1) as source, - c.TID as transponderid + c.TID, + e.vid FROM EPG as e, CHANNELS as c WHERE e.eventid = ? - and - e.channel_id = c.Id + AND e.channel_id = c.id + AND e.vid = c.vid |; - my $sth = $obj->{dbh}->prepare($sql); + my $tmod = main::getModule('TIMERS'); + + my $sth = $self->{dbh}->prepare($sql); $sth->execute($eid) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); my $data = $sth->fetchrow_hashref(); - my $erg = $tim->checkOverlapping($data) || ['ok']; - my $tmod = main::getModule('TIMERS'); + my $erg = $tmod->checkOverlapping($data) || ['ok']; + # Zeige den Title des Timers foreach (@$erg) { $_ = $tmod->getTimerById((split(':', $_))[0])->{file} @@ -1489,12 +1569,12 @@ WHERE # ------------------ sub getDescription { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $eid = shift || 0; - my $event = $obj->getId($eid,"description"); + my $event = $self->getId($eid,"description"); $console->message($event && $event->{description} ? $event->{description} : "") if(ref $console); @@ -1503,7 +1583,7 @@ sub getDescription { # ------------------ sub toFullHour { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $zeit = shift || return error ('No time to convert defined!'); my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = @@ -1516,14 +1596,14 @@ sub toFullHour { # ------------------ sub getId { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return error('No id defined!'); my $fields = shift || '*'; foreach my $table (qw/EPG OLDEPG/) { # EPG my $sql = sprintf('SELECT SQL_CACHE %s from %s WHERE eventid = ?',$fields, $table); - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($id) or return error "Couldn't execute query: $sth->errstr."; @@ -1538,7 +1618,7 @@ sub getId { # ------------------ sub suggest { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $search = shift; @@ -1547,17 +1627,18 @@ sub suggest { if($search) { my $ch = ''; if($params->{channel}) { - $ch = " AND c.POS = ? "; + $ch = " AND c.pos = ? "; } my $sql = qq| - SELECT SQL_CACHE + SELECT SQL_CACHE e.title as title FROM EPG as e, CHANNELS as c WHERE - channel_id = c.Id + channel_id = c.id + AND e.vid = c.vid AND ( e.title LIKE ? ) $ch GROUP BY @@ -1569,7 +1650,8 @@ UNION EPG as e, CHANNELS as c WHERE - channel_id = c.Id + channel_id = c.id + AND e.vid = c.vid AND ( e.subtitle LIKE ? ) $ch GROUP BY @@ -1578,7 +1660,7 @@ ORDER BY title LIMIT 25 |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); if($params->{channel}) { $sth->execute('%'.$search.'%',$params->{channel},'%'.$search.'%',$params->{channel}) or return error "Couldn't execute query: $sth->errstr."; diff --git a/lib/XXV/MODULES/GRAB.pm b/lib/XXV/MODULES/GRAB.pm index e49e106..70684cc 100644 --- a/lib/XXV/MODULES/GRAB.pm +++ b/lib/XXV/MODULES/GRAB.pm @@ -9,7 +9,7 @@ use File::Find; # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'GRAB', Prereq => { @@ -77,7 +77,7 @@ sub module { description => gettext('TrueType font to draw overlay text'), default => 'VeraIt.ttf', type => 'list', - choices => $obj->findttf, + choices => $self->findttf, }, imgfontsize => { description => gettext('Font size to draw image text (only for ttf font!).'), @@ -110,7 +110,7 @@ sub module { gdisplay => { description => gettext('Display current picture of video output.'), short => 'gd', - callback => sub{ $obj->display(@_) }, + callback => sub{ $self->display(@_) }, Level => 'user', DenyClass => 'remote', binary => 'nocache' @@ -170,11 +170,11 @@ sub new { # ------------------ sub _init { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); main::after(sub{ - $obj->{svdrp} = main::getModule('SVDRP'); - unless($obj->{svdrp}) { + $self->{svdrp} = main::getModule('SVDRP'); + unless($self->{svdrp}) { panic ("Couldn't get modul SVDRP"); return 0; } @@ -186,13 +186,14 @@ sub _init { # ------------------ sub _grab { # ------------------ - my $obj = shift || return error('No object defined!'); - my $width = shift || $obj->{xsize}; - my $height = shift || $obj->{ysize}; + my $self = shift || return error('No object defined!'); + my $width = shift || $self->{xsize}; + my $height = shift || $self->{ysize}; + my $vid = shift; # command for get inline data (JPEG BASE64 coded) - my $cmd = sprintf('grab - %d %d %d', $obj->{imgquality}, $width, $height); - my $data = $obj->{svdrp}->command($cmd); + my $cmd = sprintf('grab - %d %d %d', $self->{imgquality}, $width, $height); + my $data = $self->{svdrp}->command($cmd, $vid); my $binary; foreach my $l (@{$data}) { @@ -202,13 +203,13 @@ sub _grab { } } # create noised image as failback. - $binary = $obj->_noise($width,$height) + $binary = $self->_noise($width,$height) unless($binary); if($data && $binary) { # Make overlay on image - $binary = $obj->makeImgText($binary, $obj->{overlay}, $height) - if($obj->{overlay}); + $binary = $self->makeImgText($binary, $self->{overlay}, $height, $vid) + if($self->{overlay}); } return $binary; } @@ -216,13 +217,15 @@ sub _grab { # ------------------ sub display { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); + my $data = shift; + my $params = shift; my $width = $console->{cgi} && $console->{cgi}->param('width') ? $console->{cgi}->param('width') - : $obj->{xsize}; + : $self->{xsize}; unless($width =~ /^\d+$/sig and $width >= 8 and $width < 4096) { error sprintf("Image width incorrect! : %s", $width ); return $console->err(gettext('Value incorrect!')); @@ -230,13 +233,13 @@ sub display { my $height = $console->{cgi} && $console->{cgi}->param('height') ? $console->{cgi}->param('height') - : $obj->{ysize}; + : $self->{ysize}; unless($height =~ /^\d+$/sig and $height >= 8 and $height < 4096) { error sprintf("Image height incorrect! : %s", $height ); return $console->err(gettext('Value incorrect!')); } - my $binary = $obj->_grab($width,$height); + my $binary = $self->_grab($width,$height, $params && $params->{vdr} ? $params->{vdr} : undef); if($binary) { # Datei existiert und hat eine Grösse von mehr als 0 Bytes $console->{nocache} = 1; $console->{nopack} = 1; @@ -251,10 +254,11 @@ sub display { # ------------------ sub makeImgText { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $binary = shift || return error ('No data to create overlay defined!'); my $text = shift || return error ('No text to display defined!'); - my $height = shift || $obj->{ysize}; + my $height = shift || $self->{ysize}; + my $vid = shift; my $image = GD::Image->newFromJpegData($binary); unless($image && $image->width > 8 && $image->height > 8) { @@ -263,7 +267,7 @@ sub makeImgText { my $color = $image->colorClosest(255,255,255); my $shadow = $image->colorClosest(0,0,0); - my $event = main::getModule('EPG')->NowOnChannel(undef,undef); + my $event = main::getModule('EPG')->NowOnChannel(undef,undef,undef,$vid); # Hier sollten noch mehr Informationen dazu kommen my $vars = { @@ -271,16 +275,16 @@ sub makeImgText { }; my $output = ''; - $obj->{tt}->process(\$text, $vars, \$output) - or return error($obj->{tt}->error()); + $self->{tt}->process(\$text, $vars, \$output) + or return error($self->{tt}->error()); - my $vpos = CORE::int(($height / $obj->{ysize}) * $obj->{vpos}); - my $imgfontsize = CORE::int(($height / $obj->{ysize}) * $obj->{imgfontsize}); + my $vpos = CORE::int(($height / $self->{ysize}) * $self->{vpos}); + my $imgfontsize = CORE::int(($height / $self->{ysize}) * $self->{imgfontsize}); lg sprintf("height: %d vpos: %d imgfontsize: %d",$height,$vpos,$imgfontsize); - my $font = sprintf("%s/%s",$obj->{paths}->{FONTPATH},$obj->{font}); - if($obj->{paths}->{FONTPATH} and $obj->{font} and -r $font) { + my $font = sprintf("%s/%s",$self->{paths}->{FONTPATH},$self->{font}); + if($self->{paths}->{FONTPATH} and $self->{font} and -r $font) { my $h = ($imgfontsize + 2); $h *= -1 if($vpos > ($height / 2)); @@ -302,14 +306,14 @@ sub makeImgText { } } - my $img_data = $image->jpeg($obj->{imgquality}); + my $img_data = $image->jpeg($self->{imgquality}); return $img_data; } sub _noise { - my $obj = shift || return error('No object defined!'); - my $width = shift || $obj->{xsize}; - my $height = shift || $obj->{ysize}; + my $self = shift || return error('No object defined!'); + my $width = shift || $self->{xsize}; + my $height = shift || $self->{ysize}; my $image = GD::Image->new($width, $height,1); @@ -318,13 +322,13 @@ sub _noise { push( @{$colors}, $image->colorClosest(128,128,128)); push( @{$colors}, $image->colorClosest(0,0,0)); - $obj->_noise_rect($image,0,0,$width,$height,$colors); - my $img_data = $image->jpeg($obj->{imgquality}); + $self->_noise_rect($image,0,0,$width,$height,$colors); + my $img_data = $image->jpeg($self->{imgquality}); return $img_data; } sub _noise_rect { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $image = shift; my $x1 = shift; my $y1 = shift; my $x2 = shift; my $y2 = shift; @@ -347,7 +351,7 @@ sub _noise_rect { sub findttf # ------------------ { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $found; find({ wanted => sub{ if($File::Find::name =~ /\.ttf$/sig) { @@ -358,9 +362,9 @@ sub findttf follow => 1, follow_skip => 2, }, - $obj->{paths}->{FONTPATH} + $self->{paths}->{FONTPATH} ); - error "Couldn't find useful font at : ", $obj->{paths}->{FONTPATH} + error "Couldn't find useful font at : ", $self->{paths}->{FONTPATH} if(scalar $found == 0); return $found; } diff --git a/lib/XXV/MODULES/KEYWORDS.pm b/lib/XXV/MODULES/KEYWORDS.pm index 830229d..de71d04 100644 --- a/lib/XXV/MODULES/KEYWORDS.pm +++ b/lib/XXV/MODULES/KEYWORDS.pm @@ -111,7 +111,7 @@ sub _init { return 0; } - my $version = 29; # Must be increment if rows of table changed + my $version = 30; # Must be increment if rows of table changed # this tables hasen't handmade user data, # therefore old table could dropped if updated rows if(!tableUpdated($self->{dbh},'KEYWORDS',$version,1)) { @@ -122,13 +122,13 @@ sub _init { $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS KEYWORDS ( id int(11) NOT NULL auto_increment, - md5 varchar(32) NOT NULL, + hash varchar(32) NOT NULL, keyword varchar(128) NOT NULL, rank tinyint NOT NULL, total tinyint NOT NULL, source enum('recording', 'timer'), PRIMARY KEY (id), - UNIQUE KEY (md5,keyword) + UNIQUE KEY (hash,keyword) ) COMMENT = '$version' |); @@ -147,7 +147,7 @@ sub insert { return unless($self->{active} eq 'y'); - my $sth = $self->{dbh}->prepare(qq|REPLACE INTO KEYWORDS(md5, keyword, rank, total, source ) VALUES (?,?,?,?,?)|); + my $sth = $self->{dbh}->prepare(qq|REPLACE INTO KEYWORDS(hash, keyword, rank, total, source ) VALUES (?,?,?,?,?)|); my @words = split(/[,;\r\n]/, $keywords); my $total = scalar @words; my $rank = $total + 1; @@ -169,13 +169,13 @@ sub remove { # ------------------ my $self = shift || return error('No object defined!'); my $type = shift || return error('No type defined!'); - my $md5 = shift || return undef; + my $hash = shift || return undef; return unless($self->{active} eq 'y'); - my $sql = sprintf('DELETE FROM KEYWORDS WHERE md5 IN (%s)', join(',' => ('?') x @$md5)); + my $sql = sprintf('DELETE FROM KEYWORDS WHERE hash IN (%s)', join(',' => ('?') x @$hash)); my $sth = $self->{dbh}->prepare($sql); - $sth->execute(@$md5) + $sth->execute(@$hash) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); return 1; } @@ -227,12 +227,12 @@ sub list { # ------------------ my $self = shift || return error('No object defined!'); my $type = shift || return error('No type defined!'); - my $md5 = shift; + my $hash = shift; return (undef,0,0) unless($self->{active} eq 'y'); # Get keywords with highest ranking - my $list = $self->_list($type,$md5); + my $list = $self->_list($type,$hash); return (undef,0,0) unless($list and scalar @$list); # Remember highest and lowest ranking for scaling my $keywordmax = $list->[0]->[1]; @@ -248,18 +248,18 @@ sub _list { # ------------------ my $self = shift || return error('No object defined!'); my $type = shift || return error('No type defined!'); - my $md5 = shift; + my $hash = shift; my $sth; - if($md5 and ref $md5 eq 'ARRAY') { + if($hash and ref $hash eq 'ARRAY') { my $sql = sprintf(qq|SELECT SQL_CACHE keyword,sum(100/total*rank) as pos FROM KEYWORDS - WHERE source = ? AND md5 IN (%s) + WHERE source = ? AND hash IN (%s) GROUP BY keyword ORDER BY pos desc - LIMIT 20|, join(',' => ('?') x @$md5)); - unshift(@$md5,$type); + LIMIT 20|, join(',' => ('?') x @$hash)); + unshift(@$hash,$type); $sth = $self->{dbh}->prepare($sql); - $sth->execute(@$md5) + $sth->execute(@$hash) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); } else { my $sql = qq|SELECT SQL_CACHE keyword,sum(100/total*rank) as pos @@ -293,7 +293,7 @@ sub timer_keywords { my $term; my $search; my $query = buildsearch("k.keyword",$text); - $search = sprintf('AND ( %s ) AND ( t.id = k.md5 )', $query->{query}); + $search = sprintf('AND ( %s ) AND ( t.id = k.hash )', $query->{query}); foreach(@{$query->{term}}) { push(@{$term},$_); } return $tmod->_list($watcher,$console,$search,$term,$params,', KEYWORDS as k'); @@ -314,7 +314,7 @@ sub recording_keywords { } my $query = buildsearch("k.keyword",$text); - return $rmod->_search($watcher,$console,$query->{query}.' ) AND ( r.RecordMD5 = k.md5 ',$query->{term},$params,', KEYWORDS as k'); + return $rmod->_search($watcher,$console,$query->{query}.' ) AND ( r.RecordMD5 = k.hash ',$query->{term},$params,', KEYWORDS as k'); } # ------------------ diff --git a/lib/XXV/MODULES/MOVETIMER.pm b/lib/XXV/MODULES/MOVETIMER.pm index 6b92d30..fed2f89 100644 --- a/lib/XXV/MODULES/MOVETIMER.pm +++ b/lib/XXV/MODULES/MOVETIMER.pm @@ -131,12 +131,14 @@ sub _init { $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS MOVETIMER ( id int unsigned auto_increment NOT NULL, + sourcevid int unsigned NOT NULL default '1', source varchar(64) NOT NULL, + destinationvid int unsigned NOT NULL default '1', destination varchar(64) NOT NULL, move enum('y', 'n', 'collision') default 'collision', original enum('move', 'keep', 'copy') default 'move', PRIMARY KEY (id), - UNIQUE KEY (source) + UNIQUE KEY (sourcevid, source) ) COMMENT = '$version' |); @@ -192,8 +194,9 @@ sub _movetimer { q| select t.id as id, + t.vid as vid, t.pos as pos, - IF(t.flags & 1,'y','n') as activ, + IF(t.flags & 1,'y','n') as active, IF(t.flags & 4,'y','n') as vps, t.flags as flags, t.channel as channel, @@ -209,6 +212,7 @@ q| from TIMERS as t,MOVETIMER as m where m.source = t.channel + and m.sourcevid = t.vid and m.move != 'm' and t.flags & 1 |); @@ -227,7 +231,7 @@ q| } my $rules = $sth->fetchall_hashref('id'); return unless($rules); - + my $todel; my $bChange = 0; foreach my $tid (keys %$timer) { @@ -264,27 +268,35 @@ q| if($rule->{original} eq 'keep' ) { # Keep original timer but disable him - $data->{activ} = 'n'; + $data->{active} = 'n'; $self->modifyTimer($data); # Create new timer - $data->{activ} = 'y'; + $data->{active} = 'y'; $data->{channel} = $rule->{destination}; + $data->{vid} = $rule->{destinationvid}; $data->{pos} = 0; $self->modifyTimer($data); } elsif($rule->{original} eq 'copy' ) { # Copy to new timer - $data->{activ} = 'y'; + $data->{active} = 'y'; $data->{channel} = $rule->{destination}; + $data->{vid} = $rule->{destinationvid}; $data->{pos} = 0; $self->modifyTimer($data); } else { + # delete original timer + if($data->{vid} != $rule->{destinationvid}) { + push(@$todel,[$data->{vid},$data->{pos},$data->{running}]); + $data->{pos} = 0; + } # Edit timer direct $data->{channel} = $rule->{destination}; + $data->{vid} = $rule->{destinationvid}; $self->modifyTimer($data); } @@ -293,6 +305,14 @@ q| } } } + if($todel) { + foreach my $d (reverse sort{ $a->[1] <=> $b->[1] } @$todel) { + $self->{svdrp}->queue_cmds(sprintf("modt %d off", $d->[1]), $d->[0]) + if($d->[2]); + $self->{svdrp}->queue_cmds(sprintf("delt %d", $d->[1]), $d->[0]); + } + } + if($self->{svdrp}->queue_cmds('COUNT')) { my $erg = $self->{svdrp}->queue_cmds("CALL"); # deqeue commands $console->msg($erg, $self->{svdrp}->err) @@ -313,7 +333,7 @@ sub modifyTimer { my $self = shift || return error('No object defined!'); my $data = shift || return error('No data defined!'); - my $flags = ($data->{activ} eq 'y' ? 1 : 0); + my $flags = ($data->{active} eq 'y' ? 1 : 0); $flags |= ($data->{vps} eq 'y' ? 4 : 0); $data->{file} =~ s/:/|/g; @@ -332,6 +352,7 @@ sub modifyTimer { $data->{file}, ($data->{aux} || '') ) + ,$data->{vid} ); } @@ -376,53 +397,57 @@ sub movetimeredit { } my $con = $console->typ eq "CONSOLE"; + my $vlist = $self->{svdrp}->enum_onlinehosts(); + my $questions = [ 'id' => { typ => 'hidden', def => $rule->{id} || 0, }, + 'sourcevid' => { + typ => scalar @$vlist > 1 ? 'list' : 'hidden', + def => $rule->{sourcevid} || $self->{svdrp}->primary_hosts(), + choices => $vlist, + msg => gettext('Which video disk recorder should as source?'), + }, 'source' => { typ => 'list', def => $con ? $modC->ChannelToPos($rule->{source}) : $rule->{source}, - choices => $con ? $modC->ChannelArray('Name') : $modC->ChannelWithGroup('Name,Id'), + choices => $con ? $modC->ChannelArray('Name') : $modC->ChannelWithGroup('c.name,c.id'), msg => gettext('Which channel should used as source?'), req => gettext("This is required!"), check => sub{ - my $value = shift || return; - - if(my $name = $modC->ChannelToName($value)) { - $data->{source} = $value; - return $value; - } elsif(my $ch = $modC->PosToChannel($value) || $modC->NameToChannel($value) ) { - $data->{source} = $value; - return $ch; - } elsif( ! $modC->NameToChannel($value)) { - return undef, sprintf(gettext("This channel '%s' does not exist!"),$value); - } else { - return undef, gettext("This is required!"); - } + my $value = shift; + return undef, gettext("This is required!") + unless($value); + + my $ch = $modC->ToCID($value,$rule->{sourcevid}); + return undef, sprintf(gettext("Channel '%s' does not exist on video disk recorder %s!"),$value, $self->{svdrp}->hostname($rule->{sourcevid})) + unless($ch); + return $ch; }, }, + 'destinationvid' => { + typ => scalar @$vlist > 1 ? 'list' : 'hidden', + def => $rule->{destinationvid} || $self->{svdrp}->primary_hosts(), + choices => $vlist, + msg => gettext('Which video disk recorder should as destination?'), + }, 'destination' => { typ => 'list', def => $con ? $modC->ChannelToPos($rule->{destination}) : $rule->{destination}, - choices => $con ? $modC->ChannelArray('Name') : $modC->ChannelWithGroup('Name,Id'), + choices => $con ? $modC->ChannelArray('Name') : $modC->ChannelWithGroup('c.name,c.id'), msg => gettext('Which channel should used as destination?'), req => gettext("This is required!"), check => sub{ - my $value = shift || return; - - if(my $name = $modC->ChannelToName($value)) { - $data->{destination} = $value; - return $value; - } elsif(my $ch = $modC->PosToChannel($value) || $modC->NameToChannel($value) ) { - $data->{destination} = $value; - return $ch; - } elsif( ! $modC->NameToChannel($value)) { - return undef, sprintf(gettext("This channel '%s' does not exist!"),$value); - } else { - return undef, gettext("This is required!"); - } + my $value = shift; + return undef, gettext("This is required!") + unless($value); + + my $ch = $modC->ToCID($value,$rule->{destinationvid}); + return undef, sprintf(gettext("Channel '%s' does not exist on video disk recorder %s!"),$value, $self->{svdrp}->hostname($rule->{destinationvid})) + unless($ch); + return $ch; }, }, 'move' => { @@ -498,7 +523,7 @@ sub _insert { return 0; } } else { - $sth = $self->{dbh}->prepare('REPLACE INTO MOVETIMER VALUES (?,?,?,?,?)'); + $sth = $self->{dbh}->prepare('REPLACE INTO MOVETIMER VALUES (?,?,?,?,?,?,?)'); if(!$sth->execute(@$data)) { error sprintf("Couldn't execute query: %s.",$sth->errstr); $console->err(sprintf(gettext("Couldn't insert rule move timer in database!"))); @@ -561,11 +586,11 @@ sub movetimerlist { id as \'$f{'id'}\', (SELECT Name FROM CHANNELS as c - WHERE m.source = c.Id + WHERE m.source = c.id LIMIT 1) as \'$f{'source'}\', (SELECT Name FROM CHANNELS as c - WHERE m.destination = c.Id + WHERE m.destination = c.id LIMIT 1) as \'$f{'destination'}\', move as \'$f{'move'}\', original as \'$f{'original'}\' @@ -622,7 +647,7 @@ sub _original_timer_rules { return [ [ 'move', gettext('Move timer') ], - [ 'keep', gettext('Keep inactiv original timer') ], + [ 'keep', gettext('Keep inactive original timer') ], [ 'copy', gettext('Copy original timer') ], ]; } diff --git a/lib/XXV/MODULES/RECORDS.pm b/lib/XXV/MODULES/RECORDS.pm index 18a8129..2fee3ad 100644 --- a/lib/XXV/MODULES/RECORDS.pm +++ b/lib/XXV/MODULES/RECORDS.pm @@ -16,7 +16,7 @@ $SIG{CHLD} = 'IGNORE'; # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'RECORDS', @@ -30,7 +30,7 @@ sub module { Date => (split(/ /, '$Date$'))[1], Author => 'xpix', LastAuthor => (split(/ /, '$Author$'))[1], - Status => sub{ $obj->status(@_) }, + Status => sub{ $self->status(@_) }, Preferences => { commandfile => { description => sprintf(gettext("Path of file '%s'"),'reccmds.conf'), @@ -100,79 +100,79 @@ sub module { rdisplay => { description => gettext("Display recording 'rid'"), short => 'rd', - callback => sub{ $obj->display(@_) }, + callback => sub{ $self->display(@_) }, DenyClass => 'rlist', }, rlist => { description => gettext('List of recordings'), short => 'rl', - callback => sub{ $obj->list(@_) }, + callback => sub{ $self->list(@_) }, DenyClass => 'rlist', }, rsearch => { description => gettext("Search recordings 'text'"), short => 'rs', - callback => sub{ $obj->search(@_) }, + callback => sub{ $self->search(@_) }, DenyClass => 'rlist', }, rupdate => { description => gettext('Update recordings'), short => 'ru', - callback => sub{ $obj->refresh(@_) }, + callback => sub{ $self->refresh(@_) }, Level => 'user', DenyClass => 'redit', }, rdelete => { description => gettext("Delete recording 'rid'"), short => 'rr', - callback => sub{ $obj->delete(@_) }, + callback => sub{ $self->delete(@_) }, Level => 'user', DenyClass => 'redit', }, rrecover => { description => gettext("Recover deleted recordings"), short => 'rru', - callback => sub{ $obj->recover(@_) }, + callback => sub{ $self->recover(@_) }, Level => 'user', DenyClass => 'redit', }, redit => { description => gettext("Edit recording 'rid'"), short => 're', - callback => sub{ $obj->redit(@_) }, + callback => sub{ $self->redit(@_) }, Level => 'user', DenyClass => 'redit', }, rconvert => { description => gettext("Convert recording 'rid'"), short => 'rc', - callback => sub{ $obj->conv(@_) }, + callback => sub{ $self->conv(@_) }, Level => 'user', DenyClass => 'redit', }, rplay => { description => gettext("Play recording 'rid' in the VDR."), short => 'rpv', - callback => sub{ $obj->play(@_) }, + callback => sub{ $self->play(@_) }, Level => 'user', DenyClass => 'remote', }, rcut => { description => gettext("Cut recording 'rid' in vdr"), short => 'rcu', - callback => sub{ $obj->cut(@_) }, + callback => sub{ $self->cut(@_) }, Level => 'user', DenyClass => 'remote', }, rsuggest => { hidden => 'yes', - callback => sub{ $obj->suggest(@_) }, + callback => sub{ $self->suggest(@_) }, DenyClass => 'rlist', }, rimage => { hidden => 'yes', short => 'ri', - callback => sub{ $obj->image(@_) }, + callback => sub{ $self->image(@_) }, binary => 'cache' } }, @@ -275,9 +275,9 @@ sub new { # ------------------ sub _init { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); - unless($obj->{dbh}) { + unless($self->{dbh}) { panic("Session to database is'nt connected"); return 0; } @@ -285,12 +285,12 @@ sub _init { my $version = 29; # Must be increment if rows of table changed # this tables hasen't handmade user data, # therefore old table could dropped if updated rows - if(!tableUpdated($obj->{dbh},'RECORDS',$version,1)) { + if(!tableUpdated($self->{dbh},'RECORDS',$version,1)) { return 0; } # Look for table or create this table - $obj->{dbh}->do(qq| + $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS RECORDS ( eventid int unsigned NOT NULL, RecordId int unsigned not NULL, @@ -310,27 +310,27 @@ sub _init { ) COMMENT = '$version' |); - $obj->{JOBS} = []; - $obj->{after_updated} = []; - $obj->{countReading} = 0; - $obj->{inotify} = undef; - $obj->{lastupdate} = 0; + $self->{JOBS} = []; + $self->{after_updated} = []; + $self->{countReading} = 0; + $self->{inotify} = undef; + $self->{lastupdate} = 0; main::after(sub{ - $obj->{svdrp} = main::getModule('SVDRP'); - unless($obj->{svdrp}) { + $self->{svdrp} = main::getModule('SVDRP'); + unless($self->{svdrp}) { return 0; } - $obj->{timers} = main::getModule('TIMERS'); - unless($obj->{timers}) { + $self->{timers} = main::getModule('TIMERS'); + unless($self->{timers}) { return 0; } - $obj->{keywords} = main::getModule('KEYWORDS'); - unless($obj->{keywords}) { + $self->{keywords} = main::getModule('KEYWORDS'); + unless($self->{keywords}) { return 0; } - my $updatefile = sprintf("%s/.update",$obj->{videodir}); + my $updatefile = sprintf("%s/.update",$self->{videodir}); if( -r $updatefile) { my $inotify = new Linux::Inotify2 or panic sprintf("Unable to create new inotify object: %s",$!); @@ -346,28 +346,28 @@ sub _init { $inotify->watch( $updatefile, IN_ALL_EVENTS, - sub { my $e = shift; $obj->_notify_readData($e); } + sub { my $e = shift; $self->_notify_readData($e); } ); - $obj->{inotify} = 'active'; + $self->{inotify} = 'active'; } } # Interval to read recordings and put to DB Event->timer( - interval => $obj->{reading} * 60, + interval => $self->{reading} * 60, prio => 6, # -1 very hard ... 6 very low cb => sub { - my $forceUpdate = ($obj->{countReading} % ( $obj->{fullreading} * 60 / $obj->{reading} ) == 0); - if($forceUpdate || (time - $obj->{lastupdate}) > ($obj->{reading}/2) ) { - $obj->readData(undef,undef,undef,$forceUpdate); - $obj->{lastupdate} = time; + my $forceUpdate = ($self->{countReading} % ( $self->{fullreading} * 60 / $self->{reading} ) == 0); + if($forceUpdate || (time - $self->{lastupdate}) > ($self->{reading}/2) ) { + $self->readData(undef,undef,undef,$forceUpdate); + $self->{lastupdate} = time; } - $obj->{countReading} += 1; + $self->{countReading} += 1; }, ); - $obj->readData(undef,undef,undef,'force'); - $obj->{countReading} += 1; - $obj->{lastupdate} = time; + $self->readData(undef,undef,undef,'force'); + $self->{countReading} += 1; + $self->{lastupdate} = time; return 1; }, "RECORDS: Store recordings in database ...", 20); @@ -379,26 +379,26 @@ sub _init { # trigged by file notifcation from inotify sub _notify_readData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $e = shift; lg sprintf "notify events for %s:%d received: %x", $e->fullname, $e->cookie, $e->mask; - if((time - $obj->{lastupdate}) > 3 # Only if last update prior 3 seconds (avoid callback chill) - && $obj->readData()) { + if((time - $self->{lastupdate}) > 3 # Only if last update prior 3 seconds (avoid callback chill) + && $self->readData()) { - $obj->{lastupdate} = time; + $self->{lastupdate} = time; # Update preview images after five minutes - my $after = ($obj->{timers}->{prevminutes}) * 60 * 2; + my $after = ($self->{timers}->{prevminutes}) * 60 * 2; $after = 300 if($after <= 300); Event->timer( interval => 60, after => $after, cb => sub { - if((time - $obj->{lastupdate}) >= ($after - 30)) { - if($obj->readData()) { - $obj->{lastupdate} = time; + if((time - $self->{lastupdate}) >= ($after - 30)) { + if($self->readData()) { + $self->{lastupdate} = time; } $_[0]->w->cancel; } @@ -418,7 +418,7 @@ sub dot1000 { # ------------------ sub parseData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $vdata = shift || return error('No data defined!'); my ($event, $hash, $id, $date, $hour, $minute, $state, $duration, $title, $day, $month, $year); my $dataHash = {}; @@ -460,7 +460,7 @@ sub parseData { # ------------------ sub scandirectory { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $typ = shift; my $files = (); # Hash with md5 and path to recording @@ -487,9 +487,9 @@ sub scandirectory { # convert path to title my $title = dirname($path); - $title =~ s/^$obj->{videodir}//g; + $title =~ s/^$self->{videodir}//g; $title =~ s/^\///g; - $rec->{title} = $obj->converttitle($title); + $rec->{title} = $self->converttitle($title); # add file push(@{$rec->{files}},$File::Find::name); @@ -508,7 +508,7 @@ sub scandirectory { follow => 1, follow_skip => 2, }, - $obj->{videodir} + $self->{videodir} ); return $files; } @@ -516,7 +516,7 @@ sub scandirectory { # ------------------ sub readData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $waiter = shift; @@ -524,13 +524,13 @@ sub readData { my $forceUpdate = shift; # Read recording over SVDRP - my $lstr = $obj->{svdrp}->command('lstr'); + my $lstr = $self->{svdrp}->command('lstr'); my $vdata = [ grep(/^250/, @$lstr) ]; unless(scalar @$vdata) { # Delete old Records - $obj->{dbh}->do('DELETE FROM RECORDS'); - $obj->{keywords}->removesource('recording'); + $self->{dbh}->do('DELETE FROM RECORDS'); + $self->{keywords}->removesource('recording'); my $msg = gettext('No recordings available!'); con_err($console,$msg); @@ -538,7 +538,7 @@ sub readData { } # Get state from used harddrive (/video) - my $disk = $obj->{svdrp}->command('stat disk'); + my $disk = $self->{svdrp}->command('stat disk'); my ($total, $totalUnit, $free, $freeUnit, $percent); my $totalDuration = 0; my $totalSpace = 0; @@ -548,13 +548,13 @@ sub readData { ($total, $totalUnit, $free, $freeUnit, $percent) = $disk->[1] =~ /^250[\-|\s](\d+)(\S+)\s+(\d+)(\S+)\s+(\S+)/s; - $obj->{CapacityMessage} = sprintf(gettext("Used %s, total %s%s, free %s%s"),$percent, dot1000($total), $totalUnit, dot1000($free), $freeUnit); - $obj->{CapacityPercent} = int($percent); + $self->{CapacityMessage} = sprintf(gettext("Used %s, total %s%s, free %s%s"),$percent, dot1000($total), $totalUnit, dot1000($free), $freeUnit); + $self->{CapacityPercent} = int($percent); } else { error("Couldn't get disc state : ".join("\n", @$disk)); - $obj->{CapacityMessage} = gettext("Unknown disc capacity!"); - $obj->{CapacityPercent} = 0; + $self->{CapacityMessage} = gettext("Unknown disc capacity!"); + $self->{CapacityPercent} = 0; } @@ -564,7 +564,7 @@ sub readData { my $l = 0; my $err = []; - my $vdrData = $obj->parseData($vdata); + my $vdrData = $self->parseData($vdata); # Adjust waiter max value now. $waiter->max(scalar keys %$vdrData) @@ -572,8 +572,8 @@ sub readData { my $db_data; if($forceUpdate) { - $obj->{dbh}->do('DELETE FROM RECORDS'); - $obj->{keywords}->removesource('recording'); + $self->{dbh}->do('DELETE FROM RECORDS'); + $self->{keywords}->removesource('recording'); } else { # read database for compare with vdr data my $sql = qq|SELECT SQL_CACHE r.eventid as eventid, r.RecordId as id, @@ -589,9 +589,10 @@ sub readData { r.RecordMD5 from RECORDS as r,OLDEPG as e where r.eventid = e.eventid |; - $db_data = $obj->{dbh}->selectall_hashref($sql, 'hash'); + $db_data = $self->{dbh}->selectall_hashref($sql, 'hash'); - lg sprintf( 'Compare recording database with data from vdr : %d / %d', + lg sprintf( 'Compare recording database with data from %s : %d / %d', + $self->{svdrp}->hostname(), scalar keys %$db_data,scalar keys %$vdrData ); } @@ -612,7 +613,7 @@ sub readData { foreach my $field (qw/id state/) { if($db_data->{$h}->{$field} != $event->{$field}) { - $obj->_updateState($db_data->{$h}, $event); + $self->_updateState($db_data->{$h}, $event); $updatedState++; last; @@ -621,12 +622,12 @@ sub readData { # Update Duration and maybe preview images, if recordings added during timer run if(($db_data->{$h}->{starttime} + $db_data->{$h}->{duration} + 7200) > $db_data->{$h}->{addtime}) { - my $duration = $obj->_recordinglength($db_data->{$h}->{path}); + my $duration = $self->_recordinglength($db_data->{$h}->{path}); if($duration != $db_data->{$h}->{duration}) { # Update duration at database entry $db_data->{$h}->{duration} = $duration; - $db_data->{$h}->{FileSize} = $obj->_recordingsize($db_data->{$h}->{path}, ($duration * 8 * $obj->{framerate})); + $db_data->{$h}->{FileSize} = $self->_recordingsize($db_data->{$h}->{path}, ($duration * 8 * $self->{framerate})); # set addtime only if called from EVENT::TIMER # avoid generating preview image during user actions @@ -634,14 +635,14 @@ sub readData { unless($console) { $db_data->{$h}->{addtime} = time; # Make preview and remove older Preview images - my $job = $obj->videoPreview( $db_data->{$h}, 1); + my $job = $self->videoPreview( $db_data->{$h}, 1); if($job) { - push(@{$obj->{JOBS}}, $job); - $obj->_updatePreview($job->{RecordMD5}, $db_data->{$h}->{preview}); + push(@{$self->{JOBS}}, $job); + $self->_updatePreview($job->{RecordMD5}, $db_data->{$h}->{preview}); } } - $obj->_updateEvent($db_data->{$h}); - $obj->_updateFileSize($db_data->{$h}); + $self->_updateEvent($db_data->{$h}); + $self->_updateFileSize($db_data->{$h}); $updatedState++; } @@ -662,22 +663,22 @@ sub readData { # Read VideoDir only at first call unless($files) { - $files = $obj->scandirectory('rec'); + $files = $self->scandirectory('rec'); } unless($files && keys %{$files}) { last; } - my $info = $obj->analyze($files,$event); + my $info = $self->analyze($files,$event); if(ref $info eq 'HASH') { $totalDuration += $info->{Duration}; $totalSpace += $info->{FileSize}; - if($obj->insert($info)) { + if($self->insert($info)) { push(@merkMD5,$info->{RecordMD5}); $insertedData++; - $obj->{keywords}->insert('recording',$info->{RecordMD5},$info->{keywords}); + $self->{keywords}->insert('recording',$info->{RecordMD5},$info->{keywords}); } else { push(@{$err},sprintf(gettext("Can't add recording '%s' into database!"),$info->{title})); @@ -700,11 +701,11 @@ sub readData { push(@todel,$db_data->{$t}->{RecordMD5}); } my $sql = sprintf('DELETE FROM RECORDS WHERE RecordMD5 IN (%s)', join(',' => ('?') x @todel)); - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute(@todel) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); - $obj->{keywords}->remove('recording',\@todel); + $self->{keywords}->remove('recording',\@todel); } my $removedData = $db_data ? scalar keys %$db_data : 0; @@ -713,24 +714,24 @@ sub readData { error sprintf("Unsupported unit '%s' to calc free capacity",$freeUnit) unless($freeUnit eq 'MB'); # use store capacity and recordings length to calc free capacity - $obj->{CapacityTotal} = $totalDuration; + $self->{CapacityTotal} = $totalDuration; if($totalSpace > 1) { - $obj->{CapacityFree} = int(($free * $totalDuration) / $totalSpace); + $self->{CapacityFree} = int(($free * $totalDuration) / $totalSpace); } else { - $obj->{CapacityFree} = int($free * 3600 / 2000); # use 2GB at one hour as base + $self->{CapacityFree} = int($free * 3600 / 2000); # use 2GB at one hour as base } - $obj->{CapacityPercent} = ($totalSpace * 100 / ($free + $totalSpace)) - unless($obj->{CapacityPercent}); + $self->{CapacityPercent} = ($totalSpace * 100 / ($free + $totalSpace)) + unless($self->{CapacityPercent}); # Previews im fork erzeugen - if(scalar @{$obj->{JOBS}}) { + if(scalar @{$self->{JOBS}}) { #Changes made after the fork() won't be visible in the parent process - my @jobs = @{$obj->{JOBS}}; - $obj->{JOBS} = []; + my @jobs = @{$self->{JOBS}}; + $self->{JOBS} = []; defined(my $child = fork()) or return con_err($console, sprintf("Couldn't fork : %s",$!)); if($child == 0) { - $obj->{dbh}->{InactiveDestroy} = 1; + $self->{dbh}->{InactiveDestroy} = 1; while(scalar @jobs > 0) { my $job = shift (@jobs); @@ -743,16 +744,16 @@ sub readData { my $frame = basename($_); $frame =~ s/\.jpg$//ig; push(@{$preview},$frame); - last if(scalar @{$preview} >= $obj->{previewcount}); + last if(scalar @{$preview} >= $self->{previewcount}); } - $obj->_updatePreview($job->{RecordMD5},$preview); + $self->_updatePreview($job->{RecordMD5},$preview); } exit 0; } } # alte PreviewDirs loeschen - foreach my $dir (glob(sprintf('%s/*_shot', $obj->{previewimages}))) { + foreach my $dir (glob(sprintf('%s/*_shot', $self->{previewimages}))) { my $basedir = basename($dir); unless(grep(sprintf('%s_shot',$_) eq $basedir, @merkMD5)) { lg sprintf("Remove old preview files : '%s'",$dir); @@ -769,11 +770,11 @@ DELETE FROM OLDEPG and eventid not in ( SELECT eventid FROM RECORDS ) |; - $obj->{dbh}->do($sqldeleteEvents) + $self->{dbh}->do($sqldeleteEvents) or error sprintf("Couldn't execute query: %s, %s.",$sqldeleteEvents, $DBI::errstr); } - $obj->updated() if($insertedData); + $self->updated() if($insertedData); # last call of waiter $waiter->end() if(ref $waiter); @@ -793,14 +794,14 @@ DELETE FROM OLDEPG # ------------------ sub updated { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $cb = shift || 0; my $log = shift || 0; if($cb) { - push(@{$obj->{after_updated}}, [$cb, $log]); + push(@{$self->{after_updated}}, [$cb, $log]); } else { - foreach my $CB (@{$obj->{after_updated}}) { + foreach my $CB (@{$self->{after_updated}}) { next unless(ref $CB eq 'ARRAY'); lg $CB->[1] if($CB->[1]); @@ -813,7 +814,7 @@ sub updated { # ------------------ sub refresh { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; @@ -824,7 +825,7 @@ sub refresh { con_msg($console,gettext("Get information on recordings ...")); } - if($obj->readData($watcher,$console,$waiter,'force')) { + if($self->readData($watcher,$console,$waiter,'force')) { $console->redirect({url => '?cmd=rlist', wait => 1}) if(ref $console and $console->typ eq 'HTML'); @@ -837,10 +838,10 @@ sub refresh { # ------------------ sub insert { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $attr = shift || return 0; - my $sth = $obj->{dbh}->prepare( + my $sth = $self->{dbh}->prepare( qq| REPLACE INTO RECORDS (eventid, RecordId, RecordMD5, Path, Prio, Lifetime, State, FileSize, Marks, Type, preview, aux, addtime ) @@ -869,10 +870,10 @@ sub insert { # ------------------ sub _updateEvent { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $event = shift || return undef; - my $sth = $obj->{dbh}->prepare('UPDATE OLDEPG SET duration=?, starttime=FROM_UNIXTIME(?), addtime=FROM_UNIXTIME(?) where eventid=?'); + my $sth = $self->{dbh}->prepare('UPDATE OLDEPG SET duration=?, starttime=FROM_UNIXTIME(?), addtime=FROM_UNIXTIME(?) where eventid=?'); if(!$sth->execute($event->{duration},$event->{starttime},$event->{addtime},$event->{eventid})) { error sprintf("Couldn't update event!: '%s' !",$event->{eventid}); return undef; @@ -883,56 +884,56 @@ sub _updateEvent { # ------------------ sub _updateState { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $oldattr = shift || return error ('No data defined!'); my $attr = shift || return error ('No data to replace!'); - my $sth = $obj->{dbh}->prepare('UPDATE RECORDS SET RecordId=?, State=?, addtime=NOW() where RecordMD5=?'); + my $sth = $self->{dbh}->prepare('UPDATE RECORDS SET RecordId=?, State=?, addtime=NOW() where RecordMD5=?'); return $sth->execute($attr->{id},$attr->{state},$oldattr->{RecordMD5}); } # ------------------ sub _updatePreview { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $RecordMD5 = shift || return error ('No data defined!'); my $preview = shift || return error ('No data to replace!'); my $images = join(',',@{$preview}); - my $sth = $obj->{dbh}->prepare('UPDATE RECORDS SET preview=?, addtime=NOW() where RecordMD5=?'); + my $sth = $self->{dbh}->prepare('UPDATE RECORDS SET preview=?, addtime=NOW() where RecordMD5=?'); return $sth->execute($images,$RecordMD5); } # ------------------ sub _updateFileSize { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $attr = shift || return error ('No data to replace!'); - my $sth = $obj->{dbh}->prepare('UPDATE RECORDS SET FileSize=?, addtime=NOW() where RecordMD5=?'); + my $sth = $self->{dbh}->prepare('UPDATE RECORDS SET FileSize=?, addtime=NOW() where RecordMD5=?'); return $sth->execute($attr->{FileSize},$attr->{RecordMD5}); } # ------------------ sub analyze { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $files = shift; # Hash with md5 and path to recording my $recattr = shift; lg sprintf('Analyze recording "%s"', $recattr->{title} ); - my $info = $obj->videoInfo($files,$recattr->{title}, $recattr->{starttime}); + my $info = $self->videoInfo($files,$recattr->{title}, $recattr->{starttime}); unless($info && ref $info eq 'HASH') { error sprintf("Couldn't find recording '%s' with id : '%s' !",$recattr->{title}, $recattr->{id}); return 0; } - my $event = $obj->SearchEpgId( $recattr->{starttime}, $info->{duration}, $recattr->{title}, $info->{channel} ); + my $event = $self->SearchEpgId( $recattr->{starttime}, $info->{duration}, $recattr->{title}, $info->{channel} ); if($event) { my $id = $event->{eventid}; $event->{addtime} = time; $event->{duration} = int($info->{duration}); $event->{starttime} = $recattr->{starttime}; - $event = $obj->_updateEvent($event); + $event = $self->_updateEvent($event); unless($event) { return 0; } @@ -948,7 +949,7 @@ sub analyze { $title = join('~',@t); } - $event = $obj->createOldEventId($recattr->{id}, $recattr->{starttime}, $info->{duration}, $title, $subtitle, $info); + $event = $self->createOldEventId($recattr->{id}, $recattr->{starttime}, $info->{duration}, $title, $subtitle, $info); unless($event) { error sprintf("Couldn't create event!: '%s' !",$recattr->{id}); return 0; @@ -956,8 +957,8 @@ sub analyze { } # Make Preview - my $job = $obj->videoPreview( $info ); - push(@{$obj->{JOBS}}, $job) if($job); + my $job = $self->videoPreview( $info ); + push(@{$self->{JOBS}}, $job) if($job); my $ret = { RecordMD5 => $info->{RecordMD5}, @@ -986,7 +987,7 @@ sub analyze { # ------------------ sub videoInfo { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $files = shift; # Hash with md5 and path to recording my $title = shift; # title from VDR my $starttime = shift; # time from VDR @@ -1006,17 +1007,17 @@ sub videoInfo { && $rec->{hour} == $hour && $rec->{minute} == $minute) { - my $info = $obj->readinfo($rec->{path}); + my $info = $self->readinfo($rec->{path}); $info->{RecordMD5} = $md5; $info->{path} = $rec->{path}; $info->{Prio} = $rec->{priority}; $info->{Lifetime} = $rec->{lifetime}; - $info->{duration} = $obj->_recordinglength($rec->{path}); - $info->{FileSize} = $obj->_recordingCapacity($rec->{files}, - ($info->{duration} * 8 * $obj->{framerate})); + $info->{duration} = $self->_recordinglength($rec->{path}); + $info->{FileSize} = $self->_recordingCapacity($rec->{files}, + ($info->{duration} * 8 * $self->{framerate})); - my $marks = $obj->readmarks($rec->{path}); + my $marks = $self->readmarks($rec->{path}); map { $info->{$_} = $marks->{$_}; } keys %{$marks}; delete $files->{$md5}; # remove from hash, avoid double lookup @@ -1031,7 +1032,7 @@ sub videoInfo { #------------------------------------------------------------------------------- # get cut marks from marks.vdr sub readmarks { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $path = shift || return error ('No recording path defined!'); my $status; @@ -1055,7 +1056,7 @@ sub readmarks { #------------------------------------------------------------------------------- # get information about recording from info.vdr sub readinfo { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $path = shift || return error ('No recording path defined!'); my $info; @@ -1100,7 +1101,7 @@ sub readinfo { $info->{aux} =~ s/^\s+//; # no leading white space $info->{aux} =~ s/\s+$//; # no trailing white space - my $xml = $obj->{keywords}->parsexml($info->{aux}); + my $xml = $self->{keywords}->parsexml($info->{aux}); # $info->{keywords} = $xml->{'autotimer'} # if($xml && defined $xml->{'autotimer'} ); $info->{keywords} = $xml->{'keywords'} @@ -1114,7 +1115,7 @@ sub readinfo { #------------------------------------------------------------------------------- # store information about recording into info.vdr sub saveinfo { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $path = shift || return error ('No recording path defined!'); my $info = shift || return error ('No information defined!'); @@ -1236,20 +1237,20 @@ sub qquote { # ------------------ sub videoPreview { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $info = shift || return error ('No information defined!'); my $rebuild = shift || 0; $info->{preview} = []; - if ($obj->{previewcommand} eq 'Nothing') { + if ($self->{previewcommand} eq 'Nothing') { return 0; } if($info->{type} and $info->{type} eq 'RADIO') { return 0; } # Mplayer - unless(-x $obj->{previewbinary}) { + unless(-x $self->{previewbinary}) { error("Couldn't find executable file as usable preview command!"); return 0; } @@ -1261,9 +1262,9 @@ sub videoPreview { return 0; } - my $outdir = sprintf('%s/%s_shot', $obj->{previewimages}, $info->{RecordMD5}); + my $outdir = sprintf('%s/%s_shot', $self->{previewimages}, $info->{RecordMD5}); - my $count = $obj->{previewcount}; + my $count = $self->{previewcount}; # Stop here if enough files present my @images = glob("$outdir/[0-9]*.jpg"); if(scalar @images >= $count && !$rebuild) { @@ -1271,13 +1272,13 @@ sub videoPreview { my $frame = basename($_); $frame =~ s/\.jpg$//ig; push(@{$info->{preview}},$frame); - last if(scalar @{$info->{preview}} >= $obj->{previewcount}); + last if(scalar @{$info->{preview}} >= $self->{previewcount}); } return 0; } - my $startseconds = ($obj->{timers}->{prevminutes} * 60) * 2; - my $endseconds = ($obj->{timers}->{afterminutes} * 60) * 2; + my $startseconds = ($self->{timers}->{prevminutes} * 60) * 2; + my $endseconds = ($self->{timers}->{afterminutes} * 60) * 2; my $stepseconds = ($info->{duration} - ($startseconds + $endseconds)) / $count; # reduced interval on short movies if($stepseconds <= 0 or ($startseconds + ($count * $stepseconds)) > $info->{duration}) { @@ -1307,20 +1308,20 @@ sub videoPreview { my @files; my @frames; - if ($obj->{previewcommand} eq 'vdr2jpeg') { + if ($self->{previewcommand} eq 'vdr2jpeg') { my $m = ref $info->{marks} eq 'ARRAY' ? scalar(@{$info->{marks}}) : 0; if($m > 1 && $info->{duration}) { - my $total = $info->{duration} * $obj->{framerate}; + my $total = $info->{duration} * $self->{framerate}; my $limit = $count * 4; my $x = 2; my $y = 1; while (scalar @frames < $count && $x < $limit) { my $f = int($total / $x * $y); # 1/2, 1/3, 2/3, 1/4, 2/4, 3/4, 1/5, 2/5, 3/5 ... for (my $n = 0;$n < $m; $n += 2 ) { - my $fin = $obj->_mark2frames(@{$info->{marks}}[$n]); + my $fin = $self->_mark2frames(@{$info->{marks}}[$n]); my $fout = $total; - $fout = $obj->_mark2frames(@{$info->{marks}}[$n+1]) if($n+1 < $m); + $fout = $self->_mark2frames(@{$info->{marks}}[$n+1]) if($n+1 < $m); if ($f >= $fin && $f <= $fout && 0 == (grep {$f == $_;} @frames) @@ -1334,10 +1335,10 @@ sub videoPreview { } } - my $s = int($startseconds * $obj->{framerate}); + my $s = int($startseconds * $self->{framerate}); while (scalar @frames < $count) { push(@frames, $s); - $s += int( $stepseconds * $obj->{framerate} ); + $s += int( $stepseconds * $self->{framerate} ); } } else { @files = glob("$vdir/[0-9][0-9][0-9].vdr"); @@ -1347,14 +1348,14 @@ sub videoPreview { my $scalex = 180; my $mversions = { 'MPlayer1.0pre5' => sprintf("%s -noautosub -noconsolecontrols -nosound -nolirc -nojoystick -quiet -vo jpeg -jpeg outdir=%s -ni -ss %d -sstep %d -vf scale -zoom -xy %d -frames %d %s >> %s 2>&1", - $obj->{previewbinary}, qquote($outdir), $startseconds / 5, $stepseconds / 5, $scalex, $count, join(' ',@files), qquote($log)), + $self->{previewbinary}, qquote($outdir), $startseconds / 5, $stepseconds / 5, $scalex, $count, join(' ',@files), qquote($log)), 'MPlayer1.0pre6' => sprintf("%s -noautosub -noconsolecontrols -nosound -nolirc -nojoystick -quiet -vo jpeg:outdir=%s -ni -ss %d -sstep %d -vf scale -zoom -xy %d -frames %d %s >> %s 2>&1", - $obj->{previewbinary}, qquote($outdir), $startseconds / 5, $stepseconds / 5, $scalex, $count, join(' ',@files), qquote($log)), + $self->{previewbinary}, qquote($outdir), $startseconds / 5, $stepseconds / 5, $scalex, $count, join(' ',@files), qquote($log)), 'vdr2jpeg' => sprintf("%s -r %s -f %s -x %d -o %s >> %s 2>&1", - $obj->{previewbinary}, qquote($vdir), join(' -f ', @frames), $scalex, qquote($outdir), qquote($log)), + $self->{previewbinary}, qquote($vdir), join(' -f ', @frames), $scalex, qquote($outdir), qquote($log)), }; return { - command => $mversions->{$obj->{previewcommand}}, + command => $mversions->{$self->{previewcommand}}, previewdir => $outdir, RecordMD5 => $info->{RecordMD5} } @@ -1372,7 +1373,7 @@ sub _mark2frames{ # ------------------ sub SearchEpgId { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $start = shift || return error('No start time defined!'); my $dur = shift || return 0; my $title = shift || return error('No title defined!'); @@ -1381,7 +1382,7 @@ sub SearchEpgId { my $sth; my $bis = int($start + $dur); if($channel && $channel ne "") { - $sth = $obj->{dbh}->prepare( + $sth = $self->{dbh}->prepare( qq|SELECT SQL_CACHE * FROM OLDEPG WHERE UNIX_TIMESTAMP(starttime) >= ? AND UNIX_TIMESTAMP(starttime)+duration <= ? @@ -1390,7 +1391,7 @@ qq|SELECT SQL_CACHE * FROM OLDEPG WHERE $sth->execute($start,$bis,$title,$channel) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); } else { - $sth = $obj->{dbh}->prepare( + $sth = $self->{dbh}->prepare( qq|SELECT SQL_CACHE * FROM OLDEPG WHERE UNIX_TIMESTAMP(starttime) >= ? AND UNIX_TIMESTAMP(starttime)+duration <= ? @@ -1407,7 +1408,7 @@ qq|SELECT SQL_CACHE * FROM OLDEPG WHERE # ------------------ sub createOldEventId { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return error('No eventid defined!'); my $start = shift || return error('No start time defined!'); my $duration = shift || 0; @@ -1427,12 +1428,12 @@ sub createOldEventId { audio => $info->{audio} || "", }; - $attr->{eventid} = $obj->{dbh}->selectrow_arrayref('SELECT SQL_CACHE max(eventid)+1 from OLDEPG')->[0]; + $attr->{eventid} = $self->{dbh}->selectrow_arrayref('SELECT SQL_CACHE max(eventid)+1 from OLDEPG')->[0]; $attr->{eventid} = 1000000000 if(not defined $attr->{eventid} or $attr->{eventid} < 1000000000 ); lg sprintf('Create event "%s" into OLDEPG', $subtitle ? $title .'~'. $subtitle : $title); - my $sth = $obj->{dbh}->prepare( + my $sth = $self->{dbh}->prepare( q|REPLACE INTO OLDEPG(eventid, title, subtitle, description, channel_id, duration, tableid, starttime, vpstime, video, audio, addtime) VALUES (?,?,?,?,?,?,?,FROM_UNIXTIME(?),FROM_UNIXTIME(?),?,?,NOW())|); @@ -1457,7 +1458,7 @@ q|REPLACE INTO OLDEPG(eventid, title, subtitle, description, channel_id, # ------------------ sub display { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $recordid = shift; @@ -1496,7 +1497,7 @@ where my $erg; # my $fields; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); if(!$sth->execute($recordid) # || !($fields = $sth->{'NAME'}) || !($erg = $sth->fetchrow_hashref())) { @@ -1509,13 +1510,13 @@ where $erg->{StopTime} = datum($erg->{StopTime},'voll'); } - $obj->_loadreccmds; - my @reccmds = @{$obj->{reccmds}}; + $self->_loadreccmds; + my @reccmds = @{$self->{reccmds}}; map { $_ =~ s/\s*\:.*$//; } @reccmds; - my ($keywords,$keywordmax,$keywordmin) = $obj->{keywords}->list('recording',[ $erg->{'RecordId'} ]); + my ($keywords,$keywordmax,$keywordmin) = $self->{keywords}->list('recording',[ $erg->{'RecordId'} ]); my $param = { reccmds => \@reccmds, @@ -1527,7 +1528,7 @@ where # ------------------ sub play { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $recordid = shift || return con_err($console,gettext("No recording defined for playback! Please use rplay 'rid'.")); @@ -1535,7 +1536,7 @@ sub play { my $sql = qq|SELECT SQL_CACHE r.RecordID,r.RecordMD5,e.duration as duration FROM RECORDS as r, OLDEPG as e WHERE e.eventid = r.eventid and r.RecordMD5 = ?|; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); my $rec; if(!$sth->execute($recordid) || !($rec = $sth->fetchrow_hashref())) { @@ -1547,7 +1548,7 @@ sub play { $start = &text2frame($params->{start}); } if($start) { - if($start < 0 or ($start / $obj->{framerate}) >= ($rec->{duration})) { + if($start < 0 or ($start / $self->{framerate}) >= ($rec->{duration})) { $start = 'begin'; } else { $start = &frame2hms($start); @@ -1558,7 +1559,7 @@ sub play { my $cmd = sprintf('PLAY %d %s', $rec->{RecordID}, $start); - if($obj->{svdrp}->scommand($watcher, $console, $cmd)) { + if($self->{svdrp}->scommand($watcher, $console, $cmd)) { $console->redirect({url => sprintf('?cmd=rdisplay&data=%s',$rec->{RecordMD5}), wait => 1}) if(ref $console and $console->typ eq 'HTML'); @@ -1571,13 +1572,13 @@ sub play { # ------------------ sub cut { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $recordid = shift || return con_err($console,gettext("No recording defined for playback! Please use rplay 'rid'.")); my $sql = qq|SELECT SQL_CACHE RecordID,RecordMD5 FROM RECORDS WHERE RecordMD5 = ?|; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); my $rec; if(!$sth->execute($recordid) || !($rec = $sth->fetchrow_hashref())) { @@ -1585,7 +1586,7 @@ sub cut { } my $cmd = sprintf('EDIT %d', $rec->{RecordID}); - if($obj->{svdrp}->scommand($watcher, $console, $cmd)) { + if($self->{svdrp}->scommand($watcher, $console, $cmd)) { $console->redirect({url => sprintf('?cmd=rdisplay&data=%s',$rec->{RecordMD5}), wait => 1}) if(ref $console and $console->typ eq 'HTML'); @@ -1598,14 +1599,14 @@ sub cut { # ------------------ sub list { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $text = shift || ""; my $params = shift; my $deep = 1; - my $folder = scalar (my @a = split('/',$obj->{videodir})) + 1; + my $folder = scalar (my @a = split('/',$self->{videodir})) + 1; my $term; my $where = "e.eventid = r.eventid"; @@ -1680,7 +1681,7 @@ ORDER BY __IsRecording asc, my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -1698,7 +1699,7 @@ ORDER BY __IsRecording asc, } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); + $sth = $self->{dbh}->prepare($sql); $sth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); @@ -1718,18 +1719,18 @@ ORDER BY __IsRecording asc, $_->[5] = datum($_->[5],'short'); } @$erg; - ($keywords,$keywordmax,$keywordmin) = $obj->{keywords}->list('recording',$md5); + ($keywords,$keywordmax,$keywordmin) = $self->{keywords}->list('recording',$md5); unshift(@$erg, $fields); } my $param = { sortable => 1, - usage => $obj->{CapacityMessage}, - used => $obj->{CapacityPercent}, - total => $obj->{CapacityTotal}, - free => $obj->{CapacityFree}, - previewcommand => $obj->{previewlistthumbs}, + usage => $self->{CapacityMessage}, + used => $self->{CapacityPercent}, + total => $self->{CapacityTotal}, + free => $self->{CapacityFree}, + previewcommand => $self->{previewlistthumbs}, keywords => $keywords, keywordsmax => $keywordmax, keywordsmin => $keywordmin, @@ -1741,20 +1742,20 @@ ORDER BY __IsRecording asc, # ------------------ sub search { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $text = shift || return $obj->list($watcher,$console); + my $text = shift || return $self->list($watcher,$console); my $params = shift; my $query = buildsearch("e.title,e.subtitle,e.description",$text); - return $obj->_search($watcher,$console,$query->{query},$query->{term},$params); + return $self->_search($watcher,$console,$query->{query},$query->{term},$params); } # ------------------ sub _search { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $search = shift; @@ -1815,7 +1816,7 @@ ORDER BY my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -1833,7 +1834,7 @@ ORDER BY } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); + $sth = $self->{dbh}->prepare($sql); $sth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); @@ -1853,18 +1854,18 @@ ORDER BY $_->[5] = datum($_->[5],'short'); } @$erg; - ($keywords,$keywordmax,$keywordmin) = $obj->{keywords}->list('recording',$md5); + ($keywords,$keywordmax,$keywordmin) = $self->{keywords}->list('recording',$md5); unshift(@$erg, $fields); } my $param = { sortable => 1, - usage => $obj->{CapacityMessage}, - used => $obj->{CapacityPercent}, - total => $obj->{CapacityTotal}, - free => $obj->{CapacityFree}, - previewcommand => $obj->{previewcommand}, + usage => $self->{CapacityMessage}, + used => $self->{CapacityPercent}, + total => $self->{CapacityTotal}, + free => $self->{CapacityFree}, + previewcommand => $self->{previewcommand}, keywords => $keywords, keywordsmax => $keywordmax, keywordsmin => $keywordmin, @@ -1878,7 +1879,7 @@ ORDER BY # ------------------ sub delete { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $record = shift || return con_err($console,gettext("No recording defined for deletion! Please use rdelete 'id'.")); @@ -1891,7 +1892,7 @@ sub delete { foreach my $item (@rcs) { if($item =~ /^all\:(\w+)/i) { - my $ids = $obj->getGroupIds($1); + my $ids = $self->getGroupIds($1); for(@$ids) { $rec{$_} = 1; } @@ -1902,7 +1903,7 @@ sub delete { my @recordings = keys %rec; my $sql = sprintf("SELECT SQL_CACHE r.RecordId,CONCAT_WS('~',e.title,e.subtitle),r.RecordMD5 FROM RECORDS as r,OLDEPG as e WHERE e.eventid = r.eventid and r.RecordMD5 IN (%s) ORDER BY r.RecordId desc", join(',' => ('?') x @recordings)); - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute(@recordings) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); my $data = $sth->fetchall_arrayref(); # Query as array to hold ordering ! @@ -1932,7 +1933,7 @@ sub delete { ); - $obj->{svdrp}->queue_cmds(sprintf("delr %s",$r->{Id})); + $self->{svdrp}->queue_cmds(sprintf("delr %s",$r->{Id})); push(@{$todelete},$r->{Title}); # Remember title push(@{$md5delete},$r->{MD5}); # Remember hash @@ -1952,33 +1953,33 @@ sub delete { join('\',\'',@recordings))) if(scalar @recordings); - if($obj->{svdrp}->queue_cmds('COUNT')) { + if($self->{svdrp}->queue_cmds('COUNT')) { my $msg = sprintf(gettext("Recording '%s' to delete"),join('\',\'',@{$todelete})); - my $erg = $obj->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos + my $erg = $self->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos my $waiter; - if($obj->{svdrp}->err) { + if($self->{svdrp}->err) { con_err($console,$erg); } else { - if(ref $console && $console->typ eq 'HTML' && !$obj->{inotify}) { + if(ref $console && $console->typ eq 'HTML' && !$self->{inotify}) { $waiter = $console->wait($msg,0,1000,'no'); }else { con_msg($console,$msg); } my $dsql = sprintf("DELETE FROM RECORDS WHERE RecordMD5 IN (%s)", join(',' => ('?') x @{$md5delete})); - my $dsth = $obj->{dbh}->prepare($dsql); + my $dsth = $self->{dbh}->prepare($dsql); $sth->execute(@{$md5delete}) or return con_err($console, sprintf("Couldn't execute query: %s.",$sth->errstr)); - $obj->{keywords}->remove('recording',$md5delete); + $self->{keywords}->remove('recording',$md5delete); } - $obj->readData($watcher,$console,$waiter) - unless($obj->{inotify}); + $self->readData($watcher,$console,$waiter) + unless($self->{inotify}); if(ref $console && $console->typ eq 'HTML') { my @t = split('~', $todelete->[0]); @@ -2013,7 +2014,7 @@ sub is_empty_dir { # ------------------ sub redit { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $recordid = shift || return con_err($console,gettext("No recording defined for editing!")); @@ -2035,14 +2036,14 @@ WHERE e.eventid = r.eventid AND ( r.RecordMD5 = ? ) |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); if(!$sth->execute($recordid) || !($rec = $sth->fetchrow_hashref())) { return con_err($console,sprintf(gettext("Recording '%s' does not exist in the database!"),$recordid)); } } - my $status = $obj->readinfo($rec->{Path}); + my $status = $self->readinfo($rec->{Path}); my $marksfile = sprintf('%s/%s', $rec->{Path}, 'marks.vdr'); my $marks = (-r $marksfile ? load_file($marksfile) : ''); @@ -2118,7 +2119,7 @@ WHERE def => $status->{aux}, }, 'keywords' => { - typ => $obj->{keywords}->{active} eq 'y' ? 'string' : 'hidden', + typ => $self->{keywords}->{active} eq 'y' ? 'string' : 'hidden', msg => gettext('Keywords'), def => $status->{keywords}, }, @@ -2168,9 +2169,9 @@ WHERE $info->{title} = join('~',@t); } - $info->{aux} = $obj->{keywords}->mergexml($info->{aux},'keywords',$info->{keywords}); + $info->{aux} = $self->{keywords}->mergexml($info->{aux},'keywords',$info->{keywords}); - $obj->saveinfo($rec->{Path},$info) + $self->saveinfo($rec->{Path},$info) or return con_err($console,sprintf(gettext("Couldn't write file '%s' : %s"),$rec->{Path} . '/info.vdr',$!)); $ChangeRecordingData = 1 if($info->{aux} ne $status->{aux}); @@ -2207,7 +2208,7 @@ WHERE if($data->{title} ne $rec->{title}) { # Rename auf der Platte - my $newPath = sprintf('%s/%s/%s', $obj->{videodir}, $obj->translate($data->{title}),basename($rec->{Path})); + my $newPath = sprintf('%s/%s/%s', $self->{videodir}, $self->translate($data->{title}),basename($rec->{Path})); my $parentnew = dirname($newPath); unless( -d $parentnew) { @@ -2219,7 +2220,7 @@ WHERE or return con_err($console,sprintf(gettext("Recording: '%s', couldn't move to '%s' : %s"),$rec->{title},$data->{title},$!)); my $parentold = dirname($rec->{Path}); - if($obj->{videodir} ne $parentold + if($self->{videodir} ne $parentold and -d $parentold and is_empty_dir($parentold)) { rmdir($parentold) @@ -2233,35 +2234,35 @@ WHERE if($dropEPGEntry) { # Delete EpgOld Entrys - my $sth = $obj->{dbh}->prepare('DELETE FROM OLDEPG WHERE eventid = ?'); + my $sth = $self->{dbh}->prepare('DELETE FROM OLDEPG WHERE eventid = ?'); $sth->execute($rec->{EventId}) or return con_err($console,sprintf("Couldn't execute query: %s.",$sth->errstr)); } if($ChangeRecordingData) { - my $sth = $obj->{dbh}->prepare('DELETE FROM RECORDS WHERE RecordMD5 = ?'); + my $sth = $self->{dbh}->prepare('DELETE FROM RECORDS WHERE RecordMD5 = ?'); $sth->execute($recordid) or return con_err($console,sprintf("Couldn't execute query: %s.",$sth->errstr)); my $todel; push(@$todel,$recordid); - $obj->{keywords}->remove('recording',$todel); + $self->{keywords}->remove('recording',$todel); } if($dropEPGEntry || $ChangeRecordingData) { - $obj->{lastupdate} = 0; - touch($obj->{videodir}."/.update"); + $self->{lastupdate} = 0; + touch($self->{videodir}."/.update"); } if($dropEPGEntry || $ChangeRecordingData) { my $waiter; - if(ref $console && $console->typ eq 'HTML' && !($obj->{inotify})) { + if(ref $console && $console->typ eq 'HTML' && !($self->{inotify})) { $waiter = $console->wait(gettext('Recording edited!'),0,1000,'no'); }else { con_msg($console,gettext('Recording edited!')); } sleep(1); - $obj->readData($watcher,$console,$waiter) - unless($obj->{inotify}); + $self->readData($watcher,$console,$waiter) + unless($self->{inotify}); } else { con_msg($console,gettext("Recording was'nt changed!")); @@ -2278,14 +2279,14 @@ WHERE # Load Reccmds's sub _loadreccmds { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); - unless($obj->{reccmds}) { - $obj->{reccmds} = []; - if(-r $obj->{commandfile} and my $text = load_file($obj->{commandfile})) { + unless($self->{reccmds}) { + $self->{reccmds} = []; + if(-r $self->{commandfile} and my $text = load_file($self->{commandfile})) { foreach my $zeile (split(/\n/, $text)) { if($zeile !~ /^\#/ and $zeile !~ /^$/ and $zeile !~ /true/) { - push(@{$obj->{reccmds}}, $zeile); + push(@{$self->{reccmds}}, $zeile); } } } @@ -2295,32 +2296,32 @@ sub _loadreccmds { # ------------------ sub conv { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $data = shift || 0; - $obj->_loadreccmds; + $self->_loadreccmds; - unless(scalar @{$obj->{reccmds}}) { + unless(scalar @{$self->{reccmds}}) { con_err($console,gettext('No reccmds.conf on your system!')); return 1; } unless($data) { con_err($console,gettext("Please use rconvert 'cmdid_rid'")); - unshift(@{$obj->{reccmds}}, + unshift(@{$self->{reccmds}}, [ gettext('Description'), gettext('Command') ]); - $console->table($obj->{reccmds}); - $obj->list($watcher, $console); + $console->table($self->{reccmds}); + $self->list($watcher, $console); } my ($cmdid, $recid) = split(/[\s_]/, $data); - my $cmd = (split(':', $obj->{reccmds}->[$cmdid-1]))[-1] || return con_err($console,gettext("Couldn't find this command ID!")); - my $path = $obj->IdToPath($recid) || return con_err($console,sprintf(gettext("Recording '%s' does not exist in the database!"),$recid)); + my $cmd = (split(':', $self->{reccmds}->[$cmdid-1]))[-1] || return con_err($console,gettext("Couldn't find this command ID!")); + my $path = $self->IdToPath($recid) || return con_err($console,sprintf(gettext("Recording '%s' does not exist in the database!"),$recid)); my $command = sprintf("%s %s",$cmd,qquote($path)); debug sprintf('Call command %s%s', @@ -2353,7 +2354,7 @@ sub conv { # ------------------ sub status { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $lastReportTime = shift; @@ -2376,7 +2377,7 @@ ORDER BY e.starttime asc |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($lastReportTime) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $fields = $sth->{'NAME'}; @@ -2393,10 +2394,10 @@ ORDER BY # ------------------ sub IdToData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return undef; - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE * from RECORDS as r, OLDEPG as e where e.eventid = r.eventid and RecordMD5 = ?'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE * from RECORDS as r, OLDEPG as e where e.eventid = r.eventid and RecordMD5 = ?'); $sth->execute($id) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchrow_hashref(); @@ -2406,10 +2407,10 @@ sub IdToData { # ------------------ sub IdToPath { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return undef; - my $sth = $obj->{dbh}->prepare('SELECT SQL_CACHE Path from RECORDS where RecordMD5 = ?'); + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE Path from RECORDS where RecordMD5 = ?'); $sth->execute($id) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchrow_hashref(); @@ -2419,17 +2420,17 @@ sub IdToPath { # ------------------ sub getGroupIds { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $recid = shift || return error ('No recording defined!'); - my $data = $obj->IdToData($recid); + my $data = $self->IdToData($recid); unless($data) { error sprintf("Couldn't find recording '%s'!", $recid); return; } my $text = $data->{title}; - my $folder = scalar (my @a = split('/',$obj->{videodir})) + 1; + my $folder = scalar (my @a = split('/',$self->{videodir})) + 1; my $deep = scalar (my @c = split('~',$text)); $folder += $deep; $deep += 1; @@ -2454,7 +2455,7 @@ GROUP BY SUBSTRING_INDEX(r.Path, '/', IF(Length(e.subtitle)<=0, $folder + 1, $folder)) |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($text,$text .'~%') or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchall_arrayref(); @@ -2471,9 +2472,9 @@ GROUP BY # title to path sub translate { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $title = shift || return error ('No title in translate!'); - my $vfat = shift || $obj->{vfat}; + my $vfat = shift || $self->{vfat}; if($vfat eq 'y') { @@ -2494,9 +2495,9 @@ sub translate { # path to title sub converttitle { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $title = shift || return error ('No title in translate!'); - my $vfat = shift || $obj->{vfat}; + my $vfat = shift || $self->{vfat}; $title =~ s/_/ /g; $title =~ tr#\/~\x01\x02#~\/\'\/#; @@ -2514,7 +2515,7 @@ sub converttitle { # return value as integer sub _recordinglength { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $path = shift || return error ('Missing path from recording!' ); my $f = sprintf("%s/index.vdr", $path); @@ -2526,7 +2527,7 @@ sub _recordinglength { return 0 unless($fst and $rst); if($fst->mode & 00400) { # mode & S_IRUSR - return int(($fst->size / 8) / $obj->{framerate}); + return int(($fst->size / 8) / $self->{framerate}); } else { error sprintf("Couldn't read : '%s'", $f); } @@ -2538,12 +2539,12 @@ sub _recordinglength { # return value as integer sub _recordingsize { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $path = shift || return error('Missing path from recording!'); my $size = shift || 0; # Filesize offset e.g. from index.vdr my @files = glob("$path/[0-9][0-9][0-9].vdr"); - return $obj->_recordingCapacity(\@files,$size); + return $self->_recordingCapacity(\@files,$size); } # ------------------ @@ -2551,7 +2552,7 @@ sub _recordingsize { # return value as integer sub _recordingCapacity { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $files = shift || return error('Missing files from recording!'); my $size = shift || 0; # Filesize offset e.g. from index.vdr @@ -2580,7 +2581,7 @@ sub _recordingCapacity { # ------------------ sub suggest { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $search = shift; @@ -2613,7 +2614,7 @@ ORDER BY title LIMIT 25 |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute('%'.$search.'%','%'.$search.'%') or return error "Couldn't execute query: $sth->errstr."; my $result = $sth->fetchall_arrayref(); @@ -2625,13 +2626,13 @@ LIMIT 25 # ------------------ sub recover { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $recordid = shift || 0; my $data = shift || 0; - my $files = $obj->scandirectory('del'); + my $files = $self->scandirectory('del'); return con_msg($console,gettext("There none recoverable recordings!")) unless($files and keys %{$files}); @@ -2687,18 +2688,18 @@ sub recover { if($ChangeRecordingData) { my $waiter; - $obj->{lastupdate} = 0; - touch($obj->{videodir}."/.update"); + $self->{lastupdate} = 0; + touch($self->{videodir}."/.update"); - if(ref $console && $console->typ eq 'HTML' && !($obj->{inotify})) { + if(ref $console && $console->typ eq 'HTML' && !($self->{inotify})) { $waiter = $console->wait(gettext('Recording recovered!'),0,1000,'no'); }else { con_msg($console,gettext('Recording recovered!')); } sleep(1); - $obj->readData($watcher,$console,$waiter) - unless($obj->{inotify}); + $self->readData($watcher,$console,$waiter) + unless($self->{inotify}); } else { con_msg($console,gettext("None recording was'nt recovered!")); @@ -2714,7 +2715,7 @@ sub recover { ################################################################################ # find file and offset from frame sub frametofile { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $path = shift || return error ('Missing path from recording!' ); my $frame = int (shift); @@ -2765,7 +2766,7 @@ sub frametofile { # ------------------ sub image { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $data = shift; @@ -2784,7 +2785,7 @@ sub image { if(length($frame) < 8) { $frame = sprintf("%08d",$frame); } - return $console->datei(sprintf('%s/%s_shot/%s.jpg', $obj->{previewimages}, $recordid, $frame)); + return $console->datei(sprintf('%s/%s_shot/%s.jpg', $self->{previewimages}, $recordid, $frame)); } 1; diff --git a/lib/XXV/MODULES/REMOTE.pm b/lib/XXV/MODULES/REMOTE.pm index 972ee86..758aa99 100644 --- a/lib/XXV/MODULES/REMOTE.pm +++ b/lib/XXV/MODULES/REMOTE.pm @@ -8,7 +8,7 @@ use Tools; # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'REMOTE', Prereq => { @@ -44,25 +44,25 @@ sub module { remote => { description => gettext("Display ir remote 'cmd'"), short => 'r', - callback => sub{ $obj->remote(@_) }, + callback => sub{ $self->remote(@_) }, DenyClass => 'remote', }, switch => { description => gettext("Switch to channel 'cid'"), short => 'sw', - callback => sub{ $obj->switch(@_) }, + callback => sub{ $self->switch(@_) }, DenyClass => 'remote', }, command => { description => gettext("Call the command 'cid'"), short => 'cmd', - callback => sub{ $obj->command(@_) }, + callback => sub{ $self->command(@_) }, DenyClass => 'remote', }, cmdlist => { description => gettext("List the commands"), short => 'cmdl', - callback => sub{ $obj->list(@_) }, + callback => sub{ $self->list(@_) }, DenyClass => 'remote', }, }, @@ -111,16 +111,16 @@ sub new { # ------------------ sub init { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); main::after(sub{ - $obj->{svdrp} = main::getModule('SVDRP'); - unless($obj->{svdrp}) { + $self->{svdrp} = main::getModule('SVDRP'); + unless($self->{svdrp}) { panic ("Couldn't get modul SVDRP"); return 0; } - $obj->{CMDS} = $obj->parse(); + $self->{CMDS} = $self->parse(); return 1; }, "REMOTE: Parse Commandfile ..."); @@ -130,17 +130,17 @@ sub init { # ------------------ sub parse { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); return 0 - unless (exists $obj->{commands}); + unless (exists $self->{commands}); - if(! -r $obj->{commands}) { - error (sprintf("Could not open file '%s'! : %s",$obj->{commands},$!)); + if(! -r $self->{commands}) { + error (sprintf("Could not open file '%s'! : %s",$self->{commands},$!)); return 0; } - my $cmds = load_file($obj->{commands}); + my $cmds = load_file($self->{commands}); my $c = 0; my $ret = {}; @@ -159,10 +159,10 @@ sub parse { # ------------------ sub list { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $cmds = $obj->parse(); + my $cmds = $self->parse(); my @list = (['__Id', 'Name', 'Cmd']); foreach my $id (sort {$a <=> $b} keys %$cmds) { @@ -175,11 +175,11 @@ sub list { # ------------------ sub command { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $command = shift || return error('No command defined!'); - my $cmds = $obj->parse(); + my $cmds = $self->parse(); return $console->err(gettext('This cmd id does not exist!')) unless(exists $cmds->{$command}); @@ -207,27 +207,30 @@ sub command { # ------------------ sub remote { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $command = shift; + my $params = shift; - debug sprintf('Call remote with command "%s"%s', - $command, - ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) - ); + my $vdr = $self->{svdrp}->primary_hosts(); + if($params->{vdr}) { + $vdr = $params->{vdr}; + } unless($command) { - my $mod = main::getModule('GRAB'); + my $gmod = main::getModule('GRAB'); + my $cmod = main::getModule('CHANNELS'); my $params = { - width => $mod->{xsize}, - height => $mod->{ysize}, - monitor => $obj->{monitor} eq "y" ? 1 : 0 + width => $gmod->{xsize}, + height => $gmod->{ysize}, + monitor => $self->{monitor} eq "y" ? 1 : 0, + channels => $cmod->ChannelWithGroup('c.name,c.id'), + vdrlist => $self->{svdrp}->enum_onlinehosts(), + vdr => $vdr, }; return $console->remote(undef, $params); } else { - # the svdrp module - my $svdrp = $obj->{svdrp}; my $translate = { '<' => 'Channel-', @@ -244,11 +247,16 @@ sub remote { $command = $translate->{$command} if(exists $translate->{$command}); - # the command - my $cmd = sprintf('hitk %s', $command); - my $erg = $svdrp->command($cmd); + lg sprintf('Call remote command "%s" on %s%s', + $command, + $self->{svdrp}->hostname($vdr), + ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) + ); + + # fire hit key command via svdrp + my $erg = $self->{svdrp}->command(sprintf('hitk %s', $command), $vdr); - $console->msg($erg, $svdrp->err) + $console->msg($erg, $self->{svdrp}->err) if(ref $console); } return 1; @@ -257,28 +265,36 @@ sub remote { # ------------------ sub switch { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; - my $channel = shift || ''; - - lg sprintf('Call switch with channel "%s"%s', - $channel, + my $cid = shift || ''; + my $params = shift; + + my $cmod = main::getModule('CHANNELS'); + my $hash = $cmod->ToHash($cid, $params && $params->{vdr} ? $params->{vdr} : undef); + return con_err($console, sprintf(gettext("Channel '%s' does not exist in the database!"),$cid)) + unless($hash); + + my $channel; + $channel = $cmod->GetChannel($hash); + return con_err($console, sprintf(gettext("Channel '%s' does not exist in the database!"),$cid)) + unless($channel); + + lg sprintf('Change channel "%s" on %s%s', + $channel->{name}, + $self->{svdrp}->hostname($channel->{vid}), ( ref $console && $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - # the svdrp module - my $svdrp = $obj->{svdrp}; - - # the command - my $cmd = sprintf('chan %s', $channel); - my $erg = $svdrp->command($cmd); + # fire change channel command via svdrp + my $erg = $self->{svdrp}->command(sprintf('chan %s', $channel->{pos}),$channel->{vid}); my ($ret) = $erg->[1] =~ /^\d{3}\s*(.+)/s; - $console->msg($erg, $svdrp->err) + $console->msg($erg, $self->{svdrp}->err) if(ref $console); - $console->redirect({url => sprintf('?cmd=program&data=%s',$channel), wait => 1}) + $console->redirect({url => sprintf('?cmd=program&data=%s',$channel->{hash}), wait => 1}) if(ref $console and $console->typ eq 'HTML'); diff --git a/lib/XXV/MODULES/STREAM.pm b/lib/XXV/MODULES/STREAM.pm index 3fdce55..b5b07ca 100644 --- a/lib/XXV/MODULES/STREAM.pm +++ b/lib/XXV/MODULES/STREAM.pm @@ -5,6 +5,7 @@ use Tools; use File::Basename; use File::Find; use File::Path; +use File::stat; use File::Glob ':glob'; $SIG{CHLD} = 'IGNORE'; @@ -189,24 +190,30 @@ sub livestream { my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $channel = shift || return con_err($console,gettext("No channel defined for streaming!")); + my $cid = shift || return con_err($console,gettext("No channel defined for streaming!")); my $params = shift; return $console->err(gettext("Can't stream files!")) unless($console->can('datei')); my $cmod = main::getModule('CHANNELS'); + unless($cid and $cid =~ /^[0-9a-f]{32}$/) { + unless(index($cid, '-') > -1) { + $cid = $cmod->PosToHash($cid); + } else { + $cid = $cmod->CIDToHash($cid); + } + } - my $ch = $cmod->ToCID($channel); - return $console->err(sprintf(gettext("This channel '%s' does not exist!"),$channel)) - unless($ch); - my $title = $cmod->ChannelToName($ch); + return $console->err(sprintf(gettext("This channel '%s' does not exist!"),$cid)) + unless($cid); + my $channel = $cmod->GetChannel($cid); if($self->{widget} ne 'external' && (!$params || !(exists $params->{player}))) { - my $data = sprintf("?cmd=livestream&__player=1&data=%s",$ch); + my $data = sprintf("?cmd=livestream&__player=1&data=%s",$channel->{hash}); my $param = { - title => $title, + title => $channel->{name}, widget => $self->{widget}, width => $self->{width}, height => $self->{height}, @@ -214,16 +221,25 @@ sub livestream { return $console->player($data, $param); } - #my $cpos = $cmod->ChannelToPos($ch); debug sprintf('Live stream with channel "%s"%s', - $title, + $channel->{name}, ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); $console->{nopack} = 1; + + # query hostname from video disk recorder + my $livehost = main::getModule('SVDRP')->hostname($channel->{vid}); + if($self->{LiveAccessMethod} ne 'proxy' and + ($livehost eq 'localhost' or $livehost eq '127.0.0.1')) { + $livehost = $self->{host}; + } + my $liveport = 3000; - my $request = sprintf("/%s/%s", $self->{streamtype}, $ch); - my $url = sprintf("http://%s:%d%s",$self->{host},$liveport,$request); + + my $request = sprintf("/%s/%s", $self->{streamtype}, $channel->{id}); + my $url = sprintf("http://%s:%d%s",$livehost,$liveport,$request); + if($self->{LiveAccessMethod} eq 'redirect') { debug(sprintf("Redirect to %s",$url)); $console->statusmsg(301,$url); @@ -232,16 +248,16 @@ sub livestream { debug(sprintf("Send playlist with %s",$url)); my $data; $data = "#EXTM3U\r\n"; - $data .= $url; - $data .= "\r\n"; + $data .= "#EXTINF:86400," . $channel->{name} . "\r\n"; + $data .= $url . "\r\n"; my $arg; - $arg->{'attachment'} = sprintf("livestream-%s.m3u", $ch); + $arg->{'attachment'} = sprintf("livestream-%s.m3u", $channel->{id}); $arg->{'Content-Length'} = length($data); return $console->out($data, $self->{mimetyp}, %{$arg} ); } elsif($self->{LiveAccessMethod} eq 'proxy') { - $console->proxy($self->{host},$liveport,$request,$self->{mimetyp}); + $console->proxy($livehost,$liveport,$request,$self->{mimetyp}); return; } else { $console->err(gettext('Unknown access method!')); @@ -305,21 +321,34 @@ sub playrecord { ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - if($self->{method} eq 'http') { + if(0 and $self->{method} eq 'http') { return $console->stream(\@files, $self->{mimetyp}, $offset); } else { my $videopath = $rmod->{videodir}; my $data; - $data = "#EXTM3U\r\n"; + $data = "#EXTM3U\r\n"; + foreach my $file (@files) { + my $fstat = stat($file); + $file =~ s/^$videopath//si; $file =~ s/^[\/|\\]//si; my $URL = sprintf("%s/%s\r\n", $self->{netvideo}, $file); $URL =~s/\//\\/g if($URL =~ /^\\\\/sig # Samba \\host/xxx/yyy => \\host\xxx\yyy || $URL =~ /^[a-z]\:[\/|\\]/sig); # Samba x:/xxx/yyy => x:\xxx\yyy + + + if($fstat) { + # estimate duration of file in seconds ( filesize * totaltime / totalsize ) + my $duration = CORE::int($fstat->size * $result->{duration} / ($result->{FileSize} * 1024 * 1024)); + # add duration and title as extended infomations + $data .= "#EXTINF:". $duration ."," . $result->{title}; + $data .= "~" . $result->{subtitle} if($result->{subtitle}); + $data .= "\r\n"; + } $data .= $URL; } diff --git a/lib/XXV/MODULES/SVDRP.pm b/lib/XXV/MODULES/SVDRP.pm index e18eeff..a3ba7b7 100644 --- a/lib/XXV/MODULES/SVDRP.pm +++ b/lib/XXV/MODULES/SVDRP.pm @@ -10,30 +10,18 @@ $|++; # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'SVDRP', Prereq => { 'Net::Telnet' => 'Net::Telnet allows you to make client connections to a TCP port and do network I/O', }, - Description => gettext('This module serves as telnet client for sdvrp.'), + Description => gettext('This module module manages connection to video disk recorder.'), Version => (split(/ /, '$Revision$'))[1], Date => (split(/ /, '$Date$'))[1], Author => 'xpix', LastAuthor => (split(/ /, '$Author$'))[1], Preferences => { - VdrHost => { - description => gettext('Name of host that runs the VDR.'), - default => 'localhost', - type => 'host', - required => gettext('This is required!'), - }, - VdrPort => { - description => gettext('SVDRP port on the running VDR'), - default => 2001, - type => 'integer', - required => gettext('This is required!'), - }, timeout => { description => gettext('Connection timeout defines after how many seconds an unrequited connection is terminated.'), default => 60, @@ -42,17 +30,41 @@ sub module { }, }, Commands => { + vdrlist => { + description => gettext("List defined video disk recorder."), + short => 'vl', + callback => sub{ $self->list(@_) }, + Level => 'admin', + }, + vdrnew => { + description => gettext('Create new video disk recorder definition.'), + short => 'vn', + callback => sub{ $self->create(@_) }, + Level => 'admin', + }, + vdrdelete => { + description => gettext("Delete video disk recorder definition 'id'"), + short => 'vd', + callback => sub{ $self->delete(@_) }, + Level => 'admin', + }, + vdredit => { + description => gettext("Edit video disk recorder definition 'id'"), + short => 've', + callback => sub{ $self->edit(@_) }, + Level => 'admin', + }, sstatus => { - description => gettext('Status from svdrp'), + description => gettext('Status from video disk recorder.'), short => 'ss', - callback => sub{ $obj->status(@_) }, + callback => sub{ $self->status(@_) }, Level => 'user', DenyClass => 'remote', }, scommand => { - description => gettext('Send a command to svdrp'), + description => gettext('Send a command to video disk recorder.'), short => 'sc', - callback => sub{ $obj->scommand(@_) }, + callback => sub{ $self->scommand(@_) }, Level => 'admin', DenyClass => 'remote', }, @@ -97,36 +109,399 @@ sub new { # read the DB Handle $self->{dbh} = delete $attr{'-dbh'}; - $self->{COMMANDS} = []; + # initialize modul + my $erg = $self->_init or return error('Problem to initialize modul!'); return $self; } # ------------------ +sub _init { +# ------------------ + my $self = shift || return error('No object defined!'); + + unless($self->{dbh}) { + panic("Session to database is'nt connected"); + return 0; + } + + my $version = main::getDBVersion(); + # don't remove old table, if updated rows => warn only + if(!tableUpdated($self->{dbh},'RECORDER',$version,0)) { + return 0; + } + + # Look for table or create this table + my $erg = $self->{dbh}->do(qq| + CREATE TABLE IF NOT EXISTS RECORDER ( + id int unsigned auto_increment NOT NULL, + active enum('y', 'n') default 'y', + master enum('y', 'n') default 'n', + host varchar(100) NOT NULL default 'localhost', + port smallint unsigned default 2001, + cards varchar(100) default '', + PRIMARY KEY (id) + ) COMMENT = '$version' + |); + + # The Table is empty? Make a default host ... + my $first = $self->{dbh}->selectrow_arrayref('SELECT SQL_CACHE count(*) from RECORDER'); + unless($first && $first->[0]) { + $self->_insert({ + active => 'y', + master => 'y', + host => 'localhost', + port => 2001, + cards => '' + }); + } + + return 1; +} + +# ------------------ +sub _insert { +# ------------------ + my $self = shift || return error('No object defined!'); + my $data = shift || return; + + my $sth = $self->{dbh}->prepare('REPLACE INTO RECORDER VALUES (?,?,?,?,?,?)'); + $sth->execute( + $data->{id} || 0, + $data->{active}, + $data->{master}, + $data->{host}, + $data->{port}, + $data->{cards} + ) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); +} + +sub create { + my $self = shift || return error('No object defined!'); + my $watcher = shift || return error('No watcher defined!'); + my $console = shift || return error('No console defined!'); + my $id = shift || 0; + my $data = shift || 0; + + $self->edit($watcher, $console, $id, $data); +} + +sub edit { + my $self = shift || return error('No object defined!'); + my $watcher = shift || return error('No watcher defined!'); + my $console = shift || return error('No console defined!'); + my $id = shift || 0; + my $data = shift || 0; + + my $default; + if($id and not ref $data) { + my $sth = $self->{dbh}->prepare('SELECT SQL_CACHE * from RECORDER where id = ?'); + $sth->execute($id) + or return $console->err(sprintf(gettext("Definition of video disk recorder '%s' does not exist in the database!"),$id)); + $default = $sth->fetchrow_hashref(); + } + + my $questions = [ + 'id' => { + typ => 'hidden', + def => $default->{id} || 0, + }, + 'active' => { + typ => 'confirm', + def => $default->{active} || 'y', + msg => gettext('Activate this definition'), + }, + 'host' => { + typ => 'host', + msg => gettext("Host or IP address of video disk recorder"), + req => gettext('This is required!'), + def => $default->{host} || '', + }, + 'port' => { + typ => 'integer', + msg => gettext("Used Port of SVDRP"), + req => gettext('This is required!'), + def => $default->{port} || 2001, + check => sub{ + my $value = int(shift); + if($value > 0 && $value < 65536) { + return $value; + } else { + return undef, gettext('Value incorrect!'); + } + }, + }, + 'master' => { + typ => 'confirm', + def => $default->{master} || 'n', + msg => gettext('Use as primary video disk recorder'), + }, + 'cards' => { + msg => gettext("List of present source of DVB cards. (eg. S19.2E,S19.2E,T,T )"), + def => $default->{cards} || main::getModule('CHANNELS')->buildSourceList($id || $self->primary_hosts()), + }, + + ]; + + # Ask Questions + $data = $console->question(($id ? gettext('Edit video disk recorder definition') + : gettext('Create new video disk recorder definition')), $questions, $data); + + if(ref $data eq 'HASH') { + + if($data->{'master'} eq 'y') { + $self->{dbh}->do("UPDATE RECORDER SET master='n' WHERE master = 'y'"); + } + $self->_insert($data); + + $self->_deletevdrdata($data->{'id'}) if($data->{'active'} ne 'y'); + + delete $self->{Cache}; + + debug sprintf('%s video disk recorder definition "%s" is saved%s', + ($id ? 'New' : 'Changed'), + $data->{host}, + ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) + ); + + $console->message(gettext('Video disk recorder definition saved!')); + $console->redirect({url => '?cmd=vdrlist', wait => 1}) + if($console->typ eq 'HTML'); + } + return 1; +} + +sub delete { + my $self = shift || return error('No object defined!'); + my $watcher = shift || return error('No watcher defined!'); + my $console = shift || return error('No console defined!'); + my $id = shift || return $console->err(gettext("No definition of video disk recorder for deletion! Please use sdelete 'id'.")); + + my $sth = $self->{dbh}->prepare('delete from RECORDER where id = ?'); + $sth->execute($id) + or return $console->err(sprintf(gettext("Definition of video disk recorder '%s' does not exist in the database!"),$id)); + + $self->_deletevdrdata($id); + + delete $self->{Cache}; + + $console->message(sprintf gettext("Definition of video disk recorder are %s deleted."), $id); + + debug sprintf('Delete definition of video disk recorder "%s"%s', + $id, + ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) + ); + + $console->redirect({url => '?cmd=vdrlist', wait => 1}) + if($console->typ eq 'HTML'); +} + +sub _deletevdrdata { + my $self = shift || return error('No object defined!'); + my $id = shift; + + foreach my $table (qw/EPG OLDEPG TIMERS CHANNELS CHANNELGROUPS/) { + my $sth = $self->{dbh}->prepare("delete from $table where vid = ?"); + $sth->execute($id) + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + } +} + +# ------------------ +sub list { +# ------------------ + my $self = shift || return error('No object defined!'); + my $watcher = shift || return error('No watcher defined!'); + my $console = shift || return error('No console defined!'); + + my %f = ( + 'id' => gettext('Service'), + 'active' => gettext('Active'), + 'master' => gettext('Primary'), + 'host' => gettext('Host'), + 'cards' => gettext('Typ of Cards') + ); + + my $sql = qq| +SELECT SQL_CACHE + id as \'$f{id}\', + active as \'$f{active}\', + master as \'$f{master}\', + host as \'$f{host}\', + cards as \'$f{cards}\' +from + RECORDER + |; + + my $sth = $self->{dbh}->prepare($sql); + $sth->execute() + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + my $fields = $sth->{'NAME'}; + my $erg = $sth->fetchall_arrayref(); + unshift(@$erg, $fields); + + $console->table($erg); +} + + +sub _gethost { + my $self = shift || return error('No object defined!'); + my $vdrid = shift; + + unless(exists $self->{Cache}) { + my $sth = $self->{dbh}->prepare("SELECT * from RECORDER where active = 'y'"); + $sth->execute() + or return error sprintf("Couldn't execute query: %s.",$sth->errstr); + $self->{Cache} = $sth->fetchall_hashref('id'); + } + + unless($self->{Cache} && defined $self->{Cache}) { + panic ("Couldn't query any defined video disk recorder."); + return undef; + } + + if($vdrid) { + unless(defined $self->{Cache}->{$vdrid}) { + error sprintf("Definition of video disk recorder with id '%s' does not exist in the database.", $vdrid); + return undef; + } + return $self->{Cache}->{$vdrid}; + } else { + foreach my $id (keys %{$self->{Cache}}) { + my $h = $self->{Cache}->{$id}; + next unless($h->{master} eq 'y'); + return $h; + } + } + my ($k, $v) = each %{$self->{Cache}}; + debug sprintf("None primary video disk recorder defined in the database, use %s",$v->{host}); + return $v; +} + +sub primary_hosts { + my $self = shift || return error('No object defined!'); + + unless($self->{Cache}) { + return undef unless($self->_gethost()); + } + + foreach my $id (keys %{$self->{Cache}}) { + my $h = $self->{Cache}->{$id}; + next unless($h->{master} eq 'y'); + return $id; + } + + my ($k, $v) = each %{$self->{Cache}}; + return $k; +} + +sub list_hosts { + my $self = shift || return error('No object defined!'); + + unless($self->{Cache}) { + return undef unless($self->_gethost()); + } + + my $hosts; + foreach my $id (keys %{$self->{Cache}}) { + push(@$hosts,$id); + } + + return $hosts; +} + +sub hostname { + my $self = shift || return error('No object defined!'); + my $vdrid = shift; + + my $vdr = $self->_gethost($vdrid); + return $vdr ? $vdr->{host} : undef; +} + +sub cards { + my $self = shift || return error('No object defined!'); + my $vdrid = shift; + + my $vdr = $self->_gethost($vdrid); + return $vdr ? $vdr->{cards} : undef; +} + +sub enum_onlinehosts { + my $self = shift || return error('No object defined!'); + + unless($self->{Cache}) { + return undef unless($self->_gethost()); + # check online state + foreach my $vid (keys %{$self->{Cache}}) { + $self->command('chan',$vid); + } + } + + my $hosts; + foreach my $id (keys %{$self->{Cache}}) { + + next unless($self->{Cache}->{$id}->{online} + && $self->{Cache}->{$id}->{online} eq 'yes'); + + push(@$hosts,[$self->{Cache}->{$id}->{host},$id]); + } + + return $hosts; +} + +# ------------------ sub queue_cmds { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $cmd = shift || 'CALL'; + my $vdrid = shift; if($cmd eq 'CALL') { - my $queue = delete $obj->{COMMANDS}; - $obj->{COMMANDS} = []; - return $obj->command($queue); + my $erg; + my $result; + my $queue = delete $self->{Queue}; + $self->{Queue} = undef; + foreach my $id (keys %$queue) { + if($id eq 'master') { + $erg = $self->command($queue->{'master'},undef); + } else { + $erg = $self->command($queue->{$id},$id); + } + if($erg) { + if($result) { + @$result = (@$result, @$erg); + } else { + $result = $erg; + } + } + } + return $result; } elsif($cmd eq 'COUNT') { - return scalar @{$obj->{COMMANDS}}; + my $count = 0; + foreach my $id (keys %{$self->{Queue}}) { + next if($vdrid && $id ne $vdrid); + $count += scalar @{$self->{Queue}->{$id}}; + } + return $count; } else { - push(@{$obj->{COMMANDS}}, $cmd); + push(@{$self->{Queue}->{$vdrid || 'master'}}, $cmd); } + return undef; } # ------------------ sub command { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $cmd = shift; + my $vdrid = shift; - my $host = $obj->{VdrHost}; - my $port = $obj->{VdrPort}; + my $vdr = $self->_gethost($vdrid); + unless($vdr && defined $vdr->{host} && defined $vdr->{port}) { + $self->{ERROR} = gettext("None video disk recorder defined in the database."); + return undef; + } + $vdrid = $vdr->{id}; my $data; my $line; @@ -139,15 +514,16 @@ sub command { } push(@commands, "quit"); - $obj->{ERROR} = 0; + $self->{ERROR} = 0; # Put Command follow quit and read Output my $telnet = Net::Telnet->new ( Telnetmode => 0, - Timeout => $obj->{timeout}, + Timeout => $self->{timeout}, Errmode => 'return'); - if(!$telnet or !$telnet->open(Host => $host, Port => $port)){ - error sprintf("Couldn't connect to svdrp-socket %s:%s! %s",$host,$port,$telnet ? $telnet->errmsg : $!); + if(!$telnet or !$telnet->open(Host => $vdr->{host}, Port => $vdr->{port})){ + error sprintf("Couldn't connect to svdrp-socket %s:%s! %s",$vdr->{host},$vdr->{port},$telnet ? $telnet->errmsg : $!); + $self->{Cache}->{$vdrid}->{online} = 'no'; return undef; } @@ -161,7 +537,8 @@ sub command { } while($line && $line =~ /^\d\d\d\-/); unless($data && scalar @$data){ - error sprintf("Couldn't read data from svdrp-socket %s:%s! %s",$host,$port,$telnet ? $telnet->errmsg : $!); + error sprintf("Couldn't read data from svdrp-socket %s:%s! %s",$vdr->{host},$vdr->{port},$telnet ? $telnet->errmsg : $!); + $self->{Cache}->{$vdrid}->{online} = 'no'; return undef; } @@ -173,19 +550,20 @@ sub command { $telnet->buffer_empty; #clear buffer # send command if(!$telnet->print($command)) { - error sprintf("Couldn't send svdrp-command '%s' to %s:%s! %s",$command,$host,$port,$telnet ? $telnet->errmsg : $!); + error sprintf("Couldn't send command '%s' to %s:%s! %s",$command,$vdr->{host},$vdr->{port},$telnet ? $telnet->errmsg : $!); + $self->{Cache}->{$vdrid}->{online} = 'no'; return undef; } # read response do { - $line = $telnet->getline; + $line = $telnet->getline; chomp($line) if($line); if($line) { if($line =~ /^(\d{3})\s+(.+)/ && (int($1) >= 500)) { - my $msg = sprintf("Error at command '%s' to %s:%s! %s", $command,$host,$port, $2); + my $msg = sprintf("Error at command '%s' to %s:%s! %s", $command,$vdr->{host},$vdr->{port}, $2); error($msg); - $obj->{ERROR} .= $msg . "\n"; + $self->{ERROR} .= $msg . "\n"; } push(@$data, $line); @@ -196,9 +574,11 @@ sub command { # close socket $telnet->close(); + $self->{Cache}->{$vdrid}->{online} = 'yes'; + foreach my $command (@commands) { my @lines = (split(/[\r\n]/, $command)); - event(sprintf('Call command "%s" on svdrp %s.', $lines[0], $obj->{ERROR} ? " failed" : "successful")) + event(sprintf('Call command "%s" on %s %s.', $lines[0], $vdr->{host}, $self->{ERROR} ? " failed" : "successful")) if($command ne "quit"); } return \@$data; @@ -207,44 +587,43 @@ sub command { # ------------------ sub status { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return; - my $erg = $obj->command('stat disk'); - $console->msg($erg, $obj->err) + my $erg = $self->command('stat disk'); + $console->msg($erg, $self->{ERROR}) if(ref $console); return 1 - unless($obj->{ERROR}); + unless($self->{ERROR}); return 0; } # ------------------ sub scommand { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $text = shift || return $console->err(gettext("No command defined! Please use scommand 'cmd'.")); - my $erg = $obj->command($text); + my $erg = $self->command($text); return 0 - unless($erg || $obj->{ERROR}); + unless($erg || $self->{ERROR}); - $console->msg($erg, $obj->{ERROR}); + $console->msg($erg, $self->{ERROR}); return 1 - unless($obj->{ERROR}); + unless($self->{ERROR}); return 0; } - # ------------------ sub err { # ------------------ - my $obj = shift || return error('No object defined!'); - return $obj->{ERROR}; + my $self = shift || return error('No object defined!'); + return $self->{ERROR}; } 1; diff --git a/lib/XXV/MODULES/TIMERS.pm b/lib/XXV/MODULES/TIMERS.pm index 1bfe644..f6caccf 100644 --- a/lib/XXV/MODULES/TIMERS.pm +++ b/lib/XXV/MODULES/TIMERS.pm @@ -8,7 +8,7 @@ use POSIX ":sys_wait_h", qw(strftime mktime); # ------------------ sub module { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $args = { Name => 'TIMERS', Prereq => { @@ -20,7 +20,7 @@ sub module { Date => (split(/ /, '$Date$'))[1], Author => 'xpix', LastAuthor => (split(/ /, '$Author$'))[1], - Status => sub{ $obj->status(@_) }, + Status => sub{ $self->status(@_) }, Preferences => { interval => { description => gettext('How often timers are to be updated (in seconds)'), @@ -48,11 +48,6 @@ sub module { default => 50, type => 'integer', }, - DVBCardsTyp => { - description => gettext('List of present source of DVB cards. (eg. S19.2E,S19.2E,T,T )'), - default => '', - type => 'string', - }, usevpstime => { description => gettext('Use Programme Delivery Control (PDC) to control start time'), default => 'n', @@ -68,53 +63,53 @@ sub module { tlist => { description => gettext("List timers 'tid'"), short => 'tl', - callback => sub{ $obj->list(@_) }, + callback => sub{ $self->list(@_) }, DenyClass => 'tlist', }, tsearch => { description => gettext("Search timers 'text'"), short => 'ts', - callback => sub{ $obj->search(@_) }, + callback => sub{ $self->search(@_) }, DenyClass => 'tlist', }, tupdate => { description => gettext("Read timers and write them to the database"), short => 'tu', - callback => sub{ $obj->readData(@_)}, + callback => sub{ $self->readData(@_)}, Level => 'user', DenyClass => 'tedit', }, tnew => { description => gettext("Create timer 'eid'"), short => 'tn', - callback => sub{ $obj->newTimer(@_) }, + callback => sub{ $self->newTimer(@_) }, Level => 'user', DenyClass => 'tedit', }, tedit => { description => gettext("Edit timer 'tid'"), short => 'te', - callback => sub{ $obj->editTimer(@_) }, + callback => sub{ $self->editTimer(@_) }, Level => 'user', DenyClass => 'tedit', }, tdelete => { description => gettext("Delete timer 'tid'"), short => 'td', - callback => sub{ $obj->deleteTimer(@_) }, + callback => sub{ $self->deleteTimer(@_) }, Level => 'user', DenyClass => 'tedit', }, ttoggle => { description => gettext("Activate/Deactive timer 'tid'"), short => 'tt', - callback => sub{ $obj->toggleTimer(@_) }, + callback => sub{ $self->toggleTimer(@_) }, Level => 'user', DenyClass => 'tedit', }, tsuggest => { hidden => 'yes', - callback => sub{ $obj->suggest(@_) }, + callback => sub{ $self->suggest(@_) }, DenyClass => 'tlist', }, }, @@ -336,14 +331,14 @@ sub module { # ------------------ sub status { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $lastReportTime = shift || 0; my $total = 0; { - my $sth = $obj->{dbh}->prepare("SELECT SQL_CACHE count(*) as count from TIMERS"); + my $sth = $self->{dbh}->prepare("SELECT SQL_CACHE count(*) as count from TIMERS"); if(!$sth->execute()) { error sprintf("Couldn't execute query: %s.",$sth->errstr); @@ -403,30 +398,31 @@ sub new { # ------------------ sub _init { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); - unless($obj->{dbh}) { + unless($self->{dbh}) { panic("Session to database is'nt connected"); return 0; } - my $version = 29; # Must be increment if rows of table changed + my $version = 30; # Must be increment if rows of table changed # this tables hasen't handmade user data, # therefore old table could dropped if updated rows - if(!tableUpdated($obj->{dbh},'TIMERS',$version,1)) { + if(!tableUpdated($self->{dbh},'TIMERS',$version,1)) { return 0; } # Look for table or create this table - $obj->{dbh}->do(qq| + $self->{dbh}->do(qq| CREATE TABLE IF NOT EXISTS TIMERS ( id varchar(32) NOT NULL, - pos int(11) unsigned NOT NULL, + vid int unsigned NOT NULL, + pos int unsigned NOT NULL, flags char(1) default 1, channel varchar(100) NOT NULL default '', day varchar(20) default '-------', - start int(11) unsigned, - stop int(11) unsigned, + start int unsigned, + stop int unsigned, priority tinyint(2), lifetime tinyint(2), file text, @@ -437,40 +433,35 @@ sub _init { eventid int unsigned default '0', eventstarttime datetime, eventduration int unsigned default '0', - autotimerid int(11) unsigned default '0', + autotimerid int unsigned default '0', checked char(1) default 0, addtime timestamp, PRIMARY KEY(id) ) COMMENT = '$version' |); - $obj->{after_updated} = []; + $self->{after_updated} = []; main::after(sub{ - $obj->{svdrp} = main::getModule('SVDRP'); - unless($obj->{svdrp}) { + $self->{svdrp} = main::getModule('SVDRP'); + unless($self->{svdrp}) { panic ("Couldn't get modul SVDRP"); return 0; } - $obj->{keywords} = main::getModule('KEYWORDS'); - unless($obj->{keywords}) { + $self->{keywords} = main::getModule('KEYWORDS'); + unless($self->{keywords}) { return 0; } - # merge source from channels to enum typ of used DVB cards like S19.2E,S19.2E,T - $obj->{MOD}->{Preferences}->{DVBCardsTyp}->{default} = $obj->_buildDVBCardsTyp(); - $obj->{DVBCardsTyp} = $obj->{MOD}->{Preferences}->{DVBCardsTyp}->{default} - if(!$obj->{DVBCardsTyp} || (length($obj->{DVBCardsTyp}) < 1)); - # import data - $obj->_readData(); + $self->_readData(); # Interval to read timers and put to DB Event->timer( - interval => $obj->{interval}, + interval => $self->{interval}, prio => 6, # -1 very hard ... 6 very low cb => sub{ - $obj->_readData(); + $self->_readData(); } ); return 1; @@ -483,24 +474,27 @@ sub _init { # ------------------ sub saveTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $data = shift || return error('No data defined!'); - $obj->_saveTimer($data); - if($obj->{svdrp}->queue_cmds('COUNT')) { - my $erg = $obj->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos + $self->_saveTimer($data); + if($self->{svdrp}->queue_cmds('COUNT')) { + my $erg = $self->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos + if(!(exists $data->{vid})) { + $data->{vid} = $self->{svdrp}->primary_hosts(); + } # Save shortly this timer in DB if this only a new timer (at) # Very Important for Autotimer! my $pos = $1 if($erg->[1] =~ /^250\s+(\d+)/); if(!(exists $data->{pos}) and $pos) { $data->{pos} = $pos; - $obj->_insert($data); + $self->_insert($data); } event sprintf('Save timer "%s" with id: "%d"', $data->{file}, $pos || 0); - $obj->{changedTimer} = 1; + $self->{changedTimer} = 1; return $erg; } @@ -510,21 +504,21 @@ sub saveTimer { # ------------------ sub _saveTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $data = shift || return error('No data defined!'); - $data->{flags} = ($data->{activ} eq 'y' ? 1 : 0); + $data->{flags} = ($data->{active} eq 'y' ? 1 : 0); $data->{flags} |= ($data->{vps} eq 'y' ? 4 : 0); $data->{file} =~ s/(\r|\n)//sg; # Add Keywords to timer - $data->{aux} = $obj->{keywords}->mergexml($data->{aux},'keywords',$data->{keywords}); + $data->{aux} = $self->{keywords}->mergexml($data->{aux},'keywords',$data->{keywords}); my $file = $data->{file}; $file =~ s/:/|/g; - $obj->{svdrp}->queue_cmds( + $self->{svdrp}->queue_cmds( sprintf("%s %s:%s:%s:%s:%s:%s:%s:%s:%s", $data->{pos} ? "modt $data->{pos}" : "newt", $data->{flags}, @@ -536,19 +530,20 @@ sub _saveTimer { int($data->{lifetime}), $file, ($data->{aux} || '') - ) + ), + $data->{vid} ); } sub _newTimerdefaults { - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $timer = shift; - $timer->{activ} = 'y'; - $timer->{priority} = $obj->{Priority}; - $timer->{lifetime} = $obj->{Lifetime}; + $timer->{active} = 'y'; + $timer->{priority} = $self->{Priority}; + $timer->{lifetime} = $self->{Lifetime}; - if($timer->{vpsstart} && $obj->{usevpstime} eq 'y') { + if($timer->{vpsstart} && $self->{usevpstime} eq 'y') { $timer->{vps} = 'y'; $timer->{day} = $timer->{vpsday}; $timer->{start} = $timer->{vpsstart}; @@ -560,7 +555,7 @@ sub _newTimerdefaults { # ------------------ sub newTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $epgid = shift || 0; @@ -587,8 +582,8 @@ WHERE|; $sql .= sprintf(" eventid in (%s)", join(',' => ('?') x @events)); my $data; - my $sth = $obj->{dbh}->prepare($sql); - if(!$sth->execute($obj->{prevminutes} * 60, $obj->{prevminutes} * 60, $obj->{afterminutes} * 60, @events) + my $sth = $self->{dbh}->prepare($sql); + if(!$sth->execute($self->{prevminutes} * 60, $self->{prevminutes} * 60, $self->{afterminutes} * 60, @events) || !($data = $sth->fetchall_hashref('eventid')) || (scalar keys %{$data} < 1)) { return $console->err(sprintf(gettext("Event '%s' does not exist in the database!"),join(',',@events))); @@ -597,9 +592,9 @@ WHERE|; my $count = 1; foreach my $eventid (keys %{$data}) { $epg = $data->{$eventid}; - $obj->_newTimerdefaults($epg); + $self->_newTimerdefaults($epg); $epg->{action} = 'save' if(scalar keys %{$data} > 1 || $fast ); - $obj->_editTimer($watcher, $console, 0, $epg) if($count < scalar keys %{$data}); + $self->_editTimer($watcher, $console, 0, $epg) if($count < scalar keys %{$data}); $count += 1; } } @@ -612,26 +607,27 @@ WHERE|; start => my_strftime("%H%M",$t), stop => my_strftime("%H%M",$t) }; - $obj->_newTimerdefaults($epg); + $self->_newTimerdefaults($epg); } - $obj->editTimer($watcher, $console, 0, $epg); + $self->editTimer($watcher, $console, 0, $epg); } # ------------------ sub _editTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $timerid = shift || 0; # If timerid the edittimer my $data = shift || 0; # Data for defaults - my $timerData; - if($timerid and not ref $data) { - my $sth = $obj->{dbh}->prepare( + my $default; + if($timerid) { + my $sth = $self->{dbh}->prepare( qq| SELECT SQL_CACHE id, + vid, channel, file, aux, @@ -640,8 +636,9 @@ SELECT SQL_CACHE day, priority, lifetime, - IF(flags & 1,'y','n') as activ, + IF(flags & 1,'y','n') as active, IF(flags & 4,'y','n') as vps, + NOW() between starttime and stoptime AND (flags & 1) as running, (SELECT description FROM EPG as e WHERE t.eventid = e.eventid @@ -653,51 +650,60 @@ WHERE |); if(!$sth->execute($timerid) - || !($timerData = $sth->fetchrow_hashref()) - || (scalar keys %{$timerData} < 1)) { + || !($default = $sth->fetchrow_hashref()) + || (scalar keys %{$default} < 1)) { return $console->err(sprintf(gettext("Timer '%s' does not exist in the database!"),$timerid)); } - if(defined $timerData->{aux}) { - $timerData->{aux} =~ s/(\r|\n)//sig; + if(not ref $data + && defined $default->{aux} + && $self->{keywords}->{active} eq 'y') { + $default->{aux} =~ s/(\r|\n)//sig; - my $xml = $obj->{keywords}->parsexml($timerData->{aux}); -# $timerData->{keywords} = $xml->{'autotimer'} + my $xml = $self->{keywords}->parsexml($default->{aux}); +# $default->{keywords} = $xml->{'autotimer'} # if($xml && defined $xml->{'autotimer'} ); - $timerData->{keywords} = $xml->{'keywords'} + $default->{keywords} = $xml->{'keywords'} if($xml && defined $xml->{'keywords'} ); } - } elsif (ref $data eq 'HASH') { - $timerData = $data; + } + if (ref $data eq 'HASH') { + $data->{id} = $default->{id} || 0; + $data->{aux} = $default->{aux} || ''; + $data->{running} = $default->{running} || 0; + $default = $data; } my $modC = main::getModule('CHANNELS'); my $con = $console->typ eq "CONSOLE"; + my $vlist = $self->{svdrp}->enum_onlinehosts(); my $questions = [ - 'id' => { - typ => 'hidden', - def => $timerData->{id} || 0, - }, - 'activ' => { + 'active' => { typ => 'confirm', - def => $timerData->{activ}, + def => $default->{active}, msg => gettext('Enable this timer'), }, 'vps' => { typ => 'confirm', - def => $timerData->{vps}, + def => $default->{vps}, msg => gettext('Use PDC time to control timer'), }, 'file' => { msg => gettext('Title of recording'), - def => $timerData->{file}, + def => $default->{file}, req => gettext("This is required!"), }, + 'vid' => { + typ => scalar @$vlist > 1 ? 'list' : 'hidden', + def => $default->{vid} || $self->{svdrp}->primary_hosts(), + choices => $vlist, + msg => gettext('Which video disk recorder should record'), + }, 'channel' => { typ => 'list', - def => $con ? $modC->ChannelToPos($timerData->{channel}) : $timerData->{channel}, - choices => $con ? $modC->ChannelArray('Name') : $modC->ChannelWithGroup('Name,Id'), + def => $con ? $modC->ChannelToPos($default->{channel}) : $default->{channel}, + choices => $con ? $modC->ChannelArray('name') : $modC->ChannelWithGroup('c.name,c.id'), msg => gettext('Which channel should recorded'), req => gettext("This is required!"), check => sub{ @@ -705,8 +711,8 @@ WHERE return undef, gettext("This is required!") unless($value); - my $ch = $modC->ToCID($value); - return undef, sprintf(gettext("This channel '%s' does not exist!"),$value) + my $ch = $modC->ToCID($value,$data->{vid}); + return undef, sprintf(gettext("Channel '%s' does not exist on video disk recorder %s!"),$value, $self->{svdrp}->hostname($data->{vid})) unless($ch); return $ch; }, @@ -715,7 +721,7 @@ WHERE typ => $con ? 'string' : 'date', def => sub{ # Convert day from VDR format to locale format - my $value = $timerData->{day}; + my $value = $default->{day}; if($value and $value =~ /^\d{4}\-\d{2}-\d{2}$/) { Date_Init("Language=English"); my $d = ParseDate($value); @@ -753,7 +759,7 @@ WHERE 'start' => { typ => 'string', def => sub{ - return fmttime($timerData->{start}); + return fmttime($default->{start}); }, msg => gettext("Start time in format 'HH:MM'"), check => sub{ @@ -772,7 +778,7 @@ WHERE 'stop' => { typ => 'string', def => sub{ - return fmttime($timerData->{stop}); + return fmttime($default->{stop}); }, msg => gettext("End time in format 'HH:MM'"), check => sub{ @@ -791,7 +797,7 @@ WHERE 'priority' => { typ => 'integer', msg => sprintf(gettext('Priority (%d ... %d)'),0,$console->{USER}->{MaxPriority} ? $console->{USER}->{MaxPriority} : 99 ), - def => int($timerData->{priority}), + def => int($default->{priority}), check => sub{ my $value = shift || 0; if($value =~ /^\d+$/sig and $value >= 0 and $value < 100) { @@ -807,7 +813,7 @@ WHERE 'lifetime' => { typ => 'integer', msg => sprintf(gettext('Lifetime (%d ... %d)'),0,$console->{USER}->{MaxLifeTime} ? $console->{USER}->{MaxLifeTime} : 99 ), - def => int($timerData->{lifetime}), + def => int($default->{lifetime}), check => sub{ my $value = shift || 0; if($value =~ /^\d+$/sig and $value >= 0 and $value < 100) { @@ -821,18 +827,19 @@ WHERE }, }, 'keywords' => { - typ => $obj->{keywords}->{active} eq 'y' ? 'string' : 'hidden', - def => $timerData->{keywords}, + typ => $self->{keywords}->{active} eq 'y' ? 'string' : 'hidden', + def => $default->{keywords}, msg => gettext('Add keywords to recording'), - }, - 'aux' => { - typ => 'hidden', - def => $timerData->{aux}, + check => sub{ + my $value = shift || 0; + $value =~ s/(\r|\n)/,/sg; + return $value; + } }, 'description' => { msg => gettext('Description'), - typ => $timerData->{description} ? 'textfield' : 'hidden', - def => $timerData->{description}, + typ => $default->{description} ? 'textfield' : 'hidden', + def => $default->{description}, readonly => 1 } ]; @@ -842,10 +849,22 @@ WHERE : gettext('New timer')), $questions, $data); if(ref $datasave eq 'HASH') { + my ($oldvid,$pos); if($timerid) { - $datasave->{pos} = $obj->getPos($timerid); + ($oldvid,$pos) = $self->getPos($timerid); + if($datasave->{vid} == $oldvid) { + $datasave->{pos} = $pos; + $oldvid = undef; + } + } + # Save timer on video disk recorder + $self->_saveTimer($datasave); + # Remove timer from old video disk recorder + if($pos && $oldvid) { + $self->{svdrp}->queue_cmds(sprintf("modt %d off", $pos), $oldvid) + if($data->{running}); + $self->{svdrp}->queue_cmds(sprintf("delt %d", $pos), $oldvid) } - $obj->_saveTimer($datasave); return 1; } return 0; @@ -853,15 +872,15 @@ WHERE # ------------------ sub editTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $timerid = shift; # If timerid the edittimer + my $timerid = shift; # id of present timer, then edit this timer my $data = shift; # Data for defaults - if($obj->_editTimer($watcher,$console,$timerid,$data) - && $obj->{svdrp}->queue_cmds('COUNT')) { - my $erg = $obj->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos + if($self->_editTimer($watcher,$console,$timerid,$data) + && $self->{svdrp}->queue_cmds('COUNT')) { + my $erg = $self->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos my $error; foreach my $zeile (@$erg) { if($zeile =~ /^(\d{3})\s+(.+)/) { @@ -885,9 +904,9 @@ sub editTimer { ); $console->err($erg); } - $obj->{changedTimer} = 1; + $self->{changedTimer} = 1; - if($obj->_readData($watcher,$console)) { + if($self->_readData($watcher,$console)) { $console->redirect({url => '?cmd=tlist', wait => 1}) if(!$error && $console->typ eq 'HTML'); } @@ -897,7 +916,7 @@ sub editTimer { # ------------------ sub deleteTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $timerid = shift || return $console->err(gettext("No timer defined for deletion! Please use tdelete 'tid'.")); # If timerid the edittimer @@ -905,8 +924,8 @@ sub deleteTimer { my @timers = split(/[^0-9a-f]/, $timerid); - my $sql = sprintf('SELECT SQL_CACHE id,pos,file,channel,starttime,flags & 1 and NOW() between starttime and stoptime FROM TIMERS where id in (%s) ORDER BY pos desc', join(',' => ('?') x @timers)); - my $sth = $obj->{dbh}->prepare($sql); + my $sql = sprintf('SELECT SQL_CACHE id,vid,pos,file,channel,starttime,flags & 1 and NOW() between starttime and stoptime FROM TIMERS where id in (%s) ORDER BY pos desc', join(',' => ('?') x @timers)); + my $sth = $self->{dbh}->prepare($sql); $sth->execute(@timers) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $data = $sth->fetchall_arrayref(); @@ -915,11 +934,12 @@ sub deleteTimer { foreach my $d (@$data) { my $t = { id => $d->[0], - pos => $d->[1], - file => $d->[2], - channel => $d->[3], - start => $d->[4], - running => $d->[5] + vid => $d->[1], + pos => $d->[2], + file => $d->[3], + channel => $d->[4], + start => $d->[5], + running => $d->[6] }; if(ref $console and $console->{TYP} eq 'CONSOLE') { @@ -941,9 +961,9 @@ sub deleteTimer { ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - $obj->{svdrp}->queue_cmds(sprintf("modt %d off", $t->{pos})) + $self->{svdrp}->queue_cmds(sprintf("modt %d off", $t->{pos}), $t->{vid}) if($t->{running}); - $obj->{svdrp}->queue_cmds(sprintf("delt %d", $t->{pos})); + $self->{svdrp}->queue_cmds(sprintf("delt %d", $t->{pos}), $t->{vid}); # Delete timer from request, if found in database my $i = 0; @@ -961,14 +981,14 @@ sub deleteTimer { join('\',\'',@timers))) if(scalar @timers); - if($obj->{svdrp}->queue_cmds('COUNT')) { - my $erg = $obj->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos - $console->msg($erg, $obj->{svdrp}->err) + if($self->{svdrp}->queue_cmds('COUNT')) { + my $erg = $self->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos + $console->msg($erg, $self->{svdrp}->err) if(ref $console); sleep(1); - if($obj->_readData($watcher,$console)) { + if($self->_readData($watcher,$console)) { $console->redirect({url => '?cmd=tlist', wait => 1}) if(ref $console and $console->typ eq 'HTML'); } @@ -982,15 +1002,15 @@ sub deleteTimer { # ------------------ sub toggleTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $timerid = shift || return $console->err(gettext("No timer defined to toggle! Please use ttoggle 'id'.")); # If timerid the edittimer my @timers = split(/[^0-9a-f]/, $timerid); - my $sql = sprintf('SELECT SQL_CACHE id,pos,file,flags,starttime,stoptime FROM TIMERS where id in (%s) ORDER BY pos desc', join(',' => ('?') x @timers)); - my $sth = $obj->{dbh}->prepare($sql); + my $sql = sprintf('SELECT SQL_CACHE id,vid,pos,file,flags,starttime,stoptime FROM TIMERS where id in (%s) ORDER BY pos desc', join(',' => ('?') x @timers)); + my $sth = $self->{dbh}->prepare($sql); $sth->execute(@timers) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $data = $sth->fetchall_arrayref(); @@ -1000,11 +1020,12 @@ sub toggleTimer { foreach my $d (@$data) { my $t = { id => $d->[0], - pos => $d->[1], - file => $d->[2], - flags => $d->[3], - start => $d->[4], - stop => $d->[5] + vid => $d->[1], + pos => $d->[2], + file => $d->[3], + flags => $d->[4], + start => $d->[5], + stop => $d->[6] }; # Build query for all timers with possible collisions @@ -1020,7 +1041,7 @@ sub toggleTimer { ( $console->{USER} && $console->{USER}->{Name} ? sprintf(' from user: %s', $console->{USER}->{Name}) : "" ) ); - $obj->{svdrp}->queue_cmds("modt $t->{pos} $status"); # Sammeln der Kommandos + $self->{svdrp}->queue_cmds("modt $t->{pos} $status",$t->{vid}); # Sammeln der Kommandos # Delete timer from request, if found in database my $i = 0; @@ -1039,13 +1060,13 @@ sub toggleTimer { join('\',\'',@timers))) if(scalar @timers); - if($obj->{svdrp}->queue_cmds('COUNT')) { + if($self->{svdrp}->queue_cmds('COUNT')) { - my $erg = $obj->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos - $console->msg($erg, $obj->{svdrp}->err) + my $erg = $self->{svdrp}->queue_cmds("CALL"); # Aufrufen der Kommandos + $console->msg($erg, $self->{svdrp}->err) if(ref $console and $console->typ ne 'AJAX'); - if($obj->_readData($watcher, $console)) { + if($self->_readData($watcher, $console)) { $console->redirect({url => '?cmd=tlist', wait => 1}) if(ref $console and $console->typ eq 'HTML'); } @@ -1055,7 +1076,7 @@ sub toggleTimer { # { "data" : [ [ 5, 1, 0, 0 ], .... ] } my $sql = sprintf('SELECT SQL_CACHE id, flags & 1 as Active, NOW() between starttime and stoptime as Running, Collision from TIMERS where id in (%s) %s', join(',' => ('?') x @success),$ref); - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute(@success) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $erg = $sth->fetchall_arrayref(); @@ -1082,7 +1103,7 @@ sub _insert { # change pos to channelid, because change to telnet reader if(index($timer->{channel}, '-') < 0) { - $timer->{channel} = main::getModule('CHANNELS')->ToCID($timer->{channel}) + $timer->{channel} = main::getModule('CHANNELS')->ToCID($timer->{channel},$timer->{vid}) or return error(sprintf("Couldn't get channel from this timer: %d '%s'", $timer->{pos}, $timer->{channel})); } @@ -1113,11 +1134,12 @@ sub _insert { my $sth = $self->{dbh}->prepare( q|REPLACE INTO TIMERS VALUES - (?,?,?,?,?,?,?,?,?,?,?,FROM_UNIXTIME(?), FROM_UNIXTIME(?),0,?,?,?,?,?,NOW()) + (?,?,?,?,?,?,?,?,?,?,?,?,FROM_UNIXTIME(?), FROM_UNIXTIME(?),0,?,?,?,?,?,NOW()) |); - my $id = md5_hex($timer->{channel} . $nexttime->{start} . $nexttime->{stop} ); + my $id = md5_hex($timer->{vid} . $timer->{channel} . $nexttime->{start} . $nexttime->{stop} ); $sth->execute( $id, + $timer->{vid}, $timer->{pos}, $timer->{flags}, $timer->{channel}, @@ -1137,72 +1159,80 @@ q|REPLACE INTO TIMERS VALUES $checked ) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); - $self->{keywords}->insert('timer',$id,$keywords); + $self->{keywords}->insert('timer',$id,$keywords); + + return 1; } # Read data # ------------------ sub _readData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; # Search for correct times - $obj->getCheckTimer() - if($obj->{adjust} eq 'y'); + $self->getCheckTimer() + if($self->{adjust} eq 'y'); my $oldTimers = &getDataByTable('TIMERS'); - $obj->{dbh}->do('DELETE FROM TIMERS'); - $obj->{keywords}->removesource('timer'); - - # read from svdrp - my $tlist = $obj->{svdrp}->command('lstt'); + $self->{dbh}->do('DELETE FROM TIMERS'); + $self->{keywords}->removesource('timer'); my $c = 0; - foreach my $line (@$tlist) { - next if(! $line or $line =~ /^22/); - $line =~ s/^\d+[- ]+\d+\s//sig; - $c++; - my @data = split(':', $line, 9); - if(scalar @data > 2) { - my $timer = { - pos => $c, - flags => $data[0], - channel => $data[1], - day => $data[2], - start => $data[3], - stop => $data[4], - priority=> $data[5], - lifetime=> $data[6], - file => $data[7], - aux => $data[8] - }; - $obj->_insert($timer, 1); - } - } + my $hostlist = $self->{svdrp}->list_hosts(); + # read from svdrp + foreach my $vid (@$hostlist) { + my $tlist = $self->{svdrp}->command('lstt',$vid); + + foreach my $line (@$tlist) { + next unless($line and $line =~ /^250[- ](\d+)/s); + my $pos = $1; + $line =~ s/^\d+[- ]+\d+\s//sig; + my @data = split(':', $line, 9); + if(scalar @data > 2) { + my $timer = { + vid => $vid, + pos => $pos, + flags => $data[0], + channel => $data[1], + day => $data[2], + start => $data[3], + stop => $data[4], + priority=> $data[5], + lifetime=> $data[6], + file => $data[7], + aux => $data[8] + }; + if($self->_insert($timer, 1)) { + $c++; + } + } + } + } # Search for overlapping Timers - $obj->findOverlapping(); + $self->findOverlapping(); # Get timers by Autotimer my $aids = getDataByFields('AUTOTIMER', 'Id'); - $obj->getTimersByAutotimer($aids); + $self->getTimersByAutotimer($aids); # Get new timers by User - if($oldTimers or exists $obj->{changedTimer}) { + if($oldTimers or exists $self->{changedTimer}) { - my $timers = $obj->getNewTimers($oldTimers); - foreach my $timerdata (@$timers) { - event sprintf('New timer "%s" with id: "%d"', $timerdata->{file}, $timerdata->{pos}); + my $timers = $self->getNewTimers($oldTimers); + foreach my $t (@$timers) { + event sprintf('New timer "%s" with id: "%d"', $t->{file}, $t->{pos}); } - $obj->updated() if(scalar @$timers or exists $obj->{changedTimer}); - delete $obj->{changedTimer} if(exists $obj->{changedTimer}); + $self->updated() if(scalar @$timers or exists $self->{changedTimer}); + delete $self->{changedTimer} if(exists $self->{changedTimer}); } - $obj->{REGISTER}++; - if(scalar keys %$oldTimers != $c or $obj->{REGISTER} == 2) { + $self->{REGISTER}++; + if(scalar keys %$oldTimers != $c or $self->{REGISTER} == 2) { # Event to signal we are finish to read event(sprintf('Reread %d timers and written into database!', $c)); } @@ -1216,11 +1246,11 @@ sub _readData { # ------------------ sub readData { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; - if($obj->_readData($watcher,$console)) { + if($self->_readData($watcher,$console)) { $console->redirect({url => '?cmd=tlist', wait => 1}) if(ref $console and $console->typ eq 'HTML'); } @@ -1231,14 +1261,14 @@ sub readData { # ------------------ sub updated { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $cb = shift || 0; my $log = shift || 0; if($cb) { - push(@{$obj->{after_updated}}, [$cb, $log]); + push(@{$self->{after_updated}}, [$cb, $log]); } else { - foreach my $CB (@{$obj->{after_updated}}) { + foreach my $CB (@{$self->{after_updated}}) { next unless(ref $CB eq 'ARRAY'); lg $CB->[1] if($CB->[1]); @@ -1251,7 +1281,7 @@ sub updated { # ------------------ sub list { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $id = shift; @@ -1265,16 +1295,16 @@ sub list { foreach(@timers) { push(@{$term},$_); } } - return $obj->_list($watcher,$console,$search,$term,$params); + return $self->_list($watcher,$console,$search,$term,$params); } # ------------------ sub search { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); - my $text = shift || return $obj->list($watcher,$console); + my $text = shift || return $self->list($watcher,$console); my $params = shift; my $term; @@ -1283,13 +1313,13 @@ sub search { $search = sprintf('AND ( %s )', $query->{query}); foreach(@{$query->{term}}) { push(@{$term},$_); } - return $obj->_list($watcher,$console,$search,$term,$params); + return $self->_list($watcher,$console,$search,$term,$params); } # ------------------ sub _list { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift; my $console = shift; my $search = shift || ''; @@ -1312,8 +1342,8 @@ sub _list { SELECT SQL_CACHE t.id as \'$f{'id'}\', t.flags as \'$f{'flags'}\', - c.Name as \'$f{'channel'}\', - c.Pos as __pos, + c.name as \'$f{'channel'}\', + c.hash as __pos, UNIX_TIMESTAMP(t.starttime) as \'$f{'day'}\', DATE_FORMAT(t.starttime, '%H:%i') as \'$f{'start'}\', DATE_FORMAT(t.stoptime, '%H:%i') as \'$f{'stop'}\', @@ -1334,7 +1364,8 @@ FROM $table WHERE t.stoptime > NOW() - AND t.channel = c.Id + AND t.channel = c.id + AND t.vid = c.vid $search ORDER BY t.starttime @@ -1345,7 +1376,7 @@ ORDER BY my $limit = $console->{cgi} && $console->{cgi}->param('limit') ? CORE::int($console->{cgi}->param('limit')) : 0; if($limit > 0) { # Query total count of rows - my $rsth = $obj->{dbh}->prepare($sql); + my $rsth = $self->{dbh}->prepare($sql); $rsth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$rsth->errstr); $rows = $rsth->rows; @@ -1363,7 +1394,7 @@ ORDER BY } unless($sth) { - $sth = $obj->{dbh}->prepare($sql); + $sth = $self->{dbh}->prepare($sql); $sth->execute(@{$term}) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); $rows = $sth->rows unless($rows); @@ -1383,17 +1414,13 @@ ORDER BY $_->[4] = datum($_->[4],'weekday'); } @$erg; - ($keywords,$keywordmax,$keywordmin) = $obj->{keywords}->list('timer',$md5); + ($keywords,$keywordmax,$keywordmin) = $self->{keywords}->list('timer',$md5); unshift(@$erg, $fields); } - my @DVBCARDS = split(',',$obj->{DVBCardsTyp}); - my $cards = scalar @DVBCARDS; - $console->setCall('tlist'); $console->table($erg, { - cards => $cards, capacity => main::getModule('RECORDS')->{CapacityFree}, keywords => $keywords, keywordsmax => $keywordmax, @@ -1405,7 +1432,7 @@ ORDER BY # ------------------ sub getTimerById { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $tid = shift || return error('No id defined!'); my $sql = qq| @@ -1427,11 +1454,12 @@ FROM TIMERS as t, CHANNELS as c WHERE - t.channel = c.Id + t.channel = c.id + AND t.vid = c.vid and t.id = ? |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($tid) or return error(sprintf("Timer '%s' does not exist in the database!",$tid)); return $sth->fetchrow_hashref(); @@ -1440,7 +1468,7 @@ WHERE # ------------------ sub getTimerByPos { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $tid = shift || return error('No id defined!'); my $sql = qq| @@ -1462,11 +1490,12 @@ FROM TIMERS as t, CHANNELS as c WHERE - t.channel = c.Id + t.channel = c.id + AND t.vid = c.vid and t.pos = ? |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($tid) or return error(sprintf("Timer '%s' does not exist in the database!",$tid)); return $sth->fetchrow_hashref(); @@ -1474,17 +1503,17 @@ WHERE # ------------------ sub getRunningTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $rowname = shift || 'id'; my $sql = "SELECT SQL_CACHE $rowname from TIMERS where NOW() between starttime and stoptime AND (flags & 1)"; - my $erg = $obj->{dbh}->selectall_hashref($sql, $rowname); + my $erg = $self->{dbh}->selectall_hashref($sql, $rowname); return $erg; } # ------------------ sub getNewTimers { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $oldTimers = shift || return; my $ret = []; @@ -1499,12 +1528,10 @@ sub getNewTimers { # ------------------ sub getCheckTimer { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $sql = qq| -SELECT SQL_CACHE t.id as id,t.pos as pos, t.flags as flags,t.channel as channel, - t.priority as priority, t.lifetime as lifetime, - t.file as file, t.aux as aux, - t.start as timerstart,t.stop as timerstop, +SELECT SQL_CACHE t.id, t.vid, t.pos, t.flags, t.channel, t.priority, t.lifetime, + t.file, t.aux, t.start as timerstart,t.stop as timerstop, UNIX_TIMESTAMP(e.starttime) as starttime, UNIX_TIMESTAMP(e.starttime) + e.duration as stoptime, @@ -1525,7 +1552,7 @@ SELECT SQL_CACHE t.id as id,t.pos as pos, t.flags as flags,t.channel as channel ) AND SUBSTRING_INDEX( t.file , '~', 1 ) LIKE CONCAT('%', e.title ,'%') |; - my $erg = $obj->{dbh}->selectall_hashref($sql, 'id'); + my $erg = $self->{dbh}->selectall_hashref($sql, 'id'); foreach my $t (keys %$erg) { my %tt; @@ -1546,8 +1573,9 @@ SELECT SQL_CACHE t.id as id,t.pos as pos, t.flags as flags,t.channel as channel # Format parameterhash for saveTimer my $tt = { + vid => $erg->{$t}->{vid}, pos => $erg->{$t}->{pos}, - activ => (($erg->{$t}->{flags} & 1) ? 'y' : 'n'), + active => (($erg->{$t}->{flags} & 1) ? 'y' : 'n'), vps => (($erg->{$t}->{flags} & 4) ? 'y' : 'n'), channel => $erg->{$t}->{channel}, file => $erg->{$t}->{file}, @@ -1566,7 +1594,7 @@ SELECT SQL_CACHE t.id as id,t.pos as pos, t.flags as flags,t.channel as channel fmttime($erg->{$t}->{timerstart}), fmttime($erg->{$t}->{timerstop}), fmttime($tt->{start}),fmttime($tt->{stop})); - $obj->saveTimer($tt); + $self->saveTimer($tt); } return $erg; } @@ -1574,27 +1602,28 @@ SELECT SQL_CACHE t.id as id,t.pos as pos, t.flags as flags,t.channel as channel # ------------------ sub getPos { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $tid = shift || return error('No id defined!'); my $sql = qq| -SELECT SQL_CACHE - pos from TIMERS as t -where +SELECT SQL_CACHE + vid, pos + from TIMERS as t + where t.id = ? |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($tid) or return error(sprintf("Timer '%s' does not exist in the database!",$tid)); my $erg = $sth->fetchrow_hashref(); - return $erg ? $erg->{pos} : 0; + return $erg ? ($erg->{vid}, $erg->{pos}) : undef; } # ------------------ sub getEpgDesc { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $tid = shift || return error('No id defined!'); my $sql = qq| @@ -1606,7 +1635,7 @@ where t.id = ? |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($tid) or return error(sprintf("Timer '%s' does not exist in the database!",$tid)); my $erg = $sth->fetchrow_hashref(); @@ -1614,54 +1643,31 @@ where } # ------------------ -sub _buildDVBCardsTyp { -# ------------------ - my $self = shift || return error('No object defined!'); - - my @DVBCardsTyp; - - my $sql = qq| - select Source from CHANNELS -group by - Source -ORDER BY - Source asc -|; - my $sth = $self->{dbh}->prepare($sql); - $sth->execute() - or return error sprintf("Couldn't execute query: %s.",$sth->errstr); - - my $result = $sth->fetchall_arrayref(); - foreach my $source (@$result ) { - push(@DVBCardsTyp,$source->[0]); - } - my $cards = join(',',@DVBCardsTyp); - lg sprintf("Founded sources of channels %s", $cards); - return $cards; -} - -# ------------------ sub findOverlapping { # ------------------ my $self = shift || return error('No object defined!'); my $CARDS; - my @DVBCARDS = split(',',$self->{DVBCardsTyp}); - my $cardid = 1; - - foreach my $source (@DVBCARDS) { - $source =~ s/^\s+//; # no leading white space - $source =~ s/\s+$//; # no trailing white space - - unshift(@{$CARDS},{ - Source => $source, - tid => undef, - stoptime => 0, - cardID => $cardid ++ - #HOST => '', - #CA => '' - } - ); + my $hostlist = $self->{svdrp}->list_hosts(); + # read from svdrp + foreach my $vid (@$hostlist) { + my $cards = $self->{svdrp}->cards($vid); + my @DVBCARDS = split(',',$cards); + my $cardid = 1; + foreach my $source (@DVBCARDS) { + $source =~ s/^\s+//; # no leading white space + $source =~ s/\s+$//; # no trailing white space + + unshift(@{$CARDS},{ + Source => $source, + tid => undef, + stoptime => 0, + cardID => $cardid ++, + VDR => $vid, + #CA => '' + } + ); + } } # for my $ca (@{$CARDS}) { @@ -1673,11 +1679,12 @@ sub findOverlapping { use constant fstop => 2; use constant fpriority => 3; use constant fCardOnly => 4; - use constant fSource => 5; - use constant fTID => 6; - use constant fCardUsed => 7; - use constant fCollision => 8; - use constant fFile => 9; + use constant fVDR => 5; + use constant fSource => 6; + use constant fTID => 7; + use constant fCardUsed => 8; + use constant fCollision => 9; + use constant fFile => 10; my $sql = qq| SELECT t.id, @@ -1685,7 +1692,8 @@ SELECT t.id, UNIX_TIMESTAMP(t.stoptime), t.priority, c.CA, - c.Source, + c.vid, + c.source, c.TID, NULL, NULL, @@ -1694,7 +1702,8 @@ FROM TIMERS as t, CHANNELS as c WHERE (t.flags & 1) - AND t.channel = c.Id + AND t.channel = c.id + AND t.vid = c.vid ORDER BY t.starttime asc, t.priority desc @@ -1713,7 +1722,7 @@ ORDER BY } for my $ca (@{$CARDS}) { if(!($ti->[fCardUsed]) # If'nt assign - # && $ca->{Host} eq $ti->[fHost] # Same host + && $ca->{VDR} eq $ti->[fVDR] # Same host && $ca->{Source} eq $ti->[fSource] # Same source && (!$CardOnly || $ca->{cardID} == $CardOnly) # if CA has DVB Card number && (!$ca->{tid} # Unused transponder @@ -1741,7 +1750,7 @@ ORDER BY foreach my $co (@{$timer}) { if($ti->[fid] ne $co->[fid] && $co->[fCardUsed] # used card -# && ($co->[Host] eq $ti->[fHost]) #Same Host + && ($co->[fVDR] eq $ti->[fVDR]) #Same Host && ($co->[fSource] eq $ti->[fSource]) #Same Source && ((($ti->[fstart] >= $co->[fstart]) # start >= start && ($ti->[fstart] <= $co->[fstop])) # start <= stop @@ -1781,15 +1790,16 @@ ORDER BY # ------------------ sub checkOverlapping { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $data = shift || return error('No data defined!'); my $starttime = $data->{starttime}; my $stoptime = $data->{stoptime}; - my $transponder = $data->{transponderid}; + my $transponder = $data->{tid}; my $source = $data->{source}; - my $Priority = $data->{priority} || $obj->{Priority}; - my $tid = $data->{id} || 0; + my $Priority = $data->{priority} || $self->{Priority}; + my $timer = $data->{id} || 0; + my $vid = $data->{vid}; my $sql = qq| SELECT SQL_CACHE @@ -1805,17 +1815,18 @@ WHERE OR (t.stoptime between ? AND ?)) AND t.id != ? AND (t.flags & 1) - AND t.channel = c.Id + AND t.channel = c.id + AND t.vid = c.vid AND c.TID != ? AND LEFT(c.Source,1) = ? ORDER BY t.priority desc |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute($starttime,$stoptime, $starttime,$stoptime, $starttime,$stoptime, - $tid,$transponder,$source) + $timer,$transponder,$source) or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $result = $sth->fetchall_arrayref(); @@ -1856,68 +1867,31 @@ ORDER BY } } - my @DVBCARDS = split(',',$obj->{DVBCardsTyp}); - my $cards = scalar @DVBCARDS; + my $howmany = 1; + my $cards = $self->{svdrp}->cards($vid); + if($cards) { + my @DVBCARDS = split(',',$self->{svdrp}->cards($vid)); + $howmany = scalar @DVBCARDS; + } - if(scalar(@$coltext) > ($cards - 1)) { + if(scalar(@$coltext) > ($howmany - 1)) { return $coltext; } } } -# ------------------ -sub getNextTimer { -# ------------------ - my $obj = shift || return error('No object defined!'); - - my $erg = $obj->{svdrp}->command('NEXT abs'); - my @eerg = grep(/^250/, @$erg); - if(scalar @eerg and my ($errcode, $nextTimer, $zeit) = split(/\s+/, $eerg[0])) { - return if( - ! $nextTimer - or $zeit < time - or (ref $obj->{NextTimerEvent} and $obj->{NextTimerEvent}->at == $zeit) - ); - - my $timer = $obj->getTimerByPos($nextTimer); - - $obj->{NextTimerEvent} = Event->timer( - at => $zeit, - data => $timer, - hard => 1, - repeat => 0, - prio => 2, # -1 very hard ... 6 very low - cb => sub{ - my $event = shift; - my $watcher = $event->w; - my $data = $watcher->data; - - my $modR = main::getModule('REPORT'); - $modR->news( - sprintf(gettext("Timer title '%s' has started the recording!"), $data->{file}), - sprintf(gettext("on channel: %s to %s"), $data->{channel}, fmttime($data->{stop})), - 'tedit', - $data->{id}, - 'harmless' - ); - $watcher->cancel; - }, - ); - } -} - # Find EPG to selected timer # ------------------ sub _getNextEpgId { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $timer = shift || return error('No data defined!'); my $e; my @file = split('~', $timer->{file}); my $timemode = ($timer->{flags} & 4) ? 'vpstime' : 'starttime'; if(scalar @file >= 2) { # title and subtitle defined - my $sth = $obj->{dbh}->prepare(sprintf(qq| + my $sth = $self->{dbh}->prepare(sprintf(qq| SELECT SQL_CACHE eventid,%s as starttime,duration from EPG WHERE channel_id = ? @@ -1937,7 +1911,7 @@ sub _getNextEpgId { $e = $sth->fetchrow_hashref(); } else { - my $sth = $obj->{dbh}->prepare(sprintf(qq| + my $sth = $self->{dbh}->prepare(sprintf(qq| SELECT SQL_CACHE eventid,%s as starttime,duration from EPG WHERE channel_id = ? @@ -1964,11 +1938,11 @@ sub _getNextEpgId { # The following subroutines is stolen from vdradmind and vdradmin-0.97-am # Thanks on Cooper and Thomas for this great work! -# $obj->getNextTime('MDMDFSS', 1300, 1200) +# $self->getNextTime('MDMDFSS', 1300, 1200) # ------------------ sub getNextTime { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $dor = shift || return error('No day defined!'); my $start = shift || return error('No start time defined!'); my $stop = shift || return error('No stop time defined!'); @@ -2046,15 +2020,15 @@ sub getNextTime { # ------------------ # Name: getTimersByAutotimer # Descr: Routine group Autotimer to Timers. -# Usage: $hash = $obj->getTimersByAutotimer([$aid, $aid, $aid, ...]); +# Usage: $hash = $self->getTimersByAutotimer([$aid, $aid, $aid, ...]); # ------------------ sub getTimersByAutotimer { - my $obj = shift || return error('No object defined!'); - my $aids = shift || return $obj->{AIDS}; + my $self = shift || return error('No object defined!'); + my $aids = shift || return $self->{AIDS}; - $obj->{AIDS} = {}; + $self->{AIDS} = {}; for my $aid (@$aids) { - $obj->{AIDS}->{$aid} = { + $self->{AIDS}->{$aid} = { allTimer => [], activeTimer => [], deactiveTimer => [], @@ -2062,28 +2036,11 @@ sub getTimersByAutotimer { my $erg = getDataBySearch('TIMERS', 'autotimerid = ?', $aid); map { my $type = ($_->[1] ? 'activeTimer' : 'deactiveTimer'); - push(@{$obj->{AIDS}->{$aid}->{$type}}, $_->[0]); - push(@{$obj->{AIDS}->{$aid}->{allTimer}}, $_->[0]); + push(@{$self->{AIDS}->{$aid}->{$type}}, $_->[0]); + push(@{$self->{AIDS}->{$aid}->{allTimer}}, $_->[0]); } @$erg; } - return $obj->{AIDS}; -} - -# ------------------ -# Name: getRootDirs -# Descr: Get first root dir's. -# Usage: $hash = $obj->getRootDirs([$count]); -# ------------------ -sub getRootDirs { - my $obj = shift || return error('No object defined!'); - my $count = shift || 1; - my $sql = "SELECT SQL_CACHE distinct SUBSTRING_INDEX(file,'~',$count) from TIMERS;"; - my $erg = $obj->{dbh}->selectall_arrayref($sql); - my @ret; - for(@$erg) { - push(@ret, $_->[0]); - } - return \@ret; + return $self->{AIDS}; } sub my_mktime { @@ -2106,7 +2063,7 @@ sub my_strftime { # ------------------ sub suggest { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $watcher = shift || return error('No watcher defined!'); my $console = shift || return error('No console defined!'); my $search = shift; @@ -2126,7 +2083,7 @@ sub suggest { file LIMIT 25 |; - my $sth = $obj->{dbh}->prepare($sql); + my $sth = $self->{dbh}->prepare($sql); $sth->execute('%'.$search.'%') or return error sprintf("Couldn't execute query: %s.",$sth->errstr); my $result = $sth->fetchall_arrayref(); diff --git a/lib/XXV/MODULES/XMLTV.pm b/lib/XXV/MODULES/XMLTV.pm index b3ed74b..f5a5388 100644 --- a/lib/XXV/MODULES/XMLTV.pm +++ b/lib/XXV/MODULES/XMLTV.pm @@ -153,13 +153,14 @@ sub _init { id int unsigned auto_increment NOT NULL, active enum('y', 'n') default 'n', xmltvname varchar(256) default NULL, + vid int unsigned NOT NULL default '1', channel varchar(64) NOT NULL, template enum('y', 'n') default 'n', updateinterval enum('e', 'd', 'w') default 'e', source text NOT NULL, updated datetime NOT NULL default '0000-00-00 00:00:00', PRIMARY KEY (id), - UNIQUE KEY (channel) + UNIQUE KEY (vid, channel) ) COMMENT = '$version' |); @@ -624,10 +625,10 @@ sub _insert { # ------------------ sub _updateTime { # ------------------ - my $obj = shift || return error('No object defined!'); + my $self = shift || return error('No object defined!'); my $id = shift || return error ('No data defined!'); - my $sth = $obj->{dbh}->prepare('UPDATE XMLTV SET updated=NOW() where id=?'); + my $sth = $self->{dbh}->prepare('UPDATE XMLTV SET updated=NOW() where id=?'); return $sth->execute($id); } diff --git a/lib/XXV/OUTPUT/Html.pm b/lib/XXV/OUTPUT/Html.pm index 429ac4e..0bd2473 100644 --- a/lib/XXV/OUTPUT/Html.pm +++ b/lib/XXV/OUTPUT/Html.pm @@ -863,7 +863,7 @@ sub _proxy { if ($fd == $handle) { do { $r = 0; - $bytes = sysread( $handle, $buf, 1500 ); + $bytes = sysread( $handle, $buf, 4096 ); if($bytes) { $tousage += $bytes; $peer = $streamdev->peername; @@ -873,14 +873,14 @@ sub _proxy { } # lg(sprintf("Read host bytes %d (%d)",$bytes,$r)); } while $r && $bytes > 0; - if (!$peer || $tousage < -100000 || $tousage > 100000) { + if (!$peer || $tousage < -1000000 || $tousage > 1000000) { $bExit = 2; } } elsif ($fd == $streamdev) { do { $r = 0; - $bytes = sysread( $streamdev, $buf, 1500 ); + $bytes = sysread( $streamdev, $buf, 4096 ); if($bytes) { $fromusage += $bytes; my $peer = $handle->peername; @@ -889,7 +889,7 @@ sub _proxy { $fromusage -= $r if($r); } } while $r && $bytes > 0; - if ($fromusage < -100000 || $fromusage > 100000) { + if ($fromusage < -1000000 || $fromusage > 1000000) { $bExit = 1; } } else { |
