Version 2.1.7

VDR developer version 2.1.7 is now available at

       ftp://ftp.tvdr.de/vdr/Developer/vdr-2.1.7.tar.bz2

A 'diff' against the previous version is available at

       ftp://ftp.tvdr.de/vdr/Developer/vdr-2.1.6-2.1.7.diff

MD5 checksums:

1c954bad31ce74cd1cbd7987e62d2a98  vdr-2.1.7.tar.bz2
88a90327a75833b7723942d3bd25f954  vdr-2.1.6-2.1.7.diff

WARNING:
========

This is a *developer* version. Even though *I* use it in my productive
environment, I strongly recommend that you only use it under controlled
conditions and for testing and debugging.

From the HISTORY file:
- No longer logging an error message in DirSizeMB() if the given directory doesn't
  exist. This avoids lots of log entries in case several VDRs use the same video
  directory and one of them has already physically removed a recording directory,
  while the others still have it in their list of deleted recordings.
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- A cCamSlot that has WantsTsData set to true in its constructor now also gets
  the CAT and EMM PIDs data.
- Fixed a possible division by zero in frame rate detection.
- VDR now reads command line options from *.conf files in /etc/vdr/conf.d (thanks
  to Lars Hanisch). See vdr.1 and vdr.5 for details.
- Fixed a possible crash in the LCARS skin (thanks to Thomas Reufer).
- Updated the dvbhddevice plugin source.
- Fixed a bug in the Makefile when installing plugins with LCLBLD=1 (thanks to
  Stefan Huelswitt).
- The pid of the PMT in which the CA descriptors of a given channel are broadcast
  is now stored together with the CA descriptors and can be retrieved by calling
  GetPmtPid() (this information is only required to receive encrypted channels
  with the OctopusNet receiver via the 'satip' plugin).
- Channels that are not listed in the SDT are now only marked as OBSOLETE if
  "Setup/DVB/Update channels" is set to a value other than "no" or "PIDs only".
- Fixed multiple OBSOLETE marks in channels that are not listed in the SDT in case
  "Setup/Miscellaneous/Show channel names with source" is set to "yes".
- The new function cOsd::DrawScaledBitmap() is now used for drawing subtitles.
  This function can be reimplemented by high level OSDs which may be able to do
  the scaling in hardware or otherwise more efficiently (thanks to Thomas Reufer).
- Fixed detaching receivers from devices in case a CAM needs to receive the TS
  (reported by Dietmar Spingler).
- Fixed resetting the receiver for EMM pids for CAMs that need to receive the TS
  (reported by Dietmar Spingler).
- Fixed (well, actually worked around) a problem with subtitles not being displayed
  because the broadcaster doesn't set the data's version numbers as required by the
  DVB standard (thanks to Rolf Ahrenberg).
- Fixed support for systemd (thanks to Christopher Reimer).
- Added a missing backslash to the help text of the SVDRP command MOVR (thanks to
  Lars Hanisch).
- Added subsystem id support for DVB devices connected via USB (thanks to Jose
  Alberto Reguero).
- Added the functions IndexOf(), InsertUnique(), AppendUnique() and RemoveElement()
  to the cVector class (thanks to Stefan Schallenberg).
- Fixed a possible out-of-bounds access in cVector::Remove().
- Added functions to set and retrieve the priority of a cReceiver (suggested by
  Frank Schmirler).
- Added the new parameters "Setup/Miscellaneous/Volume steps" and
  ".../Volume linearize" (thanks to Claus Muus). See the MANUAL for details.
- Fixed jumping to an absolute position via the Red key in case replay was paused
  (reported by Dieter Ferdinand).
- Changed the German weekday names from "MonDieMitDonFreSamSon" to
  "Mo.Di.Mi.Do.Fr.Sa.So." (thanks to Stefan Blochberger).
- Now handling CAT sections that consist of more than one TS packet.
- Added handling for DTS audio tracks to cPatPmtParser::ParsePmt() (thanks to
  Thomas Reufer).
- Added support for PGS subtitles (thanks to Thomas Reufer).
- Use of the function cOsd::GetBitmap() outside of derived classes is now deprecated,
  and it may be made 'protected' in a future version, since it doesn't work with
  TrueColor OSDs. Plugin authors may want to modify their code so that it
  works without this function.
- Modified the descriptions of several threads, so that the important information
  (like device or frontend numbers) is within the first 15 characters of the
  string, because only these are displayed in thread listings. Plugin authors may
  want to do the same.
- Added the channel name to log messages that reference a channel (suggested by
  Dietmar Spingler).
- Modified the CAM API so that it is possible to implement CAMs that can be freely
  assigned to any devices (thanks to Jasmin Jessich).
- Plugins can now implement the function SetMenuSortMode() in their skin objects
  derived from cSkinDisplayMenu, to get informed about the currently used sort
  mode, if applicable (suggested by Martin Schirrmacher).
- Added cOsdProvider::OsdSizeChanged(), which plugins that implement an output device
  can call to signal a change in the OSD that requires a redraw of the currently
  displayed object (thanks to Thomas Reufer).
- Added a comment to cRecorder::Activate() about the need to call Detach() in the
  destructor (suggested by Eike Sauer).
- Now returning from removing deleted recordings after at most 10 seconds, or if the
  user presses a remote control key, to keep the system from getting unresponsive
  when removing a huge number of files (reported by Dieter Ferdinand).
- Fixed generating the index file of an existing recording in case at the of a TS file
  there is less data in the buffer than needed by the frame detector. In such a case
  it was possible that frames were missed, and there was most likely a distortion
  when replaying that part of a recording. This is mostly a problem for recordings that
  consist of more than one *.ts file. Single file recordings could only lose some
  frames at their very end, which probably doesn't matter. At any rate, if you have
  generated an index file with VDR version 2.0.6, 2.1.5 or 2.1.6, you may want to
  do so again with this version to make sure the index is OK.
- Added the new command line option --updindex, which can be used to update an
  incomplete index of a recording (based on a patch from Helmut Auer).
This commit is contained in:
Klaus Schmidinger 2015-01-18 11:38:00 +01:00 committed by Dieter Hametner
parent 3e4e4454fc
commit 2db7397542
82 changed files with 1615 additions and 246 deletions

View File

@ -232,6 +232,7 @@ Stefan Huelswitt <s.huelswitt@gmx.de>
featured DVB cards featured DVB cards
for pointing out a bug in handling lowercase polarization characters in channel for pointing out a bug in handling lowercase polarization characters in channel
definitions if no DiSEqC is used definitions if no DiSEqC is used
for fixing a bug in the Makefile when installing plugins with LCLBLD=1
Ulrich Röder <roeder@efr-net.de> Ulrich Röder <roeder@efr-net.de>
for pointing out that there are channels that have a symbol rate higher than 27500 for pointing out that there are channels that have a symbol rate higher than 27500
@ -622,6 +623,7 @@ Helmut Auer <vdr@helmutauer.de>
via the main menu and by pressing the Recordings key via the main menu and by pressing the Recordings key
for helping to debug a problem with frame detection in MPEG-2 streams that have "bottom fields" for helping to debug a problem with frame detection in MPEG-2 streams that have "bottom fields"
or varying GOP structures or varying GOP structures
for a patch that was used to implement the command line option --updindex
Jeremy Hall <jhall@UU.NET> Jeremy Hall <jhall@UU.NET>
for fixing an incomplete initialization of the filter parameters in eit.c for fixing an incomplete initialization of the filter parameters in eit.c
@ -1188,6 +1190,8 @@ Rolf Ahrenberg <Rolf.Ahrenberg@sci.fi>
for reporting a problem with adding new source types in case they are already for reporting a problem with adding new source types in case they are already
registered registered
for adding support for "Pilot", "T2-System-Id" and "SISO/MISO" parameters for adding support for "Pilot", "T2-System-Id" and "SISO/MISO" parameters
for fixing a problem with subtitles not being displayed because the broadcaster
doesn't set the data's version numbers as required by the DVB standard
Ralf Klueber <ralf.klueber@vodafone.com> Ralf Klueber <ralf.klueber@vodafone.com>
for reporting a bug in cutting a recording if there is only a single editing mark for reporting a bug in cutting a recording if there is only a single editing mark
@ -2546,6 +2550,7 @@ Frank Schmirler <vdr@schmirler.de>
for suggestions used in revising priority handling to allow receivers with a priority for suggestions used in revising priority handling to allow receivers with a priority
that is lower than that of live viewing that is lower than that of live viewing
for fixing handling IDLEPRIORITY in cDvbDevice::ProvidesChannel() for fixing handling IDLEPRIORITY in cDvbDevice::ProvidesChannel()
for suggesting to add functions to set and retrieve the priority of a cReceiver
Jörn Reder <joern@zyn.de> Jörn Reder <joern@zyn.de>
for reporting that a recording may unnecessarily block a device with a CAM, while for reporting that a recording may unnecessarily block a device with a CAM, while
@ -2615,6 +2620,7 @@ Jose Alberto Reguero <jareguero@telefonica.net>
for a patch that fixed part of a crash in i18n character set conversion for a patch that fixed part of a crash in i18n character set conversion
for fixing cDvbPlayer::NextFile() to handle files larger than 2GB for fixing cDvbPlayer::NextFile() to handle files larger than 2GB
for implementing full handling of the stream types of Dolby Digital pids for implementing full handling of the stream types of Dolby Digital pids
for adding subsystem id support for DVB devices connected via USB
Patrice Staudt <staudt@engsystem.net> Patrice Staudt <staudt@engsystem.net>
for adding full weekday names to i18n.c for plugins to use for adding full weekday names to i18n.c for plugins to use
@ -2895,6 +2901,8 @@ Lars Hanisch <dvb@flensrocker.de>
the caller to have it display only a certain subset of the recordings the caller to have it display only a certain subset of the recordings
for adding handling UTF-8 'umlaut' characters to cKbdRemote for adding handling UTF-8 'umlaut' characters to cKbdRemote
for fixing learning keyboard remote control codes for fixing learning keyboard remote control codes
for making VDR read command line options from *.conf files in /etc/vdr/conf.d
for adding a missing backslash to the help text of the SVDRP command MOVR
Alex Lasnier <alex@fepg.org> Alex Lasnier <alex@fepg.org>
for adding tuning support for ATSC devices for adding tuning support for ATSC devices
@ -3168,6 +3176,7 @@ Stefan Blochberger <Stefan.Blochberger@gmx.de>
recording is started recording is started
for suggesting that floating point numbers presented to the user shall be displayed for suggesting that floating point numbers presented to the user shall be displayed
in the way defined by the current locale in the way defined by the current locale
for changing the German weekday names from "MonDieMitDonFreSamSon" to "Mo.Di.Mi.Do.Fr.Sa.So."
Cedric Dewijs <cedric.dewijs@telfort.nl> Cedric Dewijs <cedric.dewijs@telfort.nl>
for adding maximum SNR value for PCTV Systems PCTV 73ESE for adding maximum SNR value for PCTV Systems PCTV 73ESE
@ -3259,11 +3268,18 @@ Thomas Reufer <thomas@reufer.ch>
for suggesting to add an additional parameter named Forward to cDevice::TrickSpeed() for suggesting to add an additional parameter named Forward to cDevice::TrickSpeed()
for suggesting to add a note to ePlayMode in device.h that VDR itself always uses for suggesting to add a note to ePlayMode in device.h that VDR itself always uses
pmAudioVideo when replaying a recording pmAudioVideo when replaying a recording
for fixing a possible crash in the LCARS skin
for implementing cOsd::DrawScaledBitmap()
for adding handling for DTS audio tracks to cPatPmtParser::ParsePmt()
for adding support for PGS subtitles
for adding cOsdProvider::OsdSizeChanged()
Eike Sauer <EikeSauer@t-online.de> Eike Sauer <EikeSauer@t-online.de>
for reporting a problem with channels that need more than 5 TS packets for detecting for reporting a problem with channels that need more than 5 TS packets for detecting
frame borders frame borders
for reporting a problem in handling the frame detection buffer length for reporting a problem in handling the frame detection buffer length
for suggesting to add a comment to cRecorder::Activate() about the need to call
Detach() in the destructor
Christian Paulick <cpaulick@xeatre.tv> Christian Paulick <cpaulick@xeatre.tv>
for reporting a problem with frame detection in MPEG-2 streams that have "bottom fields" for reporting a problem with frame detection in MPEG-2 streams that have "bottom fields"
@ -3284,3 +3300,32 @@ Tony Houghton <h@realh.co.uk>
Christian Winkler <winkler_chr@yahoo.de> Christian Winkler <winkler_chr@yahoo.de>
for reporting a problem with transfer mode on full featured DVB cards for encrypted for reporting a problem with transfer mode on full featured DVB cards for encrypted
channels that have no audio pid channels that have no audio pid
Dietmar Spingler <d_spingler@gmx.de>
for reporting a problem that led to a fix in detaching receivers from devices in case
a CAM needs to receive the TS
for reporting a problem that led to a fix with EMM pids not being properly reset for
CAMs that need to receive the TS
for suggesting to add the channel name to log messages that reference a channel
Stefan Schallenberg <infos@nafets.de>
for adding the functions IndexOf(), InsertUnique(), AppendUnique() and RemoveElement()
to the cVector class
Claus Muus <email@clausmuus.de>
for adding the new parameters "Setup/Miscellaneous/Volume steps" and
".../Volume linearize"
Dieter Ferdinand <dieter.ferdinand@gmx.de>
for reporting a problem with jumping to an absolute position via the Red key in
case replay was paused
for reporting a problem with the system getting unresponsive when removing a huge
number of files in the thread that removes deleted recordings
Jasmin Jessich <jasmin@anw.at>
for modifying the CAM API so that it is possible to implement CAMs that can be freely
assigned to any devices
Martin Schirrmacher <schirrmie@gmail.com>
for suggesting to provide a way for skin plugins to get informed about the currently
used sort mode of a menu

134
HISTORY
View File

@ -8260,3 +8260,137 @@ Video Disk Recorder Revision History
IsOnVideoDirectoryFileSystem(). IsOnVideoDirectoryFileSystem().
- Added support for systemd (thanks to Christopher Reimer). To activate this you - Added support for systemd (thanks to Christopher Reimer). To activate this you
need to add "SDNOTIFY=1" to the 'make' call. need to add "SDNOTIFY=1" to the 'make' call.
2014-03-22: Version 2.0.6
- Updated 'sources.conf' (thanks to Antti Hartikainen).
- cFont::CreateFont() now returns a dummy font in case there are no fonts installed.
This prevents a crash with the LCARS skin on a system that has no fonts.
- Fixed detecting frame borders in MPEG-2 streams that have "bottom fields" or varying
GOP structures (reported by Christian Paulick, with help from Helmut Auer).
- Fixed a wrong alignment in cCiDateTime::SendDateTime().
- Now checking whether the primary device actually has a decoder before retuning the
current channel after a change in its parameters. This fixes broken recordings on
the primary device on "headless" systems.
- Increased MIN_TS_PACKETS_FOR_FRAME_DETECTOR to 100 and introduced counting the number
of actual video TS packets in cTsPayload in order to be able to record channels that
sometimes need even more than 10 TS packets for detecting frame borders (reported by
Eike Sauer and Oliver Endriss).
- Fixed sorting recordings by time in the Recordings menu if "Setup/OSD/Recording
directories" is set to "no".
- Fixed clearing non-editable members in the channel editor (thanks to Rolf Ahrenberg).
- Fixed flickering if subtitles are active while the OSD demo is running.
- Fixed a possible crash in the OSD demo (reported by Christopher Reimer).
- Fixed learning keyboard remote control codes (thanks to Lars Hanisch).
- Fixed the replay progress display for very long recordings.
- Improved PAT/PMT scanning to speed up initial tuning to encrypted channels on
transponders with many PAT entries (reported by Mariusz Bialonczyk).
- Fixed detecting broken video data streams when recording.
- Fixed handling frame detection buffer length (reported by Eike Sauer).
- Fixed keeping the current position in the Recordings menu if a recording was
deleted in a sub folder.
- Fixed handling transfer mode on full featured DVB cards for encrypted channels
that have no audio pid (reported by Christian Winkler).
- Fixed a possible endless loop in cH264Parser::GetGolombUe(), which caused recordings
on some HD channels to get stuck and resulted in buffer overflows.
- Fixed handling PAT packets when detecting frames, so that they can be properly
taken into account when regenerating the index of a recording.
- Fixed adding new source types in case they are already registered (reported by Rolf
Ahrenberg).
- Fixed drawing the live indicator in the LCARS skin in case there are no devices.
- The SDT is now only parsed *after* the NIT has been read, and it explicitly uses
the source value derived from the NIT. This should prevent new channels from being
created with the wrong source.
- Now initializing the isOnVideoDirectoryFileSystem member of cRecording when
scanning the video directory, so that it won't cause a delay when opening the menu
on a system with a large number of recordings.
- The APIVERSION has been increased to 2.0.6 due to the changes to pat.h, sdt.h and
the functional modification to cFont::CreateFont().
2015-01-18: Version 2.1.7
- No longer logging an error message in DirSizeMB() if the given directory doesn't
exist. This avoids lots of log entries in case several VDRs use the same video
directory and one of them has already physically removed a recording directory,
while the others still have it in their list of deleted recordings.
- Updated the Italian OSD texts (thanks to Diego Pierotto).
- A cCamSlot that has WantsTsData set to true in its constructor now also gets
the CAT and EMM PIDs data.
- Fixed a possible division by zero in frame rate detection.
- VDR now reads command line options from *.conf files in /etc/vdr/conf.d (thanks
to Lars Hanisch). See vdr.1 and vdr.5 for details.
- Fixed a possible crash in the LCARS skin (thanks to Thomas Reufer).
- Updated the dvbhddevice plugin source.
- Fixed a bug in the Makefile when installing plugins with LCLBLD=1 (thanks to
Stefan Huelswitt).
- The pid of the PMT in which the CA descriptors of a given channel are broadcast
is now stored together with the CA descriptors and can be retrieved by calling
GetPmtPid() (this information is only required to receive encrypted channels
with the OctopusNet receiver via the 'satip' plugin).
- Channels that are not listed in the SDT are now only marked as OBSOLETE if
"Setup/DVB/Update channels" is set to a value other than "no" or "PIDs only".
- Fixed multiple OBSOLETE marks in channels that are not listed in the SDT in case
"Setup/Miscellaneous/Show channel names with source" is set to "yes".
- The new function cOsd::DrawScaledBitmap() is now used for drawing subtitles.
This function can be reimplemented by high level OSDs which may be able to do
the scaling in hardware or otherwise more efficiently (thanks to Thomas Reufer).
- Fixed detaching receivers from devices in case a CAM needs to receive the TS
(reported by Dietmar Spingler).
- Fixed resetting the receiver for EMM pids for CAMs that need to receive the TS
(reported by Dietmar Spingler).
- Fixed (well, actually worked around) a problem with subtitles not being displayed
because the broadcaster doesn't set the data's version numbers as required by the
DVB standard (thanks to Rolf Ahrenberg).
- Fixed support for systemd (thanks to Christopher Reimer).
- Added a missing backslash to the help text of the SVDRP command MOVR (thanks to
Lars Hanisch).
- Added subsystem id support for DVB devices connected via USB (thanks to Jose
Alberto Reguero).
- Added the functions IndexOf(), InsertUnique(), AppendUnique() and RemoveElement()
to the cVector class (thanks to Stefan Schallenberg).
- Fixed a possible out-of-bounds access in cVector::Remove().
- Added functions to set and retrieve the priority of a cReceiver (suggested by
Frank Schmirler).
- Added the new parameters "Setup/Miscellaneous/Volume steps" and
".../Volume linearize" (thanks to Claus Muus). See the MANUAL for details.
- Fixed jumping to an absolute position via the Red key in case replay was paused
(reported by Dieter Ferdinand).
- Changed the German weekday names from "MonDieMitDonFreSamSon" to
"Mo.Di.Mi.Do.Fr.Sa.So." (thanks to Stefan Blochberger).
- Now handling CAT sections that consist of more than one TS packet.
- Added handling for DTS audio tracks to cPatPmtParser::ParsePmt() (thanks to
Thomas Reufer).
- Added support for PGS subtitles (thanks to Thomas Reufer).
- Use of the function cOsd::GetBitmap() outside of derived classes is now deprecated,
and it may be made 'protected' in a future version, since it doesn't work with
TrueColor OSDs. Plugin authors may want to modify their code so that it
works without this function.
- Modified the descriptions of several threads, so that the important information
(like device or frontend numbers) is within the first 15 characters of the
string, because only these are displayed in thread listings. Plugin authors may
want to do the same.
- Added the channel name to log messages that reference a channel (suggested by
Dietmar Spingler).
- Modified the CAM API so that it is possible to implement CAMs that can be freely
assigned to any devices (thanks to Jasmin Jessich).
- Plugins can now implement the function SetMenuSortMode() in their skin objects
derived from cSkinDisplayMenu, to get informed about the currently used sort
mode, if applicable (suggested by Martin Schirrmacher).
- Added cOsdProvider::OsdSizeChanged(), which plugins that implement an output device
can call to signal a change in the OSD that requires a redraw of the currently
displayed object (thanks to Thomas Reufer).
- Added a comment to cRecorder::Activate() about the need to call Detach() in the
destructor (suggested by Eike Sauer).
- Now returning from removing deleted recordings after at most 10 seconds, or if the
user presses a remote control key, to keep the system from getting unresponsive
when removing a huge number of files (reported by Dieter Ferdinand).
- Fixed generating the index file of an existing recording in case at the of a TS file
there is less data in the buffer than needed by the frame detector. In such a case
it was possible that frames were missed, and there was most likely a distortion
when replaying that part of a recording. This is mostly a problem for recordings that
consist of more than one *.ts file. Single file recordings could only lose some
frames at their very end, which probably doesn't matter. At any rate, if you have
generated an index file with VDR version 2.0.6, 2.1.5 or 2.1.6, you may want to
do so again with this version to make sure the index is OK.
- Added the new command line option --updindex, which can be used to update an
incomplete index of a recording (based on a patch from Helmut Auer).

11
MANUAL
View File

@ -999,6 +999,17 @@ Version 2.0
VDR was stopped will be used. The valid range is from VDR was stopped will be used. The valid range is from
0 (silent) to 255 (loudest). 0 (silent) to 255 (loudest).
Volume steps = 51 The number of steps the volume will use when moving from
the lowest to the highest value. The valid range is from
5 to 255.
Volume linearize = 0 How to linearize the volume control. The valid range is
from -20 to 20. A value of 0 results in no linearization.
The higher this value is, the more fine grained the control
of the volume is for low sound levels. Lower values do the
same for high sound levels. This allows you to adjust the
more or less linear volume control of your sound card.
Channels wrap = no During zapping with the "Up" and "Down" keys (or the Channels wrap = no During zapping with the "Up" and "Down" keys (or the
"Channel+" and "Channel-" keys) the current channel will "Channel+" and "Channel-" keys) the current channel will
wrap around the beginning or end of the channel list if wrap around the beginning or end of the channel list if

View File

