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 | |
| 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)
| -rw-r--r-- | Makefile | 2 | ||||
| -rwxr-xr-x | bin/xxvd | 1 | ||||
| -rw-r--r-- | contrib/create-database.sql | 2 | ||||
| -rwxr-xr-x | contrib/update-xxv | 4 | ||||
| -rw-r--r-- | contrib/upgrade-xxv-db.sql | 23 | ||||
| -rw-r--r-- | html/clist.tmpl | 14 | ||||
| -rw-r--r-- | html/help.tmpl | 29 | ||||
| -rw-r--r-- | html/ulist.tmpl | 2 | ||||
| -rw-r--r-- | html/vdrlist.tmpl | 41 | ||||
| -rw-r--r-- | html/widgets/remote.tmpl | 53 | ||||
| -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 | ||||
| -rw-r--r-- | locale/de.po | 1233 | ||||
| -rw-r--r-- | locale/de/LC_MESSAGES/xxv.mo | bin | 79256 -> 81706 bytes |
26 files changed, 2991 insertions, 2003 deletions
@@ -4,7 +4,7 @@ # $Id$ XXV = xxv -VERSION = 1.2 +VERSION = 1.3 ### The name of the distribution archive: @@ -47,7 +47,6 @@ my $VERSION = '1.3'; my $VDRVERSION = 0; my $DBVERSION = 0; my $CLEANUP; -my $DBCACHE = {}; my $AFTER = [0 ... 50]; my $killer = 0; my $version = 0; diff --git a/contrib/create-database.sql b/contrib/create-database.sql index 8c31b90..91ffa08 100644 --- a/contrib/create-database.sql +++ b/contrib/create-database.sql @@ -14,7 +14,7 @@ use xxv; -- USR=username -- The first line is useful for granting access to user xxv on all computers in a network. -/* grant all privileges on xxv.* to username@'%' IDENTIFIED BY 'password'; */ +-- grant all privileges on xxv.* to username@'%' IDENTIFIED BY 'password'; -- -- Grant access to user xxv on the local machine with password 'xxv' grant all privileges on xxv.* to xxv@localhost IDENTIFIED BY 'xxv'; diff --git a/contrib/update-xxv b/contrib/update-xxv index b31388e..a611e4f 100755 --- a/contrib/update-xxv +++ b/contrib/update-xxv @@ -18,11 +18,11 @@ # Increment the version number each time the database changes! # -actualVersion=29 +actualVersion=30 # Specify tables to export before and import after update # -tables='AUTOTIMER CHRONICLE MEDIALIB_ACTORS MEDIALIB_VIDEODATA MEDIALIB_VIDEOGENRE MOVETIMER USER XMLTV' +tables='AUTOTIMER CHRONICLE MEDIALIB_ACTORS MEDIALIB_VIDEODATA MEDIALIB_VIDEOGENRE MOVETIMER USER XMLTV RECORDER' showTitle() { diff --git a/contrib/upgrade-xxv-db.sql b/contrib/upgrade-xxv-db.sql index ebcf781..5cbf4a4 100644 --- a/contrib/upgrade-xxv-db.sql +++ b/contrib/upgrade-xxv-db.sql @@ -128,12 +128,28 @@ CREATE TABLE IF NOT EXISTS `MEDIALIB_VIDEOGENRE` ( CREATE TABLE IF NOT EXISTS `MOVETIMER` ( `id` int(10) unsigned NOT NULL auto_increment, + `sourcevid` int(10) unsigned NOT NULL default '1', `source` varchar(64) NOT NULL, + `destinationvid` int(10) 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` (`source`) + UNIQUE KEY (`sourcevid`,`source`) +); + +-- +-- Table structure for table `RECORDER` +-- + +CREATE TABLE IF NOT EXISTS `RECORDER` ( + `id` int(11) unsigned NOT NULL auto_increment, + `active` enum('y','n') default 'y', + `master` enum('y','n') default 'n', + `host` varchar(100) NOT NULL default 'localhost', + `port` smallint(4) unsigned default '2001', + `cards` varchar(100) default '', + PRIMARY KEY (`id`) ); -- @@ -161,13 +177,14 @@ CREATE TABLE IF NOT EXISTS `XMLTV` ( `id` int(10) unsigned NOT NULL auto_increment, `active` enum('y','n') default 'n', `xmltvname` varchar(256) NOT 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` (`channel`) + UNIQUE KEY (`vid`,`channel`) ); /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -176,4 +193,4 @@ CREATE TABLE IF NOT EXISTS `XMLTV` ( /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2008-06-13 9:50:16 +-- Dump completed on 2008-07-26 18:32:18 diff --git a/html/clist.tmpl b/html/clist.tmpl index 039c57f..4cc980a 100644 --- a/html/clist.tmpl +++ b/html/clist.tmpl @@ -36,7 +36,7 @@ <a href="?cmd=cedit&data=<?% id %?>" title="<?% gettext("Edit channel") %?>">[E]</a> <?%- END -%?> <?%- IF allow('cdelete') -%?> -<a href="javascript:sure(document.KanalListe, '<?% gettext("Would you like to delete this channel?") %?>\n\'<?% escape(name) %?>\' ?','?cmd=cdelete&data=<?% POS %?>')" +<a href="javascript:sure(document.KanalListe, '<?% gettext("Would you like to delete this channel?") %?>\n\'<?% escape(name) %?>\' ?','?cmd=cdelete&data=<?% id %?>')" title="<?% gettext("Delete channel") %?>" >[D]</a> <?%- END -%?> <?% END %?> @@ -45,7 +45,7 @@ <tr<?% ' bgcolor="#F5F5F5"' IF loop.count mod 2 == 0 %?>> <td> <?% IF enableform %?> - <input type="checkbox" value="<?% POS %?>" name="<?% name %?>" /> + <input type="checkbox" value="<?% id %?>" name="<?% name %?>" /> <?% END %?> </td> <td> @@ -142,8 +142,14 @@ <th width="64" align="right"></th> </tr> <?% FOREACH zeile = data %?> - <?% id=zeile.0;name=zeile.1;frequency=zeile.2;parameters=zeile.3;source=zeile.4;srate=zeile.5;VPID=zeile.6;APID=zeile.7;TPID=zeile.8;CA=zeile.9;SID=zeile.10;NID=zeile.11;TID=zeile.12;RID=zeile.13;GRP=zeile.14;POS=zeile.15;CGRP=zeile.16 %?> - <?% IF CGRP != CGRP_OLD %?> + <?% id=zeile.0;name=zeile.1;frequency=zeile.2;parameters=zeile.3;source=zeile.4;srate=zeile.5;VPID=zeile.6;APID=zeile.7;TPID=zeile.8;CA=zeile.9;SID=zeile.10;NID=zeile.11;TID=zeile.12;RID=zeile.13;GRP=zeile.14;POS=zeile.15;CGRP=zeile.16;HOST=zeile.17; %?> + <?% IF not sortby.defined && OLDHOST != HOST %?> + <tr> + <td colspan=10 bgcolor='#CCCCCC'><b><?% gettext("Video disk recorder") %?> : <?% HOST %?></b></td> + <tr> + <?% OLDHOST = HOST %?> + <?% END %?> + <?% IF not sortby.defined && CGRP != CGRP_OLD %?> <tr> <td colspan=10 bgcolor='#DDDDDD'><b><?% CGRP %?></b></td> <tr> diff --git a/html/help.tmpl b/html/help.tmpl index 2989164..b03f955 100644 --- a/html/help.tmpl +++ b/html/help.tmpl @@ -51,7 +51,11 @@ var tree = new WebFXTree("XXV", "?cmd=<?% getModule('HTTPD').StartPage %?>"); var program = new WebFXTreeItem("<?% gettext("Program guide") %?>","?cmd=schema",tree); <?% IF allow('topten') %?>program.add(new WebFXTreeItem("<?% gettext("Top ten entry") %?>", "?cmd=t10"));<?% END %?> <?% FOREACH ch = param.CHANNELS %?> - program.add(new WebFXTreeItem("<?% escape(chop(ch.0,10)) %?>", "?cmd=program&data=<?% ch.1 %?>")); + <?% IF ch.2 != lastgroup;lastgroup = ch.2 %?> + <?% CNT = CNT + 1 %?> + var programgroup<?% CNT %?> = new WebFXTreeItem("<?% escape(chop(lastgroup,10)) %?>", "?cmd=program&data=<?% ch.1 %?>",program); + <?% END %?> + programgroup<?% CNT %?>.add(new WebFXTreeItem("<?% escape(chop(ch.0,10)) %?>", "?cmd=program&data=<?% ch.1 %?>")); <?% END %?> <?% END %?> @@ -79,16 +83,6 @@ var tools = new WebFXTreeItem("<?% gettext("Tools",15) %?>",0,tree); <?% END %?> -<?% IF allow('configedit') %?> - var prefs = new WebFXTreeItem("<?% gettext("Preferences") %?>","?cmd=configedit",tree); - <?% FOREACH co = param.CONFIGS %?> - <?% IF co != "CONFIG" %?> - prefs.add(new WebFXTreeItem("<?% chop(co,10) %?>", "?cmd=configedit&data=<?% co %?>")); - <?% END %?> - <?% END %?> - prefs.add(new WebFXTreeItem("<?% gettext("Edit channels",10) %?>", "?cmd=cl")); -<?% END %?> - <?% IF allow('sa') %?> var status = new WebFXTreeItem("<?% gettext("Status") %?>","?cmd=sa",tree); status.add(new WebFXTreeItem("<?% gettext("Vitals") %?>", "?cmd=sv")); @@ -113,14 +107,25 @@ logger.add(new WebFXTreeItem("<?% gettext("Standard") %?>", "?cmd=logger&data=m logger.add(new WebFXTreeItem("<?% gettext("Syslog") %?>", "?cmd=logger&data=syslog")); <?% END %?> -<?% IF allow('ul') || allow('uprefs') || allow('rel') || allow('restart') %?> +<?% IF allow('ul') || allow('uprefs') || allow('vl') || allow('cl') || allow('rel') || allow('restart') %?> var admin = new WebFXTreeItem("<?% gettext("Administration") %?>",0,tree); +<?% IF allow('vl') %?>admin.add(new WebFXTreeItem("<?% gettext("Video disk recorder",12) %?>", "?cmd=vl"));<?% END %?> +<?% IF allow('cl') %?>admin.add(new WebFXTreeItem("<?% gettext("Channels",12) %?>", "?cmd=cl"));<?% END %?> <?% IF allow('ul') %?>admin.add(new WebFXTreeItem("<?% gettext("User") %?>","?cmd=ul")); <?% ELSIF allow('uprefs') %?>admin.add(new WebFXTreeItem("<?% gettext("Personality") %?>","?cmd=uprefs"));<?% END %?> <?% IF allow('rel') %?>admin.add(new WebFXTreeItem("<?% gettext("Reload") %?>","?cmd=rel"));<?% END %?> <?% IF allow('restart') %?>admin.add(new WebFXTreeItem("<?% gettext("Restart") %?>","?cmd=restart"));<?% END %?> <?% END %?> +<?% IF allow('configedit') %?> + var prefs = new WebFXTreeItem("<?% gettext("Preferences") %?>","?cmd=configedit",tree); + <?% FOREACH co = param.CONFIGS %?> + <?% IF co != "CONFIG" %?> + prefs.add(new WebFXTreeItem("<?% chop(co,10) %?>", "?cmd=configedit&data=<?% co %?>")); + <?% END %?> + <?% END %?> +<?% END %?> + <?% IF allow('logout') %?>var lout = new WebFXTreeItem("<?% gettext("Logout") %?>","?cmd=logout",tree);<?% END %?> document.write(tree); diff --git a/html/ulist.tmpl b/html/ulist.tmpl index f7e7187..27811fb 100644 --- a/html/ulist.tmpl +++ b/html/ulist.tmpl @@ -27,7 +27,7 @@ [<?% gettext("Edit") %?>]</a> <a title="<?% gettext("Delete user account") %?>" href="javascript:sure(document.UserList, '<?% gettext("Would you like to delete this user account?") %?>: <?% escape(zeile.1) %?>','?cmd=udelete&data=<?% zeile.0 %?>')"> - [<?% gettext("Del") %?>] + [<?% gettext("Delete") %?>] </a> </td> <?% ELSE %?> diff --git a/html/vdrlist.tmpl b/html/vdrlist.tmpl new file mode 100644 index 0000000..30e360d --- /dev/null +++ b/html/vdrlist.tmpl @@ -0,0 +1,41 @@ +<!-- TableTemplate --> +<h1><?% gettext("Administration of video disk recorder") %?></h1> + +<a href="?cmd=vdrnew">[<?% gettext("Create new definition of video disk recorder") %?>]</a> +<p> + +<table border="0" width="95%"> +<form name='vdrlist'> +<?% INCLUDE 'widgets/referer.tmpl' %?> +<?% IF data.size %?> + <?% fields = data.shift %?> + <tr> + <?% FOREACH field = fields %?> + <th><?% field %?></th> + <?% END %?> + </tr> + <?% x = -1 %?> + <?% FOREACH zeile = data %?> + <?% x = x + 1 %?> + <tr class="<?% myclass %?>" <?% IF (x mod 2) != 0 %?>bgcolor='#F5F5F5'<?% END %?>> + <?% c = 0 %?> + <?% FOREACH field = zeile %?> + <?% c = c + 1 %?> + <?% IF c == 1; # Id Field %?> + <td> + <a title="<?% gettext("Edit definition of video disk recorder") %?>" href="?cmd=vdredit&data=<?% zeile.0 %?>"> + [<?% gettext("Edit") %?>]</a> + <a title="<?% gettext("Delete definition of video disk recorder") %?>" + href="#" onclick="sure(document.vdrlist, '<?% gettext("Would you like to delete this definition of video disk recorder?") %?>: <?% escape(zeile.3) %?>','?cmd=vdrdelete&data=<?% zeile.0 %?>')"> + [<?% gettext("Delete") %?>] + </a> + </td> + <?% ELSE %?> + <td><?% field %?></td> + <?% END %?> + <?% END %?> + </tr> + <?% END %?> +<?% END %?> +</form> +</table> diff --git a/html/widgets/remote.tmpl b/html/widgets/remote.tmpl index 6c8e68f..3204c74 100644 --- a/html/widgets/remote.tmpl +++ b/html/widgets/remote.tmpl @@ -9,8 +9,15 @@ var interval = 5 var last = 0; +function post(url) { + var vdr = ( document.remoteform.vdr.options ? document.remoteform.vdr.options[document.remoteform.vdr.options.selectedIndex].value : document.remoteform.vdr.value ); + // Hmm, brutal und gemein, das Laden der URL als Bild funktioniert... + var img = new Image(); + img.src = url + '&__vdr=' + vdr; +} + function switch_channel(url) { - parent.Status.location.href = url; + post(url); <?% IF monitor %?> if(last + 1000 < Date.UTC()) { grab(); @@ -21,8 +28,9 @@ function switch_channel(url) { <?% IF monitor %?> function grab() { if(document.remoteform.grabinterval.value > 0) { - Now = new Date(); - document.livepicture.src = '?cmd=gdisplay&random=' + Now.getTime(); + Now = new Date(); + var vdr = ( document.remoteform.vdr.options ? document.remoteform.vdr.options[document.remoteform.vdr.options.selectedIndex].value : document.remoteform.vdr.value ); + document.livepicture.src = '?cmd=gdisplay&__vdr='+vdr+'&random=' + Now.getTime(); } last = Date.UTC(); } @@ -52,8 +60,8 @@ aktiv = window.setInterval("grab()", inter); <table border=0 cellpadding=0 cellspacing=0> <tr> <?% IF monitor %?> - <td rowspan="12"> - <img src="?cmd=gdisplay&random=<?% date.now %?>" width="<?% param.width %?>" height="<?% param.height %?>" name="livepicture"> + <td rowspan="14"> + <img src="?cmd=gdisplay&random=<?% date.now %?>&__vdr=<?% param.vdr %?>" width="<?% param.width %?>" height="<?% param.height %?>" name="livepicture"> </td> <?% END %?> <td colspan="3"><nobr> @@ -115,6 +123,41 @@ aktiv = window.setInterval("grab()", inter); <td align='center'> </td> <td align='center'><input id='small' onclick="switch_channel('?cmd=remote&data=VolumePlus')" type="button" name="lauter" value="+"></td> </tr> +<?% IF param.vdrlist.size > 1 %?> +<tr> + <td colspan="3" align="center"> + <select style="width:150px;" name="vdr"> + <?% FOREACH l = param.vdrlist %?> + <option value='<?% l.1 %?>'<?% IF l.1 == param.vdr %?> selected<?% END %?>><?% l.0 %?></option> + <?% END %?> + </select> + </td> +</tr> +<?% ELSE %?> +<tr> + <td colspan="7" align="center"> + <input type="hidden" name="vdr" value="<?% param.vdr %?>" /> + </td> +</tr> +<?% END %?> +<tr> + <td colspan="3" align="center"> + <select style="width:150px;" name="channels" onchange="post('?cmd=switch&data='+ this.form.channels.options[this.form.channels.options.selectedIndex].value)"> + <?% FOREACH l = param.channels %?> + <?% IF l.2 && l.2 != optgroup %?> + <?% IF optgroup %?> + </optgroup> + <?% END %?> + <optgroup label="<?% optgroup = l.2;l.2 %?>"> + <?% END %?> + <option value='<?% l.1 %?>'><?% l.0 %?></option> + <?% END %?> + <?% IF optgroup %?> + </optgroup> + <?% END %?> + </select> + </td> +</tr> <?% IF monitor %?> <tr> <td align='center' colspan="3"> 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 { diff --git a/locale/de.po b/locale/de.po index 3ad8b91..f7ed785 100644 --- a/locale/de.po +++ b/locale/de.po @@ -59,7 +59,7 @@ msgid "Data source for the connection to the database" msgstr "Name der Datenquelle für die Verbindung zur Datenbank" #-------------------- -#: ../bin/xxvd:718 ../bin/xxvd:724 ../bin/xxvd:730 ../bin/xxvd:745 ../lib/XXV/MODULES/AUTOTIMER.pm:31 ../lib/XXV/MODULES/AUTOTIMER.pm:714 ../lib/XXV/MODULES/CHANNELS.pm:1005 ../lib/XXV/MODULES/CHANNELS.pm:28 ../lib/XXV/MODULES/CHANNELS.pm:901 ../lib/XXV/MODULES/CHANNELS.pm:927 ../lib/XXV/MODULES/CHANNELS.pm:940 ../lib/XXV/MODULES/CHANNELS.pm:979 ../lib/XXV/MODULES/CHRONICLE.pm:27 ../lib/XXV/MODULES/EPG.pm:33 ../lib/XXV/MODULES/EPG.pm:39 ../lib/XXV/MODULES/EPG.pm:45 ../lib/XXV/MODULES/EVENTS.pm:33 ../lib/XXV/MODULES/GRAB.pm:29 ../lib/XXV/MODULES/GRAB.pm:43 ../lib/XXV/MODULES/HTTPD.pm:62 ../lib/XXV/MODULES/HTTPD.pm:68 ../lib/XXV/MODULES/HTTPD.pm:74 ../lib/XXV/MODULES/HTTPD.pm:80 ../lib/XXV/MODULES/HTTPD.pm:86 ../lib/XXV/MODULES/HTTPD.pm:93 ../lib/XXV/MODULES/INTERFACE.pm:32 ../lib/XXV/MODULES/INTERFACE.pm:38 ../lib/XXV/MODULES/INTERFACE.pm:44 ../lib/XXV/MODULES/KEYWORDS.pm:27 ../lib/XXV/MODULES/LOGREAD.pm:31 ../lib/XXV/MODULES/LOGREAD.pm:37 ../lib/XXV/MODULES/LOGREAD.pm:43 ../lib/XXV/MODULES/LOGREAD.pm:49 ../lib/XXV/MODULES/MEDIALIB.pm:32 ../lib/XXV/MODULES/MEDIALIB.pm:38 ../lib/XXV/MODULES/MEDIALIB.pm:44 ../lib/XXV/MODULES/MEDIALIB.pm:50 ../lib/XXV/MODULES/MEDIALIB.pm:56 ../lib/XXV/MODULES/MOVETIMER.pm:26 ../lib/XXV/MODULES/MOVETIMER.pm:389 ../lib/XXV/MODULES/MOVETIMER.pm:402 ../lib/XXV/MODULES/MOVETIMER.pm:411 ../lib/XXV/MODULES/MOVETIMER.pm:424 ../lib/XXV/MODULES/MUSIC.pm:39 ../lib/XXV/MODULES/MUSIC.pm:45 ../lib/XXV/MODULES/MUSIC.pm:51 ../lib/XXV/MODULES/MUSIC.pm:57 ../lib/XXV/MODULES/MUSIC.pm:68 ../lib/XXV/MODULES/MUSIC.pm:74 ../lib/XXV/MODULES/RECORDS.pm:2069 ../lib/XXV/MODULES/RECORDS.pm:2083 ../lib/XXV/MODULES/RECORDS.pm:2097 ../lib/XXV/MODULES/RECORDS.pm:2116 ../lib/XXV/MODULES/RECORDS.pm:2671 ../lib/XXV/MODULES/RECORDS.pm:2683 ../lib/XXV/MODULES/RECORDS.pm:40 ../lib/XXV/MODULES/RECORDS.pm:46 ../lib/XXV/MODULES/RECORDS.pm:52 ../lib/XXV/MODULES/RECORDS.pm:58 ../lib/XXV/MODULES/RECORDS.pm:64 ../lib/XXV/MODULES/RECORDS.pm:76 ../lib/XXV/MODULES/RECORDS.pm:92 ../lib/XXV/MODULES/REMOTE.pm:28 ../lib/XXV/MODULES/REMOTE.pm:34 ../lib/XXV/MODULES/REMOTE.pm:40 ../lib/XXV/MODULES/REPORT.pm:29 ../lib/XXV/MODULES/REPORT.pm:45 ../lib/XXV/MODULES/ROBOT.pm:28 ../lib/XXV/MODULES/SHARE.pm:64 ../lib/XXV/MODULES/SHARE.pm:81 ../lib/XXV/MODULES/SHARE.pm:87 ../lib/XXV/MODULES/STATUS.pm:31 ../lib/XXV/MODULES/STATUS.pm:37 ../lib/XXV/MODULES/STATUS.pm:42 ../lib/XXV/MODULES/STATUS.pm:48 ../lib/XXV/MODULES/STREAM.pm:107 ../lib/XXV/MODULES/STREAM.pm:32 ../lib/XXV/MODULES/STREAM.pm:42 ../lib/XXV/MODULES/STREAM.pm:63 ../lib/XXV/MODULES/STREAM.pm:69 ../lib/XXV/MODULES/STREAM.pm:87 ../lib/XXV/MODULES/STREAM.pm:93 ../lib/XXV/MODULES/SVDRP.pm:29 ../lib/XXV/MODULES/SVDRP.pm:35 ../lib/XXV/MODULES/SVDRP.pm:41 ../lib/XXV/MODULES/TELNET.pm:29 ../lib/XXV/MODULES/TELNET.pm:35 ../lib/XXV/MODULES/TELNET.pm:41 ../lib/XXV/MODULES/TELNET.pm:47 ../lib/XXV/MODULES/TIMERS.pm:30 ../lib/XXV/MODULES/TIMERS.pm:720 ../lib/XXV/MODULES/TIMERS.pm:727 ../lib/XXV/MODULES/TIMERS.pm:730 ../lib/XXV/MODULES/TIMERS.pm:755 ../lib/XXV/MODULES/USER.pm:275 ../lib/XXV/MODULES/USER.pm:367 ../lib/XXV/MODULES/USER.pm:373 ../lib/XXV/MODULES/USER.pm:398 ../lib/XXV/MODULES/USER.pm:67 ../lib/XXV/MODULES/VTX.pm:33 ../lib/XXV/MODULES/VTX.pm:39 ../lib/XXV/MODULES/WAPD.pm:42 ../lib/XXV/MODULES/WAPD.pm:48 ../lib/XXV/MODULES/WAPD.pm:54 ../lib/XXV/MODULES/WAPD.pm:60 ../lib/XXV/MODULES/WAPD.pm:66 ../lib/XXV/MODULES/WAPD.pm:73 ../lib/XXV/MODULES/XMLTV.pm:32 ../lib/XXV/MODULES/XMLTV.pm:506 ../lib/XXV/MODULES/XMLTV.pm:519 ../lib/XXV/MODULES/XMLTV.pm:532 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:116 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:122 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:128 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:68 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:98 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:106 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:33 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:63 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:81 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:95 ../lib/XXV/OUTPUT/NEWS/RSS.pm:32 ../lib/XXV/OUTPUT/NEWS/RSS.pm:62 ../lib/XXV/OUTPUT/NEWS/VDR.pm:29 ../lib/XXV/OUTPUT/NEWS/VDR.pm:59 +#: ../bin/xxvd:718 ../bin/xxvd:724 ../bin/xxvd:730 ../bin/xxvd:745 ../lib/XXV/MODULES/AUTOTIMER.pm:30 ../lib/XXV/MODULES/AUTOTIMER.pm:713 ../lib/XXV/MODULES/CHANNELS.pm:1105 ../lib/XXV/MODULES/CHANNELS.pm:1131 ../lib/XXV/MODULES/CHANNELS.pm:1144 ../lib/XXV/MODULES/CHANNELS.pm:1183 ../lib/XXV/MODULES/CHANNELS.pm:1209 ../lib/XXV/MODULES/CHANNELS.pm:28 ../lib/XXV/MODULES/CHRONICLE.pm:27 ../lib/XXV/MODULES/EPG.pm:33 ../lib/XXV/MODULES/EPG.pm:39 ../lib/XXV/MODULES/EPG.pm:45 ../lib/XXV/MODULES/EVENTS.pm:33 ../lib/XXV/MODULES/GRAB.pm:29 ../lib/XXV/MODULES/GRAB.pm:43 ../lib/XXV/MODULES/HTTPD.pm:62 ../lib/XXV/MODULES/HTTPD.pm:68 ../lib/XXV/MODULES/HTTPD.pm:74 ../lib/XXV/MODULES/HTTPD.pm:80 ../lib/XXV/MODULES/HTTPD.pm:86 ../lib/XXV/MODULES/HTTPD.pm:93 ../lib/XXV/MODULES/INTERFACE.pm:32 ../lib/XXV/MODULES/INTERFACE.pm:38 ../lib/XXV/MODULES/INTERFACE.pm:44 ../lib/XXV/MODULES/KEYWORDS.pm:28 ../lib/XXV/MODULES/LOGREAD.pm:31 ../lib/XXV/MODULES/LOGREAD.pm:37 ../lib/XXV/MODULES/LOGREAD.pm:43 ../lib/XXV/MODULES/LOGREAD.pm:49 ../lib/XXV/MODULES/MEDIALIB.pm:32 ../lib/XXV/MODULES/MEDIALIB.pm:38 ../lib/XXV/MODULES/MEDIALIB.pm:44 ../lib/XXV/MODULES/MEDIALIB.pm:50 ../lib/XXV/MODULES/MEDIALIB.pm:56 ../lib/XXV/MODULES/MOVETIMER.pm:26 ../lib/XXV/MODULES/MOVETIMER.pm:418 ../lib/XXV/MODULES/MOVETIMER.pm:421 ../lib/XXV/MODULES/MOVETIMER.pm:441 ../lib/XXV/MODULES/MOVETIMER.pm:444 ../lib/XXV/MODULES/MUSIC.pm:39 ../lib/XXV/MODULES/MUSIC.pm:45 ../lib/XXV/MODULES/MUSIC.pm:51 ../lib/XXV/MODULES/MUSIC.pm:57 ../lib/XXV/MODULES/MUSIC.pm:68 ../lib/XXV/MODULES/MUSIC.pm:74 ../lib/XXV/MODULES/RECORDS.pm:2060 ../lib/XXV/MODULES/RECORDS.pm:2074 ../lib/XXV/MODULES/RECORDS.pm:2088 ../lib/XXV/MODULES/RECORDS.pm:2107 ../lib/XXV/MODULES/RECORDS.pm:2647 ../lib/XXV/MODULES/RECORDS.pm:2659 ../lib/XXV/MODULES/RECORDS.pm:39 ../lib/XXV/MODULES/RECORDS.pm:45 ../lib/XXV/MODULES/RECORDS.pm:51 ../lib/XXV/MODULES/RECORDS.pm:57 ../lib/XXV/MODULES/RECORDS.pm:63 ../lib/XXV/MODULES/RECORDS.pm:75 ../lib/XXV/MODULES/RECORDS.pm:91 ../lib/XXV/MODULES/REMOTE.pm:28 ../lib/XXV/MODULES/REMOTE.pm:34 ../lib/XXV/MODULES/REMOTE.pm:40 ../lib/XXV/MODULES/REPORT.pm:29 ../lib/XXV/MODULES/REPORT.pm:45 ../lib/XXV/MODULES/ROBOT.pm:28 ../lib/XXV/MODULES/SHARE.pm:64 ../lib/XXV/MODULES/SHARE.pm:81 ../lib/XXV/MODULES/SHARE.pm:87 ../lib/XXV/MODULES/STATUS.pm:31 ../lib/XXV/MODULES/STATUS.pm:37 ../lib/XXV/MODULES/STATUS.pm:42 ../lib/XXV/MODULES/STATUS.pm:48 ../lib/XXV/MODULES/STREAM.pm:108 ../lib/XXV/MODULES/STREAM.pm:33 ../lib/XXV/MODULES/STREAM.pm:43 ../lib/XXV/MODULES/STREAM.pm:64 ../lib/XXV/MODULES/STREAM.pm:70 ../lib/XXV/MODULES/STREAM.pm:88 ../lib/XXV/MODULES/STREAM.pm:94 ../lib/XXV/MODULES/SVDRP.pm:217 ../lib/XXV/MODULES/SVDRP.pm:223 ../lib/XXV/MODULES/SVDRP.pm:29 ../lib/XXV/MODULES/TELNET.pm:29 ../lib/XXV/MODULES/TELNET.pm:35 ../lib/XXV/MODULES/TELNET.pm:41 ../lib/XXV/MODULES/TELNET.pm:47 ../lib/XXV/MODULES/TIMERS.pm:29 ../lib/XXV/MODULES/TIMERS.pm:695 ../lib/XXV/MODULES/TIMERS.pm:708 ../lib/XXV/MODULES/TIMERS.pm:711 ../lib/XXV/MODULES/TIMERS.pm:736 ../lib/XXV/MODULES/USER.pm:275 ../lib/XXV/MODULES/USER.pm:367 ../lib/XXV/MODULES/USER.pm:373 ../lib/XXV/MODULES/USER.pm:398 ../lib/XXV/MODULES/USER.pm:67 ../lib/XXV/MODULES/VTX.pm:33 ../lib/XXV/MODULES/VTX.pm:39 ../lib/XXV/MODULES/WAPD.pm:42 ../lib/XXV/MODULES/WAPD.pm:48 ../lib/XXV/MODULES/WAPD.pm:54 ../lib/XXV/MODULES/WAPD.pm:60 ../lib/XXV/MODULES/WAPD.pm:66 ../lib/XXV/MODULES/WAPD.pm:73 ../lib/XXV/MODULES/XMLTV.pm:32 ../lib/XXV/MODULES/XMLTV.pm:507 ../lib/XXV/MODULES/XMLTV.pm:520 ../lib/XXV/MODULES/XMLTV.pm:533 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:116 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:122 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:128 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:68 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:98 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:106 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:33 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:63 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:81 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:95 ../lib/XXV/OUTPUT/NEWS/RSS.pm:32 ../lib/XXV/OUTPUT/NEWS/RSS.pm:62 ../lib/XXV/OUTPUT/NEWS/VDR.pm:29 ../lib/XXV/OUTPUT/NEWS/VDR.pm:59 msgid "This is required!" msgstr "Das ist erforderlich!" @@ -99,12 +99,12 @@ msgid "Wished automated recordings" msgstr "Gewünschte automatische Aufnahmen" #-------------------- -#: ../html/alist.tmpl:45 ../html/tlist.tmpl:94 ../lib/XXV/MODULES/AUTOTIMER.pm:1026 +#: ../html/alist.tmpl:45 ../html/tlist.tmpl:94 ../lib/XXV/MODULES/AUTOTIMER.pm:1024 msgid "Edit autotimer" msgstr "Autotimer bearbeiten" #-------------------- -#: ../html/alist.tmpl:46 ../html/mlnavcontainer.tmpl:16 ../html/next.tmpl:66 ../html/now.tmpl:66 ../html/ulist.tmpl:27 ../wml/tlist.tmpl:46 ../wml/tsearch.tmpl:46 +#: ../html/alist.tmpl:46 ../html/mlnavcontainer.tmpl:16 ../html/next.tmpl:66 ../html/now.tmpl:66 ../html/ulist.tmpl:27 ../html/vdrlist.tmpl:27 ../wml/tlist.tmpl:46 msgid "Edit" msgstr "Ändern" @@ -114,7 +114,7 @@ msgid "Delete autotimer" msgstr "Lösche Autotimer" #-------------------- -#: ../html/alist.tmpl:5 ../lib/XXV/MODULES/AUTOTIMER.pm:1027 ../lib/XXV/MODULES/AUTOTIMER.pm:55 +#: ../html/alist.tmpl:5 ../lib/XXV/MODULES/AUTOTIMER.pm:1025 ../lib/XXV/MODULES/AUTOTIMER.pm:54 msgid "Create new autotimer" msgstr "Neuer Autotimer" @@ -124,17 +124,17 @@ msgid "Would you like to delete this autotimer?" msgstr "Wollen Sie diese Autotimer löschen?" #-------------------- -#: ../html/alist.tmpl:51 ../html/ulist.tmpl:30 +#: ../html/alist.tmpl:51 msgid "Del" msgstr "Lösch" #-------------------- -#: ../html/alist.tmpl:57 ../html/tlist.tmpl:88 ../wml/tlist.tmpl:33 ../wml/tsearch.tmpl:33 +#: ../html/alist.tmpl:57 ../html/tlist.tmpl:88 ../wml/tlist.tmpl:33 msgid "Off" msgstr "Aus" #-------------------- -#: ../html/alist.tmpl:58 ../html/tlist.tmpl:89 ../wml/tlist.tmpl:33 ../wml/tsearch.tmpl:33 +#: ../html/alist.tmpl:58 ../html/tlist.tmpl:89 ../wml/tlist.tmpl:33 msgid "On" msgstr "An" @@ -199,57 +199,63 @@ msgid "Delete channels" msgstr "Kanäle löschen" #-------------------- -#: ../html/clist.tmpl:134 ../lib/XXV/MODULES/CHANNELS.pm:570 ../lib/XXV/MODULES/CHANNELS.pm:895 ../lib/XXV/MODULES/USER.pm:533 ../lib/XXV/OUTPUT/Console.pm:170 ../lib/XXV/OUTPUT/Console.pm:233 +#: ../html/clist.tmpl:134 ../lib/XXV/MODULES/CHANNELS.pm:1099 ../lib/XXV/MODULES/CHANNELS.pm:1378 ../lib/XXV/MODULES/CHANNELS.pm:604 ../lib/XXV/MODULES/USER.pm:533 ../lib/XXV/OUTPUT/Console.pm:170 ../lib/XXV/OUTPUT/Console.pm:233 msgid "Name" msgstr "Name" #-------------------- -#: ../html/clist.tmpl:135 ../lib/XXV/MODULES/CHANNELS.pm:571 ../lib/XXV/MODULES/CHANNELS.pm:907 +#: ../html/clist.tmpl:135 ../lib/XXV/MODULES/CHANNELS.pm:1111 ../lib/XXV/MODULES/CHANNELS.pm:605 msgid "Transponder frequency" msgstr "Frequenz des Transponder" #-------------------- -#: ../html/clist.tmpl:136 ../lib/XXV/MODULES/CHANNELS.pm:934 +#: ../html/clist.tmpl:136 ../lib/XXV/MODULES/CHANNELS.pm:1138 msgid "Various parameters, depending on signal source" msgstr "Verschiedene Parameter, abhängig von der Signalquelle" #-------------------- -#: ../html/clist.tmpl:137 ../html/movetimerlist.tmpl:82 ../lib/XXV/MODULES/MOVETIMER.pm:553 +#: ../html/clist.tmpl:137 ../html/movetimerlist.tmpl:82 ../lib/XXV/MODULES/MOVETIMER.pm:578 msgid "Source" msgstr "Quelle" #-------------------- -#: ../html/clist.tmpl:138 ../lib/XXV/MODULES/CHANNELS.pm:959 +#: ../html/clist.tmpl:138 ../lib/XXV/MODULES/CHANNELS.pm:1163 msgid "Video PID (VPID)" msgstr "Video PID (VPID)" #-------------------- -#: ../html/clist.tmpl:139 ../lib/XXV/MODULES/CHANNELS.pm:973 +#: ../html/clist.tmpl:139 ../lib/XXV/MODULES/CHANNELS.pm:1177 msgid "Audio PID (APID)" msgstr "Audio PID (APID)" #-------------------- -#: ../html/clist.tmpl:140 ../lib/XXV/MODULES/CHANNELS.pm:985 +#: ../html/clist.tmpl:140 ../lib/XXV/MODULES/CHANNELS.pm:1189 msgid "Teletext PID (TPID)" msgstr "Videotext PID (TPID)" #-------------------- -#: ../html/clist.tmpl:141 ../lib/XXV/MODULES/CHANNELS.pm:999 +#: ../html/clist.tmpl:141 ../lib/XXV/MODULES/CHANNELS.pm:1203 msgid "Conditional access (CA)" msgstr "Zugangsberechtigungssystem (CA)" #-------------------- +#: ../html/clist.tmpl:148 ../html/help.tmpl:112 ../lib/XXV/MODULES/CHANNELS.pm:1379 +#. (12) +msgid "Video disk recorder" +msgstr "Video Disk Rekorder" + +#-------------------- #: ../html/clist.tmpl:34 msgid "Switch to channel" msgstr "Schalte zum Kanal" #-------------------- -#: ../html/clist.tmpl:36 ../lib/XXV/MODULES/CHANNELS.pm:1065 +#: ../html/clist.tmpl:36 ../lib/XXV/MODULES/CHANNELS.pm:1269 msgid "Edit channel" msgstr "Kanal bearbeiten" #-------------------- -#: ../html/clist.tmpl:39 ../lib/XXV/MODULES/CHANNELS.pm:1170 +#: ../html/clist.tmpl:39 ../lib/XXV/MODULES/CHANNELS.pm:1384 msgid "Would you like to delete this channel?" msgstr "Wollen Sie diesen Kanal löschen?" @@ -259,7 +265,8 @@ msgid "Delete channel" msgstr "Kanal löschen" #-------------------- -#: ../html/clist.tmpl:94 ../lib/XXV/MODULES/AUTOTIMER.pm:1175 ../lib/XXV/MODULES/CHANNELS.pm:452 +#: ../html/clist.tmpl:94 ../html/help.tmpl:113 ../lib/XXV/MODULES/AUTOTIMER.pm:1173 ../lib/XXV/MODULES/CHANNELS.pm:486 +#. (12) msgid "Channels" msgstr "Kanäle" @@ -274,17 +281,17 @@ msgid "Detailed program information" msgstr "Detailierte Programminformation" #-------------------- -#: ../html/display.tmpl:21 ../html/display.tmpl:44 ../lib/XXV/MODULES/EPG.pm:1174 ../lib/XXV/MODULES/EPG.pm:918 +#: ../html/display.tmpl:21 ../html/display.tmpl:44 ../lib/XXV/MODULES/EPG.pm:1189 ../lib/XXV/MODULES/EPG.pm:922 msgid "Percent" msgstr "Prozent" #-------------------- -#: ../html/display.tmpl:25 ../html/rdisplay.tmpl:158 ../html/search.tmpl:54 ../lib/XXV/MODULES/AUTOTIMER.pm:180 ../lib/XXV/MODULES/AUTOTIMER.pm:457 ../lib/XXV/MODULES/CHRONICLE.pm:176 ../lib/XXV/MODULES/CHRONICLE.pm:257 ../lib/XXV/MODULES/EPG.pm:1040 ../lib/XXV/MODULES/EPG.pm:1171 ../lib/XXV/MODULES/EPG.pm:678 ../lib/XXV/MODULES/EPG.pm:804 ../lib/XXV/MODULES/EPG.pm:914 ../lib/XXV/MODULES/RECORDS.pm:2107 ../lib/XXV/MODULES/SHARE.pm:345 ../lib/XXV/MODULES/TIMERS.pm:1334 ../lib/XXV/MODULES/TIMERS.pm:953 ../lib/XXV/MODULES/XMLTV.pm:677 +#: ../html/display.tmpl:25 ../html/rdisplay.tmpl:158 ../html/search.tmpl:54 ../lib/XXV/MODULES/AUTOTIMER.pm:179 ../lib/XXV/MODULES/AUTOTIMER.pm:456 ../lib/XXV/MODULES/CHRONICLE.pm:176 ../lib/XXV/MODULES/CHRONICLE.pm:257 ../lib/XXV/MODULES/EPG.pm:1063 ../lib/XXV/MODULES/EPG.pm:1186 ../lib/XXV/MODULES/EPG.pm:688 ../lib/XXV/MODULES/EPG.pm:918 ../lib/XXV/MODULES/RECORDS.pm:2098 ../lib/XXV/MODULES/SHARE.pm:345 ../lib/XXV/MODULES/TIMERS.pm:1334 ../lib/XXV/MODULES/TIMERS.pm:948 ../lib/XXV/MODULES/XMLTV.pm:678 msgid "Channel" msgstr "Kanal" #-------------------- -#: ../html/display.tmpl:27 ../html/movetimerlist.tmpl:81 ../lib/XXV/MODULES/AUTOTIMER.pm:1172 ../lib/XXV/MODULES/CHANNELS.pm:569 ../lib/XXV/MODULES/CHRONICLE.pm:174 ../lib/XXV/MODULES/CHRONICLE.pm:255 ../lib/XXV/MODULES/EPG.pm:1038 ../lib/XXV/MODULES/EPG.pm:1169 ../lib/XXV/MODULES/EPG.pm:676 ../lib/XXV/MODULES/EPG.pm:802 ../lib/XXV/MODULES/EPG.pm:911 ../lib/XXV/MODULES/MOVETIMER.pm:552 ../lib/XXV/MODULES/MUSIC.pm:614 ../lib/XXV/MODULES/SHARE.pm:343 ../lib/XXV/MODULES/TIMERS.pm:1331 ../lib/XXV/MODULES/USER.pm:532 ../lib/XXV/MODULES/XMLTV.pm:675 +#: ../html/display.tmpl:27 ../html/movetimerlist.tmpl:81 ../lib/XXV/MODULES/AUTOTIMER.pm:1170 ../lib/XXV/MODULES/CHANNELS.pm:603 ../lib/XXV/MODULES/CHRONICLE.pm:174 ../lib/XXV/MODULES/CHRONICLE.pm:255 ../lib/XXV/MODULES/EPG.pm:1061 ../lib/XXV/MODULES/EPG.pm:1184 ../lib/XXV/MODULES/EPG.pm:686 ../lib/XXV/MODULES/EPG.pm:806 ../lib/XXV/MODULES/EPG.pm:915 ../lib/XXV/MODULES/MOVETIMER.pm:577 ../lib/XXV/MODULES/MUSIC.pm:614 ../lib/XXV/MODULES/SHARE.pm:343 ../lib/XXV/MODULES/SVDRP.pm:318 ../lib/XXV/MODULES/TIMERS.pm:1331 ../lib/XXV/MODULES/USER.pm:532 ../lib/XXV/MODULES/XMLTV.pm:676 msgid "Service" msgstr "Service" @@ -314,12 +321,12 @@ msgid "Search with OFDb" msgstr "Suche mit OFDb" #-------------------- -#: ../html/display.tmpl:60 ../lib/XXV/MODULES/AUTOTIMER.pm:466 ../lib/XXV/MODULES/AUTOTIMER.pm:676 ../lib/XXV/MODULES/EPG.pm:917 ../lib/XXV/MODULES/RECORDS.pm:2122 ../lib/XXV/MODULES/RECORDS.pm:2338 ../lib/XXV/MODULES/TIMERS.pm:858 ../lib/XXV/OUTPUT/Console.pm:171 +#: ../html/display.tmpl:60 ../lib/XXV/MODULES/AUTOTIMER.pm:465 ../lib/XXV/MODULES/AUTOTIMER.pm:675 ../lib/XXV/MODULES/EPG.pm:921 ../lib/XXV/MODULES/RECORDS.pm:2113 ../lib/XXV/MODULES/RECORDS.pm:2314 ../lib/XXV/MODULES/TIMERS.pm:840 ../lib/XXV/OUTPUT/Console.pm:171 msgid "Description" msgstr "Beschreibung" #-------------------- -#: ../html/display.tmpl:69 ../lib/XXV/MODULES/AUTOTIMER.pm:181 ../lib/XXV/MODULES/AUTOTIMER.pm:460 ../lib/XXV/MODULES/AUTOTIMER.pm:463 ../lib/XXV/MODULES/CHRONICLE.pm:178 ../lib/XXV/MODULES/CHRONICLE.pm:259 ../lib/XXV/MODULES/EPG.pm:1041 ../lib/XXV/MODULES/EPG.pm:1172 ../lib/XXV/MODULES/EPG.pm:679 ../lib/XXV/MODULES/EPG.pm:805 ../lib/XXV/MODULES/EPG.pm:915 ../lib/XXV/MODULES/SHARE.pm:346 ../lib/XXV/MODULES/TIMERS.pm:1335 ../lib/XXV/MODULES/TIMERS.pm:954 +#: ../html/display.tmpl:69 ../lib/XXV/MODULES/AUTOTIMER.pm:180 ../lib/XXV/MODULES/AUTOTIMER.pm:459 ../lib/XXV/MODULES/AUTOTIMER.pm:462 ../lib/XXV/MODULES/CHRONICLE.pm:178 ../lib/XXV/MODULES/CHRONICLE.pm:259 ../lib/XXV/MODULES/EPG.pm:1064 ../lib/XXV/MODULES/EPG.pm:1187 ../lib/XXV/MODULES/EPG.pm:689 ../lib/XXV/MODULES/EPG.pm:808 ../lib/XXV/MODULES/EPG.pm:919 ../lib/XXV/MODULES/SHARE.pm:346 ../lib/XXV/MODULES/TIMERS.pm:1335 ../lib/XXV/MODULES/TIMERS.pm:949 msgid "Start" msgstr "Start" @@ -329,7 +336,7 @@ msgid "PDC" msgstr "VPS" #-------------------- -#: ../html/display.tmpl:75 ../html/widgets/player.tmpl:100 ../html/widgets/player.tmpl:60 ../lib/XXV/MODULES/AUTOTIMER.pm:182 ../lib/XXV/MODULES/AUTOTIMER.pm:461 ../lib/XXV/MODULES/AUTOTIMER.pm:464 ../lib/XXV/MODULES/CHRONICLE.pm:179 ../lib/XXV/MODULES/CHRONICLE.pm:260 ../lib/XXV/MODULES/EPG.pm:1042 ../lib/XXV/MODULES/EPG.pm:1173 ../lib/XXV/MODULES/EPG.pm:680 ../lib/XXV/MODULES/EPG.pm:806 ../lib/XXV/MODULES/EPG.pm:916 ../lib/XXV/MODULES/SHARE.pm:347 ../lib/XXV/MODULES/TIMERS.pm:1336 +#: ../html/display.tmpl:75 ../html/widgets/player.tmpl:100 ../html/widgets/player.tmpl:60 ../lib/XXV/MODULES/AUTOTIMER.pm:181 ../lib/XXV/MODULES/AUTOTIMER.pm:460 ../lib/XXV/MODULES/AUTOTIMER.pm:463 ../lib/XXV/MODULES/CHRONICLE.pm:179 ../lib/XXV/MODULES/CHRONICLE.pm:260 ../lib/XXV/MODULES/EPG.pm:1065 ../lib/XXV/MODULES/EPG.pm:1188 ../lib/XXV/MODULES/EPG.pm:690 ../lib/XXV/MODULES/EPG.pm:809 ../lib/XXV/MODULES/EPG.pm:920 ../lib/XXV/MODULES/SHARE.pm:347 ../lib/XXV/MODULES/TIMERS.pm:1336 msgid "Stop" msgstr "Stopp" @@ -339,82 +346,67 @@ msgid "Total space" msgstr "Gesamte Speicherkapazität" #-------------------- -#: ../html/help.tmpl:102 -msgid "Documentation" -msgstr "Dokumentation" - -#-------------------- -#: ../html/help.tmpl:103 -msgid "News" -msgstr "Neuigkeiten" - -#-------------------- -#: ../html/help.tmpl:104 ../lib/XXV/MODULES/MEDIALIB.pm:1258 -msgid "History" -msgstr "Geschichte" - -#-------------------- -#: ../html/help.tmpl:105 -msgid "License" -msgstr "Lizenz" - -#-------------------- -#: ../html/help.tmpl:106 +#: ../html/help.tmpl:100 msgid "Readme" msgstr "Liesmich" #-------------------- -#: ../html/help.tmpl:107 +#: ../html/help.tmpl:101 msgid "Tutorial" msgstr "Anleitung" #-------------------- -#: ../html/help.tmpl:111 +#: ../html/help.tmpl:105 msgid "Log files" msgstr "Log-Dateien" #-------------------- -#: ../html/help.tmpl:112 +#: ../html/help.tmpl:106 msgid "Standard" msgstr "Standard" #-------------------- -#: ../html/help.tmpl:113 +#: ../html/help.tmpl:107 msgid "Syslog" msgstr "Syslog" #-------------------- -#: ../html/help.tmpl:117 +#: ../html/help.tmpl:111 msgid "Administration" msgstr "Administration" #-------------------- -#: ../html/help.tmpl:118 ../lib/XXV/MODULES/USER.pm:356 +#: ../html/help.tmpl:114 ../lib/XXV/MODULES/USER.pm:356 msgid "User" msgstr "Anwender" #-------------------- -#: ../html/help.tmpl:119 +#: ../html/help.tmpl:115 msgid "Personality" msgstr "Persönlichkeit" #-------------------- -#: ../html/help.tmpl:120 +#: ../html/help.tmpl:116 msgid "Reload" msgstr "Erneut laden" #-------------------- -#: ../html/help.tmpl:121 +#: ../html/help.tmpl:117 msgid "Restart" msgstr "Neustart" #-------------------- -#: ../html/help.tmpl:124 +#: ../html/help.tmpl:121 ../lib/XXV/MODULES/USER.pm:535 +msgid "Preferences" +msgstr "Einstellungen" + +#-------------------- +#: ../html/help.tmpl:129 msgid "Logout" msgstr "Abmelden" #-------------------- -#: ../html/help.tmpl:133 +#: ../html/help.tmpl:138 msgid "search" msgstr "Suchen" @@ -440,125 +432,134 @@ msgid "Top ten entry" msgstr "Die besten Zehn" #-------------------- -#: ../html/help.tmpl:60 +#: ../html/help.tmpl:64 #. (15) msgid "Programming" msgstr "Programmierung" #-------------------- -#: ../html/help.tmpl:61 ../lib/XXV/MODULES/HTTPD.pm:649 ../lib/XXV/MODULES/WAPD.pm:78 ../wml/tlist.tmpl:2 ../wml/tsearch.tmpl:2 ../wml/widgets/footer.tmpl:15 +#: ../html/help.tmpl:65 ../lib/XXV/MODULES/HTTPD.pm:649 ../lib/XXV/MODULES/WAPD.pm:78 ../wml/tlist.tmpl:2 ../wml/widgets/footer.tmpl:15 #. (12) msgid "Timers" msgstr "Timer" #-------------------- -#: ../html/help.tmpl:62 ../lib/XXV/MODULES/HTTPD.pm:648 ../lib/XXV/MODULES/WAPD.pm:77 ../wml/widgets/footer.tmpl:17 +#: ../html/help.tmpl:66 ../lib/XXV/MODULES/HTTPD.pm:648 ../lib/XXV/MODULES/WAPD.pm:77 ../wml/widgets/footer.tmpl:17 #. (12) msgid "Autotimer" msgstr "Autotimer" #-------------------- -#: ../html/help.tmpl:63 +#: ../html/help.tmpl:67 #. (12) msgid "Rules to move timer" msgstr "Regel zum Verschieben von Timern" #-------------------- -#: ../html/help.tmpl:67 +#: ../html/help.tmpl:71 #. (15) msgid "Media content" msgstr "Medieninhalte" #-------------------- -#: ../html/help.tmpl:68 ../lib/XXV/MODULES/HTTPD.pm:650 ../lib/XXV/MODULES/WAPD.pm:79 ../wml/widgets/footer.tmpl:18 +#: ../html/help.tmpl:72 ../lib/XXV/MODULES/HTTPD.pm:650 ../lib/XXV/MODULES/WAPD.pm:79 ../wml/widgets/footer.tmpl:18 #. (12) msgid "Recordings" msgstr "Aufnahmen" #-------------------- -#: ../html/help.tmpl:69 ../lib/XXV/MODULES/HTTPD.pm:651 ../lib/XXV/MODULES/MEDIALIB.pm:1250 ../lib/XXV/MODULES/WAPD.pm:80 +#: ../html/help.tmpl:73 ../lib/XXV/MODULES/HTTPD.pm:651 ../lib/XXV/MODULES/MEDIALIB.pm:1250 ../lib/XXV/MODULES/WAPD.pm:80 #. (12) msgid "Music" msgstr "Musik" #-------------------- -#: ../html/help.tmpl:70 +#: ../html/help.tmpl:74 #. (12) msgid "Media library" msgstr "Medienbibliothek" #-------------------- -#: ../html/help.tmpl:74 +#: ../html/help.tmpl:78 #. (15) msgid "Tools" msgstr "Werkzeuge" #-------------------- -#: ../html/help.tmpl:75 ../lib/XXV/MODULES/HTTPD.pm:652 ../lib/XXV/MODULES/WAPD.pm:81 ../wml/widgets/footer.tmpl:19 +#: ../html/help.tmpl:79 ../lib/XXV/MODULES/HTTPD.pm:652 ../lib/XXV/MODULES/WAPD.pm:81 ../wml/widgets/footer.tmpl:19 #. (12) msgid "Remote" msgstr "Fernbedienung" #-------------------- -#: ../html/help.tmpl:76 ../html/widgets/vtx.tmpl:3 ../lib/XXV/MODULES/HTTPD.pm:653 ../lib/XXV/MODULES/WAPD.pm:82 +#: ../html/help.tmpl:80 ../html/widgets/vtx.tmpl:3 ../lib/XXV/MODULES/HTTPD.pm:653 ../lib/XXV/MODULES/WAPD.pm:82 #. (12) msgid "Teletext" msgstr "Videotext" #-------------------- -#: ../html/help.tmpl:77 +#: ../html/help.tmpl:81 #. (12) msgid "Report" msgstr "Bericht" #-------------------- -#: ../html/help.tmpl:78 +#: ../html/help.tmpl:82 #. (12) msgid "Commands" msgstr "Kommandos" #-------------------- -#: ../html/help.tmpl:83 ../lib/XXV/MODULES/USER.pm:535 -msgid "Preferences" -msgstr "Einstellungen" - -#-------------------- -#: ../html/help.tmpl:89 -#. (10) -msgid "Edit channels" -msgstr "Kanäle bearbeiten" - -#-------------------- -#: ../html/help.tmpl:93 ../html/widgets/player.tmpl:105 ../html/widgets/player.tmpl:69 ../lib/XXV/MODULES/HTTPD.pm:654 ../lib/XXV/MODULES/TIMERS.pm:1332 ../lib/XXV/MODULES/WAPD.pm:83 +#: ../html/help.tmpl:87 ../html/widgets/player.tmpl:105 ../html/widgets/player.tmpl:69 ../lib/XXV/MODULES/HTTPD.pm:654 ../lib/XXV/MODULES/TIMERS.pm:1332 ../lib/XXV/MODULES/WAPD.pm:83 msgid "Status" msgstr "Status" #-------------------- -#: ../html/help.tmpl:94 ../lib/XXV/MODULES/STATUS.pm:217 +#: ../html/help.tmpl:88 ../lib/XXV/MODULES/STATUS.pm:217 msgid "Vitals" msgstr "Wichtiges" #-------------------- -#: ../html/help.tmpl:95 ../lib/XXV/MODULES/STATUS.pm:281 +#: ../html/help.tmpl:89 ../lib/XXV/MODULES/STATUS.pm:281 msgid "Memory" msgstr "Speicher" #-------------------- -#: ../html/help.tmpl:96 ../lib/XXV/MODULES/STATUS.pm:717 +#: ../html/help.tmpl:90 ../lib/XXV/MODULES/STATUS.pm:717 msgid "Filesystem" msgstr "Filesystem" #-------------------- -#: ../html/help.tmpl:97 ../lib/XXV/MODULES/STATUS.pm:235 +#: ../html/help.tmpl:91 ../lib/XXV/MODULES/STATUS.pm:235 msgid "Network" msgstr "Netzwerk" #-------------------- -#: ../html/help.tmpl:98 +#: ../html/help.tmpl:92 msgid "Hardware" msgstr "Hardware" #-------------------- +#: ../html/help.tmpl:96 +msgid "Documentation" +msgstr "Dokumentation" + +#-------------------- +#: ../html/help.tmpl:97 +msgid "News" +msgstr "Neuigkeiten" + +#-------------------- +#: ../html/help.tmpl:98 ../lib/XXV/MODULES/MEDIALIB.pm:1258 +msgid "History" +msgstr "Geschichte" + +#-------------------- +#: ../html/help.tmpl:99 +msgid "License" +msgstr "Lizenz" + +#-------------------- #: ../html/javascript/records.js:7 msgid "When you want this timer save then has him a conflict with timer: " msgstr "Wenn du diesen Timer zu speichern wünschst, dann hat er ein Konflikt mit Timer: " @@ -684,7 +685,7 @@ msgid "Save" msgstr "Speichern" #-------------------- -#: ../html/mlcopy.tmpl:23 ../html/mledit.tmpl:23 ../html/mlimport.tmpl:23 ../lib/XXV/MODULES/AUTOTIMER.pm:178 ../lib/XXV/MODULES/AUTOTIMER.pm:454 ../lib/XXV/MODULES/AUTOTIMER.pm:674 ../lib/XXV/MODULES/CHRONICLE.pm:175 ../lib/XXV/MODULES/CHRONICLE.pm:256 ../lib/XXV/MODULES/EPG.pm:1039 ../lib/XXV/MODULES/EPG.pm:1170 ../lib/XXV/MODULES/EPG.pm:677 ../lib/XXV/MODULES/EPG.pm:803 ../lib/XXV/MODULES/EPG.pm:912 ../lib/XXV/MODULES/MEDIALIB.pm:1294 ../lib/XXV/MODULES/MUSIC.pm:617 ../lib/XXV/MODULES/RECORDS.pm:1641 ../lib/XXV/MODULES/RECORDS.pm:1778 ../lib/XXV/MODULES/SHARE.pm:344 ../lib/XXV/MODULES/TIMERS.pm:1337 ../lib/XXV/MODULES/TIMERS.pm:952 +#: ../html/mlcopy.tmpl:23 ../html/mledit.tmpl:23 ../html/mlimport.tmpl:23 ../lib/XXV/MODULES/AUTOTIMER.pm:177 ../lib/XXV/MODULES/AUTOTIMER.pm:453 ../lib/XXV/MODULES/AUTOTIMER.pm:673 ../lib/XXV/MODULES/CHRONICLE.pm:175 ../lib/XXV/MODULES/CHRONICLE.pm:256 ../lib/XXV/MODULES/EPG.pm:1062 ../lib/XXV/MODULES/EPG.pm:1185 ../lib/XXV/MODULES/EPG.pm:687 ../lib/XXV/MODULES/EPG.pm:807 ../lib/XXV/MODULES/EPG.pm:916 ../lib/XXV/MODULES/MEDIALIB.pm:1294 ../lib/XXV/MODULES/MUSIC.pm:617 ../lib/XXV/MODULES/RECORDS.pm:1632 ../lib/XXV/MODULES/RECORDS.pm:1769 ../lib/XXV/MODULES/SHARE.pm:344 ../lib/XXV/MODULES/TIMERS.pm:1337 ../lib/XXV/MODULES/TIMERS.pm:947 msgid "Title" msgstr "Titel" @@ -694,7 +695,7 @@ msgid "Search at" msgstr "Suche bei" #-------------------- -#: ../html/mlcopy.tmpl:36 ../html/mledit.tmpl:36 ../html/mlimport.tmpl:36 ../lib/XXV/MODULES/AUTOTIMER.pm:455 ../lib/XXV/MODULES/AUTOTIMER.pm:675 ../lib/XXV/MODULES/EPG.pm:913 ../lib/XXV/MODULES/MEDIALIB.pm:1295 ../lib/XXV/MODULES/RECORDS.pm:1642 ../lib/XXV/MODULES/RECORDS.pm:1779 +#: ../html/mlcopy.tmpl:36 ../html/mledit.tmpl:36 ../html/mlimport.tmpl:36 ../lib/XXV/MODULES/AUTOTIMER.pm:454 ../lib/XXV/MODULES/AUTOTIMER.pm:674 ../lib/XXV/MODULES/EPG.pm:917 ../lib/XXV/MODULES/MEDIALIB.pm:1295 ../lib/XXV/MODULES/RECORDS.pm:1633 ../lib/XXV/MODULES/RECORDS.pm:1770 msgid "Subtitle" msgstr "Serientitel" @@ -779,7 +780,7 @@ msgid "Albums" msgstr "Alben" #-------------------- -#: ../html/mlist.tmpl:24 ../html/mlnavcontainer.tmpl:28 ../html/mlsearch.tmpl:46 ../html/search.tmpl:75 ../html/widgets/vtx.tmpl:28 ../lib/XXV/MODULES/AUTOTIMER.pm:1174 ../wml/next.tmpl:15 ../wml/now.tmpl:15 ../wml/program.tmpl:43 ../wml/search.tmpl:17 +#: ../html/mlist.tmpl:24 ../html/mlnavcontainer.tmpl:28 ../html/mlsearch.tmpl:46 ../html/search.tmpl:75 ../html/widgets/vtx.tmpl:28 ../lib/XXV/MODULES/AUTOTIMER.pm:1172 ../wml/next.tmpl:15 ../wml/now.tmpl:15 ../wml/program.tmpl:43 ../wml/search.tmpl:17 msgid "Search" msgstr "Suche" @@ -840,7 +841,7 @@ msgid "Copy" msgstr "Kopieren" #-------------------- -#: ../html/mlnavcontainer.tmpl:22 ../wml/tlist.tmpl:49 ../wml/tsearch.tmpl:49 +#: ../html/mlnavcontainer.tmpl:22 ../html/ulist.tmpl:30 ../html/vdrlist.tmpl:30 ../wml/tlist.tmpl:49 msgid "Delete" msgstr "Löschen" @@ -905,7 +906,7 @@ msgid "Rules to move timer between channels" msgstr "Regeln zum Verschieben von Timern zwischen Kanälen" #-------------------- -#: ../html/movetimerlist.tmpl:54 ../html/movetimerlist.tmpl:55 ../lib/XXV/MODULES/MOVETIMER.pm:452 +#: ../html/movetimerlist.tmpl:54 ../html/movetimerlist.tmpl:55 ../lib/XXV/MODULES/MOVETIMER.pm:477 #. (25) msgid "Create a new rule to move timer" msgstr "Erzeuge eine neue Regel zum Verschieben von Timern" @@ -928,22 +929,22 @@ msgid "Would you like to delete these rules?" msgstr "Wollen Sie diese Regeln löschen?" #-------------------- -#: ../html/movetimerlist.tmpl:7 ../lib/XXV/MODULES/MOVETIMER.pm:451 +#: ../html/movetimerlist.tmpl:7 ../lib/XXV/MODULES/MOVETIMER.pm:476 msgid "Edit rule to move timer" msgstr "Regel zum Verschieben von Timern bearbeiten" #-------------------- -#: ../html/movetimerlist.tmpl:83 ../lib/XXV/MODULES/MOVETIMER.pm:554 +#: ../html/movetimerlist.tmpl:83 ../lib/XXV/MODULES/MOVETIMER.pm:579 msgid "Destination" msgstr "Ziel" #-------------------- -#: ../html/movetimerlist.tmpl:84 ../lib/XXV/MODULES/MOVETIMER.pm:555 ../lib/XXV/MODULES/MOVETIMER.pm:624 +#: ../html/movetimerlist.tmpl:84 ../lib/XXV/MODULES/MOVETIMER.pm:580 ../lib/XXV/MODULES/MOVETIMER.pm:649 msgid "Move timer" msgstr "Verschiebe Timer" #-------------------- -#: ../html/movetimerlist.tmpl:85 ../lib/XXV/MODULES/MOVETIMER.pm:556 +#: ../html/movetimerlist.tmpl:85 ../lib/XXV/MODULES/MOVETIMER.pm:581 msgid "Change original timer" msgstr "Ändere original Timer" @@ -1043,7 +1044,7 @@ msgid "New recording" msgstr "Neue Aufnahme" #-------------------- -#: ../html/rdisplay.tmpl:167 ../lib/XXV/MODULES/RECORDS.pm:2131 +#: ../html/rdisplay.tmpl:167 ../lib/XXV/MODULES/RECORDS.pm:2122 msgid "Keywords" msgstr "Stichwörter" @@ -1053,12 +1054,12 @@ msgid "Lifetime" msgstr "Lebenszeit" #-------------------- -#: ../html/rdisplay.tmpl:190 ../lib/XXV/MODULES/AUTOTIMER.pm:183 ../lib/XXV/MODULES/TIMERS.pm:1338 +#: ../html/rdisplay.tmpl:190 ../lib/XXV/MODULES/AUTOTIMER.pm:182 ../lib/XXV/MODULES/TIMERS.pm:1338 msgid "Priority" msgstr "Priorität" #-------------------- -#: ../html/rdisplay.tmpl:65 ../html/rlist.tmpl:102 ../lib/XXV/MODULES/RECORDS.pm:1643 ../lib/XXV/MODULES/RECORDS.pm:1780 +#: ../html/rdisplay.tmpl:65 ../html/rlist.tmpl:102 ../lib/XXV/MODULES/RECORDS.pm:1634 ../lib/XXV/MODULES/RECORDS.pm:1771 msgid "Duration" msgstr "Dauer" @@ -1068,7 +1069,7 @@ msgid "Recording list" msgstr "Aufnahmeliste" #-------------------- -#: ../html/rdisplay.tmpl:78 ../lib/XXV/MODULES/RECORDS.pm:1932 +#: ../html/rdisplay.tmpl:78 ../lib/XXV/MODULES/RECORDS.pm:1923 msgid "Would you like to delete this recording?" msgstr "Wollen Sie diese Aufnahme löschen?" @@ -1083,7 +1084,7 @@ msgid "Cut recording" msgstr "Aufnahme schneiden" #-------------------- -#: ../html/rdisplay.tmpl:86 ../lib/XXV/MODULES/RECORDS.pm:2151 +#: ../html/rdisplay.tmpl:86 ../lib/XXV/MODULES/RECORDS.pm:2142 msgid "Edit recording" msgstr "Aufnahme bearbeiten" @@ -1113,7 +1114,7 @@ msgid "Stored recordings" msgstr "Gespeicherte Aufnahmen" #-------------------- -#: ../html/rlist.tmpl:120 ../lib/XXV/MODULES/RECORDS.pm:120 +#: ../html/rlist.tmpl:120 ../lib/XXV/MODULES/RECORDS.pm:119 msgid "Update recordings" msgstr "Lese die Aufnahmeliste neu ein" @@ -1128,7 +1129,7 @@ msgid "Delete recordings" msgstr "Aufnahmen löschen" #-------------------- -#: ../html/rlist.tmpl:127 ../lib/XXV/MODULES/RECORDS.pm:134 +#: ../html/rlist.tmpl:127 ../lib/XXV/MODULES/RECORDS.pm:133 msgid "Recover deleted recordings" msgstr "Gelöschte Aufnahmen wiederherstellen" @@ -1268,13 +1269,13 @@ msgid "Jump to program:" msgstr "Springe zum Programm:" #-------------------- -#: ../html/tlist.tmpl:13 ../wml/tlist.tmpl:8 ../wml/tsearch.tmpl:8 +#: ../html/tlist.tmpl:13 ../wml/tlist.tmpl:8 #. (12) msgid "Create new timer" msgstr "Erzeuge neuen Timer" #-------------------- -#: ../html/tlist.tmpl:16 ../wml/tlist.tmpl:11 ../wml/tsearch.tmpl:11 +#: ../html/tlist.tmpl:16 ../wml/tlist.tmpl:11 #. (12) msgid "Update timers" msgstr "Aktualisieren der Timer" @@ -1305,7 +1306,7 @@ msgid "Planned recordings" msgstr "Geplante Aufnahmen" #-------------------- -#: ../html/tlist.tmpl:83 ../lib/XXV/MODULES/TIMERS.pm:959 +#: ../html/tlist.tmpl:83 ../lib/XXV/MODULES/TIMERS.pm:954 msgid "Would you like to delete this timer?" msgstr "Wollen Sie diesen Timer löschen?" @@ -1350,6 +1351,31 @@ msgid "Create new account for user" msgstr "Erzeuge neuen Anwenderzugang" #-------------------- +#: ../html/vdrlist.tmpl:2 +msgid "Administration of video disk recorder" +msgstr "Verwaltung der Video Disk Rekorder" + +#-------------------- +#: ../html/vdrlist.tmpl:26 +msgid "Edit definition of video disk recorder" +msgstr "Bearbeite die Definition eines Video Disk Rekorder" + +#-------------------- +#: ../html/vdrlist.tmpl:28 +msgid "Delete definition of video disk recorder" +msgstr "Lösche die Definition eines Video Disk Rekorder" + +#-------------------- +#: ../html/vdrlist.tmpl:29 +msgid "Would you like to delete this definition of video disk recorder?" +msgstr "Wollen Sie die Definition des Video Disk Rekorder wirklich löschen?" + +#-------------------- +#: ../html/vdrlist.tmpl:4 +msgid "Create new definition of video disk recorder" +msgstr "Erzeuge neue Definierung eines Video Disk Rekorder" + +#-------------------- #: ../html/vitals.tmpl:46 msgid "Average load" msgstr "Durchschnittliche Auslastung" @@ -1470,7 +1496,7 @@ msgid "Volume" msgstr "Lautstärke" #-------------------- -#: ../html/widgets/remote.tmpl:109 ../wml/next.tmpl:32 ../wml/next.tmpl:46 ../wml/now.tmpl:32 ../wml/now.tmpl:46 ../wml/program.tmpl:25 ../wml/program.tmpl:63 ../wml/program.tmpl:77 ../wml/search.tmpl:34 ../wml/search.tmpl:48 ../wml/tlist.tmpl:13 ../wml/tlist.tmpl:62 ../wml/tlist.tmpl:76 ../wml/tsearch.tmpl:13 ../wml/tsearch.tmpl:62 ../wml/tsearch.tmpl:76 ../wml/widgets/err.tmpl:18 ../wml/widgets/footer.tmpl:2 ../wml/widgets/formEnd.tmpl:5 ../wml/widgets/message.tmpl:18 +#: ../html/widgets/remote.tmpl:109 ../wml/next.tmpl:32 ../wml/next.tmpl:46 ../wml/now.tmpl:32 ../wml/now.tmpl:46 ../wml/program.tmpl:25 ../wml/program.tmpl:63 ../wml/program.tmpl:77 ../wml/search.tmpl:34 ../wml/search.tmpl:48 ../wml/tlist.tmpl:13 ../wml/tlist.tmpl:62 ../wml/tlist.tmpl:76 ../wml/widgets/err.tmpl:18 ../wml/widgets/footer.tmpl:2 ../wml/widgets/formEnd.tmpl:5 ../wml/widgets/message.tmpl:18 msgid "Menu" msgstr "Menü" @@ -1525,277 +1551,277 @@ msgid "Next page" msgstr "Nächste Seite" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1002 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1000 msgid "Stop date as YYYY-MM-DD HH:MM:SS." msgstr "Enddatum als DD.MM.YYYY HH:MM:SS." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1008 ../lib/XXV/MODULES/AUTOTIMER.pm:976 ../lib/XXV/MODULES/TIMERS.pm:760 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1006 ../lib/XXV/MODULES/AUTOTIMER.pm:974 ../lib/XXV/MODULES/TIMERS.pm:741 msgid "Language=English" msgstr "Language=German,DateFormat=non-US" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1015 ../lib/XXV/MODULES/AUTOTIMER.pm:983 ../lib/XXV/MODULES/TIMERS.pm:774 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1013 ../lib/XXV/MODULES/AUTOTIMER.pm:981 ../lib/XXV/MODULES/TIMERS.pm:755 msgid "The day is incorrect or was in a wrong format!" msgstr "Das eingegebene Datum ist nicht korrekt oder hatte ein falsches Format!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1021 ../lib/XXV/MODULES/TIMERS.pm:851 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1019 ../lib/XXV/MODULES/TIMERS.pm:832 msgid "Add keywords to recording" msgstr "Stichwörter zur Aufnahme hinzufügen" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1037 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1035 msgid "Autotimer saved!" msgstr "Autotimer gespeichert!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1057 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1055 msgid "No autotimer defined for deletion! Please use adelete 'aid'!" msgstr "Kein Autotimer zum Löschen definiert! Bitte verwende adelete 'aid'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1066 ../lib/XXV/MODULES/AUTOTIMER.pm:1096 ../lib/XXV/MODULES/AUTOTIMER.pm:1105 ../lib/XXV/MODULES/AUTOTIMER.pm:642 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1064 ../lib/XXV/MODULES/AUTOTIMER.pm:1094 ../lib/XXV/MODULES/AUTOTIMER.pm:1103 ../lib/XXV/MODULES/AUTOTIMER.pm:641 msgid "The autotimer '%s' does not exist in the database." msgstr "Der Autotimer '%s' existiert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1070 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1068 msgid "Autotimer %s deleted." msgstr "Autotimer %s wurde gelöscht." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1088 -msgid "No autotimer defined to toggle! Please use atoggle 'aid'!" -msgstr "Kein ID eines Autotimer zum Umschalten definiert! Bitte verwende atoggle 'aid'" - -#-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:109 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:108 msgid "Create event entries if an autotimer has created a new timer." msgstr "Erzeuge Eventeinträge, wenn eine neuer Timer durch einen Autotimer erzeugt wurde." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1115 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1086 +msgid "No autotimer defined to toggle! Please use atoggle 'aid'!" +msgstr "Kein ID eines Autotimer zum Umschalten definiert! Bitte verwende atoggle 'aid'" + +#-------------------- +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1113 msgid "Couldn't toggle autotimer with ID '%s'!" msgstr "Konnte Autotimer mit ID '%s' nicht umschalten!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1126 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1124 msgid "disabled" msgstr "Deaktiviert" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1127 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1125 msgid "activated" msgstr "Aktiviert" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1128 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1126 msgid "Autotimer %s is %s." msgstr "Autotimer %s ist %s." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1173 -msgid "Activ" +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1171 ../lib/XXV/MODULES/SVDRP.pm:319 ../lib/XXV/MODULES/XMLTV.pm:677 +msgid "Active" msgstr "Aktiv" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1176 ../lib/XXV/MODULES/RECORDS.pm:1644 ../lib/XXV/MODULES/RECORDS.pm:1781 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1174 ../lib/XXV/MODULES/RECORDS.pm:1635 ../lib/XXV/MODULES/RECORDS.pm:1772 msgid "Start time" msgstr "Startzeit" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1177 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1175 msgid "Stop time" msgstr "Stoppzeit" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1178 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1176 msgid "Directory" msgstr "Verzeichnis" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1179 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1177 msgid "Minimum length" msgstr "Minimale Länge" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:1256 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:1254 msgid "Unknown channel : %s" msgstr "Unbekannter Kanal : %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:136 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:135 msgid "Autotimer('%s') found: %s" msgstr "Autotimer('%s') hat gefunden: %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:142 ../lib/XXV/MODULES/TIMERS.pm:155 ../lib/XXV/MODULES/TIMERS.pm:210 ../lib/XXV/MODULES/TIMERS.pm:264 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:141 ../lib/XXV/MODULES/TIMERS.pm:149 ../lib/XXV/MODULES/TIMERS.pm:204 ../lib/XXV/MODULES/TIMERS.pm:258 msgid "Channel: %s" msgstr "Kanal: %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:148 ../lib/XXV/MODULES/TIMERS.pm:162 ../lib/XXV/MODULES/TIMERS.pm:217 ../lib/XXV/MODULES/TIMERS.pm:272 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:147 ../lib/XXV/MODULES/TIMERS.pm:156 ../lib/XXV/MODULES/TIMERS.pm:211 ../lib/XXV/MODULES/TIMERS.pm:266 msgid "On: %s to %s" msgstr "Um: %s bis %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:152 ../lib/XXV/MODULES/RECORDS.pm:216 ../lib/XXV/MODULES/TIMERS.pm:166 ../lib/XXV/MODULES/TIMERS.pm:221 ../lib/XXV/MODULES/TIMERS.pm:276 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:151 ../lib/XXV/MODULES/RECORDS.pm:215 ../lib/XXV/MODULES/TIMERS.pm:160 ../lib/XXV/MODULES/TIMERS.pm:215 ../lib/XXV/MODULES/TIMERS.pm:270 msgid "Description: %s" msgstr "Beschreibung: %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:179 ../lib/XXV/MODULES/CHRONICLE.pm:177 ../lib/XXV/MODULES/CHRONICLE.pm:258 ../lib/XXV/MODULES/EPG.pm:681 ../lib/XXV/MODULES/EPG.pm:807 ../lib/XXV/MODULES/SHARE.pm:348 ../lib/XXV/MODULES/TIMERS.pm:1333 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:178 ../lib/XXV/MODULES/CHRONICLE.pm:177 ../lib/XXV/MODULES/CHRONICLE.pm:258 ../lib/XXV/MODULES/EPG.pm:691 ../lib/XXV/MODULES/EPG.pm:810 ../lib/XXV/MODULES/SHARE.pm:348 ../lib/XXV/MODULES/TIMERS.pm:1333 msgid "Day" msgstr "Datum" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:20 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:19 msgid "This module searches for EPG entries with user-defined text and creates new timers." msgstr "Diese Modul sucht nach EPG Einträgen mit nutzerdefinierten Texten und erzeugt neue Timer." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:224 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:223 msgid "Autotimer has programmed %d new timer(s) since last report to %s" msgstr "Autotimer hat %d neuen Timer programmiert, seit letztem Report an %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:28 ../lib/XXV/MODULES/CHRONICLE.pm:24 ../lib/XXV/MODULES/EVENTS.pm:30 ../lib/XXV/MODULES/HTTPD.pm:59 ../lib/XXV/MODULES/INTERFACE.pm:29 ../lib/XXV/MODULES/KEYWORDS.pm:24 ../lib/XXV/MODULES/LOGREAD.pm:28 ../lib/XXV/MODULES/MEDIALIB.pm:29 ../lib/XXV/MODULES/MOVETIMER.pm:23 ../lib/XXV/MODULES/MUSIC.pm:36 ../lib/XXV/MODULES/REMOTE.pm:25 ../lib/XXV/MODULES/REPORT.pm:26 ../lib/XXV/MODULES/ROBOT.pm:25 ../lib/XXV/MODULES/SHARE.pm:61 ../lib/XXV/MODULES/STATUS.pm:28 ../lib/XXV/MODULES/TELNET.pm:26 ../lib/XXV/MODULES/VTX.pm:25 ../lib/XXV/MODULES/WAPD.pm:39 ../lib/XXV/MODULES/XMLTV.pm:29 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:65 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:30 ../lib/XXV/OUTPUT/NEWS/RSS.pm:29 ../lib/XXV/OUTPUT/NEWS/VDR.pm:26 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:27 ../lib/XXV/MODULES/CHRONICLE.pm:24 ../lib/XXV/MODULES/EVENTS.pm:30 ../lib/XXV/MODULES/HTTPD.pm:59 ../lib/XXV/MODULES/INTERFACE.pm:29 ../lib/XXV/MODULES/KEYWORDS.pm:25 ../lib/XXV/MODULES/LOGREAD.pm:28 ../lib/XXV/MODULES/MEDIALIB.pm:29 ../lib/XXV/MODULES/MOVETIMER.pm:23 ../lib/XXV/MODULES/MUSIC.pm:36 ../lib/XXV/MODULES/REMOTE.pm:25 ../lib/XXV/MODULES/REPORT.pm:26 ../lib/XXV/MODULES/ROBOT.pm:25 ../lib/XXV/MODULES/SHARE.pm:61 ../lib/XXV/MODULES/STATUS.pm:28 ../lib/XXV/MODULES/TELNET.pm:26 ../lib/XXV/MODULES/VTX.pm:25 ../lib/XXV/MODULES/WAPD.pm:39 ../lib/XXV/MODULES/XMLTV.pm:29 ../lib/XXV/OUTPUT/NEWS/JABBER.pm:65 ../lib/XXV/OUTPUT/NEWS/MAIL.pm:30 ../lib/XXV/OUTPUT/NEWS/RSS.pm:29 ../lib/XXV/OUTPUT/NEWS/VDR.pm:26 msgid "Activate this service" msgstr "Aktiviere diesen Dienst" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:34 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:33 msgid "Exclude channels from autotimer" msgstr "Schliesse Kanäle von Autotimer aus." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:355 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:354 msgid "Searching for autotimer ..." msgstr "Schaue nach Autotimer ..." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:365 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:364 msgid "Autotimer process created %d timers and modified %d timers." msgstr "Autotimervorgang hat %d Timer erzeugt und %d Timer modifiziert." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:369 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:368 msgid "Back to autotimer listing." msgstr "Zurück zur Autotimer Liste" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:438 ../lib/XXV/MODULES/AUTOTIMER.pm:443 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:437 ../lib/XXV/MODULES/AUTOTIMER.pm:442 msgid "Search for autotimer '%s'" msgstr "Schaue nach Autotimer '%s'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:451 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:450 msgid "Found %d entries for '%s' in EPG database." msgstr "%d Einträge für '%s' in EPG Datenbank gefunden." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:49 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:48 msgid "Display status of autotimers." msgstr "Status der Autotimer anzeigen." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:558 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:557 msgid "Could not save timer for '%s' : %s" msgstr "Konnte Timer für '%s' nicht speichern : %s" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:563 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:562 msgid "Modified timer for '%s'." msgstr "Timer für '%s' modifiziert." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:567 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:566 msgid "Timer for '%s' has been created." msgstr "Timer für '%s' erzeugt." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:575 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:574 msgid "Created %d timer for '%s'." msgstr "%d Timer für '%s' erzeugt. " #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:584 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:583 msgid "Modified %d timer for '%s'." msgstr "%d Timer für '%s' modifiziert." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:599 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:598 msgid "Read new timers into database." msgstr "Lese neue Timer in Datenbank." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:62 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:61 msgid "Delete a autotimer 'aid'" msgstr "Löschen eines Autotimer 'aid'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:664 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:663 msgid "Mon" msgstr "Mo" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:665 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:664 msgid "Tue" msgstr "Di" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:666 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:665 msgid "Wed" msgstr "Mi" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:667 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:666 msgid "Thu" msgstr "Do" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:668 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:667 msgid "Fri" msgstr "Fr" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:669 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:668 msgid "Sat" msgstr "Sa" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:670 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:669 msgid "Sun" msgstr "So" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:680 ../wml/tlist.tmpl:26 ../wml/tlist.tmpl:67 ../wml/tsearch.tmpl:26 ../wml/tsearch.tmpl:67 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:679 ../wml/tlist.tmpl:26 ../wml/tlist.tmpl:67 msgid "Timer" msgstr "Timer" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:681 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:68 +msgid "Edit an autotimer 'aid'" +msgstr "Editieren eines Autotimer 'aid'" + +#-------------------- +#: ../lib/XXV/MODULES/AUTOTIMER.pm:680 msgid "Existing recording" msgstr "Vorhandene Aufnahme" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:682 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:681 msgid "Recording chronicle" msgstr "Aufnahmechronik" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:69 -msgid "Edit an autotimer 'aid'" -msgstr "Editieren eines Autotimer 'aid'" - -#-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:699 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:698 msgid "Activate this autotimer" msgstr "Aktiviere diesen Autotimer" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:703 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:702 msgid "" "Search terms to search for EPG entries.\n" "You can also fine tune your search :\n" @@ -1810,216 +1836,236 @@ msgstr "" "* durch ein Minuszeichen zum Ausschliessen von Suchbegriffen z.B. 'Heute,-Morgen'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:711 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:710 msgid "Search in this EPG fields" msgstr "Suche in diesen EPG-Feldern" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:732 ../lib/XXV/MODULES/AUTOTIMER.pm:782 ../lib/XXV/MODULES/AUTOTIMER.pm:859 ../lib/XXV/MODULES/USER.pm:405 ../lib/XXV/MODULES/USER.pm:412 ../lib/XXV/MODULES/USER.pm:428 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:731 ../lib/XXV/MODULES/AUTOTIMER.pm:781 ../lib/XXV/MODULES/AUTOTIMER.pm:858 ../lib/XXV/MODULES/USER.pm:405 ../lib/XXV/MODULES/USER.pm:412 ../lib/XXV/MODULES/USER.pm:428 msgid "You can choose: %s!" msgstr "Sie können wählen: %s!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:747 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:746 msgid "Limit search to these channels" msgstr "Begrenze Suche auf diese Kanäle" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:755 -msgid "The channel '%s' does not exist!" -msgstr "Der Kanal '%s' existiert nicht!" - -#-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:76 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:75 msgid "Search for autotimer with text 'aid'" msgstr "Suche nach Autotimer mit Text 'aid'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:762 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:754 +msgid "The channel '%s' does not exist!" +msgstr "Der Kanal '%s' existiert nicht!" + +#-------------------- +#: ../lib/XXV/MODULES/AUTOTIMER.pm:761 msgid "Ignore retries with same title?" msgstr "Ignoriere Wiederholungen mit gleichen Titel?" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:798 ../lib/XXV/MODULES/TIMERS.pm:783 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:797 ../lib/XXV/MODULES/TIMERS.pm:764 msgid "Start time in format 'HH:MM'" msgstr "Startzeit im Format 'HH:MM'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:801 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:800 msgid "You set a start time without an end time!" msgstr "Startzeitpunkt ohne Stoppzeitpunkt definiert!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:805 ../lib/XXV/MODULES/AUTOTIMER.pm:811 ../lib/XXV/MODULES/AUTOTIMER.pm:828 ../lib/XXV/MODULES/AUTOTIMER.pm:834 ../lib/XXV/MODULES/TIMERS.pm:787 ../lib/XXV/MODULES/TIMERS.pm:793 ../lib/XXV/MODULES/TIMERS.pm:806 ../lib/XXV/MODULES/TIMERS.pm:812 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:804 ../lib/XXV/MODULES/AUTOTIMER.pm:810 ../lib/XXV/MODULES/AUTOTIMER.pm:827 ../lib/XXV/MODULES/AUTOTIMER.pm:833 ../lib/XXV/MODULES/TIMERS.pm:768 ../lib/XXV/MODULES/TIMERS.pm:774 ../lib/XXV/MODULES/TIMERS.pm:787 ../lib/XXV/MODULES/TIMERS.pm:793 msgid "The time is incorrect!" msgstr "Die Zeit ist nicht korrekt!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:82 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:81 msgid "Show autotimer 'aid'" msgstr "Zeige Autotimer 'aid'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:821 ../lib/XXV/MODULES/TIMERS.pm:802 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:820 ../lib/XXV/MODULES/TIMERS.pm:783 msgid "End time in format 'HH:MM'" msgstr "Endzeit im Format 'HH:MM'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:824 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:823 msgid "You set an end time without a start time!" msgstr "Stoppzeitpunkt ohne Startzeitpunkt definiert!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:839 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:838 msgid "Only search these weekdays" msgstr "Suche nur an diesen Wochentagen" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:872 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:87 +msgid "Start autotimer search." +msgstr "Autotimersuche durchführen" + +#-------------------- +#: ../lib/XXV/MODULES/AUTOTIMER.pm:871 msgid "Use PDC time to control created timer" msgstr "Verwende VPS zum Überwachen neuer Timer" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:876 ../lib/XXV/MODULES/TIMERS.pm:33 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:875 ../lib/XXV/MODULES/TIMERS.pm:32 msgid "Buffer time in minutes before the scheduled start of a recording" msgstr "Pufferzeit in Minuten, vor dem zeitlichen Anfang der Aufnahme." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:88 -msgid "Start autotimer search." -msgstr "Autotimersuche durchführen" - -#-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:884 ../lib/XXV/MODULES/AUTOTIMER.pm:898 ../lib/XXV/MODULES/AUTOTIMER.pm:911 ../lib/XXV/MODULES/AUTOTIMER.pm:927 ../lib/XXV/MODULES/AUTOTIMER.pm:943 ../lib/XXV/MODULES/CHANNELS.pm:1018 ../lib/XXV/MODULES/CHANNELS.pm:1031 ../lib/XXV/MODULES/CHANNELS.pm:1044 ../lib/XXV/MODULES/CHANNELS.pm:1057 ../lib/XXV/MODULES/CHANNELS.pm:883 ../lib/XXV/MODULES/CHANNELS.pm:914 ../lib/XXV/MODULES/CHANNELS.pm:953 ../lib/XXV/MODULES/CHANNELS.pm:966 ../lib/XXV/MODULES/CHANNELS.pm:992 ../lib/XXV/MODULES/GRAB.pm:104 ../lib/XXV/MODULES/GRAB.pm:228 ../lib/XXV/MODULES/GRAB.pm:236 ../lib/XXV/MODULES/GRAB.pm:35 ../lib/XXV/MODULES/GRAB.pm:49 ../lib/XXV/MODULES/GRAB.pm:72 ../lib/XXV/MODULES/GRAB.pm:91 ../lib/XXV/MODULES/RECORDS.pm:2080 ../lib/XXV/MODULES/RECORDS.pm:2094 ../lib/XXV/MODULES/STREAM.pm:113 ../lib/XXV/MODULES/STREAM.pm:99 ../lib/XXV/MODULES/TIMERS.pm:828 ../lib/XXV/MODULES/TIMERS.pm:844 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:883 ../lib/XXV/MODULES/AUTOTIMER.pm:897 ../lib/XXV/MODULES/AUTOTIMER.pm:910 ../lib/XXV/MODULES/AUTOTIMER.pm:926 ../lib/XXV/MODULES/AUTOTIMER.pm:942 ../lib/XXV/MODULES/CHANNELS.pm:1087 ../lib/XXV/MODULES/CHANNELS.pm:1118 ../lib/XXV/MODULES/CHANNELS.pm:1157 ../lib/XXV/MODULES/CHANNELS.pm:1170 ../lib/XXV/MODULES/CHANNELS.pm:1196 ../lib/XXV/MODULES/CHANNELS.pm:1222 ../lib/XXV/MODULES/CHANNELS.pm:1235 ../lib/XXV/MODULES/CHANNELS.pm:1248 ../lib/XXV/MODULES/CHANNELS.pm:1261 ../lib/XXV/MODULES/GRAB.pm:104 ../lib/XXV/MODULES/GRAB.pm:228 ../lib/XXV/MODULES/GRAB.pm:236 ../lib/XXV/MODULES/GRAB.pm:35 ../lib/XXV/MODULES/GRAB.pm:49 ../lib/XXV/MODULES/GRAB.pm:72 ../lib/XXV/MODULES/GRAB.pm:91 ../lib/XXV/MODULES/RECORDS.pm:2071 ../lib/XXV/MODULES/RECORDS.pm:2085 ../lib/XXV/MODULES/STREAM.pm:100 ../lib/XXV/MODULES/STREAM.pm:114 ../lib/XXV/MODULES/SVDRP.pm:230 ../lib/XXV/MODULES/TIMERS.pm:809 ../lib/XXV/MODULES/TIMERS.pm:825 msgid "Value incorrect!" msgstr "Der Wert ist nicht korrekt!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:890 ../lib/XXV/MODULES/TIMERS.pm:38 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:889 ../lib/XXV/MODULES/TIMERS.pm:37 msgid "Buffer time in minutes past the scheduled end of a recording" msgstr "Pufferzeit in Minuten, nach dem zeitlichen Ende der Aufnahme." #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:904 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:903 msgid "Minimum play time in minutes" msgstr "Mindestlänge in Minuten" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:917 ../lib/XXV/MODULES/RECORDS.pm:2087 ../lib/XXV/MODULES/TIMERS.pm:818 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:916 ../lib/XXV/MODULES/RECORDS.pm:2078 ../lib/XXV/MODULES/TIMERS.pm:799 msgid "Priority (%d ... %d)" msgstr "Priorität (%d ... %d)" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:923 ../lib/XXV/MODULES/TIMERS.pm:824 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:922 ../lib/XXV/MODULES/TIMERS.pm:805 msgid "Sorry, but the maximum priority is limited to %d!" msgstr "Entschuldigung, aber die maximale Priorität ist auf %d begrenzt!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:933 ../lib/XXV/MODULES/RECORDS.pm:2073 ../lib/XXV/MODULES/TIMERS.pm:834 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:932 ../lib/XXV/MODULES/RECORDS.pm:2064 ../lib/XXV/MODULES/TIMERS.pm:815 msgid "Lifetime (%d ... %d)" msgstr "Lebenszeit (%d ... %d)" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:939 ../lib/XXV/MODULES/TIMERS.pm:840 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:938 ../lib/XXV/MODULES/TIMERS.pm:821 msgid "Sorry, but the maximum life time is limited to %d!" msgstr "Entschuldigung, aber die maximale Lebenszeit ist auf %d begrenzt!" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:949 -msgid "Group all recordings into one directory" -msgstr "Gruppiere alle Aufnahmen in einem Verzeichnis" - -#-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:95 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:94 msgid "Toggle autotimer on or off 'aid'" msgstr "Umschalten der Autotimer zwischen Ein und Aus 'aid'" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:963 ../lib/XXV/MODULES/AUTOTIMER.pm:996 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:948 +msgid "Group all recordings into one directory" +msgstr "Gruppiere alle Aufnahmen in einem Verzeichnis" + +#-------------------- +#: ../lib/XXV/MODULES/AUTOTIMER.pm:961 ../lib/XXV/MODULES/AUTOTIMER.pm:994 msgid "%Y-%m-%d %H:%M:%S" msgstr "%d.%m.%Y %H:%M:%S" #-------------------- -#: ../lib/XXV/MODULES/AUTOTIMER.pm:969 +#: ../lib/XXV/MODULES/AUTOTIMER.pm:967 msgid "Start date as YYYY-MM-DD HH:MM:SS." msgstr "Startdatum als DD.MM.YYYY HH:MM:SS." #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1011 +#: ../lib/XXV/MODULES/CHANNELS.pm:104 +msgid "Deletes one or more channels 'pos'" +msgstr "Löscht einen oder mehrere Kanäle 'pos'" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1052 ../lib/XXV/MODULES/CHANNELS.pm:1057 ../lib/XXV/MODULES/CHANNELS.pm:1408 ../lib/XXV/MODULES/REMOTE.pm:275 +msgid "Channel '%s' does not exist in the database!" +msgstr "Der Kanal '%s' existiert nicht in der Datenbank!" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1073 +msgid "Which video disk recorder should used" +msgstr "Welcher Video Disk Rekorder soll genutzt werden" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1080 ../lib/XXV/MODULES/CHANNELS.pm:1377 ../lib/XXV/MODULES/CHANNELS.pm:618 +msgid "Position" +msgstr "Position" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1098 ../lib/XXV/MODULES/CHANNELS.pm:1270 +msgid "New channel" +msgstr "Neuer Kanal" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1125 ../lib/XXV/MODULES/CHANNELS.pm:607 +msgid "Signal source" +msgstr "Signalquelle" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1150 ../lib/XXV/MODULES/CHANNELS.pm:608 +msgid "Symbol rate" +msgstr "Symbolrate" + +#-------------------- +#: ../lib/XXV/MODULES/CHANNELS.pm:1215 msgid "Service ID (SID)" msgstr "Service ID (SID)" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1024 +#: ../lib/XXV/MODULES/CHANNELS.pm:1228 msgid "Network ID (NID)" msgstr "Netzwerk ID (NID)" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1037 +#: ../lib/XXV/MODULES/CHANNELS.pm:1241 msgid "Transport stream ID (TID)" msgstr "Transport stream ID (TID)" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:104 -msgid "Deletes one or more channels 'pos'" -msgstr "Löscht einen oder mehrere Kanäle 'pos'" - -#-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1050 +#: ../lib/XXV/MODULES/CHANNELS.pm:1254 msgid "Radio ID (RID)" msgstr "Radio ID (RID)" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1066 ../lib/XXV/MODULES/CHANNELS.pm:894 -msgid "New channel" -msgstr "Neuer Kanal" +#: ../lib/XXV/MODULES/CHANNELS.pm:130 +msgid "The system has saved %d channels from %d groups" +msgstr "Das System hat %d Kanäle aus %d Gruppen gespeichert" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1148 +#: ../lib/XXV/MODULES/CHANNELS.pm:1352 msgid "No channel defined for deletion! Please use cdelete 'pos'!" msgstr "Kanal zu löschen definiert! Bitte verwende cdelete 'pos'" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1161 ../lib/XXV/MODULES/CHANNELS.pm:861 -msgid "Channel '%s' does not exist in the database!" -msgstr "Der Kanal '%s' existiert nicht in der Datenbank!" - -#-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1195 -msgid "No channel defined for deletion!" -msgstr "Kein Kanal zum Löschen definiert!" +#: ../lib/XXV/MODULES/CHANNELS.pm:1424 +msgid "Found no channel to delete!" +msgstr "Kein Kanal zum Löschen gefunden!" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1210 +#: ../lib/XXV/MODULES/CHANNELS.pm:1439 msgid "New %s channel: %s on position: %d %s" msgstr "Neuer %s Kanal: %s auf Position: %d %s" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1212 +#: ../lib/XXV/MODULES/CHANNELS.pm:1441 msgid "TV" msgstr "TV" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1213 +#: ../lib/XXV/MODULES/CHANNELS.pm:1442 msgid "Radio" msgstr "Radio" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1216 +#: ../lib/XXV/MODULES/CHANNELS.pm:1445 msgid "(encrypted)" msgstr "(verschlüsselt)" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:1223 +#: ../lib/XXV/MODULES/CHANNELS.pm:1452 msgid "Found %d new channels!" msgstr "%d neue Kanäle gefunden!" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:130 -msgid "The system has saved %d channels from %d groups" -msgstr "Das System hat %d Kanäle aus %d Gruppen gespeichert" - -#-------------------- #: ../lib/XXV/MODULES/CHANNELS.pm:17 msgid "This module reads new channels and stores them in the database." msgstr "Dieses Modul list neue Kanäle und speichert sie in der Datenbank." @@ -2040,11 +2086,6 @@ msgid "Filter channel list, set all wanted CA (Common Access)" msgstr "Filter Kanalliste, setze alle gesuche CA(Common Access)" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:396 -msgid "No channels available!" -msgstr "Keine Kanäle verfügbar!" - -#-------------------- #: ../lib/XXV/MODULES/CHANNELS.pm:45 msgid "Free-to-air" msgstr "Frei empfangbar" @@ -2055,76 +2096,61 @@ msgid "DVB card %s" msgstr "DVB Karte %s" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:536 +#: ../lib/XXV/MODULES/CHANNELS.pm:570 msgid "There are %d channels inserted, %d channels updated, %d channels deleted into database." msgstr "Es wurden %d Kanäle hinzugefügt, %d Kanäle aktualisiert und %d Kanäle in der Datenbank gelöscht." #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:572 +#: ../lib/XXV/MODULES/CHANNELS.pm:606 msgid "Parameters" msgstr "Parameter" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:573 ../lib/XXV/MODULES/CHANNELS.pm:921 -msgid "Signal source" -msgstr "Signalquelle" - -#-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:574 ../lib/XXV/MODULES/CHANNELS.pm:946 -msgid "Symbol rate" -msgstr "Symbolrate" - -#-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:575 +#: ../lib/XXV/MODULES/CHANNELS.pm:609 msgid "Video PID" msgstr "Video PID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:576 +#: ../lib/XXV/MODULES/CHANNELS.pm:610 msgid "Audio PID" msgstr "Audio PID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:577 +#: ../lib/XXV/MODULES/CHANNELS.pm:611 msgid "Teletext PID" msgstr "Videotext PID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:578 +#: ../lib/XXV/MODULES/CHANNELS.pm:612 msgid "Conditional access" msgstr "Zugangsberechtigungssystem" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:579 +#: ../lib/XXV/MODULES/CHANNELS.pm:613 msgid "SID" msgstr "SID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:580 +#: ../lib/XXV/MODULES/CHANNELS.pm:614 msgid "TID" msgstr "TID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:581 +#: ../lib/XXV/MODULES/CHANNELS.pm:615 msgid "NID" msgstr "NID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:582 +#: ../lib/XXV/MODULES/CHANNELS.pm:616 msgid "RID" msgstr "RID" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:583 +#: ../lib/XXV/MODULES/CHANNELS.pm:617 msgid "Channel group" msgstr "Kanalgruppe" #-------------------- -#: ../lib/XXV/MODULES/CHANNELS.pm:584 ../lib/XXV/MODULES/CHANNELS.pm:876 -msgid "Position" -msgstr "Position" - -#-------------------- #: ../lib/XXV/MODULES/CHANNELS.pm:65 msgid "Cleans out channel names, only the 'long' part is visible." msgstr "Bereinigt Kanalnamen, nur Teil 'long' ist sichtbar" @@ -2180,27 +2206,27 @@ msgid "Delete within chronicle with 'ID'" msgstr "Lösche in der Chronik mit 'ID'" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:112 +#: ../lib/XXV/MODULES/CONFIG.pm:122 msgid "Settings for XXV" msgstr "Einstellungen für XXV" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:127 +#: ../lib/XXV/MODULES/CONFIG.pm:137 msgid "Save configuration" msgstr "Übernehme Konfiguration" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:131 ../lib/XXV/MODULES/CONFIG.pm:30 +#: ../lib/XXV/MODULES/CONFIG.pm:141 ../lib/XXV/MODULES/CONFIG.pm:30 msgid "Saves the configuration." msgstr "Speichert Konfiguration" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:154 ../lib/XXV/MODULES/CONFIG.pm:229 +#: ../lib/XXV/MODULES/CONFIG.pm:164 ../lib/XXV/MODULES/CONFIG.pm:239 msgid "Sorry, but section %s does not exist in the configuration!" msgstr "Verzeihung, aber der Abschnitt %s existiert nicht in der Konfiguration!" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:159 +#: ../lib/XXV/MODULES/CONFIG.pm:169 msgid "Sorry, but the settings in module: %s do not exist!" msgstr "Verzeihung, aber die Einstellungen in Modul: %s existieren nicht!" @@ -2210,32 +2236,32 @@ msgid "This module edits, writes and saves the configuration." msgstr "Dieses Modul bearbeitet, schreibt und übernimmt die Konfiguration." #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:170 +#: ../lib/XXV/MODULES/CONFIG.pm:180 msgid "No description" msgstr "Keine Beschreibung" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:180 +#: ../lib/XXV/MODULES/CONFIG.pm:190 msgid "%s manual" msgstr "%s Dokumentation" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:183 +#: ../lib/XXV/MODULES/CONFIG.pm:193 msgid "Edit configuration %s" msgstr "Konfiguration %s bearbeiten" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:190 +#: ../lib/XXV/MODULES/CONFIG.pm:200 msgid "Section: '%s' saving ... please wait." msgstr "Abschnitt: '%s' speichere .. bitte warten." #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:208 +#: ../lib/XXV/MODULES/CONFIG.pm:218 msgid "Configuration written to '%s'." msgstr "Konfiguration nach '%s' geschrieben." #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:222 +#: ../lib/XXV/MODULES/CONFIG.pm:232 msgid "Need a name of the module to display the configuration!" msgstr "Ich benötige einen Namen des Moduls um die Konfiguration anzuzeigen!" @@ -2245,17 +2271,17 @@ msgid "Edit configuration 'section'" msgstr "Konfiguration bearbeiten 'Abschnitt'" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:271 +#: ../lib/XXV/MODULES/CONFIG.pm:281 msgid "Couldn't find %s in %s!" msgstr "Bearbeiten war erfolgreich" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:279 +#: ../lib/XXV/MODULES/CONFIG.pm:289 msgid "Edit successful!" msgstr "Bearbeiten war erfolgreich!" #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:320 +#: ../lib/XXV/MODULES/CONFIG.pm:330 msgid "" "%sThis is the xxv %s server.\n" "Please use the following commands:\n" @@ -2284,17 +2310,22 @@ msgid "Restart all modules." msgstr "Dieses lädt alle Module neu." #-------------------- -#: ../lib/XXV/MODULES/CONFIG.pm:61 -msgid "Modules loaded." -msgstr "Module neugeladen." +#: ../lib/XXV/MODULES/CONFIG.pm:68 +msgid "Reload %d modules." +msgstr "%d Module neu geladen" + +#-------------------- +#: ../lib/XXV/MODULES/CONFIG.pm:70 +msgid "There none module reloaded." +msgstr "Es wurden keine Module neugeladen." #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:1283 ../lib/XXV/MODULES/VTX.pm:1356 +#: ../lib/XXV/MODULES/EPG.pm:1318 ../lib/XXV/MODULES/VTX.pm:1356 msgid "No channel defined!" msgstr "Kein Kanal definiert!" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:1455 +#: ../lib/XXV/MODULES/EPG.pm:1524 msgid "No event id defined!" msgstr "Keine ID zum Event definiert!" @@ -2314,7 +2345,7 @@ msgid "Location of additional EPG images." msgstr "Position von zusätzlichen EPG Bildern." #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:284 +#: ../lib/XXV/MODULES/EPG.pm:285 msgid "Read EPG data ..." msgstr "Lese EPG Daten" @@ -2324,7 +2355,7 @@ msgid "How often EPG data are to be analyzed (in seconds)" msgstr "Wie oft sollen EPG Daten analysiert werden (in Sekunden)" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:315 +#: ../lib/XXV/MODULES/EPG.pm:319 msgid "%d events in database updated." msgstr "Es wurden %d Einträge in Datenbank aktualisiert." @@ -2334,7 +2365,7 @@ msgid "Preferred program times. (eg. 12:00, 18:00)" msgstr "Die bevorzugten Programmzeiten (Kommagetrenne Liste)" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:406 +#: ../lib/XXV/MODULES/EPG.pm:411 msgid "Analyze channel '%s'" msgstr "Untersuche Kanal '%s'" @@ -2354,7 +2385,7 @@ msgid "List program for channel 'channel name'" msgstr "Zeige Programm für Kanal 'Kanalname'" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:559 +#: ../lib/XXV/MODULES/EPG.pm:568 msgid "No title" msgstr "Kein Titel" @@ -2379,17 +2410,12 @@ msgid "Display events in a schematic way" msgstr "Zeigt Sendungen in einer übersichtlichen Weise" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:792 ../lib/XXV/MODULES/EPG.pm:795 -msgid "This channel '%s' does not exist in the database!" -msgstr "Dieser Kanal '%s' existiert nicht in der Datenbank!" - -#-------------------- #: ../lib/XXV/MODULES/EPG.pm:80 msgid "Update EPG data." msgstr "Aktualisiere EPG Daten" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:906 +#: ../lib/XXV/MODULES/EPG.pm:910 msgid "No ID defined to display this program! Please use display 'eid'!" msgstr "Keine ID einer Sendung, zur Anzeige dieses Programmes, definiert! Bitte verwende display 'eid'" @@ -2399,7 +2425,7 @@ msgid "Display the current program running in the VDR" msgstr "Zeigt die Sendung, die im VDR läuft" #-------------------- -#: ../lib/XXV/MODULES/EPG.pm:972 +#: ../lib/XXV/MODULES/EPG.pm:977 msgid "Event '%d' does not exist in the database!" msgstr "Sendung '%d' existiert nicht in der Datenbank!" @@ -2579,17 +2605,17 @@ msgid "Number of port to listen for soap clients" msgstr "Nummer des Port, um auf SOAP-Clients zu lauschen" #-------------------- -#: ../lib/XXV/MODULES/KEYWORDS.pm:16 +#: ../lib/XXV/MODULES/KEYWORDS.pm:17 msgid "This module manages keywords and tag within timer and recordings." msgstr "Diese Modul verwaltet Stichwörter innerhalb von Timern und Aufnahmen." #-------------------- -#: ../lib/XXV/MODULES/KEYWORDS.pm:32 +#: ../lib/XXV/MODULES/KEYWORDS.pm:33 msgid "Search timers 'keywords'" msgstr "Suche Timer 'Stichwort'" #-------------------- -#: ../lib/XXV/MODULES/KEYWORDS.pm:43 +#: ../lib/XXV/MODULES/KEYWORDS.pm:44 msgid "Search recordings 'keywords'" msgstr "Sucht Aufnahmen 'Stichwort'" @@ -2614,7 +2640,7 @@ msgid "Lines to display" msgstr "Wieviel Zeilen anzeigen?" #-------------------- -#: ../lib/XXV/MODULES/LOGREAD.pm:46 ../lib/XXV/MODULES/RECORDS.pm:37 ../lib/XXV/MODULES/REMOTE.pm:37 +#: ../lib/XXV/MODULES/LOGREAD.pm:46 ../lib/XXV/MODULES/RECORDS.pm:36 ../lib/XXV/MODULES/REMOTE.pm:37 msgid "Path of file '%s'" msgstr "Pfad der Datei '%s'" @@ -2924,77 +2950,87 @@ msgid "This module move timers between channels." msgstr "Diese Modul verschiebt Timer zwischen Kanälen." #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:225 +#: ../lib/XXV/MODULES/MOVETIMER.pm:229 msgid "Couldn't query rules to move timer from database!" msgstr "Konnte Regel zum Verschieben der Timer nicht aus der Datenbank abfragen!" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:303 +#: ../lib/XXV/MODULES/MOVETIMER.pm:323 msgid "There none timer to move." msgstr "Es wurden keine Timer verschoben." #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:371 ../lib/XXV/MODULES/MOVETIMER.pm:528 +#: ../lib/XXV/MODULES/MOVETIMER.pm:38 +msgid "List rules to move timer between channels" +msgstr "Zeige Regel zum Verschieben von Timer zwischen Kanälen" + +#-------------------- +#: ../lib/XXV/MODULES/MOVETIMER.pm:392 ../lib/XXV/MODULES/MOVETIMER.pm:553 msgid "Rule to move timer with ID '%s' does not exist in the database!" msgstr "Regel zum Verschieben der Timer mit ID '%s' exisitert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:38 -msgid "List rules to move timer between channels" -msgstr "Zeige Regel zum Verschieben von Timer zwischen Kanälen" +#: ../lib/XXV/MODULES/MOVETIMER.pm:411 +msgid "Which video disk recorder should as source?" +msgstr "Welcher Video Disk Rekorder soll als Quelle dienen?" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:388 +#: ../lib/XXV/MODULES/MOVETIMER.pm:417 msgid "Which channel should used as source?" msgstr "Welcher Kanal soll als Quelle verwendet werden?" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:400 ../lib/XXV/MODULES/MOVETIMER.pm:422 ../lib/XXV/MODULES/RECORDS.pm:2114 ../lib/XXV/MODULES/STREAM.pm:201 ../lib/XXV/MODULES/TIMERS.pm:734 ../lib/XXV/MODULES/XMLTV.pm:530 -msgid "This channel '%s' does not exist!" -msgstr "Dieser Kanal '%s' existiert nicht in der Datenbank!" +#: ../lib/XXV/MODULES/MOVETIMER.pm:425 ../lib/XXV/MODULES/MOVETIMER.pm:448 ../lib/XXV/MODULES/TIMERS.pm:715 +msgid "Channel '%s' does not exist on video disk recorder %s!" +msgstr "Kanal '%s' existiert nicht auf Video Disk Rekorder %s!" + +#-------------------- +#: ../lib/XXV/MODULES/MOVETIMER.pm:434 +msgid "Which video disk recorder should as destination?" +msgstr "Welcher Video Disk Rekorder soll als Ziel dienen?" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:410 +#: ../lib/XXV/MODULES/MOVETIMER.pm:440 msgid "Which channel should used as destination?" msgstr "Welcher Kanal soll als Ziel verwendet werden?" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:429 +#: ../lib/XXV/MODULES/MOVETIMER.pm:45 +msgid "Create rule to move timer between channels" +msgstr "Erzeuge eine neue Regel zum Verschieben von Timern zwischen Kanälen" + +#-------------------- +#: ../lib/XXV/MODULES/MOVETIMER.pm:454 msgid "When should use this rule" msgstr "Wann soll die Regel verwendet werden" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:439 +#: ../lib/XXV/MODULES/MOVETIMER.pm:464 msgid "How should timer handled, if changed" msgstr "Wie sollen Timer behandelt bei Änderungen behandelt werden" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:45 -msgid "Create rule to move timer between channels" -msgstr "Erzeuge eine neue Regel zum Verschieben von Timern zwischen Kanälen" - -#-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:460 +#: ../lib/XXV/MODULES/MOVETIMER.pm:485 msgid "Rule to move timer saved!" msgstr "Regel zum Verschieben von Timern gespeichert!" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:497 ../lib/XXV/MODULES/MOVETIMER.pm:504 -msgid "Couldn't insert rule move timer in database!" -msgstr "Regel zum Verschieben von Timern konnte nicht in Datenbank eingefügt werden!" - -#-------------------- #: ../lib/XXV/MODULES/MOVETIMER.pm:52 msgid "Delete rule to move timer between channels" msgstr "Lösche Regel zum Verschieben von Timern zwischen Kanälen" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:520 +#: ../lib/XXV/MODULES/MOVETIMER.pm:522 ../lib/XXV/MODULES/MOVETIMER.pm:529 +msgid "Couldn't insert rule move timer in database!" +msgstr "Regel zum Verschieben von Timern konnte nicht in Datenbank eingefügt werden!" + +#-------------------- +#: ../lib/XXV/MODULES/MOVETIMER.pm:545 msgid "Missing ID to select rules for deletion! Please use movetimerdelete 'id'" msgstr "Benötige ID zum Auswählen der Regel für die Löschung! Bitte verwende movetimerdelete 'id'" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:532 +#: ../lib/XXV/MODULES/MOVETIMER.pm:557 msgid "Rule to move timer %s is deleted." msgstr "Regel zum Verschieben der Timer %s wurde gelöscht." @@ -3004,27 +3040,27 @@ msgid "Edit rule to move timer between channels" msgstr "Bearbeite Regel zum Verschieben von Timern zwischen Kanälen" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:612 +#: ../lib/XXV/MODULES/MOVETIMER.pm:637 msgid "Allways" msgstr "Immer" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:613 +#: ../lib/XXV/MODULES/MOVETIMER.pm:638 msgid "Newer" msgstr "Niemals" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:614 +#: ../lib/XXV/MODULES/MOVETIMER.pm:639 msgid "If collision detected" msgstr "Wenn eine Kollision erkannt wurde" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:625 -msgid "Keep inactiv original timer" +#: ../lib/XXV/MODULES/MOVETIMER.pm:650 +msgid "Keep inactive original timer" msgstr "Behalte den inaktiven original Timer" #-------------------- -#: ../lib/XXV/MODULES/MOVETIMER.pm:626 +#: ../lib/XXV/MODULES/MOVETIMER.pm:651 msgid "Copy original timer" msgstr "Kopiere den original Timer" @@ -3189,342 +3225,347 @@ msgid "Please wait, search for new covers ..." msgstr "Bitte warten, suche nach neuen Plattenhüllen ..." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:102 +#: ../lib/XXV/MODULES/RECORDS.pm:101 msgid "Display recording 'rid'" msgstr "Zeige Aufnahme 'rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:108 +#: ../lib/XXV/MODULES/RECORDS.pm:107 msgid "List of recordings" msgstr "Aufnahmenliste" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:114 +#: ../lib/XXV/MODULES/RECORDS.pm:113 msgid "Search recordings 'text'" msgstr "Sucht Aufnahmen 'text'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:127 +#: ../lib/XXV/MODULES/RECORDS.pm:126 msgid "Delete recording 'rid'" msgstr "Aufnahme löschen 'rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:141 +#: ../lib/XXV/MODULES/RECORDS.pm:140 msgid "Edit recording 'rid'" msgstr "Aufnahme bearbeiten 'rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:1475 +#: ../lib/XXV/MODULES/RECORDS.pm:1466 msgid "No recording defined for display! Please use rdisplay 'rid'" msgstr "Keine Aufnahme zum Anzeigen definiert! Bitte verwende rdisplay 'rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:148 +#: ../lib/XXV/MODULES/RECORDS.pm:147 msgid "Convert recording 'rid'" msgstr "Aufnahme konvertieren 'rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:1512 ../lib/XXV/MODULES/RECORDS.pm:1551 ../lib/XXV/MODULES/RECORDS.pm:1593 ../lib/XXV/MODULES/RECORDS.pm:1960 ../lib/XXV/MODULES/RECORDS.pm:2050 ../lib/XXV/MODULES/RECORDS.pm:2347 +#: ../lib/XXV/MODULES/RECORDS.pm:1503 ../lib/XXV/MODULES/RECORDS.pm:1542 ../lib/XXV/MODULES/RECORDS.pm:1584 ../lib/XXV/MODULES/RECORDS.pm:1951 ../lib/XXV/MODULES/RECORDS.pm:2041 ../lib/XXV/MODULES/RECORDS.pm:2323 msgid "Recording '%s' does not exist in the database!" msgstr "Aufnahme '%s' existiert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:1542 ../lib/XXV/MODULES/RECORDS.pm:1586 +#: ../lib/XXV/MODULES/RECORDS.pm:1533 ../lib/XXV/MODULES/RECORDS.pm:1577 msgid "No recording defined for playback! Please use rplay 'rid'." msgstr "Keine Aufnahme zum Wiedergabe definiert! Bitte verwende rplay 'rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:155 +#: ../lib/XXV/MODULES/RECORDS.pm:154 msgid "Play recording 'rid' in the VDR." msgstr "Spiele Aufnahme 'rid' im VDR" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:162 +#: ../lib/XXV/MODULES/RECORDS.pm:161 msgid "Cut recording 'rid' in vdr" msgstr "Schneide Aufnahme 'rid' im VDR" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:1640 ../lib/XXV/MODULES/RECORDS.pm:1777 +#: ../lib/XXV/MODULES/RECORDS.pm:1631 ../lib/XXV/MODULES/RECORDS.pm:1768 msgid "Index" msgstr "Index" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:182 +#: ../lib/XXV/MODULES/RECORDS.pm:181 msgid "Create event entries if a recording has been deleted." msgstr "Erzeuge Eventeinträge, wenn eine Aufnahme gelöscht wurde." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:1893 +#: ../lib/XXV/MODULES/RECORDS.pm:1884 msgid "No recording defined for deletion! Please use rdelete 'id'." msgstr "Keine Aufnahme zum Löschen definiert! Bitte verwende rdelete 'rid'." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:1966 +#: ../lib/XXV/MODULES/RECORDS.pm:1957 msgid "Recording '%s' to delete" msgstr "Aufnahme '%s' wird gelöscht" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2002 +#: ../lib/XXV/MODULES/RECORDS.pm:1993 msgid "No recording to delete!" msgstr "Keine Aufnahme zum Löschen!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2028 +#: ../lib/XXV/MODULES/RECORDS.pm:2019 msgid "No recording defined for editing!" msgstr "Keine Aufnahme-ID zum Bearbeiten!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2067 ../lib/XXV/MODULES/RECORDS.pm:2670 ../lib/XXV/MODULES/TIMERS.pm:718 +#: ../lib/XXV/MODULES/RECORDS.pm:2058 ../lib/XXV/MODULES/RECORDS.pm:2646 ../lib/XXV/MODULES/TIMERS.pm:693 msgid "Title of recording" msgstr "Titel der Aufnahme" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:208 +#: ../lib/XXV/MODULES/RECORDS.pm:207 msgid "Recording deleted: %s" msgstr "Aufnahme gelöscht: %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2104 +#: ../lib/XXV/MODULES/RECORDS.pm:2095 msgid "Undefined" msgstr "Unbestimmt" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:212 +#: ../lib/XXV/MODULES/RECORDS.pm:2105 ../lib/XXV/MODULES/STREAM.pm:208 ../lib/XXV/MODULES/XMLTV.pm:531 +msgid "This channel '%s' does not exist!" +msgstr "Dieser Kanal '%s' existiert nicht in der Datenbank!" + +#-------------------- +#: ../lib/XXV/MODULES/RECORDS.pm:211 msgid "Subtitle: %s" msgstr "Serientitel: %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2136 +#: ../lib/XXV/MODULES/RECORDS.pm:2127 msgid "Video" msgstr "Video" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2141 +#: ../lib/XXV/MODULES/RECORDS.pm:2132 msgid "Audio" msgstr "Audio" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2146 +#: ../lib/XXV/MODULES/RECORDS.pm:2137 msgid "Cut marks" msgstr "Schnittmarken" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2198 ../lib/XXV/MODULES/RECORDS.pm:2206 +#: ../lib/XXV/MODULES/RECORDS.pm:2174 ../lib/XXV/MODULES/RECORDS.pm:2182 msgid "Couldn't write file '%s' : %s" msgstr "Konnte Datei '%s' nicht schreiben : %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2225 ../lib/XXV/MODULES/RECORDS.pm:2243 +#: ../lib/XXV/MODULES/RECORDS.pm:2201 ../lib/XXV/MODULES/RECORDS.pm:2219 msgid "Recording: '%s', couldn't move to '%s' : %s" msgstr "Aufnahme: '%s', konnte nicht nach '%s' verschoben werden : %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2239 +#: ../lib/XXV/MODULES/RECORDS.pm:2215 msgid "Recording: '%s', couldn't mkpath: '%s' : %s" msgstr "Aufnahme: '%s', konnte nicht Verzeichnis '%s' nicht erstellen : %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2250 +#: ../lib/XXV/MODULES/RECORDS.pm:2226 msgid "Recording: '%s', couldn't remove '%s' : %s" msgstr "Aufnahme: '%s', konnte nicht '%s' nicht entfernen : %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2281 ../lib/XXV/MODULES/RECORDS.pm:2283 +#: ../lib/XXV/MODULES/RECORDS.pm:2257 ../lib/XXV/MODULES/RECORDS.pm:2259 msgid "Recording edited!" msgstr "Aufnahme wurde bearbeitet!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2291 +#: ../lib/XXV/MODULES/RECORDS.pm:2267 msgid "Recording was'nt changed!" msgstr "Aufnahme wurde nicht verändert!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2330 +#: ../lib/XXV/MODULES/RECORDS.pm:2306 msgid "No reccmds.conf on your system!" msgstr "Keine reccmds.conf auf dem System!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2335 +#: ../lib/XXV/MODULES/RECORDS.pm:2311 msgid "Please use rconvert 'cmdid_rid'" msgstr "Bitte verwende rconvert 'cmdid_rid'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2339 +#: ../lib/XXV/MODULES/RECORDS.pm:2315 msgid "Command" msgstr "Kommando" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2346 +#: ../lib/XXV/MODULES/RECORDS.pm:2322 msgid "Couldn't find this command ID!" msgstr "Kann diese Kommando-ID nicht finden!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2360 +#: ../lib/XXV/MODULES/RECORDS.pm:2336 msgid "Call %s '%s', standard error output :" msgstr "Aufruf %s '%s', Standardfehlerausgabe :" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2363 +#: ../lib/XXV/MODULES/RECORDS.pm:2339 msgid "Call %s '%s', standard output :" msgstr "Aufruf %s '%s', Ausgabe :" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2367 +#: ../lib/XXV/MODULES/RECORDS.pm:2343 msgid "Sorry! Couldn't call %s '%s'! %s" msgstr "Entschuldigung! Konnte %s '%s' nicht aufrufen! %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2371 +#: ../lib/XXV/MODULES/RECORDS.pm:2347 msgid "Back to recording list" msgstr "Zurück zur Aufnahmeliste" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2410 +#: ../lib/XXV/MODULES/RECORDS.pm:2386 msgid "%d new recordings since last report time %s" msgstr "%d neue Aufnahmen seit der letzten Reportzeit %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2660 +#: ../lib/XXV/MODULES/RECORDS.pm:2636 msgid "There none recoverable recordings!" msgstr "Es sind keine wiederherstellbaren Aufnahmen vorhanden!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2690 +#: ../lib/XXV/MODULES/RECORDS.pm:2666 msgid "Recover recording" msgstr "Aufnahme wiederherstellen" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2696 +#: ../lib/XXV/MODULES/RECORDS.pm:2672 msgid "Can't recover recording, maybe was this in the meantime deleted!" msgstr "Aufnahme konnte nicht wiederhergestellt werden, möglicherweise wurde sie in der zwischenzeit gelöscht!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2705 +#: ../lib/XXV/MODULES/RECORDS.pm:2681 msgid "Recover recording, couldn't rename '%s' to %s : %s" msgstr "Wiederhergestellen der Aufnahme, konnte '%s' nicht in %s umbenennen : %s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2718 ../lib/XXV/MODULES/RECORDS.pm:2720 +#: ../lib/XXV/MODULES/RECORDS.pm:2694 ../lib/XXV/MODULES/RECORDS.pm:2696 msgid "Recording recovered!" msgstr "Aufnahme wiederhergestellt!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2728 +#: ../lib/XXV/MODULES/RECORDS.pm:2704 msgid "None recording was'nt recovered!" msgstr "Keine Aufnahme wurde wiederhergestellt!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:2797 ../lib/XXV/MODULES/VTX.pm:1419 +#: ../lib/XXV/MODULES/RECORDS.pm:2773 ../lib/XXV/MODULES/VTX.pm:1419 msgid "Sorry, get image is'nt supported" msgstr "Entschuldigung, Bilder werden nicht unterstützt!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:29 +#: ../lib/XXV/MODULES/RECORDS.pm:28 msgid "This module manages recordings." msgstr "Dieses Modul verwaltet die Aufnahmen." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:43 +#: ../lib/XXV/MODULES/RECORDS.pm:42 msgid "How often recordings are to be updated (in minutes)" msgstr "Wie oft sollen Aufnahmen eingelesen werden (in Minuten)" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:49 +#: ../lib/XXV/MODULES/RECORDS.pm:48 msgid "How often recordings are to be completely read in (in hours)" msgstr "Wie oft sollen Aufnahmen vollständig eingelesen werden (in Stunden)" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:540 +#: ../lib/XXV/MODULES/RECORDS.pm:535 msgid "No recordings available!" msgstr "Keine Aufnahmen verfügbar!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:55 +#: ../lib/XXV/MODULES/RECORDS.pm:54 msgid "Directory where recordings are stored" msgstr "Verzeichnis, wo die vdr Aufnahmen gespeichert sind" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:556 +#: ../lib/XXV/MODULES/RECORDS.pm:551 msgid "Used %s, total %s%s, free %s%s" msgstr "Genutzt %s, Gesamt %s%s, Frei %s%s" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:561 +#: ../lib/XXV/MODULES/RECORDS.pm:556 msgid "Unknown disc capacity!" msgstr "Unbekannte Festplattenkapazität!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:61 +#: ../lib/XXV/MODULES/RECORDS.pm:60 msgid "Location of used program to produce thumbnails on your system." msgstr "Position des verwendeten Programms, zum Erzeugen der Vorschaubildern." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:612 +#: ../lib/XXV/MODULES/RECORDS.pm:607 msgid "Update recording '%s'" msgstr "Aktualisiere Aufnahme '%s'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:664 +#: ../lib/XXV/MODULES/RECORDS.pm:659 msgid "Analyze recording '%s'" msgstr "Untersuche Aufnahme '%s'" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:67 +#: ../lib/XXV/MODULES/RECORDS.pm:66 msgid "The program used to create thumbnails" msgstr "Das verwendete Programm, um Vorschaubildern zu erzeugen" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:688 +#: ../lib/XXV/MODULES/RECORDS.pm:683 msgid "Can't add recording '%s' into database!" msgstr "Konnte Aufnahme '%s' nicht in Datenbank einfügen!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:691 +#: ../lib/XXV/MODULES/RECORDS.pm:686 msgid "Can't assign recording '%s' to file!" msgstr "Kann Aufnahme '%s' keiner Datei zuordnen!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:698 -msgid "Recording '%s' without id or unique title and date from VDR!" -msgstr "Aufnahme '%s' ohne ID oder eindeutigen Titel und Datum vom VDR!" - -#-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:70 +#: ../lib/XXV/MODULES/RECORDS.pm:69 msgid "None" msgstr "Keines" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:788 -msgid "Write %d recordings to the database." -msgstr "Schreibe %d Aufnahmen in die Datenbank." +#: ../lib/XXV/MODULES/RECORDS.pm:693 +msgid "Recording '%s' without id or unique title and date from VDR!" +msgstr "Aufnahme '%s' ohne ID oder eindeutigen Titel und Datum vom VDR!" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:79 +#: ../lib/XXV/MODULES/RECORDS.pm:78 msgid "Produce how many thumbnails" msgstr "Wieviele Vorschaubildern erzeugen?" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:790 +#: ../lib/XXV/MODULES/RECORDS.pm:783 +msgid "Write %d recordings to the database." +msgstr "Schreibe %d Aufnahmen in die Datenbank." + +#-------------------- +#: ../lib/XXV/MODULES/RECORDS.pm:785 msgid "Write %d recordings to the database. Couldn't assign %d recordings." msgstr "Schreibe nur %d Aufnahmen in die Datenbank. Kann %d Aufnahmen nicht zuordnen." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:827 ../lib/XXV/MODULES/RECORDS.pm:829 +#: ../lib/XXV/MODULES/RECORDS.pm:822 ../lib/XXV/MODULES/RECORDS.pm:824 msgid "Get information on recordings ..." msgstr "Hole Informationen über Aufnahmen ..." #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:84 +#: ../lib/XXV/MODULES/RECORDS.pm:83 msgid "Display recording list with thumbnails?" msgstr "Zeige Aufnahmeliste mit Vorschaubildern?" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:89 +#: ../lib/XXV/MODULES/RECORDS.pm:88 msgid "Common directory for preview images" msgstr "Gemeinsames Verzeichnis für Vorschaubilder" #-------------------- -#: ../lib/XXV/MODULES/RECORDS.pm:95 +#: ../lib/XXV/MODULES/RECORDS.pm:94 msgid "VDR compiled for VFAT system (VFAT=1)" msgstr "Setze auf ja, wenn dein vdr kompiliert wurde für das VFAT System (VFAT=1)" @@ -3904,184 +3945,269 @@ msgid "Display the vitals informations" msgstr "Zeigt die wichtigen Informationen" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:104 +#: ../lib/XXV/MODULES/STREAM.pm:105 msgid "Stream widget height" msgstr "Streaming Widgethöhe" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:120 +#: ../lib/XXV/MODULES/STREAM.pm:121 msgid "Stream a recordings." msgstr "Aufnahme streamen." #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:127 +#: ../lib/XXV/MODULES/STREAM.pm:128 msgid "Stream a channel 'cid'. This required the streamdev plugin!" msgstr "Stream eines Kanales 'cid'. Dies erfordert das Streamdev Plugin!" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:192 +#: ../lib/XXV/MODULES/STREAM.pm:193 msgid "No channel defined for streaming!" msgstr "Kein Kanal für Streaming definiert!" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:195 ../lib/XXV/MODULES/STREAM.pm:260 +#: ../lib/XXV/MODULES/STREAM.pm:196 ../lib/XXV/MODULES/STREAM.pm:276 msgid "Can't stream files!" msgstr "Kann Datei nicht streamen!" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:22 +#: ../lib/XXV/MODULES/STREAM.pm:23 msgid "This module generate streams from recordings." msgstr "Dieses Modul erzeugt Streams von Aufnahmen." #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:247 +#: ../lib/XXV/MODULES/STREAM.pm:263 msgid "Unknown access method!" msgstr "Unbekannte Methode des Zugriffs!" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:257 +#: ../lib/XXV/MODULES/STREAM.pm:273 msgid "No recording defined for streaming!" msgstr "Keine Aufnahme für Streaming definiert!" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:29 +#: ../lib/XXV/MODULES/STREAM.pm:30 msgid "Used host of referred link inside playlist." msgstr "Benutzter Host für verweisende Links innerhalb der Abspiellisten." #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:35 +#: ../lib/XXV/MODULES/STREAM.pm:36 msgid "Typ of stream recordings" msgstr "Typ des Stream der Aufnahme" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:39 +#: ../lib/XXV/MODULES/STREAM.pm:40 msgid "HTTP Streaming" msgstr "HTTP Streaming" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:40 +#: ../lib/XXV/MODULES/STREAM.pm:41 msgid "Remote SMB/NFS share" msgstr "SMB/NFS Dateifreigabe" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:45 +#: ../lib/XXV/MODULES/STREAM.pm:46 msgid "Used mime type of delivered playlist video streams" msgstr "Verwendeter MIME Typ der ausgelieferten Abspielliste des Videostream" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:50 +#: ../lib/XXV/MODULES/STREAM.pm:51 msgid "Base directory of remote SMB/NFS share." msgstr "Basisverzeichnis für SMB/NFS Dateifreigaben." #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:55 +#: ../lib/XXV/MODULES/STREAM.pm:56 msgid "Used stream widget" msgstr "Verwendetes Streamwidget" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:59 +#: ../lib/XXV/MODULES/STREAM.pm:60 msgid "Other external player" msgstr "Anderer externer Player" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:60 +#: ../lib/XXV/MODULES/STREAM.pm:61 msgid "Embed media player" msgstr "Eingebetteter Media Player" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:61 +#: ../lib/XXV/MODULES/STREAM.pm:62 msgid "Embed vlc player" msgstr "Eingebetteter VLC Player" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:66 +#: ../lib/XXV/MODULES/STREAM.pm:67 msgid "Method of connect live-tv stream from recorder." msgstr "Methode um die Verbindung zum Rekorder beim Live-TV Stream herzustellen." #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:71 +#: ../lib/XXV/MODULES/STREAM.pm:72 msgid "Send playlist" msgstr "Übermittle als Abspielliste" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:72 +#: ../lib/XXV/MODULES/STREAM.pm:73 msgid "Redirect HTTP request" msgstr "Direktes weiterleiten der HTTP Abfrage" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:73 +#: ../lib/XXV/MODULES/STREAM.pm:74 msgid "Relay stream as proxy" msgstr "Stream als Proxy umleiten" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:77 +#: ../lib/XXV/MODULES/STREAM.pm:78 msgid "Used live stream type" msgstr "Verwendetes Format für Live-Stream" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:81 +#: ../lib/XXV/MODULES/STREAM.pm:82 msgid "TS - Transport Stream" msgstr "TS - Transport Stream" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:82 +#: ../lib/XXV/MODULES/STREAM.pm:83 msgid "PS - Program Stream" msgstr "PS - Program Stream" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:83 +#: ../lib/XXV/MODULES/STREAM.pm:84 msgid "PES - Packetized Elementary Stream" msgstr "PES - Packetized Elementary Stream" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:84 +#: ../lib/XXV/MODULES/STREAM.pm:85 msgid "ES - Elementary Stream" msgstr "ES - Elementary Stream" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:85 +#: ../lib/XXV/MODULES/STREAM.pm:86 msgid "External stream type" msgstr "Externer Streamtyp" #-------------------- -#: ../lib/XXV/MODULES/STREAM.pm:90 +#: ../lib/XXV/MODULES/STREAM.pm:91 msgid "Stream widget width" msgstr "Streaming Widgetbreite" #-------------------- #: ../lib/XXV/MODULES/SVDRP.pm:19 -msgid "This module serves as telnet client for sdvrp." -msgstr "Das Modul dient als Telnet Client für sdvrp." +msgid "This module module manages connection to video disk recorder." +msgstr "Das Modul verwaltet die Verbindung zu den Video Disk Rekordern." #-------------------- -#: ../lib/XXV/MODULES/SVDRP.pm:228 -msgid "No command defined! Please use scommand 'cmd'." -msgstr "Kein Kommando definiert! Bitte verwende scommand 'cmd'" +#: ../lib/XXV/MODULES/SVDRP.pm:200 ../lib/XXV/MODULES/SVDRP.pm:282 +msgid "Definition of video disk recorder '%s' does not exist in the database!" +msgstr "Definition '%s' des Video Disk Rekorder existiert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/SVDRP.pm:26 -msgid "Name of host that runs the VDR." -msgstr "Name des Host, auf dem der VDR läuft." +#: ../lib/XXV/MODULES/SVDRP.pm:212 +msgid "Activate this definition" +msgstr "Aktiviere diese Definition" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:216 +msgid "Host or IP address of video disk recorder" +msgstr "Host bzw. IP-Adresse des Video Disk Rekorder" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:222 +msgid "Used Port of SVDRP" +msgstr "Verwendeter SVDRP Port" #-------------------- -#: ../lib/XXV/MODULES/SVDRP.pm:32 -msgid "SVDRP port on the running VDR" -msgstr "SVDRP-Port auf dem laufenden VDR Client" +#: ../lib/XXV/MODULES/SVDRP.pm:237 +msgid "Use as primary video disk recorder" +msgstr "Verwende als primären Video Disk Rekorder" #-------------------- -#: ../lib/XXV/MODULES/SVDRP.pm:38 +#: ../lib/XXV/MODULES/SVDRP.pm:240 +msgid "List of present source of DVB cards. (eg. S19.2E,S19.2E,T,T )" +msgstr "Liste der vorhandenen Quellen der DVB Karten. (z.B. S19.2E,S19.2E,T,T )" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:247 +msgid "Edit video disk recorder definition" +msgstr "Bearbeiten der Video Disk Rekorder Definition" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:248 +msgid "Create new video disk recorder definition" +msgstr "Erzeuge neue Video Disk Rekorder Definition" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:26 msgid "Connection timeout defines after how many seconds an unrequited connection is terminated." msgstr "Nach wievielen Sekunden wird eine unerwiderte Verbindung beendet." #-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:267 +msgid "Video disk recorder definition saved!" +msgstr "Video Disk Rekorder Definition wurde gespeichert!" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:278 +msgid "No definition of video disk recorder for deletion! Please use sdelete 'id'." +msgstr "Keine Definition eines Video Disk Rekorder zum Löschen! Bitte verwende sdelete 'id'." + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:288 +msgid "Definition of video disk recorder are %s deleted." +msgstr "Definition '%s' des Video Disk Rekorder wurde gelöscht." + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:320 +msgid "Primary" +msgstr "Primär" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:321 +msgid "Host" +msgstr "Host" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:322 +msgid "Typ of Cards" +msgstr "Art von Karten" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:34 +msgid "List defined video disk recorder." +msgstr "Zeige Definition der Video Disk Rekorder" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:40 +msgid "Create new video disk recorder definition." +msgstr "Erzeuge neue Video Disk Rekorder Definition" + +#-------------------- #: ../lib/XXV/MODULES/SVDRP.pm:46 -msgid "Status from svdrp" -msgstr "Status vom svdrp" +msgid "Delete video disk recorder definition 'id'" +msgstr "Lösche Video Disk Rekorder Definition 'id'" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:501 +msgid "None video disk recorder defined in the database." +msgstr "Kein Video Disk Rekorder in der Datenbank definiert." + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:52 +msgid "Edit video disk recorder definition 'id'" +msgstr "Bearbeiten Video Disk Rekorder Definition 'id'" + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:58 +msgid "Status from video disk recorder." +msgstr "Status des Video Disk Rekorder." + +#-------------------- +#: ../lib/XXV/MODULES/SVDRP.pm:608 +msgid "No command defined! Please use scommand 'cmd'." +msgstr "Kein Kommando definiert! Bitte verwende scommand 'cmd'" #-------------------- -#: ../lib/XXV/MODULES/SVDRP.pm:53 -msgid "Send a command to svdrp" -msgstr "Sende ein Kommando zum svdrp" +#: ../lib/XXV/MODULES/SVDRP.pm:65 +msgid "Send a command to video disk recorder." +msgstr "Sende Befehl an Video Disk Rekorder." #-------------------- #: ../lib/XXV/MODULES/TELNET.pm:19 @@ -4138,37 +4264,27 @@ msgid "Are you sure to exit the xxv system?" msgstr "Sind Sie sicher, das XXV-System zu beenden?" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:1001 -msgid "No timer to delete!" -msgstr "Kein Timer zum Löschen!" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:1013 +#: ../lib/XXV/MODULES/TIMERS.pm:1008 msgid "No timer defined to toggle! Please use ttoggle 'id'." msgstr "Kein Timer zum Umschalten definiert! Bitte verwende ttoggle 'tid'" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:103 -msgid "Delete timer 'tid'" -msgstr "Lösche Timer 'tid'" +#: ../lib/XXV/MODULES/TIMERS.pm:104 +msgid "Activate/Deactive timer 'tid'" +msgstr "Aktiviere/Deaktiviere Timer 'tid'" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:1063 ../lib/XXV/MODULES/TIMERS.pm:677 ../lib/XXV/MODULES/TIMERS.pm:985 +#: ../lib/XXV/MODULES/TIMERS.pm:1059 ../lib/XXV/MODULES/TIMERS.pm:655 ../lib/XXV/MODULES/TIMERS.pm:980 msgid "Timer '%s' does not exist in the database!" msgstr "Timer '%s' existiert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:1092 +#: ../lib/XXV/MODULES/TIMERS.pm:1088 msgid "No timer to toggle!" msgstr "Kein Timer zum Umschalten!" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:110 -msgid "Activate/Deactive timer 'tid'" -msgstr "Aktiviere/Deaktiviere Timer 'tid'" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:124 +#: ../lib/XXV/MODULES/TIMERS.pm:118 msgid "Create event entries if the user has created a new timer." msgstr "Erzeuge Ereigniseinträge, wenn ein neuer Timer vom Anwender erstellt wurde." @@ -4178,159 +4294,159 @@ msgid "%d timer written to database." msgstr "%d Timer in Datenbank geschrieben." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:150 +#: ../lib/XXV/MODULES/TIMERS.pm:144 msgid "New timer found: %s" msgstr "Neuer Timer gefunden: %s" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:19 +#: ../lib/XXV/MODULES/TIMERS.pm:18 msgid "This module reads timers and saves it to the database." msgstr "Diese Modul liest die timers.conf und speichert sie in der Datenbank." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:192 +#: ../lib/XXV/MODULES/TIMERS.pm:186 msgid "Create event entries if the user has deleted a timer." msgstr "Erzeuge Ereigniseinträge, wenn ein Timer vom Anwender gelöscht wurde." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:1927 -msgid "Timer title '%s' has started the recording!" -msgstr "Timer mit Titel '%s' hat die Aufnahme gestartet!" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:1928 -msgid "on channel: %s to %s" -msgstr "auf Kanal: %s bis %s" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:204 +#: ../lib/XXV/MODULES/TIMERS.pm:198 msgid "Timer deleted: %s" msgstr "Timer gelöscht: %s" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:241 +#: ../lib/XXV/MODULES/TIMERS.pm:235 msgid "Create event entries if the user has toggled a timer." msgstr "Erzeugt Eventeinträge, wenn eine Timer vom User umgeschaltet wurde." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:256 +#: ../lib/XXV/MODULES/TIMERS.pm:250 msgid "Timer activated: %s" msgstr "Timer aktiviert: %s" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:258 +#: ../lib/XXV/MODULES/TIMERS.pm:252 msgid "Timer deactivated: %s" msgstr "Timer deaktiviert: %s" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:27 +#: ../lib/XXV/MODULES/TIMERS.pm:26 msgid "How often timers are to be updated (in seconds)" msgstr "Wie oft sollen Timer aktualisiert werden (in Sekunden)" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:301 +#: ../lib/XXV/MODULES/TIMERS.pm:295 msgid "Create event entries if a timer has been updated." msgstr "Erzeuge Eventeinträge, wenn ein Timer aktualisiert wurde." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:358 +#: ../lib/XXV/MODULES/TIMERS.pm:352 msgid "%d timer exists." msgstr "Es exisiteren %d Timer." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:43 +#: ../lib/XXV/MODULES/TIMERS.pm:42 msgid "Priority of a timer for recordings when creating a new timer" msgstr "Die Priorität eines Timers für Aufnahmen, bei Erzeugen eines neuen Timer" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:48 +#: ../lib/XXV/MODULES/TIMERS.pm:47 msgid "The guaranteed lifetime (in days) of a recording created by this timer" msgstr "Die garantierte Lebenszeit (in Tagen) einer Aufnahme, die durch diesen Timer erzeugt wurde" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:53 -msgid "List of present source of DVB cards. (eg. S19.2E,S19.2E,T,T )" -msgstr "Liste der vorhandenen Quellen der DVB Karten. (z.B. S19.2E,S19.2E,T,T )" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:58 +#: ../lib/XXV/MODULES/TIMERS.pm:52 msgid "Use Programme Delivery Control (PDC) to control start time" msgstr "Verwende Video Program System (VPS) zum Überwachen der Startzeit" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:613 +#: ../lib/XXV/MODULES/TIMERS.pm:57 +msgid "Change timers if EPG entries change" +msgstr "Timer justieren, wenn EPG Eintrag verändert wurde" + +#-------------------- +#: ../lib/XXV/MODULES/TIMERS.pm:589 msgid "Event '%s' does not exist in the database!" msgstr "Sendung '%s' existiert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:629 ../lib/XXV/MODULES/TIMERS.pm:867 +#: ../lib/XXV/MODULES/TIMERS.pm:605 ../lib/XXV/MODULES/TIMERS.pm:849 msgid "New timer" msgstr "Neuer Timer" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:63 -msgid "Change timers if EPG entries change" -msgstr "Timer justieren, wenn EPG Eintrag verändert wurde" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:70 +#: ../lib/XXV/MODULES/TIMERS.pm:64 msgid "List timers 'tid'" msgstr "Zeige Timer 'tid'" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:710 +#: ../lib/XXV/MODULES/TIMERS.pm:685 msgid "Enable this timer" msgstr "Aktiviere diesen Timer" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:715 +#: ../lib/XXV/MODULES/TIMERS.pm:690 msgid "Use PDC time to control timer" msgstr "Verwende VPS Zeit zum Überwachen des Timers" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:726 +#: ../lib/XXV/MODULES/TIMERS.pm:70 +msgid "Search timers 'text'" +msgstr "Suche Timer 'text'" + +#-------------------- +#: ../lib/XXV/MODULES/TIMERS.pm:701 +msgid "Which video disk recorder should record" +msgstr "Welcher Video Disk Recorder soll aufzeichen" + +#-------------------- +#: ../lib/XXV/MODULES/TIMERS.pm:707 msgid "Which channel should recorded" msgstr "Welcher Kanal soll aufgezeichnet werden" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:748 +#: ../lib/XXV/MODULES/TIMERS.pm:729 msgid "%Y-%m-%d" msgstr "%d.%m.%Y" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:754 +#: ../lib/XXV/MODULES/TIMERS.pm:735 msgid "Enter a day or weekday in format 'MTWTFSS'." msgstr "Datum oder Wochentag im Format 'MDMDFSS' eingeben." #-------------------- #: ../lib/XXV/MODULES/TIMERS.pm:76 -msgid "Search timers 'text'" -msgstr "Suche Timer 'text'" - -#-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:82 msgid "Read timers and write them to the database" msgstr "Lese Timer und schreibe sie in die Datenbank" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:866 +#: ../lib/XXV/MODULES/TIMERS.pm:83 +msgid "Create timer 'eid'" +msgstr "Erzeuge Timer 'eid'" + +#-------------------- +#: ../lib/XXV/MODULES/TIMERS.pm:848 msgid "Edit timer" msgstr "Timer bearbeiten" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:89 -msgid "Create timer 'eid'" -msgstr "Erzeuge Timer 'eid'" +#: ../lib/XXV/MODULES/TIMERS.pm:90 +msgid "Edit timer 'tid'" +msgstr "Bearbeite Timer 'tid'" #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:928 +#: ../lib/XXV/MODULES/TIMERS.pm:922 msgid "No timer defined for deletion! Please use tdelete 'tid'." msgstr "Kein Timer zum Löschen definiert! Bitte verwende tdelete 'tid'." #-------------------- -#: ../lib/XXV/MODULES/TIMERS.pm:96 -msgid "Edit timer 'tid'" -msgstr "Bearbeite Timer 'tid'" +#: ../lib/XXV/MODULES/TIMERS.pm:97 +msgid "Delete timer 'tid'" +msgstr "Lösche Timer 'tid'" + +#-------------------- +#: ../lib/XXV/MODULES/TIMERS.pm:996 +msgid "No timer to delete!" +msgstr "Kein Timer zum Löschen!" #-------------------- #: ../lib/XXV/MODULES/USER.pm:102 @@ -4609,7 +4725,7 @@ msgid "Number of port to listen for wap clients" msgstr "Nummer des Port, um auf WAP-Clients zu lauschen" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:202 +#: ../lib/XXV/MODULES/XMLTV.pm:203 msgid "Import epg data from xmltv sources ..." msgstr "Importiere EPG Daten von XMLTV Quellen" @@ -4619,17 +4735,17 @@ msgid "This module import epg data from xmltv sources." msgstr "Dieses Modul importiert EPG Daten von XMLTV Quellen." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:262 +#: ../lib/XXV/MODULES/XMLTV.pm:263 msgid "Import epg data for channel '%s'" msgstr "Importiere EPG Daten für Kanal '%s'" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:293 +#: ../lib/XXV/MODULES/XMLTV.pm:294 msgid "Transmit data." msgstr "Übertrage Daten." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:313 +#: ../lib/XXV/MODULES/XMLTV.pm:314 msgid "None data exits to import" msgstr "Keine Daten zum Importieren vorhanden." @@ -4639,7 +4755,7 @@ msgid "Manual import epg data from xmltv sources." msgstr "Manueller Import der EPG Daten von XMLTV Quellen." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:382 +#: ../lib/XXV/MODULES/XMLTV.pm:383 msgid "Title not available" msgstr "Titel nicht verfügbar" @@ -4649,17 +4765,17 @@ msgid "List rules to import epg data from xmltv sources." msgstr "Zeige Regeln zum Importieren von EPG-Daten von XMLTV Quellen." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:484 ../lib/XXV/MODULES/XMLTV.pm:651 +#: ../lib/XXV/MODULES/XMLTV.pm:485 ../lib/XXV/MODULES/XMLTV.pm:652 msgid "Rule to import epg data from xmltv sources with ID '%s' does not exist in the database!" msgstr "Regel zum Importieren von EPG-Daten von XMLTV Quellen mit ID '%s' existiert nicht in der Datenbank!" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:500 +#: ../lib/XXV/MODULES/XMLTV.pm:501 msgid "Enable this rule" msgstr "Aktiviere Regel" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:503 +#: ../lib/XXV/MODULES/XMLTV.pm:504 msgid "Source to import?" msgstr "Quelle zum Importieren?" @@ -4669,37 +4785,37 @@ msgid "Create rule to import epg data from xmltv sources." msgstr "Erzeuge Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:510 +#: ../lib/XXV/MODULES/XMLTV.pm:511 msgid "Limit import by this channel name inside xmltv source?" msgstr "Begrenze Import auf diesen Kanalnamen innerhalb der XMLTV Quelle!" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:518 +#: ../lib/XXV/MODULES/XMLTV.pm:519 msgid "Assign data to channel?" msgstr "Weise Daten einen Kanal zu?" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:537 +#: ../lib/XXV/MODULES/XMLTV.pm:538 msgid "Parse data as template?" msgstr "Übersetzte Daten als Template?" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:547 +#: ../lib/XXV/MODULES/XMLTV.pm:548 msgid "Interval to parse data?" msgstr "Intervall zum Lesen der Daten?" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:559 +#: ../lib/XXV/MODULES/XMLTV.pm:560 msgid "Edit rule to import epg data from xmltv sources" msgstr "Bearbeite Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:560 +#: ../lib/XXV/MODULES/XMLTV.pm:561 msgid "Create a new rule to import epg data from xmltv sources" msgstr "Erzeuge neue Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:568 +#: ../lib/XXV/MODULES/XMLTV.pm:569 msgid "Rule to import epg data from xmltv sources saved!" msgstr "Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle gespeichert!" @@ -4709,12 +4825,12 @@ msgid "Delete rule to import epg data from xmltv sources." msgstr "Lösche Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:610 ../lib/XXV/MODULES/XMLTV.pm:617 +#: ../lib/XXV/MODULES/XMLTV.pm:611 ../lib/XXV/MODULES/XMLTV.pm:618 msgid "Couldn't insert rule to import epg data from xmltv sources in database!" msgstr "Konnte Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle nicht in Datenbank einfügen!" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:643 +#: ../lib/XXV/MODULES/XMLTV.pm:644 msgid "Missing ID to select rules for deletion! Please use xmltvremove 'id'" msgstr "Vermisse ID zur Auswahl der Regel zum Löschen! Bitte verwende xmltvremove 'id'" @@ -4724,52 +4840,47 @@ msgid "Edit rule to import epg data from xmltv sources." msgstr "Bearbeite Regel zum Importieren von EPG-Daten aus einer XMLTV Quelle." #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:655 +#: ../lib/XXV/MODULES/XMLTV.pm:656 msgid "Rule import epg data from xmltv sources %s is deleted." msgstr "Regel %s zum Importieren von EPG-Daten aus einer XMLTV Quelle gelöscht!" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:676 -msgid "Active" -msgstr "Aktive" - -#-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:678 +#: ../lib/XXV/MODULES/XMLTV.pm:679 msgid "Parse data as template" msgstr "Übersetze Daten als Template" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:679 +#: ../lib/XXV/MODULES/XMLTV.pm:680 msgid "Interval to parse data" msgstr "Intervall zum einlesen der Daten" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:680 +#: ../lib/XXV/MODULES/XMLTV.pm:681 msgid "source to import" msgstr "Quelle zum Importieren" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:760 +#: ../lib/XXV/MODULES/XMLTV.pm:761 msgid "Yes" msgstr "Ja" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:761 +#: ../lib/XXV/MODULES/XMLTV.pm:762 msgid "No" msgstr "Nein" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:772 +#: ../lib/XXV/MODULES/XMLTV.pm:773 msgid "Every EPG Data import" msgstr "Import bei jedem einlesen von EPG Daten" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:773 +#: ../lib/XXV/MODULES/XMLTV.pm:774 msgid "Once every day" msgstr "Einmalig per Tag" #-------------------- -#: ../lib/XXV/MODULES/XMLTV.pm:774 +#: ../lib/XXV/MODULES/XMLTV.pm:775 msgid "Once every week" msgstr "Einmalig per Woche" @@ -5065,12 +5176,12 @@ msgid "This receives and sends WAP messages." msgstr "Dies empfängt und sendet WAP Nachrichten." #-------------------- -#: ../wml/next.tmpl:31 ../wml/next.tmpl:44 ../wml/now.tmpl:31 ../wml/now.tmpl:44 ../wml/program.tmpl:23 ../wml/program.tmpl:62 ../wml/program.tmpl:75 ../wml/search.tmpl:33 ../wml/search.tmpl:46 ../wml/tlist.tmpl:61 ../wml/tlist.tmpl:74 ../wml/tsearch.tmpl:61 ../wml/tsearch.tmpl:74 +#: ../wml/next.tmpl:31 ../wml/next.tmpl:44 ../wml/now.tmpl:31 ../wml/now.tmpl:44 ../wml/program.tmpl:23 ../wml/program.tmpl:62 ../wml/program.tmpl:75 ../wml/search.tmpl:33 ../wml/search.tmpl:46 ../wml/tlist.tmpl:61 ../wml/tlist.tmpl:74 msgid "Forward" msgstr "Weiter" #-------------------- -#: ../wml/tlist.tmpl:5 ../wml/tsearch.tmpl:5 +#: ../wml/tlist.tmpl:5 #. (12) msgid "Show timers" msgstr "Zeige Timer" diff --git a/locale/de/LC_MESSAGES/xxv.mo b/locale/de/LC_MESSAGES/xxv.mo Binary files differindex 0676eb2..ad3f842 100644 --- a/locale/de/LC_MESSAGES/xxv.mo +++ b/locale/de/LC_MESSAGES/xxv.mo |