@ -6,7 +6,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Make.config.template 3.0 2013/02/18 10:55:39 kls Exp $ # $Id: Make.config.template 3.1 2014/04/14 11:43:53 kls Exp $
### The C compiler and options: ### The C compiler and options:
@ -38,6 +38,7 @@ endif
#VIDEODIR = /srv/vdr/video #VIDEODIR = /srv/vdr/video
#CONFDIR = /var/lib/vdr #CONFDIR = /var/lib/vdr
#ARGSDIR = /etc/vdr/conf.d
#CACHEDIR = /var/cache/vdr #CACHEDIR = /var/cache/vdr
# Overrides for preset/legacy configurations: # Overrides for preset/legacy configurations:

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 3.2 2014/03/16 12:47:35 kls Exp $ # $Id: Makefile 3.4 2015/01/01 13:52:07 kls Exp $
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
@ -31,6 +31,7 @@ PLUGINDIR ?= $(CWD)/PLUGINS
DESTDIR ?= DESTDIR ?=
VIDEODIR ?= /srv/vdr/video VIDEODIR ?= /srv/vdr/video
CONFDIR ?= /var/lib/vdr CONFDIR ?= /var/lib/vdr
ARGSDIR ?= /etc/vdr/conf.d
CACHEDIR ?= /var/cache/vdr CACHEDIR ?= /var/cache/vdr
PREFIX ?= /usr/local PREFIX ?= /usr/local
@ -66,7 +67,7 @@ endif
SILIB = $(LSIDIR)/libsi.a SILIB = $(LSIDIR)/libsi.a
OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbci.o\ OBJS = args.o audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbci.o\
dvbplayer.o dvbspu.o dvbsubtitle.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\ dvbplayer.o dvbspu.o dvbsubtitle.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o positioner.o\ lirc.o menu.o menuitems.o nit.o osdbase.o osd.o pat.o player.o plugin.o positioner.o\
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\ receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o shutdown.o\
@ -104,6 +105,7 @@ LIRC_DEVICE ?= /var/run/lirc/lircd
DEFINES += -DLIRC_DEVICE=\"$(LIRC_DEVICE)\" DEFINES += -DLIRC_DEVICE=\"$(LIRC_DEVICE)\"
DEFINES += -DVIDEODIR=\"$(VIDEODIR)\" DEFINES += -DVIDEODIR=\"$(VIDEODIR)\"
DEFINES += -DCONFDIR=\"$(CONFDIR)\" DEFINES += -DCONFDIR=\"$(CONFDIR)\"
DEFINES += -DARGSDIR=\"$(ARGSDIR)\"
DEFINES += -DCACHEDIR=\"$(CACHEDIR)\" DEFINES += -DCACHEDIR=\"$(CACHEDIR)\"
DEFINES += -DRESDIR=\"$(RESDIR)\" DEFINES += -DRESDIR=\"$(RESDIR)\"
DEFINES += -DPLUGINDIR=\"$(LIBDIR)\" DEFINES += -DPLUGINDIR=\"$(LIBDIR)\"
@ -146,8 +148,9 @@ $(SILIB):
vdr.pc: vdr.pc:
@echo "bindir=$(BINDIR)" > $@ @echo "bindir=$(BINDIR)" > $@
@echo "mandir=$(MANDIR)" >> $@ @echo "mandir=$(MANDIR)" >> $@
@echo "configdir=$(CONFDIR)" >> $@
@echo "videodir=$(VIDEODIR)" >> $@ @echo "videodir=$(VIDEODIR)" >> $@
@echo "configdir=$(CONFDIR)" >> $@
@echo "argsdir=$(ARGSDIR)" >> $@
@echo "cachedir=$(CACHEDIR)" >> $@ @echo "cachedir=$(CACHEDIR)" >> $@
@echo "resdir=$(RESDIR)" >> $@ @echo "resdir=$(RESDIR)" >> $@
@echo "libdir=$(LIBDIR)" >> $@ @echo "libdir=$(LIBDIR)" >> $@
@ -225,7 +228,7 @@ plugins: include-dir vdr.pc
INCLUDES="-I$(CWD)/include"\ INCLUDES="-I$(CWD)/include"\
$(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR="$(CWD)" || failed="$$failed $$i";\ $(MAKE) --no-print-directory -C "$(PLUGINDIR)/src/$$i" VDRDIR="$(CWD)" || failed="$$failed $$i";\
if [ -n "$(LCLBLD)" ] ; then\ if [ -n "$(LCLBLD)" ] ; then\
(cd $(PLUGINDIR)/src/$$i; for l in `find -name 'libvdr-*.so' -o -name 'lib$$i-*.so'`; do install $$l $(LIBDIR)/`basename $$l`.$(APIVERSION); done);\ (cd $(PLUGINDIR)/src/$$i; for l in `find -name "libvdr-*.so" -o -name "lib$$i-*.so"`; do install $$l $(LIBDIR)/`basename $$l`.$(APIVERSION); done);\
if [ -d $(PLUGINDIR)/src/$$i/po ]; then\ if [ -d $(PLUGINDIR)/src/$$i/po ]; then\
for l in `ls $(PLUGINDIR)/src/$$i/po/*.mo`; do\ for l in `ls $(PLUGINDIR)/src/$$i/po/*.mo`; do\
install -D -m644 $$l $(LOCDIR)/`basename $$l | cut -d. -f1`/LC_MESSAGES/vdr-$$i.mo;\ install -D -m644 $$l $(LOCDIR)/`basename $$l | cut -d. -f1`/LC_MESSAGES/vdr-$$i.mo;\
@ -265,6 +268,7 @@ install-bin: vdr
install-dirs: install-dirs:
@mkdir -p $(DESTDIR)$(VIDEODIR) @mkdir -p $(DESTDIR)$(VIDEODIR)
@mkdir -p $(DESTDIR)$(CONFDIR) @mkdir -p $(DESTDIR)$(CONFDIR)
@mkdir -p $(DESTDIR)$(ARGSDIR)
@mkdir -p $(DESTDIR)$(CACHEDIR) @mkdir -p $(DESTDIR)$(CACHEDIR)
@mkdir -p $(DESTDIR)$(RESDIR) @mkdir -p $(DESTDIR)$(RESDIR)

View File

@ -108,17 +108,12 @@ cDvbHdFfDevice::~cDvbHdFfDevice()
void cDvbHdFfDevice::MakePrimaryDevice(bool On) void cDvbHdFfDevice::MakePrimaryDevice(bool On)
{ {
if (On) { if (On) {
new cHdffOsdProvider(mHdffCmdIf); new cHdffOsdProvider(mHdffCmdIf);
//TODO the same code is also used in cHdffSetupPage::Store() and cHdffMenu::SetVideoConversion() - combine?
HdffVideoFormat_t videoFormat; gHdffSetup.SetVideoFormat(mHdffCmdIf);
videoFormat.AutomaticEnabled = true; }
videoFormat.AfdEnabled = false; cDvbDevice::MakePrimaryDevice(On);
videoFormat.TvFormat = (HdffTvFormat_t) gHdffSetup.TvFormat;
videoFormat.VideoConversion = (HdffVideoConversion_t) gHdffSetup.VideoConversion;
mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat);
}
cDvbDevice::MakePrimaryDevice(On);
} }
bool cDvbHdFfDevice::HasDecoder(void) const bool cDvbHdFfDevice::HasDecoder(void) const
@ -243,6 +238,26 @@ uchar *cDvbHdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, i
return result; return result;
} }
void cDvbHdFfDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
{
if (gHdffSetup.TvFormat == HDFF_TV_FORMAT_4_BY_3)
{
switch (VideoDisplayFormat)
{
case vdfPanAndScan:
case vdfCenterCutOut:
gHdffSetup.VideoConversion = HDFF_VIDEO_CONVERSION_CENTRE_CUT_OUT;
break;
case vdfLetterBox:
gHdffSetup.VideoConversion = HDFF_VIDEO_CONVERSION_LETTERBOX_16_BY_9;
break;
}
gHdffSetup.SetVideoFormat(mHdffCmdIf);
}
cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
}
void cDvbHdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect) void cDvbHdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
{ {
if (fd_video >= 0) { if (fd_video >= 0) {
@ -795,6 +810,11 @@ int cDvbHdFfDevice::PlayVideo(const uchar *Data, int Length)
mHdffCmdIf->CmdAvEnableSync(0, true); mHdffCmdIf->CmdAvEnableSync(0, true);
isPlayingVideo = true; isPlayingVideo = true;
} }
// ignore padding PES packets
if (Data[3] == 0xBE)
return Length;
//TODO: support greater Length //TODO: support greater Length
uint8_t tsBuffer[188 * 16]; uint8_t tsBuffer[188 * 16];
uint32_t tsLength; uint32_t tsLength;

View File

@ -51,6 +51,7 @@ public:
// Video format facilities // Video format facilities
public: public:
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat);
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect); virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect);
virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect); virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect);

View File

@ -663,14 +663,23 @@ void cHdffOsdRaw::Flush(void)
{ {
if (!Active() || (mDisplay == HDFF_INVALID_HANDLE)) if (!Active() || (mDisplay == HDFF_INVALID_HANDLE))
return; return;
//struct timeval start; #ifdef MEASURE_OSD_TIME
//struct timeval end; struct timeval start;
//struct timezone timeZone; struct timeval end;
//gettimeofday(&start, &timeZone); struct timezone timeZone;
gettimeofday(&start, &timeZone);
#endif
bool render = false; bool render = false;
if (IsTrueColor()) if (IsTrueColor())
{ {
uint8_t * buffer = 0;
if (gHdffSetup.TrueColorFormat != 0)
{
buffer = new uint8_t[MAX_BITMAP_SIZE];
if (!buffer)
return;
}
LOCK_PIXMAPS; LOCK_PIXMAPS;
while (cPixmapMemory *pm = RenderPixmaps()) while (cPixmapMemory *pm = RenderPixmaps())
{ {
@ -682,17 +691,56 @@ void cHdffOsdRaw::Flush(void)
Chunk = h; Chunk = h;
for (int y = 0; y < h; y += Chunk) for (int y = 0; y < h; y += Chunk)
{ {
int hc = Chunk; int hc = Chunk;
if (y + hc > h) if (y + hc > h)
hc = h - y; hc = h - y;
mHdffCmdIf->CmdOsdDrawBitmap(mDisplay, if (gHdffSetup.TrueColorFormat == 0) // ARGB8888 (32 bit)
Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y, {
pm->Data() + y * d, w, hc, hc * d, mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
HDFF_COLOR_TYPE_ARGB8888, HDFF_INVALID_HANDLE); Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y,
pm->Data() + y * d, w, hc, hc * d,
HDFF_COLOR_TYPE_ARGB8888, HDFF_INVALID_HANDLE);
}
else if (gHdffSetup.TrueColorFormat == 1) // ARGB8565 (24 bit)
{
const tColor * pixmapData = (const tColor *) (pm->Data() + y * d);
uint8_t * bitmapData = buffer;
for (int i = 0; i < hc * w; i++)
{
bitmapData[2] = (pixmapData[i] & 0xFF000000) >> 24;
bitmapData[1] = ((pixmapData[i] & 0x00F80000) >> 16)
| ((pixmapData[i] & 0x0000E000) >> 13);
bitmapData[0] = ((pixmapData[i] & 0x00001C00) >> 5)
| ((pixmapData[i] & 0x000000F8) >> 3);
bitmapData += 3;
}
mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y,
buffer, w, hc, hc * w * 3,
HDFF_COLOR_TYPE_ARGB8565, HDFF_INVALID_HANDLE);
}
else if (gHdffSetup.TrueColorFormat == 2) // ARGB4444 (16 bit)
{
const tColor * pixmapData = (const tColor *) (pm->Data() + y * d);
uint16_t * bitmapData = (uint16_t *) buffer;
for (int i = 0; i < hc * w; i++)
{
bitmapData[i] = ((pixmapData[i] & 0xF0000000) >> 16)
| ((pixmapData[i] & 0x00F00000) >> 12)
| ((pixmapData[i] & 0x0000F000) >> 8)
| ((pixmapData[i] & 0x000000F0) >> 4);
}
mHdffCmdIf->CmdOsdDrawBitmap(mDisplay,
Left() + pm->ViewPort().X(), Top() + pm->ViewPort().Y() + y,
buffer, w, hc, hc * w * 2,
HDFF_COLOR_TYPE_ARGB4444, HDFF_INVALID_HANDLE);
}
} }
delete pm; delete pm;
render = true; render = true;
} }
if (buffer)
delete[] buffer;
} }
else else
{ {
@ -755,10 +803,12 @@ void cHdffOsdRaw::Flush(void)
if (render) if (render)
{ {
mHdffCmdIf->CmdOsdRenderDisplay(mDisplay); mHdffCmdIf->CmdOsdRenderDisplay(mDisplay);
//gettimeofday(&end, &timeZone); #ifdef MEASURE_OSD_TIME
//int timeNeeded = end.tv_usec - start.tv_usec; gettimeofday(&end, &timeZone);
//timeNeeded += (end.tv_sec - start.tv_sec) * 1000000; int timeNeeded = end.tv_usec - start.tv_usec;
//printf("time = %d\n", timeNeeded); timeNeeded += (end.tv_sec - start.tv_sec) * 1000000;
printf("time = %d\n", timeNeeded);
#endif
} }
refresh = false; refresh = false;
} }

View File

@ -56,12 +56,7 @@ eOSState cHdffMenu::ProcessKey(eKeys key)
void cHdffMenu::SetVideoConversion(void) void cHdffMenu::SetVideoConversion(void)
{ {
HdffVideoFormat_t videoFormat; gHdffSetup.SetVideoFormat(mHdffCmdIf);
videoFormat.AutomaticEnabled = true;
videoFormat.AfdEnabled = false;
videoFormat.TvFormat = (HdffTvFormat_t) gHdffSetup.TvFormat;
videoFormat.VideoConversion = (HdffVideoConversion_t) gHdffSetup.VideoConversion;
mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat);
char str[128]; char str[128];
sprintf(str, "%s: %s", tr("Video Conversion"), gHdffSetup.GetVideoConversionString()); sprintf(str, "%s: %s", tr("Video Conversion"), gHdffSetup.GetVideoConversionString());

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-dvbhddevice 0.0.4\n" "Project-Id-Version: vdr-dvbhddevice 0.0.4\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2013-08-23 12:10+0200\n" "POT-Creation-Date: 2014-09-21 14:01+0200\n"
"PO-Revision-Date: 2011-04-25 21:44+0200\n" "PO-Revision-Date: 2011-04-25 21:44+0200\n"
"Last-Translator: Christoph Haubrich\n" "Last-Translator: Christoph Haubrich\n"
"Language-Team: <see README>\n" "Language-Team: <see README>\n"
@ -121,5 +121,8 @@ msgstr "High Level OSD"
msgid "Allow True Color OSD" msgid "Allow True Color OSD"
msgstr "Erlaube True Color OSD" msgstr "Erlaube True Color OSD"
msgid "True Color format"
msgstr "True Color Format"
msgid "Hide mainmenu entry" msgid "Hide mainmenu entry"
msgstr "Hauptmenüeintrag verstecken" msgstr "Hauptmenüeintrag verstecken"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-dvbhddevice 0.0.4\n" "Project-Id-Version: vdr-dvbhddevice 0.0.4\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2013-08-23 12:10+0200\n" "POT-Creation-Date: 2014-09-21 14:01+0200\n"
"PO-Revision-Date: 2011-04-25 21:44+0200\n" "PO-Revision-Date: 2011-04-25 21:44+0200\n"
"Last-Translator: Rolf Ahrenberg\n" "Last-Translator: Rolf Ahrenberg\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n" "Language-Team: Finnish <vdr@linuxtv.org>\n"
@ -121,5 +121,8 @@ msgstr "Käytä korkean tason kuvaruutunäyttöä"
msgid "Allow True Color OSD" msgid "Allow True Color OSD"
msgstr "Salli tosivärit kuvaruutunäytölle" msgstr "Salli tosivärit kuvaruutunäytölle"
msgid "True Color format"
msgstr ""
msgid "Hide mainmenu entry" msgid "Hide mainmenu entry"
msgstr "Piilota valinta päävalikosta" msgstr "Piilota valinta päävalikosta"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: vdr-dvbhddevice 0.0.4\n" "Project-Id-Version: vdr-dvbhddevice 0.0.4\n"
"Report-Msgid-Bugs-To: <see README>\n" "Report-Msgid-Bugs-To: <see README>\n"
"POT-Creation-Date: 2013-08-23 12:10+0200\n" "POT-Creation-Date: 2014-09-21 14:01+0200\n"
"PO-Revision-Date: 2013-09-19 00:00+0100\n" "PO-Revision-Date: 2013-09-19 00:00+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: <see README>\n" "Language-Team: <see README>\n"
@ -125,5 +125,8 @@ msgstr "OSD alto livello"
msgid "Allow True Color OSD" msgid "Allow True Color OSD"
msgstr "Permetti OSD True Color" msgstr "Permetti OSD True Color"
msgid "True Color format"
msgstr ""
msgid "Hide mainmenu entry" msgid "Hide mainmenu entry"
msgstr "Nascondi voce menu principale" msgstr "Nascondi voce menu principale"

View File

@ -33,6 +33,7 @@ cHdffSetup::cHdffSetup(void)
RemoteAddress = -1; RemoteAddress = -1;
HighLevelOsd = 1; HighLevelOsd = 1;
TrueColorOsd = 1; TrueColorOsd = 1;
TrueColorFormat = 0;
HideMainMenu = 0; HideMainMenu = 0;
} }
@ -54,6 +55,7 @@ bool cHdffSetup::SetupParse(const char *Name, const char *Value)
else if (strcmp(Name, "RemoteAddress") == 0) RemoteAddress = atoi(Value); else if (strcmp(Name, "RemoteAddress") == 0) RemoteAddress = atoi(Value);
else if (strcmp(Name, "HighLevelOsd") == 0) HighLevelOsd = atoi(Value); else if (strcmp(Name, "HighLevelOsd") == 0) HighLevelOsd = atoi(Value);
else if (strcmp(Name, "TrueColorOsd") == 0) TrueColorOsd = atoi(Value); else if (strcmp(Name, "TrueColorOsd") == 0) TrueColorOsd = atoi(Value);
else if (strcmp(Name, "TrueColorFormat") == 0) TrueColorFormat = atoi(Value);
else if (strcmp(Name, "HideMainMenu") == 0) HideMainMenu = atoi(Value); else if (strcmp(Name, "HideMainMenu") == 0) HideMainMenu = atoi(Value);
else return false; else return false;
return true; return true;
@ -180,6 +182,16 @@ const char * cHdffSetup::GetVideoConversionString(void)
} }
} }
void cHdffSetup::SetVideoFormat(HDFF::cHdffCmdIf * HdffCmdIf)
{
HdffVideoFormat_t videoFormat;
videoFormat.AutomaticEnabled = true;
videoFormat.AfdEnabled = false;
videoFormat.TvFormat = (HdffTvFormat_t) TvFormat;
videoFormat.VideoConversion = (HdffVideoConversion_t) VideoConversion;
HdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat);
}
cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf) cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf)
{ {
@ -190,6 +202,7 @@ cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf)
const int kAudioDownmixes = 5; const int kAudioDownmixes = 5;
const int kOsdSizes = 5; const int kOsdSizes = 5;
const int kRemoteProtocols = 3; const int kRemoteProtocols = 3;
const int kTrueColorFormats = 3;
static const char * ResolutionItems[kResolutions] = static const char * ResolutionItems[kResolutions] =
{ {
@ -246,6 +259,13 @@ cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf)
"RC6", "RC6",
}; };
static const char * TrueColorFormatItems[kTrueColorFormats] =
{
"ARGB8888",
"ARGB8565",
"ARGB4444",
};
mHdffCmdIf = pHdffCmdIf; mHdffCmdIf = pHdffCmdIf;
mNewHdffSetup = gHdffSetup; mNewHdffSetup = gHdffSetup;
@ -265,6 +285,7 @@ cHdffSetupPage::cHdffSetupPage(HDFF::cHdffCmdIf * pHdffCmdIf)
Add(new cMenuEditIntItem(tr("Remote Control Address"), &mNewHdffSetup.RemoteAddress, -1, 31)); Add(new cMenuEditIntItem(tr("Remote Control Address"), &mNewHdffSetup.RemoteAddress, -1, 31));
Add(new cMenuEditBoolItem(tr("High Level OSD"), &mNewHdffSetup.HighLevelOsd)); Add(new cMenuEditBoolItem(tr("High Level OSD"), &mNewHdffSetup.HighLevelOsd));
Add(new cMenuEditBoolItem(tr("Allow True Color OSD"), &mNewHdffSetup.TrueColorOsd)); Add(new cMenuEditBoolItem(tr("Allow True Color OSD"), &mNewHdffSetup.TrueColorOsd));
Add(new cMenuEditStraItem(tr("True Color format"), &mNewHdffSetup.TrueColorFormat, kTrueColorFormats, TrueColorFormatItems));
Add(new cMenuEditBoolItem(tr("Hide mainmenu entry"), &mNewHdffSetup.HideMainMenu)); Add(new cMenuEditBoolItem(tr("Hide mainmenu entry"), &mNewHdffSetup.HideMainMenu));
mVideoConversion = 0; mVideoConversion = 0;
@ -395,6 +416,7 @@ void cHdffSetupPage::Store(void)
SetupStore("RemoteAddress", mNewHdffSetup.RemoteAddress); SetupStore("RemoteAddress", mNewHdffSetup.RemoteAddress);
SetupStore("HighLevelOsd", mNewHdffSetup.HighLevelOsd); SetupStore("HighLevelOsd", mNewHdffSetup.HighLevelOsd);
SetupStore("TrueColorOsd", mNewHdffSetup.TrueColorOsd); SetupStore("TrueColorOsd", mNewHdffSetup.TrueColorOsd);
SetupStore("TrueColorFormat", mNewHdffSetup.TrueColorFormat);
SetupStore("HideMainMenu", mNewHdffSetup.HideMainMenu); SetupStore("HideMainMenu", mNewHdffSetup.HideMainMenu);
if (mHdffCmdIf) if (mHdffCmdIf)
@ -403,14 +425,9 @@ void cHdffSetupPage::Store(void)
{ {
mHdffCmdIf->CmdHdmiSetVideoMode(mNewHdffSetup.GetVideoMode()); mHdffCmdIf->CmdHdmiSetVideoMode(mNewHdffSetup.GetVideoMode());
} }
HdffVideoFormat_t videoFormat;
HdffHdmiConfig_t hdmiConfig; HdffHdmiConfig_t hdmiConfig;
videoFormat.AutomaticEnabled = true; mNewHdffSetup.SetVideoFormat(mHdffCmdIf);
videoFormat.AfdEnabled = false;
videoFormat.TvFormat = (HdffTvFormat_t) mNewHdffSetup.TvFormat;
videoFormat.VideoConversion = (HdffVideoConversion_t) mNewHdffSetup.VideoConversion;
mHdffCmdIf->CmdAvSetVideoFormat(0, &videoFormat);
mHdffCmdIf->CmdAvSetAudioDelay(mNewHdffSetup.AudioDelay); mHdffCmdIf->CmdAvSetAudioDelay(mNewHdffSetup.AudioDelay);
mHdffCmdIf->CmdAvSetAudioDownmix((HdffAudioDownmixMode_t) mNewHdffSetup.AudioDownmix); mHdffCmdIf->CmdAvSetAudioDownmix((HdffAudioDownmixMode_t) mNewHdffSetup.AudioDownmix);

View File

@ -18,6 +18,7 @@ struct cHdffSetup
HdffVideoMode_t GetVideoMode(void); HdffVideoMode_t GetVideoMode(void);
void SetNextVideoConversion(void); void SetNextVideoConversion(void);
const char * GetVideoConversionString(void); const char * GetVideoConversionString(void);
void SetVideoFormat(HDFF::cHdffCmdIf * HdffCmdIf);
int Resolution; int Resolution;
int VideoModeAdaption; int VideoModeAdaption;
@ -36,6 +37,7 @@ struct cHdffSetup
int HighLevelOsd; int HighLevelOsd;
int TrueColorOsd; int TrueColorOsd;
int TrueColorFormat;
int HideMainMenu; int HideMainMenu;
}; };

129
args.c Normal file
View File

@ -0,0 +1,129 @@
/*
* args.c: Read arguments from files
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* Original version written by Lars Hanisch <dvb@flensrocker.de>.
*
* $Id: args.c 1.1 2014/04/14 12:02:38 kls Exp $
*/
#include "args.h"
#include <unistd.h>
cArgs::cArgs(const char *Argv0)
{
argv0 = Argv0;
argc = 0;
argv = NULL;
}
cArgs::~cArgs(void)
{
if (argv != NULL)
delete [] argv;
}
bool cArgs::AddArg(const char *s)
{
if (inVdrSection)
args.Append(strdup(s));
else if (*lastArg == NULL)
return false;
else
lastArg = cString::sprintf("%s %s", *lastArg, s);
return true;
}
bool cArgs::ReadDirectory(const char *Directory)
{
if (argv != NULL)
delete [] argv;
argc = 0;
argv = NULL;
args.Clear();
lastArg = NULL;
inVdrSection = false;
cFileNameList files(Directory, false);
if (files.Size() == 0)
return false;
for (int i = 0; i < files.Size(); i++) {
const char *fileName = files.At(i);
if (startswith(fileName, ".") || !endswith(fileName, ".conf"))
continue;
cString fullFileName = AddDirectory(Directory, fileName);
struct stat fs;
if ((access(*fullFileName, F_OK) != 0) || (stat(*fullFileName, &fs) != 0) || S_ISDIR(fs.st_mode))
continue;
bool ok = true;
int line = 0;
FILE *f = fopen(*fullFileName, "r");
if (f) {
char *s;
cReadLine ReadLine;
while ((s = ReadLine.Read(f)) != NULL) {
line++;
s = stripspace(skipspace(s));
if (!isempty(s) && (s[0] != '#')) {
if (startswith(s, "[") && endswith(s, "]")) {
s[strlen(s) - 1] = 0;
s++;
if (*lastArg) {
args.Append(strdup(*lastArg));
lastArg = NULL;
}
if (strcmp(s, "vdr") == 0)
inVdrSection = true;
else {
inVdrSection = false;
lastArg = cString::sprintf("--plugin=%s", s);
}
}
else {
if ((strlen(s) > 2) && (s[0] == '-') && (s[1] != '-')) { // short option, split at first space
char *p = strchr(s, ' ');
if (p == NULL) {
ok = AddArg(s);
if (!ok)
break;
}
else {
*p = 0;
p++;
ok = AddArg(s);
if (!ok)
break;
ok = AddArg(p);
if (!ok)
break;
}
}
else {
ok = AddArg(s);
if (!ok)
break;
}
}
}
}
fclose(f);
}
if (!ok) {
esyslog("ERROR: args file %s, line %d", *fullFileName, line);
return false;
}
}
if (*lastArg) {
args.Append(strdup(*lastArg));
lastArg = NULL;
}
argv = new char*[args.Size() + 1];
argv[0] = strdup(*argv0);
argc = 1;
for (int i = 0; i < args.Size(); i++) {
argv[argc] = args.At(i);
argc++;
}
return true;
}

34
args.h Normal file
View File

@ -0,0 +1,34 @@
/*
* args.h: Read arguments from files
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* Original version written by Lars Hanisch <dvb@flensrocker.de>.
*
* $Id: args.h 1.1 2014/04/14 11:54:21 kls Exp $
*/
#ifndef __ARGS_H
#define __ARGS_H
#include "tools.h"
class cArgs {
private:
cString argv0;
cStringList args;
cString lastArg;
bool inVdrSection;
int argc;
char **argv;
bool AddArg(const char *s);
public:
cArgs(const char *Argv0);
~cArgs(void);
bool ReadDirectory(const char *Directory);
int GetArgc(void) const { return argc; };
char **GetArgv(void) const { return argv; };
};
#endif //__ARGS_H

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: channels.c 3.5 2014/03/10 13:14:02 kls Exp $ * $Id: channels.c 3.7 2015/01/14 12:15:03 kls Exp $
*/ */
#include "channels.h" #include "channels.h"
@ -221,7 +221,7 @@ bool cChannel::SetTransponderData(int Source, int Frequency, int Srate, const ch
nameSource = NULL; nameSource = NULL;
shortNameSource = NULL; shortNameSource = NULL;
if (Number() && !Quiet) { if (Number() && !Quiet) {
dsyslog("changing transponder data of channel %d from %s to %s", Number(), *OldTransponderData, *TransponderDataToString()); dsyslog("changing transponder data of channel %d (%s) from %s to %s", Number(), name, *OldTransponderData, *TransponderDataToString());
modification |= CHANNELMOD_TRANSP; modification |= CHANNELMOD_TRANSP;
Channels.SetModified(); Channels.SetModified();
} }
@ -233,7 +233,7 @@ void cChannel::SetId(int Nid, int Tid, int Sid, int Rid)
{ {
if (nid != Nid || tid != Tid || sid != Sid || rid != Rid) { if (nid != Nid || tid != Tid || sid != Sid || rid != Rid) {
if (Number()) { if (Number()) {
dsyslog("changing id of channel %d from %d-%d-%d-%d to %d-%d-%d-%d", Number(), nid, tid, sid, rid, Nid, Tid, Sid, Rid); dsyslog("changing id of channel %d (%s) from %d-%d-%d-%d to %d-%d-%d-%d", Number(), name, nid, tid, sid, rid, Nid, Tid, Sid, Rid);
modification |= CHANNELMOD_ID; modification |= CHANNELMOD_ID;
Channels.SetModified(); Channels.SetModified();
Channels.UnhashChannel(this); Channels.UnhashChannel(this);
@ -278,7 +278,7 @@ void cChannel::SetPortalName(const char *PortalName)
{ {
if (!isempty(PortalName) && strcmp(portalName, PortalName) != 0) { if (!isempty(PortalName) && strcmp(portalName, PortalName) != 0) {
if (Number()) { if (Number()) {
dsyslog("changing portal name of channel %d from '%s' to '%s'", Number(), portalName, PortalName); dsyslog("changing portal name of channel %d (%s) from '%s' to '%s'", Number(), name, portalName, PortalName);
modification |= CHANNELMOD_NAME; modification |= CHANNELMOD_NAME;
Channels.SetModified(); Channels.SetModified();
} }
@ -368,7 +368,7 @@ void cChannel::SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, c
q += IntArrayToString(q, Spids, 10, SLangs); q += IntArrayToString(q, Spids, 10, SLangs);
*q = 0; *q = 0;
if (Number()) if (Number())
dsyslog("changing pids of channel %d from %d+%d=%d:%s:%s:%d to %d+%d=%d:%s:%s:%d", Number(), vpid, ppid, vtype, OldApidsBuf, OldSpidsBuf, tpid, Vpid, Ppid, Vtype, NewApidsBuf, NewSpidsBuf, Tpid); dsyslog("changing pids of channel %d (%s) from %d+%d=%d:%s:%s:%d to %d+%d=%d:%s:%s:%d", Number(), name, vpid, ppid, vtype, OldApidsBuf, OldSpidsBuf, tpid, Vpid, Ppid, Vtype, NewApidsBuf, NewSpidsBuf, Tpid);
vpid = Vpid; vpid = Vpid;
ppid = Ppid; ppid = Ppid;
vtype = Vtype; vtype = Vtype;
@ -427,7 +427,7 @@ void cChannel::SetCaIds(const int *CaIds)
IntArrayToString(OldCaIdsBuf, caids, 16); IntArrayToString(OldCaIdsBuf, caids, 16);
IntArrayToString(NewCaIdsBuf, CaIds, 16); IntArrayToString(NewCaIdsBuf, CaIds, 16);
if (Number()) if (Number())
dsyslog("changing caids of channel %d from %s to %s", Number(), OldCaIdsBuf, NewCaIdsBuf); dsyslog("changing caids of channel %d (%s) from %s to %s", Number(), name, OldCaIdsBuf, NewCaIdsBuf);
for (int i = 0; i <= MAXCAIDS; i++) { // <= to copy the terminating 0 for (int i = 0; i <= MAXCAIDS; i++) { // <= to copy the terminating 0
caids[i] = CaIds[i]; caids[i] = CaIds[i];
if (!CaIds[i]) if (!CaIds[i])
@ -444,7 +444,7 @@ void cChannel::SetCaDescriptors(int Level)
modification |= CHANNELMOD_CA; modification |= CHANNELMOD_CA;
Channels.SetModified(); Channels.SetModified();
if (Number() && Level > 1) if (Number() && Level > 1)
dsyslog("changing ca descriptors of channel %d", Number()); dsyslog("changing ca descriptors of channel %d (%s)", Number(), name);
} }
} }
@ -470,7 +470,7 @@ void cChannel::SetLinkChannels(cLinkChannels *LinkChannels)
} }
char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->Count() : 0)) * 6 + 256]; // 6: 5 digit channel number plus blank, 256: other texts (see below) plus reserve char buffer[((linkChannels ? linkChannels->Count() : 0) + (LinkChannels ? LinkChannels->Count() : 0)) * 6 + 256]; // 6: 5 digit channel number plus blank, 256: other texts (see below) plus reserve
char *q = buffer; char *q = buffer;
q += sprintf(q, "linking channel %d from", Number()); q += sprintf(q, "linking channel %d (%s) from", Number(), name);
if (linkChannels) { if (linkChannels) {
for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) { for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
lc->Channel()->SetRefChannel(NULL); lc->Channel()->SetRefChannel(NULL);
@ -1040,8 +1040,11 @@ void cChannels::MarkObsoleteChannels(int Source, int Nid, int Tid)
{ {
for (cChannel *channel = First(); channel; channel = Next(channel)) { for (cChannel *channel = First(); channel; channel = Next(channel)) {
if (time(NULL) - channel->Seen() > CHANNELTIMEOBSOLETE && channel->Source() == Source && channel->Nid() == Nid && channel->Tid() == Tid && channel->Rid() == 0) { if (time(NULL) - channel->Seen() > CHANNELTIMEOBSOLETE && channel->Source() == Source && channel->Nid() == Nid && channel->Tid() == Tid && channel->Rid() == 0) {
bool OldShowChannelNamesWithSource = Setup.ShowChannelNamesWithSource;
Setup.ShowChannelNamesWithSource = false;
if (!endswith(channel->Name(), CHANNELMARKOBSOLETE)) if (!endswith(channel->Name(), CHANNELMARKOBSOLETE))
channel->SetName(cString::sprintf("%s %s", channel->Name(), CHANNELMARKOBSOLETE), channel->ShortName(), cString::sprintf("%s %s", CHANNELMARKOBSOLETE, channel->Provider())); channel->SetName(cString::sprintf("%s %s", channel->Name(), CHANNELMARKOBSOLETE), channel->ShortName(), cString::sprintf("%s %s", CHANNELMARKOBSOLETE, channel->Provider()));
Setup.ShowChannelNamesWithSource = OldShowChannelNamesWithSource;
} }
} }
} }

172
ci.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: ci.c 3.12 2014/02/25 09:59:55 kls Exp $ * $Id: ci.c 3.17 2015/01/15 09:14:57 kls Exp $
*/ */
#include "ci.h" #include "ci.h"
@ -20,6 +20,8 @@
#include "device.h" #include "device.h"
#include "pat.h" #include "pat.h"
#include "receiver.h" #include "receiver.h"
#include "remux.h"
#include "libsi/si.h"
#include "tools.h" #include "tools.h"
// Set these to 'true' for debug output: // Set these to 'true' for debug output:
@ -105,14 +107,135 @@ static char *GetString(int &Length, const uint8_t **Data)
// --- cCaPidReceiver -------------------------------------------------------- // --- cCaPidReceiver --------------------------------------------------------
// A dummy receiver, just used to make the device receive the CA pids. // A receiver that is used to make the device receive the ECM pids, as well as the
// CAT and the EMM pids.
class cCaPidReceiver : public cReceiver { class cCaPidReceiver : public cReceiver {
private:
int catVersion;
cVector<int> emmPids;
uchar buffer[2048]; // 11 bit length, max. 2048 byte
uchar *bufp;
int length;
void AddEmmPid(int Pid);
void DelEmmPids(void);
protected:
virtual void Activate(bool On);
public: public:
cCaPidReceiver(void);
virtual ~cCaPidReceiver() { Detach(); } virtual ~cCaPidReceiver() { Detach(); }
virtual void Receive(uchar *Data, int Length) {} virtual void Receive(uchar *Data, int Length);
bool HasCaPids(void) { return NumPids() - emmPids.Size() - 1 > 0; }
void Reset(void) { DelEmmPids(); catVersion = -1; }
}; };
cCaPidReceiver::cCaPidReceiver(void)
{
catVersion = -1;
bufp = NULL;
length = 0;
AddPid(CATPID);
}
void cCaPidReceiver::AddEmmPid(int Pid)
{
for (int i = 0; i < emmPids.Size(); i++) {
if (emmPids[i] == Pid)
return;
}
emmPids.Append(Pid);
AddPid(Pid);
}
void cCaPidReceiver::DelEmmPids(void)
{
for (int i = 0; i < emmPids.Size(); i++)
DelPid(emmPids[i]);
emmPids.Clear();
}
void cCaPidReceiver::Activate(bool On)
{
catVersion = -1; // can be done independent of 'On'
}
void cCaPidReceiver::Receive(uchar *Data, int Length)
{
if (TsPid(Data) == CATPID) {
uchar *p = NULL;
if (TsPayloadStart(Data)) {
if (Data[5] == SI::TableIdCAT) {
length = (int(Data[6] & 0x03) << 8) | Data[7]; // section length
if (length > 5) {
int v = (Data[10] & 0x3E) >> 1; // version number
if (v != catVersion) {
if (Data[11] == 0 && Data[12] == 0) { // section number, last section number
if (length > TS_SIZE - 8) {
int n = TS_SIZE - 13;
memcpy(buffer, Data + 13, n);
bufp = buffer + n;
length -= n + 5; // 5 = header
}
else {
p = Data + 13; // no need to copy the data
length -= 5; // header
}
}
else
dsyslog("multi table CAT section - unhandled!");
catVersion = v;
}
}
}
}
else if (bufp && length > 0) {
int n = min(length, TS_SIZE - 4);
if (bufp + n - buffer <= int(sizeof(buffer))) {
memcpy(bufp, Data + 4, n);
bufp += n;
length -= n;
if (length <= 0) {
p = buffer;
length = bufp - buffer;
}
}
else {
esyslog("ERROR: buffer overflow in cCaPidReceiver::Receive()");
bufp = 0;
length = 0;
}
}
if (p) {
int OldCatVersion = catVersion; // must preserve the current version number
cDevice *AttachedDevice = Device();
if (AttachedDevice)
AttachedDevice->Detach(this);
DelEmmPids();
for (int i = 0; i < length - 4; i++) { // -4 = checksum
if (p[i] == 0x09) {
int CaId = int(p[i + 2] << 8) | p[i + 3];
int EmmPid = int(((p[i + 4] & 0x1F) << 8)) | p[i + 5];
AddEmmPid(EmmPid);
switch (CaId >> 8) {
case 0x01: for (int j = i + 7; j < p[i + 1] + 2; j += 4) {
EmmPid = (int(p[j] & 0x0F) << 8) | p[j + 1];
AddEmmPid(EmmPid);
}
break;
}
i += p[i + 1] + 2 - 1; // -1 to compensate for the loop increment
}
}
if (AttachedDevice)
AttachedDevice->AttachReceiver(this);
catVersion = OldCatVersion;
p = NULL;
bufp = 0;
length = 0;
}
}
}
// --- cTPDU ----------------------------------------------------------------- // --- cTPDU -----------------------------------------------------------------
#define MAX_TPDU_SIZE 2048 #define MAX_TPDU_SIZE 2048
@ -1508,7 +1631,6 @@ public:
cCiAdapter::cCiAdapter(void) cCiAdapter::cCiAdapter(void)
:cThread("CI adapter") :cThread("CI adapter")
{ {
assignedDevice = NULL;
for (int i = 0; i < MAX_CAM_SLOTS_PER_ADAPTER; i++) for (int i = 0; i < MAX_CAM_SLOTS_PER_ADAPTER; i++)
camSlots[i] = NULL; camSlots[i] = NULL;
} }
@ -1534,6 +1656,17 @@ void cCiAdapter::AddCamSlot(cCamSlot *CamSlot)
} }
} }
cCamSlot *cCiAdapter::ItCamSlot(int &Iter)
{
if (Iter >= 0) {
for (; Iter < MAX_CAM_SLOTS_PER_ADAPTER; ) {
if (cCamSlot *Found = camSlots[Iter++])
return Found;
}
}
return NULL;
}
void cCiAdapter::Action(void) void cCiAdapter::Action(void)
{ {
cTPDU TPDU; cTPDU TPDU;
@ -1561,6 +1694,7 @@ void cCiAdapter::Action(void)
cCamSlot::cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids) cCamSlot::cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids)
{ {
ciAdapter = CiAdapter; ciAdapter = CiAdapter;
assignedDevice = NULL;
caPidReceiver = ReceiveCaPids ? new cCaPidReceiver : NULL; caPidReceiver = ReceiveCaPids ? new cCaPidReceiver : NULL;
slotIndex = -1; slotIndex = -1;
lastModuleStatus = msReset; // avoids initial reset log message lastModuleStatus = msReset; // avoids initial reset log message
@ -1578,8 +1712,8 @@ cCamSlot::cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids)
cCamSlot::~cCamSlot() cCamSlot::~cCamSlot()
{ {
if (ciAdapter && ciAdapter->assignedDevice) if (assignedDevice)
ciAdapter->assignedDevice->SetCamSlot(NULL); assignedDevice->SetCamSlot(NULL);
delete caPidReceiver; delete caPidReceiver;
CamSlots.Del(this, false); CamSlots.Del(this, false);
DeleteAllConnections(); DeleteAllConnections();
@ -1590,13 +1724,13 @@ bool cCamSlot::Assign(cDevice *Device, bool Query)
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
if (ciAdapter) { if (ciAdapter) {
if (ciAdapter->Assign(Device, true)) { if (ciAdapter->Assign(Device, true)) {
if (!Device && ciAdapter->assignedDevice) if (!Device && assignedDevice)
ciAdapter->assignedDevice->SetCamSlot(NULL); assignedDevice->SetCamSlot(NULL);
if (!Query) { if (!Query) {
StopDecrypting(); StopDecrypting();
source = transponder = 0; source = transponder = 0;
if (ciAdapter->Assign(Device)) { if (ciAdapter->Assign(Device)) {
ciAdapter->assignedDevice = Device; assignedDevice = Device;
if (Device) { if (Device) {
Device->SetCamSlot(this); Device->SetCamSlot(this);
dsyslog("CAM %d: assigned to device %d", slotNumber, Device->DeviceNumber() + 1); dsyslog("CAM %d: assigned to device %d", slotNumber, Device->DeviceNumber() + 1);
@ -1613,17 +1747,6 @@ bool cCamSlot::Assign(cDevice *Device, bool Query)
return false; return false;
} }
cDevice *cCamSlot::Device(void)
{
cMutexLock MutexLock(&mutex);
if (ciAdapter) {
cDevice *d = ciAdapter->assignedDevice;
if (d && d->CamSlot() == this)
return d;
}
return NULL;
}
void cCamSlot::NewConnection(void) void cCamSlot::NewConnection(void)
{ {
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
@ -1811,7 +1934,7 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)
const int *CaSystemIds = cas->GetCaSystemIds(); const int *CaSystemIds = cas->GetCaSystemIds();
if (CaSystemIds && *CaSystemIds) { if (CaSystemIds && *CaSystemIds) {
if (caProgramList.Count()) { if (caProgramList.Count()) {
if (caPidReceiver && caPidReceiver->NumPids()) { if (caPidReceiver && caPidReceiver->HasCaPids()) {
if (cDevice *d = Device()) if (cDevice *d = Device())
d->Detach(caPidReceiver); d->Detach(caPidReceiver);
} }
@ -1845,7 +1968,7 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)
} }
} }
} }
if (caPidReceiver && caPidReceiver->NumPids()) { if (caPidReceiver && caPidReceiver->HasCaPids()) {
if (cDevice *d = Device()) if (cDevice *d = Device())
d->AttachReceiver(caPidReceiver); d->AttachReceiver(caPidReceiver);
} }
@ -1854,6 +1977,11 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)
else { else {
cCiCaPmt CaPmt(CmdId, 0, 0, 0, NULL); cCiCaPmt CaPmt(CmdId, 0, 0, 0, NULL);
cas->SendPMT(&CaPmt); cas->SendPMT(&CaPmt);
if (caPidReceiver) {
if (cDevice *d = Device())
d->Detach(caPidReceiver);
caPidReceiver->Reset();
}
} }
} }
} }

14
ci.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: ci.h 3.7 2014/01/31 09:21:21 kls Exp $ * $Id: ci.h 3.9 2015/01/15 09:18:09 kls Exp $
*/ */
#ifndef __CI_H #ifndef __CI_H
@ -79,11 +79,14 @@ enum eModuleStatus { msNone, msReset, msPresent, msReady };
class cCiAdapter : public cThread { class cCiAdapter : public cThread {
friend class cCamSlot; friend class cCamSlot;
private: private:
cDevice *assignedDevice;
cCamSlot *camSlots[MAX_CAM_SLOTS_PER_ADAPTER]; cCamSlot *camSlots[MAX_CAM_SLOTS_PER_ADAPTER];
void AddCamSlot(cCamSlot *CamSlot); void AddCamSlot(cCamSlot *CamSlot);
///< Adds the given CamSlot to this CI adapter. ///< Adds the given CamSlot to this CI adapter.
protected: protected:
cCamSlot *ItCamSlot(int &Iter);
///< Iterates over all added CAM slots of this adapter. Iter has to be
///< initialized to 0 and is required to store the iteration state.
///< Returns NULL if no further CAM slot is found.
virtual void Action(void); virtual void Action(void);
///< Handles the attached CAM slots in a separate thread. ///< Handles the attached CAM slots in a separate thread.
///< The derived class must call the Start() function to ///< The derived class must call the Start() function to
@ -119,7 +122,7 @@ class cTPDU;
class cCiTransportConnection; class cCiTransportConnection;
class cCiSession; class cCiSession;
class cCiCaProgramData; class cCiCaProgramData;
class cReceiver; class cCaPidReceiver;
class cCamSlot : public cListObject { class cCamSlot : public cListObject {
friend class cCiAdapter; friend class cCiAdapter;
@ -128,7 +131,8 @@ private:
cMutex mutex; cMutex mutex;
cCondVar processed; cCondVar processed;
cCiAdapter *ciAdapter; cCiAdapter *ciAdapter;
cReceiver *caPidReceiver; cDevice *assignedDevice;
cCaPidReceiver *caPidReceiver;
int slotIndex; int slotIndex;
int slotNumber; int slotNumber;
cCiTransportConnection *tc[MAX_CONNECTIONS_PER_CAM_SLOT + 1]; // connection numbering starts with 1 cCiTransportConnection *tc[MAX_CONNECTIONS_PER_CAM_SLOT + 1]; // connection numbering starts with 1
@ -164,7 +168,7 @@ public:
///< device it was previously assigned to. The value of Query ///< device it was previously assigned to. The value of Query
///< is ignored in that case, and this function always returns ///< is ignored in that case, and this function always returns
///< 'true'. ///< 'true'.
cDevice *Device(void); cDevice *Device(void) { return assignedDevice; }
///< Returns the device this CAM slot is currently assigned to. ///< Returns the device this CAM slot is currently assigned to.
bool WantsTsData(void) const { return caPidReceiver != NULL; } bool WantsTsData(void) const { return caPidReceiver != NULL; }
///< Returns true if this CAM slot wants to receive the TS data through ///< Returns true if this CAM slot wants to receive the TS data through

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.c 3.2 2013/08/31 12:41:28 kls Exp $ * $Id: config.c 3.3 2015/01/12 14:32:17 kls Exp $
*/ */
#include "config.h" #include "config.h"
@ -473,6 +473,8 @@ cSetup::cSetup(void)
ResumeID = 0; ResumeID = 0;
CurrentChannel = -1; CurrentChannel = -1;
CurrentVolume = MAXVOLUME; CurrentVolume = MAXVOLUME;
VolumeSteps = 51;
VolumeLinearize = 0;
CurrentDolby = 0; CurrentDolby = 0;
InitialChannel = ""; InitialChannel = "";
DeviceBondings = ""; DeviceBondings = "";
@ -686,6 +688,8 @@ bool cSetup::Parse(const char *Name, const char *Value)
else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value); else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value);
else if (!strcasecmp(Name, "CurrentDolby")) CurrentDolby = atoi(Value); else if (!strcasecmp(Name, "CurrentDolby")) CurrentDolby = atoi(Value);
else if (!strcasecmp(Name, "InitialChannel")) InitialChannel = Value; else if (!strcasecmp(Name, "InitialChannel")) InitialChannel = Value;
else if (!strcasecmp(Name, "VolumeSteps")) VolumeSteps = atoi(Value);
else if (!strcasecmp(Name, "VolumeLinearize")) VolumeLinearize = atoi(Value);
else if (!strcasecmp(Name, "InitialVolume")) InitialVolume = atoi(Value); else if (!strcasecmp(Name, "InitialVolume")) InitialVolume = atoi(Value);
else if (!strcasecmp(Name, "DeviceBondings")) DeviceBondings = Value; else if (!strcasecmp(Name, "DeviceBondings")) DeviceBondings = Value;
else if (!strcasecmp(Name, "ChannelsWrap")) ChannelsWrap = atoi(Value); else if (!strcasecmp(Name, "ChannelsWrap")) ChannelsWrap = atoi(Value);
@ -801,6 +805,8 @@ bool cSetup::Save(void)
Store("CurrentVolume", CurrentVolume); Store("CurrentVolume", CurrentVolume);
Store("CurrentDolby", CurrentDolby); Store("CurrentDolby", CurrentDolby);
Store("InitialChannel", InitialChannel); Store("InitialChannel", InitialChannel);
Store("VolumeSteps", VolumeSteps);
Store("VolumeLinearize", VolumeLinearize);
Store("InitialVolume", InitialVolume); Store("InitialVolume", InitialVolume);
Store("DeviceBondings", DeviceBondings); Store("DeviceBondings", DeviceBondings);
Store("ChannelsWrap", ChannelsWrap); Store("ChannelsWrap", ChannelsWrap);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.h 3.8 2014/02/25 10:00:23 kls Exp $ * $Id: config.h 3.10 2015/01/12 14:32:17 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -22,13 +22,13 @@
// VDR's own version number: // VDR's own version number:
#define VDRVERSION "2.1.6" #define VDRVERSION "2.1.7"
#define VDRVERSNUM 20106 // Version * 10000 + Major * 100 + Minor #define VDRVERSNUM 20107 // Version * 10000 + Major * 100 + Minor
// The plugin API's version number: // The plugin API's version number:
#define APIVERSION "2.1.6" #define APIVERSION "2.1.7"
#define APIVERSNUM 20106 // Version * 10000 + Major * 100 + Minor #define APIVERSNUM 20107 // Version * 10000 + Major * 100 + Minor
// When loading plugins, VDR searches them by their APIVERSION, which // When loading plugins, VDR searches them by their APIVERSION, which
// may be smaller than VDRVERSION in case there have been no changes to // may be smaller than VDRVERSION in case there have been no changes to
@ -336,6 +336,8 @@ public:
int ResumeID; int ResumeID;
int CurrentChannel; int CurrentChannel;
int CurrentVolume; int CurrentVolume;
int VolumeSteps;
int VolumeLinearize;
int CurrentDolby; int CurrentDolby;
int InitialVolume; int InitialVolume;
int ChannelsWrap; int ChannelsWrap;

View File

@ -4,11 +4,12 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.c 3.15 2014/03/15 13:23:28 kls Exp $ * $Id: device.c 3.19 2015/01/14 12:02:44 kls Exp $
*/ */
#include "device.h" #include "device.h"
#include <errno.h> #include <errno.h>
#include <math.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mman.h> #include <sys/mman.h>
#include "audio.h" #include "audio.h"
@ -76,7 +77,7 @@ cDevice::cDevice(void)
cardIndex = nextCardIndex++; cardIndex = nextCardIndex++;
dsyslog("new device number %d", CardIndex() + 1); dsyslog("new device number %d", CardIndex() + 1);
SetDescription("receiver on device %d", CardIndex() + 1); SetDescription("device %d receiver", CardIndex() + 1);
mute = false; mute = false;
volume = Setup.CurrentVolume; volume = Setup.CurrentVolume;
@ -695,7 +696,7 @@ bool cDevice::MaySwitchTransponder(const cChannel *Channel) const
bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView) bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
{ {
if (LiveView) { if (LiveView) {
isyslog("switching to channel %d", Channel->Number()); isyslog("switching to channel %d (%s)", Channel->Number(), Channel->Name());
cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer cControl::Shutdown(); // prevents old channel from being shown too long if GetDevice() takes longer
} }
for (int i = 3; i--;) { for (int i = 3; i--;) {
@ -918,8 +919,10 @@ void cDevice::SetAudioChannel(int AudioChannel)
void cDevice::SetVolume(int Volume, bool Absolute) void cDevice::SetVolume(int Volume, bool Absolute)
{ {
int OldVolume = volume; int OldVolume = volume;
volume = constrain(Absolute ? Volume : volume + Volume, 0, MAXVOLUME); double VolumeDelta = double(MAXVOLUME) / Setup.VolumeSteps;
SetVolumeDevice(volume); double VolumeLinearize = (Setup.VolumeLinearize >= 0) ? (Setup.VolumeLinearize / 10.0 + 1.0) : (1.0 / ((-Setup.VolumeLinearize / 10.0) + 1.0));
volume = constrain(int(floor((Absolute ? Volume : volume + Volume) / VolumeDelta + 0.5) * VolumeDelta), 0, MAXVOLUME);
SetVolumeDevice(MAXVOLUME - int(pow(1.0 - pow(double(volume) / MAXVOLUME, VolumeLinearize), 1.0 / VolumeLinearize) * MAXVOLUME));
Absolute |= mute; Absolute |= mute;
cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute); cStatus::MsgSetVolume(Absolute ? volume : volume - OldVolume, Absolute);
if (volume > 0) { if (volume > 0) {
@ -1699,10 +1702,11 @@ void cDevice::Detach(cReceiver *Receiver)
receiversLeft = true; receiversLeft = true;
} }
if (camSlot) { if (camSlot) {
if (Receiver->priority > MINPRIORITY) // priority check to avoid an infinite loop with the CAM slot's caPidReceiver if (Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver
camSlot->StartDecrypting(); camSlot->StartDecrypting();
if (!camSlot->IsDecrypting()) if (!camSlot->IsDecrypting())
camSlot->Assign(NULL); camSlot->Assign(NULL);
}
} }
if (!receiversLeft) if (!receiversLeft)
Cancel(-1); Cancel(-1);
@ -1731,7 +1735,7 @@ void cDevice::DetachAllReceivers(void)
cTSBuffer::cTSBuffer(int File, int Size, int CardIndex) cTSBuffer::cTSBuffer(int File, int Size, int CardIndex)
{ {
SetDescription("TS buffer on device %d", CardIndex); SetDescription("device %d TS buffer", CardIndex);
f = File; f = File;
cardIndex = CardIndex; cardIndex = CardIndex;
delivered = false; delivered = false;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.h 3.9 2014/03/15 14:04:58 kls Exp $ * $Id: device.h 3.10 2015/01/12 14:39:09 kls Exp $
*/ */
#ifndef __DEVICE_H #ifndef __DEVICE_H
@ -30,7 +30,7 @@
#define MAXPIDHANDLES 64 // the maximum number of different PIDs per device #define MAXPIDHANDLES 64 // the maximum number of different PIDs per device
#define MAXRECEIVERS 16 // the maximum number of receivers per device #define MAXRECEIVERS 16 // the maximum number of receivers per device
#define MAXVOLUME 255 #define MAXVOLUME 255
#define VOLUMEDELTA 5 // used to increase/decrease the volume #define VOLUMEDELTA (MAXVOLUME / Setup.VolumeSteps) // used to increase/decrease the volume
#define MAXOCCUPIEDTIMEOUT 99 // max. time (in seconds) a device may be occupied #define MAXOCCUPIEDTIMEOUT 99 // max. time (in seconds) a device may be occupied
enum eSetChannelResult { scrOk, scrNotAvailable, scrNoTransfer, scrFailed }; enum eSetChannelResult { scrOk, scrNotAvailable, scrNoTransfer, scrFailed };

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbci.c 3.0 2007/01/04 12:49:10 kls Exp $ * $Id: dvbci.c 3.1 2015/01/14 11:13:49 kls Exp $
*/ */
#include "dvbci.h" #include "dvbci.h"
@ -17,7 +17,7 @@
cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd) cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd)
{ {
device = Device; device = Device;
SetDescription("CI adapter on device %d", device->DeviceNumber()); SetDescription("device %d CI adapter", device->DeviceNumber());
fd = Fd; fd = Fd;
ca_caps_t Caps; ca_caps_t Caps;
if (ioctl(fd, CA_GET_CAP, &Caps) == 0) { if (ioctl(fd, CA_GET_CAP, &Caps) == 0) {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 3.11 2014/03/16 10:38:31 kls Exp $ * $Id: dvbdevice.c 3.14 2015/01/14 12:09:19 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -372,7 +372,7 @@ cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int
tunerStatus = tsIdle; tunerStatus = tsIdle;
bondedTuner = NULL; bondedTuner = NULL;
bondedMaster = false; bondedMaster = false;
SetDescription("tuner on frontend %d/%d", adapter, frontend); SetDescription("frontend %d/%d tuner", adapter, frontend);
Start(); Start();
} }
@ -771,7 +771,7 @@ static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTranspon
else if (Channel->IsTerr()) else if (Channel->IsTerr())
ds = Dtp->System() == DVB_SYSTEM_1 ? SYS_DVBT : SYS_DVBT2; ds = Dtp->System() == DVB_SYSTEM_1 ? SYS_DVBT : SYS_DVBT2;
else else
esyslog("ERROR: can't determine frontend type for channel %d", Channel->Number()); esyslog("ERROR: can't determine frontend type for channel %d (%s)", Channel->Number(), Channel->Name());
return ds; return ds;
} }
@ -823,7 +823,7 @@ bool cDvbTuner::SetFrontend(void)
} }
} }
else { else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number()); esyslog("ERROR: no DiSEqC parameters found for channel %d (%s)", channel.Number(), channel.Name());
return false; return false;
} }
} }
@ -961,7 +961,7 @@ void cDvbTuner::Action(void)
lastDiseqc = NULL; lastDiseqc = NULL;
lastSource = 0; lastSource = 0;
if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these if (time(NULL) - lastTimeoutReport > 60) { // let's not get too many of these
isyslog("frontend %d/%d timed out while tuning to channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder()); isyslog("frontend %d/%d timed out while tuning to channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
lastTimeoutReport = time(NULL); lastTimeoutReport = time(NULL);
} }
continue; continue;
@ -979,7 +979,7 @@ void cDvbTuner::Action(void)
} }
else if (Status & FE_HAS_LOCK) { else if (Status & FE_HAS_LOCK) {
if (LostLock) { if (LostLock) {
isyslog("frontend %d/%d regained lock on channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder()); isyslog("frontend %d/%d regained lock on channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
LostLock = false; LostLock = false;
} }
tunerStatus = tsLocked; tunerStatus = tsLocked;
@ -988,7 +988,7 @@ void cDvbTuner::Action(void)
} }
else if (tunerStatus == tsLocked) { else if (tunerStatus == tsLocked) {
LostLock = true; LostLock = true;
isyslog("frontend %d/%d lost lock on channel %d, tp %d", adapter, frontend, channel.Number(), channel.Transponder()); isyslog("frontend %d/%d lost lock on channel %d (%s), tp %d", adapter, frontend, channel.Number(), channel.Name(), channel.Transponder());
tunerStatus = tsTuned; tunerStatus = tsTuned;
Timer.Set(lockTimeout); Timer.Set(lockTimeout);
lastTimeoutReport = 0; lastTimeoutReport = 0;
@ -1751,12 +1751,28 @@ uint32_t cDvbDeviceProbe::GetSubsystemId(int Adapter, int Frontend)
SubsystemId = strtoul(s, NULL, 0) << 16; SubsystemId = strtoul(s, NULL, 0) << 16;
fclose(f); fclose(f);
} }
else {
FileName = cString::sprintf("/sys/class/dvb/%s/device/idVendor", e->d_name);
if ((f = fopen(FileName, "r")) != NULL) {
if (char *s = ReadLine.Read(f))
SubsystemId = strtoul(s, NULL, 16) << 16;
fclose(f);
}
}
FileName = cString::sprintf("/sys/class/dvb/%s/device/subsystem_device", e->d_name); FileName = cString::sprintf("/sys/class/dvb/%s/device/subsystem_device", e->d_name);
if ((f = fopen(FileName, "r")) != NULL) { if ((f = fopen(FileName, "r")) != NULL) {
if (char *s = ReadLine.Read(f)) if (char *s = ReadLine.Read(f))
SubsystemId |= strtoul(s, NULL, 0); SubsystemId |= strtoul(s, NULL, 0);
fclose(f); fclose(f);
} }
else {
FileName = cString::sprintf("/sys/class/dvb/%s/device/idProduct", e->d_name);
if ((f = fopen(FileName, "r")) != NULL) {
if (char *s = ReadLine.Read(f))
SubsystemId |= strtoul(s, NULL, 16);
fclose(f);
}
}
break; break;
} }
} }

View File

@ -7,7 +7,7 @@
* Original author: Marco Schluessler <marco@lordzodiac.de> * Original author: Marco Schluessler <marco@lordzodiac.de>
* With some input from the "subtitles plugin" by Pekka Virtanen <pekka.virtanen@sci.fi> * With some input from the "subtitles plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
* *
* $Id: dvbsubtitle.c 3.5 2014/02/08 12:29:13 kls Exp $ * $Id: dvbsubtitle.c 3.9 2015/01/14 11:31:09 kls Exp $
*/ */
#include "dvbsubtitle.h" #include "dvbsubtitle.h"
@ -25,6 +25,12 @@
#define END_OF_DISPLAY_SET_SEGMENT 0x80 #define END_OF_DISPLAY_SET_SEGMENT 0x80
#define STUFFING_SEGMENT 0xFF #define STUFFING_SEGMENT 0xFF
#define PGS_PALETTE_SEGMENT 0x14
#define PGS_OBJECT_SEGMENT 0x15
#define PGS_PRESENTATION_SEGMENT 0x16
#define PGS_WINDOW_SEGMENT 0x17
#define PGS_DISPLAY_SEGMENT 0x80
// Set these to 'true' for debug output, which is written into the file dbg-log.htm // Set these to 'true' for debug output, which is written into the file dbg-log.htm
// in the current working directory. The HTML file shows the actual bitmaps (dbg-nnn.jpg) // in the current working directory. The HTML file shows the actual bitmaps (dbg-nnn.jpg)
// used to display the subtitles. // used to display the subtitles.
@ -53,6 +59,8 @@ static bool DebugOutput = DebugVerbose;
#define DBGMAXBITMAPS 100 // debug output will be stopped after this many bitmaps #define DBGMAXBITMAPS 100 // debug output will be stopped after this many bitmaps
#define DBGBITMAPWIDTH 400 #define DBGBITMAPWIDTH 400
#define FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY // some don't properly handle version numbers, which renders them useless because subtitles are not displayed
// --- cSubtitleDebug -------------------------------------------------------- // --- cSubtitleDebug --------------------------------------------------------
class cSubtitleDebug { class cSubtitleDebug {
@ -144,6 +152,7 @@ private:
public: public:
cSubtitleClut(int ClutId); cSubtitleClut(int ClutId);
void Parse(cBitStream &bs); void Parse(cBitStream &bs);
void ParsePgs(cBitStream &bs);
int ClutId(void) { return clutId; } int ClutId(void) { return clutId; }
int ClutVersionNumber(void) { return clutVersionNumber; } int ClutVersionNumber(void) { return clutVersionNumber; }
const cPalette *GetPalette(int Bpp); const cPalette *GetPalette(int Bpp);
@ -221,8 +230,10 @@ cSubtitleClut::cSubtitleClut(int ClutId)
void cSubtitleClut::Parse(cBitStream &bs) void cSubtitleClut::Parse(cBitStream &bs)
{ {
int Version = bs.GetBits(4); int Version = bs.GetBits(4);
#ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY
if (clutVersionNumber == Version) if (clutVersionNumber == Version)
return; // no update return; // no update
#endif
clutVersionNumber = Version; clutVersionNumber = Version;
bs.SkipBits(4); // reserved bs.SkipBits(4); // reserved
dbgcluts("<b>clut</b> id %d version %d<br>\n", clutId, clutVersionNumber); dbgcluts("<b>clut</b> id %d version %d<br>\n", clutId, clutVersionNumber);
@ -263,6 +274,31 @@ void cSubtitleClut::Parse(cBitStream &bs)
} }
} }
void cSubtitleClut::ParsePgs(cBitStream &bs)
{
int Version = bs.GetBits(8);
if (clutVersionNumber == Version)
return; // no update
clutVersionNumber = Version;
dbgcluts("<b>clut</b> id %d version %d<br>\n", clutId, clutVersionNumber);
for (int i = 0; i < 256; ++i)
SetColor(8, i, ArgbToColor(0, 0, 0, 0));
while (!bs.IsEOF()) {
uchar clutEntryId = bs.GetBits(8);
uchar yval = bs.GetBits(8);
uchar crval = bs.GetBits(8);
uchar cbval = bs.GetBits(8);
uchar tval = bs.GetBits(8);
tColor value = 0;
if (yval) {
value = yuv2rgb(yval, cbval, crval);
value |= ((10 - (clutEntryId ? Setup.SubtitleFgTransparency : Setup.SubtitleBgTransparency)) * tval / 10) << 24;
}
dbgcluts("%2d %08X<br>\n", clutEntryId, value);
SetColor(8, clutEntryId, value);
}
}
tColor cSubtitleClut::yuv2rgb(int Y, int Cb, int Cr) tColor cSubtitleClut::yuv2rgb(int Y, int Cb, int Cr)
{ {
int Ey, Epb, Epr; int Ey, Epb, Epr;
@ -310,6 +346,7 @@ private:
bool nonModifyingColorFlag; bool nonModifyingColorFlag;
int topLength; int topLength;
int botLength; int botLength;
int topIndex;
uchar *topData; uchar *topData;
uchar *botData; uchar *botData;
char *txtData; char *txtData;
@ -318,12 +355,14 @@ private:
bool Decode2BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y, const uint8_t *MapTable); bool Decode2BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y, const uint8_t *MapTable);
bool Decode4BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y, const uint8_t *MapTable); bool Decode4BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y, const uint8_t *MapTable);
bool Decode8BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y); bool Decode8BppCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y);
bool DecodePgsCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int&x, int y);
void DecodeSubBlock(cBitmap *Bitmap, int px, int py, const uchar *Data, int Length, bool Even); void DecodeSubBlock(cBitmap *Bitmap, int px, int py, const uchar *Data, int Length, bool Even);
void DecodeCharacterString(const uchar *Data, int NumberOfCodes); void DecodeCharacterString(const uchar *Data, int NumberOfCodes);
public: public:
cSubtitleObject(int ObjectId); cSubtitleObject(int ObjectId);
~cSubtitleObject(); ~cSubtitleObject();
void Parse(cBitStream &bs); void Parse(cBitStream &bs);
void ParsePgs(cBitStream &bs);
int ObjectId(void) { return objectId; } int ObjectId(void) { return objectId; }
int ObjectVersionNumber(void) { return objectVersionNumber; } int ObjectVersionNumber(void) { return objectVersionNumber; }
int ObjectCodingMethod(void) { return objectCodingMethod; } int ObjectCodingMethod(void) { return objectCodingMethod; }
@ -339,6 +378,7 @@ cSubtitleObject::cSubtitleObject(int ObjectId)
nonModifyingColorFlag = false; nonModifyingColorFlag = false;
topLength = 0; topLength = 0;
botLength = 0; botLength = 0;
topIndex = 0;
topData = NULL; topData = NULL;
botData = NULL; botData = NULL;
txtData = NULL; txtData = NULL;
@ -355,8 +395,10 @@ cSubtitleObject::~cSubtitleObject()
void cSubtitleObject::Parse(cBitStream &bs) void cSubtitleObject::Parse(cBitStream &bs)
{ {
int Version = bs.GetBits(4); int Version = bs.GetBits(4);
#ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY
if (objectVersionNumber == Version) if (objectVersionNumber == Version)
return; // no update return; // no update
#endif
objectVersionNumber = Version; objectVersionNumber = Version;
objectCodingMethod = bs.GetBits(2); objectCodingMethod = bs.GetBits(2);
nonModifyingColorFlag = bs.GetBit(); nonModifyingColorFlag = bs.GetBit();
@ -398,6 +440,29 @@ void cSubtitleObject::Parse(cBitStream &bs)
} }
} }
void cSubtitleObject::ParsePgs(cBitStream &bs)
{
int Version = bs.GetBits(8);
if (objectVersionNumber == Version)
return; // no update
objectVersionNumber = Version;
objectCodingMethod = 0;
int sequenceDescriptor = bs.GetBits(8);
if (!(sequenceDescriptor & 0x80) && topData != NULL) {
memcpy(topData + topIndex, bs.GetData(), (bs.Length() - bs.Index()) / 8);
topIndex += (bs.Length() - bs.Index()) / 8;
return;
}
topLength = bs.GetBits(24) - 4 + 1; // exclude width / height, add sub block type
bs.SkipBits(32);
if ((topData = MALLOC(uchar, topLength)) != NULL) {
topData[topIndex++] = 0xFF; // PGS end of line
memcpy(topData + 1, bs.GetData(), (bs.Length() - bs.Index()) / 8);
topIndex += (bs.Length() - bs.Index()) / 8 + 1;
}
dbgobjects("<b>object</b> id %d version %d method %d modify %d", objectId, objectVersionNumber, objectCodingMethod, nonModifyingColorFlag);
}
void cSubtitleObject::DecodeCharacterString(const uchar *Data, int NumberOfCodes) void cSubtitleObject::DecodeCharacterString(const uchar *Data, int NumberOfCodes)
{ {
// "ETSI EN 300 743 V1.3.1 (2006-11)", chapter 7.2.5 "Object data segment" specifies // "ETSI EN 300 743 V1.3.1 (2006-11)", chapter 7.2.5 "Object data segment" specifies
@ -484,6 +549,13 @@ void cSubtitleObject::DecodeSubBlock(cBitmap *Bitmap, int px, int py, const ucha
x = 0; x = 0;
y += 2; y += 2;
break; break;
case 0xFF:
dbgpixel("PGS code string, including EOLs<br>\n");
while (DecodePgsCodeString(Bitmap, px, py, &bs, x, y) && !bs.IsEOF()) {
x = 0;
y++;
}
break;
default: dbgpixel("unknown sub block %s %d<br>\n", __FUNCTION__, __LINE__); default: dbgpixel("unknown sub block %s %d<br>\n", __FUNCTION__, __LINE__);
} }
} }
@ -607,6 +679,28 @@ bool cSubtitleObject::Decode8BppCodeString(cBitmap *Bitmap, int px, int py, cBit
return true; return true;
} }
bool cSubtitleObject::DecodePgsCodeString(cBitmap *Bitmap, int px, int py, cBitStream *bs, int &x, int y)
{
while (!bs->IsEOF()) {
int color = bs->GetBits(8);
int rl = 1;
if (!color) {
int flags = bs->GetBits(8);
rl = flags & 0x3f;
if (flags & 0x40)
rl = (rl << 8) + bs->GetBits(8);
color = flags & 0x80 ? bs->GetBits(8) : 0;
}
if (rl > 0) {
DrawLine(Bitmap, px + x, py + y, color, rl);
x += rl;
}
else if (!rl)
return true;
}
return false;
}
void cSubtitleObject::Render(cBitmap *Bitmap, int px, int py, tIndex IndexFg, tIndex IndexBg) void cSubtitleObject::Render(cBitmap *Bitmap, int px, int py, tIndex IndexFg, tIndex IndexBg)
{ {
if (objectCodingMethod == 0) { // coding of pixels if (objectCodingMethod == 0) { // coding of pixels
@ -654,7 +748,7 @@ cSubtitleObject *cSubtitleObjects::GetObjectById(int ObjectId, bool New)
// --- cSubtitleObjectRef ---------------------------------------------------- // --- cSubtitleObjectRef ----------------------------------------------------
class cSubtitleObjectRef : public cListObject { class cSubtitleObjectRef : public cListObject {
private: protected:
int objectId; int objectId;
int objectType; int objectType;
int objectProviderFlag; int objectProviderFlag;
@ -663,6 +757,7 @@ private:
int foregroundPixelCode; int foregroundPixelCode;
int backgroundPixelCode; int backgroundPixelCode;
public: public:
cSubtitleObjectRef(void);
cSubtitleObjectRef(cBitStream &bs); cSubtitleObjectRef(cBitStream &bs);
int ObjectId(void) { return objectId; } int ObjectId(void) { return objectId; }
int ObjectType(void) { return objectType; } int ObjectType(void) { return objectType; }
@ -673,6 +768,17 @@ public:
int BackgroundPixelCode(void) { return backgroundPixelCode; } int BackgroundPixelCode(void) { return backgroundPixelCode; }
}; };
cSubtitleObjectRef::cSubtitleObjectRef(void)
{
objectId = 0;
objectType = 0;
objectProviderFlag = 0;
objectHorizontalPosition = 0;
objectVerticalPosition = 0;
foregroundPixelCode = 0;
backgroundPixelCode = 0;
}
cSubtitleObjectRef::cSubtitleObjectRef(cBitStream &bs) cSubtitleObjectRef::cSubtitleObjectRef(cBitStream &bs)
{ {
objectId = bs.GetBits(16); objectId = bs.GetBits(16);
@ -692,6 +798,38 @@ cSubtitleObjectRef::cSubtitleObjectRef(cBitStream &bs)
dbgregions("<b>objectref</b> id %d type %d flag %d x %d y %d fg %d bg %d<br>\n", objectId, objectType, objectProviderFlag, objectHorizontalPosition, objectVerticalPosition, foregroundPixelCode, backgroundPixelCode); dbgregions("<b>objectref</b> id %d type %d flag %d x %d y %d fg %d bg %d<br>\n", objectId, objectType, objectProviderFlag, objectHorizontalPosition, objectVerticalPosition, foregroundPixelCode, backgroundPixelCode);
} }
// --- cSubtitleObjectRefPgs - PGS variant of cSubtitleObjectRef -------------
class cSubtitleObjectRefPgs : public cSubtitleObjectRef {
private:
int windowId;
int compositionFlag;
int cropX;
int cropY;
int cropW;
int cropH;
public:
cSubtitleObjectRefPgs(cBitStream &bs);
};
cSubtitleObjectRefPgs::cSubtitleObjectRefPgs(cBitStream &bs)
:cSubtitleObjectRef()
{
objectId = bs.GetBits(16);
windowId = bs.GetBits(8);
compositionFlag = bs.GetBits(8);
bs.SkipBits(32); // skip absolute position, object is aligned to region
if ((compositionFlag & 0x80) != 0) {
cropX = bs.GetBits(16);
cropY = bs.GetBits(16);
cropW = bs.GetBits(16);
cropH = bs.GetBits(16);
}
else
cropX = cropY = cropW = cropH = 0;
dbgregions("<b>objectrefPgs</b> id %d flag %d x %d y %d cropX %d cropY %d cropW %d cropH %d<br>\n", objectId, compositionFlag, objectHorizontalPosition, objectVerticalPosition, cropX, cropY, cropW, cropH);
}
// --- cSubtitleRegion ------------------------------------------------------- // --- cSubtitleRegion -------------------------------------------------------
class cSubtitleRegion : public cListObject { class cSubtitleRegion : public cListObject {
@ -711,6 +849,8 @@ private:
public: public:
cSubtitleRegion(int RegionId); cSubtitleRegion(int RegionId);
void Parse(cBitStream &bs); void Parse(cBitStream &bs);
void ParsePgs(cBitStream &bs);
void SetDimensions(int Width, int Height);
int RegionId(void) { return regionId; } int RegionId(void) { return regionId; }
int RegionVersionNumber(void) { return regionVersionNumber; } int RegionVersionNumber(void) { return regionVersionNumber; }
bool RegionFillFlag(void) { return regionFillFlag; } bool RegionFillFlag(void) { return regionFillFlag; }
@ -740,8 +880,10 @@ cSubtitleRegion::cSubtitleRegion(int RegionId)
void cSubtitleRegion::Parse(cBitStream &bs) void cSubtitleRegion::Parse(cBitStream &bs)
{ {
int Version = bs.GetBits(4); int Version = bs.GetBits(4);
#ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY
if (regionVersionNumber == Version) if (regionVersionNumber == Version)
return; // no update return; // no update
#endif
regionVersionNumber = Version; regionVersionNumber = Version;
regionFillFlag = bs.GetBit(); regionFillFlag = bs.GetBit();
bs.SkipBits(3); // reserved bs.SkipBits(3); // reserved
@ -761,6 +903,24 @@ void cSubtitleRegion::Parse(cBitStream &bs)
objectRefs.Add(new cSubtitleObjectRef(bs)); objectRefs.Add(new cSubtitleObjectRef(bs));
} }
void cSubtitleRegion::ParsePgs(cBitStream &bs)
{
regionDepth = 8;
bs.SkipBits(8); // skip palette update flag
clutId = bs.GetBits(8);
dbgregions("<b>region</b> id %d version %d clutId %d<br>\n", regionId, regionVersionNumber, clutId);
int objects = bs.GetBits(8);
while (objects--)
objectRefs.Add(new cSubtitleObjectRefPgs(bs));
}
void cSubtitleRegion::SetDimensions(int Width, int Height)
{
regionWidth = Width;
regionHeight = Height;
dbgregions("<b>region</b> id %d width %d height %d<br>\n", regionId, regionWidth, regionHeight);
}
void cSubtitleRegion::Render(cBitmap *Bitmap, cSubtitleObjects *Objects) void cSubtitleRegion::Render(cBitmap *Bitmap, cSubtitleObjects *Objects)
{ {
if (regionFillFlag) { if (regionFillFlag) {
@ -786,12 +946,20 @@ private:
int regionHorizontalAddress; int regionHorizontalAddress;
int regionVerticalAddress; int regionVerticalAddress;
public: public:
cSubtitleRegionRef(int id, int x, int y);
cSubtitleRegionRef(cBitStream &bs); cSubtitleRegionRef(cBitStream &bs);
int RegionId(void) { return regionId; } int RegionId(void) { return regionId; }
int RegionHorizontalAddress(void) { return regionHorizontalAddress; } int RegionHorizontalAddress(void) { return regionHorizontalAddress; }
int RegionVerticalAddress(void) { return regionVerticalAddress; } int RegionVerticalAddress(void) { return regionVerticalAddress; }
}; };
cSubtitleRegionRef::cSubtitleRegionRef(int id, int x, int y)
{
regionId = id;
regionHorizontalAddress = x;
regionVerticalAddress = y;
dbgpages("<b>regionref</b> id %d tx %d y %d<br>\n", regionId, regionHorizontalAddress, regionVerticalAddress);
}
cSubtitleRegionRef::cSubtitleRegionRef(cBitStream &bs) cSubtitleRegionRef::cSubtitleRegionRef(cBitStream &bs)
{ {
regionId = bs.GetBits(8); regionId = bs.GetBits(8);
@ -818,6 +986,7 @@ private:
public: public:
cDvbSubtitlePage(int PageId); cDvbSubtitlePage(int PageId);
void Parse(int64_t Pts, cBitStream &bs); void Parse(int64_t Pts, cBitStream &bs);
void ParsePgs(int64_t Pts, cBitStream &bs);
int PageId(void) { return pageId; } int PageId(void) { return pageId; }
int PageTimeout(void) { return pageTimeout; } int PageTimeout(void) { return pageTimeout; }
int PageVersionNumber(void) { return pageVersionNumber; } int PageVersionNumber(void) { return pageVersionNumber; }
@ -830,6 +999,7 @@ public:
cSubtitleClut *GetClutById(int ClutId, bool New = false); cSubtitleClut *GetClutById(int ClutId, bool New = false);
cSubtitleRegion *GetRegionById(int RegionId, bool New = false); cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
cSubtitleRegionRef *GetRegionRefByIndex(int RegionRefIndex) { return regionRefs.Get(RegionRefIndex); } cSubtitleRegionRef *GetRegionRefByIndex(int RegionRefIndex) { return regionRefs.Get(RegionRefIndex); }
void AddRegionRef(cSubtitleRegionRef *rf) { regionRefs.Add(rf); }
void SetPending(bool Pending) { pending = Pending; } void SetPending(bool Pending) { pending = Pending; }
}; };
@ -849,8 +1019,10 @@ void cDvbSubtitlePage::Parse(int64_t Pts, cBitStream &bs)
pts = Pts; pts = Pts;
pageTimeout = bs.GetBits(8); pageTimeout = bs.GetBits(8);
int Version = bs.GetBits(4); int Version = bs.GetBits(4);
#ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY
if (pageVersionNumber == Version) if (pageVersionNumber == Version)
return; // no update return; // no update
#endif
pageVersionNumber = Version; pageVersionNumber = Version;
pageState = bs.GetBits(2); pageState = bs.GetBits(2);
switch (pageState) { switch (pageState) {
@ -877,6 +1049,35 @@ void cDvbSubtitlePage::Parse(int64_t Pts, cBitStream &bs)
pending = true; pending = true;
} }
void cDvbSubtitlePage::ParsePgs(int64_t Pts, cBitStream &bs)
{
if (Pts >= 0)
pts = Pts;
pageTimeout = 60000;
int Version = bs.GetBits(16);
if (pageVersionNumber == Version)
return;
pageVersionNumber = Version;
pageState = bs.GetBits(2);
switch (pageState) {
case 0: // normal case - page update
regions.Clear();
break;
case 1: // acquisition point - page refresh
case 2: // epoch start - new page
case 3: // epoch continue - new page
regions.Clear();
cluts.Clear();
objects.Clear();
break;
default: dbgpages("unknown page state: %d<br>\n", pageState);
}
bs.SkipBits(6);
dbgpages("<hr>\n<b>page</b> id %d version %d pts %"PRId64" timeout %d state %d<br>\n", pageId, pageVersionNumber, pts, pageTimeout, pageState);
regionRefs.Clear();
pending = true;
}
tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY) tArea *cDvbSubtitlePage::GetAreas(int &NumAreas, double FactorX, double FactorY)
{ {
if (regions.Count() > 0) { if (regions.Count() > 0) {
@ -1077,11 +1278,7 @@ void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
if (State() == 0 || Osd->SetAreas(areas, numAreas) == oeOk) { if (State() == 0 || Osd->SetAreas(areas, numAreas) == oeOk) {
for (int i = 0; i < bitmaps.Size(); i++) { for (int i = 0; i < bitmaps.Size(); i++) {
cBitmap *b = bitmaps[i]; cBitmap *b = bitmaps[i];
if (Scale) Osd->DrawScaledBitmap(int(round(b->X0() * osdFactorX)), int(round(b->Y0() * osdFactorY)), *b, osdFactorX, osdFactorY, AntiAlias);
b = b->Scaled(osdFactorX, osdFactorY, AntiAlias);
Osd->DrawBitmap(int(round(b->X0() * osdFactorX)), int(round(b->Y0() * osdFactorY)), *b);
if (b != bitmaps[i])
delete b;
} }
Osd->Flush(); Osd->Flush();
} }
@ -1123,7 +1320,7 @@ void cDvbSubtitleBitmaps::DbgDump(int WindowWidth, int WindowHeight)
int cDvbSubtitleConverter::setupLevel = 0; int cDvbSubtitleConverter::setupLevel = 0;
cDvbSubtitleConverter::cDvbSubtitleConverter(void) cDvbSubtitleConverter::cDvbSubtitleConverter(void)
:cThread("subtitleConverter") :cThread("subtitle converter")
{ {
dvbSubtitleAssembler = new cDvbSubtitleAssembler; dvbSubtitleAssembler = new cDvbSubtitleAssembler;
osd = NULL; osd = NULL;
@ -1226,22 +1423,24 @@ int cDvbSubtitleConverter::Convert(const uchar *Data, int Length)
dbgconverter("converter PTS: %"PRId64"<br>\n", pts); dbgconverter("converter PTS: %"PRId64"<br>\n", pts);
const uchar *data = Data + PayloadOffset; const uchar *data = Data + PayloadOffset;
int length = Length - PayloadOffset; int length = Length - PayloadOffset;
if (length > 3) { if (length > 0) {
if (data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) { if (length > 2 && data[0] == 0x20 && data[1] == 0x00 && data[2] == 0x0F) {
data += 2; data += 2;
length -= 2; length -= 2;
} }
const uchar *b = data; const uchar *b = data;
while (length > 0) { while (length > 0) {
if (b[0] == 0x0F) { if (b[0] == STUFFING_SEGMENT)
int n = ExtractSegment(b, length, pts);
if (n < 0)
break;
b += n;
length -= n;
}
else
break; break;
int n;
if (b[0] == 0x0F)
n = ExtractSegment(b, length, pts);
else
n = ExtractPgsSegment(b, length, pts);
if (n < 0)
break;
b += n;
length -= n;
} }
} }
} }
@ -1391,23 +1590,25 @@ int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t
case DISPLAY_DEFINITION_SEGMENT: { case DISPLAY_DEFINITION_SEGMENT: {
dbgsegments("DISPLAY_DEFINITION_SEGMENT<br>\n"); dbgsegments("DISPLAY_DEFINITION_SEGMENT<br>\n");
int version = bs.GetBits(4); int version = bs.GetBits(4);
if (version != ddsVersionNumber) { #ifndef FIX_SUBTITLE_VERSION_BROADCASTER_STUPIDITY
bool displayWindowFlag = bs.GetBit(); if (version == ddsVersionNumber)
windowHorizontalOffset = 0; break; // no update
windowVerticalOffset = 0; #endif
bs.SkipBits(3); // reserved bool displayWindowFlag = bs.GetBit();
displayWidth = windowWidth = bs.GetBits(16) + 1; windowHorizontalOffset = 0;
displayHeight = windowHeight = bs.GetBits(16) + 1; windowVerticalOffset = 0;
if (displayWindowFlag) { bs.SkipBits(3); // reserved
windowHorizontalOffset = bs.GetBits(16); // displayWindowHorizontalPositionMinimum displayWidth = windowWidth = bs.GetBits(16) + 1;
windowWidth = bs.GetBits(16) - windowHorizontalOffset + 1; // displayWindowHorizontalPositionMaximum displayHeight = windowHeight = bs.GetBits(16) + 1;
windowVerticalOffset = bs.GetBits(16); // displayWindowVerticalPositionMinimum if (displayWindowFlag) {
windowHeight = bs.GetBits(16) - windowVerticalOffset + 1; // displayWindowVerticalPositionMaximum windowHorizontalOffset = bs.GetBits(16); // displayWindowHorizontalPositionMinimum
} windowWidth = bs.GetBits(16) - windowHorizontalOffset + 1; // displayWindowHorizontalPositionMaximum
SetOsdData(); windowVerticalOffset = bs.GetBits(16); // displayWindowVerticalPositionMinimum
ddsVersionNumber = version; windowHeight = bs.GetBits(16) - windowVerticalOffset + 1; // displayWindowVerticalPositionMaximum
dbgdisplay("<b>display</b> version %d flag %d width %d height %d ofshor %d ofsver %d<br>\n", ddsVersionNumber, displayWindowFlag, windowWidth, windowHeight, windowHorizontalOffset, windowVerticalOffset);
} }
SetOsdData();
ddsVersionNumber = version;
dbgdisplay("<b>display</b> version %d flag %d width %d height %d ofshor %d ofsver %d<br>\n", ddsVersionNumber, displayWindowFlag, windowWidth, windowHeight, windowHorizontalOffset, windowVerticalOffset);
break; break;
} }
case DISPARITY_SIGNALING_SEGMENT: { case DISPARITY_SIGNALING_SEGMENT: {
@ -1465,6 +1666,71 @@ int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t
return -1; return -1;
} }
int cDvbSubtitleConverter::ExtractPgsSegment(const uchar *Data, int Length, int64_t Pts)
{
cBitStream bs(Data, Length * 8);
if (Length >= 3) {
int segmentType = bs.GetBits(8);
int segmentLength = bs.GetBits(16);
if (!bs.SetLength(bs.Index() + segmentLength * 8))
return -1;
LOCK_THREAD;
cDvbSubtitlePage *page = GetPageById(0, true);
switch (segmentType) {
case PGS_PRESENTATION_SEGMENT: {
if (page->Pending()) {
dbgsegments("PGS_DISPLAY_SEGMENT (simulated)<br>\n");
FinishPage(page);
}
dbgsegments("PGS_PRESENTATION_SEGMENT<br>\n");
displayWidth = windowWidth = bs.GetBits(16);
displayHeight = windowHeight = bs.GetBits(16);
bs.SkipBits(8);
page->ParsePgs(Pts, bs);
SD.SetFactor(double(DBGBITMAPWIDTH) / windowWidth);
cSubtitleRegion *region = page->GetRegionById(0, true);
region->ParsePgs(bs);
break;
}
case PGS_WINDOW_SEGMENT: {
bs.SkipBits(16);
int regionHorizontalAddress = bs.GetBits(16);
int regionVerticalAddress = bs.GetBits(16);
int regionWidth = bs.GetBits(16);
int regionHeight = bs.GetBits(16);
cSubtitleRegion *region = page->GetRegionById(0, true);
region->SetDimensions(regionWidth, regionHeight);
page->AddRegionRef(new cSubtitleRegionRef(0, regionHorizontalAddress, regionVerticalAddress));
dbgsegments("PGS_WINDOW_SEGMENT<br>\n");
break;
}
case PGS_PALETTE_SEGMENT: {
dbgsegments("PGS_PALETTE_SEGMENT<br>\n");
cSubtitleClut *clut = page->GetClutById(bs.GetBits(8), true);
clut->ParsePgs(bs);
break;
}
case PGS_OBJECT_SEGMENT: {
dbgsegments("PGS_OBJECT_SEGMENT<br>\n");
cSubtitleObject *object = page->GetObjectById(bs.GetBits(16), true);
object->ParsePgs(bs);
break;
}
case PGS_DISPLAY_SEGMENT: {
dbgsegments("PGS_DISPLAY_SEGMENT<br>\n");
FinishPage(page);
page->SetPending(false);
break;
}
default:
dbgsegments("*** unknown segment type: %02X<br>\n", segmentType);
return -1;
}
return bs.Length() / 8;
}
return -1;
}
void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page) void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
{ {
if (!AssertOsd()) if (!AssertOsd())

View File

@ -6,7 +6,7 @@
* *
* Original author: Marco Schluessler <marco@lordzodiac.de> * Original author: Marco Schluessler <marco@lordzodiac.de>
* *
* $Id: dvbsubtitle.h 3.1 2013/09/06 10:53:30 kls Exp $ * $Id: dvbsubtitle.h 3.2 2015/01/14 10:01:48 kls Exp $
*/ */
#ifndef __DVBSUBTITLE_H #ifndef __DVBSUBTITLE_H
@ -43,6 +43,7 @@ private:
void SetOsdData(void); void SetOsdData(void);
bool AssertOsd(void); bool AssertOsd(void);
int ExtractSegment(const uchar *Data, int Length, int64_t Pts); int ExtractSegment(const uchar *Data, int Length, int64_t Pts);
int ExtractPgsSegment(const uchar *Data, int Length, int64_t Pts);
void FinishPage(cDvbSubtitlePage *Page); void FinishPage(cDvbSubtitlePage *Page);
public: public:
cDvbSubtitleConverter(void); cDvbSubtitleConverter(void);

View File

@ -4,12 +4,15 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: interface.c 3.0 2012/11/19 12:21:43 kls Exp $ * $Id: interface.c 3.1 2015/01/11 13:37:47 kls Exp $
*/ */
#include "interface.h" #include "interface.h"
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef SDNOTIFY
#include <systemd/sd-daemon.h>
#endif
#include <unistd.h> #include <unistd.h>
#include "i18n.h" #include "i18n.h"
#include "status.h" #include "status.h"
@ -159,6 +162,9 @@ void cInterface::LearnKeys(void)
bool known = Keys.KnowsRemote(Remote->Name()); bool known = Keys.KnowsRemote(Remote->Name());
dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys"); dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
if (!known) { if (!known) {
#ifdef SDNOTIFY
sd_notify(0, "READY=1\nSTATUS=Learning keys...");
#endif
cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu(); cSkinDisplayMenu *DisplayMenu = Skins.Current()->DisplayMenu();
DisplayMenu->SetMenuCategory(mcUnknown); DisplayMenu->SetMenuCategory(mcUnknown);
char Headline[256]; char Headline[256];

24
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 3.23 2014/03/16 10:38:31 kls Exp $ * $Id: menu.c 3.28 2015/01/15 11:14:21 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -387,6 +387,9 @@ void cMenuChannels::Setup(void)
currentItem = item; currentItem = item;
} }
} }
SetMenuSortMode(cMenuChannelItem::SortMode() == cMenuChannelItem::csmName ? msmName :
cMenuChannelItem::SortMode() == cMenuChannelItem::csmProvider ? msmProvider :
msmNumber);
if (cMenuChannelItem::SortMode() != cMenuChannelItem::csmNumber) if (cMenuChannelItem::SortMode() != cMenuChannelItem::csmNumber)
Sort(); Sort();
SetCurrent(currentItem); SetCurrent(currentItem);
@ -2670,6 +2673,7 @@ void cMenuRecordings::Set(bool Refresh)
LastDir->IncrementCounter(recording->IsNew()); LastDir->IncrementCounter(recording->IsNew());
} }
} }
SetMenuSortMode(RecordingsSortMode == rsmName ? msmName : msmTime);
if (Refresh) if (Refresh)
Display(); Display();
} }
@ -3597,6 +3601,8 @@ cMenuSetupMisc::cMenuSetupMisc(void)
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Remote control repeat delta (ms)"), &data.RcRepeatDelta, 0)); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Remote control repeat delta (ms)"), &data.RcRepeatDelta, 0));
Add(new cMenuEditChanItem(tr("Setup.Miscellaneous$Initial channel"), &data.InitialChannel, tr("Setup.Miscellaneous$as before"))); Add(new cMenuEditChanItem(tr("Setup.Miscellaneous$Initial channel"), &data.InitialChannel, tr("Setup.Miscellaneous$as before")));
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Initial volume"), &data.InitialVolume, -1, 255, tr("Setup.Miscellaneous$as before"))); Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Initial volume"), &data.InitialVolume, -1, 255, tr("Setup.Miscellaneous$as before")));
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Volume steps"), &data.VolumeSteps, 5, 255));
Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Volume linearize"), &data.VolumeLinearize, -20, 20));
Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Channels wrap"), &data.ChannelsWrap)); Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Channels wrap"), &data.ChannelsWrap));
Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Show channel names with source"), &data.ShowChannelNamesWithSource)); Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Show channel names with source"), &data.ShowChannelNamesWithSource));
Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Emergency exit"), &data.EmergencyExit)); Add(new cMenuEditBoolItem(tr("Setup.Miscellaneous$Emergency exit"), &data.EmergencyExit));
@ -4027,6 +4033,7 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
displayChannel = Skins.Current()->DisplayChannel(withInfo); displayChannel = Skins.Current()->DisplayChannel(withInfo);
number = 0; number = 0;
timeout = Switched || Setup.TimeoutRequChInfo; timeout = Switched || Setup.TimeoutRequChInfo;
cOsdProvider::OsdSizeChanged(osdState); // just to get the current state
positioner = NULL; positioner = NULL;
channel = Channels.GetByNumber(Number); channel = Channels.GetByNumber(Number);
lastPresent = lastFollowing = NULL; lastPresent = lastFollowing = NULL;
@ -4112,6 +4119,10 @@ cChannel *cDisplayChannel::NextAvailableChannel(cChannel *Channel, int Direction
eOSState cDisplayChannel::ProcessKey(eKeys Key) eOSState cDisplayChannel::ProcessKey(eKeys Key)
{ {
if (cOsdProvider::OsdSizeChanged(osdState)) {
delete displayChannel;
displayChannel = Skins.Current()->DisplayChannel(withInfo);
}
cChannel *NewChannel = NULL; cChannel *NewChannel = NULL;
if (Key != kNone) if (Key != kNone)
lastTime.Set(); lastTime.Set();
@ -4754,7 +4765,7 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause)
int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority; int Priority = Timer ? Timer->Priority() : Pause ? Setup.PausePriority : Setup.DefaultPriority;
cDevice *device = cDevice::GetDevice(channel, Priority, false); cDevice *device = cDevice::GetDevice(channel, Priority, false);
if (device) { if (device) {
dsyslog("switching device %d to channel %d", device->DeviceNumber() + 1, channel->Number()); dsyslog("switching device %d to channel %d (%s)", device->DeviceNumber() + 1, channel->Number(), channel->Name());
if (!device->SwitchChannel(channel, false)) { if (!device->SwitchChannel(channel, false)) {
ShutdownHandler.RequestEmergencyExit(); ShutdownHandler.RequestEmergencyExit();
return false; return false;
@ -4769,7 +4780,7 @@ bool cRecordControls::Start(cTimer *Timer, bool Pause)
} }
} }
else if (!Timer || !Timer->Pending()) { else if (!Timer || !Timer->Pending()) {
isyslog("no free DVB device to record channel %d!", ch); isyslog("no free DVB device to record channel %d (%s)!", ch, channel->Name());
Skins.Message(mtError, tr("No free DVB device to record!")); Skins.Message(mtError, tr("No free DVB device to record!"));
} }
} }
@ -4864,7 +4875,7 @@ void cRecordControls::ChannelDataModified(cChannel *Channel)
if (RecordControls[i]) { if (RecordControls[i]) {
if (RecordControls[i]->Timer() && RecordControls[i]->Timer()->Channel() == Channel) { if (RecordControls[i]->Timer() && RecordControls[i]->Timer()->Channel() == Channel) {
if (RecordControls[i]->Device()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder if (RecordControls[i]->Device()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
isyslog("stopping recording due to modification of channel %d", Channel->Number()); isyslog("stopping recording due to modification of channel %d (%s)", Channel->Number(), Channel->Name());
RecordControls[i]->Stop(); RecordControls[i]->Stop();
// This will restart the recording, maybe even from a different // This will restart the recording, maybe even from a different
// device in case conditional access has changed. // device in case conditional access has changed.
@ -5145,7 +5156,10 @@ void cReplayControl::TimeSearchProcess(eKeys Key)
case kOk: case kOk:
if (timeSearchPos > 0) { if (timeSearchPos > 0) {
Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds); Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds);
Goto(SecondsToFrames(Seconds, FramesPerSecond()), Key == kDown || Key == kPause || Key == kOk); bool Still = Key == kDown || Key == kPause || Key == kOk;
Goto(SecondsToFrames(Seconds, FramesPerSecond()), Still);
if (!Still)
Play();
} }
timeSearchActive = false; timeSearchActive = false;
break; break;

3
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.h 3.5 2013/12/25 12:06:03 kls Exp $ * $Id: menu.h 3.6 2015/01/15 11:12:57 kls Exp $
*/ */
#ifndef __MENU_H #ifndef __MENU_H
@ -121,6 +121,7 @@ private:
cTimeMs lastTime; cTimeMs lastTime;
int number; int number;
bool timeout; bool timeout;
int osdState;
const cPositioner *positioner; const cPositioner *positioner;
cChannel *channel; cChannel *channel;
const cEvent *lastPresent; const cEvent *lastPresent;

23
osd.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.c 3.2 2013/09/03 11:59:17 kls Exp $ * $Id: osd.c 3.4 2015/01/15 11:20:56 kls Exp $
*/ */
#include "osd.h" #include "osd.h"
@ -1917,6 +1917,16 @@ void cOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColo
} }
} }
void cOsd::DrawScaledBitmap(int x, int y, const cBitmap &Bitmap, double FactorX, double FactorY, bool AntiAlias)
{
const cBitmap *b = &Bitmap;
if (!DoubleEqual(FactorX, 1.0) || !DoubleEqual(FactorY, 1.0))
b = b->Scaled(FactorX, FactorY, AntiAlias);
DrawBitmap(x, y, *b);
if (b != &Bitmap)
delete b;
}
void cOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment) void cOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment)
{ {
if (isTrueColor) if (isTrueColor)
@ -1968,6 +1978,7 @@ int cOsdProvider::oldWidth = 0;
int cOsdProvider::oldHeight = 0; int cOsdProvider::oldHeight = 0;
double cOsdProvider::oldAspect = 1.0; double cOsdProvider::oldAspect = 1.0;
cImage *cOsdProvider::images[MAXOSDIMAGES] = { NULL }; cImage *cOsdProvider::images[MAXOSDIMAGES] = { NULL };
int cOsdProvider::osdState = 0;
cOsdProvider::cOsdProvider(void) cOsdProvider::cOsdProvider(void)
{ {
@ -2005,6 +2016,7 @@ void cOsdProvider::UpdateOsdSize(bool Force)
int Width; int Width;
int Height; int Height;
double Aspect; double Aspect;
cMutexLock MutexLock(&cOsd::mutex);
cDevice::PrimaryDevice()->GetOsdSize(Width, Height, Aspect); cDevice::PrimaryDevice()->GetOsdSize(Width, Height, Aspect);
if (Width != oldWidth || Height != oldHeight || !DoubleEqual(Aspect, oldAspect) || Force) { if (Width != oldWidth || Height != oldHeight || !DoubleEqual(Aspect, oldAspect) || Force) {
Setup.OSDLeft = int(round(Width * Setup.OSDLeftP)); Setup.OSDLeft = int(round(Width * Setup.OSDLeftP));
@ -2022,9 +2034,18 @@ void cOsdProvider::UpdateOsdSize(bool Force)
oldHeight = Height; oldHeight = Height;
oldAspect = Aspect; oldAspect = Aspect;
dsyslog("OSD size changed to %dx%d @ %g", Width, Height, Aspect); dsyslog("OSD size changed to %dx%d @ %g", Width, Height, Aspect);
osdState++;
} }
} }
bool cOsdProvider::OsdSizeChanged(int &State)
{
cMutexLock MutexLock(&cOsd::mutex);
bool Result = osdState != State;
State = osdState;
return Result;
}
bool cOsdProvider::SupportsTrueColor(void) bool cOsdProvider::SupportsTrueColor(void)
{ {
if (osdProvider) { if (osdProvider) {

16
osd.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.h 3.2 2013/09/06 12:13:47 kls Exp $ * $Id: osd.h 3.5 2015/01/15 11:23:52 kls Exp $
*/ */
#ifndef __OSD_H #ifndef __OSD_H
@ -817,6 +817,8 @@ public:
///< If this is a true color OSD, a pointer to a dummy bitmap with 8bpp ///< If this is a true color OSD, a pointer to a dummy bitmap with 8bpp
///< is returned. This is done so that skins that call this function ///< is returned. This is done so that skins that call this function
///< in order to preset the bitmap's palette won't crash. ///< in order to preset the bitmap's palette won't crash.
///< Use of this function outside of derived classes is deprecated and it
///< may be made 'protected' in a future version.
virtual cPixmap *CreatePixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null); virtual cPixmap *CreatePixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null);
///< Creates a new true color pixmap on this OSD (see cPixmap for details). ///< Creates a new true color pixmap on this OSD (see cPixmap for details).
///< The caller must not delete the returned object, it will be deleted when ///< The caller must not delete the returned object, it will be deleted when
@ -885,6 +887,11 @@ public:
///< If Overlay is true, any pixel in Bitmap that has color index 0 will ///< If Overlay is true, any pixel in Bitmap that has color index 0 will
///< not overwrite the corresponding pixel in the target area. ///< not overwrite the corresponding pixel in the target area.
///< If this is a true color OSD, ReplacePalette has no meaning. ///< If this is a true color OSD, ReplacePalette has no meaning.
virtual void DrawScaledBitmap(int x, int y, const cBitmap &Bitmap, double FactorX, double FactorY, bool AntiAlias = false);
///< Sets the pixels in the OSD with the data from the given Bitmap, putting
///< the upper left corner of the Bitmap at (x, y) and scaled by the given
///< factors. If AntiAlias is true and either of the factors is greater than
///< 1.0, anti-aliasing is applied.
virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault);
///< Draws the given string at coordinates (x, y) with the given foreground ///< Draws the given string at coordinates (x, y) with the given foreground
///< and background color and font. If Width and Height are given, the text ///< and background color and font. If Width and Height are given, the text
@ -942,6 +949,7 @@ private:
static int oldHeight; static int oldHeight;
static double oldAspect; static double oldAspect;
static cImage *images[MAXOSDIMAGES]; static cImage *images[MAXOSDIMAGES];
static int osdState;
protected: protected:
virtual cOsd *CreateOsd(int Left, int Top, uint Level) = 0; virtual cOsd *CreateOsd(int Left, int Top, uint Level) = 0;
///< Returns a pointer to a newly created cOsd object, which will be located ///< Returns a pointer to a newly created cOsd object, which will be located
@ -978,6 +986,12 @@ public:
///< font sizes accordingly. If Force is true, all settings are recalculated, ///< font sizes accordingly. If Force is true, all settings are recalculated,
///< even if the video resolution hasn't changed since the last call to ///< even if the video resolution hasn't changed since the last call to
///< this function. ///< this function.
static bool OsdSizeChanged(int &State);
///< Checks if the OSD size has changed and a currently displayed OSD needs to
///< be redrawn. An internal reference value is incremented on every size change
///< and is compared against State when calling the method.
///< OsdSizeChanged() can be called with an uninitialized State to just get
///< the current value of State.
static bool SupportsTrueColor(void); static bool SupportsTrueColor(void);
///< Returns true if the current OSD provider is able to handle a true color OSD. ///< Returns true if the current OSD provider is able to handle a true color OSD.
static int StoreImage(const cImage &Image); static int StoreImage(const cImage &Image);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osdbase.c 3.2 2013/09/22 14:01:17 kls Exp $ * $Id: osdbase.c 3.3 2015/01/15 10:11:11 kls Exp $
*/ */
#include "osdbase.h" #include "osdbase.h"
@ -86,6 +86,7 @@ cOsdMenu::cOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4)
displayMenuItems = 0; displayMenuItems = 0;
title = NULL; title = NULL;
menuCategory = mcUnknown; menuCategory = mcUnknown;
menuSortMode = msmUnknown;
SetTitle(Title); SetTitle(Title);
SetCols(c0, c1, c2, c3, c4); SetCols(c0, c1, c2, c3, c4);
first = 0; first = 0;
@ -114,6 +115,11 @@ void cOsdMenu::SetMenuCategory(eMenuCategory MenuCategory)
menuCategory = MenuCategory; menuCategory = MenuCategory;
} }
void cOsdMenu::SetMenuSortMode(eMenuSortMode MenuSortMode)
{
menuSortMode = MenuSortMode;
}
void cOsdMenu::SetDisplayMenu(void) void cOsdMenu::SetDisplayMenu(void)
{ {
if (displayMenu) { if (displayMenu) {
@ -224,6 +230,7 @@ void cOsdMenu::Display(void)
cStatus::MsgOsdClear(); cStatus::MsgOsdClear();
if (menuCategory != displayMenu->MenuCategory()) if (menuCategory != displayMenu->MenuCategory())
displayMenu->SetMenuCategory(menuCategory); displayMenu->SetMenuCategory(menuCategory);
displayMenu->SetMenuSortMode(menuSortMode);
displayMenuItems = displayMenu->MaxItems(); displayMenuItems = displayMenu->MaxItems();
displayMenu->SetTabs(cols[0], cols[1], cols[2], cols[3], cols[4]);//XXX displayMenu->SetTabs(cols[0], cols[1], cols[2], cols[3], cols[4]);//XXX
displayMenu->SetTitle(title); displayMenu->SetTitle(title);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osdbase.h 3.1 2013/09/22 14:00:47 kls Exp $ * $Id: osdbase.h 3.2 2015/01/15 10:09:18 kls Exp $
*/ */
#ifndef __OSDBASE_H #ifndef __OSDBASE_H
@ -92,6 +92,7 @@ private:
int cols[cSkinDisplayMenu::MaxTabs]; int cols[cSkinDisplayMenu::MaxTabs];
int first, current, marked; int first, current, marked;
eMenuCategory menuCategory; eMenuCategory menuCategory;
eMenuSortMode menuSortMode;
cOsdMenu *subMenu; cOsdMenu *subMenu;
const char *helpRed, *helpGreen, *helpYellow, *helpBlue; const char *helpRed, *helpGreen, *helpYellow, *helpBlue;
bool helpDisplayed; bool helpDisplayed;
@ -131,6 +132,7 @@ public:
virtual ~cOsdMenu(); virtual ~cOsdMenu();
virtual bool NeedsFastResponse(void) { return subMenu ? subMenu->NeedsFastResponse() : cOsdObject::NeedsFastResponse(); } virtual bool NeedsFastResponse(void) { return subMenu ? subMenu->NeedsFastResponse() : cOsdObject::NeedsFastResponse(); }
void SetMenuCategory(eMenuCategory MenuCategory); void SetMenuCategory(eMenuCategory MenuCategory);
void SetMenuSortMode(eMenuSortMode MenuSortMode);
int Current(void) const { return current; } int Current(void) const { return current; }
void Add(cOsdItem *Item, bool Current = false, cOsdItem *After = NULL); void Add(cOsdItem *Item, bool Current = false, cOsdItem *After = NULL);
void Ins(cOsdItem *Item, bool Current = false, cOsdItem *Before = NULL); void Ins(cOsdItem *Item, bool Current = false, cOsdItem *Before = NULL);

27
pat.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: pat.c 3.4 2014/02/19 08:57:43 kls Exp $ * $Id: pat.c 3.5 2015/01/04 13:14:01 kls Exp $
*/ */
#include "pat.h" #include "pat.h"
@ -69,12 +69,13 @@ private:
int source; int source;
int transponder; int transponder;
int serviceId; int serviceId;
int pmtPid; // needed for OctopusNet - otherwise irrelevant!
int numCaIds; int numCaIds;
int caIds[MAXCAIDS + 1]; int caIds[MAXCAIDS + 1];
cList<cCaDescriptor> caDescriptors; cList<cCaDescriptor> caDescriptors;
void AddCaId(int CaId); void AddCaId(int CaId);
public: public:
cCaDescriptors(int Source, int Transponder, int ServiceId); cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid);
bool operator== (const cCaDescriptors &arg) const; bool operator== (const cCaDescriptors &arg) const;
bool Is(int Source, int Transponder, int ServiceId); bool Is(int Source, int Transponder, int ServiceId);
bool Is(cCaDescriptors * CaDescriptors); bool Is(cCaDescriptors * CaDescriptors);
@ -82,14 +83,16 @@ public:
void AddCaDescriptor(SI::CaDescriptor *d, int EsPid); void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid); int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids); int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids);
const int GetPmtPid(void) { return pmtPid; };
const int *CaIds(void) { return caIds; } const int *CaIds(void) { return caIds; }
}; };
cCaDescriptors::cCaDescriptors(int Source, int Transponder, int ServiceId) cCaDescriptors::cCaDescriptors(int Source, int Transponder, int ServiceId, int PmtPid)
{ {
source = Source; source = Source;
transponder = Transponder; transponder = Transponder;
serviceId = ServiceId; serviceId = ServiceId;
pmtPid = PmtPid;
numCaIds = 0; numCaIds = 0;
caIds[0] = 0; caIds[0] = 0;
} }
@ -218,6 +221,7 @@ public:
// and 2 if an existing descriptor was changed. // and 2 if an existing descriptor was changed.
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid); int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids); int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);
int GetPmtPid(int Source, int Transponder, int ServiceId);
}; };
int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors) int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
@ -258,6 +262,16 @@ int cCaDescriptorHandler::GetCaPids(int Source, int Transponder, int ServiceId,
return 0; return 0;
} }
int cCaDescriptorHandler::GetPmtPid(int Source, int Transponder, int ServiceId)
{
cMutexLock MutexLock(&mutex);
for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
if (ca->Is(Source, Transponder, ServiceId))
return ca->GetPmtPid();
}
return 0;
}
cCaDescriptorHandler CaDescriptorHandler; cCaDescriptorHandler CaDescriptorHandler;
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid) int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
@ -270,6 +284,11 @@ int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds
return CaDescriptorHandler.GetCaPids(Source, Transponder, ServiceId, CaSystemIds, BufSize, Pids); return CaDescriptorHandler.GetCaPids(Source, Transponder, ServiceId, CaSystemIds, BufSize, Pids);
} }
int GetPmtPid(int Source, int Transponder, int ServiceId)
{
return CaDescriptorHandler.GetPmtPid(Source, Transponder, ServiceId);
}
// --- cPatFilter ------------------------------------------------------------ // --- cPatFilter ------------------------------------------------------------
//#define DEBUG_PAT_PMT //#define DEBUG_PAT_PMT
@ -384,7 +403,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId()); cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId());
if (Channel) { if (Channel) {
SI::CaDescriptor *d; SI::CaDescriptor *d;
cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid()); cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid(), Pid);
// Scan the common loop: // Scan the common loop:
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) { for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
CaDescriptors->AddCaDescriptor(d, 0); CaDescriptors->AddCaDescriptor(d, 0);

5
pat.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: pat.h 3.3 2014/02/18 11:22:34 kls Exp $ * $Id: pat.h 3.4 2015/01/04 13:17:22 kls Exp $
*/ */
#ifndef __PAT_H #ifndef __PAT_H
@ -56,4 +56,7 @@ int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds
///< Returns the number of pids copied into Pids (0 if no CA descriptors are ///< Returns the number of pids copied into Pids (0 if no CA descriptors are
///< available), or -1 if BufSize was too small to hold all CA pids. ///< available), or -1 if BufSize was too small to hold all CA pids.
int GetPmtPid(int Source, int Transponder, int ServiceId);
///< Gets the Pid of the PMT in which the CA descriptors for this channel are defined.
#endif //__PAT_H #endif //__PAT_H

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-10-16 11:16-0400\n" "PO-Revision-Date: 2008-10-16 11:16-0400\n"
"Last-Translator: Osama Alrawab <alrawab@hotmail.com>\n" "Last-Translator: Osama Alrawab <alrawab@hotmail.com>\n"
"Language-Team: Arabic <ar@li.org>\n" "Language-Team: Arabic <ar@li.org>\n"
@ -1256,6 +1256,12 @@ msgstr "كسابق"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "فعل الصوت" msgstr "فعل الصوت"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Channels wrap" msgstr "Channels wrap"

View File

@ -10,7 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-03-02 19:02+0100\n" "PO-Revision-Date: 2008-03-02 19:02+0100\n"
"Last-Translator: Luca Olivetti <luca@ventoso.org>\n" "Last-Translator: Luca Olivetti <luca@ventoso.org>\n"
"Language-Team: Catalan <vdr@linuxtv.org>\n" "Language-Team: Catalan <vdr@linuxtv.org>\n"
@ -1255,6 +1255,12 @@ msgstr "anterior"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Volum inicial" msgstr "Volum inicial"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Primer canal després de l'ultim" msgstr "Primer canal després de l'ultim"

View File

@ -10,7 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2010-05-06 11:00+0200\n" "PO-Revision-Date: 2010-05-06 11:00+0200\n"
"Last-Translator: Aleš Juřík <ajurik@quick.cz>\n" "Last-Translator: Aleš Juřík <ajurik@quick.cz>\n"
"Language-Team: Czech <vdr@linuxtv.org>\n" "Language-Team: Czech <vdr@linuxtv.org>\n"
@ -1255,6 +1255,12 @@ msgstr "jako naposledy"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Hlasitost po spuštění" msgstr "Hlasitost po spuštění"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Přecházet z konce na začátek seznamu kanálů" msgstr "Přecházet z konce na začátek seznamu kanálů"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Mogens Elneff <mogens@elneff.dk>\n" "Last-Translator: Mogens Elneff <mogens@elneff.dk>\n"
"Language-Team: Danish <vdr@linuxtv.org>\n" "Language-Team: Danish <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr "som f
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Lydstyrke ved opstart" msgstr "Lydstyrke ved opstart"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "" msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2010-01-16 16:46+0100\n" "PO-Revision-Date: 2010-01-16 16:46+0100\n"
"Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n" "Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n"
"Language-Team: German <vdr@linuxtv.org>\n" "Language-Team: German <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr "wie vorher"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Lautstärke beim Einschalten" msgstr "Lautstärke beim Einschalten"
msgid "Setup.Miscellaneous$Volume steps"
msgstr "Anzahl Lautstärke Schritte"
msgid "Setup.Miscellaneous$Volume linearize"
msgstr "Lautstärke Kurve korrigieren"
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Rundum zappen" msgstr "Rundum zappen"
@ -1449,7 +1455,7 @@ msgstr "MDMDFSS"
#. TRANSLATORS: abbreviated weekdays, beginning with monday (must all be 3 letters!) #. TRANSLATORS: abbreviated weekdays, beginning with monday (must all be 3 letters!)
msgid "MonTueWedThuFriSatSun" msgid "MonTueWedThuFriSatSun"
msgstr "MonDieMitDonFreSamSon" msgstr "Mo.Di.Mi.Do.Fr.Sa.So."
msgid "Monday" msgid "Monday"
msgstr "Montag" msgstr "Montag"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Dimitrios Dimitrakos <mail@dimitrios.de>\n" "Last-Translator: Dimitrios Dimitrakos <mail@dimitrios.de>\n"
"Language-Team: Greek <vdr@linuxtv.org>\n" "Language-Team: Greek <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr ""
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "" msgstr ""
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-03-02 19:02+0100\n" "PO-Revision-Date: 2008-03-02 19:02+0100\n"
"Last-Translator: Luca Olivetti <luca@ventoso.org>\n" "Last-Translator: Luca Olivetti <luca@ventoso.org>\n"
"Language-Team: Spanish <vdr@linuxtv.org>\n" "Language-Team: Spanish <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr "anterior"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Volumen inicial" msgstr "Volumen inicial"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Primer canal después del último" msgstr "Primer canal después del último"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Arthur Konovalov <artlov@gmail.com>\n" "Last-Translator: Arthur Konovalov <artlov@gmail.com>\n"
"Language-Team: Estonian <vdr@linuxtv.org>\n" "Language-Team: Estonian <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr "endine"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Helitugevus käivitamisel" msgstr "Helitugevus käivitamisel"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Kanalite ringkerimine" msgstr "Kanalite ringkerimine"

View File

@ -11,7 +11,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2007-08-15 15:52+0200\n" "PO-Revision-Date: 2007-08-15 15:52+0200\n"
"Last-Translator: Matti Lehtimäki <matti.lehtimaki@gmail.com>\n" "Last-Translator: Matti Lehtimäki <matti.lehtimaki@gmail.com>\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n" "Language-Team: Finnish <vdr@linuxtv.org>\n"
@ -1256,6 +1256,12 @@ msgstr "edellinen"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Äänenvoimakkuus käynnistettäessä" msgstr "Äänenvoimakkuus käynnistettäessä"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Kanavien rullaus" msgstr "Kanavien rullaus"

View File

@ -17,7 +17,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-02-24 12:56+0100\n" "PO-Revision-Date: 2013-02-24 12:56+0100\n"
"Last-Translator: Dominique Plu <dplu@free.fr>\n" "Last-Translator: Dominique Plu <dplu@free.fr>\n"
"Language-Team: French <vdr@linuxtv.org>\n" "Language-Team: French <vdr@linuxtv.org>\n"
@ -1262,6 +1262,12 @@ msgstr "comme avant"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Volume initial" msgstr "Volume initial"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Affichage circulaire des chaînes" msgstr "Affichage circulaire des chaînes"

View File

@ -9,7 +9,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-03-17 19:00+0100\n" "PO-Revision-Date: 2008-03-17 19:00+0100\n"
"Last-Translator: Adrian Caval <anrxc@sysphere.org>\n" "Last-Translator: Adrian Caval <anrxc@sysphere.org>\n"
"Language-Team: Croatian <vdr@linuxtv.org>\n" "Language-Team: Croatian <vdr@linuxtv.org>\n"
@ -1254,6 +1254,12 @@ msgstr "kao prethodno"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Poèetna jaèina zvuka" msgstr "Poèetna jaèina zvuka"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "" msgstr ""

View File

@ -10,7 +10,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-03-01 19:22+0200\n" "PO-Revision-Date: 2013-03-01 19:22+0200\n"
"Last-Translator: István Füley <ifuley@tigercomp.ro>\n" "Last-Translator: István Füley <ifuley@tigercomp.ro>\n"
"Language-Team: Hungarian <vdr@linuxtv.org>\n" "Language-Team: Hungarian <vdr@linuxtv.org>\n"
@ -1256,6 +1256,12 @@ msgstr "ahogy az előbb"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Hangerő indulásnál" msgstr "Hangerő indulásnál"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Csatornalista görgetése" msgstr "Csatornalista görgetése"

View File

@ -11,8 +11,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-11-10 23:02+0100\n" "PO-Revision-Date: 2014-03-23 00:54+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n" "Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: Italian <vdr@linuxtv.org>\n" "Language-Team: Italian <vdr@linuxtv.org>\n"
"Language: it\n" "Language: it\n"
@ -84,13 +84,13 @@ msgid "StreamId"
msgstr "StreamId" msgstr "StreamId"
msgid "Pilot" msgid "Pilot"
msgstr "" msgstr "Pilot"
msgid "T2SystemId" msgid "T2SystemId"
msgstr "" msgstr "T2SystemId"
msgid "SISO/MISO" msgid "SISO/MISO"
msgstr "" msgstr "SISO/MISO"
msgid "Starting EPG scan" msgid "Starting EPG scan"
msgstr "Inizio scansione EPG" msgstr "Inizio scansione EPG"
@ -580,10 +580,10 @@ msgid "Sid"
msgstr "Sid" msgstr "Sid"
msgid "Nid" msgid "Nid"
msgstr "" msgstr "Nid"
msgid "Tid" msgid "Tid"
msgstr "" msgstr "Tid"
msgid "Channel settings are not unique!" msgid "Channel settings are not unique!"
msgstr "Parametri canale non univoci!" msgstr "Parametri canale non univoci!"
@ -795,7 +795,7 @@ msgid "Recording vanished!"
msgstr "Registrazione sparita!" msgstr "Registrazione sparita!"
msgid "Edited version already exists - overwrite?" msgid "Edited version already exists - overwrite?"
msgstr "" msgstr "Versione modificata già esistente. Sovrascrivere?"
msgid "Error while queueing recording for cutting!" msgid "Error while queueing recording for cutting!"
msgstr "Errore durante l'accodamento della registrazione per il taglio!" msgstr "Errore durante l'accodamento della registrazione per il taglio!"
@ -1259,6 +1259,12 @@ msgstr "come prima"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Volume iniziale" msgstr "Volume iniziale"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Riavvolgimento canali" msgstr "Riavvolgimento canali"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2010-10-30 11:55+0200\n" "PO-Revision-Date: 2010-10-30 11:55+0200\n"
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n" "Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
"Language-Team: Lithuanian <vdr@linuxtv.org>\n" "Language-Team: Lithuanian <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr "kaip anksčiau"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Garsas įjungimo metu" msgstr "Garsas įjungimo metu"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Kanalų pridengimas" msgstr "Kanalų pridengimas"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2012-11-19 15:18+0100\n" "PO-Revision-Date: 2012-11-19 15:18+0100\n"
"Last-Translator: Dimitar Petrovski <dimeptr@gmail.com>\n" "Last-Translator: Dimitar Petrovski <dimeptr@gmail.com>\n"
"Language-Team: Macedonian <en@li.org>\n" "Language-Team: Macedonian <en@li.org>\n"
@ -1253,6 +1253,12 @@ msgstr "како претходно"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Почетна јачина на звук" msgstr "Почетна јачина на звук"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Премотување канали" msgstr "Премотување канали"

View File

@ -12,7 +12,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-02-26 17:20+0100\n" "PO-Revision-Date: 2008-02-26 17:20+0100\n"
"Last-Translator: Cedric Dewijs <cedric.dewijs@telfort.nl>\n" "Last-Translator: Cedric Dewijs <cedric.dewijs@telfort.nl>\n"
"Language-Team: Dutch <vdr@linuxtv.org>\n" "Language-Team: Dutch <vdr@linuxtv.org>\n"
@ -1257,6 +1257,12 @@ msgstr "zoals eerder"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Opstartvolume" msgstr "Opstartvolume"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Doorscrollen kanalenlijst" msgstr "Doorscrollen kanalenlijst"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2007-08-12 14:17+0200\n" "PO-Revision-Date: 2007-08-12 14:17+0200\n"
"Last-Translator: Truls Slevigen <truls@slevigen.no>\n" "Last-Translator: Truls Slevigen <truls@slevigen.no>\n"
"Language-Team: Norwegian Nynorsk <vdr@linuxtv.org>\n" "Language-Team: Norwegian Nynorsk <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr ""
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "" msgstr ""
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "" msgstr ""

View File

@ -9,7 +9,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-03-09 12:59+0100\n" "PO-Revision-Date: 2008-03-09 12:59+0100\n"
"Last-Translator: Marek Nazarko <mnazarko@gmail.com>\n" "Last-Translator: Marek Nazarko <mnazarko@gmail.com>\n"
"Language-Team: Polish <vdr@linuxtv.org>\n" "Language-Team: Polish <vdr@linuxtv.org>\n"
@ -1254,6 +1254,12 @@ msgstr "jak ostatnio"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Pocz±tkowa g³o¶no¶æ" msgstr "Pocz±tkowa g³o¶no¶æ"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Zawijanie kana³ów" msgstr "Zawijanie kana³ów"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2010-03-28 22:49+0100\n" "PO-Revision-Date: 2010-03-28 22:49+0100\n"
"Last-Translator: Cris Silva <hudokkow@gmail.com>\n" "Last-Translator: Cris Silva <hudokkow@gmail.com>\n"
"Language-Team: Portuguese <vdr@linuxtv.org>\n" "Language-Team: Portuguese <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr "como estava"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Volume inicial" msgstr "Volume inicial"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Retroceder canais" msgstr "Retroceder canais"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-02-09 23:01+0100\n" "PO-Revision-Date: 2013-02-09 23:01+0100\n"
"Last-Translator: Lucian Muresan <lucianm@users.sorceforge.net>\n" "Last-Translator: Lucian Muresan <lucianm@users.sorceforge.net>\n"
"Language-Team: Romanian <vdr@linuxtv.org>\n" "Language-Team: Romanian <vdr@linuxtv.org>\n"
@ -1254,6 +1254,12 @@ msgstr "ca mai înainte"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Volumul la pornire" msgstr "Volumul la pornire"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Lista de canale în buclă" msgstr "Lista de canale în buclă"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-03-10 17:13+0100\n" "PO-Revision-Date: 2013-03-10 17:13+0100\n"
"Last-Translator: Oleg Roitburd <oroitburd@gmail.com>\n" "Last-Translator: Oleg Roitburd <oroitburd@gmail.com>\n"
"Language-Team: Russian <vdr@linuxtv.org>\n" "Language-Team: Russian <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr "
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "³àÞÜÚÞáâì ßàØ ÒÚÛîçÕÝØØ" msgstr "³àÞÜÚÞáâì ßàØ ÒÚÛîçÕÝØØ"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "ßàÞÚàãâÚÐ ÚÐÝÐÛÞÒ" msgstr "ßàÞÚàãâÚÐ ÚÐÝÐÛÞÒ"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-03-04 21:24+0100\n" "PO-Revision-Date: 2013-03-04 21:24+0100\n"
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n" "Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
"Language-Team: Slovak <vdr@linuxtv.org>\n" "Language-Team: Slovak <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr "ako naposledy"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Hlasitos» po spustení" msgstr "Hlasitos» po spustení"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Kanály cyklova» pri prepnutí" msgstr "Kanály cyklova» pri prepnutí"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-03-04 12:46+0100\n" "PO-Revision-Date: 2013-03-04 12:46+0100\n"
"Last-Translator: Matjaz Thaler <matjaz.thaler@guest.arnes.si>\n" "Last-Translator: Matjaz Thaler <matjaz.thaler@guest.arnes.si>\n"
"Language-Team: Slovenian <vdr@linuxtv.org>\n" "Language-Team: Slovenian <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr "kot prej"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Privzeta glasnost" msgstr "Privzeta glasnost"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Menjava kanala" msgstr "Menjava kanala"

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-03-16 15:05+0100\n" "PO-Revision-Date: 2013-03-16 15:05+0100\n"
"Last-Translator: Zoran Turalija <zoran.turalija@gmail.com>\n" "Last-Translator: Zoran Turalija <zoran.turalija@gmail.com>\n"
"Language-Team: Serbian <vdr@linuxtv.org>\n" "Language-Team: Serbian <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr "kao prethodno"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Poèetna jaèina tona" msgstr "Poèetna jaèina tona"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Prelazak sa kraja na poèetak liste kanala" msgstr "Prelazak sa kraja na poèetak liste kanala"

View File

@ -11,7 +11,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-02-18 17:04+0100\n" "PO-Revision-Date: 2013-02-18 17:04+0100\n"
"Last-Translator: Richard Lithvall <r-vdr@boomer.se>\n" "Last-Translator: Richard Lithvall <r-vdr@boomer.se>\n"
"Language-Team: Swedish <vdr@linuxtv.org>\n" "Language-Team: Swedish <vdr@linuxtv.org>\n"
@ -1256,6 +1256,12 @@ msgstr "samma som vid avslut"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Ljudstyrka vid uppstart" msgstr "Ljudstyrka vid uppstart"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Cirkulär kanallista" msgstr "Cirkulär kanallista"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2008-02-28 00:33+0100\n" "PO-Revision-Date: 2008-02-28 00:33+0100\n"
"Last-Translator: Oktay Yolgeçen <oktay_73@yahoo.de>\n" "Last-Translator: Oktay Yolgeçen <oktay_73@yahoo.de>\n"
"Language-Team: Turkish <vdr@linuxtv.org>\n" "Language-Team: Turkish <vdr@linuxtv.org>\n"
@ -1252,6 +1252,12 @@ msgstr "
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Açýlýþdaki ses" msgstr "Açýlýþdaki ses"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "" msgstr ""

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-02-09 16:00+0100\n" "PO-Revision-Date: 2013-02-09 16:00+0100\n"
"Last-Translator: Yarema aka Knedlyk <yupadmin@gmail.com>\n" "Last-Translator: Yarema aka Knedlyk <yupadmin@gmail.com>\n"
"Language-Team: Ukrainian <vdr@linuxtv.org>\n" "Language-Team: Ukrainian <vdr@linuxtv.org>\n"
@ -1253,6 +1253,12 @@ msgstr "як раніше"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "Гучність при включенні" msgstr "Гучність при включенні"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "Кінець каналів" msgstr "Кінець каналів"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: VDR 2.0.0\n" "Project-Id-Version: VDR 2.0.0\n"
"Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n" "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
"POT-Creation-Date: 2013-11-03 15:59+0100\n" "POT-Creation-Date: 2015-01-12 15:40+0100\n"
"PO-Revision-Date: 2013-03-04 14:52+0800\n" "PO-Revision-Date: 2013-03-04 14:52+0800\n"
"Last-Translator: NFVDR <nfvdr@live.com>\n" "Last-Translator: NFVDR <nfvdr@live.com>\n"
"Language-Team: Chinese (simplified) <nfvdr@live.com>\n" "Language-Team: Chinese (simplified) <nfvdr@live.com>\n"
@ -1254,6 +1254,12 @@ msgstr "之前"
msgid "Setup.Miscellaneous$Initial volume" msgid "Setup.Miscellaneous$Initial volume"
msgstr "初始化声音" msgstr "初始化声音"
msgid "Setup.Miscellaneous$Volume steps"
msgstr ""
msgid "Setup.Miscellaneous$Volume linearize"
msgstr ""
msgid "Setup.Miscellaneous$Channels wrap" msgid "Setup.Miscellaneous$Channels wrap"
msgstr "频道排序" msgstr "频道排序"

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: receiver.c 3.2 2014/02/08 15:57:30 kls Exp $ * $Id: receiver.c 3.3 2015/01/12 14:04:31 kls Exp $
*/ */
#include "receiver.h" #include "receiver.h"
@ -14,7 +14,7 @@
cReceiver::cReceiver(const cChannel *Channel, int Priority) cReceiver::cReceiver(const cChannel *Channel, int Priority)
{ {
device = NULL; device = NULL;
priority = constrain(Priority, MINPRIORITY, MAXPRIORITY); SetPriority(Priority);
numPids = 0; numPids = 0;
SetPids(Channel); SetPids(Channel);
} }
@ -29,6 +29,11 @@ cReceiver::~cReceiver()
} }
} }
void cReceiver::SetPriority(int Priority)
{
priority = constrain(Priority, MINPRIORITY, MAXPRIORITY);
}
bool cReceiver::AddPid(int Pid) bool cReceiver::AddPid(int Pid)
{ {
if (Pid) { if (Pid) {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: receiver.h 3.1 2014/01/01 11:45:09 kls Exp $ * $Id: receiver.h 3.3 2015/01/12 14:03:22 kls Exp $
*/ */
#ifndef __RECEIVER_H #ifndef __RECEIVER_H
@ -24,6 +24,7 @@ private:
int numPids; int numPids;
bool WantsPid(int Pid); bool WantsPid(int Pid);
protected: protected:
cDevice *Device(void) { return device; }
void Detach(void); void Detach(void);
virtual void Activate(bool On) {} virtual void Activate(bool On) {}
///< This function is called just before the cReceiver gets attached to ///< This function is called just before the cReceiver gets attached to
@ -48,6 +49,8 @@ public:
///< that this cReceiver may be detached at any time in favor of a timer recording ///< that this cReceiver may be detached at any time in favor of a timer recording
///< or live viewing (without blocking the cDevice it is attached to). ///< or live viewing (without blocking the cDevice it is attached to).
virtual ~cReceiver(); virtual ~cReceiver();
int Priority(void) { return priority; }
void SetPriority(int Priority);
bool AddPid(int Pid); bool AddPid(int Pid);
///< Adds the given Pid to the list of PIDs of this receiver. ///< Adds the given Pid to the list of PIDs of this receiver.
bool AddPids(const int *Pids); bool AddPids(const int *Pids);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recorder.h 3.0 2010/12/27 11:17:04 kls Exp $ * $Id: recorder.h 3.1 2015/01/15 14:27:02 kls Exp $
*/ */
#ifndef __RECORDER_H #ifndef __RECORDER_H
@ -31,12 +31,16 @@ private:
bool NextFile(void); bool NextFile(void);
protected: protected:
virtual void Activate(bool On); virtual void Activate(bool On);
///< If you override Activate() you need to call Detach() (which is a
///< member of the cReceiver class) from your own destructor in order
///< to properly get a call to Activate(false) when your object is
///< destroyed.
virtual void Receive(uchar *Data, int Length); virtual void Receive(uchar *Data, int Length);
virtual void Action(void); virtual void Action(void);
public: public:
cRecorder(const char *FileName, const cChannel *Channel, int Priority); cRecorder(const char *FileName, const cChannel *Channel, int Priority);
// Creates a new recorder for the given Channel and ///< Creates a new recorder for the given Channel and
// the given Priority that will record into the file FileName. ///< the given Priority that will record into the file FileName.
virtual ~cRecorder(); virtual ~cRecorder();
}; };

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.c 3.18 2014/03/16 11:09:17 kls Exp $ * $Id: recording.c 3.21 2015/01/17 14:52:28 kls Exp $
*/ */
#include "recording.h" #include "recording.h"
@ -65,6 +65,7 @@
#define REMOVELATENCY 10 // seconds to wait until next check after removing a file #define REMOVELATENCY 10 // seconds to wait until next check after removing a file
#define MARKSUPDATEDELTA 10 // seconds between checks for updating editing marks #define MARKSUPDATEDELTA 10 // seconds between checks for updating editing marks
#define MININDEXAGE 3600 // seconds before an index file is considered no longer to be written #define MININDEXAGE 3600 // seconds before an index file is considered no longer to be written
#define MAXREMOVETIME 10 // seconds after which to return from removing deleted recordings
#define MAX_LINK_LEVEL 6 #define MAX_LINK_LEVEL 6
@ -97,11 +98,16 @@ void cRemoveDeletedRecordingsThread::Action(void)
// Make sure only one instance of VDR does this: // Make sure only one instance of VDR does this:
cLockFile LockFile(cVideoDirectory::Name()); cLockFile LockFile(cVideoDirectory::Name());
if (LockFile.Lock()) { if (LockFile.Lock()) {
time_t StartTime = time(NULL);
bool deleted = false; bool deleted = false;
cThreadLock DeletedRecordingsLock(&DeletedRecordings); cThreadLock DeletedRecordingsLock(&DeletedRecordings);
for (cRecording *r = DeletedRecordings.First(); r; ) { for (cRecording *r = DeletedRecordings.First(); r; ) {
if (cIoThrottle::Engaged()) if (cIoThrottle::Engaged())
return; return;
if (time(NULL) - StartTime > MAXREMOVETIME)
return; // don't stay here too long
if (cRemote::HasKeys())
return; // react immediately on user input
if (r->Deleted() && time(NULL) - r->Deleted() > DELETEDLIFETIME) { if (r->Deleted() && time(NULL) - r->Deleted() > DELETEDLIFETIME) {
cRecording *next = DeletedRecordings.Next(r); cRecording *next = DeletedRecordings.Next(r);
r->Remove(); r->Remove();
@ -2235,17 +2241,19 @@ void cRecordingUserCommand::InvokeCommand(const char *State, const char *Recordi
class cIndexFileGenerator : public cThread { class cIndexFileGenerator : public cThread {
private: private:
cString recordingName; cString recordingName;
bool update;
protected: protected:
virtual void Action(void); virtual void Action(void);
public: public:
cIndexFileGenerator(const char *RecordingName); cIndexFileGenerator(const char *RecordingName, bool Update = false);
~cIndexFileGenerator(); ~cIndexFileGenerator();
}; };
cIndexFileGenerator::cIndexFileGenerator(const char *RecordingName) cIndexFileGenerator::cIndexFileGenerator(const char *RecordingName, bool Update)
:cThread("index file generator") :cThread("index file generator")
,recordingName(RecordingName) ,recordingName(RecordingName)
{ {
update = Update;
Start(); Start();
} }
@ -2264,15 +2272,34 @@ void cIndexFileGenerator::Action(void)
cRingBufferLinear Buffer(IFG_BUFFER_SIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE); cRingBufferLinear Buffer(IFG_BUFFER_SIZE, MIN_TS_PACKETS_FOR_FRAME_DETECTOR * TS_SIZE);
cPatPmtParser PatPmtParser; cPatPmtParser PatPmtParser;
cFrameDetector FrameDetector; cFrameDetector FrameDetector;
cIndexFile IndexFile(recordingName, true); cIndexFile IndexFile(recordingName, true, false, false, true);
int BufferChunks = KILOBYTE(1); // no need to read a lot at the beginning when parsing PAT/PMT int BufferChunks = KILOBYTE(1); // no need to read a lot at the beginning when parsing PAT/PMT
off_t FileSize = 0; off_t FileSize = 0;
off_t FrameOffset = -1; off_t FrameOffset = -1;
uint16_t FileNumber = 1;
off_t FileOffset = 0;
int Last = -1;
if (update) {
// Look for current index and position to end of it if present:
bool Independent;
int Length;
Last = IndexFile.Last();
if (Last >= 0 && !IndexFile.Get(Last, &FileNumber, &FileOffset, &Independent, &Length))
Last = -1; // reset Last if an error occurred
if (Last >= 0) {
Rewind = true;
isyslog("updating index file");
}
else
isyslog("generating index file");
}
Skins.QueueMessage(mtInfo, tr("Regenerating index file")); Skins.QueueMessage(mtInfo, tr("Regenerating index file"));
bool Stuffed = false;
while (Running()) { while (Running()) {
// Rewind input file: // Rewind input file:
if (Rewind) { if (Rewind) {
ReplayFile = FileName.SetOffset(1); ReplayFile = FileName.SetOffset(FileNumber, FileOffset);
FileSize = FileOffset;
Buffer.Clear(); Buffer.Clear();
Rewind = false; Rewind = false;
} }
@ -2287,7 +2314,8 @@ void cIndexFileGenerator::Action(void)
int Processed = FrameDetector.Analyze(Data, Length); int Processed = FrameDetector.Analyze(Data, Length);
if (Processed > 0) { if (Processed > 0) {
if (FrameDetector.NewFrame()) { if (FrameDetector.NewFrame()) {
IndexFile.Write(FrameDetector.IndependentFrame(), FileName.Number(), FrameOffset >= 0 ? FrameOffset : FileSize); if (IndexFileWritten || Last < 0) // check for first frame and do not write if in update mode
IndexFile.Write(FrameDetector.IndependentFrame(), FileName.Number(), FrameOffset >= 0 ? FrameOffset : FileSize);
FrameOffset = -1; FrameOffset = -1;
IndexFileWritten = true; IndexFileWritten = true;
} }
@ -2332,10 +2360,25 @@ void cIndexFileGenerator::Action(void)
else if (ReplayFile) { else if (ReplayFile) {
int Result = Buffer.Read(ReplayFile, BufferChunks); int Result = Buffer.Read(ReplayFile, BufferChunks);
if (Result == 0) { // EOF if (Result == 0) { // EOF
ReplayFile = FileName.NextFile(); if (Buffer.Available() > 0 && !Stuffed) {
FileSize = 0; // So the last call to Buffer.Get() returned NULL, but there is still
FrameOffset = -1; // data in the buffer, and we're at the end of the current TS file.
Buffer.Clear(); // The remaining data in the buffer is less than what's needed for the
// frame detector to analyze frames, so we need to put some stuffing
// packets into the buffer to flush out the rest of the data (otherwise
// any frames within the remaining data would not be seen here):
uchar StuffingPacket[TS_SIZE] = { TS_SYNC_BYTE, 0xFF };
for (int i = 0; i <= MIN_TS_PACKETS_FOR_FRAME_DETECTOR; i++)
Buffer.Put(StuffingPacket, sizeof(StuffingPacket));
Stuffed = true;
}
else {
ReplayFile = FileName.NextFile();
FileSize = 0;
FrameOffset = -1;
Buffer.Clear();
Stuffed = false;
}
} }
} }
// Recording has been processed: // Recording has been processed:
@ -2397,7 +2440,7 @@ struct tIndexTs {
#define INDEXFILECHECKINTERVAL 500 // ms between checks for existence of the regenerated index file #define INDEXFILECHECKINTERVAL 500 // ms between checks for existence of the regenerated index file
#define INDEXFILETESTINTERVAL 10 // ms between tests for the size of the index file in case of pausing live video #define INDEXFILETESTINTERVAL 10 // ms between tests for the size of the index file in case of pausing live video
cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording, bool PauseLive) cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording, bool PauseLive, bool Update)
:resumeFile(FileName, IsPesRecording) :resumeFile(FileName, IsPesRecording)
{ {
f = -1; f = -1;
@ -2436,7 +2479,7 @@ cIndexFile::cIndexFile(const char *FileName, bool Record, bool IsPesRecording, b
esyslog("ERROR: invalid file size (%"PRId64") in '%s'", buf.st_size, *fileName); esyslog("ERROR: invalid file size (%"PRId64") in '%s'", buf.st_size, *fileName);
} }
last = int((buf.st_size + delta) / sizeof(tIndexTs) - 1); last = int((buf.st_size + delta) / sizeof(tIndexTs) - 1);
if (!Record && last >= 0) { if ((!Record || Update) && last >= 0) {
size = last + 1; size = last + 1;
index = MALLOC(tIndexTs, size); index = MALLOC(tIndexTs, size);
if (index) { if (index) {
@ -2724,15 +2767,16 @@ int cIndexFile::GetLength(const char *FileName, bool IsPesRecording)
return -1; return -1;
} }
bool GenerateIndex(const char *FileName) bool GenerateIndex(const char *FileName, bool Update)
{ {
if (DirectoryOk(FileName)) { if (DirectoryOk(FileName)) {
cRecording Recording(FileName); cRecording Recording(FileName);
if (Recording.Name()) { if (Recording.Name()) {
if (!Recording.IsPesRecording()) { if (!Recording.IsPesRecording()) {
cString IndexFileName = AddDirectory(FileName, INDEXFILESUFFIX); cString IndexFileName = AddDirectory(FileName, INDEXFILESUFFIX);
unlink(IndexFileName); if (!Update)
cIndexFileGenerator *IndexFileGenerator = new cIndexFileGenerator(FileName); unlink(IndexFileName);
cIndexFileGenerator *IndexFileGenerator = new cIndexFileGenerator(FileName, Update);
while (IndexFileGenerator->Active()) while (IndexFileGenerator->Active())
cCondWait::SleepMs(INDEXFILECHECKINTERVAL); cCondWait::SleepMs(INDEXFILECHECKINTERVAL);
if (access(IndexFileName, R_OK) == 0) if (access(IndexFileName, R_OK) == 0)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: recording.h 3.4 2014/01/01 12:45:18 kls Exp $ * $Id: recording.h 3.5 2015/01/17 14:33:05 kls Exp $
*/ */
#ifndef __RECORDING_H #ifndef __RECORDING_H
@ -429,7 +429,7 @@ private:
void ConvertToPes(tIndexTs *IndexTs, int Count); void ConvertToPes(tIndexTs *IndexTs, int Count);
bool CatchUp(int Index = -1); bool CatchUp(int Index = -1);
public: public:
cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false, bool PauseLive = false); cIndexFile(const char *FileName, bool Record, bool IsPesRecording = false, bool PauseLive = false, bool Update = false);
~cIndexFile(); ~cIndexFile();
bool Ok(void) { return index != NULL; } bool Ok(void) { return index != NULL; }
bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset); bool Write(bool Independent, uint16_t FileNumber, off_t FileOffset);
@ -488,7 +488,11 @@ char *ExchangeChars(char *s, bool ToFileSystem);
// be modified and may be reallocated if more space is needed. The return // be modified and may be reallocated if more space is needed. The return
// value points to the resulting string, which may be different from s. // value points to the resulting string, which may be different from s.
bool GenerateIndex(const char *FileName); bool GenerateIndex(const char *FileName, bool Update = false);
///< Generates the index of the existing recording with the given FileName.
///< If Update is true, an existing index file will be checked whether it is
///< complete, and will be updated if it isn't. Otherwise an existing index
///< file will be removed before a new one is generated.
enum eRecordingsSortMode { rsmName, rsmTime }; enum eRecordingsSortMode { rsmName, rsmTime };
extern eRecordingsSortMode RecordingsSortMode; extern eRecordingsSortMode RecordingsSortMode;

46
remux.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: remux.c 3.5 2014/03/08 15:05:35 kls Exp $ * $Id: remux.c 3.9 2015/01/14 09:57:09 kls Exp $
*/ */
#include "remux.h" #include "remux.h"
@ -822,9 +822,12 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
} }
} }
break; break;
case 0x81: // STREAMTYPE_USER_PRIVATE case 0x81: // STREAMTYPE_USER_PRIVATE - AC3 audio for ATSC and BD
case 0x82: // STREAMTYPE_USER_PRIVATE - DTS audio for BD
{ {
dbgpatpmt(" AC3"); dbgpatpmt(" %s",
stream.getStreamType() == 0x81 ? "AC3" :
stream.getStreamType() == 0x82 ? "DTS" : "");
char lang[MAXLANGCODE1] = { 0 }; char lang[MAXLANGCODE1] = { 0 };
SI::Descriptor *d; SI::Descriptor *d;
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) { for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
@ -850,6 +853,36 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length)
} }
} }
break; break;
case 0x90: // PGS subtitles for BD
{
dbgpatpmt(" subtitling");
char lang[MAXLANGCODE1] = { 0 };
SI::Descriptor *d;
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
switch (d->getDescriptorTag()) {
case SI::ISO639LanguageDescriptorTag: {
SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
dbgpatpmt(" '%s'", ld->languageCode);
strn0cpy(lang, I18nNormalizeLanguageCode(ld->languageCode), MAXLANGCODE1);
if (NumSpids < MAXSPIDS) {
spids[NumSpids] = stream.getPid();
*slangs[NumSpids] = 0;
subtitlingTypes[NumSpids] = 0;
compositionPageIds[NumSpids] = 0;
ancillaryPageIds[NumSpids] = 0;
if (updatePrimaryDevice)
cDevice::PrimaryDevice()->SetAvailableTrack(ttSubtitle, NumSpids, stream.getPid(), lang);
NumSpids++;
spids[NumSpids] = 0;
}
}
break;
default: ;
}
delete d;
}
}
break;
default: ; default: ;
} }
dbgpatpmt("\n"); dbgpatpmt("\n");
@ -1511,7 +1544,12 @@ int cFrameDetector::Analyze(const uchar *Data, int Length)
for (int i = 0; i < numPtsValues; i++) for (int i = 0; i < numPtsValues; i++)
ptsValues[i] = ptsValues[i + 1] - ptsValues[i]; ptsValues[i] = ptsValues[i + 1] - ptsValues[i];
qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32); qsort(ptsValues, numPtsValues, sizeof(uint32_t), CmpUint32);
uint32_t Delta = ptsValues[0] / (framesPerPayloadUnit + parser->IFrameTemporalReferenceOffset()); int Div = framesPerPayloadUnit;
if (framesPerPayloadUnit > 1)
Div += parser->IFrameTemporalReferenceOffset();
if (Div <= 0)
Div = 1;
uint32_t Delta = ptsValues[0] / Div;
// determine frame info: // determine frame info:
if (isVideo) { if (isVideo) {
if (abs(Delta - 3600) <= 1) if (abs(Delta - 3600) <= 1)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: remux.h 3.3 2014/02/08 12:41:50 kls Exp $ * $Id: remux.h 3.4 2014/03/22 14:58:24 kls Exp $
*/ */
#ifndef __REMUX_H #ifndef __REMUX_H
@ -50,6 +50,7 @@ public:
#define TS_ADAPT_EXTENSION 0x01 #define TS_ADAPT_EXTENSION 0x01
#define PATPID 0x0000 // PAT PID (constant 0) #define PATPID 0x0000 // PAT PID (constant 0)
#define CATPID 0x0001 // CAT PID (constant 1)
#define MAXPID 0x2000 // for arrays that use a PID as the index #define MAXPID 0x2000 // for arrays that use a PID as the index
#define PTSTICKS 90000 // number of PTS ticks per second #define PTSTICKS 90000 // number of PTS ticks per second

8
sdt.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: sdt.c 3.3 2014/03/10 14:42:20 kls Exp $ * $Id: sdt.c 3.4 2015/01/04 14:33:35 kls Exp $
*/ */
#include "sdt.h" #include "sdt.h"
@ -152,7 +152,9 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
delete LinkChannels; delete LinkChannels;
} }
} }
if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) {
Channels.MarkObsoleteChannels(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId()); if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
Channels.MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
}
Channels.Unlock(); Channels.Unlock();
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: sections.c 3.0 2012/10/04 12:21:59 kls Exp $ * $Id: sections.c 3.1 2015/01/14 11:35:53 kls Exp $
*/ */
#include "sections.h" #include "sections.h"
@ -40,10 +40,11 @@ public:
// --- cSectionHandler ------------------------------------------------------- // --- cSectionHandler -------------------------------------------------------
cSectionHandler::cSectionHandler(cDevice *Device) cSectionHandler::cSectionHandler(cDevice *Device)
:cThread("section handler", true) :cThread(NULL, true)
{ {
shp = new cSectionHandlerPrivate; shp = new cSectionHandlerPrivate;
device = Device; device = Device;
SetDescription("device %d section handler", device->CardIndex() + 1);
statusCount = 0; statusCount = 0;
on = false; on = false;
waitForLock = false; waitForLock = false;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinlcars.c 3.7 2014/03/10 12:04:06 kls Exp $ * $Id: skinlcars.c 3.8 2014/06/12 08:48:15 kls Exp $
*/ */
// "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures, // "Star Trek: The Next Generation"(R) is a registered trademark of Paramount Pictures,
@ -482,7 +482,7 @@ cSkinLCARSDisplayChannel::~cSkinLCARSDisplayChannel()
void cSkinLCARSDisplayChannel::DrawDate(void) void cSkinLCARSDisplayChannel::DrawDate(void)
{ {
cString s = DayDateTime(); cString s = DayDateTime();
if (initial || strcmp(s, lastDate)) { if (initial || !*lastDate || strcmp(s, lastDate)) {
osd->DrawText(xc12, yc11, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xc13 - xc12, lineHeight, taRight | taBorder); osd->DrawText(xc12, yc11, s, Theme.Color(clrDateFg), Theme.Color(clrDateBg), cFont::GetFont(fontOsd), xc13 - xc12, lineHeight, taRight | taBorder);
lastDate = s; lastDate = s;
} }
@ -1070,7 +1070,7 @@ void cSkinLCARSDisplayMenu::DrawMenuFrame(void)
void cSkinLCARSDisplayMenu::DrawDate(void) void cSkinLCARSDisplayMenu::DrawDate(void)
{ {
cString s = DayDateTime(); cString s = DayDateTime();
if (initial || strcmp(s, lastDate)) { if (initial || !*lastDate || strcmp(s, lastDate)) {
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
tColor ColorFg = Theme.Color(clrDateFg); tColor ColorFg = Theme.Color(clrDateFg);
tColor ColorBg = Theme.Color(clrDateBg); tColor ColorBg = Theme.Color(clrDateBg);

14
skins.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skins.h 3.3 2014/02/17 11:05:29 kls Exp $ * $Id: skins.h 3.4 2015/01/15 10:45:47 kls Exp $
*/ */
#ifndef __SKINS_H #ifndef __SKINS_H
@ -121,6 +121,14 @@ enum eMenuCategory {
mcCam mcCam
}; };
enum eMenuSortMode {
msmUnknown = 0,
msmNumber,
msmName,
msmTime,
msmProvider
};
class cSkinDisplayMenu : public cSkinDisplay { class cSkinDisplayMenu : public cSkinDisplay {
///< This class implements the general purpose menu display, which is ///< This class implements the general purpose menu display, which is
///< used throughout the program to display information and let the ///< used throughout the program to display information and let the
@ -167,6 +175,10 @@ public:
virtual void SetTabs(int Tab1, int Tab2 = 0, int Tab3 = 0, int Tab4 = 0, int Tab5 = 0); virtual void SetTabs(int Tab1, int Tab2 = 0, int Tab3 = 0, int Tab4 = 0, int Tab5 = 0);
///< Sets the tab columns to the given values, which are the number of ///< Sets the tab columns to the given values, which are the number of
///< characters in each column. ///< characters in each column.
virtual void SetMenuSortMode(eMenuSortMode MenuSortMode) {}
///< Sets the mode by which the items in this menu are sorted.
///< This is purely informative and may be used by a skin to display the
///< current sort mode by means of some text or symbol.
virtual void Scroll(bool Up, bool Page); virtual void Scroll(bool Up, bool Page);
///< If this menu contains a text area that can be scrolled, this function ///< If this menu contains a text area that can be scrolled, this function
///< will be called to actually scroll the text. Up indicates whether the ///< will be called to actually scroll the text. Up indicates whether the

View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * graphical interface that sits on top of an SVDRP connection.
* *
* $Id: svdrp.c 3.5 2013/10/21 07:46:04 kls Exp $ * $Id: svdrp.c 3.6 2015/01/12 11:16:27 kls Exp $
*/ */
#include "svdrp.h" #include "svdrp.h"
@ -261,7 +261,7 @@ const char *HelpPages[] = {
" Move the recording with the given number. Before a recording can be\n" " Move the recording with the given number. Before a recording can be\n"
" moved, an LSTR command must have been executed in order to retrieve\n" " moved, an LSTR command must have been executed in order to retrieve\n"
" the recording numbers. The numbers don't change during subsequent MOVR\n" " the recording numbers. The numbers don't change during subsequent MOVR\n"
" commands.n", " commands.\n",
"NEWC <settings>\n" "NEWC <settings>\n"
" Create a new channel. Settings must be in the same format as returned\n" " Create a new channel. Settings must be in the same format as returned\n"
" by the LSTC command.", " by the LSTC command.",

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.h 3.1 2013/04/11 08:47:31 kls Exp $ * $Id: thread.h 3.2 2015/01/14 11:39:55 kls Exp $
*/ */
#ifndef __THREAD_H #ifndef __THREAD_H
@ -110,12 +110,16 @@ public:
cThread(const char *Description = NULL, bool LowPriority = false); cThread(const char *Description = NULL, bool LowPriority = false);
///< Creates a new thread. ///< Creates a new thread.
///< If Description is present, a log file entry will be made when ///< If Description is present, a log file entry will be made when
///< the thread starts and stops. The Start() function must be called ///< the thread starts and stops (see SetDescription()).
///< to actually start the thread. ///< The Start() function must be called to actually start the thread.
///< LowPriority can be set to true to make this thread run at a lower ///< LowPriority can be set to true to make this thread run at a lower
///< priority. ///< priority.
virtual ~cThread(); virtual ~cThread();
void SetDescription(const char *Description, ...) __attribute__ ((format (printf, 2, 3))); void SetDescription(const char *Description, ...) __attribute__ ((format (printf, 2, 3)));
///< Sets the description of this thread, which will be used when logging
///< starting or stopping of the thread. Make sure any important information
///< is within the first 15 characters of Description, because only these
///< may be displayed in thread listings (like 'htop', for instance).
bool Start(void); bool Start(void);
///< Actually starts the thread. ///< Actually starts the thread.
///< If the thread is already running, nothing happens. ///< If the thread is already running, nothing happens.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 3.2 2013/09/22 13:19:19 kls Exp $ * $Id: tools.c 3.3 2014/03/22 14:22:55 kls Exp $
*/ */
#include "tools.h" #include "tools.h"
@ -609,7 +609,7 @@ int DirSizeMB(const char *DirName)
} }
return size; return size;
} }
else else if (errno != ENOENT)
LOG_ERROR_STR(DirName); LOG_ERROR_STR(DirName);
return -1; return -1;
} }

37
tools.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 3.3 2013/09/22 13:30:14 kls Exp $ * $Id: tools.h 3.6 2015/01/14 09:09:06 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -537,6 +537,14 @@ public:
{ {
return At(Index); return At(Index);
} }
int IndexOf(const T &Data) // returns the index of Data, or -1 if not found
{
for (int i = 0; i < size; i++) {
if (data[i] == Data)
return i;
}
return -1;
}
int Size(void) const { return size; } int Size(void) const { return size; }
virtual void Insert(T Data, int Before = 0) virtual void Insert(T Data, int Before = 0)
{ {
@ -549,18 +557,45 @@ public:
else else
Append(Data); Append(Data);
} }
bool InsertUnique(T Data, int Before = 0)
{
if (IndexOf(Data) < 0) {
Insert(Data, Before);
return true;
}
return false;
}
virtual void Append(T Data) virtual void Append(T Data)
{ {
if (size >= allocated) if (size >= allocated)
Realloc(allocated * 3 / 2); // increase size by 50% Realloc(allocated * 3 / 2); // increase size by 50%
data[size++] = Data; data[size++] = Data;
} }
bool AppendUnique(T Data)
{
if (IndexOf(Data) < 0) {
Append(Data);
return true;
}
return false;
}
virtual void Remove(int Index) virtual void Remove(int Index)
{ {
if (Index < 0)
return; // prevents out-of-bounds access
if (Index < size - 1) if (Index < size - 1)
memmove(&data[Index], &data[Index + 1], (size - Index) * sizeof(T)); memmove(&data[Index], &data[Index + 1], (size - Index) * sizeof(T));
size--; size--;
} }
bool RemoveElement(const T &Data)
{
int i = IndexOf(Data);
if (i >= 0) {
Remove(i);
return true;
}
return false;
}
virtual void Clear(void) virtual void Clear(void)
{ {
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)

22
vdr.1
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.1 3.1 2013/12/25 11:01:36 kls Exp $ .\" $Id: vdr.1 3.3 2015/01/17 14:46:22 kls Exp $
.\" .\"
.TH vdr 1 "31 Mar 2013" "2.0" "Video Disk Recorder" .TH vdr 1 "31 Mar 2013" "2.0" "Video Disk Recorder"
.SH NAME .SH NAME
@ -178,6 +178,10 @@ more information.
Read resource files from \fIdir\fR Read resource files from \fIdir\fR
(default is to read them from the config directory). (default is to read them from the config directory).
.TP .TP
.BI \-\-showargs[= dir ]
Read command line arguments from \fIdir\fR (default is \fI/etc/vdr/conf.d\fR),
display them to the console and exit.
.TP
.BI \-s\ cmd ,\ \-\-shutdown= cmd .BI \-s\ cmd ,\ \-\-shutdown= cmd
Call \fIcmd\fR to shutdown the computer. See the file \fIINSTALL\fR for more Call \fIcmd\fR to shutdown the computer. See the file \fIINSTALL\fR for more
information. information.
@ -197,6 +201,18 @@ be set from the transponder data, but for security reasons
vdr can switch to a lesser privileged user id during normal vdr can switch to a lesser privileged user id during normal
operation. operation.
.TP .TP
.BI \-\-updindex= rec
Update the index file for the given recording.
\fIrec\fR must be the full path name of an existing recording.
The recording must be in TS format.
If the recording already has an index file, it will be checked
whether it is complete, and will be updated if it isn't. If
there is no index file yet, a new one will be generated.
The program will return immediately after updating the index.
Note that using this option while another instance of VDR is
currently replaying the given recording, or if the recording
has not been finished yet, may lead to unexpected results.
.TP
.BI \-\-userdump .BI \-\-userdump
Allow coredumps if -u is given (only for debugging). Allow coredumps if -u is given (only for debugging).
.TP .TP
@ -213,6 +229,10 @@ Print version information and exit.
.BI \-w\ sec ,\ \-\-watchdog= sec .BI \-w\ sec ,\ \-\-watchdog= sec
Activate the watchdog timer with a timeout of \fIsec\fR seconds. Activate the watchdog timer with a timeout of \fIsec\fR seconds.
A value of \fB0\fR (default) disables the watchdog. A value of \fB0\fR (default) disables the watchdog.
.P
If started without any options, vdr tries to read command line options
from files named '*.conf' in the directory /etc/vdr/conf.d. Files are
read in alphabetical order. See vdr(5) for details.
.SH SIGNALS .SH SIGNALS
.TP .TP
.B SIGINT, SIGTERM .B SIGINT, SIGTERM

29
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 3.2 2014/03/16 10:38:31 kls Exp $ .\" $Id: vdr.5 3.3 2014/04/14 13:11:49 kls Exp $
.\" .\"
.TH vdr 5 "31 Mar 2013" "2.0" "Video Disk Recorder Files" .TH vdr 5 "31 Mar 2013" "2.0" "Video Disk Recorder Files"
.SH NAME .SH NAME
@ -899,6 +899,33 @@ Note that the \fBevent id\fR that comes from the DVB data stream is actually
just 16 bit wide. The internal representation in VDR allows for 32 bit to just 16 bit wide. The internal representation in VDR allows for 32 bit to
be used, so that external tools can generate EPG data that is guaranteed be used, so that external tools can generate EPG data that is guaranteed
not to collide with the ids of existing data. not to collide with the ids of existing data.
.SS COMMANDLINE OPTIONS
If started without any options, vdr tries to read any files in the directory
/etc/vdr/conf.d with names that do not begin with a '.' and that end with '.conf'.
These files are read in alphabetical order. The format of these files is
# comment
.br
[name]
.br
-a
.br
-b 123
.br
--long
.br
--longarg=123
.br
Any lines that begin with '#' as the first non-whitespace character are considered
comments and are ignored.
A command line option file consists of one or more sections, indicated by '[name]',
where 'name' is either the fixed word 'vdr' (if this section contains options for
the main VDR program) or the name of the plugin this section applies to.
Each option must be written on a separate line, including the leading '-' (for
a short option) or '--' (for a long option). If the option has additional arguments,
they have to be written on the same line as the option itself, separated from the
option with a blank (short option) or equal sign (long option).
.SH SEE ALSO .SH SEE ALSO
.BR vdr (1) .BR vdr (1)
.SH AUTHOR .SH AUTHOR

40
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.tvdr.de * The project's page is at http://www.tvdr.de
* *
* $Id: vdr.c 3.11 2014/03/16 12:49:13 kls Exp $ * $Id: vdr.c 3.15 2015/01/17 14:48:09 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -39,6 +39,7 @@
#endif #endif
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#include "args.h"
#include "audio.h" #include "audio.h"
#include "channels.h" #include "channels.h"
#include "config.h" #include "config.h"
@ -190,6 +191,7 @@ int main(int argc, char *argv[])
#define DEFAULTWATCHDOG 0 // seconds #define DEFAULTWATCHDOG 0 // seconds
#define DEFAULTVIDEODIR VIDEODIR #define DEFAULTVIDEODIR VIDEODIR
#define DEFAULTCONFDIR dd(CONFDIR, VideoDirectory) #define DEFAULTCONFDIR dd(CONFDIR, VideoDirectory)
#define DEFAULTARGSDIR dd(ARGSDIR, "/etc/vdr/conf.d")
#define DEFAULTCACHEDIR dd(CACHEDIR, VideoDirectory) #define DEFAULTCACHEDIR dd(CACHEDIR, VideoDirectory)
#define DEFAULTRESDIR dd(RESDIR, ConfigDirectory) #define DEFAULTRESDIR dd(RESDIR, ConfigDirectory)
#define DEFAULTPLUGINDIR PLUGINDIR #define DEFAULTPLUGINDIR PLUGINDIR
@ -227,6 +229,15 @@ int main(int argc, char *argv[])
VdrUser = VDR_USER; VdrUser = VDR_USER;
#endif #endif
cArgs *Args = NULL;
if (argc == 1) {
Args = new cArgs(argv[0]);
if (Args->ReadDirectory(DEFAULTARGSDIR)) {
argc = Args->GetArgc();
argv = Args->GetArgv();
}
}
cVideoDirectory::SetName(VideoDirectory); cVideoDirectory::SetName(VideoDirectory);
cPluginManager PluginManager(DEFAULTPLUGINDIR); cPluginManager PluginManager(DEFAULTPLUGINDIR);
@ -254,9 +265,11 @@ int main(int argc, char *argv[])
{ "port", required_argument, NULL, 'p' }, { "port", required_argument, NULL, 'p' },
{ "record", required_argument, NULL, 'r' }, { "record", required_argument, NULL, 'r' },
{ "resdir", required_argument, NULL, 'r' | 0x100 }, { "resdir", required_argument, NULL, 'r' | 0x100 },
{ "showargs", optional_argument, NULL, 's' | 0x200 },
{ "shutdown", required_argument, NULL, 's' }, { "shutdown", required_argument, NULL, 's' },
{ "split", no_argument, NULL, 's' | 0x100 }, { "split", no_argument, NULL, 's' | 0x100 },
{ "terminal", required_argument, NULL, 't' }, { "terminal", required_argument, NULL, 't' },
{ "updindex", required_argument, NULL, 'u' | 0x200 },
{ "user", required_argument, NULL, 'u' }, { "user", required_argument, NULL, 'u' },
{ "userdump", no_argument, NULL, 'u' | 0x100 }, { "userdump", no_argument, NULL, 'u' | 0x100 },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
@ -426,6 +439,19 @@ int main(int argc, char *argv[])
case 's' | 0x100: case 's' | 0x100:
Setup.SplitEditedFiles = 1; Setup.SplitEditedFiles = 1;
break; break;
case 's' | 0x200: {
const char *ArgsDir = optarg ? optarg : DEFAULTARGSDIR;
cArgs Args(argv[0]);
if (!Args.ReadDirectory(ArgsDir)) {
fprintf(stderr, "vdr: can't read arguments from directory: %s\n", ArgsDir);
return 2;
}
int c = Args.GetArgc();
char **v = Args.GetArgv();
for (int i = 1; i < c; i++)
printf("%s\n", v[i]);
return 0;
}
case 't': Terminal = optarg; case 't': Terminal = optarg;
if (access(Terminal, R_OK | W_OK) < 0) { if (access(Terminal, R_OK | W_OK) < 0) {
fprintf(stderr, "vdr: can't access terminal: %s\n", Terminal); fprintf(stderr, "vdr: can't access terminal: %s\n", Terminal);
@ -438,6 +464,8 @@ int main(int argc, char *argv[])
case 'u' | 0x100: case 'u' | 0x100:
UserDump = true; UserDump = true;
break; break;
case 'u' | 0x200:
return GenerateIndex(optarg, true) ? 0 : 2;
case 'V': DisplayVersion = true; case 'V': DisplayVersion = true;
break; break;
case 'v' | 0x100: case 'v' | 0x100:
@ -539,9 +567,12 @@ int main(int argc, char *argv[])
" -s CMD, --shutdown=CMD call CMD to shutdown the computer\n" " -s CMD, --shutdown=CMD call CMD to shutdown the computer\n"
" --split split edited files at the editing marks (only\n" " --split split edited files at the editing marks (only\n"
" useful in conjunction with --edit)\n" " useful in conjunction with --edit)\n"
" --showargs[=DIR] print the arguments read from DIR and exit\n"
" (default: %s)\n"
" -t TTY, --terminal=TTY controlling tty\n" " -t TTY, --terminal=TTY controlling tty\n"
" -u USER, --user=USER run as user USER; only applicable if started as\n" " -u USER, --user=USER run as user USER; only applicable if started as\n"
" root\n" " root\n"
" --updindex=REC update index for recording REC and exit\n"
" --userdump allow coredumps if -u is given (debugging)\n" " --userdump allow coredumps if -u is given (debugging)\n"
" -v DIR, --video=DIR use DIR as video directory (default: %s)\n" " -v DIR, --video=DIR use DIR as video directory (default: %s)\n"
" -V, --version print version information and exit\n" " -V, --version print version information and exit\n"
@ -561,6 +592,7 @@ int main(int argc, char *argv[])
DEFAULTLOCDIR, DEFAULTLOCDIR,
DEFAULTSVDRPPORT, DEFAULTSVDRPPORT,
DEFAULTRESDIR, DEFAULTRESDIR,
DEFAULTARGSDIR,
DEFAULTVIDEODIR, DEFAULTVIDEODIR,
DEFAULTWATCHDOG DEFAULTWATCHDOG
); );
@ -849,7 +881,7 @@ int main(int argc, char *argv[])
} }
#ifdef SDNOTIFY #ifdef SDNOTIFY
sd_notify(0, "READY=1"); sd_notify(0, "READY=1\nSTATUS=Ready");
#endif #endif
// Main program loop: // Main program loop:
@ -927,7 +959,7 @@ int main(int argc, char *argv[])
if (Channel->Number() == cDevice::CurrentChannel() && cDevice::PrimaryDevice()->HasDecoder()) { if (Channel->Number() == cDevice::CurrentChannel() && cDevice::PrimaryDevice()->HasDecoder()) {
if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) { if (!cDevice::PrimaryDevice()->Replaying() || cDevice::PrimaryDevice()->Transferring()) {
if (cDevice::ActualDevice()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder if (cDevice::ActualDevice()->ProvidesTransponder(Channel)) { // avoids retune on devices that don't really access the transponder
isyslog("retuning due to modification of channel %d", Channel->Number()); isyslog("retuning due to modification of channel %d (%s)", Channel->Number(), Channel->Name());
Channels.SwitchTo(Channel->Number()); Channels.SwitchTo(Channel->Number());
} }
} }
@ -1004,7 +1036,7 @@ int main(int argc, char *argv[])
if (!Device->IsTunedToTransponder(Timer->Channel())) { if (!Device->IsTunedToTransponder(Timer->Channel())) {
if (Device == cDevice::ActualDevice() && !Device->IsPrimaryDevice()) if (Device == cDevice::ActualDevice() && !Device->IsPrimaryDevice())
cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode cDevice::PrimaryDevice()->StopReplay(); // stop transfer mode
dsyslog("switching device %d to channel %d", Device->DeviceNumber() + 1, Timer->Channel()->Number()); dsyslog("switching device %d to channel %d (%s)", Device->DeviceNumber() + 1, Timer->Channel()->Number(), Timer->Channel()->Name());
if (Device->SwitchChannel(Timer->Channel(), false)) if (Device->SwitchChannel(Timer->Channel(), false))
Device->SetOccupied(TIMERDEVICETIMEOUT); Device->SetOccupied(TIMERDEVICETIMEOUT);
} }